Conversation
… HEAD (#223) ckptReusable (byte-identical in issue-triage-fanout, issue-research-fanout, pr-triage-fanout) previously reused a cached entry purely because the issue/PR's `updatedAt` was unchanged — but a triage verdict is a claim about REPO STATE ("is this already done", "does this file exist"), not just about the issue text, so an untouched issue kept serving an arbitrarily stale verdict forever. Each entry now also carries the HEAD sha it was computed against. On reuse, an entry whose cached sha differs from the current HEAD is only kept if a batched `git diff --name-only <sha> HEAD` (one ckpt-treecheck agent call per run, never per item) proves the diff does not touch that entry's own files[] footprint; an unknown/empty footprint (every pr-triage entry, and non-GREEN research verdicts) fails closed to any non-empty diff. SPINE_VERSION is bumped 1.0.0 -> 1.1.0 so every pre-#223 entry (no headSha) recomputes once. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NnAzwVH94FkU5tpsrjr3hs
|
The That's a GitHub-side model-routing/availability error in the Copilot backend ( All other checks are green: Generated by Claude Code Generated by Claude Code |
|
Follow-up: the re-run attempt itself was blocked — Leaving this PR subscribed and watched; if the check re-fires on its own (e.g. on the next push, or GitHub retries it server-side) I'll act on the result then. This is not blocking merge — it's not a required status check, and every check that actually reviews this PR's code ( Generated by Claude Code Generated by Claude Code |
|
Auto-merge routine: blocked — confirmed medium-severity findings
Additionally, Per the merge routine's gate, a confirmed medium+ finding blocks auto-merge regardless of CI/risk-path status. Applying Generated by Claude Code |
Summary
ckptReusable(byte-identical acrossissue-triage-fanout,issue-research-fanout,pr-triage-fanout) previously reused a cached entry purely because the issue/PR'supdatedAtwas unchanged — but a triage verdict is a claim about repo state, not just issue text, so an untouched issue could keep serving an arbitrarily stale verdict forever (the#15repro in the issue).ckpt-treecheckagent's batchedgit diff --name-only <sha> HEAD(one call per run, per distinct stale sha — never per item) proves the diff does not touch that entry's ownfiles[]footprint. An unknown/empty footprint (everypr-triage-fanoutentry, and every non-GREENissue-research-fanoutverdict) fails closed to any non-empty diff — the same direction as a plain HEAD-sha key.SPINE_VERSIONbumped1.0.0→1.1.0in all three files so every pre-Checkpoint reuse ignores repo HEAD, re-serving verdicts about a stale tree #223 cached entry (none carriesheadSha) recomputes exactly once and is stamped going forward.Closes #223
Test plan
npm test— 1259 passing, 0 failing (up from the base commit; includes ~50 new tests for the tree-check across the three sims, plus a test assertingckptReusable's md5 stays identical across all three files).args.fresh; a fresh entry is stamped with the resolved HEAD sha; the exact#15-shaped repro (a cachedBLOCKEDverdict recomputes once its blocker's file lands, with noupdatedAtchange).Choices made
files[]) with Option 1 (plain HEAD-sha key) as the fail-closed fallback whenfiles[]is unknown — exactly the issue's own recommendation. Every failure mode (unresolved current HEAD, unresolved historical sha, unknown footprint) fails closed to a recompute rather than a silent reuse, since the bug this fixes is itself a silent-stale-reuse.pr-triage-fanouthas nofiles[]field at all (its schema never carried one — a PR's mergeability/CI verdict isn't framed as "which files does this depend on"). Rather than special-case it, the same uniformckptReusableapplies: every entry there has an unknown footprint, so any non-empty tree diff invalidates it. This is actually correct, not just a fallback — a PR's mergeability/CI can change from an unrelated commit landing on the base branch alone, with zero change to the PR itself or itsupdatedAt, which was itself a real (if unremarked) instance of the same bug class. SinceckptReusablestill needed thenormFiles/fileKey/normPathcomparison helpers to stay byte-identical across all three files, I copied that leaf-function trio (not the full file-overlap engine, whichpr-triage-fanouthas no use for) intopr-triage-fanout.jstoo.ckpt-metacall, no extra agent) and is only spawned at all when at least one candidate's cachedheadShadiffers from the current HEAD — one call for the whole run, deduped over distinct stale shas, never one per item. A no-change re-run still spawns zero relay/classify and zero tree-check agents.CLAUDE.md) is offline AsyncFunction-wrapped simulators with stubbed runtime globals — there's no harness in this repo for spawning a live two-commit Workflow run, and every other checkpoint/injection-hardening behavior here is verified the same way. I've encoded that exact scenario as a sim test (#223 the exact repro: a cached BLOCKED verdict is recomputed once its blocker's file lands) using fixture git-diff output instead of a real commit pair. Flagging this rather than silently claiming the literal acceptance wording is met.Deferred
None of the issue's Acceptance items are unshipped — see the choice above on how the "real two-commit run" item was interpreted given this repo's sim-only test infra.
Note on review
This diff doesn't touch
plugin.json,.claude-plugin/, or the untrusted-issue-text injection fence/preamble/nonce mechanics of any workflow, but it does touch the checkpoint logic of all three security-sensitive read-only fan-outs and adds a new agent (ckpt-treecheck) whose prompt embeds model-generatedfiles[]path strings into agit diff -- <paths>pathspec. That's read-only and terminated by--(no shell injection surface), but it's close enough to this repo's security-critical surface that I'm leaving auto-merge off for a human look, per the repo's own auto-merge policy erring toward review for anything security-adjacent in these workflows.🤖 Generated with Claude Code
https://claude.ai/code/session_01NnAzwVH94FkU5tpsrjr3hs
Generated by Claude Code