Repository navigation
Commit 0744f94
feat(scripts): a third test-budget class, "compiles the package type graph once" (#23897)
Fixes #23821
Clause-②: no
The refresh diff's closed list of test-budget classes
(`TEST_BUDGET_CLASSES` in `scripts/measure-test-shard-timings.mjs`)
gains its third value, `compiles the package type graph once`. A test
file whose irreducible cost is one compile of its package's type graph
can now declare its own measured budget, under the same grammar, number
rule and refusals as the first two classes. One file changed: +107 /
−16.
## The ruling
Ruling record `6212133431` (letter A, the maintainer's 「同意」), which
extends ruling record `6181973363` on #23534 by one class. Verbatim:
> 1. **The class name** is `compiles the package type graph once`. It is
the third value of `TEST_BUDGET_CLASSES`
(`scripts/measure-test-shard-timings.mjs:1255-1258` at this read, two
values); the refusal at `:1295` and its text at `:1269` list three
classes; the self-test at `:2997` pins three.
> 2. **The number** stays ruling 6181973363 item 2: the measured CI
reading × 1.25, rounded up to the next 10 s, rising only by a PR that
re-measures and says why in the line. **The three prohibitions** (item
5) stand: no deletion without a named duplicate, no timeout raise, no
move to a slower or skipped project.
> 4. No `AGENTS.md` edit: `AGENTS.md:129-130` names the ruling record
and no class list.
Ruling item 3 (the two declarations themselves) is the spec lane's.
**The two header lines in
`packages/spec/src/contracts/scoped-context.test.ts` and
`packages/spec/src/integration/connector-author-shape.test.ts` follow on
#23180 in the spec lane once this lands.** This PR touches no
`packages/**` file, no workflow and no `AGENTS.md`.
## Every place in the script that changed
Line numbers are at `origin/main` `497518c3f`. They match the ruling's
read.
| Where (`origin/main`) | Before | After |
|:--|:--|:--|
| `:1225-1231`, the `readTestBudget` docblock | "(ruling record
6181973363, letter B)"; "Two classes …"; "A file of either class …" |
Cites both records. "Three classes …" names the third (a single compile
of the package's type graph, every probe after the first reading that
one program; ruling record 6212133431, letter A, which adds this class
and changes nothing else). "A file of any class …" |
| `:1239`, the grammar's CLASS row | "spelled as the ruling names it" |
"spelled as its ruling names it" |
| `:1255-1258`, `TEST_BUDGET_CLASSES` | two values | a third value,
`'compiles the package type graph once'` |
| `:1268-1269`, the refusal's text | "(ruling record 6181973363)";
`CLASS is "a" or "b"` | "(ruling records 6181973363 and 6212133431)";
`CLASS is one of "a", "b", "c"`, so every refusal lists all three
classes |
| `:1295`, the class refusal | `the class "X" is neither class the
ruling names` | `the class "X" is none of the 3 classes the rulings
name` (the count is read from the list) |
| `:1662-1664`, the battery roster | `'per-file budget declarations
(ruling 6181973363)': 14` | `18`, and the comment names ruling record
6212133431's cases |
| `:2982-2986`, self-test fixtures | `[producerClass,
wholePackageClass]` | adds `typeGraphClass`; `ruledClasses` (the three
spellings as **literals**); `specFileWith` (the two spec files' real
header, declaration on line 2); `typeGraphLine` (the ruling's line) |
| `:2996-2999`, the class pin | `length !== 2`, two spellings | `length
!== 3`, three spellings in order, against the literals |
| `:3019-3021`, the off-list class case | "a class naming neither" | "a
class naming none of them" (wording only) |
The only other places that cite the mechanism name no class and list
none, so they are unchanged:
- `:212-217` (`FILE_BUDGET_SECONDS`' doc);
- `:1545` (the rendered "Held to the budget it declares" line prints
each file's own class);
- the self-test section banner at `:2980`.
A tree-wide grep for `TEST_BUDGET_CLASSES`, either class phrase and
`test-budget` outside this script found only the 12 declaring test
files. It found nothing in `docs/`, `content/`, `.claude/`, `AGENTS.md`
or `.github/workflows/`.
## Proof the new value is read end to end
Four new self-test cases are in battery `per-file budget declarations
(ruling 6181973363)`, which grows from 14 to 18:
1. **Accepted.** The ruling's line, `// test-budget: 30 — compiles the
package type graph once: …`, sits under the exact header of the two spec
files (copyright line, then the declaration on line 2, where all 12
declarations in the tree sit). It reads as `{ seconds: 30, cls:
'compiles the package type graph once', line: 2 }`.
2. **The two earlier classes still read** in that same header, at 40 s
each. The third class took nothing from them.
3. **Near misses are refused loudly.** Six spellings are refused:
`type-graph`, a dropped `once`, a dropped `package`, `packages`, a
capital `C`, and a trailing space before the colon. Each refusal starts
with `f.test.ts:3: `, quotes the bad spelling, and names **all three**
classes.
4. **On disk, through `--diff`.** A file carrying the ruling's line goes
through `declaredBudgetInTree` and the real `diffMain`, with the same
CLI path as the existing round trip.
- At the card's slowest CI reading (18.1 s), it is held, not listed: ``
`src/integration/graph.test.ts` (`spec`) 18.10 s of its 30 s, compiles
the package type graph once ``.
- At 31 s it is listed against its own budget: `| ... | 31.00 (declared
30) | 1 / 1 |`.
**Ablation.** This was one-off, on `f8bacd05b` (the head), through
`scripts/ablation-replace.mjs` in WRAP mode, with a trap backstop on
absolute paths. No permanent mutation test remains. All four legs
restored to blob `5e2b82584d38`, which equals HEAD, and `git diff HEAD`
was empty after each.
| Leg | Mutation (anchor 1 → 0, blob changed) | Self-test reading |
|:--|:--|:--|
| 0 | battery pin 18 → 19 | exit 1: `registered 18 case(s), below its
pinned floor of 19`. The battery runs exactly 18. |
| 1 | delete the third value | exit 1 at the pin: `budget: the classes
read ["spawns the real producer once per single-cause
fixture","whole-package import"]` |
| 2 | control: the `check` thunk catches each failure and prints `RED`
instead of aborting; the value is present | exit 0, **zero** `RED` lines
|
| 3 | delete the third value **and** the leg-2 instrumentation | exactly
**four** `RED` lines; every other case stayed green |
The four `RED` lines in leg 3:
- the pin;
- case 1 (`scoped-context.test.ts:2: the class "compiles the package
type graph once" is none of the 2 classes the rulings name`);
- case 3 (the first near miss: the refusal no longer names a third
class);
- case 4 (the on-disk `--diff` refuses `graph.test.ts:2`).
Case 2 stayed green, as a control should.
**The 12 declarations on `main` read unchanged.** The script has no
dry-run mode, so a read-only probe imported the script's own
`readTestBudget` and read every file in `packages/`, `apps/` and
`examples/` that carries a `// test-budget:` line. The reading is the
same 12 files (10 producer-class, 2 whole-package), with identical
seconds, class, line and reason. The rows digest is `f1975b9e4af0…` at
both `497518c3f` (before) and `f8bacd05b` (after). The two spec files
read `null` on disk today. With the ruling's line spliced in at line 2
**in memory only**, each reads as the third class at 30 s.
## Tests
`node scripts/measure-test-shard-timings.mjs --self-test` printed
`measure-test-shard-timings: self-test OK`, exit 0, at `f8bacd05b`.
`pnpm exec eslint --no-inline-config
scripts/measure-test-shard-timings.mjs` exited 0. The control-byte scan
found nothing.
## Gates (local, at `f8bacd05b`, the final head)
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived **32** commands from git, against
merge base `497518c3f`.
- All 32 ran and all 32 exited **0**, each exit captured before any
pipe. They include:
- `pnpm check:pm-dispatch-gates`, run detached with its exit written to
a file: `✓ dispatch-gates self-test (fast tier): 1884 cases pass`;
- `check:nul-bytes`, `check:entry-guard` and
`check:cross-package-test-inputs`;
- the self-test wiring and anchor gates with their self-tests;
- the three shard-timing self-tests (`measure-test-shard-timings`,
`partition-test-shards`, `ci/select-shard-timings-run`).
- `--ran`: `✓ dispatch-gates --ran: 32 derived famil(ies) accounted for
— 32 run, 0 NOT-MEASURED (a DERIVED zero — all 32 recorded an exit code
and none of them is 3)`.
- `node scripts/pm/check-governed-merges.mjs --branch
claude/issue-23821-type-graph-budget-class` reported `0 of 1 path(s) hit
the register` (**NOT governed**), with 123 changed lines, under the
3,000 threshold.
- Every family CI runs is read from this PR's check-runs.
`scripts/**` ships in no package, so no changeset.
## Acceptance notes (not filed)
- **The battery's name still reads `(ruling 6181973363)`.** Renaming it
would only churn the roster. Its comment names both records. Carrier:
none.
- **No PR-time parse of a declaration (as in PR #23595).** The spec
lane's two lines are parsed only by the next weekly refresh. The spec
lane can check them locally before pushing:
```bash
node -e "import('./scripts/measure-test-shard-timings.mjs').then((m) =>
console.log(m.readTestBudget(require('fs').readFileSync(process.argv[1],
'utf8'), process.argv[1])))"
packages/spec/src/contracts/scoped-context.test.ts
```
---
_Generated by [Claude
Code](https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent a13fd4d commit 0744f94
1 file changed
Lines changed: 107 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1222 | 1222 | | |
1223 | 1223 | | |
1224 | 1224 | | |
1225 | | - | |
| 1225 | + | |
1226 | 1226 | | |
1227 | | - | |
| 1227 | + | |
1228 | 1228 | | |
1229 | | - | |
1230 | | - | |
1231 | | - | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
1232 | 1236 | | |
1233 | 1237 | | |
1234 | 1238 | | |
1235 | 1239 | | |
1236 | 1240 | | |
1237 | 1241 | | |
1238 | 1242 | | |
1239 | | - | |
| 1243 | + | |
1240 | 1244 | | |
1241 | 1245 | | |
1242 | 1246 | | |
| |||
1255 | 1259 | | |
1256 | 1260 | | |
1257 | 1261 | | |
| 1262 | + | |
1258 | 1263 | | |
1259 | 1264 | | |
1260 | 1265 | | |
| |||
1265 | 1270 | | |
1266 | 1271 | | |
1267 | 1272 | | |
1268 | | - | |
1269 | | - | |
| 1273 | + | |
| 1274 | + | |
1270 | 1275 | | |
1271 | 1276 | | |
1272 | 1277 | | |
| |||
1292 | 1297 | | |
1293 | 1298 | | |
1294 | 1299 | | |
1295 | | - | |
| 1300 | + | |
1296 | 1301 | | |
1297 | 1302 | | |
1298 | 1303 | | |
| |||
1660 | 1665 | | |
1661 | 1666 | | |
1662 | 1667 | | |
1663 | | - | |
1664 | | - | |
| 1668 | + | |
| 1669 | + | |
| 1670 | + | |
1665 | 1671 | | |
1666 | 1672 | | |
1667 | 1673 | | |
| |||
2979 | 2985 | | |
2980 | 2986 | | |
2981 | 2987 | | |
2982 | | - | |
| 2988 | + | |
| 2989 | + | |
| 2990 | + | |
| 2991 | + | |
2983 | 2992 | | |
2984 | 2993 | | |
2985 | 2994 | | |
2986 | 2995 | | |
| 2996 | + | |
| 2997 | + | |
| 2998 | + | |
| 2999 | + | |
| 3000 | + | |
| 3001 | + | |
2987 | 3002 | | |
2988 | 3003 | | |
2989 | 3004 | | |
| |||
2993 | 3008 | | |
2994 | 3009 | | |
2995 | 3010 | | |
2996 | | - | |
2997 | | - | |
| 3011 | + | |
| 3012 | + | |
| 3013 | + | |
| 3014 | + | |
| 3015 | + | |
| 3016 | + | |
| 3017 | + | |
2998 | 3018 | | |
2999 | 3019 | | |
3000 | 3020 | | |
| 3021 | + | |
| 3022 | + | |
| 3023 | + | |
| 3024 | + | |
| 3025 | + | |
| 3026 | + | |
| 3027 | + | |
| 3028 | + | |
| 3029 | + | |
| 3030 | + | |
| 3031 | + | |
| 3032 | + | |
| 3033 | + | |
| 3034 | + | |
| 3035 | + | |
| 3036 | + | |
| 3037 | + | |
| 3038 | + | |
| 3039 | + | |
| 3040 | + | |
| 3041 | + | |
| 3042 | + | |
| 3043 | + | |
| 3044 | + | |
| 3045 | + | |
| 3046 | + | |
| 3047 | + | |
| 3048 | + | |
| 3049 | + | |
| 3050 | + | |
| 3051 | + | |
| 3052 | + | |
| 3053 | + | |
3001 | 3054 | | |
3002 | 3055 | | |
3003 | 3056 | | |
| |||
3016 | 3069 | | |
3017 | 3070 | | |
3018 | 3071 | | |
3019 | | - | |
| 3072 | + | |
3020 | 3073 | | |
3021 | | - | |
| 3074 | + | |
3022 | 3075 | | |
3023 | 3076 | | |
3024 | 3077 | | |
| |||
3154 | 3207 | | |
3155 | 3208 | | |
3156 | 3209 | | |
| 3210 | + | |
| 3211 | + | |
| 3212 | + | |
| 3213 | + | |
| 3214 | + | |
| 3215 | + | |
| 3216 | + | |
| 3217 | + | |
| 3218 | + | |
| 3219 | + | |
| 3220 | + | |
| 3221 | + | |
| 3222 | + | |
| 3223 | + | |
| 3224 | + | |
| 3225 | + | |
| 3226 | + | |
| 3227 | + | |
| 3228 | + | |
| 3229 | + | |
| 3230 | + | |
| 3231 | + | |
| 3232 | + | |
| 3233 | + | |
| 3234 | + | |
| 3235 | + | |
| 3236 | + | |
| 3237 | + | |
| 3238 | + | |
| 3239 | + | |
| 3240 | + | |
| 3241 | + | |
| 3242 | + | |
| 3243 | + | |
| 3244 | + | |
| 3245 | + | |
| 3246 | + | |
| 3247 | + | |
3157 | 3248 | | |
3158 | 3249 | | |
3159 | 3250 | | |
| |||
0 commit comments