feat(ci): status-needs-fix label clears on the author's push — unaddressed findings become queue-visible (#2815) - #2819
Conversation
…ed finding becomes queue-visible (#2815) A /review, /validate-pr or merge-train finding is posted as a COMMENT, and a comment never moves `reviewDecision`. So a PR carrying an unaddressed CRITICAL was byte-identical, in every field the queue reads, to one nobody had looked at: three such PRs sat under Ready and the next train re-validated each at full lane depth to rediscover what was already written on them. The finding is now also the `status-needs-fix` label (created on the repo); the skills that post findings set it, /open-pull-requests sorts it out of Ready and /merge-train Phase 0 holds it (trinity-dev#28). This workflow is the other half: the author's next push (`pull_request: synchronize`) removes the label, so "a finding is outstanding" needs no human bookkeeping in either direction. `pull_request`, not `pull_request_target`, twice over: a `_target` workflow is registered from the default branch and would be inert on dev until the next release (#2814); and on a same-repo PR — every PR the train handles — the plain token can already write labels. A fork PR's read-only token gets a warning, never a red run, and the reviewer clears the label by hand (#2767). Job-gated on the label, so an unlabelled push spends no runner. No checkout, no `run:`, no PR text read; pinned by tests/unit/test_2815_needs_fix_label_workflow.py. Fixes #2815 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VpvcfgWkmQPD7DrDLmATTf
|
`synchronize` also fires for a reviewer's "Update branch" click and for the merge train's Phase 4 conflict push to a member branch. Neither addresses a finding, and clearing on them hands the PR back to the queue with the finding still standing — the /review I1 on #2819. The event's `sender` is the pusher; the job now requires it to be the PR author, which is what AC#3 says in words ("a push by the author"). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VpvcfgWkmQPD7DrDLmATTf
vybe
left a comment
There was a problem hiding this comment.
merge-train 2026-09-15: validated at lane depth; all checks green on the merged head.
…ords its mutation (#2829) Three of five ejections on the 2026-09-15 merge train — the third train running — were tests that prove the code was written rather than that it runs: source-text regexes over the module under test (#2811), a bound check at the one value where both bounds coincide (#2817), a docstring claim about CI never negative-controlled (#2805). All green. - docs/testing/STRATEGY.md: a new "Evidence bar for a test" section beside the harness bar — the three spellings, the two greps (the live-consumer grep is the one that decides), guard-vs-source-only with the train's own pair (#2819 kept, #2811 ejected, same shape), mutation as the fix standard, bound tests away from the coincidence — each with what enforces it. - .github/pull_request_template.md: a Testing checkbox for "every new test executes the changed path" and a `Mutation:` line naming the test(s) that go red with the fix reverted ("n/a — not a fix" otherwise). The trailing space after the colon matches the existing `Journey Impact:` line — a fill-in prompt. - docs/memory/learnings.md: the class, with the prior occurrences. The skill half — /review Step 2.5 and /validate-pr §5.4 answered first and in writing, /implement's two done-criteria — is trinity-dev#29. Fixes #2829 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VpvcfgWkmQPD7DrDLmATTf
…ords its mutation (#2829) (#2833) Three of five ejections on the 2026-09-15 merge train — the third train running — were tests that prove the code was written rather than that it runs: source-text regexes over the module under test (#2811), a bound check at the one value where both bounds coincide (#2817), a docstring claim about CI never negative-controlled (#2805). All green. - docs/testing/STRATEGY.md: a new "Evidence bar for a test" section beside the harness bar — the three spellings, the two greps (the live-consumer grep is the one that decides), guard-vs-source-only with the train's own pair (#2819 kept, #2811 ejected, same shape), mutation as the fix standard, bound tests away from the coincidence — each with what enforces it. - .github/pull_request_template.md: a Testing checkbox for "every new test executes the changed path" and a `Mutation:` line naming the test(s) that go red with the fix reverted ("n/a — not a fix" otherwise). The trailing space after the colon matches the existing `Journey Impact:` line — a fill-in prompt. - docs/memory/learnings.md: the class, with the prior occurrences. The skill half — /review Step 2.5 and /validate-pr §5.4 answered first and in writing, /implement's two done-criteria — is trinity-dev#29. Fixes #2829 Claude-Session: https://claude.ai/code/session_01VpvcfgWkmQPD7DrDLmATTf Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Eugene Vyborov <1073874+vybe@users.noreply.github.com>
Summary
A
/review,/validate-pror merge-train finding is posted as a comment, and a comment never movesreviewDecision— so a PR with an unaddressed CRITICAL was byte-identical, in every field the queue reads, to one nobody had looked at. Three such PRs sat under ✅ Ready and the next train re-validated each at full lane depth to rediscover what was already written on them.The issue's "cheapest fix that would have worked", built in two halves:
status-needs-fix— created on this repo (D93F0B)./open-pull-requestssorts it out of Ready;/merge-trainPhase 0 shows it asNFIXand Phase 1 drops it without spending Phase 2.needs-fix-clear-on-push.ymlpull_request: types: [synchronize]— a push to the PR branch. Job-gated oncontains(labels.*.name, 'status-needs-fix'), so an unlabelled push spends no runner.pull_request, notpull_request_target, for two reasons that are both load-bearing: a_targetworkflow is registered from the default branch and would be inert ondevuntil the next release (bug(ci): issue promotion has not run since #2769 — the pull_request_target trigger is inert until it reaches main #2814 — this one has to work the day it lands); and on a same-repo PR the plain token can already write labels.core.warning, never a red run; the reviewer clears the label by hand at re-review. Any other refusal issetFailed. A 404 (raced with a manual removal) is not a failure.run:, no PR text read — it deletes one label from the PR that emitted the event and nothing else.tests/unit/test_2815_needs_fix_label_workflow.py10 static guards in the
test_2767shape: the trigger issynchronizeonly; it removes exactly this label and never adds one; the job is gated on the label; 403 → warning, 404 → info, else → failed; trigger ispull_requestand not_target; no checkout; norun:; nopr.title/pr.body;permissions == {pull-requests: write}only. Also confirmed the #2814 trigger-parity guard accepts this workflow (apull_request-onlyon:is out of its scope by design).Not in this PR
The
trinity-enterpriserepo has no such label or workflow./open-pull-requestsreads both repos, and an absent label is simply never Blocked-by-label there — the train is public-repo-only. Add both there if enterprise PRs start getting/review-ed at volume.Test Plan
cd tests && pytest unit/test_2815_needs_fix_label_workflow.py unit/test_2625_workflow_expression_cap.py unit/test_1891_python_version_parity.py -v— 56 passedNeeds-Fix Label Clears on Pushrun appears and the label is gone (thepull_requesttrigger reads the PR ref, so this is verifiable on the first push after merge — unlike bug(ci): issue promotion has not run since #2769 — the pull_request_target trigger is inert until it reaches main #2814's class)Fixes #2815
🤖 Generated with Claude Code
https://claude.ai/code/session_01VpvcfgWkmQPD7DrDLmATTf