# Testing and coverage

This is the maintained guide to reproducing pi-tidy-ui checks, not a journal of past runs. Use a repository checkout; the npm package contains runtime code/documentation, not the harness or fixtures. Visual behavior is specified in the [presentation contracts](README.md#extension-host-and-presentation); the root [user guide](../README.md) explains everyday use, and integration boundaries are described in [architecture](architecture.md).

Current [platform support](releases.md#supported-platforms) is GNU Linux x64/ARM64, macOS x64/ARM64 and Windows x64. **Windows ARM64 is temporarily unsupported for the entire extension** because of disproportionate verification cost. Windows ARM64 stays in the central platform catalogue but is disabled unless repository Actions variable `CI_WINDOWS_ARM64=true`; enabling that platform or citing a historical pass does not establish restored support.

## Requirements and commands

- Node.js >=22.19.0. CI selects exact Node 22.19.0 and 26.7.0.
- An explicitly prepared Pi dependency graph. The compatibility matrix selects minimum Pi 1.0.1 and the exact version resolved once from npm's public `latest` dist-tag during workflow planning, never an independently moving tag or an installed CLI. CLI, SDK, TUI, AI/core, extension imports, type checks and child probes must use the selected coherent graph; Pi-family package version strings need not all be equal.
- For native preparation: provisioned Rust **1.99.0**, including rustfmt and Clippy, and platform compiler/linker prerequisites. User Cargo configuration is not an input.
- For physical CLI tests: POSIX, declared Python 3 with PTY support and the prepared CLI. Python runs with `-I -S`, excluding environment/user/global site startup customizers. No model credentials are needed: the driver uses an offline scripted provider.
- The Linux suspend entries under `cli/native/syntax/linux/` and `cli/shared/syntax/linux/` require real shell job control plus `/proc` stopped-helper evidence; they are platform-inapplicable elsewhere. Four independent transport/terminal-mode files each run SOURCE, STYLE and incremental append serially: all twelve semantic cases, 45-second case bounds and actual 4.5-second stopped intervals remain. They prove bounded wake recovery, physical current/new cards and idle/warm reuse; they do not mock request settlement or defer an already-delivered reply.
- For actual native/owned-syntax CLI tests: a verified same-source Occipital artifact. Only selected shared tests additionally require an explicit Subconscious host executable. Only selected installed-profile tests require `--integration`. Neither prerequisite is imposed by unrelated footer/editor/card tests. Native launch fixtures follow the documented [Occipital executable modes](occipital/runtime.md#executable-entry) and isolate process state with private working, HOME and XDG roots; the daemon has no `--config` argument.

### Real SDK fixture boundaries

- Offline tool fixtures import schema builders from the host's `typebox` package, not optional `pi-ai` re-exports.
- Prototype-based `InteractiveMode` fixtures initialize host-owned fields used by real public UI methods, including an empty `extensionDialogs` stack for the no-open-dialog state. Native activity probes release their fixture-owned indicators in `finally` even after assertion failure; restoring Toolview deliberately does not dispose Pi's native activity clock.
- Real `highlightCode()` fixtures install the same active theme instance that their palette input samples and update both on theme changes. Loading a standalone theme alone does not initialize Pi's classifier; general bootstrap must not substitute an unrelated default theme.
- Renderer-replacement controls explicitly invalidate the native component before checking the new callback composition. Argument-update controls instead observe replacement after a real native frame: streamed `updateArgs()` may defer composition until that frame. Edit-preflight witnesses are armed after the argument update itself, which may independently request a frame.
- Old-argument WeakRef controls require collection while the custom owner remains attached. Deferred native composition does not justify retaining prior input or forcing a native frame. A stock baseline measures SDK composition per argument update; the custom adapter must add none across several deltas, materialize neither slot on custom frames, and provide the latest arguments when a retained native leaf is accessed directly. Removing the result callback after initial stock ownership excludes that owner from adapter-only argument synchronization, including after replacing the call callback with a foreign function; absent callbacks cannot establish registered-pair membership. Genuine eager SDK callback generations remain authoritative. See [lazy ownership](host-integration.md#lazy-stock-writeedit-renderers).

### Ordinary feature work

Start with one explicit graph (Linux, Node 22.19.0, Pi 1.0.1), not the operator's Pi or the entire compatibility matrix. A fresh Git clone with its reachable release history/tags is sufficient: no historical `.test-artifacts`, repository `node_modules`, installed Pi or personal transcripts are needed. The preparer itself uses Node built-ins and installs the selected graph into its owned runtime; do not install a second graph in the checkout first. Provision Node/npm compatible with each other, Git and the platform tools below. On local Linux graphical sessions, wrap **all fallible test commands below** in the [verified ordinary scope](#local-memory-containment-and-assertion-diagnostics); raw runner examples show selection arguments, not permission to run uncontained.

```sh
npm run test:prepare -- --pi-version 1.0.1 --output /absolute/path/to/feature-inputs
INPUTS=/absolute/path/to/feature-inputs/inputs.json

# Tight edit loop: refresh sources without reinstalling/copying the sealed dependency tree.
node scripts/test/prepare.mjs --refresh-inputs "$INPUTS"
npm run test:group -- --inputs "$INPUTS" --groups footer --layer node

# Feature acceptance: types + common product SDK/logic/GC + smoke + affected real CLI.
npm run test:feature -- --inputs "$INPUTS" --features footer --refresh --output /absolute/path/to/footer-receipts
```

Replace `footer` with a comma-separated combination of `summaries,bash,edit,write,user,queued,editor,footer,layout,lifecycle,activity,settings,terminal-colors,logging,syntax,native,shared,profile,harness,delivery`. A coupled test belongs to one file but may be selected by multiple domains; the command de-duplicates it. `--features ''` is the common baseline. `--affected-only` is a local composition/debugging option that omits the common baseline and default type stage, not a CI selection mechanism or replacement for feature acceptance. Add `--check-types` to retain types with that local option. CI independently runs its fixed complete suites; a local feature command is not equivalent to full CI.

`--refresh`/`--refresh-inputs` recheck the selected Node/host, manifest/lock, complete owned dependency bytes and neutral runtime ancestry. They remove old source files (including deleted tests) before copying current sources. Each runtime owns its source inventory; failed replacement preparation cannot overwrite the surviving runtime's inventory, and an interrupted refresh retains attempted additions for later cleanup. The runner rejects that incomplete inventory before launching children; successful refresh restores execution. Legacy unsealed descriptors retain byte-checked execution but cannot refresh without one fresh preparation. Reports count dependency installations/copies and source copies. Changed graph inputs require preparation again; changed native inputs require a new verified helper. Refresh does not relabel an old helper's provenance or regenerate a source-bound consumer archive closure; after source changes, prepare that closure again before consumer execution. It requires a sealed graph from the current preparer; older inputs need one fresh preparation.

The 2–3-minute end-to-end target applies to the **local feature loop only**, not full CI. It is a guideline, not a timeout or pass condition; justified variation is acceptable. Include preparation and prerequisite costs, distinguish owned-cache/source-refresh runs from cold setup, and report longer required integrations rather than hiding them. Do not run full compatibility acceptance for a local presentation-only edit. The [structural catalogue](../scripts/test/catalog.mjs) discovers executable membership; feature subdirectories select local groups, not source-impact CI routes.

### Provision optional inputs from a fresh clone

Ordinary types/product/footer/editor preparation needs neither Rust nor a native/shared service. Physical CLI needs declared Python 3 (standard-library PTY on POSIX) and Bash for real job-control cases. If selecting another Node executable, `--node` selects that actual runtime; `--tools /absolute/tools.json` may supply an absolute `npm` JavaScript CLI entry compatible with it. No tool path or private tools map from a historical run is a prerequisite.

Native tests additionally need the pinned Rust **1.99.0** sysroot with rustfmt/Clippy and the host C/C++ compiler/linker. Provision it separately, never during test execution. For example, using an already provisioned explicit Rustup executable, install into fresh owned stores (not user defaults):

```sh
TEST_ROOT=/absolute/new-test-input-root
mkdir -p "$TEST_ROOT"
export RUSTUP_HOME="$TEST_ROOT/rustup" CARGO_HOME="$TEST_ROOT/cargo"
/absolute/rustup toolchain install 1.99.0 --profile minimal --component rustfmt --component clippy
RUST_ROOT=$(/absolute/rustup run 1.99.0 rustc --print sysroot)
# Supply --rust-root "$RUST_ROOT" --build-native to preparation, then execute offline.
```

For Linux x64 shared integration, use the same pinned public input as CI. This is explicit **preparation/network acquisition**, not runtime discovery or a download from inside a test:

```sh
mkdir -p "$TEST_ROOT/shared-host"
curl --fail --location --output "$TEST_ROOT/shared-host/host.zip" \
  https://github.com/cortexkit/subconscious/releases/download/subc-core-v0.20.83/ck-subc-linux-x64.zip
printf '%s  %s\n' c905fd8c5eba045c38fb61dd0c6c0ffc8254ae2cb0be50ef1017cde5470e62c4 \
  "$TEST_ROOT/shared-host/host.zip" | sha256sum --check
unzip -j "$TEST_ROOT/shared-host/host.zip" ck-subc -d "$TEST_ROOT/shared-host"
chmod 700 "$TEST_ROOT/shared-host/ck-subc"
# Supply --shared-host "$TEST_ROOT/shared-host/ck-subc" to preparation.
```

Shared fixtures explicitly set `port: 0` in their private `subc.jsonc`, in addition to private HOME/config/runtime/discovery roots. The pinned host [supports OS-assigned loopback ports and publishes the actual bound port](https://github.com/cortexkit/subconscious/blob/subc-core-v0.20.83/crates/subc-daemon/src/bootstrap.rs#L1438-L1501); no find-free-port probe, retry or cross-run lock is needed. The simultaneous real-host control `tests/cli/shared/syntax/shared-host-isolation.cli.test.mjs` verifies distinct published ports, independent helper processes and real traffic while both hosts remain live. Leaving the production default port implicit makes otherwise-private fixtures collide during parallel file execution.

All private Subconscious test-host launchers use [`sharedHostEnv`](../tests/fixtures/shared-host-environment.mjs), which composes the existing sanitized `childEnv` with `SUBC_CGROUP_PLACEMENT=disabled` and **`TOKIO_WORKER_THREADS=2`**. This explicit integration-fixture budget keeps hosts and managed helpers inside the verified aggregate scope and avoids multiplying CPU-count-sized async worker pools when independent files run concurrently. [Tokio's worker setting](https://docs.rs/tokio/1.52.3/tokio/runtime/struct.Builder.html#method.worker_threads) otherwise defaults to available cores; the fixture does not pin CPUs or change ordinary Node/Cargo, Occipital's existing worker/actor policy, production/user host settings or benchmark conditions. Shared integration therefore certifies the real host with two Tokio async workers, not its CPU-derived default pool size. Required concurrent hosts, physical jobs and peer progress remain real; the aggregate 2 GiB/128-task limits are unchanged. The environment regression checks polluted callers and an actual child, including that ordinary child environments do not acquire this host-only policy.

Suspend evidence records monotonic stopped/resume boundaries and asserts at least 4.5 seconds actually stopped. The fixture waits to a monotonic deadline, rescheduling only a positive remaining interval: a nominal `setTimeout(4500)` can return a fraction of a millisecond early. This keeps the existing 4-second request deadline plus full 500 ms margin, without shortening the pause or increasing the 45-second case bound.

That asset recipe establishes Linux x64 input provisioning only; other platforms require their own explicitly verified host input and are not covered by this archive. `--integration` installs the tracked audited `tests/fixtures/integration-profile/{package.json,package-lock.json}`; `--archives` prepares the consumer closure described below. Missing selected prerequisites fail before cases, never become successful skips.

### Clean-state harness acceptance

For changes to the harness itself, use a separate **real Git clone**, including the history/tags needed for native version stamping. Start with no generated artifacts, installed dependency tree, Pi settings or operator caches. Follow the ordinary preparation and verified-scope commands above/below, run types plus representative product/harness and real offline-provider CLI, then explicitly provision/build the optional native/shared lane and run it. Repeat prepared execution with `--network-isolated` on Linux. First installation may acquire declared public inputs; clean clone is not an air-gapped install.

The maintained tiny admitted-fixture controls exercise the **actual** `execute` API and runner CLI at jobs=1/2, including production resource preloads. Parent-held peer gates prove serialization/bounded overlap without speed thresholds; rejection, cancellation, abrupt startup and SDK-bootstrap failure preserve peer evidence. POSIX SIGINT/SIGTERM controls start two workers with real descendants and verify interruption reports, reaping and root cleanup; they do not establish Windows signal acceptance. Native-build fixture controls remain fixed jobs=1 and use inert Rust, not compiler acceptance.

This is a standalone acceptance procedure, **not** a discovered `tests/harness` case, automatic feature prerequisite or extra CI job. Never recursively clone/download/build native dependencies from a network-isolated ordinary test. A clone of HEAD cannot prove uncommitted candidate changes: before commit authorization, overlay only the reviewed intended source files/deletions, record the resulting exact source identity and label it prospective-clone evidence. Do not copy generated state or create a commit just for that proof. Final committed-clone evidence needs the separately authorized source commit.

### Prepare broader inputs, then execute

Preparation owns dependency resolution, allowed public-network acquisition and native building. It records source commit/tree identity, native-source `nativeTree`, exact Node executable/version, selected Pi packages/lock, declared tools and required artifact hashes in `inputs.json`. It materializes a test tree with its own dependency graph without changing repository manifests/lockfiles or user installations. Preparation uses owned npm/Cargo stores and clean configuration, not user credentials, proxies, `.npmrc`, Cargo config or incidental caches. Unsupported Node engines fail preparation rather than merely warning. Prepared source copies, including Cargo's working directory, live outside the checkout and its ancestor configuration search; the original checkout is not rewritten.

`npm run test:prepare -- ...` invokes the same preparer. Its default output is `.test-artifacts/harness/1.0.1` (or the selected Pi version); explicit separate outputs avoid mixing host/runtime inputs. For the broader native/Rust/shared/profile/consumer union, with the pinned Rust sysroot and shared host already provisioned:

```sh
node scripts/test/prepare.mjs --pi-version 1.0.1 \
  --rust-root /absolute/path/to/rust-1.99.0 --build-native \
  --integration --archives --shared-host /absolute/path/to/ck-subc \
  --output /absolute/path/to/prepared-pi-1.0.1 \
  --run-root /absolute/path/to/runtime-parent

npm run check -- --inputs /absolute/path/to/prepared-pi-1.0.1/inputs.json
npm test -- --inputs /absolute/path/to/prepared-pi-1.0.1/inputs.json
npm run test:native-release -- --inputs /absolute/path/to/prepared-pi-1.0.1/inputs.json
npm run test:rust-check -- --inputs /absolute/path/to/prepared-pi-1.0.1/inputs.json
```

Use separate output directories for each Node/Pi selection. To reuse the verified current-source helper in a second host graph, set `PI_VERSION` to the exact alternate version recorded by CI (not a tag/range):

```sh
node scripts/test/prepare.mjs --pi-version "$PI_VERSION" \
  --native-inputs /absolute/path/to/prepared-pi-1.0.1/inputs.json \
  --integration --archives --shared-host /absolute/path/to/ck-subc \
  --output /absolute/path/to/prepared-pi-alternate
npm run check -- --inputs /absolute/path/to/prepared-pi-alternate/inputs.json
npm test -- --inputs /absolute/path/to/prepared-pi-alternate/inputs.json
```

Run the expanded Pi/Node matrix when host/runtime contracts change and for full compatibility/release acceptance, not after each ordinary feature edit. A → B → A controls detect cross-version contamination. These examples select checks, not a claim of full compatibility acceptance. Execution rejects a changed tested commit/tree; source-only refresh is described below.

| Preparation option | Meaning |
| --- | --- |
| `--node ABSOLUTE_EXECUTABLE` | Record and use that actual Node executable/version, including children |
| `--tools FILE` | JSON of explicit absolute prerequisite tool paths, including the npm CLI JavaScript entry when needed |
| `--offline --npm-cache DIRECTORY` | Use explicitly supplied npm content cache, with no public dependency fetch; non-baseline offline preparation also requires its previously resolved exact manifest/lock in the output directory |
| `--registry-inputs INPUTS_JSON` | Reuse a prepared consumer closure only after matching its source snapshot, selected host/runtime and archive/document/lock integrity; required for offline `--archives` |
| `--native-inputs INPUTS_JSON` | Reuse a recorded helper only after matching tested commit, `nativeTree`, size and hash |
| `--native-artifact DIRECTORY` | Admit a staged current-commit CI artifact; modified local native sources require a new `--build-native` instead |
| `--rust-root SYSROOT --build-native` | Fetch locked dependencies during preparation, stamp the selected daemon version in a disposable native source tree, then build offline with the pinned compiler |
| `--cargo-cache DIRECTORY` | Copy declared Cargo registry/Git artifacts into the owned Cargo home, not user configuration |
| `--integration` | Prepare the locked, audited third-party profile for full terminal coverage |
| `--archives` | Prepare the integrity-checked transitive npm archive closure for the local consumer fixture |
| `--shared-host EXECUTABLE` | Record the explicit isolated shared host and its hash |
| `--run-root DIRECTORY` | Parent for disposable execution roots; must be outside the tested checkout, with no ancestor `.git` or `.cargo/config[.toml]` (default is the fixed system temporary parent, not inherited TMPDIR/HOME) |

Windows consumer CI explicitly supplies `--run-root "$RUNNER_TEMP"`: owned runtime/source/consumer trees use the declared runner storage, not inherited TEMP/TMP or a hardcoded drive. Native compilation keeps its established path policy. Neutral Git/Cargo ancestry checks apply to both. The execution environment deliberately keeps `UV_THREADPOOL_SIZE=4`: controlled 4/16-thread comparisons did not establish a consistent cross-platform benefit or remove the Windows unpack bottleneck, so higher concurrency is not assumed to improve these workloads.

Preparation without native options supports types, product logic/SDK, smoke and affected UI/card/fallback-logging groups. Requirements come from discovered structural categories, not source-file impact or suite names alone. The complete `unit` union contains actual native and installed-profile integration tests and therefore needs their inputs; use `product`, groups or a feature command for local feature work. Every ordinary executed Occipital helper must match the tested commit and native source snapshot, not just `--version`. There is no published-binary fallback. A cached artifact is usable only when its recorded source and bytes still match.

Execution starts a fresh sanitized process tree **before** importing host/production modules, with owned HOME, agent/config/session/temp/cache roots outside the tested checkout and controlled tool PATH. Node startup controls, credentials, proxy settings, user Git/npm configuration and service-discovery state are not inherited. This guarantee concerns the spawned test tree, not the caller's already-running shell/npm process. The bootstrap validates actual Node identity, host manifests, CLI location and SDK/TUI class identity. Direct `node --test` or fixture invocation without the harness context is not a supported shortcut.

This is reproducible-input isolation, **not a security sandbox against malicious dependency code**. Environment allowlists, sentinels and network namespaces do not deny all host filesystem access. npm installation lifecycle scripts are disabled. Kernel memory/process containment is a separate safety boundary; neither it nor a passing hermeticity check certifies arbitrary dependency code as safe.

For changes to preparation, bootstrap, environment sanitization or child-launch boundaries, compare the relevant checks using identical prepared inputs under clean and deliberately polluted caller environments. Pollute fixture-owned HOME/Pi settings/extensions/auth, competing Pi/PATH entries, Node startup/module lookup, terminal/locale, Git/npm configuration, proxies, service discovery and caches as applicable. Use observable startup/configuration sentinels; require unchanged selected coverage and semantic results, no unintended execution/access effects inside the spawned test tree, and unchanged fixture configuration. The caller's already-running process is outside that guarantee. Compare outcomes and concrete counters, not timestamps, PIDs, temporary paths or timings. Exercise A → B → A when host-graph isolation is affected. This is harness validation, not a requirement to execute these controls for documentation-only changes.

Reports retain selected files and explicit filters, every observed test case, counts, runtime/host/source identities and setup/harness/product failure classification. Disposable execution environments are removed after success/failure; the report directory remains available for inspection. Each `scripts/test/run.mjs` invocation writes an atomically replaced `report.json`, a `*.progress.jsonl` stream for run/step start and completion, and—when Node's test runner executes cases—a `*.tests.jsonl` event stream. A timeout or external termination therefore leaves the last valid report plus complete progress records even when no final summary can be written. A POSIX regression holds a test with a real live timer, force-kills its separately owned whole process group and verifies the persisted start event remains readable and is reconstructed as an unfinished case. A never-settling Promise alone is not a valid hold: Node may cancel it when the event loop has no live work.

The Node event reporter records test dequeue/completion with workspace-relative file, test name, nesting/line where supplied by Node, status and Node's measured `duration_ms`. The final run report includes every completed case, currently active cases, the 20 slowest tests and 20 slowest suites; the console prints the top 10 slowest tests. A trailing incomplete JSONL record is identifiable and does not invalidate preceding events. `test:feature` additionally keeps its own `report.json` and `progress.jsonl`, atomically recording the currently running stage, its start/end time, status and selected child report/progress filenames. When a child runner throws after writing a classified report, the feature report preserves that child failure status/reason; only an exception without a classified child report becomes `harness-failed / runner-exception`. Native-build test runs use the same per-case reporter. For stable Rust `libtest`, individual cases and the Cargo step duration are recorded, but libtest does not expose reliable per-case elapsed times; the report states this limitation rather than inventing timings. Durations are measured on the current machine/run and locate bottlenecks; they are not portable performance thresholds.

On POSIX, interruption terminates the test process group, including descendants; Windows uses explicitly declared `taskkill /T`. Native build inputs and prepared dependency stores remain available for subsequent runs. Failed preparation removes only its newly allocated runtime tree; earlier successful inputs and explicit caches remain available. Runtime ancestry is checked again before execution, so later parent Git/Cargo configuration cannot become an undeclared test input. Physical selected-CLI/Python-startup controls belong to the harness CLI group, not the portable node layer. The optional `PiTerminal({ jobControl: true })` fixture uses the declared Bash and Python tools to launch Pi as a real foreground job after the shell prompt. Suspend checks must observe Bash's stopped-job state before `fg`, not rely on signaling an orphaned PTY group. Cleanup resumes/terminates the separately owned job group as well as the shell; complete validated group-ID records prevent empty/partial startup files from becoming process-group-zero signals. Reports explicitly distinguish inapplicable platform entries from performed checks; missing required inputs never become green skips.

Native-build controls use a **separate Pi-free descriptor**, not `prepare.mjs`'s general Pi inputs:

```sh
node scripts/test/prepare-native.mjs --rust-root /absolute/path/to/rust-1.99.0 \
  --output /absolute/path/to/native-build-inputs
npm run test:rust-harness -- --inputs /absolute/path/to/native-build-inputs/inputs.json
```

`native-harness.mjs` uses the existing `prepare-native.mjs` descriptor (schema 1 / kind `native-build`) and Node's test runner for all `.test.ts` / `.test.mjs` files under `tests/native-build/`. It verifies the selected Node, pinned Rust and unstamped source snapshot without installing Pi. Its real `checkCargoAncestry` control proves that a poisoned ancestor config is effective in the positive control but absent from the neutral materialization. Producers run this suite once **before stamping**, separately from workspace product tests and later artifact admission. Node consumers run no native-build controls and provision neither Rust nor MSVC.

On Linux, append `--network-isolated` to `scripts/test/run.mjs` (or through npm's `--`) to use declared bubblewrap with a real network namespace, for example `npm run test:harness -- --inputs /absolute/path/to/prepared/inputs.json --network-isolated`. Local fixture endpoints remain real; public egress is denied for children too. `test:harness` checks trusted connection-file ancestry, exactly one successful local HTTP request and a public socket failure of `ENETUNREACH`. This is not a `fetch` mock. Elsewhere the built-in flag fails explicitly: equivalent OS/container enforcement requires platform-specific verification. Prepared-local inputs and sanitized environments alone do not establish OS-enforced egress isolation; current non-Linux CI has that verification gap.

## Make shortcuts

GNU Make/POSIX-shell entry points route checks to the same runner. `make` prints help only. Supply absolute `INPUTS`; there is no helper discovery or implicit preparation during test execution. Optional `JOBS=N` forwards the same file bound for ordinary test/feature/focus/product/native/CLI/release targets; fixed type/Rust/consumer targets reject it instead of silently ignoring it. GNU Make's own `-j` is not a substitute for the runner's single bounded file pool.

| Target | Scope |
| --- | --- |
| `make deps PI_VERSION=1.0.1 PREPARE_OUTPUT=...` | Prepare exact host dependencies; no implicit native build |
| `make build RUST_ROOT=... CARGO_HOME=...` | Explicit offline locked local release build and colocated copy; requires pinned sysroot and owned prefilled Cargo home with no user config |
| `make check INPUTS=...` | Strict selected-host TypeScript |
| `make check-native INPUTS=...` | Offline Rust fmt, then strict all-targets Clippy |
| `make test INPUTS=...`, `make test-gc INPUTS=...` | Same unit/SDK suite with mandatory GC and same-source native inputs |
| `make test-focus INPUTS=... TEST_FILES=... TEST_PATTERN=...` | Local comma-separated unique basenames or structural paths and optional regex; GC/truecolor retained |
| `make test-rust INPUTS=...` | Offline workspace tests and doctests |
| `make test-rust-harness INPUTS=...` | Native-build discovery including real Cargo ancestry/isolation; requires the separate `prepare-native.mjs` descriptor |
| `make test-native INPUTS=...` | Real same-source helper controls |
| `make test-syntax INPUTS=...` | Short physical syntax CLI; required prepared shared host |
| `make test-terminal INPUTS=...` | Main physical CLI/replay subset; required locked integration profile |
| `make test-release INPUTS=...` | Inert packaging/release regressions |
| `make test-installed INPUTS=...` | Same-source clean consumer with prepared archives and fixture-local registry/download |
| `make test-published INPUTS=... RELEASE_REF=refs/tags/pi-tidy-ui-vVERSION` | Explicit external published-delivery verification, extension releases only |
| `make pack-check` | Development-package dry run, no publication |

Neutral native snapshots and `nativeTree` cover the Rust workspace, pinned Cargo/toolchain/config files and shared `protocol/` inputs. The protocol JSON vectors are compiled into Rust tests with `include_str!`; they must survive GNU/Make snapshot creation and changes to them invalidate native input provenance even when `.rs` files are unchanged. This does not add Pi or `node_modules` to native inputs. Repository JSON uses `*.json text eol=lf`: Git retains text diffs while every checkout preserves the LF bytes required by raw-hashed protocol-vector fixtures.

The extension has no TypeScript bundling step. `make build` does not select/stamp a release, download inputs, install tools or start services; it disables Rustup automatic installation and checks Cargo/rustc against `rust-toolchain.toml`. `CARGO_TARGET_DIR` selects its build directory and `RUST_TARGET` an explicit target triple. A merely present colocated helper is not test provenance; use prepared native inputs. Native calibration examples are not implicit prerequisites.

```sh
make check INPUTS=/absolute/path/to/prepared/inputs.json
make test-focus INPUTS=/absolute/path/to/prepared/inputs.json \
  TEST_FILES='bash.sdk.test.ts' TEST_PATTERN='^bash timeout'
make test-focus INPUTS=/absolute/path/to/prepared/inputs.json \
  TEST_FILES='syntax-work.test.ts,syntax-host.test.ts'
make test-release INPUTS=/absolute/path/to/prepared/inputs.json
```

`tests/harness/delivery/makefile.test.ts` executes the actual Makefile and GNU wrapper in disposable trees with inert executors, asserting arguments, phase order, outputs, failure propagation and real ABI admission. These are orchestration controls, not actual Rust/CLI acceptance. POSIX/GNU Make applicability is reported separately; platform inapplicability is not missing-input acceptance. `NODE`/`NPM` select existing executables, not runtime installers.

## Test selection and cadence

During the edit–test–fix loop, use affected node/CLI groups and strict types as relevant. Before delivery use common product checks plus affected integrations (`test:feature`); run offline Rust checks when native behavior is affected. `npm test` remains the complete ordinary Node/SDK/GC union, excluding separately executed inert delivery and native-build controls; `test:product` is the native/profile-independent product baseline. `test:native-release` is the inert delivery/release/Make union, not Pi-sensitive packaging or actual helper acceptance. The complete physical union is `--suite cli`; `terminal` and `syntax-terminal` remain local subset aliases. GC and truecolor are supplied by construction; a missing actual `global.gc` or required native/shared/integration input fails instead of dropping checks. Feature tags come from test-directory components: root-level `tests/integration/native/*.test.ts` cases are tagged `native`, not `syntax`, and root-level `tests/cli/shared/*.test.mjs` cases are tagged `shared`, not `syntax`. A syntax-only feature selection therefore misses those integration boundaries; select `native` and/or `shared` explicitly when changing their executable or fixture contracts. A test drain relying on `whenSettled()` must assert its `true` result; `false` denotes cancelled work, not successful completion. Whole-source visual comparisons use this passive boundary under the existing ten-second fixture deadline, then independently require publication coverage and every corpus entry's current palette, rule fingerprint, binding revision, complete/exact source version, text and valid range visits. Aggregate publication counts are assertions, not readiness signals; the observer must not repeatedly flush the queue.

Shared CLI semantic-color assertions must set `TIDY_UI_TEST_PALETTE_OBSERVE=1` and correlate actual generic SOURCE scopes with returned STYLE contexts before checking physical cells; the fixture records shared transport payloads only under this opt-in. Synthetic tool-result source fragments may have no language hint, so tests must not invent a fixed language when resolving their recorded contexts. In saved Follow Pi replay, count the three bounded write/edit-side SOURCE requests separately from the independent saved Bash SOURCE request; expansion and collapse deltas must name the exact newly exposed or restored file fragments. Punctuation coverage also requires the observed semicolon STYLE foreground binding to map through `SEMANTIC_REGIONS` to `syntax-punctuation`; deriving its expected color only from the observed expression does not prove the category.

File-preview tests check bounded-source identity when hidden argument or saved-patch suffixes change. Source-access guards prove warm frames and resizes do no new cleaning, normalization or physical-row selection; actual `Intl.Segmenter` visits are counted around preparation and geometry-only repaint, and replaced same-prefix argument/result objects must be collectible while their component owners remain live. Separate controls cover malformed fully-inspected versus physically cut patches, CRLF/CR normalization before cleaning, ten physical input and ten visual output rows, mixed diffs staying unified at preview widths, the common overflow marker independent of explanatory notes, tiny complete previews without a false truncation notice, and funded pending/error expansion. Pending edit details use standard `args.edits[]` in preference to legacy fields and stop at their shared ten-row/eight-kilounit excerpt. Funded final-error details use every available saved edit entry and complete text error without that pending-preview cap; verify more than ten entries, more than 8,192 units and rows, plus the funded and denied paths. Same-object `invalidate()` tests mutate patch, diagnostics and image parts in place: selected source and diagnostic snapshots refresh only at that boundary, warm frames keep the source token, and image results return to native rendering without per-frame rescans.

A final error body enumerates all saved source fragments to estimate construction scratch before cleaning/joining: 4 KiB fixed, six bytes per logical UTF-16 unit for three construction copies, and 64 bytes per source part. Unlike pending excerpts, final-error sources have no shared 8,192-unit/ten-row truncation; the separately retained joined text is charged at two bytes per UTF-16 unit plus its storage header. If funding is refused, do not join or retain a partial body. No row descriptors are built from physical newlines, so admission neither scans nor charges per line. Temporary parts are cleared and unused construction credit refunded before ordinary `measure()` grants fund numeric geometry. Focused controls reject the old 512-byte-per-unit estimate and prove a newline-heavy but short body remains admissible. Full preparation/measurement refusal retains the owned limitation path without stock materialization, same-mode recovery retries ordinarily, and unsupported full metadata still delegates to native. Spacing measures the same bounded/native fallback layout as rendering, including its actual height.

The two-adapter mouse control verifies that a non-owning outer wrapper delegates the original event without rendering through another adapter or creating useful file demand. The saved-write CLI shape control also renders an unsupported-metadata service row in Pi's regular TUI at 24 columns with Output padding 1, checks every returned row against the physical width and completes a capture without a host overflow failure. This physical boundary complements the layout matrix's widths 1/2/24/60/100 and padding 0/1/2 controls.

Every SDK extension fixture, including separately constructed GC/footer owners, must enter through the public `tidyUi(pi)` factory and record `registerToolRenderer`; direct `installTidyUi` tests exercise the lower-level controller boundary, not minimum-host registration. Stock write/edit callbacks are lazy only when created by the public renderer resolver, so native-visibility negatives use explicit foreign/mixed callbacks rather than a synthetic class-name difference. The performance SDK fixture's Native/Off/On renderer identities are described in [performance testing](performance-testing.md); real extension registration remains covered by host/CLI tests. Real-CLI native-savings controls observe the internal `DeferredRenderer` class from the same extension module graph: they count only effective callback materializations, require the observed wrapper prototype to match the spied class, and require an Appearance Off/native override positive control in that epoch. `nativeRenderCalls` counts host tool-component rendering and is not proof that stock syntax/preflight/result callbacks stayed cold. The edit replay Off assertion compares every raw styled tool row with a separate pure-Pi replay of the same saved session, theme, width and expanded state; a live, differently themed or collapsed capture is not an equivalent native reference.

Owned-palette resource regressions distinguish menu selection from card preparation: menu-only preview must not open/read palette data, look up a card input owner, or start a provider; cold card acquisition is measured through the actual bundled-file loader; a second live owner reuses the funded store, and repeated paint visits perform neither file I/O nor owner lookups. A warm explicit owner lookup is counted separately: it may acquire a new lease header, but must reuse the compiled store without reopening or rereading the palette. The 100-choice churn checks measure every settled retained-byte total against the non-palette baseline, exactly one current palette input, the current-minus-initial controller selection identity charge and the matching current semantic-display identity charge for the baseline entry count; entry count must stay fixed, so the starting palette input and historical selections/displays cannot be hidden in the allowance. Separate tests verify exactly one 26-role compilation per cold owned store, zero on warm reuse, old-lease validity during replacement and zero final retained bytes, plus refund/no-compilation at each denied funding reservation. Run the relevant `settings` and `syntax` groups together when changing palette selection, lease ownership, funding, or card preparation.

```sh
node scripts/test/run.mjs --inputs /absolute/path/to/prepared/inputs.json \
  --suite groups --groups bash --layer node --pattern '^bash timeout'
node scripts/test/run.mjs --inputs /absolute/path/to/prepared/inputs.json \
  --suite unit --files queued-cards.test.ts,spinner-scheduler.test.ts
node scripts/test/run.mjs --inputs /absolute/path/to/prepared/inputs.json \
  --suite groups --groups footer --layer cli
node scripts/test/run.mjs --inputs /absolute/path/to/prepared/inputs.json \
  --suite groups --groups editor --layer cli
```

Local `--groups` composes feature domains and `--layer node|cli` limits execution. `--files` accepts comma-separated **unique basenames or structural paths relative to `tests/`** (for example `product/footer/footer.sdk.test.ts`), not globs or checkout paths; ambiguous basenames fail. Fixed type/Rust/consumer commands cannot be replaced with unrelated files, and native-build controls require their dedicated runner. Prerequisites follow discovered categories even through a local alias. `--pattern` selects test names; `--skip` forwards an explicit skip regex. Prefer `--skip` for exclusions: a negative name pattern can match a parent test and include the supposedly excluded child. Focused/excluded coverage must be reported, not called a full run. Ordinary Node and CLI suites default to file concurrency **2** and retain `--expose-gc`. Controlled physical suspend pairs established real stopped-interval overlap and lower wall time; jobs=4 exceeded the unchanged aggregate 128-task limit in both full Node and suspend trials, and the intermediate Node jobs=3 also exhausted that envelope. Neither is a supported default. An explicit larger job bound is an experiment within the same resource envelope, not permission to raise its limits. `--jobs N` overrides the positive-integer file-worker bound through direct, npm group and feature entry points. It does not enable concurrent subtests or parallel feature stages and does not bound the number of PTYs/helpers a file starts. Feature types → Node → CLI remain serial; the same requested jobs reaches only its ordinary Node/CLI stages. Fixed type/Rust/consumer entries reject `--jobs`; the separate native-build runner retains jobs=1. Reports retain requested and effective jobs. Explicit jobs=1 is a focused diagnostic/control configuration.

Full physical CLI execution is time-expensive. For local work, use affected groups during editing and relevant integrations before delivery, not automatically every terminal case after every edit. Documentation-only work needs links/claims/diff checks, not product execution. Harness/workflow changes need checks appropriate to their execution and coverage contracts, not only workflow lint. These local choices do not narrow CI.

### Diagnostic test performance results

Ordinary runner results include diagnostic performance data, not only pass/fail. Existing `durationMs`, `slowestTests`, `slowestSuites` and stage/whole-run elapsed times locate slow cases without double-counting parent/child durations. Native consumer geometry controls compare complete source-work observer snapshots across theme/rollback, not a duplicated hand-maintained subset that drops newly added counters. Their dense finite-file workload explicitly selects the full view before attachment: it requires all 255 newline-terminated records and one provisional tail, not a bounded preview prefix. `report.resources.files` adds per-file worker elapsed time, user/system CPU milliseconds and maximum RSS bytes, plus `largestWorkers`, `slowestFiles` and observed file-worker overlap. Feature stage records retain the child jobs/resources; the Pi-free native-build runner retains fixed jobs=1 and the same worker observations.

Physical presentation tests close and reap completed native/reference/replay processes at their final live interaction/event read, before independent variants or modes start. `PiTerminal.close()` retains session/workspace files; defer `dispose()`/`closeTerminals()` until the last borrower finishes and keep outer `finally` registration for failures. Later comparisons use detached real captures/traffic, never synthetic controls or post-close `events()` reads. Required simultaneous native/live active comparisons, normal quit/release checks and atomic same-session transitions remain intact. Keep references live when later checks actually resize/recolor/recapture them (for example shape-write and user Markdown controls); passive replay/native captures, including actual expanded states, can be retained after shutdown. Close each independent mode before the next starts, attempt every grouped cleanup and surface failures. Closing completed processes is a resource-ownership boundary, not a second scheduler or a reduction of semantic coverage. Runner cancellation controls explicitly abort a started child test through its public `AbortSignal`; they do not rely on Node cancelling a never-settling Promise when the event loop becomes idle, which differs between supported Node versions.

The worker collector uses Node's public `process.resourceUsage()` (CPU microseconds converted to milliseconds; maxRSS KiB converted to bytes). It checkpoints a private per-PID record at admission, once per second and at ordinary process exit. These records remain beside the report under the named `resources.observations` directory even on interruption. Final/partial/missing observations are distinct: an abrupt death may leave only the last checkpoint, and a worker that never reached admission has null metrics with an explicit reason. A checkpoint's high-water value covers that worker's lifetime **through its observation**, not an individual test phase. Collection adds no product instrumentation, signal handlers, heap dumps or automatic retries.

Worker CPU/RSS **exclude descendants**: Pi PTYs, helper and shared-host processes may consume substantially more RAM. Do not interpret the worker ranking as an exact ranking of complete test trees. On Linux inside the dedicated verified test scope, `aggregateBefore`/`aggregateAfter` and step snapshots record kernel `memory.peak`, `memory.events`, `pids.peak/events`, `cpu.stat`, effective affinity and limits. These are **scope-lifetime** measurements; a feature's types/Node/CLI stages share that scope. Do not subtract cumulative peaks or sum workers' independent peaks to invent per-case or aggregate memory. The outer scope receipt's `preCleanup` is sampled after the target command exits and before whole-scope teardown; `finalLifetime` is sampled after teardown. A removed cgroup can make final counters unavailable, so a pre-cleanup peak is not relabeled as a measured final cleanup peak; unavailable counters stay explicit. Non-Linux or non-dedicated scopes report aggregate collection unavailable, not zero.

To investigate a slow or RAM-intensive ordinary file, use its `rerun` argument array (retaining explicit name/skip/network filters) or select it explicitly with `--files` and `--jobs 1`, inside a **new** ordinary guard scope with a new receipt. The separate Pi-free native-build entry keeps its fixed selection: rerun that dedicated entry in a new scope rather than pretending its files are admitted by the Pi runner. Keep the same prepared Node/Pi/helper and resource limits. That bounded scope measures the focused runner **and all its descendants**, including launcher/cleanup overhead; it is not Pi-only RSS. Add an explicit name pattern for a case only when that pattern preserves its necessary setup/ordered scenario. Examine `activeTests`, the persisted test event stream and partial worker records if the run died. Regular reports have no automatic machine-dependent anomaly threshold. Detailed product CPU/allocation/GC profiling remains the separate opt-in [performance framework](performance-testing.md); it changes measurement identity and is not silently enabled for ordinary tests.

### Fixed CI obligations

Every `main` push, pull request and ordinary manual dispatch runs the same fixed required coverage. Full physical and release compatibility coverage is explicitly distinguished from shorter physical compatibility checks. There is **no diff/impact routing, per-file registration, maintainer scope block or approval-based narrowing**. [The planner](../scripts/test/ci-plan.mjs) receives the event/ref and exact source SHA, not changed paths. All jobs use that same authority: PR HEAD for pull requests, the pushed SHA for pushes. A manual dispatch does not acquire tag publication authority.

| Trigger | Required checks |
| --- | --- |
| `main` push / PR / ordinary manual | All five enabled native producers and one minimum-Node/minimum-Pi consumer per target; types and complete `unit` on both Nodes × minimum/resolved-latest Pi; complete CLI on Linux x64 / Node 22.19.0 / latest Pi, fixed smoke/editor physical compatibility on each other profile; inert delivery once per Node on minimum Pi |
| Nightly schedule | Types and `compatibility` on resolved-latest Pi on both Nodes; complete CLI on those two profiles; Linux x64 Pi-free helper producer as their prerequisite only |
| Occipital push tag | All enabled native producers and both-Node/minimum-Pi consumers; once-per-Node minimum-Pi inert delivery and mandatory `daemon-regression` (`integration/native` plus `harness/packaging`) on both Nodes/minimum Pi; GitHub Release then exact-byte native npm publication |
| Extension push tag | Complete types/`unit` and full CLI on both Nodes × minimum/latest Pi; all enabled native producers and both-Node/minimum-Pi consumers, including public native delivery verification; inert delivery on both Nodes, admitted extension packing/OIDC/provenance/public-byte verification, then required changelog-derived GitHub notes |

Ordinary/extension SDK and CLI profiles use Node **22.19.0 / 26.7.0 × minimum Pi 1.0.1 / exact resolved latest**. Planning reads public `@earendil-works/pi-coding-agent/latest` metadata once, validates package identity and exact version at least 1.0.1, and pins every SDK/CLI profile to that value. Invalid/unavailable metadata fails without an older fallback. Equal minimum/latest profiles collapse. Job retries reuse the plan; a new workflow resolves afresh. Independent Occipital releases and platform consumers remain minimum-only and do not resolve latest.

Complete SDK/types coverage retains the Node × Pi cross-product because class/loading identity, GC ownership and deferred callback behavior involve both dimensions. Ordinary platform consumers use minimum Node **and minimum Pi** to preserve the supported clean-install floor; Linux SDK/CLI profiles provide latest-Pi coverage. Neither set substitutes for the other.

A **complete CLI** profile executes all physical tests through four exhaustive, disjoint sorted round-robin partitions: `--suite cli --shard I/4`, for I = 1–4. Sharding rejects `--files`, groups, name patterns, skip filters and layer narrowing, as well as malformed/out-of-range or empty partitions. New CLI tests automatically join exactly one partition. Reports record both complete discovery and the selected partition.

Ordinary CI uses the complete role only on **Linux x64 / Node 22.19.0 / exact latest Pi**. Each other distinct Node/Pi profile runs `--suite cli-compatibility` once, unsharded: the union of all tests under `tests/cli/lifecycle/smoke/` and `tests/cli/editor/`. These existing real-Pi scenarios exercise execution, reload/replay and editor interaction without reproducing every dedicated physical scenario. The fixed role rejects files, groups, patterns, skips, layers and shards; new nested tests join automatically. Reports explicitly label `coverage: compatibility`, selected membership and the full physical-file boundary; zero skips inside this smaller suite is not full-suite coverage. Both roles are mandatory for the ordinary result. Nightly and extension tags keep complete CLI on every planned profile. If latest equals minimum, profiles deduplicate without losing the one complete reference profile.

This deliberately defers dedicated secondary-profile physical scenarios beyond smoke/editor to existing full nightly/latest or extension-release coverage; nightly does not recover full minimum-Pi CLI coverage. Ordinary consumers no longer establish newer-Node clean-install compatibility on every OS; both-Node release consumers retain that check. See the [CI workflow contract](releases.md#workflow-relationship) for the exact trade-offs. Job counts are not test counts: with five targets and distinct minimum/latest, ordinary coverage uses 25 active jobs rather than the previous 39, but net runner-hour savings require an executed measurement. Aggregate runner time means the sum of observed job start-to-completion intervals, including setup; it is not pipeline wall time, CPU time or billed cost. Compare that sum and the critical path separately rather than inferring savings from fewer jobs.

The nightly cron is **03:23 UTC**, best-effort GitHub scheduling, not a promised start time. Its latest-only `compatibility` union includes all `product/` and `integration/` tests and Pi-sensitive `harness/packaging`, not unrelated harness or inert delivery. Nightly has **no minimum-Pi profile, native consumer matrix, other-OS builds or delivery/publication jobs**. Its concurrency group and `Nightly latest-Pi result` check are distinct from ordinary `Complete CI result`; nightly cannot cancel or replace the ordinary conclusion. The final result requires success from every planned branch/matrix, including all complete CLI partitions and all planned physical compatibility profiles. Required failure, cancellation or skip cannot turn green; a later commit's success is not evidence for the earlier source.

Native jobs compile each enabled platform once and immediately unlock that platform's selected consumers: minimum Node/Pi for ordinary events, both Nodes/minimum Pi for release tags. Their existing fresh optional/non-optional installations, SDK/native identity, cold/warm and incremental-work counters and cleanup are unchanged. Windows ARM64 stays disabled unless `CI_WINDOWS_ARM64=true`; see [platform policy](releases.md#platform-selection-and-immutable-releases). Linux x64 production unlocks SDK/CLI without waiting for other platforms or consumers. Discovered structural prerequisites determine native/shared/profile provisioning, **not which tests run**. GNU smoke and current-source consumers share one offline preparation per Node, with separate runner processes and fresh optionality installations. The pinned real Cargo ancestry control runs once per producer before stamping, under the dedicated native-build descriptor (Linux retains enforced network isolation); consumer jobs install neither Rust nor MSVC. Release publication waits for every required build, consumer, delivery and daemon-regression branch.

The only Actions artifacts are same-run native staging transfers with `retention-days: 1`. No test receipts, npm diagnostics, screenshots, development tarballs or publication receipts are uploaded. Build/test failures and safe fixed-field summaries stay in job logs; raw npm logs, environment, commands, URLs and opaque error text are not diagnostic projections. Local ignored reports/physical captures are not retained by CI. Expired transfers require renewed production, not another run's artifacts. Durable release binaries remain GitHub Release/npm assets. This policy does not delete existing stored artifacts.

Maintained JavaScript actions use reviewed stable Node24-runtime releases and require hosted runner **2.327.1+**. Their internal runtime is independent of test Node **22.19.0 / 26.7.0** and the GNU test container. `setup-node` has `package-manager-cache: false`; forced-runtime variables do not suppress deprecation warnings. See the official [setup-node migration](https://github.com/actions/setup-node/blob/v7.1.0/README.md) and [checkout migration](https://github.com/actions/checkout/blob/v7.0.1/README.md). Rollback is reserved for a confirmed upstream action defect.

CI restores only public content-addressed npm inputs (`_cacache`) into the actual owned preparation root, not npm configuration/logs, installed trees, test state or operator caches. Archive acquisition checks that owned cache by the locked integrity digest in online and offline modes. Online fetches only genuinely absent content; corruption, permission failures and other unexpected errors remain failures. Integrity, root manifests and the full optional/nonhost closure are still validated; cached input bytes never replace fresh consumer installations. A cold miss acquires exact locked inputs during preparation. Check-profile keys include selected Pi and required integration inputs.

Workflow definitions and local source inspection do not establish a passing hosted run. Required-check configuration and independent executed acceptance remain separate evidence.

Test names, scenarios and audited third-party versions live in sources/locked fixtures; do not duplicate a historical run total here.

## Test layers

The existing runner reads all `.test.ts` and `.test.mjs` files recursively from **five execution roots** in the prepared source snapshot. Adding a test under the right folder needs **no filename-list edit**. `fixtures`, `helpers` and `support` directories are non-registering support. Unknown execution roots fail selection. Feature subdirectories determine local groups; execution folders determine prerequisites, not source-impact routing. Structural `linux` and `posix` directories declare applicability. Explicit files outside their platform scope fail; automatic suite/group/feature exclusion is retained in `platformExclusions`, not counted as performed or passing integration coverage. Owned suspend's six cases belong to the `native` feature, shared suspend's six to `shared`; `syntax` and complete CLI retain all twelve. The separate `--suite native` Node/integration alias is unchanged.

| Root under `tests/` | Purpose and prerequisite subdirectories |
| --- | --- |
| [product/](../tests/product/) | Logic/SDK/GC, presentation and lifecycle contracts, including pure native/protocol contracts under `native/`. No real service prerequisite; controlled subprocesses and GC probes remain legitimate. |
| [integration/](../tests/integration/) | `native/` requires the verified same-source helper (`native`); `profile/` requires the locked third-party packages (`integration`). |
| [cli/](../tests/cli/) | Physical Pi tests under feature directories. `native/` requires the helper, `shared/` requires helper plus explicit Subconscious host, and `profile/` requires the locked installed profile. Ordinary feature directories need none of those services. |
| [harness/](../tests/harness/) | Preparation, bootstrap, source/environment authority, selection, PTY/parser/observer and cleanup controls. `packaging/` is Pi-sensitive ordinary coverage on every required Node/Pi profile, including nightly latest and daemon regressions. `delivery/` contains inert delivery/release/Make controls, separately once per Node/minimum Pi. |
| [native-build/](../tests/native-build/) | Pi-free Node tests requiring pinned native tools, including the real Cargo ancestry control; uses the existing native descriptor/bootstrap and runs before stamping. |

`unit` includes all `product/`, `integration/` and non-delivery `harness/` tests. `compatibility` includes all product/integration tests plus `harness/packaging/`; `daemon-regression` includes `integration/native/` plus `harness/packaging/`. `native-release` includes `harness/delivery/`. `cli` includes every physical test under `cli/` before partitioning. `cli-compatibility` is only the fixed smoke/editor physical union described above, not the nightly Node `compatibility` suite. These folder unions, not a per-file registry, define CI coverage.

The two fixed consumer scripts remain explicit interfaces outside test-file discovery: `tests/fixtures/installed-occipital.mjs` (`consumer`, requiring `native,registry`) and `tests/fixtures/published-occipital.mjs` (`published-consumer`, requiring explicit extension-tag/public-network authority).

Shared support under `tests/fixtures/` retains the actual-SDK cache/GC probes, offline scripted provider, production extension drivers, foreign-editor controls, terminal output publisher, Python PTY bridge/xterm harness and locked integration profile. Importing support registers no tests. Presentation and counter obligations are described below rather than duplicated as a filename inventory.

The unit runner invokes the SDK cache probes in separate Node processes with `--expose-gc`. Forced GC and diagnostic instrumentations are test-only; none run in the extension.

## Syntax/native checks

Physical syntax controls use a disposable real-version extension/driver in one selected module graph, injecting the prepared same-source artifact into the extension-owned [download storage](syntax/providers.md#acquiring-and-owning-the-local-process), not a production runtime-mode flag. Source version `0.0.0` retains its strict local-only rule. The current helper accepts `--stdio` for framed stdin/stdout or `--subc CONNECTION_FILE` for shared mode; it has no `--config` launch option. Keep test state isolated through the child's `cwd` and HOME/XDG environment while passing only the supported mode arguments. Bootstrap regressions use an explicit agent directory and assert one cold download, warm reuse across owners, unchanged settings and untouched legacy cache files; real installed consumers additionally verify the executed path, exact helper bytes and obsolete-download removal with and without optional packages. Download-retention regressions exercise exact A → B → A release selection with explicit download counts, cleanup on warm/installed hits, failed/cancelled-transfer preservation, current-target/unknown-entry/symlink isolation, differently-cased filesystem aliases versus distinct versions, ignored enumeration/deletion failures and subsequent retries. Filesystem assertions run after acquisition settles, without cleanup sleeps or background receipts. The actual-helper retention control parses a new Bash source through the already-running old process after another release is acquired, then proves warm cleanup after process exit; report real platform execution separately from injected Windows-style deletion errors. The [retention contract](syntax/providers.md#downloaded-release-retention) intentionally does not promise transparent recovery from concurrent acquisition/startup races.

```sh
npm run test:native -- --inputs /absolute/path/to/prepared/inputs.json
npm run test:syntax-terminal -- --inputs /absolute/path/to/prepared/inputs.json
npm run test:installed-native -- --inputs /absolute/path/to/prepared/inputs.json
node scripts/test/run.mjs --inputs /absolute/path/to/prepared/inputs.json \
  --suite unit --files syntax-work.test.ts,syntax-host.test.ts,syntax-runtime.test.ts
```

`syntax-terminal` registers only its own physical syntax cases. Identical stock `syntax-cards` traffic/persisted references are lazily executed once per terminal mode, then closed and retained only as detached deeply frozen evidence plus artifact location. Focused consumers build their own missing reference; all feature-bearing processes and replays remain independent, and comparisons use the original exact projections without additional normalization. The shared `tests/fixtures/terminal-harness.mjs` support registers no tests; importing it does not run the broad terminal suite. Native/shared inputs are mandatory. Structured-style coverage checks actual RGB/font cells in write/old/new sources and the complete selected native palette across unified/split frames, gutters, signs and semantic diff backgrounds. The shared transition fixture uses `scenario()`'s live markers (`SYNTAX_OUTPUT`, `x=1`, `x=2`) for generic STYLE readiness and checks physical foreground cells against those recorded expressions; `THEME_*` markers belong to the distinct saved-session fixture. Width and Pi dark/light changes retain that independent palette without new source/style work. The CLI picker fixture verifies selection on the palette page, which remains open after choosing an item, together with the persisted local choice. Whole-card native selection is not expected to preserve earlier Pi frame/background colors.

CI provisions official **Subconscious 0.20.83**, asset `ck-subc-linux-x64.zip`, with SHA-256 `c905fd8c5eba045c38fb61dd0c6c0ffc8254ae2cb0be50ef1017cde5470e62c4`. Preparation records the extracted executable hash. The fixture launches it with no arguments and a private XDG `cortexkit/subc.jsonc`, runtime/connection files and the current-source Occipital module; it neither discovers nor installs a user service. The real shared discovery/loss/owned-return control checks three calls, three results, four model contexts and `peerWarmDelta: 0`, including actual owned-helper reaping. Linux bubblewrap permits trusted connection-file ancestry; supplied-host presence alone is not shared acceptance.

### Current-source consumer and external delivery

`test:installed-native` / `--suite consumer` is the ordinary clean-consumer interface. Prepare `--archives` plus the verified current-source native input first. Its required contract is real npm installation from integrity-checked prepared archives through a fixture-local registry/download server, in consumers outside checkout ancestry. Each installed consumer imports the package from a separate process working directory containing spaces and a non-ASCII character, outside both checkout and package roots; cleanup restores the original cwd. This verifies package-owned bootstrap and palette files resolve from their installed module location rather than the process cwd. Both the optional native npm payload and the raw download endpoint must contain the **same tested commit/nativeTree bytes**. Public release selection or fetching missing transitive packages during this lane violates the ordinary-test boundary.

Online consumer preparation acquires the lock with `npm install --package-lock-only`, then captures independent graph/peer preflight with a fresh-cache `npm ci --dry-run`. All final lock archives, including omitted/nonhost optional entries, are still integrity-checked inputs. Lock-only/dry-run success is not installation acceptance: actual extraction, import, native behavior and completeness are proved by the mandatory fresh consumers below. Bundled/shrinkwrapped dependencies may still require npm extraction during acquisition; no new graph exclusion or public-fetch fallback is permitted. Offline **closure preparation** replays both frozen locks with `npm ci --dry-run`, without materializing consumer `node_modules`. It validates the unchanged graph and complete archive closure, not installation. Zero preflight unpack work is a fixed-graph control, not a universal npm guarantee for arbitrary graphs. The fixture then performs two independent actual `npm ci` installs (with and without optional packages); extraction/import and the native cold/warm/incremental counter controls remain mandatory acceptance.

Retain both consumers: optional dependencies install automatically with zero bootstrap downloads; `--omit=optional` excludes native payload and shared SDK, requires real SDK import failure, one exact cold fixture-native download and zero warm HTTP. Normal bootstrap must prove compiled version, UTF-8 colors, three incremental SOURCE dispatches with STYLE work recorded separately, unchanged committed-prefix work, no repeated warm SOURCE or STYLE work, retention/timer cleanup and process reaping. A local registry is not proof of public npm publication; source/hash admission is not a substitute for actually running these controls.

`test:installed-native:published` / `--suite published-consumer --release-ref refs/tags/pi-tidy-ui-vVERSION` preserves genuinely networked public npm/GitHub delivery verification separately. The tag must identify the tested commit. It uses the public release of the nearest reachable Occipital tag and its exact native npm family, with the corresponding public cold download/warm-cache controls. An incomplete selected release fails; selection never searches backward for a completed older release. CI runs it **only on extension push tags**, never ordinary main/PR, Occipital releases, nightly compatibility or manual dispatch merely pointing at a tag, and is not hermetic acceptance. See [release workflows](releases.md#workflow-relationship).

GNU CI builds offline in glibc 2.28 from a verified neutral source copy, stamps only that copy, stages the exact current executable separately, and verifies the original checkout is unchanged before admitting that staged artifact for actual-helper smoke and the current consumer on each Node runtime. `scripts/release/installed-linux-gnu.sh` takes explicit target, suite, preparation directory and artifact directory. Linked worktrees additionally mount their exact Git common directory read-only, so source/tag authority does not depend on an inaccessible host path. Ordinary clone metadata remains inside the checkout mount; `native`/`consumer` run with Docker `--network=none`, while `published-consumer` requires the extension release ref and deliberately allows public networking. The image's Git and Node runtime prerequisites are not new Occipital runtime dependencies. Container execution proves neither an older kernel nor macOS/Windows behavior.

Npm diagnostics retain only the safe projection in `.test-artifacts/installed-preparation-*/npm.json` and consumer `fixture.json`: known progress stages, acquisition/preflight/standard mode enums, numeric HTTP status/duration, cache enums, allowlisted timers, aggregate unpack counts/durations, numeric I/O-pool size, temporary drive letter and child exit/signal fields. Consumer preparation also emits fixed-name numeric phase durations and archive-record counts. Host and GNU collectors retain these preparation reports even before `inputs.json` exists and installed reports from the actual tested source root, not the SDK tree. Raw logs/timing files remain in owned temporary directories and are removed; commands, URLs, package/path identifiers, environment, stdout/stderr and opaque error text are not copied to CI artifacts. Empty log/timing lists mean unavailable data, not acceptance. Overlapping `reify:unpack` durations include fetching and are not wall time; cache messages or HTTP 200 alone do not prove saved work. Prepared npm cache reuse never replaces a fresh consumer or cold/warm native assertions. Native consumer CI steps allow fifteen minutes per Node; npm commands have their own five-minute bound. Archive preparation also logs fixed numeric cache-hit/miss, request, byte and tar-command counters and cache/fetch/tar durations; these distinguish saved work from timing variation.

Missing required helper or GC capability is a setup failure. Tests awaiting weakly owned transport initialization or responses must retain that transport through the lifecycle, for example `t.after(() => transport.close())`: awaiting its notification alone does not retain its owner. Abandoned-owner GC controls deliberately omit that ownership. `tests/product/syntax/shared-fixture-ownership.test.ts` exercises the actual optional-import case under mandatory forced GC without changing production timers/callbacks. The prepared executable/version and child runtime receipts are authoritative, not an npm/npx wrapper's assumed selection.

The opt-in edit fixture records producer `card_preparation` receipts from the optional runtime hook. `updated` identifies the actual accepted source input; `prepared` follows the real preparation and paint application attempts. The fixture matches these opaque update IDs, not private card state, text colors or elapsed quiet time; a fresh fixture epoch prevents pre-reload completions from acknowledging a newly loaded module graph. Pi reference preparation requires zero refused source admissions, successful Pi outcomes, successful paint application and a nonzero paint publication; native `waiting`, retained older neutral paint and a partially admitted source collection are not such completion. Replacing the selected input fails rather than silently following the replacement. Source-ineligible error summaries are not classification targets. The edit CLI's completed custom-card captures select all five source-bearing successes explicitly, while pending, native, expanded and failed-summary controls retain their distinct meanings. `capturePrepared` has one 12-second watchdog spanning the input fence, producer completion, dump, selected physical snapshot and persistence, with a warning on successful completion after one second. Its bounded numeric stage chronology is saved beside each capture and printed on failure; the opt-in fixture keeps ordinary extension journals directly in that terminal's `logs/` evidence directory. These files remain local, not CI uploads. Unit controls cover prior completions, multiple selected cards, replacement, refused paint application and one watchdog budget across stages. The real `preparation-signal.cli.test.mjs` control holds actual `continueWork`/`resumePreparation` continuations without resetting scheduler flags or inventing completion, then releases their originals once. It requires that release event before either dump or physical selection, and checks complete panel placement, syntax color, one selected capture and unchanged traffic/session bytes in both terminal modes.

Await fresh public provider/effective-palette state and settled source/style publication before reference captures; terminal silence or a completed SOURCE reply alone is not ready paint. The acquisition-gate regression keeps Pi quiet before actual helper publication. Diagnostic source ownership follows the current public `SyntaxRuntime.attach`, including a native-disabled reinstall, rather than the last native classification. Track legitimate source correction and incompatible/incomplete recovery separately from ordinary appends and missing-style resolution; a palette change must not restart parsing. Bridge-install counts alone do not measure thrown/invalid Pi-classifier invocations; focused work tests cover those paths directly.

The v4 wire controls exercise both actual production transports and the pinned helper: descriptors advertise the exact capability and operation sets, generic STYLE carries expressions without a palette, and stale-version adapter rejection is distinguished from native admission rejection. The shared-consumer control uses one real host and two public Pi themes to prove identical symbolic rule results can paint independently without repeating SOURCE or STYLE. The consumer waits for its public `SyntaxClient.whenSettled()` producer boundary, then checks the ready display and counters once; the separate host-connection and process-reaping checks observe external state and are not product readiness. Unmatched grammar contexts may inherit unstyled expressions; classifier tests assert representative bindings rather than assuming every context is colored.

macOS producers log a logical-file/byte breakdown of the restored Cargo registry and target directories without following symlinks. `targetWorkspaceNamed` is explicitly only the Occipital-named subset, not every workspace integration-test binary; category totals are disjoint, and logical bytes are not compressed-cache size or physical disk usage. Existing Cargo commands additionally emit fixed phase durations, workspace/dependency compile-notice counts and exit/signal fields. These summaries contain no paths or compiler diagnostic text; ordinary compiler stderr remains visible without filtering. Cargo fingerprint tracing and host-process snapshots are not enabled. These diagnostics do not change compilation flags, source paths, test selection or artifact admission. Rust children on macOS additionally receive only the pinned toolchain's `lib` directory in `DYLD_FALLBACK_LIBRARY_PATH`, and the owned tool PATH declares `xcrun` and `dsymutil`; ambient SDK/loader overrides are not inherited. A native-build control requires real SDK discovery, LLVM startup/stripping and Cargo release stripping before the workspace is stamped.

macOS Cargo caches retain registry inputs and compiled dependencies, not workspace outputs. After native staging has copied and verified the executable, Cargo cleans package `occipital` in debug and release profiles before the cache is saved. Ordinary macOS CI retains Cargo's default incremental policy; avoiding retained state alone is not proof of a lower total build cost. Local developer defaults and release-profile settings remain unchanged. The gate's Bash timer reports elapsed, user and system CPU seconds for the Node/Cargo process tree, not billed time or per-phase CPU usage. Other platforms retain their existing cache and compilation policy. The macOS namespace is separate from the previous full-output cache; the latter can seed the first dependency-cache save. Source timestamps are not restored or fabricated, Cargo still decides freshness, and all native tests/lint/build/byte-admission gates remain mandatory. Correcting SDK/stripping execution is not proof of equality to historical public binaries: release admission must still reject mismatched bytes rather than replacing published assets.

The controller STYLE unit controls pair a cached-expression local funding refusal with palette-only and binding-only recovery, then separately prove that a missing-context STYLE denial remains quiet across those same local changes. A positive coalescing control uses diagnostic dispatch identity to establish that a multi-member card owns the valid shared reply, denies only its local publication grant with real `DataBudget` pressure, and requires the overlapping peer to publish from the installed expression without another STYLE request. These controls check owner-local retry state without reopening generic STYLE admission.

The native crate has separate Rust correctness/format/lint checks. Its calibration examples and large-input cases are **not** an implicit prerequisite for each local UI check. For local validation, scope tests to affected behavior, honor operator restrictions on new traffic/measurements, and name any excluded required coverage in the working report instead of calling a partial run the full suite. Use the runner's `--skip` for exclusions: a negative `--pattern` can match a parent test and thereby include the supposedly excluded child. `tests/harness/test-filtering.test.ts` checks actual top-level and nested body non-execution on the current Node executable.

Local release preparation scripts accept explicit inputs and produce staged artifacts/metadata; `test:native-release` also covers inert tag stamping, exact-commit all-platform artifact assembly and automatic native npm publication. `tests/harness/delivery/npm-release.test.mjs` checks exact push-tag caller/OIDC authority, public-release equality, configured-platform manifest/byte admission, real inert tarball packing, array/object npm metadata, no-overwrite registry preflight and per-package receipts. Publication tests inject the npm executor, exact-version/archive fetcher and fixture-only OIDC environment: they assert explicit `--provenance`, stopping on generation failure, and npm-only `+build` rejection before output/packing/registry access while preserving GitHub SemVer support. They do not upload anything or establish actual trusted-publisher/provenance acceptance. `tests/harness/delivery/extension-release.test.mjs` exercises real tiny Git histories/current artifact families, current-CI admission for the enabled targets and validation of every platform declared by the selected historical public/npm release. Its default control admits five current targets while validating all six historical public packages; a separate Windows ARM64 opt-in requires six current targets. It also checks generated optional-dependency/metadata agreement, immutable source manifests/lockfile and tarball contents. Failed selected releases/bytes/npm identities stop preparation without choosing older releases. `tests/harness/delivery/extension-publication.test.mjs` separately exercises the root extension publisher: exact push-tag/source/caller/OIDC guards, immutable SHA-512-bound archive selection, structured-404 absence, conflicts/matching skips, required provenance, safe uncertain receipts, bounded public-byte verification and no automatic republish. A real inert staged package is packed with actual npm and its archived manifest/native pins are inspected; an environment permitting lifecycle scripts proves the explicit ignore-scripts flag suppresses them. The publication executor and registry responses remain injected, including for the real-archive control: no test authenticates OIDC, uploads a package, establishes live provenance or admits that fixture's historical helper as a current release. Workflow tests retain every admission prerequisite and reject publication on non-release events or token-based routes. The preparation scripts do not publish; only the separate exact-tag publisher entry point can mutate npm during authorized CI. The [CI and release workflows](releases.md) compile versioned native artifacts and reuse them for an Occipital-only GitHub release; defining the matrix does not establish actual platform support or authorize inserting unavailable packages/URLs into production. GNU jobs additionally use the [native glibc 2.28 gate](#release-and-platform-validation): full Rust checks/lint, required ELF symbol versions and the actual helper control all run inside the older userspace on each native architecture. No memory/source calibration modes run there; the diagnostic example explicitly reports unavailable pre-2.33 allocator information rather than requiring a newer libc. Container testing does not prove an older kernel's behavior. Third-party source notices, source/binary/toolchain provenance, actual per-target builds/ABI/installation and verified published exact artifacts remain distinct G5 gates. See the [syntax contract](syntax/providers.md#binary-compatibility-and-delivery).

## CLI isolation and evidence

Each Pi process starts with a fresh temporary HOME, agent directory and settings; workspace/session sharing is explicit for same-data execution and replay controls. It loads the offline driver and exercises actual built-in tools, not replacements presented as native execution. Representative metadata fixtures are separate explicit opt-ins. Native, pi-tidy-ui, off/on, reload and replay controls use the same supplied data and owned workspaces. Child processes use isolated settings and do not inherit model credentials. The integration-profile helper reads only locked prepared packages, never the user's installed inventory; tests do not modify user settings, publish packages or change user installations.

The selected CLI receives a test-only in-memory observer through Node's synchronous load hook. Its plan follows the actual CLI import graph, identifies the native interactive class and hashes its original module; incompatible shapes or source changes fail explicitly. Command and frame receipts observe the existing input loop, submit promise, native render scheduling and autocomplete work. `/reload` waits for native submit completion (including shortcut rebinding) and its parsed frame; it does not require the terminal to reprint unchanged `Reloaded` status cells. They neither request extra frames nor accelerate native timers. An ordinary fence completes only after xterm parses its nonprinting receipt after the native frame; detached operations such as the native session picker have their own loaded-screen condition. Ordinary `settle()` waits for a physical frame, not a quiet interval or elapsed animation time. Explicit `observeAnimation()` retains the full 220ms observation window and final physical fence where clock movement or zero warm work across native frames is the requirement; source/provider gates remain separate. Draft-clear keys respect Pi's real double-interrupt exit window rather than relying on unrelated screen delays.

`PiTerminal.captureSettled(name, { action, signal, screen = true })` is the passive result path. The optional action receives the capture's abort signal and must return its actual completion Promise. The observer first permits requested normal rendering, awaits the registered highlighting client's producer boundary, and rechecks the renderer, producer identity and normal-frame count. A later frame invalidates the earlier proof and may admit more work; this uses native frame/producer notifications, not silence, repeated successful assertions or forced rendering. The syntax fixture registers its existing weak client identity and counter sampler at the actual client-start lifecycle for the attached runtime, without waiting for a card or diagnostic snapshot to access it; empty-history startup therefore uses the same boundary without priming commands. The transparent wrapper preserves original start arguments and the exact return Promise and restores the original method at fixture teardown while still owned. The owned fallback logging fixture uses that same attached-runtime/source identity and weak start/attach registration, with transparent delegation and owned restoration on teardown/reload. It does not bind whichever client happened to start last. The observer knows no card/source readiness schema. It samples once immediately before the existing OSC receipt, then xterm detaches the corresponding screen once inside that receipt's parser callback. The default helper returns `sample`, `screen`, `cells` and a small `receipt` containing the existing request, renderer-generation and frame identities; it never invokes `/tidy-ui-dump`. Explicit `screen: false` uses the identical action/producer/render proof and receipt but returns only `sample`/`receipt`, without detaching cells or writing screen artifacts. This choice belongs to each active correlated request, including interleaved counter/screen requests; it introduces no new protocol kind. Component diagnostic/render tests and deliberately held-work frames retain the separate existing capture paths.

Syntax CLI `settledStats` awaits that shared boundary once with `screen: false`, then asserts its expected outcome once; it does not retry correctness predicates. `intermediateStats` is the separate legacy progress observation for deliberately held work, not whole-owner completion. When a test also requires component rows, branch or palette metadata, `captureThenRenderDiagnostics` takes the natural-frame counter/cell capture first and only then executes the explicitly rendered component dump. Its diagnostic fields describe that separate action, not another passive snapshot. Keep the natural sample as the cold work baseline and assert subsequent diagnostic/warm work against it; metadata rendering must not prewarm first adoption. Owned and shared shebang split/unified checks retain that cold sample across resize and compare the entire native/local-work vector, rather than replacing it with post-diagnostic counters. `scenario` opts owned fallback results into that same final path explicitly with `{ ownedFallback: true }`; genuine stock/no-owner and `awaitClassification: false` held-work paths retain their explicit diagnostic captures. Fallback completion does not require native success. Its primitive logger snapshot is only a sample, not journal-drain proof; `loggingFrame` and the explicit journal-drain/render tests remain separate. Recovery results observe the actual acquisition, released fixture gate or clock action before awaiting current work; settlement does not predict a future process-loss notification. Frozen retained paint is not itself held work: completed SOURCE/STYLE and local rebinding use the same final boundary. Truly held replies and SIGSTOP-pending operations keep event/frame observations until release. Resource diagnostics after appearance Off follow the completed UI teardown action rather than asking a disposed owner to report successful settlement.

Settled capture has one watchdog across action and receipt, supports caller cancellation, and rejects producer cancellation/replacement, renderer replacement and process exit rather than accepting a successor's result. Ordinary acknowledgements copy no cells. Only active receipt waits retain request identities; completion, caller abort or exit retires them without keeping cancelled-ID history. Late capture/cancellation packets and correlated errors with no active waiter are discarded before copying cells, including output queued in the terminal parser when the bridge exits. Native cancellation still travels on the existing correlated channel. Pending producer subscriptions are reused across cancelled captures, not attached again to an unchanged unresolved Promise. A delivered `false` completion cancels the covered request before normal-render/autocomplete readiness checks, including a pending or stopped renderer. Frame changes invalidate only successful drain proofs, not cancellation. Receipt waits are armed before sending their existing request; startup `ready` remains the one unsolicited receipt. The original row-wise screen persistence is unchanged.

The same selected-CLI import-graph pass identifies native `Editor` as well as the interactive class; the loader checks both original module hashes. Start/cancel wrappers retain native arguments, returns, Promise identities and debounce/request ordering. Native cancellation only schedules another guard check: an abort-ignoring current request still owes its real Promise completion. A cancelled debounce wakes the observer without a 2 ms poll, and a successor retains the native previous-task chain. Performance-mode preload instrumentation is unchanged.

Cache regression controls release two independent workers before first cache-directory creation and two actual CLI processes before Pi startup against an empty private Node/Jiti cache. The physical pair is followed by serial warm-hit and same-length changed-source checks; warm-loader source-hash rejection stays mandatory. A cold racer may reuse a peer's newly published entry, but at least one actual miss and subsequent Jiti/native hits are required. Sharing compiled source never shares module evaluation, HOME or sessions. Startup gates are bounded test controls, not cache locks or retries. The maintained executable fixture `tests/fixtures/compilation-cache-control.mjs` owns a separate child TMPDIR so other scheduled files cannot warm its cache first; no function serialization or nested test-runner pool is needed.

Pi processes share only a fresh suite-private cache of compiled Node/Jiti source. All test-file workers in one runner invocation use the same cache; the owning runner removes it after the suite, not when an individual worker exits. Every process still evaluates modules anew and gets its own HOME, agent, settings, workspace, temporary directory and session. Jiti's documented temporary cache subdirectory is linked to the private compiled-source cache; no other temporary files or runtime module objects are shared. A real CLI control checks accepted native cache reuse, Jiti hits, fresh process/module execution, same-length source invalidation and warm-loader source-hash rejection. These controls check behavior and work counters, not V8 source-coverage precision; dedicated unit/GC launch environments are unchanged.

Python transports actual PTY output into `@xterm/headless`. Explicit capture fences detach screen text and complete cells synchronously in the matching OSC parser callback, before later bytes can advance the emulator. Ordinary command/frame acknowledgements copy no cells. The parsed receipt already orders all preceding bytes, so fences do not drain unrelated following parser work; shutdown still drains its owned queue. Cells are persisted row by row in the unchanged JSON array format, without building another whole-screen JSON string. Physical-screen assertions inspect terminal cells, including foreground/background/attributes and cursor width, not only calls to `component.render(width)`. The terminal emulator answers native cursor/device queries. PTY chunks enter its native FIFO write queue immediately; the latest callback drains all preceding chunks, including split UTF-8/control sequences. Row-width checks first apply the selected Pi's native cursor composition to component rows: internal hardware/fake-cursor metadata is not terminal output. They then queue independently reset painted rows and check overflow in every row's parser callback, retaining complete text/attribute/cursor/cell controls and draining queued rows before disposal even on failure. ASCII and wide-glyph cursor regressions require real overflow rejection and no parser errors; this is not control-sequence stripping or log suppression. During the existing two-second SIGTERM grace, the bridge continues forwarding PTY bytes so a graceful exit cannot block on a full output buffer. Buffered tail data precedes the reaped exit status and numeric shutdown receipt; a drain/transport error fails the test after cleanup. Resize waits with a bounded deadline for a fresh, matching PTY ioctl receipt and the fixture's observed Node TTY width/height, not a fixed sleep or quiet output; unchanged dimensions still require a fresh receipt. The observer samples geometry on native resize/session-start events, adds no render requests or draft commands and removes its listener on shutdown. A controlled regression delays ioctl and pauses Pi after ioctl acknowledgement, checking width-only, height-only, identical-size and repeated-target transitions in both modes. Input exercises real keyboard sequences and normalized mouse clicks/selection; no production pointer observer is introduced.

After input/host validation, the runner writes machine-readable source/host/Node/selection/network/status reports under the preparation directory's `runs/`, including failures during suite setup, and removes disposable runtime roots in `finally`. Physical captures remain under the materialized project's `.test-artifacts/terminal-<timestamp>-<pid>/`. Live `events.jsonl` reads consume only newline-terminated records: an unfinished tail remains pending, while malformed completed JSON still fails immediately. Every JSONL author uses the shared publisher, which emits a nonprinting PTY notice only after appending a complete record. Editor, foreign-editor, footer, queued-card and terminal-color diagnostic authors likewise notify only after a complete JSON write, so their readers await actual file publication rather than 30ms polling; each physical observation still retains its final frame fence. Event/geometry waits recheck the actual journal or matching ioctl receipt on progress, including an initial check for already-published state; the notice is not itself completion proof. They retain the existing 12-second failure deadline without repeated 30ms polling. The unit/harness `CLI event journal:` controls exercise these reads with tiny inputs. Pure journal, popup, comparator, paging and completion-gate controls live in `tests/harness/terminal-helper.test.mjs`, not the physical CLI entry point. Physical captures are local execution evidence only: CI uploads no captures or reports, only the one-day same-run native transfers described above; safe summaries remain in job logs. Captures include invocations, dumps, terminal output/screens, tool events, model contexts, sessions and coverage/counter packets. Standalone experiments and review reports also belong under ignored `.test-artifacts/`. Record the tested source baseline, exact command, executed versus skipped coverage, findings and unresolved limits there. Do not append run histories or local agent-session paths to project specifications.

### Local artifact retention

After a task is explicitly closed, its reproducible dependency trees, npm/Cargo caches and build outputs under `.test-artifacts/` may be removed with operator authorization. Check live processes and active prepared-input/tool paths first: another task can still borrow a completed task's Node/Rust installation or cache. Do not infer closure from age or a directory name. Preserve plans, reviews, test reports, source identities, custom scripts/fixtures and non-reproducible evidence such as physical captures or performance observations. Retained `inputs.json` files describe historical runs; after their generated inputs are removed, prepare a fresh graph before executing checks again. Artifact cleanup does not authorize changes to maintained fixtures, operator research, public release assets or active task directories.

### Local memory containment and assertion diagnostics

Sanitized HOME/network/process-group cleanup do **not** limit memory consumption. On a local Linux graphical session, run fallible tests, CLI experiments and negative controls through the tracked `scripts/test/safe-run.py`, in a separate systemd scope with an aggregate RAM limit, no swap, and group OOM termination. After preparation, create a receipt parent and use a **new** absolute receipt path for every invocation:

```sh
mkdir -p /absolute/test-receipts
/usr/bin/python3 -I -S scripts/test/safe-run.py \
  --label focused --receipt /absolute/test-receipts/focused-scope-01.json -- \
  /absolute/prepared/node scripts/test/run.mjs --inputs "$INPUTS" \
  --suite groups --files selected.cli.test.mjs --jobs 1

# Feature acceptance uses the same aggregate scope around every stage/worker.
/usr/bin/python3 -I -S scripts/test/safe-run.py \
  --label feature --receipt /absolute/test-receipts/feature-scope-01.json -- \
  /absolute/prepared/node scripts/test/feature.mjs --inputs "$INPUTS" \
  --features footer --refresh --output /absolute/test-receipts/footer
```

Verify the launched process's `/proc/self/cgroup` is outside the compositor service and that its cgroup reports the requested `memory.max`, `memory.swap.max`, and `memory.oom.group=1` **before** running the test. Fail closed if containment is unavailable; a V8 heap flag or JavaScript timeout is not an equivalent process-tree bound. These example limits are local test-safety settings, not product highlighting budgets or measurements of normal Pi memory. The wrapper shares `scripts/test/scope_core.py` with the benchmark guard and independently verifies membership, all kernel limits and inherited CPU affinity on both sides of a pre-launch handshake. It enforces 2 GiB aggregate RAM, 1.5 GiB high watermark, zero swap, group OOM, 128 tasks and bounded whole-scope teardown. It defaults to 300 seconds and permits an explicit justified `--limit-seconds 600` without relaxing memory/process limits. Ordinary tests retain the launcher's allowed CPU set; benchmark-only two-CPU pinning is not ordinary safety policy. The target gets only the scope-receipt locator by default; use absolute executables and explicit inputs. Optional `--env-file` is a complete owned mode-0600 JSON map, never automatic caller-environment inheritance. User systemd bus access stays with the outer supervisor. Both Python entries disable bytecode writes, so loading the shared guard does not modify a prepared source snapshot. Other platforms need their own verified isolation.

The strict `check` entry launches only its TypeScript Node child with fixed `--max-old-space-size=1024`. Checking the complete selected SDK and regression sources can exceed Node's automatic heap allowance before reaching the aggregate safety limit. This explicit **1024 MiB V8 old-generation** allowance is not a whole-heap, process-RSS or process-tree bound: young-generation, native and other process memory still count toward the unchanged aggregate containment above. The parent runner, ordinary Node/SDK workers, CLI workers/applications and other suites retain their existing launch policy; no global `NODE_OPTIONS` is introduced. Compiler options, root-file coverage and dependencies are unchanged. The tiny admitted-fixture runner regression records actual child `process.execArgv` and startup environment for check, ordinary test, CLI worker and CLI application paths, rather than matching runner source text.

Do not pass a live terminal, TUI, child process or similar object graph as the actual/expected value of a potentially failing deep assertion. Assert primitive counts and `===` identity as booleans instead; failure formatting itself can otherwise traverse and allocate for the graph synchronously. Register newly constructed terminals for cleanup **before** the first awaited/fallible startup operation, and test failure cleanup without serializing the terminal object.

## Strict control comparisons

- Compare actual tool arguments/results, cumulative model contexts and persisted metadata exactly. Presentation checks must not weaken these data checks.
- UI actions must leave saved session bytes unchanged. History replay must execute zero new tools/results/model requests.
- Compare native opt-out/restoration with appropriate native controls, retaining all available output. Normalize only an explicitly variable field, such as native execution duration across separate executions; never erase semantic text to make a comparison pass.
- Native live edit preflight and persisted replay are different in Pi 1.0.0. Compare an edit native override with unpatched replay of the identical session, not a fresh execution whose header may include an asynchronous preview. Native Bash can also have a renderer-local `Took` row when the saved result has no recorded duration; compare reload/fresh history with a real unpatched replay rather than removing timing rows.
- Check complete source/command reconstruction without trimming source characters. Distinguish frame padding from actual source indentation and trailing spaces.
- At narrow widths find complete expected summary row blocks, not only shared title prefixes. When user cards are present, identify Bash frames by actual `$ ` content, not by assuming every `┃` panel is Bash.

## Coverage by presentation

| Area | Required controls |
| --- | --- |
| Compact summaries | Exact edit/write path-only/generic fallback and action-first parameter order; visible payloads and exact masking; 256-grapheme values and 1024-grapheme total preview, balanced abbreviations and bounded source-value visits; comma/CJK/grapheme wrapping; oversized-fragment remainder fill and nearest separator cuts with 20-grapheme/half-free-column bounds and JSON escape controls; continuation origins and native Output-padding 0/1 exterior margins; tiny/zero widths; complete failure colors; no result bodies/badges by default; native expansion |
| Shared frame and Bash | Complete multiline commands; comments/workdir; ten-row visual preview and overflow; partial/final metadata; exact separated exit-footer and timeout-pair exceptions, numeric-code/pair-boundary guards, one-block-only removal and partial-to-final replacement before cutoff; embedded/separate-content terminal reminders, adjacent groups, malformed/nested/cross-block guards, muted foreground independent of command status, separate ten-row previews/shared expansion and exact replay; tabs/Unicode/controls; panel/stripe/margins in both themes; selection-safe whole-panel clicks; regular/fullscreen controls |
| User cards | Original Markdown transformations and semantic styles at equal content widths; OSC 133 zones; physical geometry/colors; native selection and copied text; no user expansion; off/on/reload and replay |
| Queued cards | Full plain-text cards in the native pending slot, not history; native/compaction ordering, complete metadata and remapped edit-all hint only in the last card; `max(10,floor(height/3))` whole-block budget including decoration, first-to-last 5→1 sweeps, early stopping, in-row ellipsis and overflow without dropping cards; tiny/Unicode/control widths and raw-data preservation; badge background equals stripe foreground, dim parentheses/muted hint in both themes; unchanged native edit-all/delivery and later pending components; missing/foreign shape guards, native removal/clear and first-owner GC including a natively pre-rendered queue rebuilt while still nonempty; native hit geometry and scoped render descriptor restoration on success/failure/immutable/later owners; exact one-column ellipsis on full-width Unicode/tiny rows; zero added requests or body builds on warm/height-only frames; real keyboard enqueue/dequeue, physical regular/fullscreen blocks, resizes, off/on preserving drafts, reload/replay and strict native model/session comparisons (only cross-run timestamps and validated assistant durationMs are normalized) |
| Main editor | Conditional unpainted upper-widget separator for nonzero returned rows, no separator for absent/zero-row/lower-only widgets, live height/multiple-widget transitions, default-color empty cells, shifted text/menu clicks, no extra foreign renders against exact native SDK counters, owned descriptor restoration and active first-upper-group GC; supported-host compatibility gates require real native spacer/dock/render order and actual CLI feature activation rather than accepting graceful fallback; same native instance/state; user paint with native Editor padding as exterior margins; real `/settings` values 0–3 change the whole input/status/edge without reload, preserving fixed inner gaps; full-width hardware marker at every margin; impossible-margin native fallback; native menu/status and overflow; CJK/combining normalized clicks; expanded-paste maps and atomic programmatic text insertion, undo/history and shortcuts; custom-factory/subclass/instance/later-owner guards; active first-installer GC; both modes, themes/resizes, off/on and empty-draft reload; native separate activity routing with unchanged indicator identity/clock and complete same-editor state, public-flag/setter/focus restoration and SDK compatibility activation, model.name/provider ID/selected thinking freshness, Idle/busy-hidden/unknown-native precedence, literal/Unicode native status preservation without fragment extraction, physical half-block paint/default background, semantic metadata/path/branch foregrounds, right alignment/one-cell padding, two-block column quotas and ordered grapheme-safe path/branch reduction, native roots, real Git discovery/worktrees/bare/unborn/detached/environment/watch/cancellation controls and zero Git jobs on warm frames; active off/on, autocomplete metadata hiding while native activity remains visible, pending/empty-suggestion controls, footer/menu placement, short-height native activity versus metadata clipping, reload and replay |
| Session footer | Native cumulative accounting parity across assistant/tool/side/compaction/branch-summary/abandoned records behind three false-by-default source flags; no hidden auth reads; ten primary reports in chronological order without equal-percentage merging or streaming/render double counts, eviction and side-usage exclusion, cold zero/full error bar versus unknown/dots, all eight inverse height levels, cache-write denominator, latest CH alignment and saved restoration; real 33-request/30-tool native controls in both modes; context k/M precision/carry/null/undefined, disabled-only auto-off warning and current window/settings/auth; requested dark/light bar/bracket/dot/auto-off/CH colors and rounded-CH versus raw-context thresholds; cache-first/CH-before-context order including absent context and auto-off, cache-prefix priority under tail clipping, one-row statistics and whole-producer-status-preserving right-aligned packing with full-row-only ellipsis, ANSI/background/bold/link isolation, tiny/Unicode/exact-fit rows; no dangling separators; off/on/reload/session/replay and later foreign owner, initial/late foreign editor disables footer, exact-stock foreign factories and instance guards, eligible explicit-on recovery and temporary native selectors; active first-footer GC; real CLI native data/traffic and zero warm/Working history/context/aggregation/layout work, ordinary low-height clipping |
| Edit cards | Actual built-in successes/failures; argument-streaming and executing gates; final failure summaries; old/new syntax including multiline tokens and hidden opening context; metadata formats/hunks/numbers; context cap and omission rules; one-sided unified/mixed split; semantic/contrast-bounded code and number/sign backgrounds; neutral/missing hints; saturated/indexed gamut edges; empty-pane/right-padding paint; native click expansion |
| Write cards | Actual stock creation/empty-file fill/replacement/clearing/failure; isolated compatible metadata shapes; Created/Edited/Replaced/Wrote classification before context projection; no-op/truncated/malformed/hidden cases; full available numbered source without diff signs/tint; shared diff geometry/syntax; native expansion and lifecycle/replay controls. The test-only capture gate enrolls only currently useful write owners and retires them on pause/removal; weak owner identity prevents a late old-owner retirement from removing a same-call replacement. Hidden zero-row cards remain excluded, and capture must still match the complete set of framed writes |
| Shebang-derived file language | Exercise the bounded alias detector and UTF-8 byte limit, direct and supported `env` forms, unknown/no shebang, malformed control lines, and explicit shebang-selected language over path, and path-only selection when language is absent. File-preparation tests must use authoritative `old=1`/`next=1` coordinates, verify one-side format inheritance versus two independently selected formats, propagate hints across omitted source fragments, and reject hints made visible only by display sanitization. Controller/protocol tests cover canonical language selectors, payload admission, exact `source_hint_revision`, absent/null/empty selector semantics, optional path and pathless text, malformed field shapes, stale same-source replies, and one-shot plus streaming resolution. Real owned stdio and shared-helper CLI controls must observe physical colors: split shared context uses the grammar for each displayed side, unified context uses the new grammar, and no-shebang remains an ordinary `unknown_syntax/not_started` fallback without an unexpected-error notification. Correlate successful v4 SOURCE and generic STYLE replies with the actual Python and shell string scopes, and require each painted string to match the selected local palette binding; relative equality alone can pass on fallback paint. Descriptor controls require the exact six advertised operations and reject the removed theme-refresh operation. The actual classifier corpus also checks the 44 common semantic slots, declaration-owned parameter qualification and grammar contexts without a matching variable scope. Require a positive measured-row count for the unique shebang fixture before asserting that width-only warm frames add no measurements. Do not substitute source-payload checks or in-memory renderer tests for the physical color assertions. Refresh the prepared source snapshot, run affected `syntax` groups and `test:feature --features syntax` with required native/shared inputs; missing integrations are not acceptance. |
| Edit computation | Complete minified source and ANSI growth bounded by supplied style-command lengths and glyph count; monotonic prepared-coordinate/range work; palette-generation colors; validation-only uncached spacing/rejected input; malformed native fallback; large changed blocks without argument-spread overflow |
| Output padding | Real `/settings` 0→1→0 without reload; physical summaries and Bash/edit/write/user frames at 24/100 columns; fixed internal gaps and live mouse bounds; independent Editor padding and unmodified native delegation; same-session native/off/on/reload/replay with strict traffic/session bytes; restored file history is checked first as bounded preview, then as full content only after an actual card click, with preview and full compared to matching modes; retain physical full-panel padding/stripe checks as well as preview checks; settings read once per normal document pass rather than per tool/neighbor; latest-layout cache key/inline height/spinner origin and tiny widths at both values; project-overridden settings remain authoritative if native user padding diverges, preserving Markdown with no component mutation. If Pi keeps the live tool owner, compare its exact rows before and after; if the native setting rebuilds saved history, require bounded restored previews and compare exact full rows after supported expansion (fullscreen click or regular Ctrl+O). |
| Terminal defaults | Resolver forms/vars/BOM/zero; independent OSC channels and ownership; source error versus intentional empty/no-file; fixed/auto/system and project override; cold/late/reload/renderer mode guard/order and SDK drift; export-only hot reload; native query semantics/prototype preservation; stale/partial reports and weak pending-promise ownership; process-only channel handoff/exit cleanup without observer retention; source/profile RGB projection with unchanged Pi Theme; physical edge/diff and local off after native reload; warm zero source/report/output/projection counters; local/master controls; normal exit; exact native traffic/session/replay |
| Lifecycle/compatibility | Existing/future/history components; hidden/image/native safeguards; exact-name overrides; reload/shutdown/later-owner restoration; native TUI renderer replacement; active-adapter first-installer collection |

CLI edit controls cover builtin dark/light and the isolated Gruvbox fixture, narrow/unified/wide layouts and regular/fullscreen same-session replay. Palette checks measure final physical RGB contrast for code, numbers and signs, preserve original foregrounds, and export small SVG color swatches plus numeric metrics under local terminal artifacts. These are terminal-cell color evidence, not pixel-identical graphical-terminal screenshots or a universal accessibility certification. The minified CLI control changes one final digit in a 16000-character line and verifies complete old/new source rendering, physical colors, warm counters and exact traffic/replay; it does not benchmark Pi's word-diff algorithm. Dense substitutions at 400/800/1600/3200 repetitions remain in the unit regression with grapheme-work and ANSI-growth counters. Unit controls additionally cover file-type dispatch beyond the CLI TypeScript/HTML files, alternate metadata shapes, impossible tiny glyphs and native image-protocol fallback. These are distinct layers, not exhaustive parser or graphical-terminal coverage. Compact-preview CLI fixtures use CJK and combining characters for physical Unicode checks; joined-emoji preservation is additionally asserted in unit/source rows. The default headless Unicode 6 provider measures a joined family emoji as four cells while Pi measures two, so exact physical joined-emoji width is not claimed by this harness.

Editor CLI observations use a test-only shortcut so capture does not submit or exchange the draft. The observer loads production pi-tidy-ui unchanged, controls its actual registered command and verifies native editor identity/state. Remove only the exact zero-column native hardware/fake-cursor APC markers when comparing projected strings to physical cells; do not normalize source characters or weaken complete ANSI/native-cell comparisons. Native tiny-width wide-glyph recursion, actual OS IME windows and graphical image insertion are outside this gate; unit checks retain native tiny authority, expanded-paste state and atomic programmatic text insertion. Clipboard-image callback/map behavior is not directly exercised; keyboard input and host image handling remain native. Pi's foreign-editor-factory state-transfer/reload limitations are not claimed fixed; the same-default activity-routing self-transfer is explicitly suppressed and regression-tested.

The foreign-editor CLI regression compares a separately loaded factory extension against processes that never load pi-tidy-ui. It requires identical complete ANSI editor rows, physical input/widget cells, input/expanded-paste/cursor state, hardware cursor geometry and normalized fullscreen mouse events; complete native footer data/ANSI is restored at every foreign-editor lifecycle phase; absolute screen y is checked against each real physical click; upper/lower widgets must remain contiguous with no pi-tidy-ui separator or metadata/edge rows. Both extension load orders, takeover after warmed stock presentation, a registered factory returning the exact stock class, extension-owned shortcut/method identity, both embedded and separate native active Working, themes/resizes, off/on, empty-draft reload and same-session replay are covered. Tool presentations must remain active; calls/results/model contexts and session bytes stay strict. This is a real factory integration, not full installed `pi-powerline-footer` execution; regular-mode mouse remains terminal-owned.

## Performance counter discipline

Use observable work counters, not timings as the sole proof:

- Compact argument formatting must serialize only bounded string prefixes and visit only the displayed prefix of structured values; path-only edits/writes must not enumerate/read ignored fields. Unicode caps preserve whole graphemes/escapes. These counters do not claim that Pi's native argument processing or root key enumeration becomes bounded.
- An unchanged retained frame must build no custom body and repeat no custom highlighting/wrapping/color work. Updating one tool rebuilds that tool; actual width/theme changes legitimately rebuild affected layouts. Height-only changes/scrolling should reuse retained bodies.
- Proven stock edit custom states must make no discarded native visibility render calls. Unpatched/expanded native controls must remain positive. Custom/mixed/reused-Box self-render visibility must remain native-authoritative, with no phantom neighbor spacing.
- Component-owned entries survive former count/byte pressure and oversized layouts. Check one latest layout per owner, exact kind/group/aggregate arithmetic and footer estimates; clear/off/shutdown; immediate ordinary detach/nested-subtree-clear release even while owners stay held; weak microtask retirement for the stable TUI's current-renderer clear, preserving synchronous same-owner transfer and already-moved descendants while blocking detached queued work; pending-retirement owner GC and unload; weak rows/owners/accounting GC with an active adapter; and repeated attach/render/remove cycles without accumulation. Retired command arguments must report usage without evicting data. Real CLI controls remove/reinsert an actual built-in owner without changing saved traffic/session bytes, then check both regular/fullscreen warm and clear/replay counts. Lookup misses are not body builds: metadata-only spacing may miss without materializing a diff.
- Retained-byte statistics are accounting estimates; reported process heap is the whole Pi process. Neither establishes pi-tidy-ui heap ownership, GC pauses or user-session latency.
- Footer counters distinguish session aggregation/record visits from presentation rebuilds. Native `SessionManager.getEntries` and `AgentSession.getContextUsage` spies preserve original methods and expose actual calls. Ordinary width/theme/status changes must not redo history/context work; warm/native-Working frames also rebuild no layout. The fixture loads the unchanged production extension and its diagnostic getter in one graph (separate extension-loader module copies would make false-zero counters); the native control never activates pi-tidy-ui. Opt-in scripted usage and an explicit real persisted side-usage record are supplied fixtures, not live billing or installed Magic Context validation. Strict traffic/session/replay comparisons remain unchanged.
- Git source counters distinguish discovery and branch refresh from rendering: ordinary warm/animated frames must start zero subprocesses; metadata/semantic changes must refresh without polling. Real temporary repositories cover actual executable results, atomic HEAD changes, available reftable backends and Git environment isolation. Cancelled/old-cwd replies must not publish; disabled/foreign/shutdown runtimes must release watches/jobs. Linux/POSIX CLI evidence is not a Windows filesystem-watcher guarantee.
- Terminal-color counters separate accepted metadata reads, channel sets/releases/packets, default reports, stale replies, projection builds and warnings. The fixture shares the production module graph to avoid false-zero diagnostics. Fifty warm renders must change none of them. Controlled OSC handlers retain application overrides across profile changes, answer with actual model profile/current values and require releases before native auto-selection queries. A public query may also request ANSI palette entries; no palette writes are permitted. Local off can sample released profile RGB without reading metadata or applying defaults. Initially auto and auto reload/switch must keep feature reads/reports/sets/resets zero. Physical foreground/background cells verify the local projection, not only component strings; a native no-feature control and strict tool/model/session replay comparisons remain required. This model does not establish support/no-flicker/identical pixels in every graphical terminal.
- Syntax counters distinguish supplied/encoded source bytes, completed-line/tail calls, SOURCE and STYLE dispatches, local style binding, glyph measurement/reflow and matching-prefix verification, Pi classifications/bridge installs, provider generations and unsettled reservations. In the online-wait recovery control, keep the early backend snapshot for request/byte accounting, but take the warm-work baseline only after the first recovered physical frame and its command-color assertions. Backend settlement can precede delivery of the local adoption notification and its first prefix comparison. The deterministic SDK control retains that real notification until SOURCE/STYLE have settled, releases it once, observes the initial proof, and then requires exact counter equality across width changes; it adds neither a readiness retry nor a delay. For genuinely gradual prefixes, an ordinary append must preserve completed-line calls/bytes; a nonappend correction is one named source resynchronization. Warm frames and width changes add zero source/style work; width changes add no glyph remeasurement or repeated scalar-prefix verification. A first uncached style selection must show positive style work; cached theme reuse must explicitly assert unchanged requests. Shared request-specific counters may be uninstrumented, so their zero values alone prove nothing; pair positive dispatch/parser/local counters with exact warm equality. Keep exact model/tool/session fields and replay's zero executions strict; inspect physical foreground cells rather than only rendered ANSI. For fullscreen exit compare default transcript with resume-hint: saved Bash/edit/write owners must add no SOURCE/STYLE, source preparation or glyph work, and the actual final normal-screen transcript must preserve complete source text and literal foreground/background/font cells. Inspect the completed journal after successful PTY exit and verify helper cleanup and unchanged session bytes. An opt-in held-response control receives an actual short-source Rust result, withholds delivery to the controller and checks real input/tool progress, unchanged warm counters, zero Pi capture attempts/bridge installs, eventual native colors and strict stock traffic/session equality. It tests an unsettled client response, not deliberately slow parsing, worker fairness or latency. Application byte charges do not prove whole-process RSS/OOM bounds or control private SDK buffers.
- The actual-native owned-palette burst seeds its 20 complete sources one at a time and requires `whenSettled() === true` after each. Before the 100-choice warm interval it verifies every key's provider acknowledgment, exact complete source version and published complete display at the initial palette. A single local `flush()` does not guarantee remote admission: [DATA admission](occipital/protocol.md#admission-and-scheduling) may refuse work for physical job or byte capacity.
- Owned-palette input acceptance uses test-only, scoped observation of package-file opens/reads, `PaletteInputOwner.prepare` calls and existing `DataBudget` statistics. A menu-only preview must cause no palette open/read or input preparation; requesting the selected card supplies a positive cold-read control; a successful warm owner lookup may acquire a lease but must not reopen or reread the asset. The second-owner warm interval performs the same accepted visit plus `useful(owner, revision)` render enrollment as production for both live owners, settles the controller, and requires unchanged file-I/O, lookup, lease-byte, preparation-receipt and SOURCE/STYLE counters. A separate 100-choice live-card loop checks retained bytes and semantic-entry count at every settled point against the non-palette baseline plus the current input, not the history of selections. The owned-role compilation counter is restored in `finally`; cold preparation compiles one immutable value per card role, warm reuse compiles none, and each funding refusal must refund without compiling. These are focused local test counters, not production instrumentation or a heap-allocation profiler.
- The real shared-host Follow Pi CLI test runs independently in regular and fullscreen modes. Each mode exercises live Pi-origin paint and light/dark palette rebinding, then replays the saved session in a fresh process over the still-running shared host. Replay may take one finite Pi source capture per restored file fragment; every capture must receive shared SOURCE parsing and current Pi-origin paint. It must preserve tool output, perform no model/tool calls, publish actual SOURCE/STYLE results and add no warm SOURCE/STYLE/palette work or additional Pi source capture/projection. Its counter record separates positive replay SOURCE/STYLE totals and per-fragment Pi captures/bridges from palette/warm deltas; connection-acquisition counts alone do not establish whether useful work ran. The test requires the prepared native helper and shared host, and complements rather than replaces the separate shared suspend/recovery cases.
- Logging overhead controls first prove active real journal writes, then drain pending startup/snapshot work before the baseline. A test-only zero-row public widget acknowledges actual native frames without calling `render` itself. Unchanged frames and repeated same-size resize receipts add exactly zero journal records, detailed writes, rotations or cleanup scans; native classification/Pi bridges and strict stock tool/model/session data remain unchanged. Reload/replay keep session identity and obtain distinct runs; cancelled session replacement keeps the active run. Real-file errors and disabled capture are separate SDK/unit controls. First-tool/user/editor/footer/color/spinner GC probes keep an actual writer alive. The text journal never stores command/source bodies; test traffic/session evidence remains the separate existing harness data. Linux/POSIX checks do not establish Windows ACL behavior.
- SDK synthetic workloads prove mechanisms, not real tool execution. Keep their results separate from actual CLI traffic/replay evidence.

Public **Display cache → Clear saved layouts** receipts snapshot counters synchronously before the resulting repaint; a diagnostic capture can itself materialize current-width layouts. For a strict spinner warm interval, clear through the popup, close it and make a preparation capture, then obtain a fresh cache packet and verify that all tool/user owners are represented before defining the baseline. The cold preparation is outside the no-new-build interval; do not use the earlier clear packet as its baseline or replace exact counters with delays/retries.

Alternate-width manual dump probes intentionally replace the latest-width cache. Diagnostic scenarios suppress those probes when measuring warm frames; generic captures keep them for width coverage. Spinner diagnostics also avoid width-zero probes, which intentionally stop animation participation. Native asynchronous startup/grammar invalidation can add cold work; establish a controlled cache-clear epoch before asserting exact warm deltas.

Spinner checks distinguish host-driven prefix changes from fallback wakes. Deterministic SDK visits every 80 ms must yield zero pi-tidy-ui requests, changing time-based prefixes and unchanged custom builds. A 100 ms silence deadline makes one request regardless of participant count, queues no duplicate while awaiting a document visit, and rearms from successful return rather than a fixed interval phase. A native request before the deadline with delayed document completion must still permit exactly one fallback; holding completion queues no further deadlines/requests, and resumed successful 80 ms visits suppress fallback again without rebuilding bodies. Verify one shared deadline, a call-local phase for slow passes, no acknowledgement from mere requests/direct tool/unrelated renders or failed document visits, obsolete callback rejection, silent-detachment pruning on host-driven passes, lifecycle stops and zero idle resources/requests. The isolated actual-SDK `spinner-gc-probe.ts` also holds the real unreferenced Node handle and production callback until the last owner is collected, then dispatches expiry: zero rearming, requests and retained entries. Only dispatch is controlled, so early expiry cannot release an accidentally captured owner and make GC falsely pass. Native clock identity/lifecycle controls remain unchanged.

The real CLI spinner scenario runs in both regular and fullscreen modes. During native `Working`, prove physically moving compact glyphs and native Working glyphs, one pi-tidy-ui request per expired document-inactivity deadline, and unchanged body/invalidation counters. Zero fallback is required for timely successful document visits (covered deterministically), not merely for an enabled native indicator; a queued native request does not acknowledge document completion. Use public `setWorkingIndicator({ frames: ["●"] })` to stop native animation while the actual tool remains running, then prove moving physical glyphs and exactly one request per eligible fallback wake; restoring native animation must resume physical native Working movement and document visits while retaining the same one-request-per-expiry and unchanged-work guarantees. The fixture observes production timeout allocation/cancellation/expiry/unref counts separately: at most one pending deadline, and `starts - cancels - ticks == active`; cancellation/rearming is not an animation wake. Sampling physical frames does not call `render` or submit diagnostic commands. Retain unchanged body/invalidation counters, native partial/full-information, completion/cancellation/off/on/reload/replay, strict tool/model/session equality, UI-only session-byte equality and active-first-installer GC. A direct document diagnostic still counts as the accepted layout signal; these tests do not establish a public after-present hook, precise physical cadence, total CPU/latency or O(1) host layout.

## Installed-extension profile and limits

The integration test reads the audited manifest/lock in `tests/fixtures/integration-profile/` through `integration-profile.mjs` and requires `--integration` preparation. A missing or mismatched package is a setup failure, not a skip; the developer's installed extensions do not select coverage. Its sanitized environment and temporary configuration preserve real registration while disabling networked/secondary model work and unrelated background services. Fresh HOME is required as well as the isolated agent directory because some packages read `homedir()` directly.

In that profile, local task tools have real execution/renderer coverage. Agent, web, ask and Magic Context integrations have registration-only coverage; registration does not prove their renderer ran. AFT is excluded because startup schedules auto-build/refresh/warmup work; keep-awake is excluded because it starts an OS sleep inhibitor. Deterministic AFT-shaped diff/diagnostic/exit metadata tests do not execute installed AFT or subscribe to its LSP.

No full user-runtime compatibility guarantee is made. Graphical Kitty/iTerm2 image display, all host/parser/terminal versions, identical OpenCode Tree-sitter grammars or literal screenshots, arbitrary competing private-method hooks and whole-process heap/latency distributions are not established by this harness.

## Changing behavior

Start with a failing regression for the contract being changed. Keep native/data controls strict, run the affected gates, and use an independent fresh-file review for substantive behavior/integration changes. Reviewers should read the current source and authoritative SDK/reference sources; summaries and an earlier green run are not a substitute. Record findings and final execution evidence locally, explicitly separating reviewer source inspection from parent-run compiler/tests.

Maintained documentation describes the current architecture, accepted behavior and reproducible verification method. Historical run counts, superseded proposals and agent handoffs are working artifacts, not new project contracts.

## README screenshots

The checkout-only `npm run screenshot -- --inputs INPUTS --output NEW_DIRECTORY` uses the prepared Pi/native graph and verified Linux scopes to retain an offline Pi ANSI frame, render it in a real temporary foot window and capture only that window with grim on Wayland/Hyprland. [Screenshot generation](screenshots.md) documents all tracked inputs, explicit system tools/font, fresh-clone preparation, source refresh, outputs and manual asset replacement. Old `.test-artifacts` files are not inputs. Native rendering needs declared foot/grim/hyprctl tools and the caller's desktop coordinates only in its separate graphics stage; it does not use SVG or ImageMagick. `tests/harness/screenshot.test.mjs` provides portable CLI/workspace/readiness/color/SVG controls, including tracked Gruvbox theme, model/thinking metadata, native Working presence with Idle exclusion, independent SVG raster scaling without changing the captured grid and actual-OSC default-color observation. Working mode uses one pending local simulated provider turn, then aborts it before shutdown; it makes no external model request and does not replay tools. The capture receipt separates local requests, external requests and cancelled local streams. The current demo also uses private `editorPaddingX: 1`/`outputPad: 1` settings, a one-line unfinished, unsent editor draft with the native cursor at its end, visible native thinking and interleaved compact calls including one wrapped query. A preceding research reply anchors the user card, a restored missing-file result exercises the ordinary error presentation without executing a failing operation, and the larger router patch retains existing route behavior. An additional edit contains added test lines and unchanged context only, selecting the ordinary full-width unified view at 160 columns; the terminal is 104 rows high, leaving the normal separator above Working after the additional Bash row. A single `&&` chain after the write card naturally wraps into three visual rows: router/test syntax checks, a focused Node test with its full quoted name, then diff/status inspections. It preserves the actual cache-control test failure status 1; the trailing Git commands are skipped by shell short-circuiting. Its scripted tool result has numeric `details.exit_code` and `isError: false`, so the unmodified presenter shows `[exit code: 1]` without an execution-error label. The later addition-only query-parameter test is staged but not rerun in this demo. This example generation is distinct from regression-suite acceptance. Its 147k/272k context comes from synthetic saved usage and the offline model's real declared limit, not a replacement footer. The real `tests/cli/harness/terminal-workspace.cli.test.mjs` control verifies that normal `PiTerminal` fixture seeding remains enabled and `seedFixtures: false` preserves caller-owned files without creating the test fixture set. The screenshot opts out so its dedicated Git clone receives only the story files. The existing pure SVG controls do not certify native foot capture. Actual Pi/native/foot/PNG generation is an additional manual integration, not an automatic CI screenshot job or a substitute for the release gates.

The portable screenshot controls require the complete visible story/context/exit-status metadata and preserve a drained cell/ANSI frame across newer parser work and asynchronous output writes. `tests/harness/linux/screenshot-native.test.mjs` uses explicit inert foot/grim/hyprctl/supervisor tools: successful toplevel-only capture, grim failure, missing acknowledgement, wrong grid and both catchable termination signals must stop/await the owned child before rule/runtime cleanup. These tests contact no compositor and require no actual Occipital artifact; their sentinel PNG/scope replies are contract fixtures, not real rendering, native admission or kernel verification. Run them through the ordinary real containment with refreshed sources, then perform a fresh real foot/grim capture for manual integration acceptance. SIGKILL/host crashes remain outside catchable cleanup.

## Manual performance measurements

[Performance testing](performance-testing.md) describes the opt-in `test:perf` command, prepared inputs, synthetic SDK/real-Pi workloads, raw V8 counter/CPU/retention metrics, bounded process-tree peaks, profiling and saved-result comparison. Its [metric boundaries](performance-testing.md#metric-boundaries) explain allocation-buffer accounting and the influence of boundary sampling: cumulative counter deltas are not exact JS-object allocation traffic, and heap growth is neither allocated volume nor proof that no GC occurred. Normal CI runs framework correctness controls only; it does not run benchmark batches or enforce machine-dependent performance thresholds. Never interpret cumulative counter bytes as live heap/RSS, a sampled profile as an exact object count, or a kernel whole-tree peak as target-Pi RSS.

## Presentation-specific validation

Use the catalogue groups above, not historical task plans, to select checks. These requirements supplement those groups; they are not a second file registry or source-impact CI selector. They do not replace prepared-input provenance, real integrations or process containment. Controlled Node pipes, real Pi SDK classes, actual Pi/PTY, Rust helpers, real shared hosts and published-package consumers establish different things; none silently substitutes for another.

### Cards and native data

- Compare exact call arguments, result/model context and saved session bytes before and after UI operations. Representative third-party metadata is shape coverage, not execution of an installed AFT extension.
- Bash checks cover complete command reconstruction, comments/workdirs, whitespace and 10/11-row previews, partial/final replacement, structured exit/error combinations, strict duplicate-footer and timeout-pair guards, metadata-qualified own-task annotations, trailing reminder recognition and independent previews. Check malformed, foreign, ANSI-decorated, cross-block and nonterminal candidates as literal output. Verify native opt-out/compact precedence, selection-safe expansion and zero warm work.
- Edit/write checks cover both saved diff formats, numbering, one-sided versus mixed changes across all hunks, context projection, unavailable gaps, hidden-context syntax, plain Created/Wrote sources, empty/no-op/truncated/malformed metadata and source-versus-submitted-content distinctions. Bounded-preview tests also compare a complete short malformed hunk with a genuinely cut hunk, count the physical input-row cap including headers, verify a hidden suffix adds no retained descriptor funding or classifier input, preserve tabs/Unicode/control sanitization on the visible prefix, prove preview-to-full source preparation includes the newly exposed suffix, and prove accepted full-to-preview demotion releases full display/source charges, invalidates the old measurement, and lets the old display-row array and a real measured region be collected through WeakRefs while the owner, original full arguments and bounded preview remain live. Pending tests use Pi's standard `edits[]` shape as well as the legacy top-level pair, prove array precedence, and stop work at the shared per-call unit/row bounds. Final-error tests prove array precedence and retain all funded saved entries and text beyond ten entries, 8,192 units and ten rows, without target-file reads; the denial control retains only its bounded unavailable-details message. With malformed preview metadata, guard diagnostic entries and messages to ensure the bounded notice remains O(1); full mode retains a positive diagnostics control. Check streaming/partial/failure routing before any diff inspection, whole-summary error paint, execution-only animation and native visibility/override/image guards. The automatic file-view window is the rolling latest ten successful attached write/edit owners across turns. During an active turn, an owner remains preview until its matching completion is finalized. Eligible successes are batched and demoted only at `turn_end`; empty/non-file turns leave the window unchanged. The focused `file-preview-state.test.ts` also pins missing/mismatched completion rejection, owner-record replacement, attached-owner filtering, reverse-order success recency, late completions after turn end/reset and pruning candidates after their weakly held owner is collected. Turn start/end share the clearing of pending/current-turn successes; reset additionally clears manual and automatic history. Record successful attachments before hidden/native presentation guards so completed hidden or explicit-native file calls still occupy recency slots without changing how they render; apply the ceiling to attached final-success candidates, and do not backfill an older demoted card when a recent owner is removed. Restored history starts bounded. Verify 3+2-turn accumulation, 9+2 retaining only the newest ten, a batch above ten and reverse completion order; manual per-card choices, global Ctrl+O and selection-safe clicks remain independent.
- Compatible third-party write/edit result shapes must retain their saved-data cards with original callbacks and producer state untouched. Cover visible foreign self-shell, genuinely empty self-shell at actual width, and mixed stock/foreign call/result pairs. These controls prove presentation compatibility, not zero native callback work; only the exact Pi 1.0.1 public tool-renderer resolver may defer/evict stock callbacks. Keep its stock laziness assertions separate. A mixed pair must also retain an already-materialized deferred stock half across custom presentation, while a complete exact-owned pair may release its native cache. The direct SDK `createToolHtmlRenderer` callback control keeps HTML-renderer and TUI owner state distinct even for equal tool-call IDs, leaves host renderer state untouched, and releases superseded native children when a custom preview takes over while Pi still owns old mouse-layout wrappers. Separately, Pi's real `/export <path>` command template-renders `write`/`edit` from saved session data; it does not invoke their deferred TUI stock callbacks. Its real-CLI control decodes the embedded session payload to check the full saved write call tail and matching result, verifies session bytes/model/tool traffic are unchanged, and keeps positive native callback evidence in the separate Appearance-Off TUI control. For unsupported bounded previews, measure the following tool's gap from the same owned multi-row fallback that the predecessor renders and prove the stock callback stays cold; preserve the separate explicitly unsupported-full native control. Distinguish cache release from obsolete callback retirement: genuine native callback replacement/invalidation must reuse the current owner component/state, and the first completed native edit frame must reflect the available call plus successful result. Test native→custom→native without new callback regeneration or global invalidation. Throwing native callbacks/components must produce bounded non-sensitive fallback and a visible runtime-health issue which a later successful callback generation clears. Renderer-transfer tests must preserve the accepted display/ticket across a transient clear and reattachment, apply source changes made while detached on that same ticket, release ownership after actual removal, and avoid rebuilding extension layouts during direct detached renders.
- File paint identity includes whether retained source slots match the current card version; a mode change can make otherwise identical source temporarily ineligible, then eligible after local preparation. Keep Pi-following and owned-palette preview→full→preview controls with the actual semantic foreground, exact full text/returned rows, no extra Pi/SOURCE/STYLE work, and unrelated source jobs held. This file-only identity must not change Bash projection/warm-prefix behavior. Check independent diff backgrounds and actual emitted foreground contrast with dark/light, Gruvbox, saturated, indexed and unknown colors. Cover Unicode/control/tab safety, tiny widths, unified/split layouts and all source rows. Count source preparation, glyph work, palette builds and warm reuse separately; cover argument-spread-sized changed blocks and validation-only spacing/rejected clicks.
- Retain sparse/minified and dense algorithmic edit controls; a physical sparse case does not replace dense SDK complexity checks. Compact-summary controls cover punctuation, long words, arrays/objects, bounded masking, failed paint, continuation clicks and native expansion without overriding intentionally hidden renderers.
- Real stock edit/write operations and representative metadata fixtures are separate controls. Use actual Pi 1.0.1 and current Pi, regular/fullscreen live and same-session replay, widths including 24/100/140, Ctrl+O, native appearance off/on, native tool overrides and `/reload`. Pi's regular TUI mode does not parse SGR mouse input; run selection-safe pointer-click controls only in fullscreen, and use Pi's actual global Ctrl+O key in regular mode to compare full and bounded presentation. Restored history starts in bounded generic `Write`/`Edit` preview; assert its visible rows and physical ink separately, then deliberately select the full owned view before comparing complete live/replay colors or body rows. For source-replay measurements, keep the initial bounded-prefix capture/SOURCE counts separate from any full-view work caused by expansion; derive expected full SOURCE fragments from the complete write input and saved edit diff, and match the expansion counter delta to exactly those fragments. On collapse, match emitted SOURCE text to the exact initial bounded captures and its counter delta to those prefix fragments; do not assume preview and full source text are identical. Prove full physical content after it settles, compare warm frames to the full-view baseline, and keep subsequent warm-preview frames quiet. After appearance re-enable, assert the Pi expansion state actually retained: compare the bounded preview when collapsed, or the full owned view when expanded, and only then compare matching rows. A same-live-session `/reload` may retain expansion but restore Pi's `argsComplete=false`; for failed edits, compare against a native replay in that same restored phase rather than a live-native `argsComplete=true` result whose preflight and boxed error layout differ. A separate real-Pi write history executes 12 successful files in one turn, an empty turn and one more successful write; it checks the newest-ten rotation, an older manual full-view choice across the empty turn, all-preview replay, exact saved tool/session data, and records observed full-redraw and scrollback-clear counters in fullscreen 100×240 and regular 100×40 without imposing a timing or zero-redraw threshold or promising scrollback preservation. Large hidden-suffix equivalence remains a controlled source/unit proof; the real CLI large-source gate separately verifies bounded source traffic. `nativeRenderCalls` counts host component frames, not stock callback preparation; measure warm render deltas from the baseline immediately after final On, because Off legitimately renders native components. A new replayed session starts in bounded preview. Global Ctrl+O also expands other Pi tools; compare their actual full output against native controls instead of applying compact-summary border assertions to expanded tools. All successful file cards, HTML cells and session data remain compared. When both captures use the same full-view geometry, compare the original styled rows directly; use body-only comparisons only where the header legitimately wraps at a different width, with exact physical panel snapshots retained per width. Separately verify fixed service-row, omission, unavailable and click-hint bounds after Output padding at widths 1, 2, 24, 60 and 100; include regular-mode physical rendering so the stock renderer cannot throw on an overwide row. In regular mode use this real global key because Pi does not dispatch SGR mouse events there; fullscreen retains the individual selection-safe click controls. An expanded custom write error presents the saved request and error detail rather than Pi's native expanded layout; compare unrelated/native tools separately and assert the payload plus error code. Owned file clicks change the file-view choice without claiming to set Pi's `node.expanded`; stock-native expansion remains a separate control. The lifecycle smoke retains an exact same-session Pi-native full write/edit reference with Appearance Off, separate from Toolview's custom full view under Appearance On. During custom file views assert zero stock write highlight-cache/edit diff/preflight invocation and retain positive native plus HTML export controls. The real minimum-host startup/lifecycle CLI can enable a test-only observer on the internal `DeferredRenderer.materialize` method in the same extension module graph, before any tool component is constructed. It records effective per-tool/per-slot stock preparation attempts only when the wrapper is live, has no materialized child, and retains its invocation callback; each extension epoch is checked independently across reload. The probe verifies zero attempts through custom construction/rendering and a positive callback path through Appearance Off or an explicit native override. Its prototype identity and positive control fail closed; a zero count alone is not evidence, and the probe says nothing about arbitrary foreign callbacks or a raw renderer pair. File preview↔full transitions that reuse identical text must regain current-version paint while unrelated native jobs are held, with no added Pi classification, SOURCE or STYLE. For an already accepted full logical file display, repeat same-width denied geometry grants and count `CardSources.updateDisplay` separately from geometry attempts: source preparation stays at zero additional calls, each frame retries geometry, and ordinary funded recovery uses the retained display. A geometry-grant denial does not prove paint was reached. Pending/error files use owned bounded summaries and do not invoke stock renderers merely because `expanded` is true; test actual updates, collapse/reopen, missing-path pending work, and saved error access. Collapsed and warm layouts must not traverse result text; pending full details retain only the bounded excerpt, and final-error sources are enumerated for funding before joining/measurement after the funded cold input/mode transition. Resize and following-sibling spacing reuse the prepared detail, while funding refusal retains no copied body or hidden native layout. A collected expanded-error owner releases its funded receipt without a per-turn scan of all retained error cards. Denied final-error details show a bounded details-unavailable marker, distinct from a full successful-card funding refusal. A native edit may have an asynchronous live preflight error preview absent from replay; native override comparisons use same-session native replay rather than erasing this distinction.

### Streaming display versus work

- Hold real or controlled replies while appending one-line and multiline commands. Matching historical foregrounds, including provisional tails, remain visible; every current character is shown and new graphemes are neutral unless their first scalar belongs to the matching prefix. Corrections never recover matching suffix islands. Include combining/variation/ZWJ/Prepend/surrogate boundaries, controls, tabs and narrow soft wraps.
- Count dispatches, parser calls, body builds, explicit invalidations and host render requests independently. Waiting, same-text completion and completion-only acknowledgment do not rebuild unchanged bodies. A style-changed reply must repaint even when parser-call counts are zero. Final empty appends still settle real leases.
- Live formation failure freezes SOURCE work, preserves compatible ready paint and allows valid already-requested STYLE to finish under current ownership. It does not execute arguments or revive a lease. A new restored owner receives one finite classification, including incomplete saved arguments; subsequent warm/width changes add no source work. Bash uses zero Pi classifications in every fallback state.
- Exercise availability backlogs with multiple weak owners, held acquisition/replacement, newest-first cooperative batches, removal/pause/freeze/GC, latest-version coalescing and an event-loop turn after at most two preparations. Recovery must not reparse already-current owners or turn an unrelated refusal into readiness demand.
- Use physical foreground cells throughout actual Pi streams, not just final screenshots. Compare complete native tool/model/session data, live/replay glyphs and geometry. Warm frames produce zero new parser/RPC/normalization/log/I/O work; width changes perform only necessary reflow from retained measurements.

### Frames, queued messages and stock editor

- Independently assert exterior margins, panel/content/click bounds, fixed internal gaps, terminal-default stripe/background resets, ordinary/error stripe foregrounds, neutral panel and no hover/motion repaint. Reconstruct complete commands from physical cells at real terminal widths, not only direct component renders. Exercise renderer replacement and selection/drag/wheel/nonprimary guards.
- User cards compare actual SDK Markdown at equal content widths, preserving every glyph's foreground/attributes, OSC zones and copied text. Include zero/empty/tiny widths, native padding changes, image-protocol delegation, later-owner restoration and first-installer GC. Component protocol guards do not establish graphical-terminal image support.
- Queued-message controls use actual native queue/compaction order and edit-all methods. Cover the 5→1 first-to-last height reductions, decoration accounting, early stop/overflow, remapped hints, Unicode/ellipsis/badge cells, appended foreign components, call-local descriptor restoration and native mouse geometry. Warm/height-only frames do no body wrapping/painting. Include held-removed-owner and first-owner GC, both terminal modes, enqueue/dequeue/delivery, off/on/reload and exact native data equality.
- Stock-editor controls use real SDK identity, paste maps, programmatic insertion, cursor/undo/history/focus and native shortcuts. Cover exterior padding 0–3, impossible-margin delegation, end cursor, status literals, autocomplete mouse routing, foreign factories/subclasses/instance/later owners and restoration on failure. Actual CLI controls include large-paste expansion across off/on, native settings without reload, CJK/combining input, dark/light cells and 24/60/100-column resizes. Hardware-marker/painted-cursor checks do not establish OS IME windows, clipboard-image callbacks or graphical image insertion.
- Upper-widget controls verify the supported managed container/spacer composition, upper-before-editor order, exact native render counts and an active separator immediately before input. Include absent/zero-height/lower-only/multiple widgets, height transitions and unknown-shape fallback. Supported-host activation tests must fail if a changed host shape silently disables the feature.
- Below-editor controls cover width reduction, roots/Unicode/color roles, actual native activity identity/clock/unknown kinds, autocomplete and busy/idle transitions. The synthetic HOME path stays short and independent of prepared runtime depth so boundary checks do not accidentally test path truncation. Use real Git discovery, environment isolation, directory-watch replacement/cancellation and zero warm-frame Git-process counters. Preserve stock-editor state through public status relocation and verify weak-owner collection. Low-height controls compare native/custom placement and resize restoration; ordinary clipping is allowed, not a guessed widget-height guarantee. Status literals are not border decoration.

### Footer

Verify native cumulative accounting behind the three false-by-default source flags; side/tool/summary/abandoned usage; no hidden authentication reads; ten-report ordering, equal consecutive percentages, unknown versus zero, error/abort reports and cache-write denominator. Check context/CH precision and thresholds independently, full-width statistics truncation, whole-status transfer/truncation, Unicode and SGR/hyperlink isolation. Exercise session-title five-column minimum, separator boundaries, public rename/clear and zero extra history/context work. Real regular/fullscreen live/replay checks cover theme/settings/status changes, foreign-editor/footer ownership, delayed startup selectors, off/on/reload and first-footer GC. Supplied offline usage/status fixtures are not live provider billing or installed Magic Context/Powerline integration.

### Terminal defaults and lifecycle

Cover default-Off startup with missing/empty/theme-only or initially invalid settings, explicit saved On/Off, and returning to Off when a shared terminal-color preference is removed. Defaults must not write configuration or set/reset unowned terminal channels, and native highlighting stays On. Real regular/fullscreen startup checks observe no color changes until explicit opt-in, then verify saved On across reload and explicit Off releases. Enabled lifecycle/repaint fixtures opt in explicitly. Cover resolver/channel first-red cases, independent OSC releases, atomic last-good retention, numeric zero, actual SDK mode/SGR/observer activation and invalid host-field guards. Exercise fixed→automatic ordering under project overrides, initially automatic/late loading, both renderers and reload with no transient application. Observe actual OSC set/reset/report traffic and physical repaint of an unchanged marker; same-value ordinary refresh, RGB-only reports and warm frames must not force redraws. Verify session handoff without unchanged-value reset/reapply, no-successor cleanup and owner-free process exit.

Use real shell job control for Ctrl+Z/`fg`, not only direct method calls: independent releases, current target restoration, Off/automatic/empty transitions, failed start, retained draft/paste/cursor/session bytes and Reapply after a foreign reset. Include stale queries, source errors during suspension, inactive-controller/pending-report GC and zero warm read/query/output/projection work. Check diff/half-block colors with stale native defaults and late unowned reports. The headless terminal's profile/override model is not universal graphical-terminal coverage; a graphical-terminal smoke test is separate.

A forced-repaint control enters native appearance tracking through ordinary rendering without manually invalidating the unchanged target widget; otherwise it can miss reentrant cursor/previous-row corruption. Regular forced redraw may clear scrollback without changing the saved session.

For Occipital suspend recovery, hold actual SOURCE, STYLE and incremental append work in both owned/shared modes. Include a stop beyond the production request deadline without increasing that deadline. Assert intentional interruption, actual old-helper exit before replacement, fresh leases with latest full text, useful current/new cards, no expired-old-timer effects and no clicks or reload. Cover idle-provider retention, repeated stop during recovery, preexisting ordinary failure, Native Off/on, paused/frozen/removed owners, crash budgets and the bounded shared-return window. A pending model response is not a pending Occipital request; the independent shared service must stay running. Each routine suspend case immediately persists `suspend-lifecycle.jsonl` (also embedded in `suspend-evidence.json`): transport/mode/operation, wall-clock timestamp and monotonic nanoseconds at proved stopped state, immediately before `fg`, and after resume. Intersections of same-host monotonic stopped intervals from independent files prove overlapped waits; incomplete intervals are diagnostics, not acceptance. Traffic/persisted captures remain unchanged and do not claim a saved-session replay in every suspend case.

### Retained layouts and animation

Use counters to prove unchanged frames build no custom bodies; one mutable-object update rebuilds only its owner; neighbor measurement does not build hidden Bash/file bodies. Exercise warm full-document scans beyond former count/byte caps, oversized live entries, one latest width/state, exact group/kind/accounting totals, clear/off/disposal, held detached subtrees, active-first-owner GC, later method owners and renderer transfers. Estimated layout bytes are not exact V8 or whole-process attribution.

For compact spinners, separately count elapsed-time phase, successful document visits, fallback deadlines and explicit render requests. Deterministic controls require zero fallback with timely 80 ms document visits, one request after an expired deadline, no repeat while that request awaits a successful document visit, successful-return-only rearming and stale-callback rejection. Merely enabling native Working is not proof of timely document completion. Real regular/fullscreen controls use Pi's public one-frame Working setting to stop native animation, prove physical fallback movement, then restore native animation. Preserve body/invalidation counts, lifecycle/visibility/selection/data guards and active-first-installer GC.

### Diagnostics and runtime health

Filesystem/child-process controls cover private permissions, batch/rotation/retention bounds, partial writes, dropped records, write/overview failure and bounded shutdown. SDK/GC and real offline Pi live/replay controls cover capture Off, writer-independent owner-specific health, coalesced error notifications, recovered versus owner-removed disposition, stale callbacks and exact tool/model/session preservation. Active-logger warm frames add zero records or I/O. Before no-work assertions, prove capture is active and drain startup/pending records. Exercise two runs of the same saved session, late old-owner callbacks, explicit retry and logging Off; useful mixed native/Pi/plain decisions require real Pi/helper boundaries, not an earlier RPC alone. GC controls exclude strong card/source retention. Do not infer runtime health from log-line counts, provider readiness or success of another owner; do not infer Windows ACL/watch behavior from POSIX results.


### Syntax and palette validation

The producer-owned [`whenSettled()` boundaries](syntax/work.md#observing-completed-work) need deterministic hold/release controls, not a native-job-count or timed-silence proxy. Hold the actual source notification after SOURCE/STYLE jobs reach zero, verify the waiter remains pending, then release delivery and assert the first measured Bash-prefix proof and exact warm equality. Supply an explicit observer predicate for new source markers; an unselected marker cannot establish zero work. Also hold the real host-turn preparation continuation, include work queued by delivered notifications, observe startup/preference restoration and an already-running provider probe, and prove that observation starts nothing or advances no future timer. Check shared pending-Promise identity, explicit `false` on lifecycle cancellation, old-completion rejection, native-disabled local preparation and active-first-owner GC. Hold preference loading across repeated observation/suspend/resume and count subscriptions to the unchanged restore/startup Promises: cancellation must not accumulate new producer observers. Keep physical reservation assertions separate from waiter cancellation. For escaped group-presentation GC, retain the first owner and preparation through `whenSettled() === true` and a successful current-palette publication/read. While both are still strongly held, capture the global bookkeeping baseline and return only their weak references, the reader and that primitive baseline. Do not insert an awaited settling interval after the helper returns: it could collect the target before the refund baseline is measured. Then keep a live peer, perform the bounded 40-turn GC check, and require the owner/preparation to collect, the reader to become invalid and global bookkeeping to decrease.

Withdrawal controls keep another controller's two physical slots held while pausing/removing the last blocked preparation, both alone and with an unpaused but idle sibling; a genuinely queued sibling must still block. Cover SOURCE freeze/removal/refusal/empty replacement and desired STYLE withdrawal, retaining genuinely useful frozen STYLE. Also replace a parsed, clean SOURCE that is blocked only on STYLE with a different empty generation: client empty styles must finish locally while a missing selected-palette input must keep waiting for real funding. Replace uncached STYLE with cached local styles and separately with another uncached rule/palette selection; identical effective selections must not add withdrawal wakes. Use another card's normal geometry funding to produce real current-generation and frozen-previous eviction receipts, without a new parser request hiding the stale-wait failure. Preserve an actually queued preparation and a lease close as independent positive controls.

Deliver terminal transport denial through the actual broker/client metadata and card paths while another controller holds both physical slots. Await the real FILE Pi fallback and the final unavailable broker separately: fallback can finish during the preceding transport-retirement publication. Keep the Follow Pi selection and native source retained; drained failed-provider work must not depend on foreign credit. Also change the public Pi palette after failure with retained nonempty semantic contexts to detect accidental renewed STYLE credit interest; keep the unparsed-generation palette case as a separate control. Deliver actual recoverable `lost` through the broker and hold its real replacement acquisition: source work may drain, but the original client/provider observations must remain pending until recovery and its delivery finish. Verify cached offline rebind, incompatible-vocabulary preservation and fresh late dispatch validation after a reentrant selected-input callback invalidates the provider, including positive context-visit and zero-encoding/dispatch counters for that rejected work. For a genuine local-work control, queue work reentrantly from a real preparation/delivery callback before the original observation can finish, then hold the real quota continuation until explicit release. Work first admitted after an observation has completed requires a new observation instead. A rejected request or fake readiness flag alone does not establish this terminal lifetime transition.

Count ordinary wakes to prove repeated no-op withdrawals are inert and assert that group withdrawal reconciles only after all members are removed. Verify unchanged physical jobs/bytes/admission, LIFO order, the actual two-owner host-turn barrier and cached-local controls; the permitted extra ordinary reconciliation may have quota-bound continuations, not just one microtask.

Run focused `completion boundary:` tests and affected existing controller/client/provider/runtime/GC checks from a freshly refreshed prepared source snapshot under [aggregate containment](#local-memory-containment-and-assertion-diagnostics). These producer checks alone do not establish terminal-frame/result-capture integration or replace real CLI/replay acceptance. The `settled capture:` observer controls separately hold first-frame work, finish it before a later frame admits a second operation, keep unchanged pixels/frame counts while externally changing counters, and cover native debounce cancellation, abort-ignoring requests and chained successors using the actually loaded Editor. Keep operation cancellation, owner/renderer replacement, exact receipt-order cells (including a split receipt), zero ordinary copies/one explicit copy and sampler work/render counters as independent controls. Real CLI proof must use this same passive helper and fixture-owned counters, not a diagnostic render command or a counter/color polling predicate. Caller-adapter controls must hold actual producer delivery even at zero native jobs, reject a wrong completed outcome after one assertion, and propagate producer failure. Keep the natural-frame cold sample before separately completed component diagnostics; diagnostic rendering cannot establish or rewrite the cold work baseline. Counter-only controls retain the same held action/producer/later-frame ordering, require zero cell copies/screen writes, reverse mixed-request receipts and reject cancelled or post-exit late results before copying. Real empty-history startup in both terminal modes must succeed before any stats/dump command, use zero screen copies and send no tool/model traffic. Keep exact prepared-work deltas and physical cell/color assertions, but retain frame IDs as evidence rather than demanding global absence of legitimate native redraws. Observation-induced rendering is checked with deterministic observer/producer counters, without an idle/Git gate or suppressing native activity.

Pure provider/controller/range/palette tests do not establish Rust or transport compatibility. Protocol/font/resource changes require matching TypeScript and Rust vectors plus a real SOURCE/STYLE round trip. SOURCE-hint changes additionally test exact `source_hint_revision` negotiation before payload submission and memory/byte admission. Real native/shared groups need their admitted same-source helper and supplied shared host; selected checks cannot pass by skipping missing inputs. The palette-independent Rust resolver tests also retain global exact-score declaration-order ties for null and qualified rules, separate foreground/background/font-bit winners, explicit zero-mask inheritance, global and empty-context behavior, cursor-local prefix reuse, workspace and maximum-depth admission, and cursor validity after the resolver owner is dropped. Parser context tests separately exercise zero-width clear/restore scopes without comparing against removed native-theme behavior.

Follow Pi uses real public theme prefixes, not guessed theme JSON colors. Cover dark/light, Gruvbox, neutral, indexed-only, partially known and default/faint inputs in truecolor and 256 colors. Generate indexed swatches with the selected prepared Pi graph's actual ANSI encoder, not a generic xterm quantizer; compare the emitted DATA code with its source RGB and record the encoder version. Compare final emitted colors, role-specific marker separation and contrast on already-fixed code/diff surfaces. Static literal palettes keep one RGB per marker slot: accept a derived shade only when that same RGB remains distinct and meets contrast on the final fixed surfaces in truecolor and after the exact prepared Pi 1.0.0 256-color encoding; otherwise retain the parent RGB rather than invent mode-specific palette values. Recompute against the complete finalized palette before emitting swatches. Inspect whole source at normal size: numeric color distance alone is not visual acceptance. Include both Markdown-bold forms with exact accent, opening/closing markers, nested italic/strike/link/code, fenced code, lists, headings, links/images/reference definitions and repeated markers.

The owned-helper Follow Pi palette fixture serializes DATA calls only on its own `StdioTransport`, forwarding each original request and options. This isolates visual correctness from protocol-permitted `busy` refusal under bounded credit pressure; the fixture asserts a settled, single-request transport and every SOURCE/STYLE dispatch admitted. Keep this wrapper local to palette visual proof: admission/concurrency tests must exercise real overlap.

Owned palettes must not borrow Pi fallback colors; a complete Pi fallback after owned-asset failure must follow actual public Pi color changes. Host transition tests compare the exact selected semantic binding ink against neutral card-code ink; merely matching any palette color does not prove semantic paint.

Owned-palette acceptance reads real manifest-owned package assets, covers all 72 IDs and every output-quantized semantic/card role, and exercises known-file missing/corrupt data as well as invalid/unknown IDs. Enforce the exact six-digit RGB form and reject a valid JSON payload padded beyond the 32 KiB file cap. Prove one bounded user notification plus active status/health issue on failure, release on recovery, coherent prior-paint retention while a replacement fails, and Pi-color resampling only while whole-card Follow Pi fallback is active. A static owned palette must remain unchanged across Pi theme changes. Funding-denial tests must prove the attempted acquisition actually failed, preserve the desired Pi projection without reusing an owned lease, and include positive acquisition/denial counters plus same-source recovery. Final emitted diff-surface contrast is checked through truecolor and exact 256-color encoding, independently from helper-equality assertions. The real installer verifies its initial local Pi and owned-palette input paths; final-adoption cleanup tests retain both funded-identity mismatch and late getter-throw controls.

Audit grammar-scope names and their meanings against the [pinned grammar definitions and static vocabulary](occipital/assets.md#extracting-all-static-grammar-scopes) generated by `crates/occipital/vocabulary_build.rs`. Inspect context relationships and selector precedence where names alone are insufficient. A finite corpus neither defines that vocabulary nor proves exhaustive language coverage. Focused regressions exercise the actual classifier's changed mappings and font composition; a mismatch in rules assembled from proposed expectations is not baseline-classifier failure evidence. Use the prepared test runners; scope dumps are optional diagnostics, not a separate acceptance prerequisite.

The shared `crates/occipital/tests/fixtures/follow_pi_corpus.json` is checked by the Rust context/vocabulary test and by `tests/integration/native/syntax/follow-pi-scopes.native.test.ts`, which is catalogued in the syntax feature group and exercises the current production Pi rule definition through the native helper. The Rust check verifies byte coverage and generated-vocabulary membership for those concrete parses; it is not an exhaustive inventory or semantic mapping proof. For its TypeScript case, it also asserts the actual pinned grammar's `variable.parameter.ts` declaration versus `variable.other.readwrite.ts` use, and the `meta.object-literal.key.ts` wrapper present on a quoted property key but absent from an ordinary string value. Keep classifier expectations independent of rule construction. The native test's controls protect JSON key versus string, shell command versus variable, parameter-token current binding, and nested Markdown typography. It starts admitted work with one host-style `flush()` and then awaits `SourceController.whenSettled()` for producer-owned completion and notification delivery; repeated flush/readiness polling and native job counts are not completion evidence. The TypeScript object-key-versus-string expectation is a positive classifier assertion: the source has a distinct property-key context, and the common rules map its key text to a distinct property semantic slot before the Pi adapter binds that slot to `syntaxVariable`. Parameter declarations and ordinary variable uses likewise remain distinct semantic slots at the common-classifier boundary, although Follow Pi maps both to the same public role/ink. These controls verify classifier identity separately from final color equality.

Real regular/fullscreen cards, unified/split edits, live and saved-session replay, preview/cancel/confirm, external settings, theme switches and cached rollback must preserve source text and coherent per-card paint. For shebang-derived language selection, cover real edit/write over owned stdio and shared service with an extension that selects a different grammar; one-side hint propagation; independent old/new hints; split shared-context colors from the displayed side and unified shared-context colors from the new side; explicit language overriding known path and Plain Text; path-only selection when language is absent/null/empty; pathless explicit language; expected unknown-format no-start; malformed-hint rejection; and rejection of an older helper before SOURCE. Use observable SOURCE/style/measurement counters to prove a changed first line triggers the required new SOURCE work, while warm frames and width-only changes do not; verify that the initial measurement count is positive for a unique shebang fixture marker so unrelated measurements cannot make a zero-delta check vacuous. Native Off/On keeps its existing release/re-admission semantics. Both edit panes switch atomically. Check cold file upgrade behind newer owners without clicks, canonical fallback authority while SOURCE is pending/uncertain, stale publication rejection and warm/width-change zero-work controls. A selected palette rebinds retained expressions locally and cannot resynchronize already-parsed source merely to change colors; only missing or evicted compatible expressions require STYLE.

For volume-policy changes, keep `src/occipital/limits.ts`, the Rust limits and `protocol/syntax-v4/highlighting-limits.json` aligned. Exercise inclusive boundary/one-over aggregate batches, many blank lines, UTF-8-safe cuts, compact context expansion, decoded storage, escaped JSON size and cumulative appends. Saturated-tail changes send no more source work; refusal keeps valid/neutral display without unlimited fallback or warm retries. Check actual owned/shared cleanup, physical credit and borrowed-storage lifetime. Measure both supported Node runtimes with ordinary, dense, many-line and compact-expansion inputs; new limits need new source-bound measurements, not relabeled prior receipts. Coverage limits are not whole-process RSS or arbitrary-regex deadlines.


### Settings and preview

Cover real popup keyboard/mouse/search, clipping, scroll visibility, confirmation, per-visit rollback, late completion, persisted versus process-local switches and external-file changes during an unconfirmed preview. Preserve invalid files/unrelated settings, serialized writes and same-setting last-writer semantics; do not infer cross-process locking. Assert actual saved two-space pretty JSON and its final newline, including nested unknown data and exact numeric tokens. Loading compact input must not reformat it; the 64 KiB serialized-output boundary includes formatting whitespace, and an oversized formatted replacement leaves the old file unchanged. Owned-palette preview/rollback must exercise real manifest data, funded input and card rendering; menu stubs alone are insufficient, and missing semantic styles still require the matching helper. Opening status cannot enable a disabled provider, rewrite a session or produce model messages.

## Performance runs

The [framework contract](performance-testing.md) defines metric meanings, workload identity, containment and comparability. Run only against owned prepared inputs and generated histories, never personal transcripts. Refresh source snapshots after changes. Native-required workloads need a same-source helper and its actual build policy; the label below is an example, not an inferred property of a binary hash.

```sh
npm run test:prepare -- --node /absolute/pinned/node --pi-version 1.3.0 \
  --tools /absolute/tools.json --output /absolute/new-inputs
# Add --rust-root /absolute/pinned/rust --build-native
# (or admitted --native-inputs) for native-required workloads.

npm run test:perf -- --inputs /absolute/new-inputs/inputs.json \
  --output .test-artifacts/perf/baseline --profile quick \
  --native-build-policy cargo-release-rust-1.99.0

npm run test:perf -- --inputs /absolute/inputs.json \
  --output .test-artifacts/perf/frame-scaling --profile standard --cases frames \
  --repetitions 3 --native-build-policy cargo-release-rust-1.99.0

npm run test:perf -- --inputs /absolute/node26-inputs.json \
  --output .test-artifacts/perf/diagnostic --cases frames --cards 100 \
  --variants on --repetitions 1 --allocation-profile --gc-profile \
  --native-build-policy cargo-release-rust-1.99.0

npm run test:perf -- compare \
  .test-artifacts/perf/before/results.json .test-artifacts/perf/after/results.json \
  --output .test-artifacts/perf/comparison.json
```

Keep all repetitions and failures. Compare the same variant under compatible environment/workload/observer identities; do not combine SDK passes with terminal frames, infer allocated volume from heap growth, treat unavailable metrics as zero or subtract unrelated observer overhead. Required Linux cgroup/systemd containment fails closed; do not raise resource limits to turn a failing run green. Diagnostic profiling changes measurement identity. Numeric threshold policies require the framework's repetition and matching rules; they do not replace deterministic work/data assertions.

Add scenarios only in the bounded workload modules/fixtures with versioned inputs, explicit readiness/warmup proof, actual completed-work counts and cleanup. Run ordinary framework correctness tests and affected actual-Pi frame controls; ordinary CI does not run benchmark batches or impose machine-dependent latency/RAM thresholds. Product optimizations remain separate from measurement-tool changes.

## Release and platform validation

Packaging-policy tests use inert fixtures; they do not execute an actual delivered helper or authorize publication. Real ABI/protocol/consumer gates and exact public-release admission remain separate. Use the [release contract](releases.md) for immutable artifacts, enabled platforms, source/tag authority and mandatory workflow joins.

```sh
npm run check -- --inputs /absolute/path/to/prepared/inputs.json
npm run test:native-release -- --inputs /absolute/path/to/prepared/inputs.json
npm run test:rust-check -- --inputs /absolute/path/to/prepared/inputs.json
node scripts/release/version.mjs --resolve refs/tags/occipital-v0.1.0
```

For GNU baseline validation, provision the pinned Rust sysroot (rustfmt/Clippy included), official Node 22.19.0 and locked Cargo dependencies in an owned Cargo home. Use Docker on the corresponding native Linux architecture. Acquisition is preparation; the execution container cannot fetch missing inputs. After preparation:

```sh
RUST_ROOT=/absolute/path/to/rust-1.99.0 \
CARGO_HOME=/absolute/path/to/prepared/cargo-home \
NODE=/absolute/path/to/node-22.19.0/bin/node \
bash scripts/release/linux-gnu.sh x86_64-unknown-linux-gnu
# On a native ARM64 host, use aarch64-unknown-linux-gnu.
```

The wrapper checks native architecture/glibc and owns image/cache/SDK mounts. Image creation may need networking; execution uses `--network=none`. Internal `_gnu-native` orders format, workspace tests, allocator checks, strict lint, locked release build and ABI admission with offline Cargo. Actual-helper smoke follows separate exact-artifact staging/preparation before consumers; `_gnu-native` is not a standalone host-baseline check or that smoke. Honor `CARGO_HOME`/`CARGO_TARGET_DIR` and use isolated output. The diagnostic `engine_probe` returns unavailable allocator data as `null` before glibc 2.33; this gate runs no calibration mode.

Keep both independent optional/non-optional npm consumer installs and exact same-source bytes. Lock/dry-run closure preparation does not establish actual installability. Test zero optional bootstrap downloads, one cold fixture download, zero warm HTTP, UTF-8/incremental work and real process reaping. Public registry/GitHub verification requires its explicit extension-release authority and network profile; it is not hermetic coverage or fallback for missing current-source inputs. Linux enforcement controls do not establish equivalent OS-level egress enforcement elsewhere.

### Changelog and release-note controls

Run `npm run changelog:check` before committing. The prepared `delivery` group
covers the restricted Markdown/SemVer reader, exact product entry extraction,
immutable GitHub release retries, staged npm history and development/prerelease
tracking policy. `harness/ci-plan` and the actual workflow shell controls establish
that extension GitHub notes are required only after verified npm publication and
that the notes job has no npm/OIDC mutation authority. These are inert publication
controls: they execute real local Git/npm archive operations where needed, but
remote GitHub/npm calls are injected and no tag or public release is created.

`harness/packaging/changelog.sdk.test.mjs` uses the installed SDK's real
`DefaultResourceLoader`, package metadata and changelog parser against staged
stable/prerelease/disabled packages. On Pi 1.5 it requires package-origin metadata
with the enabled path only for the stable package; on the older supported SDK it
establishes package loadability and native-parser compatibility, not a nonexistent
extension-update UI. It asserts only the intended stable update is selected and
that the current native dependency footer survives. This is an SDK integration,
not a physical startup-screen or external npm publication check. Stable projection
also rejects literal column-zero H2 rows in fenced examples, which Pi's simpler
reader otherwise mistakes for version boundaries.
