Skip to content

Commit fbb7cad

Browse files
BunsDevCopilot
andcommitted
feat: finish coven-runtimes integration (docs, dep pin, stderr logging)
- Route tracing logs to stderr so stream-json stdout stays JSONL-only (a stray WARN line was corrupting the runtime frame stream). - Bump coven-runtime-spec/registry pin to 27f656a (v0.1.2, latest accepted registry set). - Add docs/coven-runtimes.md: flag-to-manifest contract table, stream protocol description, and the manifest version-bump process. - Link the runtime contract from the README highlights. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 087f044 commit fbb7cad

5 files changed

Lines changed: 90 additions & 6 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Recent highlights:
2424
- **/share** — share sessions via unlisted GitHub Gists `[EXPERIMENTAL]`
2525
- **/goal**`/goal <objective>` keeps the agent working across multiple turns `[EXPERIMENTAL]`
2626
- **/coven** — drive the local [Coven daemon](https://github.com/OpenCoven/coven) (sessions, harness runs, rituals) without leaving the TUI. `/coven` is the unified replacement for `coven-cli`'s interactive menu and the legacy `coven-tui` slash shell; when `coven-code` is on `PATH`, `coven` and `coven tui` exec into it automatically (opt out with `COVEN_LEGACY_TUI=1`). Run `/coven help` for the subcommand list.
27+
- **Coven runtime**`coven-code` is a registered runtime in the [coven-runtimes](https://github.com/OpenCoven/coven-runtimes) canonical registry, with a long-lived stream-json mode the daemon can drive (`--print --input-format stream-json --output-format stream-json`). `/coven runtimes` lists the accepted runtimes and their local install status. See [docs/coven-runtimes.md](docs/coven-runtimes.md).
2728

2829
---
2930

docs/coven-runtimes.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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.

src-rust/Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-rust/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ tokio-tungstenite = { version = "0.24", features = ["native-tls-vendored"] }
100100
schemars = { version = "0.8", features = ["derive"] }
101101

102102
# Runtime registry
103-
coven-runtime-spec = { git = "https://github.com/OpenCoven/coven-runtimes", rev = "9af3e4cf2fe66e95aa1a3addc867524822ea28ab" }
104-
coven-runtime-registry = { git = "https://github.com/OpenCoven/coven-runtimes", rev = "9af3e4cf2fe66e95aa1a3addc867524822ea28ab" }
103+
coven-runtime-spec = { git = "https://github.com/OpenCoven/coven-runtimes", rev = "27f656a531f00e201cf9b82cafc6c00c4d548144" }
104+
coven-runtime-registry = { git = "https://github.com/OpenCoven/coven-runtimes", rev = "27f656a531f00e201cf9b82cafc6c00c4d548144" }
105105

106106
# Workspace crates
107107
claurst-core = { path = "crates/core" }

src-rust/crates/cli/src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,10 @@ async fn main() -> anyhow::Result<()> {
507507
.with_env_filter(log_filter)
508508
.with_target(false)
509509
.without_time()
510+
// Logs go to stderr: stdout belongs to the response — plain text in
511+
// --print mode, and strictly JSONL in the stream-json runtime protocol
512+
// (a stray WARN line on stdout would corrupt the frame stream).
513+
.with_writer(std::io::stderr)
510514
.init();
511515

512516
// --context loads a coven-github session brief (headless contract v1). It

0 commit comments

Comments
 (0)