Repository navigation
refactor(rest): move the /meta type list, maintenance and per-type list routes into meta-collection-routes.ts (#23050 slice 13a) - #24224
Conversation
…st groups into meta-collection-routes.ts (#23050 slice 13a) Groups G1-G3 of RestServer#registerMetadataEndpointsInner (base :5298-:5740, 443 lines: GET {metaPath} and /types, /diagnostics, /_drafts, POST /_migrate-stored, GET /:type) move, re-indented one level, to packages/rest/src/meta-collection-routes.ts as registerMetaCollectionRoutes(this: MetaCollectionRouteHost, scope). The inner method builds scope: MetaRouteScope = { metadata, metaPath, isScoped, registerPerItemRoute } once in its head, and at the moved statements' position a host literal (routeManager by value, captured inside the umbrella's guarded swap; eight methods as late-bound closures; the static metaTypeSingular as a closure) plus one call. TransportScopedMetaRequest moves on, verbatim, from ui-routes.ts to the new module. One receiver token changes: RestServer.metaTypeSingular -> this.metaTypeSingular (ruling A). Claude-Session: https://claude.ai/code/session_01BVm1pAXVXQ3PjC42j1kPFf Co-authored-by: Claude <noreply@anthropic.com>
…name the /meta subset (#23050 slice 13a) The registrar list grows 13 -> 14. REST_SERVER_META_ROUTE_FILES names the files on it that hold a moved /meta group, whose registrations run inside the umbrella's guarded swap without being lexically inside it. Claude-Session: https://claude.ai/code/session_01BVm1pAXVXQ3PjC42j1kPFf Co-authored-by: Claude <noreply@anthropic.com>
…lice 13a) The registrar list's eight readers re-read their sums at length 14 (sites and floors unchanged, the moved alias's docblock floor moved from ui-routes.ts to the new module). The dogfood blind-spot census learns the named /meta subset: reachable = the umbrella's sites plus every site in REST_SERVER_META_ROUTE_FILES, so 70 / 19 / 51 holds, with a control that holds the subset against the module calls inside the inner method. check-route-envelope declares meta-collection-routes.ts at 0 / 0; the runtime list-projection parity test reads the list handler in its new file; three metadata_endpoints.json evidence paths and two checklist anchors name the module. Claude-Session: https://claude.ai/code/session_01BVm1pAXVXQ3PjC42j1kPFf Co-authored-by: Claude <noreply@anthropic.com>
…n routes (#23050 slice 13a) Claude-Session: https://claude.ai/code/session_01BVm1pAXVXQ3PjC42j1kPFf Co-authored-by: Claude <noreply@anthropic.com>
…3a-meta-collection
📓 Docs Drift CheckThis PR changes 2 package(s): 46 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 13 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 146 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 450166a5d2b32b7cca4ab57939cbb715fded4b19 && git checkout 450166a5d2b32b7cca4ab57939cbb715fded4b19
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin b9ac35cbfe60afcea88947ed4eaf8c50e3efc214 d6a423356c0a7d2a6f6a608332df7abc58a7a640 && git checkout -B drift-repro b9ac35cbfe60afcea88947ed4eaf8c50e3efc214 && git merge --no-ff d6a423356c0a7d2a6f6a608332df7abc58a7a640
node scripts/docs-audit/affected-docs.mjs --json b9ac35cbfe60afcea88947ed4eaf8c50e3efc214
|
…ed _migrate-stored elevation read (#23050 slice 13a) The POST /meta/_migrate-stored door's isSystem / manage_metadata check moved, unedited, from registerMetadataEndpointsInner to meta-collection-routes.ts#registerMetaCollectionRoutes. Row 50 gains that one anchor beside the inner method's, which still holds three reads. check-system-context-census refused the new file as file-without-a-row without it. Claude-Session: https://claude.ai/code/session_01BVm1pAXVXQ3PjC42j1kPFf Co-authored-by: Claude <noreply@anthropic.com>
席位核对 — ACCEPT ·
|
Part of #23050
Clause-②: no
Sub-slice 13a of the
rest-server.tssplit: the first three/metagroups. Groups G1 + G2 + G3 ofRestServer#registerMetadataEndpointsInner(base:5298–:5740, 443 lines) move, re-indented one level, to one new module,packages/rest/src/meta-collection-routes.ts. They are the type list (GET {metaPath}andGET {metaPath}/types, one handler on two paths), the whole-store maintenance family (GET /diagnostics,GET /_drafts,POST /_migrate-stored) and the per-type list (GET /:type): seven routes per base. This follows the slicing plan (os-dev-report6239704287, sub-slice 13a), the seat's ruling6239783526(Q1 A, Q2 A, Q3 A and the binding host rule) and static-receiver ruling A6205442867. The claim is6239807713.Nothing else moves:
dist/index.d.ts/index.d.ctsare byte-identical, and so are both bundles' 39-name export lists;rest-server.tsgoes from 9,086 to 8,681 lines. G4–G8, the umbrellaregisterMetadataEndpointsand its guarded swap, the inner head's four bindings, every handler body andmeta-item-read-gate.tsare untouched. #23050 stays open for 13b–13e.✅
check-system-context-censusis green (patch round 1,d6a423356). The plan did not listcontent/docs/permissions/system-context.mdxfor 13a, but the_migrate-storeddoor'sif (!ctx?.isSystem && !held.has('manage_metadata'))is an elevation read site, and it moved (baserest-server.ts:5547→meta-collection-routes.ts:452). At1e0153a68the census read[file-without-a-row] packages/rest/src/meta-collection-routes.ts holds 1 elevation read site(s) in 1 symbol(s) (registerMetaCollectionRoutes)(exit 1). Under the claim amendment6241851688, declared to the page's lane on #6023 as6241845161, row 50 (manage_metadatabypassed on metadata writes) gains one anchor,packages/rest/src/meta-collection-routes.ts#registerMetaCollectionRoutes, besiderest-server.ts#registerMetadataEndpointsInner. No other line of the page and none of the row's prose changed. The census now readsOK — 142 elevation read sites … over 158 anchors(exit 0; 157 before). The inner anchor stays valid, because three reads are still there: the per-itemDELETE(G5) andpublish/rollback(G6).The shape
Moved, at their position. In the inner method, right after
registerPerItemRoute's declaration, the head now buildsconst scope: MetaRouteScope = { metadata, metaPath, isScoped, registerPerItemRoute };once (head:5313, Q1 A). At the moved statements' old position it builds the host literalcollectionHostand callsregisterMetaCollectionRoutes.call(collectionHost, scope)(head:5324–:5335). Registration order is unchanged, with the literal segments still above/:type.The host,
MetaCollectionRouteHost: 9 members in first-read order (an AST walk of the moved range, TypeScript 6.0.3, identical on base and head):resolveProtocol(...a) => this.resolveProtocol(...a)translateMetaTypesResponserouteManagerregister, registration time)resolveExecCtxwalledCatalogRefusalresolveMetaWriteActorrefuseUnknownMetaListTypemetaListAnswerSourcesmetaTypeSingular(private static)(...a) => RestServer.metaTypeSingular(...a), typed(typeof RestServer)['metaTypeSingular']The body has no bare
this, nothis[...], nofunctionkeyword and no assignment to athismember.Host placement (binding). The literal is built inside
registerMetadataEndpointsInner, wherethis.routeManageris the umbrella's wrapping registrar for exactly the duration of the call. It is not built inregisterRoutes, the constructor, an instance cache or the umbrella above the swap. The module header and the comment above the literal say why. The guard ablation below is the runtime proof.The scope (Q1 A).
MetaRouteScopetypesmetadataasRestServer['config']['metadata']. The module opens with one destructuring line,const { metadata, metaPath, isScoped } = scope;, the three bindings it reads (noUnusedLocals/noUnusedParameters).registerPerItemRouteis handed over as the inner method's own closure; this module does not call it.The one changed token (ruling A). The per-type list's
RestServer.metaTypeSingular(req.params.type)(base:5719) isthis.metaTypeSingular(req.params.type)at module:624.Module-level names (the same walk, base vs head):
handleRouteErrorandsendFieldVisibilityFault(./error-response.js),refuseRepeatedQueryParams(./query-multiplicity.js),rethrowAuthzStoreUnavailable(@objectstack/core),metaReadGate(namespace,./meta-item-read-gate.js) andGetMetaItemsRequest(type,@objectstack/spec/api). Every one of them is still read inrest-server.ts, so no import line left it (tscnoUnusedLocalsexit 0).metaItemPackageBinding(on the package entry) andmayReadPendingDrafts(the analytics module imports it) are declared inrest-server.ts, stay there and are imported from it. Both were already exported, so no export was added anywhere.TransportScopedMetaRequest(Q2 A) moved verbatim fromui-routes.ts(base:54–:93) to the new module (:104–:143). The block extracts byte-identical on both sides (diffexit 0, sha256f10f65831fde621b…). It sits beside the newMetaRouteScopeblock.Proof
All runs went through
os-verify-lock, with every exit captured before any pipe. The base is8259ea03e, built before any edit. The head is4cb131087, and the merge head1e0153a68was measured againstorigin/mainb7f29ddfe.1. The moved text.
git show 8259ea03e:packages/rest/src/rest-server.ts | sed -n 5298,5740p, with one 4-space indent removed, was compared withmeta-collection-routes.ts:203–:645, the body after the destructuring line.diffexits 1 on exactly one line: base 422 of the range, the receiver token.this.metaTypeSingular(mapped back toRestServer.metaTypeSingular(,diffexits 0 over all 443 lines. Both sides are sha2567f562178bdc5c4c487f821ef0f13df8082ce613b2b3668390bbcc2bc8ca511f7.2.
.d.tsand exports.index.d.tsandindex.d.ctsare sha2561f0f455d24836d47de60716233f1bd74d1738c04046974019264b17b5261bbe8at base, at head, atorigin/main(that leg put main'srest-server.ts,ui-routes.tsandform-routes.tsinto the merged tree under a trap, without the new module) and at the merge head.cmpexits 0 on every pair.registerMetaCollectionRouteshits 2 in each ofindex.js/index.cjs, and 0 at base and on the main leg.b3246be6a1718700…, on every leg.3. Full-boot legs (slice 12's method), 20 configurations:
enableDiscovery: false;enableOpenApi: false; both off under scoped-optional;enableSearch: falseandenableUi: falseunder scoped-optional;enableCrud: falseunder scoped-optional;crud.operations{ list: false, delete: false }under scoped-optional; all five operations off;crud.dataPrefix: '/objects'under scoped-optional;/metaswitches, all under scoped-optional:metadata.endpoints.types,.items,.itemand.maintenanceeach false; all four false;metadata.prefix: '/metadata';api.enableMetadata: false.The route counts are 75 / 150 / 75 / 75 / 73 / 73 / 142 / 148 / 148 / 138 / 144 / 69 / 150 (slice 12's figures), then 146 / 148 / 126 / 144 / 114 / 150 / 112. In the source leg,
routes.json(getRoutes(), functions as arity),calls.json(ordered server registrations with arity) andhandlers.json(a whitespace-free sha256 of every server-visible handler) are byte-identical in all 20 configs, on four trees: base, head, main and merge head. Their concatenation is sha25608103834505ba94cd81c227c14e1c2b8dd21eb6dbd1d894d7ba7557a9f2db9baon all four. A second base run was identical. In the bundle leg (the same dump against the builtdist/index.js), routes and calls are identical. The handler text differs only at the 19/metaguard wrappers per base, and only by esbuild renumbering the@objectstack/coreimport alias inside the wrapper. The new module comes earlier in bundle order and now holds the bare name, sorest-server.ts'rethrowAuthzStoreUnavailableis bundled asrethrowAuthzStoreUnavailable2, and a later module's…2becomes…3. With that renumbering normalized, all 150 registrations are identical. The head bundle's identifier set gains exactlycollectionHost,registerMetaCollectionRoutesandrethrowAuthzStoreUnavailable3, and loses none.4. The inner-registration leg (the plan's
proof_method). Slice 12's digest is blind to/meta: every server-visible/metahandler is the umbrella's one wrapper, so the full-boot legs cannot see a moved body. Each config therefore also builds aRestServerwith a recordingrouteManagerand callsregisterMetadataEndpointsInner(basePath)directly for/api/v1and/api/v1/environments/:environmentId. That gives 688 recorded registrations over the 20 configs (19 per base where every switch is on). Each is digested whitespace-free, with the receiver token mapped back, together with its method, path, metadata and arity.2ab528c22577ded382806107cd8e484de7d525d92e7148685af9533a9bf75bdc, and a second base run gave the same.__vite_ssr_import_N__, whose number shifts in every later handler ofrest-server.tsbecause that file gained one import. Raw, this alone moves all 38 digests per config, G4–G8 included. Only the number is erased; the imported name is kept.(0, ns.f)call spelling of the two helpers the module now imports fromrest-server.ts:metaItemPackageBindingandmayReadPendingDrafts.dist/index.js): 688 of 688 identical, base vs head and main vs merge head. The digest-list sha256 is4495c6eb055d3f27e9852d172f466ae28e2596a3b72bd036159013f86ad3b862. The normalizations are esbuild's class-internal receiver_RestServer.and the alias renumbering above._draftshandler throughscripts/ablation-replace.mjs:'protocol.listDrafts() is not available in this kernel'gained a!(anchor 1 → 0, blob3e38c8ff50bf→7ae2b239f2e1).GET …/_drafts, on both bases, in the 18 configs that mount it: 36 of 688, and nowhere else.routes/calls/handlersstayed byte-identical. That is the blind spot the inner leg exists to cover.HEADandgit diff HEADis empty.5. The guard ablation. One literal anchor ran from the umbrella's
const realRouteManager = this.routeManager;to the host'srouteManager: this.routeManager,(blob43a35f016343→8bf281899dfe; the on-disk marker count during the run was 2). The mutation stashes the real manager above the swap, and the host reads it: the plan's wrong placement.a7efce0b390ea680…): an anonymous request at every moved route on both bases — GET METAPATH, METAPATH/types, /diagnostics, /_drafts, POST /_migrate-stored, GET /:type — answers401 UNAUTHENTICATEDwith zero protocol calls, 12 of 12.GETMETAPATH,/types,/diagnosticsand/:typeanswer200after a protocol read./_draftsandPOST /_migrate-storedanswer403 FORBIDDENfrom their own capability checks, not the anonymous-deny.401.Test Files 2 failed | 1 passed (3),Tests 14 failed | 86 passed (100).rest-meta-auth.test.tsis red twice ("401s an anonymous caller", "still 401s an anonymous /meta/object";expected 200 to be 401).meta-type-read-capability.test.tsis red 12 times: the/:typeshape for datasource, datasources, external_catalog and external_catalogs × author / member / other-grant (expected { shape: '/:type', status: 200, … } to deeply equal { shape: '/:type', status: 403, … }).meta-type-write-capability.test.tsstays green, because no moved route is a non-GET/:type…door./types,/diagnosticsand/_draftshave no standing anonymous pin; the one-off probe above is the evidence for them.HEADandgit diff HEADis empty. No permanent test was added.6. The late-binding ablation (one-off vitest file, deleted). The setup is slices 11 and 12's: the seven methods and the static are planted on the server before
registerRoutes(), the seven moved routes are driven, everything is planted again after registration, and the routes are driven again.MEASURElines to base): every route answers200both times. After the second planting all eight members are reached aslate, withearly calls after re-plant: 0.Tests 1 passed (1).resolveProtocol: this.resolveProtocol.bind(this)(blob43a35f016343→8e763954d37d) givesearly calls after re-plant: 12(sixearly:resolveProtocoland their six protocol reads) andAssertionError: expected [ 'early:resolveProtocol', …(11) ] to deeply equal [],Tests 1 failed (1). Restored: the blob equalsHEADandgit diff HEADis empty.Readers re-pointed (sums unchanged, no gate loosened)
rest-server-registrar-files.tsgainsmeta-collection-routes.ts(length 13 → 14). It also exportsREST_SERVER_META_ROUTE_FILES(Q3 A), the list's named subset of the files that hold a moved/metagroup, today['meta-collection-routes.ts']. Subset entries are named file by file, never by a naming convention.execctx-consumer-census.test.ts_drafts,_migrate-stored,/:type) are all locally caught, as before, so the split stays 16 / 46. The four new mentions are the seam: the forwarder, two, and the interface member, two.rest-server.tsgoes 56 → 55. There are 14 forwarders, (14 − 1) + 3 − 2, so neither map gains an entrymeta-draft-read-door-census.test.ts_drafts' two switches and the list's?preview=draftmoved. Keys name routes, not files, so no ledger row changedrest-server-query-number-census.test.tsrest-server-canonical-query-ast.test.ts(repo)meta-collection-routes.ts: 0. The list'squerykey is mid-line in the chain's options literal, whichquerySlotsdoes not readrest-server-docblock-position.test.tsui-routes.ts4 → 3 (the alias's block moved on).meta-collection-routes.ts5: header, alias,MetaRouteScope, host and function.rest-server.tskeeps its 163ui-view-route-identity/-tenancymeasurement teststhis.enforceAuth(60,this.resolveExecCtx(75 → 76authz-conformance.test.tsauthz-probe-blind-spot.census.tsREST_SERVER_META_ROUTE_FILES(13 + 6). New controls aremeta-collection-routes.ts: this.routeManager.register(6, and/meta subset ↔ .call( inside registerMetadataEndpointsInner, measured over the inner method's own extent (1) and recorded ASREST_SERVER_META_ROUTE_FILES.length, so the subset and the module calls can only move together.this.routeManager.register(stays 63 = 6 + 9 + 5 + 7 + 8 + 1 + 6 + 4 + 1 + 1 + 1 + 2 + 6 + 6.registerPerItemRoute(stays 8 andenforceAuthstays 112, because neither the moved text nor the seam spells the termReaders outside the list:
scripts/check-route-envelope.mjs(domain:spectarget table; declared on [PM seat] domain:spec — ⏳ vacant #6017,6239822550).meta-collection-routes.tsis declareddialectOnlywith ratchet [tracking] Envelope-position convergence line for packages/rest's flat dialect — the live ratchet owner #9559, atstringError 0/siblingCode 0(measured).rest-server.tsstays 8 / 4, with "8 → 8" and "4 → 4" notes. The sums are unchanged at 39 and 54. Its output differs from base only by the new row: 24 → 25 modules audited, 14 → 15 ratcheted.packages/spec/liveness/metadata_endpoints.json(declared on [PM seat] domain:spec — ⏳ vacant #6017,6239822550). Three evidence paths change,rest-server.ts#registerMetadataEndpointsInner→meta-collection-routes.ts#registerMetaCollectionRoutes: theendpoints.types,endpoints.itemsandendpoints.maintenancerows. Quoted code, producers, verdicts and statuses are unchanged.prefixstays, becausemetaPathis built in the inner head.check:livenessreads945 pointer(s) … 945 naming a symboland735 … pair(s) asked, 734 anchored, 1 exempton base and head.docs/qa/platform-checklist/areas/(declared on [PM seat] domain:devx @ objectstack — ⏳ vacant #6023,6239832477):api-backend.rest-metadata-config-contract,+ packages/rest/src/meta-collection-routes.ts#registerMetaCollectionRoutes (the types, items and maintenance endpoint gates)is added beside the inner anchor (slice 7's split form). The inner anchor's parenthetical goes from "the four endpoint gates" to "the item endpoint gate", the one gate still in that method. That wording change goes slightly past the declaration's "added beside", and it is named here so the devx seat can see it.studio-authoring.metadata-diagnostics-sweep:rest-server.ts#route(it pointed at an unrelated loop variable) →meta-collection-routes.ts#registerMetaCollectionRoutes.check:platform-checklist: 853/863 → 854/864 anchors found, and cited sources go 401 → 402.content/docs/permissions/system-context.mdx(patch round 1; claim amendment6241851688, declared on [PM seat] domain:devx @ objectstack — ⏳ vacant #6023 as6241845161). Row 50 gainspackages/rest/src/meta-collection-routes.ts#registerMetaCollectionRoutesbeside the inner anchor, in the row's existing spelling. The row's prose is unchanged.packages/runtime/src/domains/meta-list-projection-parity.test.ts(a loud cross-package reader). The list derivation readsMETA_COLLECTION_ROUTES_SOURCE; the item, tree and layers derivations still readrest-server.ts.check:cross-package-test-inputsexits 0.TransportScopedMetaRequestreaders (Q2 A).ui-routes.ts: the block leaves, an import is added, and a pointer comment plus the header sentence are re-pointed.form-routes.ts: the import and its header sentence.rest-server.ts: the import, and slice 10's pointer comment.meta-item-read-gate.tsis not touched.Red before the re-points, each measured with the readers at their base text:
3f5191027:localreadTest Files 3 failed | 290 passed (293),Tests 9 failed | 6013 passed | 326 skipped (6348): the execctx census (expected 59 to be 62), the draft census (expected [ …(5) ] to deeply equal [ …(8) ]) and theui-routes.tsdocblock floor (expected 3 to be greater than or equal to 4).Tests 2 failed | 106 passed (108):expected 64 to be 70andthis.routeManager.register(57 vs 63.Tests 1 failed | 738 passed (739):GET ${metaPath}/:type in …/rest-server.ts: expected false to be true.check:route-envelopeexited 1:meta-collection-routes.ts NOT DECLARED.repostayed5 passed, because the moved groups carry noquery:slot.9a2ba1355(the list grown, the readers not yet re-pointed):Test Files 6 failed (6),Tests 8 failed | 116 passed (124): the length pins (to have a length of 13 but got 14), theui-routes.tsfloor and the unfloored module.reporeadTests 2 failed | 260 passed | 14 skipped (276).Tests 3 failed | 105 passed (108), includingexpected 13 to be 19. That is the false reachable reading the Q3 rule exists to prevent.5a281fe51, then the merge head).Readers examined and not re-pointed
registerPerItemRoute's docblock still describe the families, the order and the switch correctly, and editing a class member's docblock would move the published.d.ts.meta-list-projection-parity.test.tsmoved with its handler and is still true.data-action-routes.ts'{@link TransportScopedMetaRequest}is prose that names no file.private registerMetadataEndpoints(and its dead-probe control are unaffected, because the umbrella stays.scripts/adr-anchors/packages__rest__src__rest-server.ts.jsoncites nothing in G1–G3.docs/qa/platform-checklist/FOLLOW-UPS.md:613(E1, prose) is optional per the plan and outside the claim's surface.Changesets
.changeset/23050-s13a-meta-collection-routes-move.mdis a@objectstack/restpatch (Clause-②: no, move-only). The shippedindex.js/index.cjsbytes change (the marker above); the declarations and exports do not..changeset/23050-s13a-meta-collection-liveness-citations.mdis a@objectstack/specpatch (Clause-②: no), becauseliveness/ships in that package'sfiles[].skip-changesetdoes not apply.Acceptance notes
system-context.mdxrow 50 gained its one anchor in patch round 1 (d6a423356). 13b–13e each add their module to the same row, as the plan already lists.ui-routes.ts' "52 sites" comment andemail-routes.ts' double-mount header.Gates and tests
The final head is
1e0153a68, one merge oforigin/mainb7f29ddfe(#24208, #24209, #24212). Those three touch none of this diff's files (git diff --quietexit 0 over the overlap), andrest-server.ts,ui-routes.tsandform-routes.tsare byte-identical across8259ea03e..b7f29ddfe. Patch round 1 addsd6a423356, one line ofcontent/docs/permissions/system-context.mdx. That page is no package's build input and no test reads it (two test files mention it in comments only), so no proof leg moves and the suites below stand at1e0153a68. The gate union below was re-run atd6a423356.pnpm turbo run build --filter=@objectstack/rest... --filter=@objectstack/dogfood... --filter=@objectstack/runtime... --concurrency=2exited 0 at base (Tasks: 66 successful, 66 total). After the merge, the five packages the merge touched were rebuilt (pnpm --workspace-concurrency=2 --filter …metadata-protocol --filter …platform-objects --filter …runtime --filter …cli --filter …rest build, exit 0). The eight workspace packages with nodist(client-react,embedder-openai,knowledge-memory,knowledge-ragflow,organizations,service-cluster-redis,service-knowledge,studio) were built for the dist readers (exit 0).pnpm --filter @objectstack/rest typecheckexits 0:check:test-typecheck: OK … 0 file(s) / 0 error(s).@objectstack/rest.local:Test Files 294 passed (294),Tests 6027 passed | 326 skipped (6353). This includesmeta-route-registration-order.test.tsandrest-config-mount-table.pin.test.ts.repo(itstest:repo):Test Files 5 passed (5),Tests 262 passed | 14 skipped (276).authz-probe-blind-spot.test.ts,authz-conformance.test.ts):Test Files 2 passed (2),Tests 108 passed (108). The dogfood shards skip on PRs and in the queue, so this local run is the evidence.packages/speclocal,scripts/liveness/):Test Files 10 passed (10),Tests 269 passed (269).test:repo.@objectstack/core:Tests 86 passed (86).@objectstack/runtime:Test Files 3 passed (3),Tests 808 passed (808);meta-list-projection-parity.test.tsis one of the three.@objectstack/spec:Test Files 67 passed (67),Tests 1115 passed (1115).pnpm exec eslint --no-inline-configover the 16 changed.ts/.mjsfiles exits 0, with no output. The repo-widepnpm lintbelongs to CI.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths) atd6a423356derives 118 commands; its stderr names the commit, and the--repoassertion holds. The change set is 22 paths vs merge baseb7f29ddfe, 1,442 changed lines (+921 / −521).pnpm turbo run build --concurrency=2ran first (Tasks: 77 successful, 77 total), so no dist reader answered exit 3.1e0153a68,pnpm check:dual-build-cjs-loadshad first answered exit 3 (nodistfor eight packages) and exited 0 once they were built. Atd6a423356it exits 0 on the whole-workspace build.node scripts/check-system-context-census.mjsexits 0 (… over 158 anchors); it exited 1 at1e0153a68, before row 50's anchor.check-affected-docs,check:docs,check:doc-anchors,check:doc-authoringand the othercontent/docsfamilies exit 0.--ran:Run reconciliation — 118 derived, 118 run, 0 NOT-MEASURED, 0 UNRUN., exit 0. The 24 beyond round 0's 94 are the families the page path derives.check:route-envelopeexit 0 (25 route module(s) audited: 9 conformant, 15 ratcheted, 1 exempt);check:livenessexit 0;check:platform-checklistexit 0;node scripts/check-platform-checklist.mjs --changed-from origin/main(an exported type moved) exit 0,15 anchor(s) judged, 0 lost;check:cross-package-test-inputsexit 0;check:pm-dispatch-gatesexit 0;check:nul-bytesexit 0.check:dev-prereqsandcheck:skill-frame-freshness(local-only families). This diff touches nopackages/specbuild input (liveness/ships as files) and no four-axis frame file.Commits:
3f5191027, the move;9a2ba1355, the list and the/metasubset;5a281fe51, the re-points;4cb131087, the changesets;1e0153a68, the merge;d6a423356, row 50's anchor (patch round 1).Generated by Claude Code