Skip to content

test(cli): budget the os dev / os serve / package spawn files, drop the tsx launcher from two - #28601

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-74yec7
Nov 1, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-74yec7

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Leehom · project thread

Part of #23181 (slice 25, the os dev / os serve / package family). The card stays open for the other slices.

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:packages/cli/test 里 6 个 os dev / os serve / 包相关的集成测试文件,各加一行第 2 行 // test-budget: 头(80 / 50 / 40 / 40 / 30 / 30 s);其中 2 个文件(package-restart-acceptance、package-owned-command-readers)把 spawn 方式从 node_modules/.bin/tsx bin/run-dev.js 改成 process.execPath bin/run-dev.js,同一个入口、同一份 src/,每次 spawn 少起一个 node 进程,本机 A/B 各快约 34%。
  • 为什么改:卡 test budget (domain:cli): 119 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23181 的测试提速职责:超过 10 s 的测试文件要么提速,要么按裁决 6181973363 B 声明预算。这 6 个文件里每次 boot/spawn 都是该文件要钉住的主体(重启、多次 boot 抓竞态、每条腿一个输入),没有重复的(命令、参数、夹具)三元组可合并,所以地板是真实工作,走 budget 头。
  • 风险与回滚:只改测试文件,不发布任何东西(cli 的 files[] 只有 dist、README、CHANGELOG);断言一条没删、没放宽,超时、层、项目都没动;回滚即 revert。
  • 先看:packages/cli/test/package-restart-acceptance.integration.test.ts(spawn 改为 process.execPath);packages/cli/test/package-owned-command-readers.test.ts(同上);其余 4 个文件只加了头。
  • 两分钟验证:pnpm --filter @objectstack/cli exec vitest run --project integration test/package-owned-command-readers.test.ts → 8/8 通过。
  • 需要你做的:无,席位落地。

What changes

Slice 23's offender table (pm-orders/server/evidence/23181-s23/offenders-after-s23.md in the project files) reads these six files over 10 s with no // test-budget: header. Readings are the default reporter's per-file module line in the Test Core shard logs of the five scheduled ci.yml runs 41199450735, 41217827347, 41237094739, 41255489006, 41271604267:

file 0735 7347 4739 9006 4267 header
dev-boot-output-order.integration.test.ts 59.0 59.4 41.9 53.6 47.2 80
package-restart-acceptance.integration.test.ts 19.7 27.2 21.9 34.4 35.1 50
package-owned-command-readers.test.ts 31.1 19.3 23.6 30.2 31.3 40
dev-organization-ownership-stale-column.integration.test.ts 28.9 29.0 18.1 25.2 21.1 40
dev-standalone-self-heal.integration.test.ts 12.5 16.7 13.5 22.9 22.6 30
serve-runtime-state-project-key.test.ts 19.7 19.0 12.0 17.5 14.8 30

Cause, per file. Every file already runs its boots or spawns once, in a beforeAll (or, for the runtime-state file, in the cases that read them). I counted them against distinct (command, flags, fixture) triples:

file tests boots / spawns distinct triples cause fix
dev-boot-output-order 3 5 boots of the built os dev (supervisor + serve child) under a real pty 5 (fresh database each) the boots are the subject: the order defect was a race one boot can miss; each boot also holds 2 s after the block and ends with a typed Ctrl+C header 80
package-restart-acceptance 5 2 boots of the source os serve --dev on one database file 2 the restart is the subject; each spawn went through the tsx binary, whose launcher (tsx/dist/cli.mjs) starts a second node process for the same entry process.execPath + header 50
package-owned-command-readers 8 6 source-CLI spawns, two alive at once 6 (doctor, diff --json, migrate meta --json over the two-package config and its one-package control) one spawn per distinct pair; same tsx launcher cost process.execPath + header 40
dev-organization-ownership-stale-column 5 2 boots of the built os dev on one database file (the second runs the upgrade ceremony) 2 the fresh boot creates the tables the stale shape is staged on; the second boot is the subject header 40
dev-standalone-self-heal 4 3 boots of the built CLI on one database file 3 (fresh os dev, restart over the staged index, production os serve) each boot is a leg the file pins header 30
serve-runtime-state-project-key 12 3 child processes publishing the state file 3 (project A, project B, a second boot of A) each child loads the real writer from src/commands/serve.ts through tsx, about 4 s of module load apiece; the file's own import of serve.ts is about 16 s locally. Distinct pids and a clean exit per child are the subject header 30

The tsx launcher. node_modules/.bin/tsx X runs tsx/dist/cli.mjs in one node process, which then spawns a second node process for X (checked: under tsx -e, process.ppid is a node …/tsx/dist/cli.mjs process). bin/run-dev.js runs straight under process.execPath, as slice 12 already does for other spawn files (serve-no-auth-secret-refusal, dev-standalone-self-heal, union-fold-command-parity): the same entry, the same src/, the same NODE_ENV that run-dev.js pins. Measured without the test manifest, node bin/run-dev.js diff --help took 5.1 to 5.2 s against 8.9 to 10.2 s through the tsx binary.

I tried the same move on serve-runtime-state-project-key (node --import tsx/dist/loader.mjs CHILD) and reverted it: about 4.0 to 4.3 s per child either way, because the cost there is loading serve.ts, not the launcher. Making the child lighter would mean moving the state writer out of serve.ts, a source change outside this slice.

Headers (ruling 6181973363 letter B, class spawns the real producer once per single-cause fixture): N = the slowest of the five CI readings × 1.25, rounded up to 10 s. The two files whose spawn changed keep their pre-change CI reading; a shard-timings refresh resizes them. All six parse with readTestBudget (scripts/measure-test-shard-timings.mjs): 80, 50, 40, 40, 30, 30, each at line 2.

Not changed: no assertion, case name, timeout, tier or project. No test helper (test/helpers/** is untouched). No source file.

Tests

  • A/B (one box, one lock hold, base copied beside head as zzbase-*, interleaved, N=3, --project integration --maxWorkers=1, the test manifest global setup on as in CI's queue tier; vitest's tests figure, and the whole Duration in brackets; copies deleted before the gate run):

    file base (s) head (s) change
    package-restart-acceptance 23.51, 23.06, 23.24 (32.98, 32.57, 32.91) 15.19, 15.55, 15.34 (24.65, 24.98, 24.72) −34% (mean 23.27 → 15.36)
    package-owned-command-readers 16.97, 17.18, 16.88 (29.32, 29.94, 29.59) 11.02, 11.25, 11.46 (23.09, 24.06, 24.15) −34% (mean 17.01 → 11.24)

    Every run exit 0; restart-acceptance 5/5 and owned-command-readers 8/8 on both sides, same names.

  • Header-only files, run once on head in the same lock hold: dev-boot-output-order 3/3 (tests 46.02 s), dev-organization-ownership-stale-column 5/5 (21.79 s), dev-standalone-self-heal 4/4 (17.17 s), serve-runtime-state-project-key 12/12 (17.86 s, import 16.53 s).

  • No ablation: no tested behaviour changed (test-only).

  • pnpm --filter @objectstack/cli typecheck (tsc + check:test-typecheck) exit 0 on 9a33975d, with NODE_OPTIONS=--max-old-space-size=4096.

Acceptance notes

  • skip-changeset. Test-only. @objectstack/cli's files[] is dist, README.md, CHANGELOG.md, and its build does not emit test/** into dist/, so no files[] content changes.
  • serve-runtime-state-project-key and package-owned-command-readers sit in vitest-tiers.ts's integration tier already (they spawn); nothing moved.

Verification

All readings on head 9a33975d (my commit eb79e981 plus one merge of origin/main after slice 23, #28581, landed; that merge touches none of these six files).

  • Derived gate families: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack → 48 families, each run with its exit code captured before any pipe, all exit 0. On the first round (before the merge) two were container prerequisites, re-read after meeting them: check-plugin-teardown-shape --self-test exit 3 (shallow clone) → git fetch --depth=1 of its pinned fixture commit → exit 0; check:dual-build-cjs-loads exit 3 (no full build) → pnpm exec turbo run build --concurrency=2 (118/118) → exit 0. The whole set then re-ran on 9a33975d. --ran reconciliation: ✓ dispatch-gates --ran: 48 derived famil(ies) accounted for — 48 run, 0 NOT-MEASURED (a DERIVED zero — all 48 recorded an exit code and none of them is 3). List with codes: pm-orders/server/evidence/23181-s25/gates-ran-9a33975d.txt in the project files.
  • Hand gates: pnpm exec eslint --no-inline-config over the six files exit 0 (@objectstack/cli has no lint script; the repo-wide pnpm lint is CI's); node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD exit 0.
  • CI families (Test Core with the cli integration tier, lint farm, type-check lanes) are read off this PR's check-runs by the seat.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FEkQ5peeAMkJqa2CHQj7ia

…the tsx launcher where it only adds a process

Six packages/cli test files read over 10 s in the scheduled ci.yml runs.
Each one's boots or spawns are the subject it pins, so each takes a line-2
test-budget header (slowest CI reading x 1.25, rounded up to 10 s).
package-restart-acceptance and package-owned-command-readers also spawn
bin/run-dev.js with process.execPath instead of the tsx binary: same entry,
same src/, one node process per spawn instead of two (about -34% each,
measured on one box, N=3).

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 1, 2026
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json cd065d3698db13969a28f46bf26f3e47e9ecc09c → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC

席位核对 · ACCEPT · domain:server seat 1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC · 2026-11-01T07:55Z

Head 9a33975d, report 6555077265 (on #23181), claim 6555115448 (slice 25). No contract review is owed: test-only, no packages/spec/** path, no governed path, no narrowing and no Clause-②: yes.

item reading
Shape Draft, base main, Part of #23181. Exactly slice 25's six packages/cli/test files, labels tests + skip-changeset. Clause-②: no, Metadata-protocol: none.
Diff check (seat) Line-2 // test-budget: headers on all six (80/50/40/40/30/30), each naming its distinct boots and the slowest CI reading × 1.25. package-owned-command-readers and package-restart-acceptance spawn bin/run-dev.js on process.execPath instead of the tsx binary, with argv, cwd, stdio and childEnv unchanged; the now-unused TSX import is dropped and the shared helper is not touched. No assertion changes; no timeout is raised.
Evidence CI green on head 9a33975d (35 success, 18 skipped, 0 failed). Mergeable state clean. Governed check: NOT governed, 17 changed lines. The report gives 48 of 48 derived gates exit 0, --ran 0 NOT-MEASURED, typecheck and scoped eslint exit 0, and A/B N=3 of about −34 % on each switched file.
Landing 「按照 pm-dispatch 规则复核过的都授权」 (Leehom, 2026-10-25T11:35Z): ready and auto-merge through the relay, once every check on this head is green or an expected skip.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 1, 2026 07:56
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 1, 2026 07:56
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 1, 2026
Merged via the queue into main with commit 87027c5 Nov 1, 2026
54 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-74yec7 branch November 1, 2026 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant