Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ under `contracts/fixtures/`.
- Tests mirror source topology one-to-one. Split a source module and its test together; do not add to
the legacy `interaction.test.ts` or platform `index.test.ts` aggregations. Pure moves carry their
tests unchanged; rename-only hunks owe no new coverage.
- A test sits beside the module it is named for: `<module>.test.ts` or `<module>-<aspect>.test.ts`
(R84). Cross-module package tests are `index-<aspect>.test.ts` beside `index.ts`; repo-level guards on
Swift sources, manifests, docs or scripts live in `test/repo-guards/`.
- Add no package `exports` entry that points at test support; R83 only lets the legacy count fall. A
fixture one package uses stays inside it, imported relatively; helpers shared across packages live only in `@agent-device/test-kit`, a
`devDependency` production source never imports and that never depends on `platform-*`,
`provider-*`, the daemon or root.

## Toolchain and worktree traps

Expand Down
2 changes: 1 addition & 1 deletion docs/agents/test-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Authoring rejects; audits hunt:
- type pins posing as runtime assertions (`Equal<A,B> = true`, `X ? true : never`, `satisfies` after erasure, `toHaveLength(n)` over literals); if erasing leaves nothing executable, use `void [fixtures]`;
- mocks asserting their own inputs; negative controls passing for the wrong reason;
- names promising more than the input exercises;
- dead code called only by tests; tests preserving test-only exports.
- dead code called only by tests; tests preserving test-only exports; a production package `exports` entry only tests import.

## Retention criteria

Expand Down
29 changes: 14 additions & 15 deletions docs/agents/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ Two selection traps recur:
- A workspace package manifest or TypeScript config can rewire all consumers, so the affected
selector fails open to the full gate set on purpose.

Docs-only changes with no runtime behavior impact need no runtime tests or new tests asserting prose.
Keep required gates; after those and focused checks pass, repeat or broaden only for changes,
failures, or unresolved risks.
Docs-only changes need no runtime tests or tests asserting prose. After the required gates, repeat
or broaden only for changes, failures, or unresolved risks.

## Platform and live-device policy

Expand Down Expand Up @@ -67,13 +66,15 @@ Read the entry file before running a lane. Do not copy its environment matrix he

## Shared test utilities

Before creating fixtures, look in `@agent-device/test-kit/` (generic) and
`packages/daemon/src/__tests__/support/` (daemon-shaped). Import named builders from their
defining module, never through a barrel. Shared `DeviceInfo`, session, snapshot, store,
runtime-fact, and mocked-binary values belong in a sibling fixture module, not in repeated
test literals. `PROPERTY_RUNS` and the touch-point/rect arbitraries live in
`@agent-device/selectors/snapshot-geometry-fixtures`;
`makeSnapshotState` lives in `@agent-device/capture-kit/snapshot-state-fixtures`.
Before creating fixtures, look in `@agent-device/test-kit` and
Comment thread
thymikee marked this conversation as resolved.
`packages/daemon/src/__tests__/support/`. Shared `DeviceInfo`, session, snapshot, store,
runtime-fact, and mocked-binary values belong in a sibling fixture module, not in repeated test
literals; a fixture one package uses is a `*.fixtures.ts` beside its module. The packages test-kit
builds on (kernel, contracts, capture-kit, host-kit, command-registry, daemon-contracts) cannot
declare it; their tests keep helpers local. Never import test-kit in the `vi.mock` factory of a
module its entry loads (`host-kit/process`, `command`, `file`): spy it in place, as
`pinOwnProcessStartTime` does. Fixtures a package still exports (R83's legacy count) stay
importable until moved.

Use `mkdtempForTest` or `mkdtempForTestSync`. Global setup redirects `TMPDIR` for the run and
removes it after every worker exits — skip per-test cleanup. An interrupted run may leave a
Expand Down Expand Up @@ -109,8 +110,8 @@ For structured classifiers, pair the positive case with the closest negative. Wh
can be identical with and without a typed reason, the negative test must prove the message alone
cannot activate retry, fallback, or recovery.

Test through public interfaces where practical; never add production exports or test-only
dependency injection — a missing seam needs a real product seam.
Test through public interfaces; never add production exports or test-only dependency injection — a
missing seam needs a real product seam.

## Properties, fuzzing, and mutation

Expand All @@ -119,9 +120,7 @@ another example. Keep examples for a real past bug or a named decision. Reuse `P
budgets so property files stay inside the unit slow-test gate.

Parser fuzz targets live in `scripts/fuzz/targets.ts`. Validation generators carry the invalid
outcome they planted, so silent acceptance and wrong error codes are failures. Cases run in a
worker process, so a case that never returns or kills its process is reported as `hang` or `crash`
against the exact input. Promote a discovered case with the command the harness prints — never
outcome they planted, so silent acceptance and wrong error codes are failures. Promote a discovered case with the command the harness prints — never
hand-copy an unshrunk input.

Mutation scope: `scripts/mutation/modules.ts#KERNEL_MODULES` (weekly), `scripts/mutation/run.ts#LANE_SOURCES`
Expand Down
Loading