Verification — debug-startup-smoke-flake
Step 5 of the 5-step executor chain. Captures the test evidence that the contract in
docs/contracts/debug-startup-smoke-flake-contract.mdhas been fulfilled.
Acceptance gates
| Gate | Result | Notes |
|---|---|---|
npm run build |
green | tsc exits 0; no type errors. |
npm run lint |
green | eslint src exits 0; the inline // eslint-disable-next-line no-console covers the diagnostic-emit line. |
5 sequential npm test runs |
5/5 green | All 1357 tests pass; wall time 20.7–21.3 s per run. See “Run-by-run evidence” below. |
Pre-fix (baseline) reproduction
Before applying the fix, the standalone tsx cold-start measurement showed:
| Run | Time to [Startup] Phase 1 |
|---|---|
| 1 (cold) | 4205 ms — exceeds the old 3000 ms spawnSync timeout by 40 % |
| 2 | 3055 ms — also over budget |
| 3 | 1439 ms |
| 4 | 1799 ms |
| 5 | 1864 ms |
A 10-run pre-fix npm test reproduction (after clearing node_modules/.cache):
RUN 1: 1357 passed
RUN 2: 1 failed, 1356 passed ← startup — subprocess smoke
RUN 3: 1357 passed
…
RUN 10: 1357 passed
Pre-fix flake rate: ~10 % (1/10).
Post-fix verification
Run-by-run evidence (10 sequential runs, fresh node_modules/.cache cleared before run 1)
=== RUN 1 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 21.012 s
=== RUN 2 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 21.250 s
=== RUN 3 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 21.037 s
=== RUN 4 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 20.727 s
=== RUN 5 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 21.109 s
=== RUN 6 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 21.180 s
=== RUN 7 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 21.024 s
=== RUN 8 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 21.036 s
=== RUN 9 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 20.752 s
=== RUN 10 ===
Test Suites: 30 passed, 30 total
Tests: 1357 passed, 1357 total
Time: 20.712 s
Post-fix flake rate: 0 % (0/10) for startup — subprocess smoke.
Build gate
$ npm run build
> colibri@0.0.1 build
> tsc
$ echo $?
0
Lint gate
$ npm run lint
> colibri@0.0.1 lint
> eslint src
$ echo $?
0
Contract compliance
| Contract clause | Status |
|---|---|
| Test passes deterministically in isolation | YES — npm test -- --testPathPattern=startup is the original isolated condition; still green. |
| Test passes deterministically under full-suite parallel | YES — 10/10 green at default Jest maxWorkers (~7 on dev box). |
Subprocess invocation preserved (tsx src/server.ts end-to-end) |
YES — same spawnSync(process.execPath, ['--import', 'tsx', SERVER_MODULE_FS_PATH], …) invocation. Only the timeout literal changed. |
[colibri] starting and [Startup] Phase 1 regex assertions preserved |
YES — both regex matches unchanged at lines 822 and 824 of the modified test file. |
No .skip() / .todo() |
YES — the test still runs every invocation. |
| Named timeout constants | YES — STARTUP_SUBPROCESS_TIMEOUT_MS = 30_000, STARTUP_SUBPROCESS_TEST_TIMEOUT_MS = 35_000. |
| Diagnostic enrichment on failure | YES — console.error emits subprocess status / signal / error / truncated stdout+stderr only when an assertion is going to fail. Green-path output is unchanged. |
| No production code changes | YES — git diff origin/main...HEAD --stat shows zero src-side .ts files modified (only the test file + 4 docs). |
Out-of-band observations
-
Pre-existing unrelated
tools/merkle.test.tsflake. During one transition between cache-clear and warm batches in the verification pass, a singletools/merkle.test.tsfailure surfaced (Test Suites: 1 failed, 29 passed; Tests: 1314 passed, 1314 total— note: no1 failedcount, suggesting the suite crashed during load, not during a test). It did not reproduce in any of the 10 contiguous post-fix runs. This is out of scope for this task but worth flagging in memory for whoever picks up suite-wide flake hygiene next. -
No production bug surfaced. Per the task escalation clause, the audit explicitly checked
src/server.ts,src/startup.ts, andsrc/db/index.tsfor genuine race conditions. None were found. The flake is purely the timing race between the subprocess cold start and the externally-imposedspawnSyncdeadline. No escalation needed. -
Diagnostic enrichment was not exercised in the verification pass — every post-fix run was green, so the on-failure
console.errorbranch never fired. This is the desired outcome (no failures means no diagnostic output). The branch’s correctness is type-checked bytsc(build green) and lint-checked byeslint(lint green); a future regression will be the first real test of its output.
Files changed
.worktrees/claude/debug-startup-smoke-flake/
├── docs/
│ ├── audits/debug-startup-smoke-flake-audit.md [new]
│ ├── contracts/debug-startup-smoke-flake-contract.md [new]
│ ├── packets/debug-startup-smoke-flake-packet.md [new]
│ └── verification/debug-startup-smoke-flake-verification.md [new — this file]
└── src/
└── __tests__/
└── startup.test.ts [edited — +40 / −2]
No src/server.ts, src/startup.ts, src/db/index.ts, or any other production source modified.
Conclusion
The flake is fixed. The contract is met. All three gates (build, lint, test × 5) are green.