Skip to content

chore(spec): re-anchor the action + object liveness ledgers to consuming symbols - #13035

Merged
os-trump merged 1 commit into
mainfrom
claude/issue-13003-anchor-adoption
Aug 28, 2026
Merged

chore(spec): re-anchor the action + object liveness ledgers to consuming symbols#13035
os-trump merged 1 commit into
mainfrom
claude/issue-13003-anchor-adoption

Conversation

@os-trump

Copy link
Copy Markdown
Collaborator

Part of #13003

Adoption batch 1 of the symbol-anchor citation grammar that #12516 / PR #13004 landed. Two ledger files, chosen by the card's own order: action.json (the hot file — the only ledger citing packages/runtime/src/action-execution.ts, 1670 lines, and the file whose two entries drifted in a day) and object.json (the oldest dated batch, verifiedAt back to 2026-07-28).

Every citation below was re-closed by reading the code on the current tree. No line number was shifted by a diff, and no existing citation was trusted. That mattered more than expected: 14 of the 15 object.json citations were already pointing at the wrong place, every one of them IN RANGE and therefore invisible to all three existing checks.

Per-entry table

= citation was already wrong and is repointed · = = citation was accurate, grammar migration only · = consumer gone, reported not executed

packages/spec/liveness/action.json

EntryFROMTORe-closure found
typebody-runner.ts:385body-runner.ts#actionBodyRunnerFactory= line still accurate (repointed 08-26)
typeaction-execution.ts:1309action-execution.ts#invokeBusinessAction= accurate
typedomains/actions.ts:591domains/actions.ts#handleActionsRequest= accurate
typebare :524:552:906#isHeadlessInvokableAction, #headlessActionTypeError, #summarizeActionnot citations at all — see below
bodybody-runner.ts:356body-runner.ts#actionBodyRunnerFactory= accurate
bodyaction-execution.ts:525action-execution.ts#isHeadlessInvokableAction= accurate
executeaction.zod.ts:581(untouched)consumer gone — reported on #13003, not executed here

The type entry carried a second, quieter defect the migration repaired: :524, :552 and :906 were written as bare line suffixes with no path in front of them. PATH_RE needs a repo-rooted token, so the evidence scanner never parsed them as citations — three of that entry's six consumers were unfalsifiable prose that no check has ever resolved. They are anchors of their own now.

packages/spec/liveness/object.json

EntryFROMTORe-closure found
datasourceengine.ts:1147#resolveDatasourceBinding, #assertWriteAllowed :1147 is a docblock about write-refusal placement (13593-line file)
indexessql-driver.ts:1181#syncTableIndexes, #syncDeclaredIndexes, #initObjects :1181 is a docblock on count_distinct lowering (16289-line file)
validationsrule-validator.ts:154#evaluateValidationRules, #legalNextStates, #needsPriorRecord :154 is a requiredWhen docblock
actionsapp-plugin.ts:929#collectBundleActions :929 is the job scheduling block
managedByregistry.ts:208spec #resolveCrudAffordances, #resolveInjectedSystemColumns; #assertEngineOwnedWriteAllowed; #collectMaskedReadFields :208 is the sibling indexes merge; readers moved package
ownershipregistry.ts:292spec #resolveInjectedSystemColumns (+ #applySystemFields as materializer) :292 is a multiTenant docblock — and the parenthetical was false, see below
requiredPermissionssecurity-plugin.ts:132#getObjectSecurityMeta, #normalizeRequiredPermissions, #requiredCapsForOperation, #crudBucketForOperation :132 is a platform-admin docblock; real read ~6400 lines later
systemFieldssecurity-plugin.ts:3281 (+ lineless registry.ts)spec #resolveInjectedSystemColumns, #applySystemFields, #getObjectSecurityMeta, #loadObjectFieldNames :3281 is a bootstrap catalogSeedPasses() call
sharingModelsharing-service.ts:54#effectiveSharingModel :54 is a blank line
publicSharingshare-link-service.ts:48 (+ :170)#getPolicy, #createLinkboth lines rotted
tenancy.enabledsql-driver.ts:1081spec #isTenancyDisabled, #computeTenantField, #getObjectSecurityMeta, #resolveInjectedSystemColumns :1081 is a withheld-filter docblock; predicate moved to spec
tenancy.organizationFieldrecord-organization.ts:177-180#resolveRecordOrganizationField=the one accurate citation — 248-line file
enable.searchableprotocol.ts:2967#searchAll :2967 is inside normalizeSortNodes, ~7100 lines off
enable.cloneprotocol.ts:2938#cloneData :2938 is normalizeSortNodes; reader at ~:9648 — a 6700-line in-range drift
isSystemsharing-service.ts:75#effectiveSharingModel :75 is a neighbouring const OWNER_FIELD

Three observations the batch is worth recording for:

  • The one accurate citation lives in the batch's smallest file (248 lines). The fourteen rotted ones are in files of 700 to 20255 lines. That is the [finding] A liveness citation can rot IN RANGE: action.target and action.requiredPermissions point at the wrong lines one day after being repointed, and every check stays green #12516 thesis measured a second time, on a different population.
  • object.ownership was falsified in prose, not just in line. Its citation read registry.ts:292 (applySystemFields reads schema.ownership). applySystemFields reads ownershipnowhere in code — its nine occurrences in that function are all comments explaining a decision it delegates to resolveInjectedSystemColumns in @objectstack/spec. The entry stays live on stronger evidence; what it demonstrates is a line refreshed on 2026-07-30 rotting again inside the same file while the prose beside it already pointed at a reader that had changed packages.
  • object.enable.clone has now been repaired twice — once in 2026-07 for a cross-package move the existence check could see, and once here for a 6700-line in-file move that nothing in the gate could. It is the worked example of why the anchor exists.

action.execute — consumer GONE, reported not executed

Per the dispatch, a gone consumer is a re-classification under ADR-0049 and is reported on the card, not executed here. The entry is left byte-for-byte untouched.

The evidence claims action.zod.ts:581 — the .transform lowers execute -> target and DROPS the alias. On the current tree there is no such transform: execute was removed in protocol 17 (#3855) and is a retiredKey(...) tombstone at action.zod.ts:1040, so authoring it is a tsc error and a parse error. packages/cli/src/utils/lower-callables.ts explicitly refuses to consume it. Meanwhile :581 is in range and lands on a comment about the global_nav enum-value retirement's declaration style.

The honest verdict is dead, matching its already-tombstoned siblings shortcut and bulkEnabled in the same file. That is a status change with its own card shape.

Census position

Measured by the gate's own counters, base c459da6bc → head e243b3191:

line citations: 300 → 280 (20 retired)
symbol anchors: 5 → 47 (42 added)
evidence paths: 402 → 410 local, all resolving
key-mention: 410 pairs asked, 409 anchored, 1 exempt (unchanged)

20 of ~300 live-entry local line citations converted, across 2 of the 24 ledger files that carry any. The card's own census framing (117–173 of 298 failing key-proximity) is a different metric and is not re-measured here. Remaining ledger files by line-citation count, for the continuation rounds: manifest.json 34, datasource.json 28, permission.json 25, email_template.json 23, api.json 21, dataset.json 18, doc.json 15.

Evidence

All gates run at head e243b3191, exit codes captured before any pipe.

Gate family derived at that commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths passed — the script took its own change set from the merge base): 25 families matched. All green except two that returned an explicit PREREQUISITE NOT MET, which is no reading rather than a failure:

  • check:livenessEXIT=0"every path#symbol anchor names a symbol its file contains"
  • check:empty-state, check:strictness-ledger, check:variant-docs, check:published-files, check:changeset-gate-self-tests, check:objectui-changeset, check:merge-driver, check:pm-half-states, check:page-declaration-shape, check:slot-lookup, check:test-source-alias, check:type-source-resolution, check:nul-bytes — all EXIT=0
  • check-adr-0087-registration, check-changeset-no-major, check-empty-changeset, check-keyed-text-bounds, check-comment-mask-adoption, check-plugin-teardown-shape, check-undeclared-dep-imports, release-rehearsal-clone --self-test — all EXIT=0
  • check-dev-prereqs.mjsEXIT=1NOT MEASURED: "The workspace is not built — 1 unmet precondition, not a list of problems". Repo-scale pnpm build; this diff contains no TypeScript.
  • scripts/pm/check-half-states.mjsEXIT=3NOT MEASURED: "PREREQUISITE NOT MET — the token in the environment is not a valid GitHub credential … Nothing was swept … It is not a clean board and it is not a dirty one — it is no reading at all."

Vitest, through the shared verify lock, at head e243b3191:

pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/liveness/
Test Files 10 passed (10)
Tests 254 passed (254)

That includes the --ledger-root self-test machinery PR #13004 committed.

Ablation — the new anchors are genuinely checked

Gate green alone would not prove it: an anchor token that stops matching PATH_RE degrades to prose silently, taking the citation's existence check with it. So one anchor was mutated to a symbol the cited file does not contain. Committed first, mutation confirmed on disk by grep counts in both directions, restore proven by an empty git diff HEAD (not by an exit code), absolute paths under an EXIT INT TERM trap. No build leg: the gate runs from source through tsx and reads the JSON directly, so no dist/ sits between the mutation and the reading.

anchor occurrences BEFORE mutation: 1
original anchor AFTER mutation: 0 (expect 0)
injected anchor AFTER mutation: 1 (expect >=1)
MUTATION CONFIRMED ON DISK
MUTATED gate EXIT=1
symbol anchors: 47 pointer(s), 46 naming a symbol the cited file contains, 1 UNRESOLVED.
object/tenancy.organizationField → …/record-organization.ts#thisSymbolDoesNotExistAnywhere
RESTORE CONFIRMED: git diff HEAD empty for target
RESTORED gate EXIT=0
symbol anchors: 47 pointer(s) written `path#symbol`, 47 naming a symbol the cited file contains.

The direction was predicted before running: red, naming the entry. It also independently confirms the 42 new anchors parse as anchors rather than as prose — the mutated run still reported 47 pointers, so the count is real.

Contract gate

None applies. The writing surface is packages/spec/liveness/*.json only — governance data, outside the packages/spec/src/** path leg. No accept set moves, no schema key changes, no runtime behaviour changes. Clause-② is not reachable.

Changeset

One is included, patch on @objectstack/spec, and the dispatch's expectation ("no changeset expected") is corrected by measurement rather than assumed: liveness is named in that package's files array (packages/spec/package.json), so these ledgers ship inside the npm tarball and this is a published-data change. skip-changeset does not apply — the diff is not confined to the convention's closed list.

Honest residual

isSymbolNamed checks only that the cited file contains the identifier as a word; it cannot check that the symbol is the one enclosing the read. Gate-green therefore does not prove the re-closures are correct — the hand reads do, and the per-entry table above is the record of them. One anchor in this batch was caught wrong by exactly that limit during authoring (secret-fields.ts#redactSecretFields, a symbol that does not exist; the real ones are collectMaskedReadFields / collectMaskedPasswordFields) and was corrected before commit.


Generated by Claude Code

…g symbols
Adoption batch 1 of the #12516 symbol-anchor citation grammar (#13003).
Twenty `path:NNN` evidence citations in liveness/action.json and
liveness/object.json become `path#symbol`, each re-closed by reading the
code on the current tree rather than by shifting a line.
Fourteen of the fifteen object.json citations were already wrong — all of
them IN RANGE, so the existence check, the line bound and the key-mention
check all passed on pointers that named a docblock, a neighbouring const,
or (object.enable.clone) a sort normalizer ~6,700 lines from its reader.
Three readers had moved package into @objectstack/spec.
action.execute is NOT touched here: its cited `.transform` lowering was
removed in protocol 17 and the key is now a retiredKey tombstone, so the
`live` verdict is falsified. That is a re-classification under ADR-0049
and is reported on #13003 rather than executed in this PR.
Part of #13003
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️2 changed file(s) yielded no anchor (packages/spec/liveness/action.json, packages/spec/liveness/object.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
  • 2 changed file(s) yielded no anchor (packages/spec/liveness/action.json, packages/spec/liveness/object.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 c459da6bc3fc9a2641019b6a06f495109e9ee911packageMentionDocs.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tooling labels Aug 28, 2026
@os-trump
os-trump marked this pull request as ready for review August 28, 2026 20:28
@os-trump
os-trump enabled auto-merge August 28, 2026 20:28
@os-trump
os-trump added this pull request to the merge queueAug 28, 2026
Merged via the queue into main with commit 93ea19bAug 28, 2026
35 checks passed
@os-trump
os-trump deleted the claude/issue-13003-anchor-adoption branch August 28, 2026 20:54
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mtooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-trump@claude