Uh oh!
There was an error while loading. Please reload this page.
chore(spec): re-classify the action.execute liveness entry dead (#13036) - #13045
Merged
Conversation
The entry was ledgered `live` on a `.transform` that lowers `execute` -> `target` and drops the alias. No such transform exists: action.zod.ts has exactly two `.transform` calls and both are `lowerRequiresFeature`. The alias and its lowering were removed together in protocol 17 (#3855); the key is a `retiredKey` tombstone with no consumer on any layer. Status flips to `dead` with the ROW STAYING - the rls.priority precedent, a tombstone keeps the key in the walked shape - matching the two already-dead siblings in the same ledger. The falsified `evidence` goes, the #3713 three-readers history is preserved in the note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
Contributor
📓 Docs Drift Check
What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
os-trump
marked this pull request as ready for review
August 29, 2026 01:14
os-trump
enabled auto-merge
August 29, 2026 01:14
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#13036
The
action.executeliveness entry was ledgeredliveon a.transformthat protocol 17 removed. This flips the verdict todeadwith the row STAYING, re-points the pointer at the tombstone, preserves the #3713 history the card asked to keep, and stampsverifiedAt. Data only — no schema, no runtime, no authoring surface moves: authoringexecutealready failedtscand the parse before this change, and still does.Premise, re-measured on the base
8cb96ec41The card's claim holds in every particular.
.transformlowers execute → target and DROPS the alias"packages/spec/src/ui/action.zod.tshas exactly two.transformcalls,:526and:1668, and both arelowerRequiresFeature. No transform touches the key.liveaction.zod.ts:1040declaresexecute: retiredKey('...was removed in @objectstack/spec 17 — usetarget...'), and its docblock reads[REMOVED in protocol 17 — #3855] The deprecated alias of target. It types the keynever.packages/cli/src/utils/lower-callables.ts#lowerActionCallabledeclines on purpose: "Only a callabletargetis lowered. A function on the removedexecutealias is deliberately left in place so the parse rejects it by name."packages/runtime/src/action-execution.ts:525gates onaction?.target || action?.body.The tombstone landed 2026-07-28 in
acbf364a0, "feat(spec)!: retire the last three deprecated authorable aliases (#3855)" (PR #3883) — dated from git, not recalled.:581is in range in an 1802-line file that names the key, which is why existence, line bound and key-mention were all green on it. What:581holds today is a comment about theglobal_navenum-VALUE retirement's declaration style.The disposition, and the precedent it follows
.claude/skills/spec-property-retirement/SKILL.md§2 splits the ledger discipline by removal route, and the two directions fail in opposite ways: deleting a tombstone key's row reports UNCLASSIFIED; keeping a strict-removed key's row reports ORPHAN.executeis theretiredKey()route —retiredKeyisz.never().optional(), still a property in the walked shape — so the row stays and the verdict changes. That is therls.priorityprecedent both same-file siblings already cite.Before
After —
status,verifiedAt,note, and noevidencekey.Why no
evidencekey: the sibling style, measured rather than assumedThe dispatch asked me to re-point the evidence "in the sibling rows' style (read how
shortcut/bulkEnabledcite theirs and match it)". Read, and they carry noevidencefield at all — the tombstone pointer lives in thenoteprose. That is the house style, not a two-row accident: across all 33deadentries in the 31 ledgers, 30 carry noevidence, and the 3 that do carry bare prose ("no reader either layer"), never a path citation.It is also the correct shape for a second reason the counters below make checkable: the walk reads
evidenceonly whenstatus === 'live'(check-liveness.mts:588). Anevidencepointer on adeadrow is scanned by nothing — no existence check, no line bound, no anchor resolution, no key-mention. Writing apath#symbolanchor there would have planted a citation that no gate can ever falsify, which is the exact failure class this card is about. So the pointer is written in thenote, inpath#symbolgrammar, beside prose that says what it is:packages/spec/src/ui/action.zod.ts#execute— the tombstonepackages/cli/src/utils/lower-callables.ts#lowerActionCallable— the deliberate refusalBoth resolve as identifier-bounded words in their files (5 and 3 occurrences). This is a declared deviation from the dispatch's literal wording, resolved in favour of its own instruction to read the siblings and match them. Flagged here rather than chosen quietly.
The #3713 history is preserved verbatim in substance — three readers disagreeing in two directions, the parse keeping
target, objectuiActionRunnerdoingexecute || target, the CLI preferring a function onexecute— because, as the card says, it is the argument fortargetbeing the single handler slot.The counter: what moved, and what the number actually reads
The dispatch predicted
2 → 1. The observable reading is82 → 81, and the reason is benign: PR #13044 (batch 4, the run that takes the counter to 2) has NOT landed. It is still a draft,mergeable_state: blocked;origin/mainis8cb96ec41, re-fetched at the start of this run and again before pushing. The2 → 1arithmetic is the post-batch-4 statement of the same one-citation movement, not a second fact.Quoted from the gate itself, exit code captured by redirect-then-read before any pipe:
The one that left is proven by identity, not by subtraction — the gate's own
scanEvidencerun over both revisions of this entry:That singleton is exactly the
action.jsonentry PR #13044 lists as HELD. With batch 4 landed, the remaining line citation isfield/conditionalRequiredand the counter reads 1 — which is #13043's to retire, not this branch's.The same probe measures the "notes are not scanned" claim instead of asserting it. The new note contains 2 line-shaped pointers and 2 anchor-shaped pointers; if the walk read notes, the counters would have gone up:
Observed: citations
82 → 81, symbol anchors383 → 383(unchanged). The walk readsevidenceandproduceronly, measured.The other counters move consistently, all from this one entry leaving the
livepopulation: evidence paths464 → 463, key-mention pairs asked464 → 463/ anchored463 → 462/ exempt1 → 1. No baseline row is orphaned:key-mention.baseline.jsonholds one exemption,email_template/fromOverride, untouched.The floor files are untouched, by design
packages/spec/scripts/has zero diff against the merge base — verified as a command, not as an intention:Both floors sit at
toBeGreaterThan(0)per ruling comment 5458356183, and both guard comments instruct that the assertion is deleted in the same PR that retires the last line citation. At 81 — and at 1 after batch 4 — the population is not zero, so the floors stay and this branch does not touch them. Their suite is green at this head:pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/liveness/→ 10 test files, 254 tests passed,VERDICT command-exit 0from the shared verify lock.This body deliberately carries no closing keyword for the #13003 worklist; that card stays open, and machine-scanning for one is part of the checklist below.
File surface: 4 files, and why it is not 2
The claim declared
action.jsonplus a changeset. Two more files came along, both as consequences of the flip rather than as scope:packages/spec/liveness/state-counts.md— a generated artifact the gate demands.check:livenesswentEXIT=1on the edit alone: "packages/spec/liveness/state-counts.md is STALE ... The count columns are GENERATED (spec(liveness): 9 rows of the README state table have count columns that disagree with the gate's--jsonreport #7377). Regenerate them, wholesale:pnpm --filter @objectstack/spec gen:liveness-counts". Regenerated with that command, never by hand. The whole diff is the movement predicted:actionrow42 0 2 2 46→41 0 3 2 46, total821 → 820live and78 → 79dead. One property changed verdict; none entered or left the walked shape.packages/spec/liveness/README.md— a sentence this change makes false. The same gate output orders the re-read: "A count that moved means a property entered or left the walked shape, or a ledger verdict changed — and the Notes cell beside that row in README.md may now describe a set it no longer has." It did. Theactionnotes cell endedshortcut + bulkEnabled ... and they are still the whole dead set— true until this commit, false after it. That is the spec(liveness): 9 rows of the README state table have count columns that disagree with the gate's--jsonreport #7377 shape the guidance names in its own next sentence. Corrected to record the third member and why the row stays. A second, smaller touch: the 2026-07 [P2] AI scope keys declared but unenforced: skill.permissions + agent.knowledge (enforce-or-prune) #3686 tally listsaction.executeunder "live, evidence corrected to the real reader"; that tally is a dated historical record and stays as written, with a footnote marker noting the key did not survive — the same treatment the file already givesskill.permissionsone line below.Nothing else: no other ledger
.json, nopackages/spec/src/**, nocheck-liveness.mts, no test file, no ADR-0087 registry (the conversionaction-execute-to-targetand its migration row have been in place since protocol 17 — this is a ledger correction, not a retirement)..changeset/action-execute-ledger-dead.mdis apatchon@objectstack/spec:liveness/is named in that package'sfilesarray, so these ledgers ship in the npm tarball and this is published data.Gates
Family derived at the committed head,
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, no paths passed — 4 paths vs merge base8cb96ec41, 25 families matched, no convention trigger fired (this diff adds and edits no test file, no gate script, no root-program TypeScript, no error code, and touches noskills/**). Exit codes captured by redirect-then-read, before any pipe.23 green:
check:changeset-gate-self-tests·@objectstack/spec check:empty-state·@objectstack/spec check:liveness·check:merge-driver·check:objectui-changeset·check:page-declaration-shape·check:pm-half-states·check:published-files·check:slot-lookup·@objectstack/spec check:strictness-ledger·check:test-source-alias·check:type-source-resolution·@objectstack/spec check:variant-docs·check-adr-0087-registration.mjs·check-changeset-no-major.mjs·check-comment-mask-adoption.mjs·check-empty-changeset.mjs·check-keyed-text-bounds.mjs·check-plugin-teardown-shape.mjs·check-undeclared-dep-imports.mjs·docs-audit/check-affected-docs.mjs·docs-audit/check-drift-comment.mjs·pm/release-rehearsal-clone.mjs --self-test. Pluspnpm check:nul-byteson top of the derivation.check:livenessverdict line at head:check:nul-bytesverdict line:2 NOT MEASURED, neither of them a red gate:
node scripts/check-dev-prereqs.mjs,EXIT=1— a container prerequisite on an unbuilt worktree, and it says so: "Fix:pnpm build". Deliberately not converted into a reading here: this diff contains zero TypeScript, so a 70-package build would spend the fleet's scarcest resource (the shared verify lock, ~6m30s when a sibling ran it 30 minutes ago) measuring the container rather than this change. A declared narrowing, not an omission.node scripts/pm/check-half-states.mjs,EXIT=3—PREREQUISITE NOT MET, no GitHub credential in this container. The gate's own words: "It is not a clean board and it is not a dirty one — it is no reading at all." Standing across this seat's whole run.No typecheck leg is owed: the diff is one JSON ledger, one generated Markdown table, one Markdown README and one changeset. No ablation is owed either, and the reason is measured rather than claimed — a status flip adds no new anchor to any scanned field, and the probe above shows the two
path#symbolspellings in the note sit outside the scanned population entirely, so there is no anchor mechanism whose failure could be demonstrated.All gates above ran at
cc4c52948withgit diff HEADempty andgit status --porcelainsilent, so the tree measured is the tree committed and pushed.Checklist
Fixes #13036; scanned for a closing keyword on any other card number — none, and [worklist] Migrate liveness line citations to symbol anchors — census: 117-173 of 298 live line-cited pairs fail key-proximity at line granularity today #13003 appears only in prose.state-counts.mdregenerated wholesale, never hand-edited.Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
Generated by Claude Code