|
| 1 | +# Coven runtime contract |
| 2 | + |
| 3 | +`coven-code` is a registered *runtime* in the |
| 4 | +[OpenCoven/coven-runtimes](https://github.com/OpenCoven/coven-runtimes) |
| 5 | +canonical registry: an agent CLI the Coven daemon can drive without any |
| 6 | +daemon-core edits. The contract is declared in |
| 7 | +[`spec/runtime-manifest/coven-code.json`](../spec/runtime-manifest/coven-code.json) |
| 8 | +and conformance-tested on every CI run. |
| 9 | + |
| 10 | +## Flag → manifest mapping |
| 11 | + |
| 12 | +| Manifest field | CLI surface | Notes | |
| 13 | +| --- | --- | --- | |
| 14 | +| `non_interactive_prompt_prefix_args: ["--print"]` | `coven-code --print <prompt>` | One-shot run, response on stdout. | |
| 15 | +| `interactive_prompt_prefix_args: []` | `coven-code` | A positional prompt switches to print mode, so interactive launches must not append one. | |
| 16 | +| `model_flag: "--model"` | `--model <id>` | | |
| 17 | +| `system_prompt_flag: "--append-system-prompt"` | `--append-system-prompt <text>` | Identity preamble; does not clobber the built-in system prompt. | |
| 18 | +| `sandbox.flag: "--permission-mode"` | `--permission-mode bypass-permissions` (full) / `--permission-mode plan` (read-only) | | |
| 19 | +| `capabilities.stream` + `stream_args.prefix_args` | `--print --input-format stream-json --output-format stream-json` | Long-lived stream mode (below). | |
| 20 | +| `stream_args.session_id_flag: "--session-id"` | `--session-id <uuid>` | Pre-assigns the session id at launch. Creating only — reusing an existing id starts a fresh transcript file under that id. | |
| 21 | +| `stream_args.resume_flag: "--resume"` | `--resume <id>` | Continues a persisted session in place. | |
| 22 | +| `capabilities.think` | `--thinking <TOKENS>` | Extended-thinking budget. | |
| 23 | +| `capabilities.speed` | `--effort <LEVEL>` | `low`, `medium`, `high`, `max`. | |
| 24 | + |
| 25 | +## Stream mode |
| 26 | + |
| 27 | +Implemented in `src-rust/crates/cli/src/stream_mode.rs`. With |
| 28 | +`--print --input-format stream-json --output-format stream-json` the process |
| 29 | +stays alive across chat turns: |
| 30 | + |
| 31 | +- **stdin** — one JSON frame per line. A |
| 32 | + `{"type":"user","message":{"role":"user","content":...}}` frame (content as |
| 33 | + a string or an array of `{"type":"text","text":...}` blocks) triggers a |
| 34 | + turn; `assistant` frames append as prefill; the legacy |
| 35 | + `{"role":...,"content":"..."}` shape is also accepted. The positional |
| 36 | + prompt argument is ignored in this mode, matching Claude Code. |
| 37 | +- **stdout** — strictly JSONL: one `system`/`init` frame at startup, then per |
| 38 | + turn `assistant` frames (tool-use and final text), `tool_result` frames, |
| 39 | + and a closing `result` frame (`subtype`, `duration_ms`, `is_error`, |
| 40 | + `num_turns`, `session_id`). Logs and warnings go to stderr, never stdout. |
| 41 | +- **exit** — stdin EOF ends the chat; per-turn model errors are reported in |
| 42 | + `result` frames and do not kill the process. |
| 43 | + |
| 44 | +The transcript is persisted after every turn, so a later relaunch with |
| 45 | +`--resume <session-id>` continues the conversation. |
| 46 | + |
| 47 | +## Stability guarantee |
| 48 | + |
| 49 | +Registry versions are immutable. The flags named in the manifest — |
| 50 | +`--print`, `--input-format`, `--output-format`, `--session-id`, `--resume`, |
| 51 | +`--model`, `--append-system-prompt`, `--permission-mode` (and its |
| 52 | +`bypass-permissions`/`plan` values), `--thinking`, `--effort` — are contract |
| 53 | +surface. The `runtime_manifest_*` tests in `crates/cli/src/main.rs` re-parse |
| 54 | +the manifest against the real clap definition on every test run; if one |
| 55 | +fails, either fix the flag regression or publish a new manifest version: |
| 56 | + |
| 57 | +1. Add the change to `spec/runtime-manifest/coven-code.json` and bump its |
| 58 | + `version`. |
| 59 | +2. Re-validate: `conjure validate spec/runtime-manifest/coven-code.json` and |
| 60 | + `conjure test` against a built binary (`conjure` lives in coven-runtimes). |
| 61 | +3. Re-accept in coven-runtimes: `conjure registry add` + PR (the old version |
| 62 | + stays resolvable for pinned consumers). |
| 63 | + |
| 64 | +Never edit the shipped definition of an accepted version in place. |
| 65 | + |
| 66 | +## Consuming the registry |
| 67 | + |
| 68 | +`coven-code` also consumes the canonical registry (pinned git dependency on |
| 69 | +`coven-runtime-spec` / `coven-runtime-registry`): |
| 70 | + |
| 71 | +- `/coven runtimes [--json]` — accepted runtimes, capabilities, and local |
| 72 | + install status (with install hints for missing binaries). |
| 73 | +- `/coven run <harness> <prompt>` — validates the harness id against the |
| 74 | + registry and local adapters before shelling out. |
| 75 | +- `/coven adapter doctor` — additionally validates |
| 76 | + `$COVEN_HOME/adapters/*.json` against the shared manifest spec. |
| 77 | + |
| 78 | +Bumping the pinned rev in `src-rust/Cargo.toml` is how newly accepted |
| 79 | +runtimes are adopted. |
0 commit comments