You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(pr-pipeline): read lane limit settings from a limits leaf in pr-pipeline.yaml #7764
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:
limits.fallback-reset: how long after a limit stop with no stated reset the lane may restart (hard-coded 5 hours).
limits.restarts-per-run: issues the hourly work-unblock sweep restarts per run (hard-coded 5).
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.
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).
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.
Activity
github-actions commentedon Oct 17, 2026
Thanks for the report. Automated triage handed this issue to a maintainer.
Automated triage. A maintainer reviews it.
kyle-sexton commentedon Oct 18, 2026
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_MSandMAX_LIMIT_STOPS(per head) in.github/scripts/pr-unblock/limit-stop.mjs:17-23plus its inline 1 h to 7 d clamp;FALLBACK_RESET_MSandclampResetin.github/scripts/work-resolve-issue/report-outcome.mjs;RESTARTS_PER_RUNandMAX_LIMIT_STOPS(per issue) in.github/scripts/work-unblock/label-unblocked.mjs:73-78.pr-pipeline.yamland its schema have nolimitsleaf; resolve-config emitsloopwith defaults, which is the pattern to copy. The twoMAX_LIMIT_STOPSconstants count different things (per PR head vs per issue since a person last addedagent-ready). Config plumbing differs: work-unblock and the write runner already resolve config andfeedback-dispatch.mjsresolves it in-script, butpr-unblock-dispatch.ymlrunsdispatch.mjswith no resolved config.needs-humanwas 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.kyle-sexton commentedon Oct 18, 2026
This was generated by AI during triage.
Agent Brief
Type: Feature
Summary: Move the lane limit-stop constants into a new
limitsleaf 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
limitsobject with integer leaves (see the decision comment for names and units) defaulting to today's values. resolve-config emits a resolvedlimitsobject with those defaults, next toloop. Each consumer reads its values from the resolved config instead of a constant: report-outcome (fallback reset and clamp, throughclampReset); 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:
limitsproperty,additionalProperties: false, integer leaves withminimum1 and today's defaultslimitsobjectclampReset(resets, from, limits),limitResetsAt(run, limits),anyHandles(runs, { now, limits })take the values as parametersrestartLimitedtakes its cap and stop count from the resolved configAcceptance criteria:
limitsleaf, and rejects an unknown key underlimitsor a non-positive integer.limitsleaf, the resolvedlimitsequals today's six values.FALLBACK_RESET_MS,RESTARTS_PER_RUNorMAX_LIMIT_STOPSconstant remains.pr-pipeline.yamleither omitslimitsor sets exactly the defaults.Out of scope:
RUN_WINDOW_MS, the review-round caps inloop).kyle-sexton commentedon Oct 18, 2026
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-resetandlimits.restarts-per-run, addlimits.reset-clamp-min/limits.reset-clamp-max, give the two stop caps separate keyslimits.limit-stops-per-headandlimits.limit-stops-per-issue, and express every duration as integer hours (documented in the schema description) — veto before mergeBasis: verified, the issue body and the code comments name
limits.fallback-resetandlimits.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-23vslabel-unblocked.mjs:76-78); every existing leaf indocs/conventions/pr-pipeline/pr-pipeline.schema.jsonis a plain integer. All choices are reversible schema edits before any consumer depends on them.feat(pr-pipeline): read lane limit settings from a limits leaf in pr-…