Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion packages/spec/liveness/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -58,7 +58,7 @@ registry to fold it back onto — the override *is* its governance.

| Status | Meaning |
|---|---|
| `live` | Has a runtime consumer. Cite it in `evidence` as `file:line`; for another repo's path, prefix the realm — `objectui: packages/app-shell/…` (see below). |
| `live` | Has a runtime consumer. Cite it in `evidence`, preferably anchored to the consuming symbol — `file#symbol` — with `file:line` as an optional convenience; for another repo's path, prefix the realm — `objectui: packages/app-shell/…` (see below). |
| `experimental` / `planned` | Declared, intentionally not enforced yet. Also read from a spec `.describe()` marker like `[EXPERIMENTAL — not enforced]`. |
| `dead` | Parsed, no consumer. Tracked for **enforce-or-remove** (ADR-0049). |

Expand All@@ -74,6 +74,23 @@ checkout. Prose around the paths is fine and encouraged — `packages/spec/src/s
(mergeActionsIntoObjects stable-sorts each group)` resolves the path and ignores
the parenthetical.

**Anchor the consuming symbol, not (only) a line** (#12516). A citation may be
written `packages/…/file.ts#dispatchFlowAction` — the proof-ref `#` convention
applied to the citation grammar — and the gate then verifies the symbol is
still in the cited file (`✗`, exit 1 when it is not; a malformed anchor — not
one identifier — also fails, the `verifiedAt` bad-date asymmetry one field
over). Prefer this form. A **line number rots in range**: the file exists, the
line is inside it, the file names the key, and the consumer has simply moved to
a different line of the same file — every check passes and the pointer is
wrong. Measured: the two `action.json` entries repointed with fresh line
numbers on 2026-08-25 had both drifted that way by 2026-08-26, because their
1670-line file is actively edited — the more precisely a line is cited, the
faster it rots. A symbol moves *with* the consumer, so the anchor survives
exactly that movement, and when the consumer is renamed or deleted the gate
goes red — a direction a stale line can never produce. A line may still ride
along (`file.ts#symbol:150`, either order): it stays a human convenience,
bounded by the past-EOF check, and the symbol is the load-bearing half.

**A repo-local path that does not resolve FAILS CI** (`✗`, exit 1 — since #5623;
it was a non-failing `⚠` before, calibrated for the parser bug described in the
note below rather than for the parser we have). A `live` verdict *is* its
Expand Down
12 changes: 6 additions & 6 deletions packages/spec/liveness/action.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,9 @@
},
"target": {
"status": "live",
"verifiedAt": "2026-08-25",
"evidence": "packages/runtime/src/action-execution.ts:725 (type:'flow' server dispatch — automation.execute(action.target, …), with :718 rejecting an unknown flow name by that same value); packages/runtime/src/action-execution.ts:472 (headlessActionTypeError names the target the client-dispatched types go to instead)",
"note": "URL/script/flow/endpoint + ${param}/${ctx} interpolation. 2026-08-25: REPOINTED — the evidence cited packages/runtime/src/http-dispatcher.ts, which has 0 occurrences of `target`; the action consumer was extracted into domains/actions.ts + action-execution.ts and http-dispatcher.ts now only delegates (handleActions → handleActionsRequest at :1969-1970). The file still existed and the citation carried no line, so nothing in the gate could see it."
"verifiedAt": "2026-08-28",
"evidence": "packages/runtime/src/action-execution.ts#dispatchFlowAction (type:'flow' server dispatch — automation.execute(action.target, …) runs inside it, after flowIsUnknown rejects an unrecognized flow name by that same value); packages/runtime/src/action-execution.ts#headlessActionTypeError (names the target the client-dispatched types go to instead)",
"note": "URL/script/flow/endpoint + ${param}/${ctx} interpolation. 2026-08-25: REPOINTED — the evidence cited packages/runtime/src/http-dispatcher.ts, which has 0 occurrences of `target`; the action consumer was extracted into domains/actions.ts + action-execution.ts and http-dispatcher.ts now only delegates. The file still existed and the citation carried no line, so nothing in the gate could see it. 2026-08-28: RE-ANCHORED (#12516) — the 08-25 repoint wrote line numbers (:725/:718/:472) and all three drifted IN RANGE within a day (the lines now hold the FlowActionRefusal brand block and disabledActionRefusal's docblock); the citation now anchors the consuming symbols, which move with the consumer."
},
"body": {
"status": "live",
Expand DownExpand Up@@ -109,9 +109,9 @@
},
"requiredPermissions": {
"status": "live",
"verifiedAt": "2026-08-25",
"evidence": "packages/runtime/src/domains/actions.ts:172-180 (ADR-0066 D4 dual-surface gate — resolves the action's declared requiredPermissions and rejects 403 when the caller's systemPermissions don't cover them); packages/runtime/src/action-execution.ts (resolveRouteActionDeclaration supplies the declaration the gate reads)",
"note": "ADR-0066 D4 dual-surface action gate. Server is source of truth: handleActionsRequest rejects (403) when the caller's systemPermissions don't cover action.requiredPermissions; objectui ActionRunner derives the same UI hide/disable. Unit-proven in packages/runtime/src/http-dispatcher.test.ts + packages/spec/src/ui/action.test.ts (both re-measured 2026-08-25 and still naming the key). 2026-08-25: REPOINTED — the evidence cited packages/runtime/src/http-dispatcher.ts, which has 0 occurrences of `requiredPermissions` since the actions domain was extracted into domains/actions.ts. Note the split the repoint exposes: the TEST kept the name while the source lost it, so the note's pointer stayed true while the evidence pointer rotted."
"verifiedAt": "2026-08-28",
"evidence": "packages/runtime/src/action-execution.ts#actionPermissionError (ADR-0066 D4 dual-surface gate — reads actionDef.requiredPermissions and returns the 403 message when the caller's systemPermissions don't cover them); packages/runtime/src/domains/actions.ts#handleActionsRequest (the /actions route's D4 call site — rejects 403 via that gate); packages/runtime/src/action-execution.ts#resolveRouteActionDeclaration (supplies the declaration the gate reads)",
"note": "ADR-0066 D4 dual-surface action gate. Server is source of truth: handleActionsRequest rejects (403) when the caller's systemPermissions don't cover action.requiredPermissions; objectui ActionRunner derives the same UI hide/disable. Unit-proven in packages/runtime/src/http-dispatcher.test.ts + packages/spec/src/ui/action.test.ts (both re-measured 2026-08-25 and still naming the key). 2026-08-25: REPOINTED — the evidence cited packages/runtime/src/http-dispatcher.ts, which has 0 occurrences of `requiredPermissions` since the actions domain was extracted into domains/actions.ts. Note the split the repoint exposes: the TEST kept the name while the source lost it, so the note's pointer stayed true while the evidence pointer rotted. 2026-08-28: RE-ANCHORED (#12516) — the 08-25 repoint wrote :172-180 and it drifted IN RANGE within a day (those lines now hold path-part parsing and the invalidBody constructor; the actual key read lives in actionPermissionError, single-sourced in action-execution.ts and called from handleActionsRequest). Symbol anchors move with the consumer."
},
"disabled": {
"status": "live",
Expand Down
Loading
Loading