Cadora · design spec
Everything needed to render or extend the control plane — the exact tokens, the five tools with their signatures and fail-modes, the tool-call trace's anatomy, the security-posture callout, and every return and error state. The rendered components are live HTML; edit them here or lift the specs into Figma.
Semantic first · green proceeds, red is the closed guard, amber degrades soft
--scr-green · #16c784started · approved · safe read--scr-red · #fb7185fail-closed · refused · 401--scr-amber · #ffd08apending · fail-soft error--scr-blue · #6ba5f0tool names · keys · paths--scr-bg · #0f172aCard ground--scr-canvas · #111c2fInset · state cards--scr-panel2 · #162237Callout surface--scr-line · #334158Borders--scr-text · #f5f7fbPrimary · run id · values--scr-muted · #9aa8bcLabels · captions · JSON structureMonospace is the instrument voice — the control plane is read as calls and JSON
| Role | Family | Size / weight | Notes |
|---|---|---|---|
| Tool name | mono | 12px / blue | start_run, review_gate — the callable surface |
| Signature | mono | 12px / 400 | Args + defaults, e.g. review_timeout=3600.0 |
| Returned JSON | mono | 11.5px | Keys blue, strings green, literals amber, braces muted |
| Error string | mono | red / amber | error: path '…' escapes the run workspace |
| Endpoint | mono | blue | http://127.0.0.1:8000/mcp |
| Metric | Value | Metric | Value |
|---|---|---|---|
| Card radius | 10px | Semantic accent | 4px left border |
| Trace line-height | 1.65 | Return indent | 20px |
| Card padding | 14px 16px | State padding | 11px 13px |
| Default transport | stdio | Default bind | 127.0.0.1 |
The whole control plane · each tool, its signature, its return, its fail-mode
| Tool | Signature | Returns | Fail-mode |
|---|---|---|---|
| start_run | (topology, run_id, cwd=".", executor="claude", archive_dir="runs", gate_cmd="ruff check . && pytest -q", gate_setup="auto", review_timeout=3600.0) | {run_id, status:"started"} | fail-closed timeout |
| review_gate | (run_id) | {pending, node_id, docs_dir, artifacts} · else {pending:false, running} | read-only |
| submit_review | (run_id, decision, comments="") | {submitted:decision} · else {error} | fail-soft |
| get_artifact | (run_id, path) | <text> · else "error: …" | traversal-safe |
| run_status | (run_id) | {running, result_path, error} | read-only |
Two tools drive the run (start_run, run_status), one reads its output (get_artifact), two service the human gate (review_gate, submit_review). decision is one of approve · request_changes · abort. Pass review_timeout=0 to wait indefinitely.
One round trip: start, watch, read the gate, decide, finish
The same audit guarantees, exposed over MCP
The callout is one component: an amber-flagged header over four .post rows, each with a semantic mark — green a guarantee that holds, red a guard that closes, amber a soft degrade. Auth logic lives in cadora/mcp/auth.py; the review and traversal guards in cadora/mcp/server.py.
Every return and error the tools produce
start_run · run launched
review_gate · gate pending
review_gate · nothing pending
submit_review · accepted
submit_review · fail-soft (bad input)
submit_review · nothing pending
get_artifact · traversal refused
get_artifact · missing file
run_status · finished
HTTP · missing / wrong bearer token
The tools never raise through the call. Every failure is a value: submit_review and review_gate/run_status return an {error} dict; get_artifact returns a string that begins error:. An unknown run_id yields unknown run '…' on any tool. Auth is the one boundary that answers before the tool runs — a 401 at the HTTP layer.
stdio local · http remote · loopback until you prove auth
| Flag | Default | Effect |
|---|---|---|
| --transport | stdio | stdio for a local client (Claude Desktop / Code, Codex CLI); http for remote — endpoint http://<host>:<port>/mcp. |
| --host | 127.0.0.1 | Bind host for HTTP. Loopback by default; a non-loopback host is refused unless authenticated or acknowledged. |
| --port | 8000 | Bind port for HTTP. |
| --auth-token | none | Requires Authorization: Bearer <token> on every HTTP request (or set CADORA_MCP_TOKEN); a present token also lifts the non-loopback refusal. Still front it with TLS. |
| --i-understand-no-auth | off | Allow binding this unauthenticated surface to a non-loopback host. The explicit escape hatch — trusted networks only. |
The control plane returns evidence, not exceptions
| Do | Not |
|---|---|
| Return the error as a value — {"error": "no review is pending"} | Raise a traceback through the tool call |
| Name the refusal — path '…' escapes the run workspace | “Access denied” |
| State the decision set — approve | request_changes | abort | “yes / no” |
| Fail closed by default — timeout aborts; 0 is the opt-out | Wait forever silently |