Repository navigation
Commit 8118be4
<!-- claude-projects-attribution: {"github_login":"os-steve"} -->
_Requested by **Steve** · [project
thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9UmbUGPtw5rdRcd3UpYXs5N)_
Part of #25467
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:为 `protocol.ts` 的类体拆分搭好“宿主”机制:新增
`protocol-host.ts`(被搬出的方法体经它访问类成员)和工具
`scripts/host-split.mjs`(只允许三种封闭改写,并逐个 token 校验搬出的方法体与原方法体一致);只搬了一个试点方法
`tenantAuthoredWriteRefusal`,没有成段搬移。
- **为什么改**:#25467 裁决 E 的第二步 E1:先把搬移规则、校验工具、两个按路径 pin 和读缝普查做成能穿过宿主的形态,E2
才能成段搬移而不让守卫失明。
- **风险与回滚**:低。没有行为改动;试点方法签名和文档不变,对外 `index.d.ts`(ESM 与 CJS)与 main
构建出的逐字节相同。回滚即整体 revert。
-
**先看**:`packages/metadata-protocol/src/protocol-host.ts`;`packages/metadata-protocol/scripts/host-split.mjs`
文件头(封闭改写集);`protocol.ts` 里类的 `static {}` 块。
- **两分钟验证**:`pnpm --filter @objectstack/metadata-protocol exec vitest
run scripts/host-split.test.mjs
src/protocol.read-verb-canonical-fold.test.ts
src/protocol.lookup-artifact-item-call-sites.test.ts`,预期 3 个文件全绿。
- **需要你做的**:无需审批级别操作(约 1,530 行,低于 3,000 行线)。`getMetaTypes()`
显式返回类型已由席位裁定移出 E1(保持推断,`.d.ts` 逐字节不变),另立小步处理。
## What changes
Step **E1** of ruling E (6537939895, item E1), claim 6578609040. The
host split machinery, one pilot member, no section moves.
**The host.** `src/protocol-host.ts` declares `ProtocolHost`: every
class member a moved body reads, each typed AS that member
(`ObjectStackProtocolImplementation['x']`, or `(typeof
ObjectStackProtocolImplementation)['x']` for a static). The class builds
the host in a `static {}` block, the one place that can read its private
members; a static block adds no member, so the published `.d.ts` does
not move. A method is forwarded as a closure called at call time (a spy
or test double on the instance is still the one a moved body reaches), a
field as a getter (plus a setter when written), a private static as a
closure to the static. `protocolHost(this)` builds one host per instance
and caches it in a WeakMap.
**The closed rewrite set and its check.**
`packages/metadata-protocol/scripts/host-split.mjs` (a tool, not a gate)
has three commands: `survey`, `move MEMBER MODULE` and `check BASE_REF
MEMBER MODULE`. Inside a moved body exactly three rewrites are allowed:
1. `this.x` becomes `host.x` (an instance member);
2. a private static `ObjectStackProtocolImplementation.fn(…)` becomes
`host.fn(…)`;
3. `this.constructor` becomes `host`.
`check` proves AST identity modulo exactly that set by walking every
token (operators and keywords included), and also proves the body text,
comments included, equals the base body rewritten and re-indented; it
checks the stub, the method's unchanged signature, the function's
parameters and return type, and that the `Pick` names exactly the
members read. Everything outside the set is a refusal: a bare `this` or
`this[…]`, `super`, the method's `arguments`, an identifier already
named `host`, a private static read as a value or a private static
field, `this.constructor` not followed by a static, an undeclared
member, generators and destructured parameters.
`scripts/host-split.test.mjs` (35 tests, collected by the package's
vitest run) pins each rewrite kind, each refusal, and fifteen negative
controls on the moved function plus three on the stub: a changed
operator (`??` to `||`, `===` to `!==`), `const` to `let`, a changed
literal, a wrong rewrite target, an unrewritten member or static, an
extra statement, a changed comment, a `Pick` naming one member too many
or too few, a renamed host parameter, a retyped parameter, a changed
return type, reordered stub arguments, a stub handing over `this`, and
an edited docblock. Writing these tests found one tool bug, fixed here:
`arguments.length` escaped the `arguments` refusal.
**The pilot.** `tenantAuthoredWriteRefusal` (5 rewrite sites, all kind
1) moved to `src/protocol-tenant-authored-write.ts`. `node
scripts/host-split.mjs check 838a802 tenantAuthoredWriteRefusal
protocol-tenant-authored-write.ts` reads `ok: true, textIdentical:
true`. Ablation, with `folded.packageId === stamped` changed to `!==` in
the module, then restored:
```
PROBLEM protocol-tenant-authored-write.ts:65: ExclamationEqualsEqualsToken where the base has EqualsEqualsEqualsToken (`===`)
PROBLEM protocol-tenant-authored-write.ts: tenantAuthoredWriteRefusal's body text differs from the base body rewritten and re-indented, first at body line 34
```
**The pins and the census read through the host, for every module.**
These are the forced test edits:
- `src/protocol.read-verb-canonical-fold.test.ts`: `delegateBody`
follows a stub (`fn(protocolHost(this), …)` or the per-member series'
`fn.call(host, …)`) to the moved function in the module protocol.ts
imports it from. A new assertion requires that the pilot is read through
the split. Before the edit the pin was red on the pilot (`expected [
'tenantAuthoredWriteRefusal' ] to deeply equal []`). Ablation, removing
the fold from the pilot module's body (`const folded = request;`), then
restored:
```
AssertionError: A `/meta` verb takes a required `type` without folding
it at the request boundary. … expected [ 'tenantAuthoredWriteRefusal' ]
to deeply equal []
```
- `src/protocol.lookup-artifact-item-call-sites.test.ts`: the site scan
covers protocol.ts plus every `protocol-*.ts` module (comments blanked
through the shared `scripts/js-comment-mask.mjs`), and a new test pins
that the module list includes the host's and the pilot's. Ablation,
planting an unrecorded `lookupArtifactItem(` call in the pilot module,
then restored:
```
AssertionError: a site with no recorded disposition: classify it …
expected [ Array(1) ] to deeply equal []
AssertionError: expected 22 to be 21
```
- Both pins import `maskComments` from `scripts/js-comment-mask.mjs`
(check:comment-mask-adoption refused a private stripper), so
`turbo.json`'s `@objectstack/metadata-protocol#test` inputs and
`scripts/cross-package-test-inputs.mjs` declare that file
(check:cross-package-test-inputs). Two config lines outside the claim's
file surface, forced by those gates.
- `scripts/check-durability-degradation-log-level.mjs` (`HOST_SPLIT`):
HOST CALL now also accepts `host.x(…)` where `host` is the function's
first parameter, typed by a host interface declared in the module or
imported by name from a split module, with members typed AS the class's
instance or static members. STUB accepts `fn(protocolHost(this), …)`.
There are 10 new self-test cases (flags, negative controls, BOUND
pairs); the self-test reads 75 cases. Ablation, renaming `hostParam` and
`hostOf`, then restored: 4 failures (the 3 E1 flags plus the deeper
BOUND), each `expected violation=true seams=1, got violation=false
count=0 seams=0`. The census reads 100 seams against main's 98. The two
new lines are `protocol-packageless-overlay-migration.ts`'s
`migratePackagelessOverlays()` guarding `storedPairRow()`, a helper that
already took its module's own host as a first parameter named `host`.
Both read "no invented answer", so no verdict or ledger row moves. This
is recorded in the docblock, as #28058 recorded its 93 to 95.
## The published `.d.ts`
Built from main and from this head, twice: before the merge of main
(main 838a802, sha256 `ef70d5a4…004a8` on both sides) and after it
(main 7f277a8, sha256 `de90eb4e…ccf88` on both sides, normaliser 2
`83d37f67…7e2c0` on both). Each time `index.d.ts` is byte-identical to
main's, and ESM equals CJS. A trial merge of the later main 6af3d29
(which edits protocol.ts again), built and then discarded, also reads
byte-identical (`0e8c1a2c…ef526` on both sides). The declaration-emit
comment leak into `getMetaTypes()`'s inferred return type struck this
diff once: a `[#28001]` docblock printed inside `examples?`. It was
cleared the way E0 cleared it, by the length of a comment line above the
leaking offset (one word in the pilot's import comment); a 1 to 8
character probe read raw-equal at 5 or more.
## Deviation the seat ruled: `getMetaTypes()` explicit return type
dropped from E1
E0 carried this item into E1 with the condition "normaliser 2 hashes
equal". The inferred return type prints as 793 lines of `.d.ts`, and an
explicit annotation prints as written, so the two meet only if that
793-line literal is pasted inline. Measured: that gives a byte-identical
`.d.ts` and green tsc, but 793 duplicated lines whose drift is silent in
the widening direction.
Seat 5 ruled option C: the return type stays inferred, so `index.d.ts`
stays byte-identical (the E-series invariant), and every E2 cut reads
the raw `.d.ts` diff of `getMetaTypes()`. A named composed type with a
type-equality pin against main's `.d.ts` (option B) becomes its own
small step after E1 lands, filed by the seat. The `turbo.json` and
`scripts/cross-package-test-inputs.mjs` lines above are accepted as
forced.
## Serial
Re-read just before opening against main 6af3d29 (34 commits past
this branch's one merge of main at 7f277a8; `git merge-tree` with
main is clean). Open PRs whose own diff touches
`packages/metadata-protocol/src/protocol.ts`: #28731 only, and `git
merge-tree` with this head is clean. No open PR touches the other files
here.
## Gates
On 710b8fe: `node scripts/pm/dispatch-gates.mjs --commands` derived
82 commands, and each records `exit 0`. `--ran` reports 82 derived, 82
run, 0 NOT-MEASURED. The first round, on cf94e93's parent, caught the
two items above: check:comment-mask-adoption and
check:cross-package-test-inputs. check:dual-build-cjs-loads exited 3
there (unbuilt packages); they were built and it now exits 0. The
package's typecheck and test, through os-verify-lock, read Test Files
305 passed, 4 skipped; Tests 22191 passed, 26 skipped. The 11 direct
dependents' typecheck exits 0. Lint (`eslint packages/metadata-protocol`
plus the three root scripts, `--no-inline-config`) exits 0. CI is not
read.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01ADHkmR4MjTzeUv5x6tNkbk)_
<!-- signed: domain:server#5 · os-steve ·
session_01ADHkmR4MjTzeUv5x6tNkbk -->
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e119e53 commit 8118be4
11 files changed
Lines changed: 1452 additions & 81 deletions
File tree
- .changeset
- packages/metadata-protocol
- scripts
- src
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
Large diffs are not rendered by default.
| 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 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 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 | + | |
0 commit comments