Skip to content

docs(objectql): re-anchor the dead tracker citations to the commits and ADRs that decided them (stage 3 of #20595) - #21268

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20595-objectql-citations
Oct 2, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20595-objectql-citations

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #20595
Clause-②: no

What changed

Stage 3 of the domain:engine lane of the dead-citation sweep: packages/objectql/**, comment and docblock prose only, per the claim (5941871762). Stages 1 and 2 (packages/metadata-protocol) landed as a7d9768ec and d150c3039; #20595 stays open for the next stage (driver-sql).

Every comment or docblock site in the package that cited a tracker number answering 404 is rewritten in ruling C+D's form C (record 5749154545 on #19123): the ADR when one records the decision, otherwise the commit in this repository's history that made it. That is 279 sites on 275 lines in 67 files, covering 70 numbers:

  • 136 census sites (136 lines, 17 files under src/): the whole allocated-but-absent population of the gate's own census in this package at the base, the slash-joined plugin.ts #10629 from the post-landing census (5923084795, now at :1543) included;
  • 1 site in vitest.config.ts (:61, #17853): outside the census glob, inside the claimed surface;
  • 142 test-comment sites (138 lines, 49 test files), which the census defers. They carry 51 numbers: the census itself reads 36 of them as dead elsewhere in the repository, and never judges the other 15 (they stand only in test files here), which the board and a single read each settle.

Anchors: 66 numbers by commit, 4 by ADR, 0 by words alone. 45 numbers reuse the anchor another lane or stage already measured for them, 23 were measured here, and 2 are split between a reused and a measured commit (see the table). Two depart from another lane's anchor for a stated reason (#10629, #10243, under Wordings to check).

Only comments changed. Every file keeps its line count (275 lines out, 275 in, plus the changeset), so no line citation into any of them moves. No code token moves (the guard below). No citation number is added: on every changed line, the numbers on the new text are a subset of those on the old, and the diff-scoped gate judged the 14 citations left on changed lines: 13 resolve and 1 is a declared cross-repo reference.

A patch changeset: 54 of the 137 rewritten non-test lines are in the published dist (the .d.ts keeps JSDoc on exported members, and esbuild keeps some comments in the JS), and dist is not byte-identical with the base text (see Changeset).

Census: objectql, before and after

Instrument (A1). The gate's own node scripts/check-issue-citations.mjs --census --json, read-only and unchanged. The count is its allocated-but-absent findings under packages/objectql/.

reading tree board whole-repo allocated-but-absent sites lines files numbers
before base 4727fcb22, run 22:38:04Z to 22:41:42Z enumerated, 191 pages, frontier #21252, 19,073 records (newest number read before and after the run: #21252) 592 136 136 17 50
after 8d6465457, run 23:19:32Z to 23:22:54Z enumerated, 191 pages, frontier #21261, 19,082 records (newest before and after: #21261) 456 0 0 0 0

The whole-repo drop is 136, and the two finding sets differ by exactly the 136 rows of this package, removed; none was added. resolves (34,638), resolves-as-pull-request (2,095) and cross-repo-unjudged (1,144) did not move. The card's 135 was taken at f11b5f20a2 with the older extractor; the base here reads 136, the difference being plugin.ts #10629. The same census at the first base d150c3039 (before a fast-forward to 4727fcb22, which touched no objectql file) read the identical 136 rows. The head's only later commit is a merge of main that touches no file under packages/objectql (git diff 8d6465457 1e0895870d -- packages/objectql is empty).

Supplementary instrument, the whole package. The census reads neither test files nor strings nor files outside src. A second reading runs the gate's own exported extractCitations (whole-file and comment-prose projections) and namesThisRepository over every tracked file in the package (430 .ts, 6 .json, 2 .md, LICENSE), and classifies each citation with the gate's classifyCitation against one board enumerated by the gate's enumerateBoard (191 pages, frontier #21252, 19,073 records, 22:43:50Z). Every one of the 70 numbers in the population was then read on its own over the issues endpoint: all 70 answer 404, and the lit controls #5286 and #12624 answer 200.

reading citations dead src comment test comment test string changelog
before, 4727fcb22 9,338 388 137 142 43 66
after, head 9,059 109 0 0 43 66

src comment includes vitest.config.ts. The drop of 279 citations is exactly the rewritten sites, and the live counts did not move (non-test comment: 2,971 resolve, 80 as pull requests; test comment: 2,700 and 122). A third, raw reading (every # followed by 2 to 6 digits, whatever surrounds it) counts 9,504 before and 9,225 after: the same drop of 279.

Comment ids. Six distinct comment-id citations stand on 11 lines in this package (5237739551, 5434929046, 5791803339, 5805782503, 5865053231, 5865693155). Each was read over the issue-comments endpoint and each answers 200 (control 5941871762, 200), so none is in the population.

Per-number table

src counts census sites (plus vitest.config.ts for #17853), test counts test-comment sites. Every sha below matches exactly one commit (git rev-parse --disambiguate, count 1) and is an ancestor of the base (git merge-base --is-ancestor, exit 0 for all 67 shas; the clone is not shallow, 15,432 commits at the base). The message or the diff of each one names the number it replaces, with one exception, #10629, explained under Wordings to check. Where a sentence credits a ruling, a measurement or a note to the number, the anchor's own message or diff carries it (checked per site; the ones that needed a reworded sentence are listed below). source says whether another lane or stage already used this anchor for this number (reused) or it was measured here (measured).

number src test anchor kind source what it decided
#6037 2 1 18189983d commit reused validate-only data operation — DataProtocol.validateData
#6083 3 2 53068c130 commit reused ADR-0122 phase 2 — flip bare names to parsed semantics
#6241 0 1 83a3b1f2e commit reused normalize the :type segment once per handler so the plural spelling cannot skip the §6.7 audience gate
#6300 5 4 74155c735 commit reused IDataEngine.find/findOne accept the author state — engine fills SortNode.order's declared default
#6311 0 1 59b794f71 commit measured narrow HookContext.api from z.unknown() to the minimal IScopedContext
#6478 0 1 474f131cf commit reused roll flow's allowOrgOverride back to false per ADR-0005's original call, the write path refusing loudly
#6483 0 9 ee58392e1 commit reused enforce the ADR-0005 whitelist: nine unratified allowOrgOverride: true flags rolled back to false (its message records the 2026-08-08 ruling)
#6573 5 6 708431313 commit measured registerHook refuses an empty object target and a self-cancelling scope
#6723 0 4 8ad609c69 commit reused declare what IMetadataService.getObject answers with
#6725 3 7 1507ba356 commit reused MetadataFacade object writes now reach the map its reads use
#6745 0 4 7a5ef0008 commit reused pin getObject(n) = get('object', n) across all three IMetadataService implementations
#8454 1 0 427344c26 commit measured the object catalog loses to an explicitly-set scalar
#8460 7 0 ADR-0029 D9.2a ADR reused ADR-0029 D9.2a, the 2026-08-13 amendment: an extender's scalar yields to a diverged base (it names the number; executed as 01a7337fc)
#8648 1 4 e5eeb499c commit reused pin the SEARCH-axis remedy agreement, and correct the three comments that claimed word-identity
#8672 6 4 ff08691e6 commit measured a system-context insert resolves the install's organization, or is refused — the runtime producer of the autonumber fork
#8818 0 1 fd6bdf89f commit reused saveMetaItem's missing-item refusal declares 400 INVALID_REQUEST instead of answering 500
#8823 10 4 4dfa369a9 commit measured drop the caller value MySQL inlines in its duplicate-entry diagnostic
#9030 2 1 27a567dd8 commit measured teach the internal-leak predicate MySQL's three error templates
#10062 2 0 fa5d137ab commit reused gate undeclared workspace imports in published src
#10091 1 0 da891e0ef commit reused gate sys_attachment beforeUpdate with the uploader-or-parent-editor rule
#10165 2 1 801296050 commit reused lifecycle ttl.onlyWhen row filter with the canonical null predicate
#10194 0 3 2306a765c commit reused validate theme / analytics_cube at the /meta write door via UNREGISTERED_KIND_SCHEMAS
#10243 1 1 ADR-0126 §7.2 ADR measured ADR-0126 §7.2: the durable ledger row replaces the process-local flowEnabled map, retiring the env-wide toggle leak's mechanism (it names the number)
#10290 4 1 2570ab05c commit measured the primary key is never a __search companion source
#10347 5 3 530c1df65 commit reused the Archiver honours a declared ttl instead of archiving by created_at age alone
#10485 0 2 35ad101bc commit reused retire the themes carrier key and ThemeSchema — app.branding is the one colour surface
#10527 1 0 5649efbf9 commit reused refuse a diverging retention + ttl + archive lifecycle triple at parse time
#10528 4 1 7d483e1e5 commit measured the Archiver resolves its window through P4 governance
#10629 1 2 199ec4712 commit measured bind federated objects whatever the boot order, and report what could not be bound
#10643 1 0 5649efbf9 commit measured refuse a diverging retention + ttl + archive lifecycle triple at parse time
#10729 1 1 10485009a commit measured log a contributed kind by its declared id
#11065 1 0 20950404c commit reused count a boolean aggregand as 1/0 in avg and sum
#11311 1 0 1272f0a6b commit reused promote resolveRecordOrganizationField to the shared platform-row resolver: approvals and automation runs stamp the subject record's organization
#11427 5 0 c3c72a4bc commit reused hydrate a tombstoned sys_file that still has a live holder
#11674 0 4 9a884c6e4 + 1cba33f16 commit reused seed pass 2 writes back by the internal id captured at insert time, healing keyless datasets / warn at load time when a seed defers a required column, and document the ordering constraint at the four pointer-pair sites
#12194 0 2 311433f6b commit reused Declare the metadata item-name grammar in spec and refuse it loudly at the publish door
#13178 2 1 f087c376f + e49d98896 commit reused+measured scope the sys_file / sys_upload_session update and delete doors to the acting organization / cut the tenant-audit control's scope by the object's tenancy, not the caller's flag
#13197 5 11 56c093c4d commit reused enforce field-level unique so a colliding write is refused, not landed
#13273 1 4 3a86a65e7 commit reused pick the find failure log level from the cause — "the table is not provisioned yet" is not "the read failed"
#13644 3 2 34ce8e7db commit reused declare ctx.referentialFieldClear on HookContextSchema, populate every set_null cleanup write, and carry it across the QuickJS sandbox boundary
#13657 4 4 b003cf2e8 commit reused Refuse an undeclared field a before-hook writes — the post-hook half of the declared-field door, one envelope on every driver
#14163 0 1 ADR-0130 D3 + 1dcb995f2 ADR measured ADR-0130 D3: the gate relaxation and the object-name uniqueness check are one change; 1dcb995f2 landed it, and its changeset names the number
#14345 0 1 e89fa9233 commit measured declare aggregate? on IDataDriver with the signature the engine calls
#14390 6 1 9d7f7259f commit reused update answers a driver unique violation with the DUPLICATE_RECORD envelope, on every driver
#14399 3 8 3c1bbd2a8 commit measured derive a view container's object through the shared helper, so the row's own name is LAST at every SOURCE registrar
#14422 0 1 dc7c226b9 commit reused give the standalone-action owner-key ladder one spelling
#14423 11 2 a56baa2bd commit reused the action audit reads the store key and asks the plane by name, and listNames gains loadMany fault parity
#14472 1 1 00ff228fe commit measured decide the insert-side runtime-owned strip by hook-write provenance
#14474 1 3 df657d9df commit reused carry an ADR-0112 envelope on the install-time namespace conflict refusal
#14484 1 0 3f64fe6c6 commit reused stamp organization_id on every sys_record_share write, backfill the stranded rows, admit the object to the tenancy ledger
#14535 0 1 1aba3159a commit measured declare the recorded-by fixture's lookup with the canonical reference key
#14666 1 6 d0ee598e6 commit measured refuse a view container whose name disagrees with its derived object key
#14667 0 1 dc7c226b9 commit reused give the standalone-action owner-key ladder one spelling
#14680 1 1 3bd9b3498 commit measured a leaf /view-container subpath keeps objectql's lean ADR-0076 closure free of the manager, chokidar, glob and js-yaml
#14683 0 4 96326040f commit reused apply the allowOrgOverride read gate inside getMetaItems, so multi-type sweeps are scoped per type
#14723 1 0 65846bc46 commit reused a batch/import ROW reports a unique-constraint refusal as UNIQUE_VIOLATION, the route's one wire spelling
#14770 0 6 d5cbb44f3 commit reused gate getMetaItem's overlay read on the metadata registry
#14878 0 2 29db3cd2a commit reused widen the deleted-member absence pin from one file to the tree
#14957 1 0 26144c204 commit measured Derive and gate the platform-object tenancy census
#15041 2 1 ADR-0104, 2026-09-05 addendum ADR reused ADR-0104's 2026-09-05 addendum: the media column holds the bare sys_file id; its execution order puts the driver card at step 2 (it names the number)
#15094 1 0 901773b21 commit measured check-react-page-adapter-contract names its class by shape, not by the records spelling, and re-anchors its citation
#16608 4 0 a016f08b8 commit reused evaluate the insert-side RLS check on the row that will be stored, after beforeInsert
#16711 1 0 7862fb711 commit measured object-definition parameters declare the keys they are read for, plus a gate that sees subclass overrides
#16729 1 0 0f38ab084 commit measured an explicit tenancy opt-out survives a partial syncSchema re-registration
#16783 1 1 854639b31 commit reused findOne, update and delete declare what they answer, and their hook seams are guarded
#16786 3 2 5c8f5af50 + 6059b29c0 commit measured+reused ObjectRepository declares the findOne / update shapes it already published / declare IScopedObjectRepository.updateById's answer — the record or null, not any
#16805 2 0 a016f08b8 commit reused evaluate the insert-side RLS check on the row that will be stored, after beforeInsert
#17195 1 0 d2c1d1980 commit reused beforeUpdate receives the persist image; the caller submission moves to ctx.submitted
#17219 3 2 706ad0fcc commit reused name the withheld read-only key when a hook faults reaching through it
#17853 1 0 08f5f0e5a commit reused make a vitest filter that selects no test file say so

Wordings to check

Most rewrites swap a tag in place ([#N] to [commit SHA], (#N) to (commit SHA), #N's X to commit SHA's X, PR #N to its squash commit), the form the landed stages use. These say more than the tag:

Sites left

  • In comments (src, test, vitest.config.ts): none.
  • String literals: 43 test-string sites, 25 numbers, 23 files (describe and it titles, assertion arguments): #14422 4, #13273 3, #13657 3, #17219 3, #11674 3, #6573 3, #14423 2, #10165 2, #14535 2, #10290 2, #8672 2, and 14 more once each. Every one of the 25 is in this stage's population, so the table above holds an anchor for each. Non-test strings carry none. Strings are outside this stage's surface.
  • Outside src: the release-owned CHANGELOG.md names dead numbers on 66 sites (44 numbers); left. test-typecheck-debt.json, tsconfig.test.json and tsconfig.scripts.json cite only live numbers.

Mechanical guard: no code token moves

The guard (stage 2's) compares, base 4727fcb22 against the working tree, over all 67 touched files, with TypeScript 6.0.3:

  • Reading 1: the parser's leaf nodes, from a forEachChild walk. Comments are trivia there, and JSDoc is never visited.
  • Reading 2: the full token stream in parser context, from a getChildren walk, JSDoc nodes skipped. String, template and numeric literals are compared in full on both readings.

Results:

  • Real run at the head: 298,707 base tokens, 0 files with a token change (exit 0).
  • Comment control (「The defaulting」 to 「The DEFAULTING」 on engine.ts:5): 0 files changed (exit 0).
  • Positive control, an identifier (ARCHIVE_BATCH_SIZE to ARCHIVE_BATCH_SIZEX, lifecycle-service.ts): DIFFER on both readings (exit 1).
  • Positive control, a string literal ('[value redacted]' to '[value redactedX]', driver-fault-redaction.ts): DIFFER on both readings (exit 1).
  • Positive control, a numeric literal (ARCHIVE_MAX_BATCHES_PER_SWEEP = 20 to 21): DIFFER on both readings (exit 1).

Each mutation went through scripts/ablation-replace.mjs (wrap mode) under a shell trap that restores by absolute path from HEAD. Each landed (anchor 1 to 0, blob changed), and each restore was proven equal to its HEAD blob (71f6c9268aeb, 34b1dd7989b8, 9594cdd593c8), with git diff HEAD empty and a clean tree afterwards.

Changeset: patch (dist measured)

files[] is dist, README.md and CHANGELOG.md, and the package is not private. The dependency closure was built first (turbo run build --filter='@objectstack/objectql^...', 13 tasks). Then the package's own build (tsup plus check-dts-emitted) ran three times in one script under the shared verify lock (VERDICT command-exit 0):

  • Leg 1, at 9d6a0a8d6: 14 dist files hashed. Of the 137 rewritten non-test lines, 54 appear verbatim in dist: 25 from engine.ts, 7 from action-governance.ts, 5 from platform-object-tenancy.ts, and 17 from ten other files; in index.d.ts / index.d.mts, the shared util-*.d.ts chunk, and index.js / index.mjs / core.js / core.mjs.
  • Leg 2, the base text put back in the 18 non-test files (18 of 18 proven equal to their base blob): 10 of the 14 files differ from leg 1 (core and index in .d.ts, .d.mts, .js, .mjs, and the util-* chunk's two .d files).
  • Leg 3, after the proven restore (18 of 18 equal to their HEAD blob, git diff HEAD empty): all 14 files are byte-identical to leg 1, so the build is deterministic and the difference is the rewrite.

So the rewrite ships, and .changeset/20595-objectql-provenance-anchors.md declares a patch for @objectstack/objectql, comment text only, with the claim's Clause-②: no line.

Gates (head 1e0895870d)

  • Derived gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at 1e0895870d (68 paths against merge base 8dea55d31; no stale-tree warning) derived 68 commands. All 68 ran, each exit code captured before any pipe: 68 exit 0. --ran reports 「68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN」 (a derived zero) and exits 0. A full turbo run build over ./packages/* and ./packages/*/* ran first under the verify lock (71 of 71 tasks, VERDICT command-exit 0), so no gate read an unbuilt workspace.
  • Named in the dispatch: node scripts/check-issue-citations.mjs exits 0 (「every citation this change adds resolves (or is a declared cross-repo reference)」, 14 judged across 17 files); pnpm check:issue-citations exits 0 (self-test); pnpm check:doc-authoring exits 0 (the sibling-package prose-id baseline holds, no growth); pnpm check:nul-bytes exits 0, and a raw scan of the 68 changed files for control bytes finds none.
  • Tests and typecheck, under the verify lock, at 1e0895870d: pnpm --filter @objectstack/objectql test: 360 test files and 7,082 tests pass. pnpm --filter @objectstack/objectql typecheck exits 0; its check:test-typecheck step compiles all 361 tracked test files under tsconfig.test.json (tsc --listFiles), the ledger holding (40 files, 234 errors, 65 pinned signatures).
  • Lint, as a proven narrowing: eslint with inline config disabled, over the 67 touched .ts files plus dist/index.js as the control: 68 results, 0 errors and 1 warning, the control's ignore notice; none of the 67 is reported ignored. eslint.config.mjs never enables type-aware linting (its lines 327-328 say so), so a comment edit cannot move the verdict on an untouched file. The repo-wide pnpm lint is CI's run.

Acceptance notes


Generated by Claude Code

claude added 3 commits October 1, 2026 23:10
…he commits and ADRs that decided them

Comment and docblock prose only, in packages/objectql: every site citing a
tracker number that answers 404 now cites an object this repository
controls (ruling C+D, form C), an ADR where one records the decision,
otherwise the commit that made it. Each file keeps its line count; no code
token, string literal or live citation moves.

Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp
Co-authored-by: Claude <noreply@anthropic.com>
…ublished dist

The rewritten docblocks sit on exported members and land in index.d.ts,
core.d.ts and the shared type chunk, and esbuild keeps some of the comments
in the JavaScript output: a patch, comment text only.

Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Oct 2, 2026
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/objectql, touching 30 documentable anchor(s). ⚠️ 8 changed file(s) yielded no anchor (packages/objectql/src/action-activation.ts, packages/objectql/src/duplicate-record-error.ts, packages/objectql/src/find-hook-result-shape.ts, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

27 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 7923c8eca09258b52591039b1b12725e0e67445a.

⛔ 8 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 8 changed file(s) yielded no anchor (packages/objectql/src/action-activation.ts, packages/objectql/src/duplicate-record-error.ts, packages/objectql/src/find-hook-result-shape.ts, …) — pages documenting those are invisible to this run
  • 1 anchor(s) matched too much of the corpus to be a work list: ObjectQL (symbol, 70 pages)
  • 4 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • 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.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 17 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 7923c8eca09258b52591039b1b12725e0e67445a → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 8f2e0f9e602208f23f2bddbf44c65c368572fd97 — the merge of head 1e0895870dae7b969fe202f7039d2854bc351836 into base 7923c8eca09258b52591039b1b12725e0e67445a, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 8f2e0f9e602208f23f2bddbf44c65c368572fd97 && git checkout 8f2e0f9e602208f23f2bddbf44c65c368572fd97
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7923c8eca09258b52591039b1b12725e0e67445a 1e0895870dae7b969fe202f7039d2854bc351836 && git checkout -B drift-repro 7923c8eca09258b52591039b1b12725e0e67445a && git merge --no-ff 1e0895870dae7b969fe202f7039d2854bc351836

node scripts/docs-audit/affected-docs.mjs --json 7923c8eca09258b52591039b1b12725e0e67445a

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 7923c8eca09258b52591039b1b12725e0e67445a → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 1e0895870dae7b969fe202f7039d2854bc351836
Local-runs: none

Inputs read, and nothing else: card #20595 (body and all thirteen comments: the two lane pointers, the post-landing census 5923084795, the stage-1 and stage-2 claims, dev reports, ACCEPTs and landing records, the stage-3 claim 5941871762, the stage-3 os-dev-report 5943020843), the stage-1 contract review 5939794396 on #21233, ruling C+D (5749154545 on #19123), PR #21268 (body, the 68-file list, the commit list, the diff against its merge base), the anchors, ADRs and files at the head through git show, git log, git grep, git rev-parse, git merge-base, git diff and one in-memory git merge-tree in a full (not shallow) clone, the issues endpoint for every number the diff removes or keeps, and the head's check-runs last. The dispatch order and the seat's own conclusions were not inputs.

① Derived judgments

Diff of record. The merge base of the head with origin/main (ee42f00e39 at read), with the PR's base.sha 7923c8eca0 and with the merged 8dea55d31 is 8dea55d31 in all three cases. GitHub's diff for #21268 (68 files, +291/-275, 244 hunks) is byte-equal, index lines aside, to git diff 8dea55d31 1e0895870d; and git diff 4727fcb22 8d6465457 (the rewrite plus the changeset, before the merge) is byte-equal to that same net diff, so the merge commit 1e0895870d contributes nothing to it: the 33 files it brought from main include no file under packages/objectql. Three commits: 9d6a0a8d6 (the rewrite, on 4727fcb22) and 8d6465457 (the changeset) each end in the model-free trailer pair; the third is the merge. Head repo equals base repo (not a fork). Judged RIGHT.

Accept set and public surface: nothing moves. Judged RIGHT, on this reading of the diff text: every -/+ line was paired in order within its hunk, 275 pairs across the 67 .ts files, no hunk unpaired, the 16 unpaired + lines being the changeset. In all 275 pairs the first differing character lies after a // on that line (none inside a URL scheme) or on a line whose first non-blank is * or /*, and no pair has a */ before its change point; the new line is a comment at that point too. The 15 pairs whose quote-character counts move are apostrophes or backticks inside comment prose (for example action-activation.ts:185 the env-wide toggle leak's, protocol-meta.test.ts:181 where a backticked number becomes a plain commit d5cbb44f3, metadata-service-getobject-equivalence.test.ts:51 a reference list). Every .ts file keeps its line count: numstat additions equal deletions for all 67, and wc -l at 8dea55d31 and at the head agree for each. So no code token, string literal or numeric literal changes on this reading. The dev's parser-based guard (0 of 67 files on two readings, comment control at 0, identifier, string and numeric controls at DIFFER) is consistent with it; I did not re-run the guard.

Sampled hunks, 36 pairs across 25 files, each read as its -/+ pair. vitest.config.ts:61 (#17853 / #17978 to Commit 08f5f0e5a / #17978, the live number kept; 08f5f0e5a names #17853 in its message); plugin.ts:1543, skip-schema-sync-registers-object-metadata.test.ts:22 and :153 (the #10629 sites, below); action-activation.ts:185 and action-activation.test.ts:23 (the #10243 mechanism ADR-0126 retires to the env-wide toggle leak's mechanism ADR-0126 §7.2 retires); engine.ts:2433 (#6573 is why to commit 708431313 says why), :5450 (#13178 census measured to census cited in commit e49d98896's message measured), :7164 and :9860 (the ruling on #15041 step 2 to sequencing step 2 of ADR-0104's 2026-09-05 addendum), :13014 (review of PR #16805 measured to review commit a016f08b8 records measured), :18230 ([#16786] to [commit 5c8f5af50]), :18272 (stays open on #16786 to (its spec half: commit 6059b29c0)); registry.ts:2508 (every shape #8460 measured to every shape the ADR-0029 D9.2a amendment records); registry-ownership-refusal-envelope.test.ts:11 ((#14163) to (ADR-0130 D3, commit 1dcb995f2)); system-write-organization.test.ts:117 (the quoted (#8672) elided to (…), not re-spelled) and :347 (#8672 measured this primitive to The card commit ff08691e6 cites measured this primitive); find-hook-result-shape.ts:30; tenancy/platform-object-tenancy.ts:144 (#13178 (update) to commit f087c376f (update)), :190 (#14484 to Commit 3f64fe6c6, the line's own decision batch #11 item 3 kept) and :209; tenancy/system-write-organization.ts:72; tenancy-by-object-classification.test.ts:26; metadata-service-roundtrip-conformance.test.ts:41 (#3984/#5881/#6241 to #3984, #5881 and the third bypass, fixed in commit 83a3b1f2e) and :68; metadata-facade.test.ts:101 (PR #6723 to commit 8ad609c69, that pull request's squash); lifecycle/lifecycle-service.ts:1293 and :1294; core-boundary.ratchet.test.ts:52; protocol-meta.test.ts:100 and :169; hook-exclude-objects.test.ts:501 and :502; action-governance.ts:339 (the card's control site, pre-#14423 to before commit a56baa2bd) and :406; query-expression-conformance.test.ts:1070; in-memory-aggregation.ts:285; validation/rule-validator.ts:881; duplicate-record-error.ts:6, :39, :137; register-object-authored-shape.pin.ts:7; driver-fault-redaction.ts:47; search-companion.ts:97; engine-autonumber-resync.test.ts:53; engine-seed-required-deferral.test.ts:10 and :139; plugin-governance-scoped-metadata.test.ts:5; adr0104-file-columns-moved-supply.test.ts:5. Every one is a comment-only rewrite in ruling C's form: an ADR where one records the decision, else a commit sha, a PR number only beside a sha (PR #7211 beside 1507ba356). Judged RIGHT.

Anchors. All 67 shas in the per-number table (the 70 numbers less the three ADR-only rows, with 5649efbf9 serving #10527 and #10643, dc7c226b9 serving #14422 and #14667, a016f08b8 serving #16608 and #16805, and the two splits) resolve with git rev-parse --disambiguate to exactly one commit each, and git merge-base --is-ancestor exits 0 against both origin/main and the merge base 8dea55d31 for all 67. The + lines introduce exactly those 67 nine-hex spans and no other. For 69 of the 70 numbers the anchor's message or diff names the number it replaces: 43 in the message body and the diff, 15 in the diff alone (#6745, #8818, #11065, #11674 for 9a884c6e4, #14163, #14345, #14422, #14535, #14723, #14770, #14878, #15094, #16711, #16786 for 5c8f5af50, #17219), and 11 only in the subject's squash suffix (#6311, #6478, #6723, #8454, #9030, #10643, #11311, #14472, #14667, #16783, #17195), where the dead number was that pull request's own and the commit is its squash. The one exception is #10629, judged next. Judged RIGHT.

The #10629 exception, judged on the commits. 199ec4712 (2026-08-12) is #7737's fix: bind federated objects whatever the boot order; its message names #7737 (once, and 11 times in the diff) and never #10629, and it states the ruling the three sites paraphrase in its own words: a deployment running with OS_SKIP_SCHEMA_SYNC is a DDL flag while the federated binding is DDL-free, and ObjectQLPlugin now reconciles federated bindings on kernel:ready. 13a6cb4ad (2026-08-22), the only commit that carries #10629 as its own, withholds expected refused a read on log noise in 16 runtime fixtures, a different subject, so the runtime lane's anchor would be wrong here. a037f7cbd (2026-08-22), which wrote the #7737/#10629 ruling phrase, is the JSON-field DDL-independence fix and records nothing #10629 contributed. #7737 answers 200 as an issue and stays as the citation's subject on all three lines. The rewritten sentences stay true: plugin.ts:1543 and the test's :22 say the same ruling #7737 made for federated objects (commit 199ec4712), and the commit's message is that ruling's in-repo record; :153 says #7737 and commit 199ec4712 already bind the federated one, which the commit does. Whatever #10629's thread added to that ruling has no surviving record in this repository, and the sentences claim nothing about it. Anchoring there is right under ruling C: the commit that decided it, the live number kept, the dead one dropped. Judged RIGHT.

The four ADR anchors, read at origin/main. ADR-0029 line 475: D9.2a — AMENDMENT (2026-08-13, #8460), the ruling the seven registry.ts sites describe; the ADR names the number. ADR-0126 ### 7.2 Enable / disable (line 327), lines 339-340: the durable ledger row replaces the process-local flowEnabled map, retiring the #10243 leak's mechanism; it names the mechanism and the number, so the env-wide toggle leak's mechanism ADR-0126 §7.2 retires is exact. ADR-0104's ## Addendum (2026-09-05) (line 1027) names #15041 as its provenance and carrier and its ### Sequencing list puts The driver card, #15989 at step 2, so sequencing step 2 of ADR-0104's 2026-09-05 addendum at engine.ts:7164, :9860 and the test is exact, with the live #15989 kept beside it. ADR-0130 ### D3 (line 211) decides that the gate relaxation and the object-name uniqueness check are one change; the ADR does not itself name #14163, and 1dcb995f2's diff names it once, in .changeset/adr-0130-install-gate-co-ownership.md, so (ADR-0130 D3, commit 1dcb995f2) is the ADR first and the executing commit beside it. All four take ruling C's first rung where it applies. Judged RIGHT.

The two splits. #13178: f087c376f (scope the sys_file / sys_upload_session update and delete doors to the acting organization (#13178)) serves platform-object-tenancy.ts:144's sys_upload_session update writer; e49d98896's message carries the #13178 census measured it silencing 135 of 175 write call sites, so census cited in commit e49d98896's message measured … 135 of 175 at engine.ts:5450 and the classification test's :26 is what that message says. #16786: 5c8f5af50's diff names #16786 eight times and declares ObjectRepository's findOne / update shapes (engine.ts:18230, :18264, two tests); 6059b29c0 says Fixes #16786 and declares updateById's answer, so engine.ts:18272's move from stays open on #16786 to (its spec half: commit 6059b29c0) records a half that has landed. Judged RIGHT.

No new tracker number; live numbers stayed. For every pair, the numbers on the + line are a subset of the numbers on its - line: 0 added. 317 occurrences on - lines, 38 on +, net 279 gone, the dev's 279 exactly, over 70 distinct numbers. Probed over the issues endpoint at my read: all 70 removed numbers answer 404; all 28 kept numbers answer 200, 24 as issues and 4 as pull requests (#1395, #4281, #7211, and #11, which is decision batch #11 on platform-object-tenancy.ts:190, not a tracker citation); controls #5286, #12624, #20595 and #21268 answer 200. Judged RIGHT.

Rewritten sentences stay true. Each sentence that credits a commit with a ruling, a measurement, a reason or a phrase was matched against that commit: a016f08b8 carries The contract review of this PR found … and The contract review measured … (engine.ts:13014, :13218); 708431313 carries which is why and All four are refused at REGISTRATION … The matching read … is already refused by #5928 (engine.ts:2433; hook-exclude-objects.test.ts:501, :502); ff08691e6's diff names #8672 five times, quoting an org-less row is defensible for and #8672 measured this primitive on sys_permission_set (system-write-organization.ts:72, test :347, :117); e5eeb499c's diff carries route 3 (query-expression-conformance.test.ts:1070); 34ce8e7db names #13644 and measures (:1070's sibling sites); 801296050 carries Maintainer ruling 2026-08-20 (option A, #10165); d5cbb44f3 carries names four raw-org callers across two files and the phantom read this branch removes (protocol-meta.test.ts:100, :181); 96326040f names #14683 nine times and its diff resurrection (:169); 9a884c6e4's diff carries Second, NOT measured and 1cba33f16's carries B half and EARLY SIGNAL (engine-seed-required-deferral.test.ts:10, :139); 901773b21's diff carries 104 blocks and its message the band (find-hook-result-shape.ts:30, which now claims only the band); 83a3b1f2e names #6241 and its diff bypass and third; a56baa2bd pins C4 as a boundary (plugin-governance-scoped-metadata.test.ts:5); 5649efbf9 names #10527 and #10643 in its subject (lifecycle-service.ts:1293, :1294); 3bd9b3498 keeps the closure free of the manager, chokidar, glob and js-yaml, the leak core-boundary.ratchet.test.ts:52 says it closed; 4ecafc78b records that the 135/77% figure has no surviving corroboration, as the body's Acceptance notes say. Nothing overclaimed. Two wordings named, neither an overclaim: platform-object-tenancy.ts:209, not in the body's list, moves #8672, named verbatim by the 2026-08-31 ruling to Commit ff08691e6's example, named verbatim by the 2026-08-31 ruling; that ruling's in-repo record is e49d98896's message (Maintainer ruling 2026-08-31 … #8672's reasoning inheriting per object … sys_permission_set included), and the file's own evidence string at :217 quotes the ruling naming an org-less row is defensible for sys_permission_set, which is the example ff08691e6 quotes, so the sentence stays true. registry.ts:2508 softens measured to records, and the D9.2a amendment is the ruling record. Judged RIGHT.

Reach into dist, which decides the changeset. Not rebuilt here. From the manifest at the head: files is dist, README.md, CHANGELOG.md; no private field; tsup.config.ts sets dts unless OS_SKIP_DTS is set, entries src/index.ts and src/core.ts, formats esm and cjs; engine.ts:18230 is a docblock on a class method and action-governance.ts:339 on an exported function, so the .d.ts emission keeps them. The dev's three-leg measurement (54 of 137 rewritten non-test lines verbatim in dist; base text rebuilt differs in 10 of 14 files; restore byte-identical, 14 of 14) is consistent with that and is read, not reproduced. A changeset is owed. Judged RIGHT.

② Semver level

.changeset/20595-objectql-provenance-anchors.md at the head: frontmatter '@objectstack/objectql': patch; a summary line; Clause-②: no bare at the start of its own line (line 7), the shape scripts/pm/clause2-line.mjs's key-line reader accepts, which both check-changeset-no-major.mjs and check-adr-0087-registration.mjs import; prose naming the four ADRs, the reach into index.d.ts / index.d.mts, core.d.ts / core.d.mts, the shared type chunk and the esbuild-kept JavaScript comments, and Comment only: no export, type, error code, status, message text or runtime behaviour changes. patch is the right level: nothing authorable, exported or on a payload moves, so no breaking marker and no ADR-0087 disposition is owed, and Clause-②: no is the right arm. No skip-changeset label (labels: documentation, size/l, tests, tooling). The PR body's first line is Part of #20595 with no closing keyword, and its second is Clause-②: no. Check Changeset and Part-of PR must not also close its card read success at the check-run read below. Judged RIGHT.

③ Boundary flags

  • Deviation (1), the fast-forward to 4727fcb22 before any edit. The base is recorded, the rewrite commit sits on it, and the dev reports identical census rows at both bases. Accepted.
  • Deviation (2), the merge of origin/main 8dea55d31 before the final push. The merge contributes nothing to the net diff (the pre-merge and net diffs are byte-equal), and none of the 33 files it brought is under packages/objectql or is check-issue-citations.mjs or dispatch-gates.mjs. Since then origin/main has moved four commits to ee42f00e39; one touches packages/objectql/src/validation/record-validator.ts, which is not in this PR's file list, and an in-memory git merge-tree --write-tree origin/main 1e0895870d reports no conflict (mergeable: true at the PR read). The queue rebuilds onto main. Accepted.
  • Deviation (3), the [finding] 15 more PASSING @objectstack/runtime tests print the same refused a read on feature — 134 lines after #10380 quiets its two, led by notifications.hono.integration.test.ts (52) #10629 anchor. Judged in ①. Accepted.
  • Deviation (4), the short enumerateBoard read. One run returned 91 pages, 9,000 records and frontier [Decision] Pre-auth discovery/bootstrap payloads: inside BaseResponseSchema (coordinated objectui flip) or ruled exempt with reasons — today they are neither #9389 at exit 0 between two 191-page reads; the dev discarded it and both census readings the body quotes come from 191-page boards bracketed by newest-number reads (fix(driver-sql): a MySQL NOW() datetime default carries its column's precision #21252, lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261), so nothing in this PR rests on it. Accepted for this record. Escalated to the seat as a tooling finding, not filed by this reviewer: the gate's own board reader degraded silently with only a zero-record guard, which is the shape Route and surface ownership rule 3 names (a verifier that silently degrades reports success); a frontier-below-newest-number refusal is the obvious guard. One occurrence, not reproduced; the seat decides whether it is a card.
  • Deviation (5), the model-free trailer pair. Both authored commits end in Claude-Session: and Co-authored-by: Claude, the pair AGENTS.md prescribes; the PR footer is the session-URL form, right for a body. Accepted.
  • The 43 test-string sites (25 numbers, 23 files). describe / it titles and assertion arguments; outside this stage by the claim's own words (no string literal), and every one of the 25 numbers has its anchor in this PR's table. Correctly left. Carrier, as stages 1 and 2 recorded: this card, a later stage whose claim widens to test strings. Escalated to the seat as the standing carrier question, not a FAIL.
  • The #7737/#10629 pair in driver-sql (sql-driver.ts, :12110 at 5923084795). The next stage's; the judgment above applies there unchanged (199ec4712, the live external-datasource-federated-read: federated read returns empty — the external object→remote-table mapping never registers (boot ordering) #7737 kept, the dead number dropped). Noted for the driver-sql stage.
  • The CHANGELOG.md sites (66, 44 numbers). Release-owned under the Documentation Guardrails; never edited in a code PR, and no CHANGELOG.md is in the file list. Correctly left. Dropped.
  • The census-figure comment at engine.ts:5450 and tenancy-by-object-classification.test.ts:26. The rewrite moves the citation to the commit whose message carries 135 of 175 and leaves the claim as written, which is right for a citation sweep; 4ecafc78b records the figure as uncorroborated, so the two sentences now state as measured a number the in-tree census artifact does not reproduce. Not this stage's population and not a FAIL. Escalated to the seat as a comment-accuracy item: a one-line qualification in a later objectql comment-prose touch or a small docs-only card, the seat's call.
  • Governance and size. The file list touches no governed surface (docs/adr/**, .claude/**, skills/**, AGENTS.md, CLAUDE.md, docs/NORTH-STAR.md); Governed Surface Queue Guard reads success; 566 changed lines, under the 5,000-line class; head repo equals base repo. This record is the dispatch's adversarial review, not a Prime Directive 14 tier record.
  • Check-runs on the head, read last, at 2026-10-02T00:14:54Z. 33 runs: 28 completed/success, 3 completed/skipped (Build Docs, Console Pin Gate, Packed-tarball smoke (opt-in)), 2 in_progress with no conclusion: Test Core (4/6) and Test Core (5/6). Of the seven required contexts by exact name: Lint & Repo Gates, TypeScript Type Check, Dogfood Regression Gate, Build Core, Temporal Conformance (live PG + MySQL) and Governed Surface Queue Guard read success; no run named exactly Test Core was present at read, its shards 1, 2, 3 and 6 reading success and 4 and 5 in progress, so that context is not yet a verdict. Also success: Check Changeset, Check PR Size, Part-of PR must not also close its card, The card this PR closes must claim this branch, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Dogfood Verify CLI, the four Type Check · jobs and the three Dogfood Regression Gate shards. An in-progress required job is not a verdict and does not by itself make this record FAIL; the seat confirms the green bar from the merge bar before enqueue.
  • Local-runs: none, spelled out. Reads only: GitHub GETs; git fetch, git show, git log, git grep, git rev-parse, git merge-base, git diff and one in-memory git merge-tree in the main clone (no worktree, no checkout); a text pairing pass over the downloaded diff and the number probes, both from the scratch directory. No build, test, gate or ablation was run or re-run; every guard, census, dist and gate figure above is the dev's, read and judged for consistency, not reproduced.

Implemented-by: claude/issue-20595-objectql-citations
Reviewed-by: session_017xfMoEjKUuSh2xYB8sCozp

VERDICT: PASS


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants