Skip to content

feat(automode): count operator form answers as user decisions in Claude Code auto mode#46

Merged
obeone merged 3 commits into
mainfrom
feat/automode-operator-rule
Jun 24, 2026
Merged

feat(automode): count operator form answers as user decisions in Claude Code auto mode#46
obeone merged 3 commits into
mainfrom
feat/automode-operator-rule

Conversation

@obeone

@obeone obeone commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Summary

Caucus routes a resolved operator form back into the room as a message stamped origin=operator (the hub sets that flag, peers cannot forge it). To the supervising human it is an explicit decision, but Claude Code auto mode only trusts the human typing in the session, so by default it does not count an operator answer as a user decision. This bridges that gap, cleanly and without depending on the automode-config skill.

What it adds:

  • caucus.automode: detects whether the operator-answer allow rule is installed (pure file read, no subprocess), and installs it atomically into .claude/settings.local.json (backup, 0600, $defaults preserved).
  • setup() now returns an automode block (operator_rule: present | missing | unknown) so the agent can propose installing the rule. The block is gated on CLAUDECODE, so non-Claude hosts (Codex, Gemini, ...) get no irrelevant noise.
  • New caucus-setup-automode console script: --apply installs the rule and runs claude auto-mode critique (a first-class Claude Code command) as the gate, keeping a human in the loop.

The rule itself is deliberately narrow. The classifier only sees rendered message text and cannot verify the origin flag, so the rule authorizes a single low or medium severity soft_deny action, never high-severity actions, and never lifts a hard_deny boundary. This scope was hardened directly in response to the claude auto-mode critique gate flagging the unbounded first draft as a prompt-injection surface.

Test plan

  • pytest: 487 passing, including 12 new cases (detection across local/user scopes, idempotent install, $defaults splice, backup, malformed JSON, host gating, CLI).
  • ruff + mypy strict: clean.
  • Drove the real app: caucus-setup-automode end to end (check, apply, re-check) with the real claude auto-mode critique gate, hub GET /protocol, bridge boot, and a real MCP stdio client calling setup() (the automode block appears under CLAUDECODE=1 and is absent without it).

obeone added 3 commits June 24, 2026 23:59
…de auto mode

Caucus routes a resolved operator form back as a message stamped
origin=operator (server-set, peers cannot forge it), but Claude Code auto
mode only trusts the human in the session, so it does not count that answer
as a user decision. Add a caucus.automode module that detects whether the
allow rule is installed and installs it atomically into
.claude/settings.local.json, then runs claude auto-mode critique as the
gate. setup() surfaces an automode block, gated on CLAUDECODE so non-Claude
hosts get no noise. Expose the caucus-setup-automode console script.

The rule scope is deliberately narrow (single low/medium soft_deny action,
never high-severity or hard_deny) because the classifier sees only text and
cannot verify the origin flag.
@obeone obeone merged commit bcde1a3 into main Jun 24, 2026
6 checks passed
@obeone obeone deleted the feat/automode-operator-rule branch June 24, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant