Repository navigation
Commit fe53769
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1X7JKgiM29GUcitRvoGGj5BU)_
Part of #25467
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Cut 23 of the `protocol.ts` split (#24586 ruling A, recorded in
`6270097840`), the first after the release pause (restart recorded on
#25467 once 18.2.0 shipped). Cuts 1–22 landed as #25494, #25518, #25538,
#25589, #25601, #25623, #25642, #25719, #25731, #25740, #25797, #25939,
#25972, #26014, #26104, #26168, #26264, #26317, #26350, #26366, #26404
and #26449. The claim is `6439185861`. It takes the cut 23 proposal of
the cut 22 report (`6433520681`). Both members passed the AST screen and
the read-seam census, and both moved unedited.
Two `ObjectStackProtocolImplementation` members move unedited into a new
module,
`packages/metadata-protocol/src/protocol-stored-item-conversion.ts`
(#23050 shape B):
- `convertStoredItemDetailed`: the ADR-0087 conversion chain over a
stored body, with its notices and TODOs handed back.
`migrateStoredMetadata` reports these per row (#4327, #17321, #25279).
- `convertStoredItem`: the read every stored row goes through. It warns
once per conversion, row and process, and fills a page's declared `type`
default (#20101).
`protocol.ts` loses 17 net lines (29,182 to 29,165). The cut is
move-only, and the card stays open for later cuts.
Branch `claude/project-thread-ybjm3h` is the harness-pinned branch for
this thread. It was restarted from `main` `f9867020c6` after the
restart. It names no issue, so the claim comment is the identity record.
It holds the move commit `1d1579ed11` and two merges of `main`:
`6d09a4555e`, and `0741a0f66b`, which was made because `dispatch-gates`
itself had changed on `main` (scripts and docs only). Neither merge
touches a file of `packages/metadata-protocol/`. The package's `src/`
tree is `c7cd94f5` at the move commit and at both merges.
## Serial with the file's in-flight PRs
Measured just before this PR was opened, against the merged head
`0741a0f66b`: of the 15 open PRs, **none edits `protocol.ts`**, and none
names either member, `withDeclaredPageTypeDefault` or
`applyConversionsToStoredItem`. One touches
`packages/metadata-protocol/src/` test files: **#26337** (3 files). Its
`git merge-tree` is clean against this head and against `origin/main`
alone. No open PR edits the new module.
`main` moved one commit after the last merge: #26599 (`dbf7e04adf`), the
spec retirement of conversion kits at or below 16.x. It does not touch
`protocol.ts`. It does edit seven `protocol.*stored*`/conversion test
files in this package and the spec conversion chain that
`applyConversionsToStoredItem` runs. Its `git merge-tree` with this head
is clean. This cut moves the call to that chain unedited, so the PR's
merge ref runs #26599's tests against the moved code. Its one stale gate
file (`scripts/check-spec-docblock-symbol-anchors.mjs`) is not among
this cut's 46 derived commands, so `main` was not merged a third time.
## The order's screen (private statics, `new Error(`, the read-seam
census)
Both members passed:
- **No private-static read.** The AST walk found no access on the
`ObjectStackProtocolImplementation` identifier and none on
`this.constructor`.
- **No error constructed.** Neither body has `new Error(`, so no
`PRODUCERS` row is owed.
- **Read-seam census.** `check-durability-degradation-log-level --list`
was taken on the base and again on the cut: `82 read seam(s)` and an
identical list once `[@:][0-9]+` is stripped. The full readings are
under "The durability `--list`".
## What moves
| Member | Base line | Visibility | Body lines | AST tokens (params +
return + body) |
|---|---|---|---|---|
| `convertStoredItem` | `:6416` | private | 13 | 138 |
| `convertStoredItemDetailed` | `:6452` | private | 15 | 187 |
## The shape (#23050 shape B, as cuts 1–22 apply it)
- **The class keeps both members.** Each keeps its name, docblock,
signature and position. Each body now delegates, marked `[#25467 cut
23]`.
- **`convertStoredItemDetailed` reads no member.** This was measured by
an AST walk over `this` accesses, with `as` casts, parentheses and `!`
stripped, and bare `this` checked. So its stub is a plain call, `return
convertStoredItemDetailed(type, data, onNotice, knownDatasources);`, as
cuts 16 and 21 did. The class signature keeps the
`ConversionNotice`/`ConversionTodoNotice` types, so those type imports
stay in `protocol.ts`.
- **`convertStoredItem` reads two members.** `StoredItemConversionHost`
types each as the class member itself
(`ObjectStackProtocolImplementation['…']`). The function types its
`this` as their `Pick`, and the stub annotates its literal as
`ThisParameterType<typeof convertStoredItem>`.
- `convertStoredItemDetailed` is handed over as a closure, so the body's
call still reaches the class method and, through its stub, the moved
function.
- `storedConversionWarned` is a private FIELD, a `Set<string>`, so it is
handed over as a getter. The body only calls `.has` and `.add` on it,
inside the `onNotice` arrow, and never reassigns it. So the warn-once
set it reads and adds to is the protocol's own, shared with every other
read, exactly as before.
- The getter is the same hand-over cut 20 used for the
`getServicesRegistry` field.
- **No member changes visibility.**
- **Every caller still calls the class method.** The
`this.convertStoredItem(` sites at `:7277`, `:9812`, `:10857`, `:10922`,
`:11498`, `:18885`, `:25342`, `:25576` and `:28359` (base) do not
change. Neither does the cut 16 closure that hands it to
`storedOverlayEntries` (`:10211`), or the remaining
`this.convertStoredItemDetailed(` site (`:21925`).
## Module-level declarations, by reader
Measured by an AST walk over each body's identifiers, against
`protocol.ts`'s top-level declarations and import bindings (property
names excluded):
| Name | Where `protocol.ts` has it | Other readers in `protocol.ts` |
What this cut does |
|---|---|---|---|
| `withDeclaredPageTypeDefault` | non-exported function, `:2263` | yes
(the save door, `:20924`) | gains `export` in place; the new module
imports it from `./protocol.js` |
| `applyConversionsToStoredItem` | the `@objectstack/spec` import,
`:170` | **none** | **dropped from that import** (its last reader
moved); the new module imports it from `@objectstack/spec` |
| `ConversionNotice`, `ConversionTodoNotice` | type imports on the same
line | yes (both stubs' declared signatures) | stay; the new module
imports them as types from there too |
| `PLURAL_TO_SINGULAR` | the `@objectstack/spec/shared` import | yes
(58) | stays; imported from there too |
`index.ts` names its exports one by one, so the in-place `export` does
not reach the published surface.
**One stale prose reference, disclosed and not edited.** The `[commit
ece4dad]` emitted-specifier comment under the imports (`:172`) says
the file imports the `@objectstack/spec` root "for
`applyConversionsToStoredItem` above". The root import stays, for
`applyConversionsToFlow` and the two notice types, so the pin it
explains still holds. The `.d.ts` readings below confirm that nothing
about the emitted declarations moved. Editing that sentence is not
move-only, so this PR leaves it for a later edit.
## The durability `--list`
`check-durability-degradation-log-level` exits 0 at both ends with
identical output: `82 read seam(s)` at both ends. Its `--list` is
**identical once `[@:][0-9]+` is stripped** (158 lines, and no entry
changes file). Neither body has a `try`. `convertStoredItem`'s
`console.warn` sits in an `onNotice` callback, not a `catch`, so the
log-level rule does not grade it. On the merged tree the verdict still
reads `82 read seam(s)`.
## The published `.d.ts`
The series bar is ruling `6348891160`: sorted-union identity, measured
first, with raw identity reported when it holds. **Both hold for this
cut.**
Base `f9867020c6` and head `1d1579ed11` were built with `pnpm --filter
@objectstack/metadata-protocol build` against one dependency tree. The
closure was built at head by a full `pnpm build` (116/116). For the base
build, the package's `src/` was swapped tree-only to base and restored
from `HEAD` under a trap. Afterwards `git diff HEAD` was empty, `git
status` was clean, and both touched blobs equalled `HEAD`'s.
- **Normalised sha256** (the ruling's bar):
`dd66cd91652093f2a0ce9a3b990290291bf3bcc40379d196a1bbe897c1ec43d7` at
both ends, on `dist/index.d.ts` and `dist/index.d.cts`. The normaliser
sorted 80 string-literal union runs. **Sorted-union identity holds.**
- **Raw sha256**:
`f4f602c840264aa052ee96788778479ba2ddccbd68199ad68f4419ff564f6ccd` at
both ends, 778,346 bytes. **Raw identity holds.** The emitted specifiers
did not move with the import change.
- **Again on the merged tree** `6d09a4555e` (closure rebuilt by a full
`pnpm build`, 116/116): the same raw and normalised sha256, and the same
`index.js`/`index.cjs` hashes, as the pre-merge head. The second merge
changed no package and no build input.
- **The two builds differ where they should.**
- `index.js` hashes `3aedf79b4657c927…` at base and `8cc705b2d0a6a59b…`
at head (`index.cjs` `b1d7383e753c4e1a…` → `8af96d570232787c…`).
- `convertStoredItem.call(host` occurs 0 times in the base bundles and
once in the head bundles (ESM and CJS alike).
- `function convertStoredItem(` goes 0 → 1.
- **Positive control** on the head tree. `private` was dropped from
`convertStoredItem` on disk (restored from `HEAD` under a trap) and the
package rebuilt. Both `.d.ts` files move to `a39e3a50ba0baab4…`
(normalised `573d8a0a1d7bb1ca…`, which differs from the bar's
`dd66cd91…`) and print `convertStoredItem(type: string, data: unknown):
unknown;`. So the bar can see a change on these members.
- **Export tables.** The ESM and CJS bundles, loaded at runtime from the
package, each export the same 78 names at base and head. The sorted list
hashes to `9f18a0177ac736ed…` on all of them. None of the moved
functions, `StoredItemConversionHost` or `withDeclaredPageTypeDefault`
appears.
No changeset: `skip-changeset`, per ruling `6348891160`.
## Proof of move-only
**Bodies, by AST token.** The compare reads the TypeScript compiler's
AST leaf tokens, with JSDoc skipped, over the parameters (less the added
`this`), the return type and the body. It compares base `protocol.ts` at
`f9867020c6` against the head module:
```
convertStoredItem: base tokens 138, head tokens 138, differ 0, text-equal(ws-collapsed, comments incl.) true
convertStoredItemDetailed: base tokens 187, head tokens 187, differ 0, text-equal(ws-collapsed, comments incl.) true
TOTAL tokens=325 differ=0 members=2
CLASS members base=301 head=301 order-same=true byte-identical=299 stubs-with-identical-docblock+signature=2 other=[]
TOP base=251 head=252 byte-identical=249
```
The two top-level statements that are not byte-identical are the
`@objectstack/spec` import, which lost `applyConversionsToStoredItem`,
and `withDeclaredPageTypeDefault`, which gained `export`. Nothing else
changed in either.
**Negative controls**, one per member. Each changed one token in an
in-memory copy of the head module:
```
MUTATED … "if (singular === 'flow')" -> "if (singular !== 'flow')"
convertStoredItem: base tokens 138, head tokens 138, differ 0, text-equal(ws-collapsed, comments incl.) true
convertStoredItemDetailed: base tokens 187, head tokens 187, differ 1, text-equal(ws-collapsed, comments incl.) false
MUTATED … "storedConversionWarned.has(key)" -> "storedConversionWarned.add(key)"
convertStoredItem: base tokens 138, head tokens 138, differ 1, text-equal(ws-collapsed, comments incl.) false
convertStoredItemDetailed: base tokens 187, head tokens 187, differ 0, text-equal(ws-collapsed, comments incl.) true
```
- **Class side.** There are 301 members at base and at head, in the same
order. The 299 that did not move are byte-identical to base, leading
comments included. Both stubs sit at their base positions and keep their
docblocks and signatures byte-identical.
- **Top level of `protocol.ts`.** Of the 251 base statements, 249 are
byte-identical, leading comments included; the other two are the import
and the `export` above. Head adds one statement, the new module's
import.
- **Size.** +111 / −30 over 2 files, 141 changed lines (the proposal's
estimate was 150–200). `protocol-stored-item-conversion.ts` has 98
lines.
## Readers of the moved lines
The tests and scripts that read `protocol.ts` by path (the files that
name `protocol.ts` and call `readFileSync`) were grepped for both member
names and for the bodies' text: `storedConversionWarned`,
`applyConversionsToStoredItem`, `withDeclaredPageTypeDefault`, `carries
a pre-protocol shape`. So were the test files in `packages/`, `docs/qa/`
and the `@objectstack/spec` liveness ledgers.
- **By path: none reads the moved bodies.** Of the 33 such files, the
one textual hit is the gitignored, build-written
`packages/spec/src/migrations/registry.ts`, which names
`applyConversionsToStoredItem` (a `@objectstack/spec` export) in its
migration entries and does not read `protocol.ts`.
- **Behaviour through the class method, no edit owed.**
`protocol.flow-canonicalizer.test.ts` and
`metadata-diagnostics.union-issues.test.ts` (metadata-protocol) and
`view-overlay-owner-hidden-retirement.test.ts` (spec) name
`convertStoredItem` in comments only, and drive the read through the
protocol. The first two pass at both ends, in the package suite.
- **The liveness ledgers.** No row points at either member. Carried
forward: `manifest.json`'s `dependencies` row →
`protocol.ts#resolveWritePackageScope` (cut 19), and `seed.json` →
`protocol.ts#applySeedBodies` (cut 14). Both still quote lines that
moved to a seam module. `check:liveness` checks only that the `#symbol`
is named in the file, and both stubs keep it. Re-pointing them is a
`packages/spec/**` edit, outside this card.
- **ADR anchors.** `check-adr-anchors` exits 0 at both ends.
- The decision-letter count is unchanged at 1,881. The moved bodies
carry no ADR letter; the docblocks that cite ADR-0087 D2 stay on the
stubs.
- The citation count goes 59,819 → 59,821 and the file count 8,353 →
8,354, from the new module's header.
- **Engine-double contract** (`check-engine-double-contract`): exits 0
at both ends.
- The `updateData`/`deleteData` seams keep their entries at new line
numbers (13883 → 13866, 13908 → 13891).
- `productionFiles` is 3,773 at base and 3,775 at head. The +2 are the
new file and the gitignored `packages/spec/src/migrations/registry.ts`
that the spec build writes in the head tree, as in cuts 20–22.
- **Identical output at both ends:** `check-adr-symbol-anchors`,
`check-system-context-census`, `check-tenant-audit-census`,
`check-query-options-erasure-ratchet`, `check-filter-alias-parity` and
`check-durability-degradation-log-level`. `check-nul-bytes` differs only
in the scanned file count, +1. The base-end readings were taken in a
clean detached worktree at `f9867020c6`.
## Verification
- `tsc --noEmit` in `packages/metadata-protocol` exits 0 at head and on
the merged tree.
- `pnpm exec eslint --no-inline-config packages/metadata-protocol` exits
0 with no output (the whole touched package, with the root `lint`
script's flags).
- **`packages/metadata-protocol` suite**, base and head, compared per
test name and status. Each leg ran vitest `--maxWorkers=2` with the JSON
reporter under the shared verify lock.
- Base `f9867020c6`: 21,595 tests (21,576 passed, 0 failed, 19 skipped),
272 files.
- Head `1d1579ed11`: 21,595 tests (21,576 passed, 0 failed, 19 skipped),
272 files.
- None lost, none added, none changed status. The base leg is the
package `src/` swapped tree-only from `f9867020c6` (the new module
removed) and restored from `HEAD` under a trap.
- The merged head `6d09a4555e` gives the same 21,595 tests, per test
identical to the pre-merge head (0 lost, 0 added, 0 changed).
- `check-platform-checklist --changed-from origin/main` (merged tree):
OK. 1 anchored file is in the change set, 29 anchors were judged, and 0
were lost.
- **Governed surface.** `check-governed-merges --branch
claude/project-thread-ybjm3h` finds 0 of 2 paths in the register (13
surfaces), so the PR is NOT governed. It has 141 changed lines, under
the 3,000-line human-merge bar.
- **Derived gates.** `dispatch-gates --commands --repo
objectstack-ai/objectstack` derives 46 gates on 2 changed paths from
`0741a0f66b`, with no stale-tree warning, and all 46 exit 0.
`dispatch-gates --ran` reports 46 derived, 46 run, 0 NOT-MEASURED and 0
UNRUN, and exits 0.
- The same 46 also exited 0 on `6d09a4555e`, after the full `pnpm build`
(116/116).
- That derivation flagged `scripts/pm/dispatch-gates.mjs` itself as
stale against `main`, so `main` was merged again, and the derivation and
every gate re-run.
- `check-durability-degradation-log-level --list` on `0741a0f66b`: `82
read seam(s)`.
## Carry-forward
These stay in `protocol.ts`:
- **The read-seam members** (cut 21). A member named in a `protocol.ts`
read-seam entry of `check-durability-degradation-log-level --list`, as
the guarded wrapper or the guarding member, stays until the gate follows
imported wrappers or a ruling accepts the loss. The census trial on this
base, over 50 members, measured the same census-negative set as cut 22's
trial: `findEnvironmentRows` 66, `packagelessAddress` 78,
`findServedOverlayRow` 79, and `foldStoredCollection`,
`applyObjectRegistryMutation`, `unmanagedImportCollisions`,
`rollBackUnmanagedImport`, `readRevertableCommit` and
`storedFlowBindingAgrees` 81. `rethrowUnlessMetadataStoreUnprovisioned`
cannot move at all.
- Public members whose return type is inferred.
- The bodies kept by a reader: `probeRecord`, `getMetaItemCached`,
`findReferencesToMeta`, `refuseUnmintableMetaType`,
`metaTypeNamespaceExists`, `viewContainerNameCollisionRefusal` with
`overlaidShippedContainerViewNames`, `reportPageRequiresAbsentAtLoad`,
the 7 `applyRegistryWriteThrough` callers,
`readCodeLayerForCarryForward` and `ensureObjectStorage`.
- The private-static readers: `refusePackagedBaseRemoval`,
`packagedBaseRefusal`, `runPublishSideEffects`,
`promoteDraftForPublish`, `publishPackageDrafts` and
`discardPackageDrafts`.
- The field writers: `warnClosureReadUnavailable`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 416a760 commit fe53769
2 files changed
Lines changed: 111 additions & 30 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
170 | | - | |
| 170 | + | |
171 | 171 | | |
172 | 172 | | |
173 | 173 | | |
| |||
411 | 411 | | |
412 | 412 | | |
413 | 413 | | |
| 414 | + | |
| 415 | + | |
414 | 416 | | |
415 | 417 | | |
416 | 418 | | |
| |||
2260 | 2262 | | |
2261 | 2263 | | |
2262 | 2264 | | |
2263 | | - | |
| 2265 | + | |
2264 | 2266 | | |
2265 | 2267 | | |
2266 | 2268 | | |
| |||
6414 | 6416 | | |
6415 | 6417 | | |
6416 | 6418 | | |
6417 | | - | |
6418 | | - | |
6419 | | - | |
6420 | | - | |
6421 | | - | |
6422 | | - | |
6423 | | - | |
6424 | | - | |
6425 | | - | |
6426 | | - | |
6427 | | - | |
6428 | | - | |
6429 | | - | |
| 6419 | + | |
| 6420 | + | |
| 6421 | + | |
| 6422 | + | |
| 6423 | + | |
| 6424 | + | |
| 6425 | + | |
6430 | 6426 | | |
6431 | 6427 | | |
6432 | 6428 | | |
| |||
6455 | 6451 | | |
6456 | 6452 | | |
6457 | 6453 | | |
6458 | | - | |
6459 | | - | |
6460 | | - | |
6461 | | - | |
6462 | | - | |
6463 | | - | |
6464 | | - | |
6465 | | - | |
6466 | | - | |
6467 | | - | |
6468 | | - | |
6469 | | - | |
6470 | | - | |
6471 | | - | |
6472 | | - | |
| 6454 | + | |
| 6455 | + | |
6473 | 6456 | | |
6474 | 6457 | | |
6475 | 6458 | | |
| |||
0 commit comments