Repository navigation
Commit 51b9990
perf(spec): check:liveness reads each cited file once per run (#23535)
Part of #23180
Clause-②: no
**This PR takes no row off the card.** Both of the card's dominant
`@objectstack/spec` rows stay over the 10 s per-file budget after it,
and the card stays open for both:
- `scripts/liveness/check-liveness.test.ts` (`local` project) drops from
about 190 to 255 s to about 87 to 101 s locally: 2.2x to 2.9x, still
about 9x over.
- `scripts/build-schemas-check-mode.test.ts` (`repo` project) is
untouched, at about 900 s.
The measured floors for both files are in the `os-dev-report` comment on
the card, along with why neither can reach 10 s without weakening what
it proves. The seat's decision on that report is to land this speed-up
and send the budget question for this class of self-test to the
maintainer.
Dispatched by the `domain:spec` seat 4 PM (`sunhaolin`), claim comment
6175077909, branch `claude/issue-23180-spec-slowest-two`.
## What changed
`packages/spec/scripts/liveness/check-liveness.mts` is the only file
changed (+21/-6):
- `lineCountOf` and `contentOf` now read a cited file through one
per-run memo, `readCited`. It is keyed by the repo-relative path, and a
missing file is memoized as missing.
- Before, every citation re-read its file. One gate run read 455.8 MB in
2,367 reads over 828 files; `packages/rest/src/rest-server.ts` alone was
read 142 times. That was nearly half of each run's wall, and the
self-test pays it on every one of its roughly 66 gate spawns.
- After, one run reads 30.5 MB.
- Nothing in the repo changes during one gate run, so the memo cannot
change a verdict. The equivalence readings below measure that.
## Readings
All readings are local, taken through `bash scripts/pm/os-verify-lock.sh
-c` (each `VERDICT command-exit 0`). They are shared-box seconds: the
lock excludes only other locked runs, so ratios are the robust part.
**The self-test file**, as the vitest `default` reporter's module line
(the number the full battery records). Command:
```
env -u AI_AGENT -u CLAUDECODE -u CLAUDE_CODE -u CURSOR_AGENT NODE_OPTIONS=--max-old-space-size=4096 pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 scripts/liveness/check-liveness.test.ts --reporter=default
```
| tree | run 1 | run 2 | run 3 | cases |
|:--|--:|--:|--:|:--|
| before: the gate at `0be162c75d` | 190.5 s | 255.3 s | 251.3 s | 71/71
pass |
| after: the memo at `f6bcfe9c91` | 87.1 s | 87.4 s | 90.0 s | 71/71
pass |
| after: this head, merged with `origin/main` `b1cfa3d263` | 97.4 s |
93.8 s | 101.3 s | 71/71 pass |
CI's reading before was 493.4 s, in run `38332198724`. The CI reading
after is NOT MEASURED until the next refresh window lists this file
again.
**One `check-liveness.mts` run.** This is what `pnpm check:liveness`
pays on every lint run, and what the self-test pays per spawn:
| comparison | before | after |
|:--|:--|:--|
| the gate at `0be162c75d` vs the memo at `f6bcfe9c91` | 3.84 to 4.20 s
| 1.23 to 1.34 s |
| `origin/main`'s gate vs this head's gate, on this head's tree | 3.02
to 3.49 s | 1.37 to 1.45 s |
**The same verdicts.** `origin/main`'s gate (a temporary untracked copy
beside this one, deleted after) and this head's gate were run on the
same tree. Their output is byte-identical:
- default mode: 6,514 bytes, exit 0 on both;
- `--json` mode: 55,633 bytes, exit 0 on both.
**The same assertions.** `check-liveness.test.ts` is not edited. Every
assertion is the one on `main`, and all 71 pass.
## Ablation: the self-test still catches a broken memo
The mutation keys `readCited` by basename, so two different cited files
collide, for example `packages/objectql/src/engine.ts` and
`packages/services/service-automation/src/engine.ts`. It was applied
with `node scripts/ablation-replace.mjs` and its `-- CMD` form, which
arms the restore before it writes:
- **Mutation:** anchor count 1 to 0, blob `141dc51f5a62` to
`835c251a41e2`. On-disk counts: injected marker 1, removed
`citedText.set(p, text);` 0.
- **Mutant self-test:** exit 1, **24 of 71 cases red.**
- The green controls exit 1 instead of 0. On the verbatim-copy control,
the gate reports `✗ 57 anchored citation(s) name a symbol the cited file
does not contain` and `✗ 22 ... citation(s) name a file that never names
the property`.
- The anchor case `FAILS when an anchored symbol is gone ...` misses its
exact `✗ 1 anchored citation(s)` count.
- **Restore:** `blob == HEAD` (`141dc51f5a62`), `git diff HEAD` empty,
porcelain clean, marker count 0.
- The source is run directly by tsx, so there is no `dist/` in the path.
## Why it stops here
**`build-schemas-check-mode.test.ts`:**
- Each of its 88 cases runs the real generator on its own fixture: about
96 runs at 8.5 to 9.0 s warm.
- Most of each run is Zod `toJSONSchema` over about 1,700 schemas, plus
git and an output rewrite.
- The median case alone takes 9.07 s.
**`check-liveness.test.ts`:**
- Its floor is about 43 distinct one-cause fixtures times one gate run.
- An in-process route measured about 7.4 s locally with zero margin, and
it reverses the file's spawn-the-real-gate design.
- Sharing the identical-state runs inside the test is left out: a case
would read another case's run, and the file's own hook-budget block
scans `runGate`'s reach to `spawnSync`.
## Changeset
None, because nothing publishes.
- `packages/spec`'s `files[]` does not list `scripts/`.
- Measured on the packed tarball (`pnpm pack` after `pnpm --filter
@objectstack/spec build`, 2,091 files):
- no `scripts/` path;
- 0 files contain `readCited`, `citedText` or the pre-existing gate-only
`EVIDENCE_SCANNED_STATUSES`;
- positive control: `listMetadataTypeSchemaTypes` is in 14 files.
- Hence `skip-changeset`.
## Gates
Derived at this head (`62adc640c1`) with `node
scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`: 55 commands. All 55 were run, with each
exit code captured before any pipe. The `--ran` reconciliation reads `55
derived famil(ies) accounted for — 53 run, 2 NOT-MEASURED (2 DERIVED
from a recorded exit 3)`, 0 UNRUN.
- **53 exit 0.** These include `pnpm --filter @objectstack/spec run
check:liveness`, `check:nul-bytes`, `check:issue-citations`,
`check:doc-authoring`, `check:cross-package-test-inputs`,
`check:test-source-alias`, `check:published-files`,
`check:closing-keyword-parity` and `check:pm-dispatch-gates`.
- **NOT MEASURED: `pnpm check:dual-build-cjs-loads` and `pnpm
check:lean-entry-closure`.** Reason: PREREQUISITE NOT MET. They load
other packages' built `dist/` entries, and only `@objectstack/spec` was
built locally. Neither can read an unshipped file under
`packages/spec/scripts/`. CI runs both.
- **Changeset readings beyond the derivation, all exit 0:** `pnpm
check:changeset-gate-self-tests`, `node
scripts/check-empty-changeset.mjs`, `node
scripts/check-changeset-no-major.mjs --base origin/main` and `pnpm
check:published-files`.
## Acceptance notes
- Option D from the report, a ruling on the 10 s line for gate
self-tests that spawn the real gate once per one-cause fixture, is the
maintainer's. It is not part of this PR.
- The merge commits from `origin/main` carry git's default message.
---
_Generated by [Claude
Code](https://claude.ai/code/session_0121ooBYRmS8ziFXm9ai5YHm)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent fba3712 commit 51b9990
1 file changed
Lines changed: 21 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
793 | 793 | | |
794 | 794 | | |
795 | 795 | | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
796 | 814 | | |
797 | 815 | | |
798 | 816 | | |
799 | 817 | | |
800 | 818 | | |
801 | 819 | | |
802 | 820 | | |
803 | | - | |
804 | | - | |
805 | | - | |
| 821 | + | |
| 822 | + | |
806 | 823 | | |
807 | 824 | | |
808 | 825 | | |
| |||
811 | 828 | | |
812 | 829 | | |
813 | 830 | | |
814 | | - | |
815 | | - | |
816 | | - | |
| 831 | + | |
817 | 832 | | |
818 | 833 | | |
819 | 834 | | |
| |||
0 commit comments