Quality bar: testing and performance
Tests run in three layers (unit tests beside code, property tests for codec and state-machine invariants, snapshot tests for wire bytes and rendered frames).
Full source summary
Tests run in three layers (unit tests beside code, property tests for codec and state-machine invariants, snapshot tests for wire bytes and rendered frames). The unit pool is just test (cargo nextest run --workspace); the full root PR bar is just ci-full. Performance is measured, not guessed: crate benches, a release profile tuned for shipped binary speed, and opt-in mutation runs that are not a CI gate.
Test strategy
Tests are organized in three layers. All three run today.
-
Unit tests colocated with the code they cover, plus crate integration tests under
crates/*/tests/. The workspace pool isjust test(cargo nextest run --workspace).just ciincludes that pool plus compile-free contract gates (fmt, lint, rustdoc, deny,just docs-check, and others listed in CONTRIBUTING.md). It does not spawn real PTY-backed servers. -
Property tests (
proptest) for invariants that should hold across arbitrary inputs. They live inphux-protocol(codec roundtrip),phux-core,phux-client-core(session kernel), andphux-tui:- Protocol codec roundtrip: encode, decode, and the result equals the input. This is the codec’s primary safety net.
- State-machine invariants, for example that after any sequence of commands the layout tree stays well-formed.
- Replay equivalence: for any PTY byte stream, writing those bytes into a
fresh
Terminalon the client reproduces the same visible grid the server’sTerminalsaw, up to the documented downsampling rewrites. The snapshot-on-attach synthesis algorithm is checked the same way: synthesize, replay into a freshTerminal, and compare the resultingRenderStatesnapshots. Seestate-sync.mdfor the synchronization model this verifies andresearch/2026-05-25-libghostty-renderstate.md§7 for the synthesis algorithm.
-
Snapshot tests (
insta) for outputs that should change only on purpose:- Wire bytes of representative messages in
crates/phux-protocol/tests/frame_wire_snapshots.rs, so an accidental format change is loud rather than silent. - Rendered TUI frames and chrome, via a cell-grid to ASCII-art helper.
- Wire bytes of representative messages in
Real-server and smoke lanes
These spawn real processes and sit outside just ci on purpose. A just ci
failure always means a deterministic defect; a green just ci is not the
PR bar.
just e2e— the fast e2e lane: ignored*_e2e.rsbinaries against PTY-backed servers (headlessrun/wait, agent-record loop, spatial edits, wall-clock perf). CI’stestjob runs this;just cidoes not.just agents-fleet-smoke— hermetic argv/control-flow gate for the placed-fleet example. No live server.just ci-full—just ciplusjust e2eplusjust agents-fleet-smoke. That is the full root PR bar.
The herdr parity work uses a repeatable gate in
../../scripts/parity-gate.sh, surfaced as
just parity-check-list and just parity-gate. The list/check mode is cheap:
it proves the named scenarios are present and still point at real scripts,
just targets, tests, and example/plugin assets. The run mode is explicit
because several scenarios spawn real PTYs, tmux, or the full CI gate.
The gate names eight evidence surfaces:
install-contract: install docs/scripts/release artifact contract checks.examples-smoke: examples/agents against a realphuxbinary.plugin-demo: checked-in plugin discovery, validation, and actions.real-pty-run-wait: the ignored e2e lane for real PTYrun/wait.tui-probe: black-box attach through an isolated tmux terminal.visual-qa-hooks: captured TUI probe output with screen and cursor markers.docs-check: the doc-system gate from this conventions layer.full-quality-gates:just ci, including fmt, lint, docs, tests, deny, and rustdoc.
Each user-visible parity child task records four receipts in the work ledger:
automated verification, a real-surface artifact, adversarial checks, and
cleanup. Evidence files live under .omo/evidence/; they are execution
artifacts, not product docs.
Mutation testing
Mutation testing with cargo-mutants is opt-in, not a just ci gate.
../TESTING_MUTATIONS.md owns the runner,
budgets, and how to read killed/survived/unviable results. There is no
required mutation score.
Performance
phux does not optimize speculatively. What is measured today:
- Crate benches:
phux-server(capture,server_measure),phux-client-core(history),phux-tui(render_frame). just perf-echo— reproducible keystroke-echo latency against an isolated release server.- Server integration tests under
crates/phux-server/tests/perf_*.rsandbenchmark_budget.rs.
The release profile uses fat LTO and a single codegen unit, since the speed of the shipped binary is a goal in its own right.
Status
| Gap | Today | Owner | Tracked |
|---|---|---|---|
| A fixed published set of throughput, fanout, and reattach numbers as a regression gate | Benches and perf-echo exist; they are not a required CI check with pinned budgets. | — | not scheduled |