Skip to content

feat(pr-pipeline): read lane limit settings from a limits leaf in pr-pipeline.yaml #7764

Description

@kyle-sexton

Refs: #7737

What to build

Add a limits leaf to docs/conventions/pr-pipeline.yaml (component C6 of the automation-lanes never-block design) and read it in place of the constants #7737 hard-codes:

Consumers

  • .github/scripts/work-resolve-issue/report-outcome.mjs: FALLBACK_RESET_MS, clampReset (also used by label-unblocked.mjs).
  • .github/scripts/pr-unblock/limit-stop.mjs: FALLBACK_RESET_MS, MAX_LIMIT_STOPS, the clamp in limitResetsAt.
  • .github/scripts/work-unblock/label-unblocked.mjs: RESTARTS_PER_RUN, MAX_LIMIT_STOPS.

The config reader is .github/actions/resolve-config; the schema and its tests need the new leaf.

Done when

Each constant above is read from the resolved config, with today's value as the schema default, and the comments pointing at this issue are removed.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 17, 2026
  2. github-actions commented on Oct 17, 2026

    @github-actions
    Contributor

    Thanks for the report. Automated triage handed this issue to a maintainer.

    Automated triage. A maintainer reviews it.

  3. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 17, 2026
  4. kyle-sexton commented on Oct 18, 2026

    @kyle-sexton
    MemberAuthor

    This was generated by AI during triage.

    Verified: request valid

    Default branch: 30e97ed (not applicable)
    Open linked PRs: none (parent #7737 merged and hard-coded these values)

    The constants are still hard-coded on main, each with a comment pointing at this issue: FALLBACK_RESET_MS and MAX_LIMIT_STOPS (per head) in .github/scripts/pr-unblock/limit-stop.mjs:17-23 plus its inline 1 h to 7 d clamp; FALLBACK_RESET_MS and clampReset in .github/scripts/work-resolve-issue/report-outcome.mjs; RESTARTS_PER_RUN and MAX_LIMIT_STOPS (per issue) in .github/scripts/work-unblock/label-unblocked.mjs:73-78. pr-pipeline.yaml and its schema have no limits leaf; resolve-config emits loop with defaults, which is the pattern to copy. The two MAX_LIMIT_STOPS constants count different things (per PR head vs per issue since a person last added agent-ready). Config plumbing differs: work-unblock and the write runner already resolve config and feedback-dispatch.mjs resolves it in-script, but pr-unblock-dispatch.yml runs dispatch.mjs with no resolved config.

    needs-human was applied by the intake lane at filing, not by a person; the item is fully specified, additive, and keeps today's values as defaults, so it is routed to the lane with the defaulted decision below.

  5. added
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    on Oct 18, 2026
  6. kyle-sexton commented on Oct 18, 2026

    @kyle-sexton
    MemberAuthor

    This was generated by AI during triage.

    Agent Brief

    Type: Feature
    Summary: Move the lane limit-stop constants into a new limits leaf of the pr-pipeline config, with schema defaults equal to today's values so behavior does not change.

    Current behavior:
    The limit-stop restart logic from #7737 hard-codes five values: the 5-hour fallback reset, the 1-hour-to-7-day reset clamp, 5 restarts per hourly sweep, 3 limit stops per head before the pr-unblock dispatchers stop re-dispatching, and 3 limit stops per issue before the work-unblock sweep hands the issue to a person. Each carries a comment pointing at this issue.

    Desired behavior:
    The pr-pipeline schema gains an optional limits object with integer leaves (see the decision comment for names and units) defaulting to today's values. resolve-config emits a resolved limits object with those defaults, next to loop. Each consumer reads its values from the resolved config instead of a constant: report-outcome (fallback reset and clamp, through clampReset); the work-unblock sweep (clampReset, restarts per run, limit stops per issue); the pr-unblock dispatch and feedback-dispatch path (limitResetsAt, anyHandles). The pr-unblock dispatch path gets the resolved config the way feedback-dispatch resolves it inside the script, so no workflow file needs editing.

    Key interfaces:

    • pr-pipeline schema: new limits property, additionalProperties: false, integer leaves with minimum 1 and today's defaults
    • resolve-config output: new limits object
    • clampReset(resets, from, limits), limitResetsAt(run, limits), anyHandles(runs, { now, limits }) take the values as parameters
    • restartLimited takes its cap and stop count from the resolved config
    • the convention README and CHANGELOG entry for the new leaf

    Acceptance criteria:

    • The schema accepts a config with and without a limits leaf, and rejects an unknown key under limits or a non-positive integer.
    • With no limits leaf, the resolved limits equals today's six values.
    • A test per consumer (report-outcome, work-unblock sweep, pr-unblock limit stop) shows a non-default value changes its behavior.
    • The existing limit-stop, report-outcome, work-unblock and resolve-config suites pass with unchanged expectations under defaults.
    • No source comment points at this issue, and no FALLBACK_RESET_MS, RESTARTS_PER_RUN or MAX_LIMIT_STOPS constant remains.
    • The repository's pr-pipeline.yaml either omits limits or sets exactly the defaults.

    Out of scope:

    • Changing any value from today's.
    • Making other lane caps configurable (max-turns, RUN_WINDOW_MS, the review-round caps in loop).
    • Editing any workflow file.
  7. kyle-sexton commented on Oct 18, 2026

    @kyle-sexton
    MemberAuthor

    This was generated by AI during triage.

    Decision defaulted: include all of them (fallback reset, reset clamp, restarts per run, both stop caps), keep the issue's key names limits.fallback-reset and limits.restarts-per-run, add limits.reset-clamp-min / limits.reset-clamp-max, give the two stop caps separate keys limits.limit-stops-per-head and limits.limit-stops-per-issue, and express every duration as integer hours (documented in the schema description) — veto before merge
    Basis: verified, the issue body and the code comments name limits.fallback-reset and limits.restarts-per-run (.github/scripts/pr-unblock/limit-stop.mjs:17, .github/scripts/work-unblock/label-unblocked.mjs:73); the two stop caps count different things (limit-stop.mjs:21-23 vs label-unblocked.mjs:76-78); every existing leaf in docs/conventions/pr-pipeline/pr-pipeline.schema.json is a plain integer. All choices are reversible schema edits before any consumer depends on them.

  8. added
    priority: lowNice-to-have, cosmetic, or speculative; opportunistic.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    on Oct 18, 2026
  9. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    and removed
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 18, 2026
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

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.priority: lowNice-to-have, cosmetic, or speculative; opportunistic.status: readyTriaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Fields

    No fields configured for Feature.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions