id: PX-PLAN-XQFSKHHG
type: plan
title: Layered Test Architecture and Owned Fixture
spec: PX-SPEC-DZLVGRW4
status: draft
depends_on:
PX-PLAN-RMJ8BIOX
Outcome
Tests are separated by guarantee: unit, Pi contract, native integration, generated package, UI acceptance.
A repository-owned fixture replaces the text-patched @marcfargas/pi-test-harness.
One Vitest coordinator runs all source layers with required isolation; TypeScript checking covers every maintained file.
Verified current state: scripts/patch_pi_test_harness.mjs rewrites installed harness files at install; 37 extensions have __tests__/harness.test.ts; test/harness.ts wraps the harness; vitest.config.ts has four projects; tsconfig.json excludes tests, benches, scripts, and the-system/index.ts.
Behaviors
flowchart TB
t1["1. Owned fixture runs ultra contract test unpatched"] --> t2["2. All harness tests migrate; patch script deleted"]
t2 --> t3["3. Layer projects in one Vitest coordinator"]
t3 --> t4["4. Generated-package project runs snapshots outside checkout"]
t3 --> t5["5. Complete typecheck; focused check per extension"]
t4 --> t6["6. UI acceptance runs against generated browser artifacts"]
test/fixture/ exposes createPiSession built on public createAgentSession, SessionManager.inMemory, ModelRuntime, and a deterministic scripted provider; owns temp dirs, env, sockets, timers, shutdown; rejects on any unexpected extension or async error.
extensions/ultra/__tests__/harness.test.ts becomes contract.test.ts on the fixture.
Migrate remaining harness.test.ts files; remove the harness devDependency from every extension manifest, test/harness.ts, scripts/patch_pi_test_harness.mjs, and the install step; static check requires __tests__/contract.test.ts.
vitest.config.ts projects by guarantee: unit (isolate false, workers), contract (isolate true), native (isolate true, one worker, per-file process env), web, strata retained as native members; validator folds into native.
Property tests live in unit with seeded runners and retained regression cases.
packages project: for each dist/<name> snapshot in a temp root, install an independent Pi version, load, assert manifests, resources, lazy first use, workers, allowed externals, no workspace leakage; one composite run for the complete collection.
Runs only when dist exists; //:verify-packages from the packages plan becomes this project.
tsconfig.json includes tests, benches, fixtures, workers, browser entrypoints, build and codegen TypeScript; per-extension tsconfig.json extends root and includes shared test/ inputs; //extensions/<name>:check runs focused tsc -p; root //:check runs the union once.
Convert remaining .mjs automation to TypeScript unless it bootstraps the build.
Playwright suites (mockup, strata, the-system, chrome-cdp, klaus) serve generated browser assets from dist/<name> rather than source.
mise run //:install performs no dependency patching.
No extension depends on @marcfargas/pi-test-harness.
//:test runs one coordinator with layered projects; contract and native retain isolation.
packages project passes for every extension and the composed collection.
tsc covers all maintained TypeScript; //extensions/ultra:check typechecks only ultra plus shared inputs.
UI acceptance loads assets from dist.
---
id: PX-PLAN-XQFSKHHG
type: plan
title: Layered Test Architecture and Owned Fixture
spec: PX-SPEC-DZLVGRW4
status: draft
depends_on:
- PX-PLAN-RMJ8BIOX
---
## Outcome
Tests are separated by guarantee: unit, Pi contract, native integration, generated package, UI acceptance.
A repository-owned fixture replaces the text-patched `@marcfargas/pi-test-harness`.
One Vitest coordinator runs all source layers with required isolation; TypeScript checking covers every maintained file.
Verified current state: `scripts/patch_pi_test_harness.mjs` rewrites installed harness files at install; 37 extensions have `__tests__/harness.test.ts`; `test/harness.ts` wraps the harness; `vitest.config.ts` has four projects; `tsconfig.json` excludes tests, benches, scripts, and `the-system/index.ts`.
## Behaviors
```mermaid
flowchart TB
t1["1. Owned fixture runs ultra contract test unpatched"] --> t2["2. All harness tests migrate; patch script deleted"]
t2 --> t3["3. Layer projects in one Vitest coordinator"]
t3 --> t4["4. Generated-package project runs snapshots outside checkout"]
t3 --> t5["5. Complete typecheck; focused check per extension"]
t4 --> t6["6. UI acceptance runs against generated browser artifacts"]
```
1. `test/fixture/` exposes `createPiSession` built on public `createAgentSession`, `SessionManager.inMemory`, `ModelRuntime`, and a deterministic scripted provider; owns temp dirs, env, sockets, timers, shutdown; rejects on any unexpected extension or async error.
`extensions/ultra/__tests__/harness.test.ts` becomes `contract.test.ts` on the fixture.
2. Migrate remaining `harness.test.ts` files; remove the harness devDependency from every extension manifest, `test/harness.ts`, `scripts/patch_pi_test_harness.mjs`, and the install step; static check requires `__tests__/contract.test.ts`.
3. `vitest.config.ts` projects by guarantee: `unit` (isolate false, workers), `contract` (isolate true), `native` (isolate true, one worker, per-file process env), `web`, `strata` retained as native members; `validator` folds into `native`.
Property tests live in `unit` with seeded runners and retained regression cases.
4. `packages` project: for each `dist/<name>` snapshot in a temp root, install an independent Pi version, load, assert manifests, resources, lazy first use, workers, allowed externals, no workspace leakage; one composite run for the complete collection.
Runs only when `dist` exists; `//:verify-packages` from the packages plan becomes this project.
5. `tsconfig.json` includes tests, benches, fixtures, workers, browser entrypoints, build and codegen TypeScript; per-extension `tsconfig.json` extends root and includes shared `test/` inputs; `//extensions/<name>:check` runs focused `tsc -p`; root `//:check` runs the union once.
Convert remaining `.mjs` automation to TypeScript unless it bootstraps the build.
6. Playwright suites (`mockup`, `strata`, `the-system`, `chrome-cdp`, `klaus`) serve generated browser assets from `dist/<name>` rather than source.
## Fixture structure
```mermaid
classDiagram
PiSession --> ScriptedProvider : streams
PiSession --> ResourceOwner : owns
PiSession --> ErrorSink : fails on
ContractTest --> PiSession : loads entrypoint
PackageTest --> PiSession : loads dist snapshot
```
Touched: `test/fixture/*`, `test/harness.ts` (removed), `scripts/patch_pi_test_harness.mjs` (removed), `mise.toml` install task, `vitest.config.ts`, `tsconfig.json`, `extensions/*/tsconfig.json`, `extensions/*/__tests__/*`, `extensions/*/package.json`, `scripts/extensions.mjs` static check, `extensions/*/playwright.config.ts`.
## Constraints
- No private Pi properties, no `as any` reach into agent internals; if the public API lacks a hook, the fixture narrows scope rather than patching.
- Concurrent sessions in one process share `process.env`; tests needing distinct env run in `native` with process isolation.
- Snapshots normalize volatile paths, timestamps, identifiers.
## Verification
- [ ] `mise run //:install` performs no dependency patching.
- [ ] No extension depends on `@marcfargas/pi-test-harness`.
- [ ] `//:test` runs one coordinator with layered projects; contract and native retain isolation.
- [ ] `packages` project passes for every extension and the composed collection.
- [ ] `tsc` covers all maintained TypeScript; `//extensions/ultra:check` typechecks only ultra plus shared inputs.
- [ ] UI acceptance loads assets from `dist`.