Adapter Contract
Purpose #
Quick-reference excerpt of the Adapter interface, the manifest shape, the watchdog stop conditions, and per-method conformance levels. The authoritative document is .docs/docs/specs/adapter-contract.md; this page links and summarises.
The interface #
import type {
AdapterManifest, ProjectContext, EmittedFile, ShellCommand,
SkillTemplate, MCPDef, RoleName, InstalledMCP, SyncPlan, DoctorCheck,
} from '@aidokit/core';
export interface Adapter {
readonly manifest: AdapterManifest;
emitAgentRulesFile(ctx: ProjectContext): EmittedFile;
emitEngineConfig(ctx: ProjectContext): EmittedFile[];
emitVerbs(ctx: ProjectContext): EmittedFile[];
emitRoles(ctx: ProjectContext): EmittedFile[];
emitSkills(ctx: ProjectContext, skills: SkillTemplate[]): EmittedFile[];
emitWatchdog(ctx: ProjectContext): EmittedFile[];
emitOutputStyles(ctx: ProjectContext): EmittedFile[];
installMCP(mcp: MCPDef, roles: RoleName[], ctx: ProjectContext): ShellCommand[];
removeMCP(mcpId: string, ctx: ProjectContext): ShellCommand[];
listInstalledMCPs(ctx: ProjectContext): Promise<InstalledMCP[]>;
postInstall(ctx: ProjectContext): ShellCommand[];
preSync(ctx: ProjectContext): SyncPlan;
doctor(ctx: ProjectContext): Promise<DoctorCheck[]>;
}
Adapters are stateless const objects (no classes — see ADR-0005 Implementation notes).
The manifest #
export interface AdapterManifest {
name: string; // kebab-case
cliTarget: string; // "Claude Code >=2.1.32"
specVersion: '2.0';
sdkVersion: string; // semver range
conformance: 'minimum' | 'standard' | 'strict';
capabilityDeclarations: CapabilityDeclarations; // writesPaths, runsShellCommands, networkCalls
capabilities?: Capabilities; // v1.0 hardening fields
gaps?: string[]; // free-form documented gaps
}
At-rest form is adapter.md with YAML frontmatter. The Adapter contract's §8 documents the full layout, reconciled with @aidokit/core schemas per ADR-0012.
Method specifications (one-liners) #
| Method | Purpose | Conformance MIN / STD / STR |
|---|---|---|
emitAgentRulesFile |
One EmittedFile — CLAUDE.md / AGENTS.md equivalent |
MUST / MUST / MUST |
emitEngineConfig |
Engine-dir config files (e.g. .claude/settings.json) |
MUST / MUST / MUST |
emitVerbs |
intake, implement-task, orchestrator-next |
MUST / MUST / MUST |
emitRoles (6) |
Six required roles | MUST / MUST / MUST |
emitRoles (7th) |
frontend-browser-tester |
MAY / SHOULD / MUST |
emitSkills |
Format SkillTemplate[] into CLI's native skill mechanism |
MUST / MUST / MUST |
emitWatchdog |
Stop-condition enforcement | MUST / MUST / MUST |
emitOutputStyles |
Output-style files (test reports, change summaries, …) | MAY / SHOULD / MUST |
installMCP |
Returns ShellCommand[] to register an MCP |
SHOULD / MUST / MUST |
removeMCP |
Returns commands to unregister; idempotent | SHOULD / MUST / MUST |
listInstalledMCPs |
Enumerate installed MCPs | SHOULD / MUST / MUST |
postInstall |
Commands after all writes (chmod, bd init, .gitignore) |
MUST / MUST / MUST |
preSync |
Compute SyncPlan before any writes |
SHOULD / MUST / MUST |
doctor |
Health-check results; runs all, no short-circuit | SHOULD / MUST / MUST |
Full per-method MUST/SHOULD/MAY breakdown in .docs/docs/specs/adapter-contract.md §7. Conformance check ids in conformance-reference.md.
Watchdog stop conditions #
From .docs/docs/specs/adapter-contract.md §10:
| Condition | Default threshold | Outcome |
|---|---|---|
| Same test fails repeatedly | 3 consecutive failures | Block further test runs; blocker |
| Same shell command fails repeatedly | 5 consecutive failures | Block further; blocker |
| Same file edited too many times | 5 edits in one task | Warn; require override |
| Repair attempts exceed cap | 2 attempts | Stop; blocker |
| Stage exceeds timeout | Configurable per stage | Stop; blocker |
| Out-of-scope file write attempted | Always | Block |
| Version bump without approval | Always | Block |
| Tracked-file deletion without approval | Always | Block |
Blocker output goes to agent-artifacts/blockers/blocker-<id>.md.
Capability profiles #
Three profiles, mapped per adapter (adapter-contract §9):
| Profile | Roles | Claude Code mapping | Codex mapping |
|---|---|---|---|
read-only |
Researcher, Architect, Planner, Tester-Reviewer | permissionMode: plan |
sandbox: read-only + approval_policy: untrusted |
docs-only-write |
Maintainer (optional) | permissionMode: default + validate-docs-only.mjs PreToolUse |
sandbox: workspace-write + role-prompt discipline |
scope-limited-write |
Builder, Maintainer (typical), Frontend-Browser-Tester | permissionMode: default + validate-scope.mjs PreToolUse |
sandbox: workspace-write + per-edit approval |
Enforcement strength must be honestly disclosed in manifest.gaps. Marketing prompt-level as hook-level is a conformance violation.
Supporting types (one-liners) #
EmittedFile—{ path, content, mode? }; path relative, no.., mode0o755for executables.ShellCommand—{ command, args?, cwd?, env?, description? }.SkillTemplate—{ id, name, source, sourcePackId?, content, autoLoadTriggers, preloadedBy, required, description?, allowedTools? }.RoleName— 7-value union: researcher, architect, planner, builder, tester-reviewer, maintainer, frontend-browser-tester.SyncPlan—{ entries: readonly SyncFileEntry[] }where each entry isidentical | template-updated | user-modified | removed-in-template | new-in-template.DoctorCheck—{ id, label, severity: 'pass' | 'warn' | 'fail', message, hint? }.CapabilityProfile—'read-only' | 'docs-only-write' | 'scope-limited-write'.
Worked example #
The full MinimalAdapter example lives at .docs/docs/specs/adapter-contract.md §12. Note: the example predates the ADR-0012 reconciliation and still shows draft-only fields — treat its structure as illustrative; the authoritative field set is §6/§8.
For a real implementation, read packages/adapter-claude-code/src/ end-to-end.