Measured while closing the re-verification half of #13272 (read of all 22 cited cloud consumers against cloud cb8ee7ff, 2026-09-15T15:1xZ). Filed rather than fixed: triage's instruction on #13272 is explicit — "A citation that turns out to have no live consumer is a liveness re-grade, and that goes back to triage rather than being decided in the PR." This card is that hand-back. ⛔ No domain:* label: that production is the triage seat's.
The row
packages/spec/liveness/agent.json, prop tools:
"tools": { "status": "live", "evidence": "cloud: packages/service-ai/src/agent-runtime.ts", "note": "legacy direct-tool fallback." }
Three readings, one direction
1. Zero consumers in cloud. At cloud cb8ee7ff (verified as the REST tip of main, not the local clone's opinion), the only two hits for agent.tools are comments recording its removal:
packages/service-ai/src/agent-runtime.ts L228 — "since framework#3894 removed agent.tools[], skills are the only tool-bearing slot (ADR-0064)"
- L566-571 — describes the deleted branch and why it went: it "resolved names against
availableTools — the FULL registry — with no surface check, so an ask-surface agent could name an authoring tool and get it: the one seam that broke the 'nothing falls through to the global registry' invariant."
2. Positive control, same corpus, same path shape, same quoting. agent.skills returns four real reads in the same tree (agent-runtime.ts L618-619, L539; routes/assistant-routes.ts L152). The instrument fires, so the zero above is a reading and not a broken grep.
3. The framework already retired the key. packages/spec/src/ai/agent.zod.ts L234 declares tools as retiredKey(...), whose payload opens "agent.tools was removed in @objectstack/spec 17 — use skills" and which types the key never, so authoring it fails tsc before any parse runs.
⇒ The ledger asserts live on a key its own schema tombstoned, citing a runtime that deleted the branch.
⭐ Why this is worth a card and not a one-line edit
The row was never scrutinised — it was exempt from scrutiny. Until PR #13309 (2026-08-30) this row's evidence read packages/services/service-ai/…, and evidence.mts's FOREIGN_PATH_PREFIXES lists exactly that prefix, so the citation was classified foreign and never resolved. #13272 filed that exemption as a path-spelling defect. This card is the first demonstration that the exemption also hid a dead key, not only a misspelled pointer — which is a sharper version of the same finding, and the reason the other 21 rows were worth reading one by one.
Note the asymmetry that keeps it hidden even now: checkEvidenceAnchors resolves local anchors only. A cloud: row's evidence is never re-derived by CI in either direction, so no gate can ever fail on this row. Only a human or a seat with a cloud checkout can.
What this card is NOT
Dedup: searched agent.tools liveness and liveness ledgers still cite over this repo including closed issues — no card on this axis; the second query is the non-vacuous control (it returns #13272 itself and 14 neighbours).
Generated by Claude Code
Measured while closing the re-verification half of #13272 (read of all 22 cited cloud consumers against cloud
cb8ee7ff, 2026-09-15T15:1xZ). Filed rather than fixed: triage's instruction on #13272 is explicit — "A citation that turns out to have no live consumer is a liveness re-grade, and that goes back to triage rather than being decided in the PR." This card is that hand-back. ⛔ Nodomain:*label: that production is the triage seat's.The row
packages/spec/liveness/agent.json, proptools:Three readings, one direction
1. Zero consumers in cloud. At cloud
cb8ee7ff(verified as the REST tip ofmain, not the local clone's opinion), the only two hits foragent.toolsare comments recording its removal:packages/service-ai/src/agent-runtime.tsL228 — "since framework#3894 removedagent.tools[], skills are the only tool-bearing slot (ADR-0064)"availableTools— the FULL registry — with no surface check, so anask-surface agent could name an authoring tool and get it: the one seam that broke the 'nothing falls through to the global registry' invariant."2. Positive control, same corpus, same path shape, same quoting.
agent.skillsreturns four real reads in the same tree (agent-runtime.tsL618-619, L539;routes/assistant-routes.tsL152). The instrument fires, so the zero above is a reading and not a broken grep.3. The framework already retired the key.
packages/spec/src/ai/agent.zod.tsL234 declarestoolsasretiredKey(...), whose payload opens "agent.toolswas removed in @objectstack/spec 17 — useskills" and which types the keynever, so authoring it failstscbefore any parse runs.⇒ The ledger asserts
liveon a key its own schema tombstoned, citing a runtime that deleted the branch.⭐ Why this is worth a card and not a one-line edit
The row was never scrutinised — it was exempt from scrutiny. Until PR #13309 (2026-08-30) this row's evidence read
packages/services/service-ai/…, andevidence.mts'sFOREIGN_PATH_PREFIXESlists exactly that prefix, so the citation was classified foreign and never resolved. #13272 filed that exemption as a path-spelling defect. This card is the first demonstration that the exemption also hid a dead key, not only a misspelled pointer — which is a sharper version of the same finding, and the reason the other 21 rows were worth reading one by one.Note the asymmetry that keeps it hidden even now:
checkEvidenceAnchorsresolves local anchors only. Acloud:row's evidence is never re-derived by CI in either direction, so no gate can ever fail on this row. Only a human or a seat with a cloud checkout can.What this card is NOT
FOREIGN_PATH_PREFIXES. Three liveness ledgers still citepackages/services/service-ai/…, a path that exists in NEITHER repo, and repeat the falsified "stale build artifact with no src/" note #13272's triage ruled that out as a rider and the ruling stands. (Separate, also not decided here: after fix(spec): repoint the agent, skill and action liveness citations at the real cloud path #13309 the constant now matches zero evidence fields across all 36 ledgers — control: 26 fields cite the realpackages/service-ai/path — so it is inert.)dead, or thelive-elsewhere-style class Liveness ledger has no verdict for keys enforced only in a sibling repo —deadmisreads as deletable (manifest.runtimecase) #13483 discussed) is triage's call, and it interacts with whether a tombstoned key should carry a liveness row at all.packages/services/service-ai/…, a path that exists in NEITHER repo, and repeat the falsified "stale build artifact with no src/" note #13272's stamping PR, which leaves this row'sstatusuntouched and stamps noverifiedAton it. AverifiedAthere would certify the wrong thing.Dedup: searched
agent.tools livenessandliveness ledgers still citeover this repo including closed issues — no card on this axis; the second query is the non-vacuous control (it returns #13272 itself and 14 neighbours).Generated by Claude Code