Skip to content

Commit f9e8401

Browse files
test(dogfood): drop the registrar-file list's length pin from authz-conformance (#26557)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9A5x8a8TEjH8k1vYVW1iwVG)_ Fixes #26524 Part of #26431 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:`packages/qa/dogfood/test/authz-conformance.test.ts` 删掉「注册器文件清单长度 = 18」这条手抄断言,同一个 case 的其它断言全部保留;`packages/rest/src/rest-server-registrar-files.ts` 头注里「每个读者都钉清单长度」这句话改成实情。只改测试和一段注释,不发布任何东西。 - 为什么改:清单本身就是权威,这个数字每拆一个路由模块出 `rest-server.ts` 就要改一次,而 PR CI 不跑 dogfood,所以拆分 PR 自己看不到,合入后 `main` 才变红。#26518 已经删了 `packages/rest` 里的六处,这是第七处(维护者在退役检查清扫里「同意」)。 - 风险与回滚:只删一条断言。实测空清单、探针漏读一个文件、探针少读一个文件这三种情况,这个 case 都照样变红;回滚就是 revert 这一个 commit。 - 先看:`authz-conformance.test.ts` 第 1624–1659 行(这个 case),然后是 `rest-server-registrar-files.ts` 第 23–26 行。 - 两分钟验证:`pnpm --filter @objectstack/dogfood exec vitest run test/authz-conformance.test.ts`(要先建好 dogfood 的依赖闭包),预期 60/60 全绿。 - 需要你做的:无,席位落地。 ## What changes - `authz-conformance.test.ts`, case "reads ZERO on the real rest-server.ts today (the pre-wiring baseline)": `expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(18)` is deleted. Everything else the case asserts stays: `REST_SERVER_REGISTRAR_PATHS[0]` is `rest-server.ts`; both probes' `alsoReads` equal the list minus its head, and `probeSource` equals the listed files joined in order; zero hits over the list; no `realtime:rest-server.ts:` tripwire key is minted. - The case's comment said the list's "length is pinned so a module added to it makes this re-read". That clause is now false, so it is cut. The fifteen `Length N → M` history lines stay, and one closing `[#26524]` line follows them. - No `toBeGreaterThan(0)` guard is added. On an empty list the case already reds at `REST_SERVER_REGISTRAR_PATHS[0]` (measured below). - `rest-server-registrar-files.ts` header, lines 23–26: "Each reader keeps its own sum over the list and pins the list's `length`" was true of seven readers before #26518 and #26520. After this PR, none pins it. The sentence now says that each reader keeps its own sum, that none pins the length, and that a module added to the list widens every reader with no edit to any of them. #26436 landed (PR #26520) before this PR opened, so the reword rides here as the card ordered. ## Why The list file's own header says it is ⛔ not a gate and that each reader stays the authority on what it counts. The length pin made the dogfood suite red on every registrar move, for a number nothing is derived from. Dogfood is skipped on PR CI, so the split PR never saw the red; `main`'s push battery did, after the merge. This follows #26431's rule as applied to the six `packages/rest` copies in #26518. ## Verification All runs are on head `55b1b414` (base `f486e9c1`), after the dogfood dependency closure was built: `pnpm --workspace-concurrency=2 --filter '@objectstack/dogfood^...' build`, lock `VERDICT command-exit 0`. - `pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/authz-conformance.test.ts test/authz-probe-blind-spot.test.ts`: `Test Files 2 passed (2)`, `Tests 70 passed (70)`, VERDICT exit 0. `authz-conformance.test.ts` alone: 60/60. - `pnpm --filter @objectstack/dogfood --filter @objectstack/rest run typecheck`: VERDICT exit 0. Both tsc programs list the changed file (`--listFilesOnly`: 1 hit each). - Acceptance grep: `git grep -n "REGISTRAR_FILES).toHaveLength" -- packages/qa` gives no hit (exit 1). - Dogfood is skipped on PR CI (it runs only on `main` push and schedule runs), so the local run above is the evidence for this suite. <details><summary>Empty list: the case still reds, so no anti-vacuity guard is added</summary> `REST_SERVER_REGISTRAR_FILES` was replaced with an empty array in `rest-server-registrar-files.ts`, using `scripts/ablation-replace.mjs`. The output was `ok mutation landed: anchor 1 -> 0`, then `ok restored: blob == HEAD (020a438) and git diff HEAD is empty`. The dogfood test imports the list from `src/` by relative path, so no `dist/` sits on the path and no rebuild is needed per leg. Result: `Tests 1 failed | 59 passed (60)`. The red is this case at `authz-conformance.test.ts:1647`: `expected undefined to be 'packages/rest/src/rest-server.ts'`. </details> <details><summary>Ablation: a probe that skips a listed file reds the case</summary> | Leg | Mutation (`ablation-replace`, anchor 1 → 0, restored to the HEAD blob) | Result | |:--|:--|:--| | B1, `alsoReads` skips `ui-routes.ts` | `REST_SERVER_REGISTRAR_ALSO_READS` filter gains `&& !file.endsWith('/ui-routes.ts')` | `Tests 1 failed / 59 passed`: this case, at line 1650 (`expected [ …(16) ] to deeply equal [ …(17) ]`) | | B2, `probeSource` reads one file fewer | `probe.alsoReads` is read with `.slice(1)` before `.map` in `probeSource` | `Tests 1 failed / 59 passed`: this case, at line 1651 (the probe-text equality) | </details> <details><summary>Dry move: a name appended to the list stays green here</summary> Probe: a new `packages/rest/src/zz-dry-move-routes.ts` (licence header and `export {};`, no route body) is appended to `REST_SERVER_REGISTRAR_FILES`, making the list length 19. The append went through `ablation-replace --hold` (`ok mutation landed: anchor 1 -> 0`) under an EXIT/INT/TERM restore trap. Afterwards both files hash to their HEAD blobs, the probe module is removed, `git diff HEAD` is empty and `git status` is clean. | Leg | Result | |:--|:--| | this head | `authz-conformance.test.ts` 60/60 green. `authz-probe-blind-spot.test.ts` reds one case, "every module on the RestServer registrar list still registers routes": the probe module has no route body. That case asserts a fact about each listed module, not a count; a real registrar module satisfies it. | | base test file (pin in), same list | `Tests 1 failed / 59 passed`: `expected [ 'rest-server.ts', …(18) ] to have a length of 18 but got 19` at line 1646 | The first attempt at this leg was a no-op. The anchor `'meta-object-state-routes.ts',` occurs twice in the list file, and `ablation-replace` refused it (`ANCHOR AMBIGUOUS`, exit 3; on-disk count 0). The two readings taken in that pass are discarded. The table above is the rerun with a unique anchor. </details> <details><summary>Gates</summary> Head `55b1b414`. Derivation: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` gave 53 commands. Each one ran with stdin closed, and its exit code was captured before any pipe. - 51 of 53 exited 0 on the first pass. - `node scripts/check-plugin-teardown-shape.mjs --self-test` exited 3 (PREREQUISITE NOT MET: the pinned fixture commit `621a4876` was missing from the shallow clone). After `git fetch --depth=1 origin` of that sha it exited 0: "48 cases pass". - `pnpm check:dual-build-cjs-loads` exited 3 (PREREQUISITE NOT MET: no `dist` for six packages outside the dogfood closure). After `turbo run build --concurrency=2 --filter='./packages/**'` (lock VERDICT exit 0) it exited 0: "112 published require entry point(s) across 69 package(s) load". - `--ran` reconciliation: "53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN", a DERIVED zero. - The families the derivation places outside its list (artifact rosters, wide populations, path-scheduled CI jobs, type-check lanes) are CI's run on this PR. The dogfood jobs among them do not run on a PR. </details> ## Acceptance notes - `authz-probe-blind-spot.test.ts:155` already carries `expect(REST_SERVER_REGISTRAR_FILES.length).toBeGreaterThan(0)`, so dogfood keeps one anti-vacuity guard on the list either way. - Changeset: none. The diff touches a dogfood test (private package) and a comment in a `src/` file that `src/index.ts` never reaches (it is not in `dist`), so nothing published changes. `skip-changeset` is set at creation. ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (not touched) - [x] 2. Every name I added uses the casing for its kind. (no names added) - [x] 3. No formatter ran; `pnpm lint` passes. (no formatter ran; lint is CI's run) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (publishes nothing; both lines are above) - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (not touched) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. (the 维护者速读 block is Chinese by repo convention) - [x] The *Before Submitting* list in CONTRIBUTING.md is done. --- _Generated by [Claude Code](https://claude.ai/code/session_01ADHkmS4BqrgK72hUV5eqNY)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1080f07 commit f9e8401

2 files changed

Lines changed: 7 additions & 7 deletions

File tree

‎packages/qa/dogfood/test/authz-conformance.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,8 +1626,7 @@ describe('#9084 — the rest-server.ts transport tripwire keys off mechanics', (
16261626
expect(hits(MECHANICS.re, src)).toEqual([]);
16271627
expect(hits(ROUTES.re, src)).toEqual([]);
16281628
// [#23050 slice 3] …and on every file `RestServer`'s registrars live in:
1629-
// 0 over the list, whose length is pinned so a module added to it makes this
1630-
// re-read. The control is that both probes really READ the list — their
1629+
// 0 over the list. The control is that both probes really READ the list — their
16311630
// text is every file on it, in order — so the zero is not a list ignored.
16321631
// [#23050 slice 4] Length 4 → 5 (`sharing-routes.ts`), still 0 over it.
16331632
// [#23050 slice 5] Length 5 → 6 (`analytics-routes.ts`), still 0 over it.
@@ -1643,7 +1642,8 @@ describe('#9084 — the rest-server.ts transport tripwire keys off mechanics', (
16431642
// [#23050 slice 13c] Length 15 → 16 (`meta-item-write-routes.ts`), still 0 over it.
16441643
// [#23050 slice 13d] Length 16 → 17 (`meta-item-history-routes.ts`), still 0 over it.
16451644
// [#23050 slice 13e] Length 17 → 18 (`meta-object-state-routes.ts`), still 0 over it.
1646-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(18);
1645+
// [#26524] The length pin is gone: the list is the authority, and a module
1646+
// added to it is read by both probes with no edit here.
16471647
expect(REST_SERVER_REGISTRAR_PATHS[0]).toBe(REST_SERVER);
16481648
const listed = REST_SERVER_REGISTRAR_PATHS.map((file) => readFileSync(join(REPO_ROOT, file), 'utf8'));
16491649
for (const probe of [MECHANICS, ROUTES]) {

‎packages/rest/src/rest-server-registrar-files.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
* moves the next body adds its module here once, and every reader widens with
2121
* it.
2222
*
23-
* Each reader keeps its own sum over the list and pins the list's `length`, so
24-
* a module added here makes every one of them re-read its number instead of
25-
* widening unnoticed. ⛔ Not a gate: nothing runs this list on its own, and a
26-
* reader that imports it stays the authority on what it counts.
23+
* Each reader keeps its own sum over the list; none pins the list's `length`,
24+
* so a module added here widens every reader with no edit to any of them.
25+
* ⛔ Not a gate: nothing runs this list on its own, and a reader that imports
26+
* it stays the authority on what it counts.
2727
*
2828
* Names are relative to this directory, which every file on the list lives in.
2929
*/

0 commit comments

Comments
 (0)