refactor(pipeline): adopt verdict read across ship-it / write-code / heal-ci — delete the 3 inline resolvers#3713
refactor(pipeline): adopt verdict read across ship-it / write-code / heal-ci — delete the 3 inline resolvers#3713usirin wants to merge 2 commits into
verdict read across ship-it / write-code / heal-ci — delete the 3 inline resolvers#3713Conversation
…al-ci — delete the 3 inline resolvers (#3686) Replace the divergent inline SHA-bound verdict-marker resolvers in the ship-it, write-code and heal-ci skills with `pipeline-cli verdict read`, each citing the verb in this same landing commit (the #3254 same-commit-adoption rule), and draw the `verdict read` grandfathered exemptions to zero. The verb owns the (PR, gate) resolution: the ADR-0055 write+ author-gate, the latest-wins pick, and the ADR-0058 SHA-staleness refusal folded into one exit code. Its existing unit tests remain the contract — no verdict-resolution behavior is changed here. Behavior that is MORE than a single (PR, gate) resolution is preserved, not folded into the verb: - write-code keeps the multi-PR pre-pick scan and the N=3 FAIL-round count (the verb resolves the latest verdict; it does not count rounds). - heal-ci keeps its N=3 cap count and the native CHANGES_REQUESTED fold. - ship-it keeps the native APPROVED/CHANGES_REQUESTED review fold and the §CP advisory resolution (an advisory is SHA-less by design, so the verb resolves it `none` — its author-gated pick stays ship-it's). - `is_current` survives only for the two signals the verb does not resolve: a native review's commit_id and a §CP advisory's body Reviewed-head SHA. write-code Step R2 now reads the resolving FAIL body via the comment id the verb returns, rather than re-deriving the latest-wins pick. Fixes #3686
|
review-code: advisory — blocking-set PR (manual merge) Reviewed-head: @ aa584d7 §CP PR ( Re-review at the new head. The prior review-skill FAIL (@ 5ab6a4d) was in the skill class; the code half was and remains clean. Every body checkbox is Acceptance criteria
Verification — the lint result is earned, not vacuousThe single risk in a diff like this is a manifest edit that clears the lint by removing its teeth. Falsified directly:
So the removals are a genuine draw-down: the lint would fire if the citations regressed, and it does not fire now because the consumers really do cite the verb. Type/API design
Checks at head
Fan-out (silent-failure · type-design · test-gap)
Note for the merge actorEvery body checkbox is |
|
review-skill: advisory — blocking-set PR (manual merge) Reviewed-head: @ aa584d7 §CP PR ( Re-review of the prior FAIL (comment 5017948256, @ 5ab6a4d). The AC3 defect is genuinely repaired. Every body checkbox is The prior FAIL — newest-wins restorationThe ruling was: the prose (ship-it lines 783/952) is the source of truth, and the refactor's FAIL-precedence fold must be reverted to newest-wins. Verified restored, and correctly.
Original scope — re-verified at this head
Non-blocking observations — none block this PR
Checks at head
Fan-out (silent-failure · type-design · test-gap)The silent-failure axis is where this PR does its work, and the two additions (newest-wins clearing + the DEFER-on-unresolved) both close real silent-failure paths. Observation 1 above is the one residual on that axis; it is pre-existing, so it is noted rather than routed as a FAIL or an appended AC. No out-of-scope findings worth a Note for the merge actorEvery body checkbox is |
…eview fold (#3686) The `verdict read` adoption refactor replaced the code-namespace fold with FAIL-precedence (`CHANGES_REQUESTED` unconditionally vetoing, `APPROVED` only counting when no FAIL stood) and dropped the timestamps newest-wins needs — `REVIEW`'s `at: .submitted_at` and the marker objects' `created_at`. That contradicted the unchanged prose in the same sections (ship-it Step 2's "the newest of {latest decisive review, latest review-code marker comment} by timestamp" and "an old FAIL behind a newer PASS does not block") and #3686's "no behavioral change to verdict resolution" AC. It is also a live wedge: a PR FAIL'd, repaired, and re-PASSed at the same head would stay permanently blocked by the superseded FAIL, breaking the repair -> re-review -> ship loop. The prose is the source of truth, so the code now matches it: - ship-it Step 2, write-code R1, heal-ci: `REVIEW` carries `at: .submitted_at` again, and the fold compares it against the resolving marker's `created_at` (resolved from the comment id `verdict read` prints, since the verb's outcome carries no timestamp). Newest event wins; a newer APPROVED clears an older FAIL, a newer marker stands over an older review. - write-code R1 / heal-ci additionally set CODE_FAIL back to 0 on a newer APPROVED, instead of only ever raising it. Also narrows the transient-5xx fail-open the reviewer raised as non-blocking: `verdict read` prints its outcome JSON on both exit paths, so absent JSON means the namespace never resolved (a transport error, not a verdict). write-code R1 and heal-ci now flag that as VERDICT_UNKNOWN and defer rather than silently read it as "no FAIL" and skip a real repair. ship-it needs no change there — an unresolved namespace already leaves both PASS and FAIL at 0, i.e. `unverified` -> refuse. Everything else the refactor achieved is preserved: the three inline verdict resolvers stay deleted and cite `pipeline-cli verdict read`, the grandfathered exemptions stay at zero, the N=3 repair caps and multi-PR scan stay, and ship-it's §CP advisory resolution is untouched.
|
repair round 1 — re-pushed at `aa584d7bcfd98addedc2aa1377c3839f6f1c0f47` (was `5ab6a4d1`). Blocking finding addressed — newest-wins restored (not FAIL-precedence)The refactored native-review fold had become FAIL-precedence while the prose in the same section still specified newest-wins (ship-it Resolution: the prose is the source of truth; the code now matches it. FAIL-precedence was not a conservative default — a PR FAIL'd, repaired, and re-PASSed at the same head would have stayed permanently blocked by the superseded FAIL, wedging the repair → re-review → ship loop. It also violated #3686's "no behavioral change to verdict resolution" AC.
Non-blocking point also addressed (it was small)The transient-5xx fail-open: I did not reduce the API-call count — that would mean re-hand-rolling the resolution the PR just deleted, which is the opposite of this issue. Preserved from the original diffThree inline verdict-marker resolvers stay deleted and cite Guards re-run at this head
The head moved, so the prior verdicts are dismissed — re-review needed against |
Adopts the already-shipped
pipeline-cli verdict readverb across the three skills that each hand-copied the ADR-0058 SHA-bound verdict-marker resolver, deleting all three inline copies and citing the verb in this same landing commit (the #3254 same-commit-adoption rule). This is adoption of an existing tested core, not a new core (#2824).What changed
skills/ship-itjqblocks (code/doc/skill/design) + theiris_currentapplicationverdict read --gate <g> --expect PASS|FAILper present namespaceskills/write-codejq, Step-R2 latest-wins body pickverdict readper gate; R2 reads the body via the comment id the verb returnsskills/heal-ciCODE/DOCmarkerjq+ staleness testverdict read --gate <g> --expect FAILadoption-lint/manifest.tsverdict readgrandfatheredexemptionsdrive-issue.jsmirror survivesThe verb owns the ADR-0055 write+ author-gate, the latest-wins pick, and the ADR-0058 SHA-staleness refusal, folded into one exit code. Its existing unit tests remain the contract — no verdict-resolution behavior is changed.
Behavior that is MORE than a single (PR, gate) resolution — preserved, not folded in
This was the reason #3265 deferred the migration (the non-drop-in rewrite). Each residue stays inline, and is now explicitly justified in-file as something the verb does not do:
verdict readresolves the latest verdict; it does not count rounds. The round count (author-gated, clustered by >120s gap) and the cap exclusion are untouched.CHANGES_REQUESTEDfold.APPROVED/CHANGES_REQUESTEDreview fold — the verb reads marker comments; a native review is a different record type (and needs no ACL gate, GitHub author-attributes it).noneand cannot author-gate it — the advisory's own author-gated pick stays ship-it's, which is why the$authorizedACL set is still built there.is_currentsurvives only for the two signals the verb does not resolve: a native review'scommit_idand a §CP advisory's bodyReviewed-headSHA.Adoption is genuine, not a citation false-positive
adoption-lint's citation check is a substring match, so a stray mention of the verb can clear a file that still re-derives. Verified this is not that: each skill has real$VERDICT read --prcall sites (ship-it 8, write-code 5, heal-ci 2). The three files still match the decision'ssignatureonly via legitimate residue — the native-reviewsort_by(...) | last, the ADR-0115 claim-marker resolver (a different decision), the run-evidence run lookup, and the round-count ACL loop — none of which is a verdict-marker resolver.Note
ship-itwas nevergrandfathered: it was already clearing the lint via its pre-existingpipeline-cli verdict postcitation while still re-derivingread. That false-clear is now a real adoption.Guards
adoption-lintclean (62 files / 6 decisions, zero exemption findings) ·pnpm lint0 ·pnpm typecheck0 (33/33) ·pipeline-clitests 1606 passed (113 files) ·gh-phoenix lint-skillsclean ·leak-guard sweepclean.Out of scope
Changing
verdict read's behavior, and the ship-it / write-code lifecycle graduations (#3691 / #3692).§CP change (adoption-lint manifest + 3 gate skills) — banks for human control-plane approval, not auto-merge.
Fixes #3686