Repository navigation
Commit 4166a92
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
0 commit comments