Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
1e60c32
fix(pr-pipeline): route pr-unblock stops to a failing status, not nee…
kyle-sexton Oct 26, 2026
e2ce4cc
fix(pr-pipeline): retry a pr-unblock stop on the same head under the …
kyle-sexton Oct 26, 2026
eb7c342
fix(pr-pipeline): count only real attempts in the stalled-stop signal…
kyle-sexton Oct 26, 2026
0f104f2
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
5488e10
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
2237125
fix(pr-pipeline): hold escalation-routes.mjs on the merge path floor
kyle-sexton Oct 26, 2026
d9ac6ed
fix(pr-pipeline): read a fix-ci run and its rung-up as one attempt
kyle-sexton Oct 26, 2026
4890f95
fix(pr-pipeline): key a fix-ci attempt on its workflow run, not its s…
kyle-sexton Oct 26, 2026
f38371e
fix(pr-pipeline): read the newest open pull requests for stalled stops
kyle-sexton Oct 26, 2026
2820d5c
chore(source-control): add the changelog fragment for the floor entry
kyle-sexton Oct 26, 2026
9ca743a
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
c9e643f
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
50a2161
fix(pr-pipeline): clear a fix-ci needs-human only on a failed ci-lane…
kyle-sexton Oct 26, 2026
3c08904
fix(pr-pipeline): leave a stop's failing status on a retry that skipped
kyle-sexton Oct 26, 2026
9656b96
fix(pr-pipeline): read a fix-ci stop's head checks with the job token
kyle-sexton Oct 26, 2026
0a9ebb0
perf(pr-pipeline): read stalled stops in one GraphQL query
kyle-sexton Oct 26, 2026
7969316
fix(pr-pipeline): end untaken review threads and failed reply jobs in…
kyle-sexton Oct 26, 2026
a431c0c
fix(pr-pipeline): count only pr-require-checks lanes for a fix-ci clear
kyle-sexton Oct 26, 2026
abb345e
fix(pr-pipeline): dispatch untaken review threads once and derive a f…
kyle-sexton Oct 26, 2026
a92de9d
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
7061638
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
764ec0b
fix(pr-pipeline): fail ci-status on a failing pr-unblock status
kyle-sexton Oct 26, 2026
8d259a6
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
cec94c6
test(pr-merge): pin a cancelled lane check clearing a fix-ci label
kyle-sexton Oct 26, 2026
98798d9
Merge origin/main into fix/pr-unblock-route-not-park
kyle-sexton Oct 26, 2026
cf287cb
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
6301bc8
fix(pr-unblock): floor the routing table and clear a stop its select …
kyle-sexton Oct 26, 2026
3c7bdbe
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
b34abd3
test(resolve-config): give the round-cap read a failing check
kyle-sexton Oct 26, 2026
473e27a
fix(pr-pipeline): keep needs-human on a moved head and never settle V…
kyle-sexton Oct 26, 2026
ed1dad0
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
afcd6d0
test(pr-unblock): expect a lane verdict to leave a VALID-defer thread…
kyle-sexton Oct 26, 2026
9f5c8aa
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
89edfc1
docs(pr-pipeline): give the reason a moved head keeps a fail-routed l…
kyle-sexton Oct 26, 2026
a31efa2
fix(pr-pipeline): copy escalation-routes.mjs and its table in separat…
kyle-sexton Oct 26, 2026
17e542d
fix(pr-unblock): list every check run so a later skip does not hide a…
kyle-sexton Oct 26, 2026
f8a1c3e
fix(pr-unblock): mark a cleared lane stop so the monitor stops listin…
kyle-sexton Oct 26, 2026
fad0417
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
e5004a0
revert: "fix(pr-unblock): mark a cleared lane stop so the monitor sto…
kyle-sexton Oct 26, 2026
ea2b0ee
docs(pr-pipeline): record the filter=all check-run listing in the cha…
kyle-sexton Oct 26, 2026
90cf0f3
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
3744340
fix(pr-pipeline): floor the scripts that act on a pr-unblock stop's r…
kyle-sexton Oct 26, 2026
a6430bc
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 26, 2026
4d05429
docs(pr-pipeline): spell labeling as the typos check expects
kyle-sexton Oct 26, 2026
fad3adf
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 27, 2026
7594b45
Merge remote-tracking branch 'origin/main' into fix/pr-unblock-route-…
kyle-sexton Oct 27, 2026
f33f3bb
Merge remote-tracking branch 'origin/main' into drive-10252
kyle-sexton Oct 27, 2026
ae9e724
fix(pr-pipeline): stage the routing table in the issue-lane fixture a…
kyle-sexton Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changes/pr-pipeline/fix-pr-unblock-route-not-park-5c1e7a20.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
bump: minor
---

### Changed

- A `pr-unblock` run that stops now ends on the route its reason has in [`escalation-routes.json`](https://github.com/melodic-software/claude-code-plugins/blob/main/.github/scripts/pr-unblock/escalation-routes.json), the one routing table that `report-escalation.sh`, `gate-source.mjs` and `clear-escalations.mjs` read. Only a reason a person must settle keeps the `needs-human` label: a path the lane token may not push or a supply-chain refusal, an intent, design or security question, a person's own thread or hold, or a finding no adjudicator may judge (security-review or CRITICAL). Every other reason (for example `ci-fix-escalated`, `feedback-not-landed`, the round and repeat caps) ends with no label, a failing commit status on the head the activity gated (`pr-unblock/conflict` for `resolve-conflicts`, `pr-unblock/<activity>` otherwise, posted by the `report-stop-status` job that replaces `report-conflict-status`), and one lanes App comment per activity that the next stop edits in place. A new head carries no status. ci-status, the one required check, fails while the newest `pr-unblock/*` status on the head by `github-actions[bot]` is `failure` or `error`, naming each such context, on pull request runs and in the merge queue (the queued pull request's head); a later `success` on the same head supersedes it.
- An `UNCERTAIN` or `VALID-defer` review reply now goes to the adjudicator as an `INCORRECT` one does, instead of to a person. A `lane` verdict (the finding does not hold) never resolves a `VALID-defer` thread, where the lane agreed the finding holds: the thread stays open and the round ends `feedback-unadjudicated`. A pr-verify note left open ends `feedback-verifier-open`, and a finding that stood at adjudication and was left open again ends `feedback-stood-open`; both route to a failing status. A round's reason held for a person now outranks any reason routed to a failing status.
- `clear-escalations` takes off a `needs-human` an older run set for a reason now routed to a failing status: a `ci-fix-*` reason once a lane check of a `pr-require-checks.yml` run on the current head reads failed. Any other fail-routed reason keeps the label for a person: a new head carries no `pr-unblock/*` status that shows the cause gone or fails that head in the label's place.
- A pr-unblock stop routed to a failing status now skips `lane-stopped` (a new `skip-reason`) instead of `awaiting-human`. On a select job's own check (a cap, or a conflict no model can resolve) it ends the head, so the dispatchers stop re-running a deterministic stop. On the push, reply or verdict job's check, the dispatcher retries the same head under the cap it already keeps:
- `limit-stops-per-head` for resolve-conflicts and review-dependency
- `fix-ci-restarts` and the per-head cap for fix-ci
- `SWEEP_HEAD_CAP` for address-feedback

The fix-ci dispatcher reads a fix-ci run and its in-run rung-up, which both post a `pr-unblock / fix-ci` check, as one attempt: a stop in either one's push job makes the attempt a failed one, and the pair counts once toward the caps.

The fix-ci and address-feedback retries run one model rung up, read in the run from the head's own stop record. A retry that acts and does not stop posts success over the failing status; one that ends on a skip (a reply job with no model turn) leaves it. fix-ci's model escalations `protected-path` and `weaken-required` stay with a person, as `ci-fix-protected-path` and the new `ci-fix-weaken-required`.
- `fix-ci-context` and the fix-ci dispatcher read every check run on the head (`filter=all`) instead of the latest per name, so a contract-only run's later skip of a lane no longer hides that lane's failure, and a head with a hidden failure is not read as resolved.
- An address-feedback round that keeps no thread while a review thread is still unresolved (a reviewer the lane does not act on, such as Codex, a review of an older head, a thread it already answered) now ends `feedback-untaken-threads`, routed to a failing status, instead of a silent `not-applicable` skip. The dispatcher now dispatches an ungated head once for any unresolved thread, so that stop is reached; the select job's lane-stopped check ends the head, and the next tick does not dispatch it again. A reply job that fails with no escalation reason (a lane token it could not get) ends `feedback-publish-failed`, also routed to a failing status, instead of posting no stop.
- The monitoring lane gains signal 10, `stalled lane stop`. Each open pull request whose pr-unblock stop has had no new attempt on its head for over 2 hours is listed in one rolling issue. A skip is not an attempt. A stop includes a `needs-human` that `clear-escalations` took off for a reason now routed to a failing status. It reads the 40 most recently updated open pull requests and their newest comments in one GraphQL query, reading up to 200 older comments only for a pull request whose newest name no stop on its head; past 40 pull requests, or past those comments, it names what it left unread in the run's gaps.
- The merge path floor (`babysit_risk.HIGH_FLOOR`, `merge-holds.mjs` `HOLD_PATH_FLOOR`, and the review lanes' and ci-status's hold lists) also holds `.github/scripts/pr-unblock/escalation-routes.mjs`, which `clear-escalations.mjs` and `gate-source.mjs` now import, and `escalation-routes.json`, the routing table it reads, and the scripts that act on a route: `report-escalation.sh`, which labels a held reason, `adjudicate-feedback.mjs` and `publish-feedback.mjs`, which decide and resolve review threads, and `.github/scripts/apply-patch/apply-patch.mjs`, which holds fix-ci escalations, with every module they import (`request-budget.mjs`, `dependency-classify.mjs`, and `predicates.mjs`, `protected-paths.mjs` and `retry-fetch.mjs` in `apply-patch/`). A change that moves a reason from `hold` to `fail`, or that stops a held reason from labeling or lets a model verdict resolve a thread a person must, needs a person. `test_merge_holds_sync.py` now also follows a module-relative file a floored module reads (`new URL("./…", import.meta.url)`), so the next such data file fails there until it is on the floor.
- A select job that finds a stop gone on its head clears that activity's failing status (`stop-resolved`): `address-feedback` once no hold and no unresolved review thread is left, `fix-ci` once a whole listing of the head's checks, every one completed, has none failing. fix-ci now reads the head's checks before its round cap, so a head re-run green after the cap clears too. A select that fails to read clears nothing.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
bump: patch
---

### Changed

- `babysit_risk.HIGH_FLOOR` also holds `.github/scripts/pr-unblock/escalation-routes.mjs`, which `clear-escalations.mjs` and `gate-source.mjs` import, and `escalation-routes.json`, the routing table it reads, so the floor still holds every module its scripts load, and the scripts that act on a pr-unblock stop's route (`report-escalation.sh`, `adjudicate-feedback.mjs`, `publish-feedback.mjs`, `apply-patch.mjs`) with every module they import.
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ before(() => {
writeFileSync(resolved, JSON.stringify({ selected: { args: "ci" } }));
// The issue lane's protected-path rules come from the base's apply-patch
// and patch-rules.json, as committed.
for (const file of [".github/scripts/apply-patch", ".github/scripts/pr-merge/merge-holds.mjs", ".github/scripts/pr-unblock/dependency-classify.mjs", ".github/scripts/pr-unblock/thread-scope.mjs", ".github/actions/resolve-config/patch-rules.json"]) {
for (const file of [".github/scripts/apply-patch", ".github/scripts/pr-merge/merge-holds.mjs", ".github/scripts/pr-unblock/dependency-classify.mjs", ".github/scripts/pr-unblock/thread-scope.mjs", ".github/scripts/pr-unblock/escalation-routes.mjs", ".github/scripts/pr-unblock/escalation-routes.json", ".github/actions/resolve-config/patch-rules.json"]) {
cpSync(path.join(REPO_ROOT, file), path.join(base, file), { recursive: true });
}
});
Expand Down
Loading
Loading