Repository navigation
feat(pr-pipeline): let fix-ci adopt idle owner PRs - #8997
Conversation
Owner decision Q22 (2026-10-22): pr-unblock-dispatch now starts fix-ci for a non-draft PR opened by an account in the new top-level `adoption` section (owner-ids; this repo lists kyle-sexton) once the PR's updatedAt and its head commit's committer date are both idle-hours (24) old, with no hold label and no body line starting `Hold:`. Lanes App PRs keep their rules. The listing query also selects User databaseId, updatedAt, body and the head commit's committedDate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #8997: the owner Hold: line now uses babysit's BODY_MERGE_HOLD_RE semantics (any case, any leading non-newline whitespace, a bare CR ends a line), and fix-ci's hold labels add the tracker's human-gated label from the base .work-item-tracker.json, as pr-merge.yml resolves it (needs-human when unmapped). An unreadable tracker config stops fix-ci alone. Docs say pr-merge's adoption path is still to land. Tests cover spoofed logins, author null, an unreadable commit date and per-node skip reasons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
claude-review reviewed Code review: PR #8997 (fix-ci adopts idle owner PRs)I found nothing to flag, so I posted no inline comments. This is a read-through of the diff. I did not run the test suites; the PR body's test counts are author-claimed and unverified by me. What I checked
Observations only (not findings)
|
|
claude-security-review reviewed Security review: PR #8997 at 5db81aeFindings: 0 PR #8997 lets What I checked
Plugin manifests
No security issues found. |
|
The pr-unblock lane stopped on this pull request and needs a person: the merge stages a change under .github/workflows/, which the lane does not push.
To resume, deal with the reason above, remove the gh workflow run pr-unblock.yml -R melodic-software/claude-code-plugins -f pr-number=8997 -f activity=resolve-conflicts |
Conflicts resolved: - dispatch.mjs: both sides renamed the same retry variable; kept main's name. - pr-pipeline.yaml, pr-pipeline.schema.json: kept both the adoption and the branch-cleanup sections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The pr-unblock lane stopped on this pull request and needs a person: the merge stages a change under .github/workflows/, which the lane does not push.
To resume, deal with the reason above, remove the gh workflow run pr-unblock.yml -R melodic-software/claude-code-plugins -f pr-number=8997 -f activity=resolve-conflicts |
Conflicts resolved: - dispatch.mjs: the header comment names both fix-ci adoption and fix-docs; the imports keep fix-ci's adoption helpers and add fix-docs-dispatch. - dispatch-limits.test.mjs: run() takes main's docsPulls third and the branch's tracker fourth; the tracker tests pass [] for docsPulls. Both the adoption tests and the fix-docs-per-run test kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts resolved: - fix-ci-dispatch.mjs: skipReason and dispatchCiFixes take both the branch's adoption and main's injectable now. Semantic fixes the markers did not show: - The infra-skip re-check main added after readRequiredRun now passes adoption, so an adopted owner PR is not rejected there as unlisted. - fix-ci-dispatch.test.mjs: drop the branch's duplicate NOW (main declares the same value) and add an infra-only adopted owner PR case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The pr-unblock lane stopped on this pull request and needs a person: the merge stages a change under .github/workflows/, which the lane does not push.
To resume, deal with the reason above, remove the gh workflow run pr-unblock.yml -R melodic-software/claude-code-plugins -f pr-number=8997 -f activity=resolve-conflicts |
…owner PRs A base .work-item-tracker.json that is not JSON stopped fix-ci for every PR, lanes App PRs included. Now lanes App PRs proceed under the default hold labels, and each adopted owner PR is skipped with the stated reason; the dispatcher run still fails so the broken file shows. The tracker file is not read at all while adoption.owner-ids is empty. While it lists anyone, the human-gated label holds lanes App PRs too, as documented. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No related issue: owner decision Q22 (2026-10-22)
Summary
This gives the lanes new unattended power. pr-unblock's
fix-ciwill now run a model on PRs that a person opened, not only on lanes App PRs, and push fix commits to those branches. Without anyone asking, it picks up a non-draft PR from an account listed in the new top-leveladoption.owner-ids(this repository lists kyle-sexton, user id 153232337) when all of these hold:main;do-not-merge,needs-humanor tracker human-gated label (config.role_labels["human-gated"]in the base.work-item-tracker.json) and no body line startingHold:;updatedAtand its head commit's committer date are both at leastadoption.idle-hours(24) old;ci-statusfailed.This is the fix-ci half of Q22. The pr-merge half reads the same
adoptionsection and lands separately.docs/conventions/pr-pipeline.yamlis a lane-power file, so a human merges this PR.Fix
fix-ci-dispatch.mjs:LIST_QUERYalso selects... on User { databaseId },updatedAt,body, and the head commit'scommittedDate.pushedDateis not used: GitHub deprecated it and it is mostly null.skipReasonadmits anadoption.ownerIdsauthor once both dates areidleHoursold. A missing or unreadable date counts as not idle.skipReasonalso skips a body line startingHold:. Lanes App PRs carryHold: a human merges this(report-outcome.mjs:99), which holds the merge, not a CI fix, so their rules are unchanged.ownerIdsis[], so nothing is adopted when the section is absent.dispatch.mjs:maintakes an injectableloadAdoption(defaultloadBaseAdoption) and passesadoptionandnowtodispatchCiFixes.baseHumanGatedLabel, the way pr-merge resolves it):adoption.owner-idslists anyone. While it is read, it is added to the hold labels for every fix-ci candidate, so it also holds a lanes App PR that carries it. This is intended: the human-gated label holds any PR. Withowner-idsempty the file is not read and lanes App PRs keep the hold labels they had (do-not-merge,needs-human)..work-item-tracker.jsonthat is not JSON holds only the adopted owner PRs: each is skipped with "base tracker config unreadable, so its human-gated label is unknown" (adoption.heldinskipReason). Lanes App PRs still get fix-ci, and the dispatcher run fails so the broken file shows.resolve-config.mjs: addsadoptionFromBase, built likeredMainFromBase. This file is not inBROKER_PATHS, andresolve.mjsis unchanged.adoptionobject (idle-hoursinteger from 1 to 720, default 24;owner-idsunique positive integers, default[]).pr-pipeline.yamlsets the section.## Adoptionsection and an updated fix-ci scope paragraph.pr-run-activity.mdand two comments inpr-unblock-dispatch.ymlnow name the new scope.Downstream checks (none refuses an owner-authored head):
check-trusted-trigger.mjs:812and the broker'sauthorize.mjs:184require only that the author is on the trusted-actor list, and kyle-sexton is listed.dispatcher.mjscheckDispatcherhas no author key on the dispatch path.fix-ciandapply-patchapplies-whenchecks only labels and draft state.apply-patch.mjsTARGETS.prchecks for a same-repository head, draft state, and hold labels. It has no author check.fix-ci-context.mjscountFixRoundscounts only the App's trailer commits, so an owner PR with zero App commits starts at 0 rounds. The existing stranger-commit test covers this.mainalong with the config (binding.mjsTRUST_FILES), so a new top-level key needs no pin bump. No file inBROKER_PATHSchanged, so the body names no broker pin.A consequence to know: fix-ci's own push restarts the idle clock, so an owner PR gets at most one fix round per idle window.
Verification
not opened by the lanes App, and the missingon Userfield in the query):fix-ci-dispatch.test.mjs:ci-statusis dispatched;Hold:line, an unlisted user, an unreadable date, or no adoption list means no dispatch;Hold: a human merges thisis still dispatched.dispatch-limits.test.mjs: the live config adopts the owner PR end to end, and the same config with theadoptionsection removed does not. A mapped human-gated label holds an adopted PR. Under a malformed tracker file, lanes App PR 63 is dispatched and an idle owner PR is not (exit 1); with noowner-idsthe file is not read (exit 0). This test was rewritten first and failed before the fix.fix-ci-dispatch.test.mjsalso coversadoption.held, and an adopted owner PR whoseci-statusfailed on infra only is left to the reconciler, as lanes App PRs are.node --testat the current head over.github/scripts/pr-unblock,.github/actions/resolve-configand.github/scripts/branch-cleanup: 1118 pass, 0 fail. Earlier results:.github/scripts/pr-unblock: 445 pass, 0 fail..github/actions/resolve-config: 552 pass, 0 fail.check-trusted-trigger298,check-wip-cap29,report-check-run99, andpr-merge/refire-refused22, all pass.scripts/check-convention-yaml.test.sh: 43 pass.check-affectedpassed.scripts/read-runner-dispatcher-gate.test.shfails the same way onmain(runner-policy not installed locally).Related
adoptionsection.🤖 Generated with Claude Code