Adapter Conformance Kit
Adapter Conformance Kit
The public Adapter Conformance Kit lets an adapter author run the same Contract v1 checks used by the project without a provider account, token, network connection, or real user configuration. It accepts a validated descriptor or an instance factory with explicit public metadata.
Public import
Import the kit from the package entry point; do not deep-import files below
skills/:
import {
ADAPTER_CONTRACT_VERSION,
defineAdapter,
runAdapterConformance,
assertAdapterConformance,
} from '@hogancv/coordinate-agents/adapter-sdk.mjs';
The package and Plugin versions are independent from both
ADAPTER_CONTRACT_VERSION and ADAPTER_CONFORMANCE_KIT_VERSION.
For a complete external module, offline executable, and explicit registration walkthrough, see the External Adapter Author Guide and the minimal external Adapter example.
Run the kit
The runner creates a temporary repository and a deterministic Node.js fake executable. The fixture path intentionally contains spaces and shell metacharacters. Launch plans are executed only when their command, prefix, and cwd point at that generated fixture; an arbitrary command is rejected before spawn.
The three repository-owned adapters expose the same descriptors and are checked
by the same runner: CODEX_CLI_ADAPTER_DESCRIPTOR,
ANTIGRAVITY_CLI_ADAPTER_DESCRIPTOR, and GENERIC_CLI_ADAPTER_DESCRIPTOR.
Built-in IDs are reserved, so maintainer conformance calls opt into
allowReserved: true; third-party adapters must use a new ID.
const descriptor = defineAdapter({
contractVersion: ADAPTER_CONTRACT_VERSION,
id: 'example-cli',
capabilities: {
detection: true,
configuration: true,
oneShotLaunch: true,
persistentSession: true,
},
create(config) {
const fixture = config.conformanceFixture;
return new ExampleAdapter({ ...config, command: fixture.command });
},
});
const report = runAdapterConformance(descriptor, {
// The callback receives the generated, isolated fixture. The runner also
// injects it as config.conformanceFixture for the adapter factory.
config: fixture => ({ vendorMode: 'fixture', command: fixture.command }),
});
if (!report.ok) {
for (const diagnostic of report.diagnostics) console.error(diagnostic);
process.exitCode = 1;
}
For CI code that should fail immediately, use assertAdapterConformance();
it throws AdapterConformanceError with the bounded report attached as
error.report. A factory function can be passed directly when id and
capabilities are supplied in the options:
const report = assertAdapterConformance(createExampleAdapter, {
id: 'example-cli',
capabilities: {
detection: true,
configuration: true,
oneShotLaunch: true,
persistentSession: true,
},
config: fixture => ({ command: fixture.command }),
});
The config option may be an object or a function receiving this immutable
fixture description:
{
root, // temporary repository containing spaces and shell metacharacters
command, // process.execPath
script, // deterministic fake executable script
prefix, // [script]
marker,
prompt,
repository, // true; an isolated Git repository is initialized at root
}
The runner adds conformanceFixture to the factory configuration and does not
mutate the caller’s object. registeredIds may be supplied to exercise
duplicate-identity rejection. execute: false performs contract and launch
shape checks without spawning; the default is to execute both declared launch
plans against the fake process. Temporary roots are removed in a finally
path. For local debugging or custom harnesses, callers may use
createConformanceFixture() directly and must call its cleanup() method.
The built-in registry creates its three adapters through their validated
Contract v1 descriptors. Runtime code reads the frozen descriptor capabilities
when it chooses persistent-session behavior; the legacy capabilities() method
remains available for compatibility metadata.
Explicit trusted-local modules
An adapter module can be added only through an explicit local path supplied by
the user or an already persisted adapters entry:
npx @hogancv/coordinate-agents adapter register "C:\\path\\to\\adapter.mjs" --json
npx @hogancv/coordinate-agents adapter list --json
npx @hogancv/coordinate-agents adapter remove "C:\\path\\to\\adapter.mjs" --json
Registration accepts only an existing regular .mjs, .js, or .cjs file
whose path contains no symlink, junction, or hard link. The module is imported
from that exact canonical path, its single exported Contract v1 descriptor is
validated against the built-in and already registered IDs, and only then is
the user configuration updated. A failed registration leaves both the user
configuration and project .agent-bus unchanged. There is no directory scan,
URL/import-specifier loading, download, registry lookup, or automatic npm
installation. The module is trusted local JavaScript and runs with the current
Node.js process permissions; Contract validation is not a JavaScript sandbox.
What is proved
The report contains bounded checks, failures, diagnostics, and structured
observations for:
- Contract v1 descriptor, identity, reserved/duplicate IDs, and capabilities;
- detection and configuration compatibility results;
- one-shot and persistent-session launch result shapes;
- launch policy and optional runtime capability facts;
- deterministic fake-process execution and persistent initial-prompt delivery;
- malformed or unsafe launch plans, with zero spawn for pre-spawn rejection.
Failures use canonical Contract v1 codes where applicable, including
INVALID_ADAPTER_CONFIG and UNSUPPORTED_CAPABILITY. Conformance-specific
codes include UNSAFE_LAUNCH, PROCESS_FAILED, and
INITIAL_INPUT_MISMATCH. Diagnostic messages are bounded and redact common
secret forms; raw process output and temporary absolute paths are not placed in
the report.
The kit validates behavior and launch-plan safety at its boundary. It is not a JavaScript sandbox: a local adapter module is trusted code executed by the current Node.js process. The kit does not scan directories, import URLs, download packages, install dependencies, access a live provider, or edit a user’s configuration.
Repository acceptance gate
The repository gate runs the built-in descriptors and the bundled external example through this same public kit, then exercises the complete external setup, Task dispatch, persistent Session reuse, input/output, close, and trusted-local cleanup path. The ordinary regression suite also protects the Task, Agent Bus, Event Journal, Inspector, MCP, review, executable-precedence, and release-authorization boundaries.
Run the local gate from a clean checkout:
npm ci
npm run check
npm run demo
npm pack --dry-run
The authoritative matrix is defined in
.github/workflows/adapter-sdk-acceptance.yml and runs these checks on
Windows, macOS, and Linux with Node.js 18 and Node.js 22. Local results prove
only the current host; the matrix workflow is the cross-platform evidence. Automatic pull-request
and main runs are limited to package.json changes and proceed only when its version differs
from the base revision. Version tags and explicit manual dispatches remain available for release
and maintenance verification.