docs/help/testing.md was 79,946 characters and mixed how-to, reference, contributor conventions, and roadmap content in one page. It is now a short index over six pages, one per reader job: - help/testing/suites: quick start, the suite reference, which suite to run, the live-test pointer, docs sanity, and offline regressions. - help/testing/live-workflows: live provider debugging through the Docker and Parallels lanes. - help/testing/docker: the Docker "works in Linux" runners, their weighted scheduler, the lane catalog, and their env vars. - help/testing/qa-runners: the qa-lab command surface, the shared Convex credential contract, and adding a channel to QA. - help/testing/contracts: plugin and channel contract tests. - help/testing/writing-tests: temp-directory rules, the agent reliability eval gaps, and how to add a regression. Anchor strategy: per-anchor routes are impossible because redirectSource() rejects any source containing [?#]. Instead every one of the 49 ids the old page published stays alive on the index as an authored <a id="..." /> stub in "Where each section moved". Ids were computed with parseDocsDocument, not a slug approximation, so punctuated headings keep both emitted forms (for example docker-runners-(optional-%22works-in-linux%22-checks) and docker-runners-optional-works-in-linux-checks). The index still publishes `related` itself, so that id is deliberately not stubbed and no duplicate authored/canonical ID is raised. Losslessness, asserted mechanically rather than by eye: all 14 original section bodies are character-identical after the move (0 lost, 0 changed), and the page lede is byte-identical. Word count 9,632 -> 9,632, code fences 18 -> 18, links 13 -> 13, table rows 0 -> 0. All 751 inline code spans and fenced blocks compare as an identical set, so every command in the guide is unchanged. The only body delta is six trailing newlines removed by scripts/format-docs.mts. Verified independently of docs-link-audit, which a split makes uninformative because it rewrites the repo's own links: the 49 pre-split ids were enumerated from HEAD, the post-split index and every child were re-parsed, and each id was asserted to resolve. 0 unresolved, 0 stub targets that miss their child, 0 collisions. Prose findings are deliberately left alone and deferred: r3-0398, r3-0399, r3-0400, r3-0401, r3-1686, r3-1687, r3-1688, r3-1689, r3-1690. Closes audit findings: r3-0397
3.4 KiB
| summary | title | read_when | |
|---|---|---|---|
| Plugin and channel contract test commands, categories, and when to run them | Contract tests |
|
Contract tests (plugin and channel shape)
Contract tests verify that every registered plugin and channel conforms to
its interface contract. They iterate over all discovered plugins and run a
suite of shape and behavior assertions. The default pnpm test unit lane
intentionally skips these shared seam and smoke files; run the contract
commands explicitly when you touch shared channel or provider surfaces.
Commands
- All contracts:
pnpm test:contracts - Channel contracts only:
pnpm test:contracts:channels - Provider contracts only:
pnpm test:contracts:plugins
Channel contracts
Located in src/channels/plugins/contracts/*.contract.test.ts. Current
top-level categories:
- channel-catalog - bundled/registry channel catalog entry metadata
- plugin (registry-backed, sharded) - basic plugin registration shape
- surfaces-only (registry-backed, sharded) - per-surface shape checks for
actions,setup,status,outbound,messaging,threading,directory, andgateway - session-binding (registry-backed) - session binding behavior
- outbound-payload - message payload structure and normalization
- group-policy (fallback) - default group policy enforcement per channel
- threading (registry-backed, sharded) - thread id handling
- directory (registry-backed, sharded) - directory/roster API
- registry and plugins-core.* - channel plugin registry, loader, and config-write authorization internals
Inbound dispatch-capture and outbound-payload harness helpers used by these
suites are exposed internally through src/plugin-sdk/channel-contract-testing.ts
(npm-excluded, not a public SDK subpath); there is no standalone
inbound.contract.test.ts file in this directory.
Provider contracts
Located in src/plugins/contracts/*.contract.test.ts. Current categories
include:
- shape - plugin manifest, API, and runtime export shape
- plugin-registration (+ parallel) - manifest registration cases
- package-manifest - package manifest requirements
- loader - plugin loader setup/teardown behavior
- registry - plugin contract registry contents and lookup
- providers - shared provider behavior across bundled providers, plus web-search providers
- auth-choice - auth choice metadata and setup behavior
- provider-catalog-deprecation - deprecated provider catalog metadata
- wizard.choice-resolution, wizard.model-picker, wizard.setup-options - provider setup wizard contracts
- embedding-provider, memory-embedding-provider, web-fetch-provider, tts - capability-specific provider contracts
- session-actions, session-attachments, session-entry-projection - plugin-owned session state contracts
- scheduled-turns - plugin scheduled turn metadata and timestamp bounds
- host-hooks, run-context-lifecycle, runtime-import-side-effects, runtime-seams - plugin host/runtime lifecycle and import-boundary contracts
- extension-runtime-dependencies - runtime dependency placement for extensions
When to run
- After changing plugin-sdk exports or subpaths
- After adding or modifying a channel or provider plugin
- After refactoring plugin registration or discovery
Contract tests run in CI and do not require real API keys.