The reliable harness
The harness is Okami's engine: a ReAct loop with reliability invariants. It doesn't trust the model's prose — it decides on state and observable effects. This is wh…
The state machine
Every task runs through explicit states. It never stays IN_PROGRESS forever: max_steps (default 24), a wall-clock and the stall detector guarantee termination.
PENDING ─► IN_PROGRESS ─► COMPLETE (exitCriteria verified)
├─► BLOCKED (structured reason)
├─► NEEDS_INPUT (missing a fact from you)
└─► FAILED (budget exceeded)Action-or-Terminate
Every turn ends in a tool-call OR a terminal signal (task_complete · task_blocked · need_input). Future-tense text (“I'll”, “let me”) with no action is caught by an intent–action reconciler (PT/EN), rejected and re-prompted: “you said you'd do X but didn't act — do it now or declare blocked.” There's no infinite “thinking”.
Verified exitCriteria
task_complete only counts if the criteria pass mechanically. If the model declares completion but a criterion fails, the harness emits complete_rejected with the exact list of what's missing — and the agent resumes.
| criterion | verifies |
|---|---|
| file_exists:<path> | the file exists in the workspace |
| file_contains:<path>:<txt> | the file exists AND contains the text |
| shell_ok:<cmd> | the command exits 0 (e.g. pytest -q) |
| ui_gate | the design-contract gate passes (§ Skills) |
Anti-loop
A weak model loves repeating the same tool and oscillating between two states. The harness breaks that without relying on the model to “notice”:
- Fingerprint + dedup — each call hashes (tool + normalized args); repeated N times → blocked with a nudge.
- Cycle detection — A,B,A,B / A,B,C,A,B,C patterns in the recent window → break.
- Circuit breaker — the same command failing N times with the same error → that approach is forbidden.
- Progress budget — lots of effect, zero progress against the exitCriteria → break.
- Hard ceilings —
max_stepsper task + per-tool cap. - Escalation ladder — nudge → re-decompose → escalate to a stronger model (
--escalate) →BLOCKEDwith a diagnosis.
Anti-hallucination
- Mandatory grounding — a claim about the code must be backed by a real observation (read-before-edit). The tool result is the truth, not the model's memory.
- Existence check for a symbol/import/package before using it (anti-slopsquatting).
- Abstention is first-class — “I don't know / need to check” is cheaper than guessing.
- Gates as a filter — build/typecheck catch a hallucinated API/import on the spot.
Dual-mode (LLM parity)
capability.tool_mode defines how the model emits actions:
params json_text mode Action as a ``json`` block in the text — works on any model. json_constrained mode Forces valid JSON via grammar/response_format (local/weak) — a malformed tool-call stops being fatal. native mode The provider's native tool-calling (strong); the transport converts it back to the action protocol.
Checkpoints & rollback
Every write records the prior state in an append-only journal with lock + chained HMAC — tampering with or inserting an entry breaks the chain, and rollback ignores the forged entry. okami rollback N undoes the last N writes.
Budget and auto-compaction
There's a per-turn step/token ceiling. When context fills (~72% of the model's window), old turns become summary nodes and durable facts are promoted to long-term memory — compacting is promote + point, never forget.
Turn events
The harness emits an event stream (consumed by the CLI, the TUI and the event log). Each shows up live in okami task/chat:
| event | means |
|---|---|
| start · step | task started · each tool-call with ✓/✗ |
| violation | a turn with no action (empty future tense) → rejected |
| loop | repetition/cycle detected |
| escalate | escalating to a stronger model |
| compact | auto-compaction (n facts → memory) |
| complete_rejected | completion denied: an exitCriterion was missing |

