12vectors / bench docs for 0.4-alpha
bench docs GitHub ↗
ReferenceThe adapter contract

The adapter contract

What you implement to put a different coding agent behind the board. Two executables, three launch intents, and one event schema; the shipped claude/ and opencode/ adapters are both of these read side by side.

An adapter is a directory with two executables:

run — execute one headless job to completion

Launch intents (AGENT_MODE)

Core signals intent; every adapter maps it to its vendor's permission mechanism. Headless runs have no human at a permission prompt, so anything not auto-approved is denied — grant each intent exactly the side effects its prompt demands, and never a blanket allow-everything (the worktree is isolated, the shell is not):

The project's allowed commands (AGENT_COMMANDS)

The git/gh grants above are universal; which test/check commands a project's agents run is project knowledge. It arrives as comma-separated plain command prefixesBOARD_AGENT_COMMANDS in local/.env, e.g. python3 -m unittest,npm test — never in any vendor's rule syntax. Each adapter renders them natively; both shipped rule languages are prefix-pattern based, so the translation is mechanical:

The model (AGENT_MODEL) — optional

Absent = the vendor's own default: launch without any model argument and let your CLI resolve it however it normally would. When set, it is an opaque vendor-native model name — a claude alias, an opencode provider/model-id — that core never validates or interprets; pass it through untranslated (claude → --model "$AGENT_MODEL", opencode → the generated config's model key). Never send your vendor an empty value: the board only sets the variable when a model is actually configured (BOARD_AGENT_MODEL and its per-intent overrides in local/.env).

wire — wire live-session visibility into the host project

Called by install.py with the project root as argv[1] (plus --dry-run). Idempotently make the project's own interactive sessions report events — however your platform allows (Claude Code: hooks in .claude/settings.json; opencode: a plugin shim in .opencode/plugin/ subscribing to its event bus). Print a report; exit 0 on ok/fixed. If the platform has no way to observe sessions, be a no-op with an honest message: the board still runs headless jobs via run, you just lose the live play-by-play.

Events — the normalized schema (v1)

POST to http://127.0.0.1:$BOARD_PORT/api/events:

{"v": 1, "session": str, "kind": str, "summary": str,
 "file"?: str, "cmd"?: str, "detail"?: str, "ok"?: bool,
 "running"?: bool, "agent"?: $BOARD_AGENT_ID, "task"?: $BOARD_TASK}

kinds: session end idle edit read search command test check git plan subagent web other. running: true marks an in-flight action (shown as the live line, not appended to the timeline); follow it with the completed event. kind: idle = finished responding; kind: end = session over. Classification happens in YOUR emitter — core never sees vendor payloads.