Skip to content

feat(roadmap): the implement job takes a medium-effort item when no low-effort item is ready #3385

Closed

Description

@dan-petty

Problem

DEFAULT_IMPLEMENT_FILTERS in src/devops_cli/roadmap/implement.py is ("status=ready", "status=planned", "effort=low"). devops roadmap explain 3307 reports: Implement job: no. The filter takes effort low. The item has effort medium. Every Ready or Planned item of medium or high effort waits, even when the job has no low-effort item to take. The Ready backlog holds many medium-effort items, so the service underuses its implement capacity.

Proposed change

  1. Add a second pass to the default implementation selection: take a low-effort item first; when none is a candidate, take a medium-effort item. A high-effort item stays out.
  2. Give the effort set a setting, roadmap.implement.effort, whose default is the low pass and then the medium fallback.
  3. Name the pass that the job takes in devops roadmap explain, and record it in the run report.

Acceptance criteria

  1. A test with one Ready low-effort item and one Ready medium-effort item asserts that one run implements the low-effort item and leaves the medium item.
  2. A test with only a Ready medium-effort item asserts that the run implements it.
  3. devops roadmap explain names the effort set and whether the fallback pass applies.

Proposed design

Problem statement

The implement job takes only low-effort items. DEFAULT_IMPLEMENT_FILTERS names effort=low, so a Ready or Planned medium-effort item waits while the job has no low-effort item to take. The service therefore uses less of its implement capacity. The change adds an ordered effort set: the job takes a low-effort item first, then a medium-effort item when no low-effort item is selectable. A high-effort item stays out. A setting holds the set, and devops roadmap explain and the run report name the pass in use.

Acceptance criteria

Requirement: Low effort takes precedence

The implement job SHALL select a low-effort item before a medium-effort item when both are selectable.

Scenario: A low-effort item and a medium-effort item are ready

  • WHEN the store holds one Ready low-effort item and one Ready medium-effort item
  • THEN the plan selects the low-effort item and leaves the medium-effort item out

Requirement: Medium fallback

The implement job MUST select a medium-effort item when no low-effort item is selectable.

Scenario: Only a medium-effort item is ready

  • WHEN the store holds one Ready medium-effort item and no Ready or Planned low-effort item
  • THEN the plan selects the medium-effort item

Requirement: High effort stays out

The implement job MUST NOT select a high-effort item in the default effort set.

Scenario: Only a high-effort item is ready

  • WHEN the store holds one Ready high-effort item and no Ready or Planned low-effort or medium-effort item
  • THEN the plan selects no item and gives the effort reason for the high-effort item

Requirement: A left-out low-effort item does not block the fallback

The fallback pass MUST apply when the job leaves out every low-effort item.

Scenario: The only low-effort item is claimed

  • WHEN an agent claims the only Ready low-effort item and a Ready medium-effort item is free
  • THEN the plan selects the medium-effort item and lists the low-effort item with its claim reason

Requirement: Effort set setting

The setting roadmap.implement.effort SHALL hold the ordered effort values and SHALL default to low,medium.

Scenario: The setting holds one effort value

  • WHEN roadmap.implement.effort is low
  • THEN the plan selects no medium-effort item when no low-effort item is selectable

Requirement: An unknown effort value fails

The setting roadmap.implement.effort MUST reject a value that is not an effort value.

Scenario: The setting holds an unknown effort value

  • WHEN roadmap.implement.effort is low,huge
  • THEN the settings load fails with a validation error that names huge

Requirement: Explain names the pass

devops roadmap explain SHALL name the effort set and whether the fallback pass applies to the item.

Scenario: A medium-effort item uses the fallback

  • WHEN the user runs devops roadmap explain on a Ready medium-effort item while no low-effort item is selectable
  • THEN the output names the effort set low,medium and says that the fallback pass applies

Requirement: Run report names the pass

The implement run report MUST name the effort pass that the run uses.

Scenario: A run uses the medium pass

  • WHEN the plan selects a medium-effort item
  • THEN the rendered plan states the effort pass medium

Requirement: Example ConfigMap holds the setting

The example ConfigMap SHALL hold roadmap.implement.effort with the default value.

Scenario: A test reads the example ConfigMap

  • WHEN a test reads the example ConfigMap
  • THEN the test finds roadmap.implement.effort equal to low,medium

Existing Tool Considered

No alternatives check has run. No open, maintained tool or library covers the need: the change edits the repository's own selection code (src/devops_cli/roadmap/implement.py) and its settings, and no outside project supplies this roadmap selection. The written cost to build it instead is small: about 1,500 tokens to write the ordered effort set, the setting, the explain text and the tests; about 500 tokens for each later fix; and about half a day of elapsed time.

Key questions

  • How does the job hold the ordered effort passes?: Add the setting roadmap.implement.effort. It holds an ordered, comma-separated list of effort values. The default low,medium lives in src/devops_cli/config/defaults.py. The job reads it when no --filter effort= is given. (best practice) [sources: src/devops_cli/roadmap/implement.py, src/devops_cli/config/defaults.py, src/devops_cli/config/settings.py, openspec/changes/archive/2026-10-31-2906-wide-stage-and-implement-filters/proposal.md]
    • Chosen: One ordered setting, roadmap.implement.effort, default low,medium. The body asks for one setting. An ordered list keeps the priority explicit and lets a person change a pass without code.
    • Rejected: Two settings, one for the first pass and one for the fallback. Two keys let a person set a contradictory pair and need a rule for their order.
    • Rejected: A code constant with no setting. The body asks for a setting, and a person could not change the set without a release.
  • When does the medium fallback pass apply?: The fallback applies when the low pass selects no item. A low-effort item that the job leaves out, such as a claimed or stopped item, must not idle the capacity. The plan reports such an item with its reason. (best practice) [sources: src/devops_cli/roadmap/implement.py]
    • Chosen: When the low pass selects no item. The body says the fallback applies when none is a candidate. An item that the job cannot take is no candidate.
    • Rejected: When the filter names no low-effort item. One low-effort item that the job leaves out would then block every medium-effort item.
  • Does one run mix effort passes to fill the limit?: No. The first pass that selects an item supplies the whole run, up to the limit. The job does not mix effort values in one run. (best practice) [sources: src/devops_cli/roadmap/implement.py]
    • Chosen: The first pass that selects an item supplies the run. The body orders the passes, and its first criterion leaves the medium-effort item when a low-effort item is ready.
    • Rejected: Fill the limit from the next pass. It mixes passes in one run report and weakens the low-effort preference.
  • Does an explicit --filter effort= replace the setting?: Yes. parse_implement_filters uses the options as given and uses the default only when the options are empty. An explicit --filter effort=high therefore bypasses the setting. [sources: src/devops_cli/roadmap/implement.py]
  • How does explain name the pass?: plan_implement sets a new effort field on ImplementPlan to the effort value of the pass in use. explain prints the effort set and, for the item, whether its effort is the pass in use or the fallback. (best practice) [sources: src/devops_cli/roadmap/implement.py, src/devops_cli/roadmap/explain.py]
    • Chosen: The plan reports the pass, and explain prints the set and the pass. Explain already plans the item, so the plan carries the pass with no second selection.
    • Rejected: Explain prints only the effort set. It does not answer whether the fallback applies, which the body requires.
  • Where does the run report record the pass?: Put the pass on ImplementPlan.effort. render_implement_plan names it, and the Service round report reads it from the plan. The job record of the issue keeps stops and branches, and it holds no per-run value. (best practice) [sources: src/devops_cli/roadmap/implement.py]
    • Chosen: A field on ImplementPlan, rendered in the report. The plan already carries the run's selection, and one field reaches every caller.
    • Rejected: The job record of the issue. The record holds the stops and the branches of an item, not the result of one run.
  • Does the Service round pick up the setting with no other change?: Yes. The Service round calls parse_implement_filters(()). The default effort set therefore applies to the Service round with no other change. [sources: openspec/changes/archive/2026-10-31-2906-wide-stage-and-implement-filters/proposal.md, src/devops_cli/roadmap/implement.py]
  • Does the example ConfigMap need the new key?: Add roadmap.implement.effort: low,medium to k8s/devops/configmap.example.yaml. Add a test that holds the value equals the default, as the stage filter test does. (best practice) [sources: openspec/changes/archive/2026-10-31-2906-wide-stage-and-implement-filters/proposal.md, openspec/changes/archive/2026-10-31-2906-wide-stage-and-implement-filters/design.md]
    • Chosen: Add the key to the example ConfigMap, with a test. The example shows every other roadmap setting, and a test keeps the example equal to the default.
    • Rejected: Leave the example alone. The example would not show the new setting, and a reader would not find it.

Fit

Fits in one pull request.

Suspected block

None.

Dependencies

None.

Activity

  1. added
    type/featureNew user-facing functionality or capability addition
    scope/roadmapThe roadmap jobs: intake, refine, stage, implement and the Service that runs them
    status/newStatus New: the item is not ready yet
    on Nov 3, 2026
  2. dan-petty commented on Nov 3, 2026

    @dan-petty
    OwnerAuthor

    Intake placed this item to the backlog: intake puts every new item in the backlog. A person plans the milestones.

    • Type: type/feature. The feat prefix of the title gives the type.
    • Scope: scope/roadmap. The (roadmap) scope of the title gives the scope.
    • Priority: P2-Medium. The backlog underuses implement capacity on medium-effort items, but no item is blocked or failing.
    • Value: Medium. More Ready items flow through the implement job, reducing idle capacity.
    • Effort: Medium. The change adds a second selection pass, a new setting, an explain update, and two new tests.
    • Related: feat(roadmap): the stage job plans every Ready item and the implement job takes every Ready item of low effort #2906, which asks for a different change. Both items change the implement job effort filter, but #2906 sets the filter to low effort only while the candidate adds a medium-effort fallback when no low-effort item is ready.
  3. added
    priority/p2-mediumStandard priority feature work and architectural improvements
    on Nov 3, 2026
  4. dan-petty commented on Nov 3, 2026

    @dan-petty
    OwnerAuthor

    This item is independent of #3307. Intake linked it as a sub-issue of #3307 in error; the link is removed. The evidence is devops roadmap explain 3307 and the default filter in src/devops_cli/roadmap/implement.py.

  5. added
    status/readyStatus Ready: problem, acceptance criteria and an answer to each key question
    and removed
    status/newStatus New: the item is not ready yet
    on Nov 3, 2026
  6. devops-cli-service commented on Nov 3, 2026

    @devops-cli-service
    Contributor

    Status set to Ready at 7d07054 (see proposed design in issue body).

  7. dan-petty commented on Nov 4, 2026

    @dan-petty
    OwnerAuthor

    @dan-petty please confirm or refuse one decision. This item changes the decision of 2026-10-31, and no comment of the owner approves that change.

    What is true.

    If you confirm the change, return this item to New with that reason, so that refine writes its block again, and add to the body:

    1. The rule: within one priority, low effort goes first. A Planned item with one of those two labels, of low or medium effort, passes the effort filter. High effort stays out. Add a scenario for it. The refine block now says "Low effort takes precedence", and this contradicts it.
    2. A ### Dependencies heading above the refine block, with fix(roadmap): raise or configure implement tool retry budget #3271 and fix(roadmap): continue past an implement group that changes no file #3460. body_dependencies takes the first such heading, and the stage job then leaves the item out until they close. Without this heading, a text on the order of the work stops no stage run. fix(roadmap): raise or configure implement tool retry budget #3271 has low effort, and the job takes only low effort (src/devops_cli/roadmap/implement.py:105), so a higher effort on fix(roadmap): raise or configure implement tool retry budget #3271 while this item waits on it makes a loop.

    If you do not confirm, this item conflicts with that decision, so it must not reach a plan. In both cases a person can start one of these items now, with --item <number> or the --filter option of devops roadmap implement. Nobody ran this on these items.

  8. added
    owner/agentOwner Agent: an agentic coder works on the item
    status/in-progressActively being designed or implemented by developer or agent
    and removed
    status/readyStatus Ready: problem, acceptance criteria and an answer to each key question
    on Nov 5, 2026
  9. added a commit that references this issue on Nov 5, 2026
  10. removed
    status/in-progressActively being designed or implemented by developer or agent
    owner/agentOwner Agent: an agentic coder works on the item
    on Nov 5, 2026
  11. devops-cli-service commented on Nov 5, 2026

    @devops-cli-service
    Contributor
  12. devops-cli-service commented on Nov 5, 2026

    @devops-cli-service
    Contributor

    Live since 2026-11-05 13:02 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    effort/mediumEffort Mediumpriority/p2-mediumStandard priority feature work and architectural improvementsscope/roadmapThe roadmap jobs: intake, refine, stage, implement and the Service that runs themsource/agentFiled by an agenttype/featureNew user-facing functionality or capability additionvalue/mediumValue Medium

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions