Repository navigation
Commit 646303e
Part of #23050
Clause-②: no
Sub-slice **13b** of the `rest-server.ts` split: the fourth `/meta`
group. Group G4 of `RestServer#registerMetadataEndpointsInner` is ONE
statement, `if (metadata.endpoints.item !== false)`, of 891 lines (base
`rest-server.ts:5336`–`:6226` at `6e43b7bc3`). It moves whole, its
switch included and re-indented one level, to a new module,
`packages/rest/src/meta-item-read-routes.ts`, as
`registerMetaItemReadRoutes`. The group registers four routes per base:
the reverse reference sweep (`GET {metaPath}/:type/:name/references`),
the layered read (`GET {metaPath}/:type/:name/layers`), the book tree
(`GET {metaPath}/book/:name/tree`) and the item read (`GET
{metaPath}/:type/:name`).
This follows the slicing plan (`os-dev-report` `6239704287`, sub-slice
13b), seat 1's ruling on it `6239783526` (quoted below), static-receiver
ruling A `6205442867`, 13a's `handover_13b` list (report `6241822317`)
and the claim `6243326550`. PR #24224 (13a, `df000d4b2`) 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 and
`origin/main` vs merge 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;
- four tokens of the moved body changed, the ruled receivers (below).
`rest-server.ts` goes from 8,699 to 7,733 lines on the merged tree.
G5–G8, the umbrella `registerMetadataEndpoints` and its guarded swap,
the inner head's bindings, every handler body,
`fetchCurrentMetaDocument` and the rest of the class head,
`meta-item-read-gate.ts`, `docs/adr/**` and `packages/spec/src/**` are
untouched. #23050 stays open for 13c–13e.
## 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).
> - **Q2, A.** 13a's `meta-collection-routes.ts` hosts `MetaRouteScope`
and takes `TransportScopedMetaRequest` from `ui-routes.ts`, re-pointing
its readers in that PR. ⛔ Not `meta-item-read-gate.ts` while #24208 is
open.
> - **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`).
> - **Q5, A.** G4 (891 lines, one `if`) moves whole in 13b, with its
switch. Slice 1 moved 1,181 lines. The fallback, if the review budget
binds, is B: a move-only split called inside the remaining brace. ⛔ C
(re-shaping the registrations) is not a move and not this card's.
> - **Q6.** A for the two body-only 13b helpers
(`notImplementedRefusalAnswer`, `anonymousFormIntakeFingerprint`): they
move with the body. B for `refuseNonAuthoringCaller` (13d): it stays and
is exported, because its callee `mayReadAuthoringTrail` is a docs anchor
(`system-context.mdx:108`). Two-home helpers (`sendMetaItemAbsent`,
`stampAnonymousFormIntakeWarnings`) stay and gain `export`, as in slices
1 and 2.
>
> **Binding on every sub-slice (from the plan's measurements):**
> - **Hosts are built inside `registerMetadataEndpointsInner`**, at the
position of the statements they replace, with `routeManager` passed by
value. ⛔ Never in `registerRoutes`, the constructor, an instance cache
or the umbrella above the swap: those capture the real manager, and the
moved routes would mount outside the anonymous-deny gate (#3963) and the
type-level admissions (#21087, #21124).
> - Each sub-slice proves this with the guard ablation in the plan: an
anonymous request at every moved route gets `401` on head, and the
ablation does not.
> - **The proof gains an inner-registration leg.** Slice 12's handler
digest is blind to `/meta`, because every route's server-visible handler
is the same guard wrapper. So each sub-slice digests the inner handlers
through a recording `routeManager` and a direct
`registerMetadataEndpointsInner(basePath)` call per base, with the ruled
receiver tokens mapped back. A one-character positive control must move
exactly that route's inner digest.
> - The full-boot legs stay: `getRoutes()`, ordered registrations,
`.d.ts`/`.d.cts`, and the 39-name export list.
> - The config matrix is slice 12's 13 configs plus the `/meta` switches
the plan names.
> - **Readers move in the same PR**, loud and silent alike, as the plan
lists per sub-slice. Cross-lane edits are declared on #6017 (spec:
liveness and gate tables) and #6023 (devx: checklist) before the PR. The
`system-context.mdx` rows change with the sub-slice that moves their
code.
Q5 A is taken: the statement moves whole, and fallback B was not needed.
## The shape
**Moved, at its position.** In the inner method, right after 13a's
`registerMetaCollectionRoutes.call(collectionHost, scope);`, the head
now builds the host literal `itemReadHost` and calls
`registerMetaItemReadRoutes.call(itemReadHost, scope)` with the ONE
existing `scope` (no second one is built). Registration order is
unchanged: after the per-type list, above the item writes, with
`/references` and `/layers` still above the item read.
**The host, `MetaItemReadRouteHost`: 16 members in first-read order** (a
symbol-resolved walk of G4 with the TypeScript 6.0.3 compiler API, on
base and head; H1 of the dispatch holds: G4 opened at `:5345`, its range
ran `:5336`–`:6226`):
| member | reads | handed over as |
|---|---:|---|
| `routeManager` | 4 (all `register`, registration time) | **by value,
captured inside the inner method** |
| `resolveProtocol` | 4 | closure `(...a) => this.resolveProtocol(...a)`
|
| `metaTypeSingular` (private static) | 2 | closure `(...a) =>
RestServer.metaTypeSingular(...a)`, typed `(typeof
RestServer)['metaTypeSingular']` |
| `resolveObjectMasker` | 2 | closure |
| `serveMetaItemLayered` | 2 | closure |
| `metaReadAudienceSources` | 1 | closure |
| `extractLocale` | 2 | closure |
| `resolveExecCtx` | 1 | closure, spelled exactly as the execctx
census's forwarder |
| `resolveI18nService` | 1 | closure |
| `metaItemReadGate` | 1 | closure |
| `maskObjectDocument` | 1 | closure |
| `anonymousFormIntakeWarnings` | 1 | closure |
| `translateMetaEnvelope` | 2 | closure |
| `STORED_VERSION_DOOR_POLICY` (private static readonly field) | 1 |
**by value** (Q4 A), typed `(typeof
RestServer)['STORED_VERSION_DOOR_POLICY']` |
| `metaItemAnswerSources` | 1 | closure |
| `sendMetaReadRefusal` (private static) | 1 | closure `(...a) =>
RestServer.sendMetaReadRefusal(...a)` |
The body has no bare `this`, no `this[...]`, no `function` keyword and
no assignment to a `this` member. It reads no instance FIELD at request
time, so no member is a getter. `STORED_VERSION_DOOR_POLICY` is the
first static FIELD any host carries. It is assigned once, at class
evaluation, from `meta-item-read-gate.ts`' constant of the same name,
and never reassigned, so the value captured is the object every read of
it returned.
**Host placement (binding).** The literal is built inside
`registerMetadataEndpointsInner`, where `this.routeManager` is the
umbrella's wrapping registrar for exactly the duration of the call. It
is not built in `registerRoutes`, 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).** The module opens with `const { metadata, metaPath,
isScoped } = scope;`, the three bindings it reads: `metadata` for the
switch and `enableCache`, `metaPath`, `isScoped`. `registerPerItemRoute`
is not called by this module.
**The four changed tokens (ruling A, named in the claim).** At base
`rest-server.ts` `:5474` and `:5623`, the layered read and the item read
each call `RestServer.metaTypeSingular(req.params.type)`. In the item
read's stored-version branch, `:6128` reads
`RestServer.STORED_VERSION_DOOR_POLICY` and `:6136` calls
`RestServer.sendMetaReadRefusal(res, answer.refusal)`. Each is now
`this.…` through the host (module `:321`, `:470`, `:975`, `:983`).
Neither static method reads anything but its arguments, so the receiver
is the whole difference.
**Module-level names** (the same walk, base vs head):
- **Moved with the body (Q6 A):** `notImplementedRefusalAnswer` (base
`:1560`–`:1673`, with its 106-line docblock) and
`anonymousFormIntakeFingerprint` (base `:1969`–`:1972`). They are
byte-identical at the module's end, each under a pointer comment, and a
pointer comment is left at each old position. No other file names either
one.
- **Gained `export` (Q6, two homes):** `sendMetaItemAbsent` (also read
by the class's `sendMetaReadRefusal` and the `/diff` door) and
`stampAnonymousFormIntakeWarnings` (also read by the class head). The
module imports both from `./rest-server.js`.
- **Already exported, imported from `./rest-server.js`:**
`META_ITEM_REFERENCES_PARAMS` (the meta door tests import it from
there), `metaItemPackageBinding` and `mayReadPendingDrafts`. All five
names are read only at request time, so the two modules importing each
other cannot see one uninitialised.
- **Imports that left `rest-server.ts`** (read only by the moved code,
so `noUnusedLocals` would refuse them; a pointer comment is left at
each): `foldVisibilityFingerprintIntoEtag`, `normalizeIfNoneMatch`,
`resolveObjectSchemaRuntimeView` and `objectFieldVisibilityFingerprint`
(`@objectstack/metadata-core`), `GetMetaItemCachedRequest`
(`@objectstack/spec/api`), the local `META_ITEM_LAYERS_PARAMS` import
(`./meta-item-read-gate.js`; the re-export that names it stays), and
`boundedDeclaredRefusalMessage`, `declaredHttpStatus` and
`thrownAnswerIsBareNotFound` (`./error-response.js`). The plan listed
six of these nine. The other three left because the two helpers moved:
`objectFieldVisibilityFingerprint` is read by the item read and by
`anonymousFormIntakeFingerprint`, and the two `error-response.js` names
only by `notImplementedRefusalAnswer`.
- **Unchanged provenance:** every other name is imported from the module
`rest-server.ts` imports it from. `MetaRouteScope` and
`TransportScopedMetaRequest` come from `./meta-collection-routes.js`.
## Proof
All runs went through `os-verify-lock`, with every exit captured before
any pipe, unless noted. The base is `6e43b7bc3`. The head is
`7b562222d`, and the merge head `083b60f20` (one merge of `origin/main`
`2bcd406a2`) was measured against `origin/main` itself. Base and main
were measured in a read-only comparison worktree at each commit.
**1. The moved text.** `git show
6e43b7b:packages/rest/src/rest-server.ts | sed -n 5336,6226p`, with
one 4-space indent removed, was compared with `meta-item-read-routes.ts`
`:183`–`:1073`, the body after the destructuring line.
- The raw `diff` exits 1 on exactly four lines: the four receiver
tokens.
- With
`this.(metaTypeSingular|STORED_VERSION_DOOR_POLICY|sendMetaReadRefusal)`
mapped back to `RestServer.…`, `diff` exits 0 over all 891 lines. Both
sides are sha256
`c9ac1ae545c47bc93ab05e8aa18f3b6493eea7afafa84f6b480c460e3de3327d`.
- Every non-empty line of the range carries the 8-space indent, no line
has trailing whitespace, and every odd-backtick line is a comment.
- The two helpers: base `:1560`–`:1673` vs module `:1079`–`:1192` (114
lines) and base `:1969`–`:1972` vs module `:1196`–`:1199`, `diff` exit 0
on both.
**2. `.d.ts` and exports.** `index.d.ts` and `index.d.cts` are sha256
`1f0f455d24836d47de60716233f1bd74d1738c04046974019264b17b5261bbe8` at
base and at head. At `origin/main` `2bcd406a2` and at the merge head
they are both
`caa84a36073f1dd5a79f66d3bc71b877e3a60806d1f380d39b310987fb15d255`
(main's #24223 edited a class-head docblock). `cmp` exits 0 on every
pair.
- The head-only marker `registerMetaItemReadRoutes` hits 2 in each of
`index.js` / `index.cjs`, and 0 at base and at main.
- Both bundles load with 39 exports and one sorted name list, sha256
`b3246be6a1718700…`, on every leg.
**3. Full-boot legs (slice 12's method), 20 configurations:** slice 12's
thirteen, then the `/meta` switches under scoped-optional:
`metadata.endpoints.types`, `.items`, `.item` and `.maintenance` each
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, then 146 / 148 / 126 /
144 / 114 / 150 / 112 (13a's figures).
- **Source leg** (a `tsx` boot of `src/rest-server.ts`): `routes.json`
(`getRoutes()`, functions as arity), `calls.json` (ordered server
registrations with arity) and `handlers.json` (a whitespace-free sha256
of every server-visible handler) are byte-identical in all 20 configs:
60 of 60 files, base vs head and main vs merge head. The concatenation
is sha256 `bd4f6685175a61ec…` on all four trees.
- **Bundle leg** (the same dump against the built `dist/index.js`): 60
of 60 identical, concatenation `20103136b32ff534…` on all four, 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 head gains exactly `itemReadHost`,
`registerMetaItemReadRoutes` and three renumbered aliases
(`rethrowAuthzStoreUnavailable4`, `ObjectSchemaMaskEvaluationError3`,
`relateObjectSchemaMaskPosture3`), and loses none. Those three names are
the ones normalized.
**4. The inner-registration leg (the plan's `proof_method`).** 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. Each is digested whitespace-free, with the four receiver
tokens mapped back, together with its method, path, metadata and arity.
- **Source leg:** 688 of 688 identical, base vs head and main vs merge
head; the digest-list sha256 is
`4f306a2a19ffdd181b36b43e4d8b49d0844dc396c50a3144e8221aeab48b4511` on
all four. Unnormalized, exactly 72 digests differ: the `/layers` and
item routes on both bases in the 18 configs that mount them, the
receiver tokens. This leg runs through `tsx`, whose per-file transform
keeps import names as written, so 13a's vitest SSR renumbering does not
arise and is not normalized.
- **Bundle leg:** 688 of 688 identical under the same three alias names;
the digest-list sha256 is
`8c47816fb3991d34bf792d04aab002f8e2c945de2e736ec93a93502c27ca3b7b` on
all four.
- **Positive control.** One character was added in the moved book-tree
handler through `scripts/ablation-replace.mjs`:
`META_QUERY_ARITY_DOORS['book-tree']` became `['book-tree!']` (anchor 1
→ 0, blob `5f398b048095` → `5b5bea5dcfbd`). The inner digests moved at
exactly `GET …/book/:name/tree`, on both bases, in the 18 configs that
mount it: 36 of 688, and nowhere else. All 20 configs' full-boot
`routes` / `calls` / `handlers` stayed byte-identical: the blind spot
the inner leg covers. Restored: the blob equals `HEAD` and `git diff
HEAD` is empty.
**5. The guard ablation** (13a's recipe). One literal multi-line anchor
ran from the umbrella's `const realRouteManager = this.routeManager;`
through `itemReadHost`'s `routeManager: this.routeManager,` (blob
`8f0876b93743` → `f2e20e0ca141`). The mutation stashes the real manager
above the swap and has `itemReadHost` read it: the plan's wrong
placement.
- **Head** (identical to base): an anonymous request at each moved route
on both bases. `/references`, `/layers` and the item read answer `401
UNAUTHENTICATED` with zero protocol calls (6 of 6). The book tree is the
declared anonymous public-audience read (#3963): the umbrella lets it
through to the handler's own audience gate, which answers `401` "This
documentation requires sign-in". All 8 server-visible handlers are the
umbrella's wrapper.
- **Ablation:** `/references` answers `200` and the item read `200`,
each after a protocol read; `/layers` answers `404 RESOURCE_NOT_FOUND`
after a protocol read. Not one of the six is `401`, and none of the 8
handlers is the wrapper.
- **Standing pins under the ablation:** `Test Files 1 failed | 2 passed
(3)`, `Tests 19 failed | 81 passed (100)`.
`meta-type-read-capability.test.ts` is red 19 times (the
`/:type/:name/layers` shape and the item read's shapes for the
datasource family × member / author / other-grant, the
existing-vs-absent byte identity, and the admin-door parity for three
bearers). `rest-meta-auth.test.ts` stays green (its probes are routes
13b does not move), and `meta-type-write-capability.test.ts` stays green
(no moved non-GET door).
- Restored: the blob equals `HEAD` and `git diff HEAD` is empty. No
permanent test was added.
**6. The late-binding ablation** (one-off script, deleted). The 12
methods are planted on the server and the 2 static methods on the class
before `registerRoutes()`, as recorders that delegate to the originals.
Ten request shapes are driven over the four moved routes
(`?state=draft`, `?layers=true`, a view, an app, a doc and a masked
object posture among them). Then everything is planted again and the
shapes are driven again.
- **Head** (byte-identical `MEASURE` lines to base): all 14 closure
members are reached before and after the re-plant, with `early calls
after re-plant: 0`.
- **Ablation:** `metaItemReadGate: this.metaItemReadGate.bind(this)`
(blob `8f0876b93743` → `85cc12e79126`) gives `early calls after
re-plant: 3 ["early:metaItemReadGate"]` 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-read-routes.ts` in
`REST_SERVER_REGISTRAR_FILES` (length 14 → 15) and in the named `/meta`
subset `REST_SERVER_META_ROUTE_FILES` (1 → 2). H2 holds: the dogfood
control counts `.call(` inside the inner method, now 2, so the subset
and the call moved together.
| reader | sum over the list | change |
|---|---|---|
| `execctx-consumer-census.test.ts` | 62 sites = 12 + 9 + 5 + 7 + 8 + 1
+ 5 + 2 + 1 + 1 + 1 + 0 + 6 + 3 + 1; mentions 133 → 137 | The item
read's site is locally caught on its continuation line, as before, so
the split stays 16 / 46, and §7's and §8's four continuation sites are
found again. `rest-server.ts` stays at 55 mentions (the site and one
prose mention out, one forwarder's two in); the module carries 4.
Fifteen forwarders: (15 − 1) + 3 − 2 |
| `meta-draft-read-door-census.test.ts` | 8 = 1 + 0 + 0 + 0 + 0 + 2 + 0
×7 + 3 + 2 | The item read's `?state=draft` and `?preview=draft` moved.
Keys name routes, so no ledger row changed |
| `rest-server-query-number-census.test.ts` | 9 = 8 + 1 + 0 ×13 | — |
| `rest-server-canonical-query-ast.test.ts` (`repo`) | 4 = 0 + 3 + 0 ×10
+ 1 + 0 + 0 | Floor `meta-item-read-routes.ts: 0` |
| `rest-server-docblock-position.test.ts` | floors sum 54 → 59 | The
module carries 5: the header, the host interface, the function and the
two moved helpers' blocks. `rest-server.ts` 163 → 161 blocks, floor 100
|
| `ui-view-route-identity` / `-tenancy` measurement tests |
`this.enforceAuth(` 60, `this.resolveExecCtx(` 76 → 77 | +1 for the
forwarder. The ownership guard is still 1 call site and 1 forwarder |
| dogfood `authz-conformance.test.ts` | 0 tripwire hits over fifteen
files | Length 14 → 15 |
| dogfood `authz-probe-blind-spot.census.ts` | 70 / 19 / 51 unchanged |
Reachable holds by 13a's Q3 rule, with no rule change. New control
`meta-item-read-routes.ts: this.routeManager.register(` 4; `/meta subset
↔ .call(` 2. `this.routeManager.register(` stays 63 = 2 + 9 + 5 + 7 + 8
+ 1 + 6 + 4 + 1 + 1 + 1 + 2 + 6 + 6 + 4; `registerPerItemRoute(` 8 and
`enforceAuth` 112 unchanged |
Readers outside the list:
- **`scripts/check-route-envelope.mjs`** (`MODULES` only; declared on
#6017, `6243336904`). `meta-item-read-routes.ts` is declared
`dialectOnly` with ratchet #9559 at `stringError 1` / `siblingCode 1`:
the `/layers` door's 501 `{ error, code }` body. `rest-server.ts` goes 8
→ 7 and 4 → 3, each with a "NOT progress — the same MOVE" note. The sums
are unchanged at 39 and 54. Output: 25 → 26 modules audited, 15 → 16
ratcheted; `--self-test` exit 0.
- **`packages/runtime/src/domains/meta-list-projection-parity.test.ts`**
(a loud cross-package reader). ⚠️ **The plan's 13b reader list missed
it** (H3): 13a left its item, tree and layers derivations reading
`rest-server.ts`, and at the move commit it reads `GET
${metaPath}/:type/:name in …/rest-server.ts: expected false to be true`.
The route derivation now finds the handlers in
`meta-item-read-routes.ts` and still reads the class method
`serveMetaItemLayered` in `rest-server.ts`. Outside the declared list,
so it is named here for the seat. `check:cross-package-test-inputs`
exits 0.
- **`packages/spec/liveness/metadata_endpoints.json`** (declared on
#6017). `enableCache` now cites
`meta-item-read-routes.ts#registerMetaItemReadRoutes`. `endpoints.item`
splits across two files, as the declaration says: the `if` half cites
the module, and the `registerPerItemRoute` half keeps
`rest-server.ts#registerMetadataEndpointsInner`. `prefix` stays.
- **`packages/spec/liveness/doc.json`** and **`book.json`** (declared on
#6017). In `doc.json`, `content.evidence` gains the module for the
single-item branch, and `_note` names it for the book-tree and
single-item branches. The `doc` list branch keeps its
`rest-server.ts#registerMetadataEndpointsInner` citation and its quote:
the quote is already stale (that code lives in
`meta-item-read-gate.ts`), and that is the spec seat's to repair, as
routed, so it is not edited here. In `book.json`, `_note` names the
module for the `book/:name/tree` branch.
- `check:liveness`: `947 pointer(s) … 947 naming a symbol` (945 before)
and `737 … pair(s) asked, 736 anchored, 1 exempt` (735 / 734 / 1
before). Measured at the move commit, before these edits, it stayed
green: these readers are silent.
- **`docs/qa/platform-checklist/areas/`** (declared on #20163,
`6243347725`):
- `api-backend.rest-metadata-config-contract`: `+
packages/rest/src/meta-item-read-routes.ts#registerMetaItemReadRoutes
(the item endpoint gate on the per-item reads)` is added beside the
inner anchor. The inner anchor's parenthetical goes from "metaPath, the
item endpoint gate and registerPerItemRoute" to "metaPath and
registerPerItemRoute", because the `if` moved (13a made the same kind of
edit).
- `platform-core` (the book tree): `rest-server.ts#metaPath` →
`meta-item-read-routes.ts#registerMetaItemReadRoutes`. The text after
the anchor is unchanged. `metaPath` still resolves in the inner head, so
leaving it would have stayed silently wrong.
- `check:platform-checklist` exit 0; `node
scripts/check-platform-checklist.mjs --changed-from origin/main` exit 0,
`12 anchor(s) judged, 0 lost`.
-
**`scripts/adr-anchors/packages__rest__src__meta-item-read-routes.ts.json`**
(NEW; outside the declared list, named for the seat).
`check-adr-anchors` checks `ADR-NNNN Dk` letters only in anchored files.
The move took G4's letter citations out of the anchored
`rest-server.ts`, and the gate read 1776 → 1760 while green: a reader
that narrowed silently, the shape card rule 3 forbids. Slices 4, 6, 7
and 11 met this with an anchor, and this does the same. It anchors
ADR-0106 and ADR-0046, its invariant adds no letter citation of its own,
and the reading is back to 1776.
-
**`scripts/adr-anchors/packages__rest__src__meta-collection-routes.ts.json`**
(NEW, its own commit `7b562222d`, an in-place repair of 13a's same
narrowing). Measured on 13a's own two commits, `b9ac35cbf` → `df000d4b2`
moved the reading 1783 → 1776 with the gate green. This anchors ADR-0131
and ADR-0106, its invariant adds no letter citation, and the reading
becomes 1783. It is the same defect class, the same mechanical shape, a
new file no claim holds, and the same gate. Dropping the commit restores
1776 and nothing else.
**Red before the re-points**, each measured with the readers at their
base text:
- **At the move commit `6fa5946df`:**
- `local` read `Test Files 2 failed | 292 passed (294)`, `Tests 6 failed
| 6021 passed | 326 skipped (6353)`. The execctx census failed four
times: `expected 61 to be 62`, `expected 15 to be 16`, and §7 and §8
`expected 3 to be greater than or equal to 4` (a continuation site out
of reach). The draft census failed twice (`expected [ …(6) ] to deeply
equal [ …(8) ]`).
- The dogfood pair read `Tests 2 failed | 106 passed (108)`: `expected
66 to be 70`, and `this.routeManager.register(` `expected 59 to be 63`.
- The runtime parity test read `Tests 1 failed | 738 passed (739)`.
- `check:route-envelope` exited 1: `meta-item-read-routes.ts NOT
DECLARED` (`MODULES` and the express table), `stringError: found 7,
declared 8`, `siblingCode: found 3, declared 4`.
- `check-adr-anchors` stayed green at 1760 (base 1776), `check:liveness`
and `check:platform-checklist` stayed green, and `repo` stayed `5
passed` (G4 carries no `query:` slot). Those are the silent readers.
- **At `8a8a105cb`** (the list grown, the readers not yet re-pointed):
- The six list readers read `Test Files 6 failed (6)`, `Tests 7 failed |
119 passed (126)`: the length pins and the unfloored module.
- `repo` read `Tests 2 failed | 85 passed | 15 skipped (102)`.
- The dogfood pair read `Tests 2 failed | 106 passed (108)`: `control
"registrar list length" … expected 15 to be 14` and the tripwire length.
- **Green after the re-points** (`5cb0f9c9b`, then the merge head).
## Not done as planned, measured
**`content/docs/permissions/system-context.mdx` row 50 is NOT edited.**
The plan, the claim and the #20163 declaration listed a row-50 anchor
for the module (the GET item `?state=` stored-version read door).
Measured on this tree, `check-system-context-census` refuses it:
`[anchor-is-not-a-read-site] the page anchors
packages/rest/src/meta-item-read-routes.ts#registerMetaItemReadRoutes,
which the census does not call an elevation read and NON_READ_ANCHORS
does not declare` (exit 1). G4 holds no `isSystem` read: H4 holds, and
the census output is identical base vs head (`142 elevation read sites …
135 symbol(s) against 135 required, over 158 anchors`). Row 50's
stored-version prose is carried by its `rest-server.ts#metaSaveVerdict`
anchor, where the read lives. Adding the anchor would need a new
`NON_READ_ANCHORS` ledger row in the gate script, which this move does
not owe, so the page is untouched. 13c and 13d still owe their row-50
anchors, because G5's DELETE and G6's publish and rollback do hold
reads.
## Changesets
- `.changeset/23050-s13b-meta-item-read-routes-move.md` is a
`@objectstack/rest` patch (`Clause-②: no`, move-only). The shipped
`index.js` / `index.cjs` bytes change (the marker above); the
declarations and exports do not.
- `.changeset/23050-s13b-meta-item-read-liveness-citations.md` is a
`@objectstack/spec` patch (`Clause-②: no`), because `liveness/` ships in
that package's `files[]`.
- `skip-changeset` does not apply.
## Acceptance notes
- The plan's 13b reader list missed
`meta-list-projection-parity.test.ts`, and its row-50 item does not
apply to G4 (both above). Its import list named six of the nine imports
that left.
- `docs/qa/platform-checklist/FOLLOW-UPS.md:613` (E1) is a closed, dated
entry that still says the inner method holds "four `endpoints.item`
gates". It is prose, read by no gate, and optional per the plan, so it
is not edited.
- The moved comments keep their deixis: "this block's closing brace" and
"below" in the item read's leading comment describe the inner method's
order. The module header says so rather than editing moved text.
- Carried from earlier slices, untouched: `ui-routes.ts`' "52 sites"
comment and `email-routes.ts`' double-mount header.
## Gates and tests
The final head is `083b60f20`, one merge of `origin/main` `2bcd406a2`
(#24223, #24229). Of those, only #24223 touches a file near this diff:
`rest-server.ts`' class-head `fetchCurrentMetaDocument`, outside G4, and
it merged cleanly. After the merge, the four packages main touched were
rebuilt. `origin/main` has since moved to `7be3cc728` (5 commits), none
of whose 34 paths is one of this diff's 23, so it was not merged again;
PR CI runs the merge ref.
- **Build.** At base, `pnpm turbo run build
--filter=@objectstack/rest... --filter=@objectstack/dogfood...
--filter=@objectstack/runtime... --concurrency=2` exited 0 (`Tasks: 66
successful, 66 total`). At the merge head, `pnpm
--workspace-concurrency=2 --filter @objectstack/metadata-protocol
--filter @objectstack/plugin-security --filter @objectstack/runtime
--filter @objectstack/rest build` exited 0. Then a whole-workspace `pnpm
turbo run build --concurrency=2` exited 0 (`Tasks: 77 successful, 77
total`), for the dist readers.
- **Typecheck.** `pnpm --filter @objectstack/rest typecheck` exits 0
(`check:test-typecheck: OK … 0 file(s) / 0 error(s)`). `pnpm --filter
@objectstack/spec typecheck` exits 0.
- **`@objectstack/rest`.** `local`: `Test Files 294 passed (294)`,
`Tests 6030 passed | 326 skipped (6356)`. This includes
`meta-route-registration-order.test.ts` and
`rest-config-mount-table.pin.test.ts`. `repo` (its `test:repo`): `Test
Files 5 passed (5)`, `Tests 266 passed | 15 skipped (281)`.
- **Dogfood pair** (`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.
- **`@objectstack/spec` local** (the liveness suites among them): `Test
Files 691 passed (691)`, `Tests 20974 passed | 1 todo (20975)`.
- **`test:repo`.** `@objectstack/runtime`: `Test Files 3 passed (3)`,
`Tests 808 passed (808)`, `meta-list-projection-parity.test.ts` among
them. `@objectstack/core`: `Test Files 6 passed (6)`, `Tests 86 passed
(86)`.
- **Lint.** `pnpm exec eslint --no-inline-config` over the 14 changed
`.ts` / `.mjs` files exits 0, with no output. The repo-wide `pnpm lint`
belongs to CI.
- **Gate union.** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (no paths) at `083b60f20` derives 95
commands; its stderr names the commit, and the `--repo` assertion holds.
The change set is 23 paths vs merge base `2bcd406a2`, 2,524 changed
lines (+1,456 / −1,068), under 3,000.
- All 95 exit 0. `pnpm check:dual-build-cjs-loads` first answered exit 3
(no whole-workspace `dist`). After the whole-workspace build it was
re-run with the five other dist readers (`check:dts-closure`,
`check:entry-guard`, `check:lean-entry-closure`,
`check:published-files`, `check:sourcemap-no-sources-content`), all exit
0, and those exits are the ones recorded.
- `--ran`: `Run reconciliation — 95 derived, 95 run, 0 NOT-MEASURED, 0
UNRUN.`, exit 0. It also printed a STALE TREE note: `origin/main` moved
after the merge and changed
`scripts/check-position-name-fold-loaders.mjs`, a family this diff does
not touch. CI runs it on the merge ref.
- Selected readings: `check:route-envelope` exit 0 (`26 route module(s)
audited: 9 conformant, 16 ratcheted, 1 exempt`); `check:adr-anchors`
exit 0 (`72 anchored file(s)`, `1783 decision-letter citation(s)`);
`check:liveness` exit 0; `check:platform-checklist` exit 0; `node
scripts/check-system-context-census.mjs` exit 0 (`over 158 anchors`,
identical to base); `check:cross-package-test-inputs` exit 0;
`check:pm-dispatch-gates` exit 0 (`1884 cases`); `check:type-check-debt`
exit 0; `check:nul-bytes` exit 0.
- By-path scan gates diffed base vs head: `check-meta-type-normalized`,
`check-dispatcher-error-vocabulary`, `check-error-status-conformance`
and `check-undeclared-dep-imports` differ only by the new file (and the
latter by +3 specifiers). `check-rest-log-declared`,
`check-durability-degradation-log-level`, `check-single-authz-resolver`
and `check-system-context-census` are identical.
- **Not run locally:** `check:dev-prereqs` and
`check:skill-frame-freshness` (local-only families). This diff touches
no `packages/spec` build input (`liveness/` ships as files) and no
four-axis frame file.
- **Not governed.** `check-governed-merges --test` over the 23 paths: `0
of 23 path(s) hit the register`, and the size is under the human-merge
threshold.
Commits:
- `6fa5946df`, the move;
- `8a8a105cb`, the list and the `/meta` subset;
- `5cb0f9c9b`, the re-points, with the module's ADR anchor;
- `d00b152fe`, the changesets;
- `7b562222d`, 13a's module ADR anchor (in-place repair);
- `083b60f20`, the merge.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QyoWKK9RwUNxBxmevy9Neb)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 03ac4ec commit 646303e
23 files changed
Lines changed: 1456 additions & 1068 deletions
File tree
- .changeset
- docs/qa/platform-checklist/areas
- packages
- qa/dogfood/test
- rest/src
- runtime/src/domains
- spec/liveness
- scripts
- adr-anchors
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2446 | 2446 | | |
2447 | 2447 | | |
2448 | 2448 | | |
2449 | | - | |
| 2449 | + | |
2450 | 2450 | | |
2451 | 2451 | | |
2452 | 2452 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1263 | 1263 | | |
1264 | 1264 | | |
1265 | 1265 | | |
1266 | | - | |
| 1266 | + | |
1267 | 1267 | | |
1268 | 1268 | | |
1269 | 1269 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1635 | 1635 | | |
1636 | 1636 | | |
1637 | 1637 | | |
1638 | | - | |
| 1638 | + | |
| 1639 | + | |
1639 | 1640 | | |
1640 | 1641 | | |
1641 | 1642 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
540 | 540 | | |
541 | 541 | | |
542 | 542 | | |
543 | | - | |
| 543 | + | |
| 544 | + | |
544 | 545 | | |
545 | 546 | | |
546 | 547 | | |
547 | 548 | | |
548 | 549 | | |
549 | | - | |
| 550 | + | |
550 | 551 | | |
551 | 552 | | |
552 | | - | |
| 553 | + | |
| 554 | + | |
553 | 555 | | |
554 | 556 | | |
555 | 557 | | |
| |||
849 | 851 | | |
850 | 852 | | |
851 | 853 | | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
852 | 869 | | |
853 | 870 | | |
854 | 871 | | |
855 | | - | |
| 872 | + | |
856 | 873 | | |
857 | 874 | | |
858 | 875 | | |
| |||
866 | 883 | | |
867 | 884 | | |
868 | 885 | | |
| 886 | + | |
869 | 887 | | |
870 | 888 | | |
871 | 889 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
124 | 124 | | |
125 | 125 | | |
126 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
127 | 132 | | |
128 | 133 | | |
129 | 134 | | |
| |||
139 | 144 | | |
140 | 145 | | |
141 | 146 | | |
142 | | - | |
143 | | - | |
144 | | - | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
145 | 150 | | |
146 | 151 | | |
147 | 152 | | |
| |||
748 | 753 | | |
749 | 754 | | |
750 | 755 | | |
751 | | - | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
752 | 770 | | |
753 | | - | |
| 771 | + | |
754 | 772 | | |
755 | 773 | | |
756 | 774 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
268 | 268 | | |
269 | 269 | | |
270 | 270 | | |
271 | | - | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
272 | 276 | | |
273 | 277 | | |
274 | 278 | | |
| |||
0 commit comments