| 1 | # Auto mode parity: Codewhale Auto-Review vs Claude Code auto mode vs Kimi Code |
| 2 | |
| 3 | Status: design + gap ledger (2026-08-15). Source of truth for Codewhale |
| 4 | behavior is `docs/MODES.md`, `docs/AUTHORIZATION_ORDER.md`, and the code in |
| 5 | `crates/tui/src/tui/auto_review.rs`, `crates/tui/src/core/engine/reviewer.rs`, |
| 6 | and `crates/tui/src/core/engine/turn_loop.rs`. Statements about the other |
| 7 | two harnesses come from their public documentation as read on 2026-08-15 and |
| 8 | are quoted, not inferred. |
| 9 | |
| 10 | ## What Claude Code does (auto mode) |
| 11 | |
| 12 | From `code.claude.com/docs/en/permission-modes` and `/auto-mode-config`: |
| 13 | |
| 14 | - Modes: `default` (Manual), `acceptEdits`, `plan`, `auto`, `dontAsk`, |
| 15 | `bypassPermissions`. "In auto mode, a second model, the classifier, |
| 16 | reviews actions instead of you." On Pro/Max/Team plans "the built-in |
| 17 | starting mode is auto mode." `Shift+Tab` cycles modes. |
| 18 | - Decision order: "1. Actions matching your allow, ask, or deny rules |
| 19 | resolve immediately… 2. Read-only actions and file edits in your working |
| 20 | directory are auto-approved, except writes to protected paths. 3. |
| 21 | Everything else goes to the classifier… 4. If the classifier blocks, |
| 22 | Claude receives the reason and tries an alternative. In most sessions the |
| 23 | reason is the fixed text `Blocked by classifier`." |
| 24 | - "The classifier sees user messages, tool calls, and your CLAUDE.md |
| 25 | content. Tool results are stripped." |
| 26 | - Explicit `permissions.ask` rules "always force a permission prompt, even |
| 27 | in auto mode"; `permissions.deny` "blocks before the classifier is |
| 28 | consulted." |
| 29 | - Broad allow rules (`Bash(*)`, wildcarded interpreters, `Agent`) are |
| 30 | dropped on entering auto mode; narrow ones carry over; |
| 31 | `autoMode.classifyAllShell` routes every shell command to the classifier. |
| 32 | - Trusted infrastructure and rule overrides are prose in |
| 33 | `autoMode.environment/allow/soft_deny/hard_deny`; `claude auto-mode |
| 34 | defaults|config|critique|reset` inspect them. |
| 35 | - Fallbacks: "A blocked action: Claude Code shows a notification and lists |
| 36 | the action in `/permissions` under the Recently denied tab, where you can |
| 37 | press `r` to retry it with a manual approval." "Repeated blocks: if the |
| 38 | classifier blocks an action 3 times in a row or 20 times total, auto mode |
| 39 | pauses and Claude Code resumes prompting." A mode switch during a pending |
| 40 | check discards a verdict the new mode would not have requested. |
| 41 | - Subagents: the delegated task description is classified before spawn, |
| 42 | each child action is classified with the parent's rules, and the child's |
| 43 | full action history is reviewed on return (a warning is prepended when the |
| 44 | review flags a concern or could not run). Messages sent to another agent |
| 45 | with `SendMessage` are also classified before delivery. |
| 46 | - Boundaries stated in conversation ("don't push") are treated as block |
| 47 | signals but are not stored as rules. |
| 48 | - Terminal UI conventions Hunter pointed at: agent rows show `· 1 queued` |
| 49 | for a follow-up waiting on a busy subagent; the transcript shows `Message |
| 50 | queued for delivery to <agent> at its next tool round.` and `Allowed by |
| 51 | auto mode classifier` under a user message the classifier reviewed; the |
| 52 | footer chain reads `… · esc to interrupt · ← for agents · ↓ to manage`. |
| 53 | |
| 54 | ## What Kimi Code does (0.34.0) |
| 55 | |
| 56 | From `kimi --help` and `moonshotai.github.io/kimi-code` (llms-full): |
| 57 | |
| 58 | - `--yolo` / `/yolo`: "Auto-approve regular tool calls; the agent may still |
| 59 | ask questions." Plan-mode exit approval is not bypassed. |
| 60 | - `--auto` / `/auto`: "fully autonomous, the agent will not ask questions"; |
| 61 | "tool approvals are handled automatically". `--yolo` and `--auto` are |
| 62 | mutually exclusive; `-p` (print mode) uses `auto` by default. |
| 63 | - `/permission` selects a permission mode; "always allow" rules accepted via |
| 64 | `/permission` or an approval dialog propagate to every subagent; the |
| 65 | `Agent` tool itself is allowed by default; each dispatch is presented as an |
| 66 | approval request unless an allow rule or YOLO applies. |
| 67 | - `/tasks` browses background tasks (`TaskList` auto-allowed, `TaskStop` |
| 68 | requires approval); Esc interrupts a turn and preserves partial output. |
| 69 | - Its Auto policy (per `docs/MODES.md`, at the pinned commit) applies deny |
| 70 | rules and then approves; there is no model reviewer. |
| 71 | |
| 72 | ## What Codewhale does today (0.9.8 candidate) |
| 73 | |
| 74 | - Postures (`Shift+Tab`, `/config approval_mode`): **Ask** (`suggest`), |
| 75 | **Auto-Review** (`auto`), **Full Access** (`bypass`), plus `never`. |
| 76 | - Auto-Review = deterministic floor (configured block rules + built-in |
| 77 | safety floor; allows proven-safe calls, hard-blocks publish-like and |
| 78 | destructive background work) → fallback holds go to a one-shot model |
| 79 | guardian (exact call + deterministic observations only; no transcript; |
| 80 | 90 s deadline; high/critical never auto-runs; any failure denies, fail |
| 81 | closed). Repo-law holds that require a person block instead of opening a |
| 82 | hidden modal. Ask rules force prompts in every posture. Full Access |
| 83 | auto-approves non-bypassable registered holds instead of opening a modal. |
| 84 | - Every decision is written to `$CODEWHALE_HOME/audit.log` |
| 85 | (`tool.auto_review` with `gate: deterministic|guardian`). |
| 86 | - Children inherit the parent posture; an explicit Full Access handoff |
| 87 | keeps the child from prompting. |
| 88 | - `Esc` is a cancel stack (footer advertises it while working). |
| 89 | |
| 90 | ## Parity matrix |
| 91 | |
| 92 | | Row | Claude Code auto | Kimi Code auto/yolo | Codewhale Auto-Review | Status | |
| 93 | | --- | --- | --- | --- | --- | |
| 94 | | What runs without asking | reads + working-dir edits by rule; rest via classifier | yolo: regular tool calls; auto: everything, no questions | proven-safe by deterministic floor; fallback holds via guardian | **parity** (different mechanism, same outcome class) | |
| 95 | | What always asks / never auto-runs | explicit `ask` rules; protected paths; org-`ask` connectors; `requiresUserInteraction` MCP | plan-mode exit | ask rules; safety-floor holds needing a person (denied, not hidden); high/critical guardian risk; repo law | **parity** — Codewhale denies rather than prompts in Auto-Review, by design (no hidden modal) | |
| 96 | | Denial UX | notification + `Blocked by classifier` reason to the model; `/permissions` → Recently denied, `r` retries | approval dialog / denial | tool error carries the reason to the model; **now** a one-line transcript receipt | **partial** → transcript receipt added here; recently-denied ledger + retry is a follow-up | |
| 97 | | Decision receipts | `Allowed by auto mode classifier` under classified messages | none documented | audit log only → **now** transcript notes for guardian allow/deny/unavailable, deterministic blocks, and held-without-pausing | **closed in this lane** | |
| 98 | | Allow/deny lists | `permissions.allow/ask/deny` + prose `autoMode.*` | `/permission` always-allow rules | `permissions.toml` ask rules (`/permissions list/remove`), configured block rules, execpolicy | **partial**: prose trusted-infrastructure config is deliberately absent (guardian sees only the exact call); `/permissions` now explains the posture and where receipts go | |
| 99 | | Escalation | classifier reasons; retry via `/permissions` | n/a | guardian returns rationale + "do not work around" | **parity** | |
| 100 | | Sandbox | sandbox network requests classified per host/port | n/a | sandbox modes incl. `external-sandbox`; DSH-grounded contract | **deliberately different** (sandbox is a separate layer, not the reviewer's job) | |
| 101 | | Interrupt | `esc to interrupt` in footer | Esc interrupts | `Esc` cancel stack; footer `Esc to interrupt` (now localized) | **parity** | |
| 102 | | Queued messages to a busy child | `· 1 queued`, delivery receipt, message classified | n/a | owned by the subagent-focus lane (`work/v098-agent-focus-20260815`) | **in progress (other lane)** | |
| 103 | | Subagent visibility / manage | agent rows, `← for agents · ↓ to manage`, `/tasks` | `/tasks` | `/fleet workers` (`/subagents`), work bar; rail + hints owned by the focus lane | **partial (other lane)** | |
| 104 | | Auto pause after repeated blocks | 3 in a row / 20 total pauses auto mode | n/a | none | **missing** — follow-up (see plan) | |
| 105 | | Child task classified before spawn / reviewed on return | yes | dispatch shown as approval | child inherits posture; no return review | **missing** — follow-up | |
| 106 | | Conversation boundaries as block signals | yes (not durable) | n/a | guardian never sees the transcript by design | **deliberately different** (durable rules only) | |
| 107 | |
| 108 | ## Changes landed in this lane |
| 109 | |
| 110 | - `Event::ToolGateDecision` (engine → hosts) with `ToolGate`, |
| 111 | `ToolGateVerdict`, and `bounded_gate_reason` (control/bidi stripped, |
| 112 | ≤220 chars). Emitted for guardian Allow/Deny/Unavailable and deterministic |
| 113 | Blocks. Proven-safe deterministic allows stay silent, like rule-based |
| 114 | auto-approvals elsewhere. |
| 115 | - TUI: `crates/tui/src/tui/gate_receipts.rs` renders one localized line per |
| 116 | decision (`Auto-Review allowed '<tool>' (<risk> risk, model guardian): |
| 117 | <reason>` / `… denied …` / `… could not review … denied, fail closed` / |
| 118 | `… blocked … (deterministic policy)`). Receipts are held until the tool's |
| 119 | card completes so they land under the card (a mid-run insert splits the |
| 120 | tool run); leftovers flush at turn end. The Auto-Review "held without |
| 121 | pausing" case is now a localized transcript note as well as a status. |
| 122 | - `/permissions` output ends with the active posture and what it decides |
| 123 | alone vs never, plus the audit-log path. |
| 124 | - Footer `Esc to interrupt` is localized (`FooterHintEscInterrupt`). |
| 125 | - 12 new `MessageId`s translated in all 15 shipped locale packs. |
| 126 | |
| 127 | ## Follow-up plan (not in this lane) |
| 128 | |
| 129 | 1. **Recently-denied ledger + retry**: keep the last N `ToolGateDecision` |
| 130 | denials per session; `/permissions denied` lists them; a retry action |
| 131 | re-issues the exact call under Ask (a person decides). Safety argument: |
| 132 | retry never bypasses the deterministic floor or repo law; it only converts |
| 133 | a guardian/hold denial into a visible prompt. |
| 134 | 2. **Auto-Review pause after repeated denials** (3 in a row / 20 total, like |
| 135 | Claude Code): switch the session to Ask with a status receipt; resuming is |
| 136 | explicit. Thresholds constant, not configurable, until measured. |
| 137 | 3. **Child dispatch review**: run the deterministic floor over an `agent` |
| 138 | task description before spawn (publish-like/destructive intent → hold), |
| 139 | and append the child's gate receipts to its return summary. No new |
| 140 | classifier: reuse the guardian with the same exact-call contract. |
| 141 | 4. **Message-to-child review**: when the focus lane lands follow-ups to a |
| 142 | busy child, route them through the same guardian only if they contain |
| 143 | tool-shaped instructions; otherwise deliver. |
| 144 |