v1.3.1 — agent integrity + three live FP fixes
New check (agentFindings, pure core + collectAgents fs wrapper; wired into
--audit and SessionStart, the only moment subagent definitions are read).
THE INCIDENT (hindsight, verified via git): 16 subagents lived in
hindsight-vercel/.claude/agents/ — one level BELOW the repo root. Claude Code
resolves .claude/agents/ by walking from the CWD upward and never descends, so
launched from the repo root not ONE ever loaded — silently, for weeks — while
CLAUDE.md claimed migrations were "enforced by the auto-invoked
migration-reviewer subagent". An agent that cannot load fails OPEN: no error, no
log. That is "fail-loud on silent-inertness" (CLAUDE.md) applied to subagents,
and a doc resting on one is Class 4 (phantom ref) over a new artifact.
It flags, all as STATIC file properties: an agents dir below the repo root;
missing frontmatter / name / description; a DOTTED model id (claude-opus-4.8 ->
claude-opus-4-8) — deliberately NOT a model allowlist, which would go stale and
false-fire on the next model shipped; duplicate names and byte-identical
descriptions (the router selects on description); and a phantom agent reference.
SCOPE, deliberately: it proves an agent CANNOT fire. It never claims one WILL —
selection is the model's discretion, and claiming otherwise is the overclaim the
positioning guard forbids. All five real failure modes lived in "cannot fire".
Replay: 14 findings at 8b93544^, 0 at HEAD.
Three live FPs from the same sessions, fixed:
- vacuous-test: blanking strings BEFORE stripping comments let an apostrophe in
prose ("// … France's longitude span …") open a phantom string that swallowed
a test body's braces AND itsawait dc.checkRound(...)— the block extracted
EMPTY and a test that plainly asserted was reported as asserting nothing. One
leftmost-first string|comment|regex pass. - compiled rules: comments were stripped only for CALL rules, so an IDENTIFIER
rule (import.meta) fired on the very COMMENT explaining it. Default inverted:
code-only unless the rule TARGETS comments — so nothing goes inert. - ledger: a VERIFICATION ask ("verify game.js does not need updating") minted an
unclosable HARD deliverable and escalated to BLOCK on work done correctly — an
empty diff there is SUCCESS. Third instance of one root defect (v1.0.5 pasted
listing, v1.2.1 declarative): the ledger presumed every named file must land in
the diff. Demoted to soft, demote-never-drop.
Adversarial review (Fable, three passes) found 13 real defects across the above,
every one fixed at root and pinned — incl. an @-in-pattern classifier that
condemned every decorator/npm-scope rule and RE-OPENED the prose FP it fixed;
untracked agent files invisible to git ls-files (the most likely home of a
broken agent — all four new ones were untracked); a bare-word phantom that
missed the incident's second blocker ("invoke the reviewer subagent"); two FNs
in the verify demotion (cross-clause anaphora, and a verify verb hiding INSIDE
the filename); a case-fold that invented a collision between QALead and qalead;
and a broken agent file minting a phantom about itself.
Self-check 638 -> 702; red-team 14/14; corpus unchanged (17/23 at-capture).
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Full symptom → root-cause → fix → regression-test in FIXES.md (v1.3.1).