Skip to content

Commit 4166a92

Browse files
test(rest): execctx-consumer-census derives its structural reading from the tree instead of hand counts (#26520)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"} --> _Requested by **Leehom** · [project thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XEmF9eLLFeZERpmZYEPkSMB)_ Fixes #26436 Part of #26431 Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么**:`execctx-consumer-census.test.ts` 里所有手数的数字(调用点 62、提及 145、caught/bare/同行 16/46/12、迁出注册器 4/4、文件数 18)和每次拆分 `rest-server.ts` 留下的重数记录全部删掉,换成一条从源码推导的规则:每个 `resolveExecCtx` 调用点,要么是「裸调用,下一行就是共享的匿名拦截」,要么是「自带 catch,且不在那道拦截后面」。 - **为什么改**:这些数字每拆一次文件、每增删一个路由都得手改,最近 30 天改了两次,红史全是「代码正常变了、数字没跟上」。#13160 要的答案(执行上下文缺失时每个消费点意味着什么)已经写在文件散文和行为测试里,数字本身什么都不证明。 - **风险与回滚**:只动一个测试文件,不发布任何包;回滚就是 revert 本 PR。驱动路由、看真实应答的行为测试(§1、§3–§9)全部保留,新规则在三次消融里都按预期变红。 - **先看**:`packages/rest/src/execctx-consumer-census.test.ts` 的 §2(新规则及其两个对照);同文件 §3 新增的「每次调用都归属到一个已普查调用点」对照。 - **两分钟验证**:`pnpm --filter @objectstack/rest exec vitest run src/execctx-consumer-census.test.ts`,预期 27 个用例全绿。 - **需要你做的**:无,席位落地。 ## What changes One file, `packages/rest/src/execctx-consumer-census.test.ts`. Seat ruling arm **(b)**: the invariant holds today, so the file stays and its counts go. - **§2 (the count block) is replaced by ONE derived assertion**: every `this.resolveExecCtx(environmentId, req)` site in every file on `REST_SERVER_REGISTRAR_FILES` is EITHER bare with `if (this.enforceAuth(req, res, context)) return;` as its very next statement, OR locally caught and not behind that floor. A failure names each site out of shape. Two derived controls sit in the same case: (i) completeness, no line in a censused file calls `resolveExecCtx` in any spelling other than a site, a host literal's forwarder or the method's declaration, so the partition cannot silently narrow; (ii) neither half of the partition is empty. - **Gone**: `SITE_FILES` length 18, `SITES` 62, 145 mentions, 16 / 46 / 12, the `EXTRA_MOVED_REGISTRARS` and `MOVED_REGISTRARS_READING_NO_EXECCTX` hand maps (4 / 4) with the forwarder-count arithmetic, the per-slice recount docblocks and the ten-entry recount changelog inside §2. - **What the forwarder-count pin used to catch is kept, derived**: `instrument()` now records a call no censused frame made as `(no censused frame)` instead of dropping it, and a new §3 control asserts that every call the mounted table makes, under the FULL and the ISOLATED mounts, is attributed to a censused site. A registrar body moved to a module that never joined the list reds there (ablation C below). A respelt forwarder reds the §2 completeness control. - **Counts that restated the population elsewhere now compare site by site**: §3's `rows.length >= 46` becomes "the rows cover every bare site"; §7's `>= 12` inline / `>= 4` continuation floors become equality with the site table's own reading of where each catch sits, per site, plus both layouts non-empty; §8's `>= 4` becomes non-empty. Titles and prose that stated a population count ("the 46 bare sites", "the 20 locally-caught sites", "the four continuation sites", "four of the inner sites") are reworded without the number. Per `describe` block (the triage asked for this): | block | before | after | |:--|:--|:--| | §1 supplier fulfils `undefined` | behaviour | stays, unchanged | | §2 counted from the tree | pins counts | goes; replaced by the one derived invariant | | §3 bare sites, driven | behaviour + a count floor | stays; floor derived; attribution control added | | §4 locally-caught sites | behaviour | stays; title count removed | | §5 public-audience carve-out | behaviour | stays, unchanged | | §6 boundary (packages door) | behaviour | stays, unchanged | | §7 catch argument | behaviour + count floors | stays; floors derived per site | | §8 total outage at continuation sites | behaviour + a count floor | stays; floor derived | | §9 partial outage | behaviour | stays, unchanged | ## Why The card (`Part of` the transcription-pin parent): the file pinned hand counts that every `rest-server.ts` split slice had to retype, and the question it answers (#13160, what an absent execution context means at each consumer) is a one-time reading already recorded in its prose. The derived rule is the reading the file itself recorded as its structural finding ("the bare sites are bare BECAUSE the shared anonymous floor is the next statement; the locally-caught ones carry a `.catch` because they are NOT behind that floor"), now asserted as a rule instead of as 46 and 0. It reds on #13160's defect shape: a consumer that takes the context bare and proceeds with nothing deciding the absent context beside it. ## Tests - `pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/execctx-consumer-census.test.ts`: 27 / 27 pass (28 before: §2's three cases became one, §3 gained one). - `pnpm --filter @objectstack/rest test` (under the shared verify lock, VERDICT command-exit 0): Test Files 324 passed (324), Tests 6482 passed, 326 skipped. - `pnpm --filter @objectstack/rest typecheck` (`tsc --noEmit && pnpm check:test-typecheck`): VERDICT command-exit 0. - `eslint packages/rest --no-inline-config`: exit 0, no output. <details><summary>Ablations — three legs, each through scripts/ablation-replace.mjs, each restored to the HEAD blob with git diff HEAD empty</summary> The suite reads `src/` directly (relative import of `./rest-server.js`, same package), so no `dist` leg applies. - **A — #13160's shape**: delete `if (this.enforceAuth(req, res, context)) return;` under the bare site in `email-routes.ts` (anchor 1 → 0, blob `30a8f5a0c886` → `8b44d5e1a6f3`). 2 failed / 25 passed: §2 names `email-routes.ts:77 — bare, and NOT followed by the shared floor`; §3's driven case reads `POST /api/v1/email/send under an absent context: expected 200 to be 401`, the absent context served. Restored, blob == HEAD `30a8f5a0c886`. - **B — a site respelt out of the census' reading**: `this.resolveExecCtx(environmentId, req)` → `this.resolveExecCtx(environmentId,req)` in `email-routes.ts` (blob `30a8f5a0c886` → `19282f570843`). 2 failed / 25 passed: §2's completeness control lists `email-routes.ts:77: const context = await this.resolveExecCtx(environmentId,req);`; §3's attribution control lists `POST /api/v1/email/send ← email-routes.ts:77`. Restored, blob == HEAD. - **C — a moved module that never joined the list** (the case the retired forwarder-count pin caught): delete `'email-routes.ts',` from `REST_SERVER_REGISTRAR_FILES` (blob `fa939290f54d` → `1f4b4e2e8c74`). 1 failed / 26 passed: §3's attribution control lists `POST /api/v1/email/send ← (no censused frame)`. Restored, blob == HEAD `fa939290f54d`. </details> ## Acceptance notes - No literal site / mention / shape count remains: `SITE_FILES` 18, `SITES` 62, 145, 16 / 46 / 12 and 4 / 4 are gone from code and prose; no `toHaveLength` remains in the file. - Two anti-vacuity floors on driven ROUTE rows (not site counts) are left as they were: §3's control serves at least 30 bare-site rows with a 2xx (measured 38 at the branch head), §4's umbrella case drives more than 10 `/meta` rows with a site (measured 19). Both sit below the measurement with margin, which is the floor family #26444 keeps. - Historical readings that name line numbers at a past revision (§8's and §9's ablation records) are kept as records; they are not counts. - Sibling #26433 edits six other `packages/rest` test files; no open PR touches this file or `rest-server-registrar-files.ts` (all open PRs' file lists read at the start of the work and again before opening this one). - `skip-changeset`: the file is not published (`@objectstack/rest` `files` is `dist`, `README.md`, `CHANGELOG.md`, and tsup's entry is `src/index.ts`). No `resolveExecCtx` docblock was touched (that was arm (a)). ## Verification All local readings at branch head `fd29a1d26`, against merge base `45de8c6cb`. - Gate families derived by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` on the real diff: 49. Each run with its exit code captured before any pipe; `--ran` reconciliation: "49 derived famil(ies) accounted for — 48 run, 1 NOT-MEASURED". - 47 exited 0 on the first pass, including `check:type-check-debt` (0 raw tsc errors, none above its recorded number), `check:cross-package-test-inputs`, `check:test-source-alias`, `check:nul-bytes`, `check:issue-citations` and `check:doc-authoring`. - `node scripts/check-plugin-teardown-shape.mjs --self-test` exited 3 on the first pass (its pinned positive-control commit was outside the shallow clone); after fetching that commit it exits 0 ("48 cases pass"). - NOT MEASURED: `pnpm check:dual-build-cjs-loads`, exit 3, PREREQUISITE NOT MET (the worktree built only the `@objectstack/rest` dependency closure, so other packages have no `dist/`). CI runs it. - Families CI owns (Lint & Repo Gates, TypeScript Type Check, Test Core and the rest) are read from this PR's check-runs, not re-run here. - Dogfood battery: n/a — no `!` in the title and no `(narrowing)` arm. ## 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. - [x] 3. No formatter ran; `pnpm lint` passes (scoped to the touched package; CI runs the repo-wide scan). - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset — this one publishes nothing; both declaration lines are filled in here. - [x] 6. `packages/spec` touched: 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 maintainer brief is Chinese by convention). - [x] The *Before Submitting* list in CONTRIBUTING.md is done. --- _Generated by [Claude Code](https://claude.ai/code/session_01FEkQ5oi3XkDNLtE2KCnbvV)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 347adbd commit 4166a92

1 file changed

Lines changed: 136 additions & 591 deletions

File tree

0 commit comments

Comments
 (0)