Skip to content

fix(spec): repoint the liveness anchors for action type / body / method at their real consumers - #12517

Merged
huangyiirene merged 2 commits into
mainfrom
claude/issue-12215-action-liveness-anchors
Aug 26, 2026
Merged

fix(spec): repoint the liveness anchors for action type / body / method at their real consumers#12517
huangyiirene merged 2 commits into
mainfrom
claude/issue-12215-action-liveness-anchors

Conversation

@huangyiirene

Copy link
Copy Markdown
Collaborator

Fixes#12215

All three entries cited packages/runtime/src/http-dispatcher.ts. None of them is read there — verified by call graph, not by grep, because for these three keys a grep is exactly the thing that cannot answer the question.

Per-entry verdict

entryold citationverified consumer (call-graph read)new anchor
typehttp-dispatcher.ts (no line)sandbox/body-runner.ts:385const type = action.type ?? 'script', the #4352 gate deciding whether a body binds a handler at all; action-execution.ts:1309action.type === 'flow'dispatchFlowAction, :524isHeadlessInvokableAction, :552headlessActionTypeError, :906 MCP summary; domains/actions.ts:591 the REST route's actionTypeREPOINTED (framework half). objectui half left as sha-pinned @732b1bf, not re-graded
bodyhttp-dispatcher.ts (no line)sandbox/body-runner.ts:356const raw = action.body, whose own header at :342 calls itself "the ONE choke point where an action.body becomes an executable handler"; action-execution.ts:525 gates headless dispatch on action?.target || action?.bodyREPOINTED
methodhttp-dispatcher.ts (no line)objectui @7b6f7f889packages/core/src/actions/ActionRunner.ts:1774 (method = action.method || 'POST') and :1780 (config.method || action.method), landing on the real request at :1800const fetchInit: RequestInit = { method, headers }REPOINTED + REALM CHANGEevidenceScope: "cross-repo"

No verdict was re-graded. All three were live and remain live — citation repair only, per the triage instruction.

Why the gate could not see this, and why a grep could not settle it

The word-bounded key-mention check added in PR #12214 caught target and requiredPermissions because http-dispatcher.ts contains 0 occurrences of either key. These three are common English and HTTP words that the file is full of for unrelated reasons, so the check anchors on the coincidence and passes. Counted on the cited file:

  • type — 9 occurrences, zero action reads. Four are the TypeScript import type keyword (:9, :13, :14, :21); the rest are other domains' data or prose (error.type:862, a field-type→JSON-Schema mapper :926, details.type:1156, a metadata type list :1634, an inbox query param :1765).
  • body — 68 occurrences, zero action reads. The inbound HTTP request body threaded through the domain delegates (:890, :961, :1732, :1969), the result envelope at :728, and the file's own "Thin delegate — body extracted to ./domains/…" comments, where body means a function body.
  • method — 41 occurrences, zero action reads. The inbound HTTP verb (15 method: string parameter declarations, route matching such as method === 'GET' at :2067, the log line at :2178) and the ordinary object-oriented sense in prose (:837, :2047, :2108, :2135).

A regex over the action config's property names (action?.type / .body / .method and friends) returns zero matches in the whole 2188-line file. The action path was extracted into domains/actions.ts + action-execution.ts and the dispatcher now only delegates: handleActionshandleActionsRequest at :1969-1970.

Each repointed entry records this in its own note, so the next reader does not re-derive it.

The method realm change

type: 'api' actions are client-dispatched by design — action-execution.ts:557-563 (the api branch of headlessActionTypeError, :551-568) refuses them server-side with "it dispatches on target, not through the action registry". So the server never read the verb, exactly as with the bodyShape / bodyExtra siblings.

The single in-repo occurrence of action.methodaction-execution.ts:561 — is a diagnostic that interpolates the verb into that very refusal. It is evidence of non-consumption, and is deliberately not cited as a consumer.

H17 — on-hold #7898/#8347 Restart-touch file

packages/runtime/src/http-dispatcher.ts was read only; it is not in this diff. No breach. All other runtime/objectui files above were likewise read-only evidence surfaces.

Verification

Gate union run on the final tree, 0350639 — all green, each read from the gate's own printed verdict line (exit codes captured before any pipe):

  • check:liveness✓ … every 'path:NNN' citation names a line that file actually has and every cited file names the property it is evidence for; line citations: 305 pointer(s) … 305 inside the cited file; key-mention anchoring: 404 pair(s) asked, 403 anchored, 1 exempt
  • check:empty-state, check:strictness-ledger, check:variant-docs — green
  • check:changeset-gate-self-tests, check:objectui-changeset, check:nul-bytes — green
  • check-adr-0087-registration ("this PR adds no declared-breaking changeset"), check-changeset-no-major, check-empty-changeset ("1 declaring changeset(s) added") — green

Reverse verification (both legs red as predicted, restore proven by an empty git diff HEAD and a blob hash identical to HEAD; no build/dist leg applies — the gate reads the ledger JSON and sources directly via tsx):

  • pushing a new citation past EOF (body-runner.ts:356:99356) → exit 1, ✗ 1 citation(s) name a line the cited file does not have: action/body → …:99356 (the file has 783 lines)
  • repointing a new anchor at a file that never names the key → exit 1, key-mention anchoring: 405 pair(s) asked, … 1 UNANCHORED

Together these prove the gate actually reads the new anchors rather than passing them by omission.

Changeset

@objectstack/spec: patch — following PR #12214, which carried one for the same ledger files. packages/spec/package.json ships liveness in its files array, so the ledger is published package content.

Out of scope, filed separately

#12516 — the two entries PR #12214 repointed the day before have already drifted: action.target cites action-execution.ts:725 for a call now at :809, and action.requiredPermissions cites domains/actions.ts:172-180 for reads now at :393-400/:473/:526. Both stay green, because the lines are in range and the files name the keys — a fourth residual none of the three checks can see. Not folded in here: different entries, and this PR's own line numbers inherit the same exposure rather than fixing it.


Generated by Claude Code

…hod`
The three entries cited packages/runtime/src/http-dispatcher.ts, which reads
none of them: the action consumer was extracted into domains/actions.ts +
action-execution.ts (+ sandbox/body-runner.ts), and the dispatcher now only
delegates. Unlike the `target`/`requiredPermissions` rot repaired earlier,
these three are common English/HTTP words, so the word-bounded key-mention
check anchors on the coincidence and passes — call-graph verification by hand
was the only way to see it.
Part of #12215
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️1 changed file(s) yielded no anchor (packages/spec/liveness/action.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/spec/liveness/action.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 7c368e85c448bc7a997ebcb3510b694bb3406557packageMentionDocs.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tooling labels Aug 26, 2026
@huangyiirene
huangyiirene marked this pull request as ready for review August 26, 2026 08:15
@huangyiirene
huangyiirene added this pull request to the merge queueAug 26, 2026
Merged via the queue into main with commit 33c5fd3Aug 26, 2026
35 checks passed
@huangyiirene
huangyiirene deleted the claude/issue-12215-action-liveness-anchors branch August 26, 2026 08:36
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/stooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] liveness action.json cites http-dispatcher.ts for type/body/method — likely stale after the actions-domain extraction

2 participants

@huangyiirene@claude