Test quality gate (rigor) — scripts/rigor-scan.sh runs rigor, a Rust-based static test quality analyzer, across tests/. Scans assertion quality, error coverage, boundary conditions, test isolation, input variety, and AI smells. Caches binary in ~/.cache/rigor/. CI gate at 60 (D-grade floor); pre-push hook via .husky/pre-push. npm run test:rigor runs locally.
pi-integration tests — tests/integration/pi-sandbox-install.test.ts and tests/integration/pi-session-lifecycle.test.ts verify the extension loads in a real pi sandbox via DefaultResourceLoader and createAgentSession. Catches "package builds but doesn't work when installed" bugs.
Test value scanner — scripts/scan-test-value.ts (heuristic) classifies test files as DELETE/REVIEW/OK. Used during audit to flag facade tests.
AGENTS.md Testing policy — firm rules: which test kinds to write (mutation-killing, edge-case, regression, property-based, integration with real I/O) and which to never write (snapshots, mocks-of-code-under-test, single-assertion-only, flaky, etc.). Includes "Test value scanner" and "Rigor quality gate" subsections.
Changed
tests/unit/state-real.test.ts rewritten from F-grade (57) to D-grade (60) with 41 tests, each explicitly named with the bug it catches ("Bug: ..." comments). Replaces weak toBeNull/toBeDefined assertions with toEqual/toBe. Documents renameWorkflow collision limitation (current behavior — duplicate names allowed).
tests/integration/architectural-invariants.test.ts (pre-existing untracked): flaky due to process.env.HOME shared across parallel tests; coverage redundant with concurrency.test.ts + orphan-workflow-recovery.test.ts + corrupt-tracking-recovery.test.ts.
Fixed
Plannotator tool type cast — replaced Promise<any> with explicit return type. Unified 5 returns to use {decision: string, feedback: string} so TDetails inference is consistent.
ctx.ui.notify(msg, "success") — success is not a valid kind in @earendil-works/pi-coding-agent@0.74+. Replaced with info in 6 call sites.
Property 2 (renameWorkflow preserves dirHash) flaky — generate raw new name and apply toSafeName() to model real rename behavior. Skips cases where toSafeName returns empty.
pi-sandbox tarball race — unlinkSync(tarballSrc) removed from pi-sandbox-install.test.ts and pi-session-lifecycle.test.ts because parallel runs caused ENOENT collisions. Source tarball now stays on disk (gitignored via calionauta-stelow-*.tgz).
readTracking crashed on array root JSON — added isTrackingShape defensive type guard. Returns null for non-tracking-shaped JSON ([], {}, primitives) instead of crashing in syncScopesIfNeeded.
Test metrics
51 test files (was 54, minus 3 deleted)
864 tests (was 988, restructured for stronger assertions in state-real)