# Capability Spec Delta: testing (2026-04-27-testing-runner-subpath) **Package**: `@suaveplan/testing` **Status**: PROPOSED ## ADDED Requirements ### Requirement: Central runner subpath The package SHALL expose a `./runner` subpath that re-exports the active test runner's primitives (`describe`, `it`, `test`, `expect`, `expectTypeOf`, `vi`, `beforeAll`/`beforeEach`/`afterAll`/`afterEach`) together with generic mock helpers (`fn`, `spy`, `stub`, `mock`, `fakeClock`, `restoreMocks`, `restoreTimers`) and runner-neutral types (`RunnerMock`, `SpyHandle`). The subpath SHALL resolve to the vitest implementation by default and to `bun:test` under the `bun` package.json condition, so consumers swap runners without changing imports. #### Scenario: vitest path re-exports primitives - **WHEN** a consumer imports `describe`, `it`, `expect`, `vi`, `expectTypeOf` from `@suaveplan/testing/runner` under the default or `vitest` condition - **THEN** the imports resolve to the corresponding vitest exports #### Scenario: bun-test path re-exports primitives with `expectTypeOf` shim - **WHEN** a consumer imports the same surface under the `bun` condition - **THEN** `describe`/`it`/`expect`/`vi` resolve to `bun:test` equivalents and `expectTypeOf` resolves to a Proxy-backed no-op chain whose calls succeed (type assertions are erased at compile time) #### Scenario: generic mock helpers preserve call signature - **WHEN** a test calls `fn<[string], number>()` from the subpath - **THEN** the returned `RunnerMock<[string], number>` is callable as `(arg: string) => number` under both the vitest and bun-test paths **Verified by:** `src/runner/mocks.test.ts::"creates a mock that records calls"` AND `src/runner/runner.spec-conformance.test.ts::"fn<[string], number>() preserves call-signature typing"` AND `src/runner/runner.spec-conformance.test.ts::"BunRunnerMock shape mirrors the vitest path"`