Skip to content

refactor(rest): move the /meta history family into meta-item-history-routes.ts (#23050 slice 13d) - #24304

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-23050-s13d-meta-item-history
Oct 18, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-23050-s13d-meta-item-history

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #23050
Clause-②: no

Sub-slice 13d of the rest-server.ts split: the sixth /meta group. Group G6 of RestServer#registerMetadataEndpointsInner, the history family, is five statements of 820 lines (base rest-server.ts:5218–:6037 at 93b4acb57, after the separator line :5217), every one a registerPerItemRoute({ … }):

route statement range with its leading comments
GET {metaPath}/:type/:name/history :5224–:5356 :5217–:5356
GET {metaPath}/:type/:name/audit :5366–:5518 :5357–:5518
POST {metaPath}/:type/:name/publish :5522–:5710 :5519–:5710
POST {metaPath}/:type/:name/rollback :5714–:5830 :5711–:5830
GET {metaPath}/:type/:name/diff :5834–:6037 :5831–:6037

They move, re-indented one level, to a new module, packages/rest/src/meta-item-history-routes.ts, as registerMetaItemHistoryRoutes. Like 13c's module, it is a registerPerItemRoute pass-through: it registers nothing on the route manager itself.

This follows the slicing plan (os-dev-report 6239704287, sub-slice 13d), seat 1's ruling on it 6239783526 (quoted below), static-receiver ruling A 6205442867, 13c's handover_13d (report 6245538958), seat 2's hand-off 6246649897 and the claim 6247249133. PR #24257 (13c, e9bc60b5a) is the shape copied.

Nothing else moves:

  • the route table, the ordered server registrations, every server-visible handler and every INNER registration (method, path, metadata, arity, handler digest) are identical, base vs head, in 20 configurations;
  • the published dist/index.d.ts / index.d.cts are byte-identical, and so are both bundles' 39-name export lists;
  • six code tokens of the moved body changed, the ruled receivers, and one comment token was re-anchored because the move made a dead tracker citation an added line for the issue-citation gate (both below).

rest-server.ts goes from 7,327 to 6,545 lines on the claim's base (7,357 to 6,575 on origin/main d537a318b, the merge head's). G7 and G8 (13e), the umbrella registerMetadataEndpoints and its guarded swap, the inner head's bindings and registerPerItemRoute itself, every handler body, the class head and its members, meta-item-read-gate.ts, docs/adr/** and packages/spec/src/** are untouched. #23050 stays open for 13e.

The basis for the Clause-②: no line above: this is a move. The route table, the inner registrations, every wire answer, the .d.ts and the export list stay identical. The one declaration change is export on the module-level helper refuseNonAuthoringCaller (ruling Q6 B), and packages/rest/src/index.ts does not re-export it: measured, dist/index.d.ts and index.d.cts are sha256 e0a7f9586d1d8802… at base, head and the first merge head, and e027d7941ba1908e… at the final head, byte-identical to a build of main d537a318b; the entry's 39 export names (ESM and CJS) contain no refuseNonAuthoringCaller. The reader edits change evidence paths only.

The ruling this follows (seat 1, 6239783526, verbatim)

  • Q1, A. The four head bindings (metadata, metaPath, isScoped, registerPerItemRoute) reach each module as ONE scope: MetaRouteScope parameter, built once in the inner head. Each module destructures only what it uses, and body tokens are unchanged. The host stays class members only.
    • registerPerItemRoute stays one closure that reads RestServer's guarded routeManager at call time. ⛔ No module-local copy: that would be a second copy of a helper (rule 2).
  • Q3, A. rest-server-registrar-files.ts exports a named subset, the /meta modules. The dogfood census's reachable count becomes "the umbrella's sites plus every site in that subset", and a control pins the subset against the number of module calls inside the inner method. This is declared at 13a with the anonymous-401 ablation as the runtime proof.
    • From 13c on, a module with no direct register site is controlled on registerPerItemRoute( instead.
    • ⛔ No naming convention, and ⛔ never "let blindSpot rise".
  • Q4, A. STORED_VERSION_DOOR_POLICY, a private static readonly field set once at class evaluation, is handed over by value. 13b and 13d name it in their claims, together with each sub-slice's static-receiver tokens (13 in all, ruling A 6205442867).
  • Q6. […] B for refuseNonAuthoringCaller (13d): it stays and is exported, because its callee mayReadAuthoringTrail is a docs anchor (system-context.mdx:108). […]

Binding on every sub-slice (from the plan's measurements):

The maintainer's rule on this card, verbatim: 「每片只搬代码、路由表前后一致、门禁和文档锚点同 PR 迁完。」

The shape

Moved, at its position. In the inner method, right after 13c's registerMetaItemWriteRoutes.call(itemWriteHost, scope);, the head now builds the host literal itemHistoryHost and calls registerMetaItemHistoryRoutes.call(itemHistoryHost, scope) with the ONE existing scope (no second one is built). Registration order is unchanged: after the per-item writes, above the object FSM read (G7).

The host, MetaItemHistoryRouteHost: 15 members in first-read order (a symbol-resolved walk of G6 with the TypeScript 6.0.3 compiler API, the plan's method; no bare this, no this[...], no function keyword, no assignment to a this member, no arguments, no super):

member reads handed over as
resolveExecCtx 5 closure (...a) => this.resolveExecCtx(...a), spelled exactly as the execctx census's forwarder
resolveProtocol 5 closure
eventDoorRefusal 2 (history, audit) closure
walledCatalogRefusal 2 (publish, rollback) closure
resolveMetaWriteActor 2 (publish, rollback) closure
metaTypeSingular (private static) 1 (diff) closure (...a) => RestServer.metaTypeSingular(...a)
resolveObjectMasker 1 (diff) closure
gatesPerCaller (private static) 1 (diff) closure on the class
fetchCurrentMetaDocument 1 (diff) closure
gatesOnItsOwnKey (private static) 1 (diff) closure on the class
diffSides (private static) 1 (diff) closure on the class
metaItemReadGate 1 (diff) closure
STORED_VERSION_DOOR_POLICY (private static readonly field) 1 (diff) BY VALUE (Q4 A)
diffEmittedFrom (private static) 1 (diff) closure on the class
maskObjectDocument 1 (diff) closure

No routeManager member. All five statements register through registerPerItemRoute, which reaches the module in scope as the inner head's ONE closure (Q1 A, ⛔ no module-local copy). That closure reads the server's this.routeManager at call time; every call runs during the inner call, inside the umbrella's swap, so all five routes still mount behind the wrapping registrar and still answer to metadata.endpoints.item, which the same closure reads. No member is a getter: the body reads no instance field at request time.

The six ruled receiver tokens (ruling A 6205442867, Q4 A), all in the diff handler: RestServer.metaTypeSingular( → this.metaTypeSingular(, RestServer.gatesPerCaller( → this.gatesPerCaller(, RestServer.gatesOnItsOwnKey( → this.gatesOnItsOwnKey(, RestServer.diffSides( → this.diffSides(, RestServer.STORED_VERSION_DOOR_POLICY → this.STORED_VERSION_DOOR_POLICY, RestServer.diffEmittedFrom( → this.diffEmittedFrom(. Each static reads nothing but its arguments (gatesPerCaller still asks gatesOnItsOwnKey on the class).

Module-level names.

  • Stays in rest-server.ts and gains export (Q6 B): refuseNonAuthoringCaller (history, audit and diff call it), beside its callee mayReadAuthoringTrail, the system-context.mdx:108 anchor; a one-paragraph pointer is added to its docblock. Row 108 is unchanged.
  • Already exported, imported from ./rest-server.js: the five closed sets META_ITEM_HISTORY_PARAMS, META_ITEM_AUDIT_PARAMS, META_ITEM_PUBLISH_PARAMS, META_ITEM_ROLLBACK_PARAMS, META_ITEM_DIFF_PARAMS (the door tests import them from there), readDeclaredQueryNumber and UNDECLARED_WHOLE_NUMBER_PARAM (approvals, data-action and search import them from there), metaItemPackageBinding and sendMetaItemAbsent. Each is read only at request time.
  • Imports that left rest-server.ts with the body (six, measured): HistoryMetaItemRequestSchema and AuditMetaItemRequestSchema (the whole value import), the types PublishMetaItemRequest, AuditMetaItemRequest, HistoryMetaItemRequest, and metaMemberSelector. The plan named five; metaMemberSelector is the sixth because its other readers left with 13b and 13c, so G6 held its last three reads (noUnusedLocals would red the leftover import). A pointer comment stands at each old position, and the thrownAnswerIsBareNotFound import comment now says the diff door's catch moved too and the class's event-door refusal still reads it.
  • Every other name is imported from the module rest-server.ts imports it from; MetaRouteScope and TransportScopedMetaRequest from ./meta-collection-routes.js.

Proof

Builds, suites, dumps, controls and ablations ran through os-verify-lock, every exit captured before any pipe; the short tsx probes ran unlocked (see Deviations). The base is 93b4acb57 (the claim's). The head is 56a51a837; the merge head 93027d839 adds one merge of origin/main 1e001c7df (#24270, #24269: packages/spec, packages/metadata-protocol, packages/runtime, packages/client, packages/objectql tests), with no path in common with this diff; 2c02e0a0d is the comment edit above (legs 1–4 re-run there: the source dump byte-identical to the head's in all 80 files, the rebuilt bundle equal to base under the declared normalization, .d.ts unchanged). The final head 03ac3135e merges origin/main d537a318b a second time, because it brought PR #24267 (the class head of rest-server.ts, metaItemReadGateSources and serveMetaItemLayered, and meta-item-read-gate.ts) and PR #24274 (row 29b of system-context.mdx), both textually disjoint from this diff, as the claim recorded; the merge was clean and this branch's delta against main is still exactly its 17 files, +1210 / −853. Re-measured against that main (built from a detached checkout of d537a318b): index.d.ts / index.d.cts are byte-identical to main's, the 39-name export list is unchanged, and the source and bundle dumps of all 20 configs equal main's: 60 of 60 full-boot files and 688 of 688 inner digests under the same mapping and normalization (raw, only GET …/diff's 36 differ, the receivers), with the concatenation hashes quoted below, which main's merge moved none of. The bundle identifier-set diff against main's ESM bundle is the same five head-only names, none lost.

1. The moved text. Base rest-server.ts:5218–:6037, with one 4-space indent removed, against meta-item-history-routes.ts:177–:996 (the body after the destructuring line), at the final head: the raw diff exits 1 on exactly seven lines, the six receivers and one comment line; with the six this.X mapped back to RestServer.X and that comment line mapped back, diff exits 0 over all 820 lines, both sides sha256 51dc0cccdc000123dbd57fa5fb528ed2a5a96c61dd73c357ef74fa28024134cc. Every non-empty line (814) carried the 8-space indent; no tab, no trailing whitespace.

The one comment edit. The audit door's moved comment called auditMetaItem's declaration "the #11006-pattern catch-up". check-issue-citations judges the lines a change ADDS, so the move made that pre-existing citation an added line, and it does not resolve: --probe-cause reads it [deleted] ("minted, gone from the board, and the web endpoint 404s too"), exit 2. The gate's own remedy is to name a target that resolves, and the re-anchor sweeps that cleaned packages/rest/src used the deciding commit: the line now reads "(the commit-cccbe51bf-pattern", cccbe51bf being the landing of that card's ruling ("feat(spec): declare publishMetaItem as optional MetadataProtocol member with PublishMetaItemRequest", read through the REST API, since this clone's history starts after it). Comment text only: esbuild drops comments, and every source and bundle digest at the final head equals the one before the edit. With it the gate reads 77 resolves, 1 resolves-as-pull-request and exits 0.

2. .d.ts and exports. index.d.ts and index.d.cts are sha256 e0a7f9586d1d8802b2b2922b957401a02f03818db56779dfa347534db20732ca at base, at head, at the first merge head and at 2c02e0a0d; at the final head they are e027d7941ba1908e700d18bcd37ae6b26241e4bca7a4fcb11364305e3b204fd9, byte-identical to a build of main d537a318b (#24267 moved them, not this diff). The head-only marker registerMetaItemHistoryRoutes hits 2 in each of index.js / index.cjs at head and merge head, 0 at base. Both bundles load with 39 exports and one sorted name list, sha256 b3246be6a1718700…, ESM == CJS, base and head (13c's reading too).

3. Full-boot legs, 20 configurations: slice 12's thirteen, then the /meta switches under scoped-optional (metadata.endpoints.types, .items, .item, .maintenance each false; all four false; metadata.prefix: '/metadata'; api.enableMetadata: false). Route counts 75 / 150 / 75 / 75 / 73 / 73 / 142 / 148 / 148 / 138 / 144 / 138 / 150 / 146 / 148 / 126 / 144 / 114 / 150 / 112, the same on both trees.

  • Source leg (a tsx boot of src/rest-server.ts): routes.json, calls.json and handlers.json byte-identical in all 20 configs, 60 of 60, concatenation sha256 e73a487e4cfc05ab… on both trees. A second base run was identical to the first (diff -r exit 0).
  • Bundle leg (the same dump against the built dist/index.js, the base bundle loaded from a copy): 60 of 60 identical, concatenation d1db493b81aaf53e…, under one declared normalization, esbuild's numeric alias suffix on an import name two bundled modules share. Measured by an identifier-set diff of the two bundles, the ESM head gains exactly itemHistoryHost, registerMetaItemHistoryRoutes and three renumbered aliases (ObjectSchemaMaskEvaluationError4, metaWriteCapabilityVerdict3, rethrowAuthzStoreUnavailable6) and loses none; those three names are the ones normalized. Unnormalized, the 19 configs that mount /meta differ only in handlers.json (the umbrella wrapper spells rethrowAuthzStoreUnavailable under a shifted suffix). The CJS bundle gains itemHistoryHost, registerMetaItemHistoryRoutes, import_core39 and import_metadata_core18.

4. The inner-registration leg. Each config builds a RestServer with a recording routeManager and calls registerMetadataEndpointsInner(basePath) directly for /api/v1 and /api/v1/environments/:environmentId: 688 recorded registrations over the 20 configs (13c's count), digested whitespace-free with the ruled receiver tokens of 13a–13d mapped back, together with method, path, metadata and arity.

  • Source leg: 688 of 688 identical, same order; digest-list sha256 2fab0c3853495542… on both trees. Unnormalized, exactly 36 digests differ: GET …/diff on both bases in the 18 configs that mount it, the six receivers. The other four moved routes are identical raw.
  • Bundle leg: 688 of 688 identical under the three alias names; digest-list sha256 0dcff1d8b81a295d… on both trees (unnormalized, GET …/published, G8, also differs: the same alias shift, in a body this PR does not touch).
  • Positive controls (one character each, through scripts/ablation-replace.mjs, anchor 1 → 0): the audit door's 501 message gained a ! (module blob 6b11bab3ccac → cdb207236e6f), then, separately, the publish door's (→ 7f57a79d8125). Each moved the inner digests of exactly its own route, on both bases, in the 18 configs that mount it: 36 of 688 each, and nowhere else; all 20 configs' full-boot files stayed byte-identical (60 of 60), the blind spot the inner leg covers. Restored each time: the blob equals HEAD and git diff HEAD is empty.

5. H2: the handed-over closure is the inner method's own. An anonymous request at each moved route on both bases (one-off tsx probe, scoped-optional), base and head byte-identical:

  • endpoints.item on: all ten mounts answer 401 UNAUTHENTICATED with zero protocol calls, and all ten server-visible handlers are the umbrella's wrapper.
  • endpoints.item: false: the five routes are gone on both bases (150 → 126 routes, 0 moved mounts), on both trees.

6. The guard ablation (the plan's shape for 13c, 13d and 13e-published). Three literal anchors, nested: the umbrella stashes its realRouteManager captured above the swap (rest-server.ts blob cb30c8a7e5b6 → e5933a89b85f), itemHistoryHost carries it as a routeManager member (→ f019c09637fa), and the module replaces the scope's registerPerItemRoute with a module-local registrar that honours the same switch but registers on that host member (module blob 6b11bab3ccac → 9614ca62b428).

7. The late-binding ablation (one-off script). The 9 instance methods are planted on the server and the 5 static methods on the class before registerRoutes(), as recorders; seven request shapes are driven over the five moved routes (history and diff on an object and on a view, audit, publish, rollback), each answering 200, then everything is planted again and the shapes are driven again.

  • Head (MEASURE lines byte-identical to base): all 14 closure members are reached before and after the re-plant, early calls after re-plant: 0.
  • Ablation: eventDoorRefusal: this.eventDoorRefusal.bind(this) (blob cb30c8a7e5b6 → 601b3610bc89) gives early calls after re-plant: 3 ["early:eventDoorRefusal"] and 13 late members, exit 1. Restored: the blob equals HEAD and git diff HEAD is empty.

Readers re-pointed (sums unchanged, no gate loosened)

rest-server-registrar-files.ts gains meta-item-history-routes.ts in REST_SERVER_REGISTRAR_FILES (length 16 → 17) and in the named /meta subset REST_SERVER_META_ROUTE_FILES (3 → 4). The dogfood control counts .call( inside the inner method, now 4, so the subset and the call moved together.

reader sum over the list change
execctx-consumer-census.test.ts 62 sites = 5 + 9 + 5 + 7 + 8 + 1 + 5 + 2 + 1 + 1 + 1 + 0 + 6 + 3 + 1 + 2 + 5; mentions 141 → 145 The five sites moved, all locally caught as before (audit, publish, rollback on their invocation lines; history and diff on their continuation lines, two of §7's and §8's four). The four new mentions are the seam: the forwarder, two, and the host interface's member, two. rest-server.ts goes 55 → 52. Seventeen forwarders = (17 − 1) + 3 − 2
meta-draft-read-door-census.test.ts 8 = … + 3 + 2 + 1 + 0 The history family reads no draft switch
rest-server-query-number-census.test.ts 9 = 7 + 1 + 0 ×14 + 1 The rollback's Number(toVersionRaw) (an exemption row keyed by route) moved; no ledger row changed
rest-server-canonical-query-ast.test.ts (repo project) 4, unchanged The module builds no query: slot; floor 0
rest-server-docblock-position.test.ts 65 = 62 + 3 The module carries three TSDoc blocks (header, host interface, function); rest-server.ts keeps its 161
ui-view-route-identity / -tenancy measurement tests this.enforceAuth( 60 unchanged, this.resolveExecCtx( 78 → 79 The fourth /meta host literal forwards resolveExecCtx only; the ownership guard is still 1 call site and 1 forwarder
dogfood authz-conformance.test.ts realtime tripwires read 0 over 17 files List length 16 → 17
dogfood authz-probe-blind-spot.census.ts 70 / 19 / 51 unchanged The module is controlled on registerPerItemRoute( (5), as 13c's is (Q3); the whole-population registerPerItemRoute( control stays 8 (1 in rest-server.ts, G8's, + 2 + 5); const registerPerItemRoute = 1, forwarder slice: 1, this.routeManager.register( 63 and enforceAuth 112 unchanged; population rule text names the module and the sixth group
scripts/check-route-envelope.mjs (MODULES) stringError 39, siblingCode 54, sums unchanged The module is declared dialectOnly + ratchet #9559 at stringError 5 / siblingCode 1 (the four 501 bodies of history, publish, rollback and diff, and the rollback's 400 INVALID_REQUEST, which is the one sibling-code body); rest-server.ts banks 7 → 2 and 3 → 2, the two class-head sites
content/docs/permissions/system-context.mdx row 50 census OK The module's anchor meta-item-history-routes.ts#registerMetaItemHistoryRoutes is added and rest-server.ts#registerMetadataEndpointsInner is dropped: publish and rollback held the inner method's last isSystem reads
docs/qa/platform-checklist/areas/studio-authoring.json:459 anchor resolves to G6 rest-server.ts#toVersion → meta-item-history-routes.ts#registerMetaItemHistoryRoutes (the 13a precedent for #route)
scripts/adr-anchors/packages__rest__src__meta-item-history-routes.ts.json (new) 1783 decision letters, restored ADR-0067, ADR-0106, ADR-0066 and ADR-0131, with the invariant the bodies' citations carry

Red before the re-points, in two stages (each reader read the readers' base text).

  • Move commit 337889b10, list not grown: the six list readers Tests 7 failed | 121 passed (128) (execctx 57 vs 62 sites, caught same-line 9 vs 12, §7 control 9 vs at least 12, §8 control 2 vs at least 4; query-number: the rollback row names no site, its positive control false, 8 vs 9 sites); dogfood Tests 2 failed | 106 passed (108) (population 65 vs 70; .call( 4 vs a subset of 3); check:route-envelope exit 1 (NOT DECLARED, and rest-server.ts found 2 vs declared 7 and 2 vs 3); check-system-context-census exit 1 ([file-without-a-row] the module, 2 reads in 1 symbol; [anchor-is-not-a-read-site] rest-server.ts#registerMetadataEndpointsInner); check-adr-anchors silently green at 1765 decision letters vs base 1783.
  • List grown 099ef9a27, readers at base text: local Tests 7 failed | 123 passed (130), repo Tests 2 failed | 93 passed | 17 skipped (112), dogfood Tests 2 failed | 106 passed (108) (the length pins and the new module's control).
  • The silent reader, measured: scripts/symbol-anchors.mjs#symbolResolutionClass reads rest-server.ts#toVersion as declaration at base (G6's const toVersion) and as literal at head (the 'toVersion' of META_ITEM_ROLLBACK_PARAMS): still resolving, now about the wrong thing. The new anchor reads declaration in the module.
  • Examined, not edited: packages/runtime/src/domains/meta-list-projection-parity.test.ts derives the item, tree and layers GET handlers by path (G6 holds none); packages/spec/liveness/*.json (the endpoints.item evidence names the inner head's registerPerItemRoute, which stays; no packages/spec edit); system-context.mdx row 108 and docs/adr/0119:118 #NOT_IMPLEMENTED (resolve outside G6).

Verification at the final head 03ac3135e

Under os-verify-lock, each exit captured before any pipe (wall clocks are shared-box readings):

  • pnpm --filter @objectstack/rest typecheck: exit 0 (check:test-typecheck: OK, 0 file(s) / 0 error(s)).
  • @objectstack/rest local (vitest run --project local): exit 0, Test Files 295 passed (295), Tests 6049 passed | 326 skipped (6375).
  • @objectstack/rest repo: exit 0, Test Files 5 passed (5), Tests 274 passed | 17 skipped (291).
  • dogfood authz-probe-blind-spot.test.ts + authz-conformance.test.ts: exit 0, Tests 108 passed (108).
  • @objectstack/runtime test:repo: exit 0, Tests 808 passed (808) (meta-list-projection-parity among them); @objectstack/core test:repo: exit 0, Tests 85 passed (85).
  • The same rest, dogfood, runtime and core runs were green at 93027d839 and (rest and dogfood) at 2c02e0a0d; @objectstack/dogfood typecheck exit 0 at 93027d839.

Gates, unlocked: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths) at 03ac3135e derives 119 commands over 17 paths against merge base d537a318b, 2,063 changed lines (+1,210 / −853), under the 3,000 threshold. All 119 ran sequentially at 03ac3135e, exit codes recorded before any pipe: all 119 exit 0. --ran: "Run reconciliation — 119 derived, 119 run, 0 NOT-MEASURED, 0 UNRUN.", exit 0. Readings: check:route-envelope 28 modules (9 conformant, 18 ratcheted, 1 exempt); check:adr-anchors 74 anchored files, 1,783 decision letters; check-system-context-census OK, 66 files, 123 symbols, 136 of 136 cited, 159 anchors; check:cross-package-test-inputs OK; check:doc-authoring clean; check:dual-build-cjs-loads 111 entry points over 69 packages; check:pm-dispatch-gates 1,913 cases; check-issue-citations exit 0. The first union, at 93027d839, read 118 of 119 exit 0 and check-issue-citations exit 2: the dead citation the comment edit above re-anchored. origin/main moved to 21070a2f0 after the second merge (#24302, #24292, #24275, #24290: packages/spec, packages/lint, docs/qa); none of its paths is in this diff, so it was not merged a third time.

Also: node scripts/check-platform-checklist.mjs --changed-from origin/main exit 0 (10 anchors judged, 0 lost); pnpm exec eslint --no-inline-config over the 13 changed .ts / .mjs files exit 0, no output; node scripts/pm/check-governed-merges.mjs --branch HEAD exit 0 (0 of 17 paths governed, 2,063 at most 3,000); a control-byte scan of every changed file finds none. Not run locally: check:dev-prereqs and check:skill-frame-freshness (local-only; not triggered: no spec build input, no four-axis frame file). The repo-wide pnpm lint is CI's.

Acceptance notes

Deviations

  • The short tsx probes (H2 on base and head, the late-binding probe on base and head) ran outside os-verify-lock, a few seconds each; dumps, controls, ablations, builds and suites ran under it. The base legs of those probes boot the base rest-server.ts from an untracked copy beside it in src/ (deleted after each run); the base bundle leg loads dist copied under packages/rest/node_modules/.s13d-base/ (gitignored).
  • A whole-workspace pnpm turbo run build --concurrency=2 (77 tasks) ran after the merge, for the dist-reading gate families.
  • One comment token of the moved body was edited (the dead #11006 citation re-anchored to commit cccbe51bf, proof 1), beyond the six ruled receivers: the diff-scoped check-issue-citations reads moved lines as added, and a byte-identical move kept it at exit 2. No code token changed.
  • The rest repo project, the runtime and core test:repo and the dogfood readers ran locally: this diff edits a repo-project test, and the runtime and core repo projects read rest sources from disk.
  • The harness attribution reminder asked for a model-named Co-Authored-By and a robot-emoji PR footer. Per the dispatch and AGENTS.md, the model-free trailers (merge commit included) and the session-URL footer are used.

Generated by Claude Code

…routes.ts (#23050 slice 13d)

The five history-family statements of registerMetadataEndpointsInner (GET
/history, GET /audit, POST /publish, POST /rollback, GET /diff) move,
re-indented, into registerMetaItemHistoryRoutes. The inner method builds
the host literal at their old position and passes the one existing scope.
Readers are re-pointed in the following commits.

Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T
Co-authored-by: Claude <noreply@anthropic.com>
…m-history-routes.ts (#23050 slice 13d)

Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T
Co-authored-by: Claude <noreply@anthropic.com>
…ly (#23050 slice 13d)

The registrar-list readers re-read their sums with the module on the list,
the dogfood census controls the pass-through module on registerPerItemRoute(,
check:route-envelope declares the module with the five string-error and one
sibling-code bodies that moved, system-context.mdx row 50 trades the inner
anchor for the module's, the studio-authoring #toVersion pointer resolves to
the moved function, and a new adr-anchors entry restores the decision-letter
count. One patch changeset on @objectstack/rest.

Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T
Co-authored-by: Claude <noreply@anthropic.com>
…eted tracker citation (#23050 slice 13d)

The diff-scoped issue-citation gate reads the moved body as added lines, and
one comment cited a tracker number that no longer resolves on the board
(deleted). Re-anchored to the commit that landed that pattern, cccbe51;
comment text only, no token of code changed.

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

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/rest, touching 69 documentable anchor(s).

23 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 21070a2f0ac944e930ab8c269e04d024d4a21eea.

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

What this run could not see
  • 2 cross-cutting symbol(s) contributed no route anchor: resolveExecCtx (28 routes), resolveProtocol (26 routes)
  • 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 — 18 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 21070a2f0ac944e930ab8c269e04d024d4a21eea → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 7b8c766c68204f978ff5ae6a3a9deb6011a31e4a — the merge of head 03ac3135eeac7a6d457129fabc761fe9e5d7d927 into base 21070a2f0ac944e930ab8c269e04d024d4a21eea, 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 7b8c766c68204f978ff5ae6a3a9deb6011a31e4a && git checkout 7b8c766c68204f978ff5ae6a3a9deb6011a31e4a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 21070a2f0ac944e930ab8c269e04d024d4a21eea 03ac3135eeac7a6d457129fabc761fe9e5d7d927 && git checkout -B drift-repro 21070a2f0ac944e930ab8c269e04d024d4a21eea && git merge --no-ff 03ac3135eeac7a6d457129fabc761fe9e5d7d927

node scripts/docs-audit/affected-docs.mjs --json 21070a2f0ac944e930ab8c269e04d024d4a21eea

⚠️ 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 21070a2f0ac944e930ab8c269e04d024d4a21eea → 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

席位核对

ACCEPT · domain:cli seat 1 (seat post #6024) · zhuangjianguo · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-18T10:28Z · on head 03ac3135e · #23050 sub-slice 13d (claim 6247249133, report 6248737371). This is the seat's own review at the default tier: move-only, Clause-②: no, no packages/spec path, not governed. It was read against GitHub, not the report.

  1. Shape: draft against main. The first line is Part of #23050, and no closing keyword is in the body (full-body scan). Clause-②: no reads as declared through scripts/pm/clause2-line.mjs, both in the PR body (bare) and in the changeset. Assignee zhuangjianguo. 17 files, +1210 / −853 (2,063 changed lines, under the 3,000 human-merge line). check-governed-merges --pr 24304: NOT governed.
  2. Premise and rulings, measured:
    • itemHistoryHost is built inside registerMetadataEndpointsInner at G6's old position (rest-server.ts:5268 at head), and the ONE scope is passed to registerMetaItemHistoryRoutes.call(itemHistoryHost, scope) (:5285) — Q1 A.
    • refuseNonAuthoringCaller stays in rest-server.ts and gains export (:1833). packages/rest/src/index.ts names it 0 times, so the entry is unchanged (Q6 B).
    • The report's proof legs carry the move: the mapped-back moved text is identical over 820 lines; getRoutes() and the full-boot legs match on 20 configs (60/60); the inner digests match 688/688, with a one-character positive control per route; .d.ts, .d.cts and the 39-name export list are identical; the guard ablation goes red (21 standing pins); late binding holds.
  3. Readers and docs, read sentence by sentence in the diff:
    • system-context.mdx row 50 adds meta-item-history-routes.ts#registerMetaItemHistoryRoutes and drops rest-server.ts#registerMetadataEndpointsInner. Publish and rollback took the inner method's last isSystem reads with them, and the report shows the census red without the drop.
    • studio-authoring.json:459's #toVersion anchor is re-pointed to the module, with the rest of the sentence unchanged. This is the silent reader the claim named.
    • A new scripts/adr-anchors/packages__rest__src__meta-item-history-routes.ts.json restores the decision-letter count (1765 → 1783).
    • check-route-envelope.mjs changes MODULES only.
    • The registrar list goes 16 → 17 and its /meta subset 3 → 4, together with their census readers and the dogfood pair.
    • The changeset is a patch on @objectstack/rest, and each of its sentences says the move changes no route, handler, answer or export.
  4. Gates: the report's local union is 119/119 exit 0 at the final head, with the --ran reconciliation at 0 NOT-MEASURED. eslint exits 0. check-platform-checklist --changed-from origin/main judges 10 anchors and loses 0. CI on this head at this stamp: 29 completed, all success or skipped; 9 in_progress; no failure. ⛔ Not ready until every check on the head is green.
  5. Deviations accepted:
    • One comment token of the moved body changed beyond the six ruled receivers: the audit door's dead #11006 citation became its landing commit cccbe51bf. The diff-scoped check-issue-citations reads moved lines as added, and AGENTS.md has a rule cite the commit, not the card. esbuild drops comments, so every source and bundle digest is unchanged.
    • metaMemberSelector left with the body: its other readers left at 13b and 13c.
    • Two main merges, both clean and disjoint, with the proofs re-measured against a build of main d537a318b.
    • The base copies and probes were uncommitted, and removed afterwards.
  6. Out of scope:
  7. Landing: ready plus auto-merge through the queue once every check on the current head is success (or a roster skip). Then read origin/main and the queue branch for the merge. The card stays open for 13e: this seat releases it to pm:queue with a Release: line in the same act as the landing record.

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/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants