v0.7.0 — token-burn: Impersonation-guard cost — make the classifier explanation a single tool message, not a re-explained skill body
## Problem There are **two** distinct guard layers that can block bro's writes, and the cost of being blocked is amplified because bro re-loads doctrine + memory files on the block event. ### Layer 1 — CC platform: auto-mode classifier Out of plugin's control. The CC harness's auto-mode classifier blocks risky Bash actions including direct sqlite3 writes that bypass the MCP write path (observed 2026-05-17: classifier blocked `sqlite3 UPDATE issues SET objective=...` when bro tried to sync local titles bypassing MCP). The block message is CC's; the plugin cannot compress or restructure it. Bro's response is what we can shape: today bro typically re-reads `feedback_mcp_recovery.md` and `feedback_pr_reviewer_required_pre_push.md` to confirm next steps, adding 2–4 KB of memory body to context. ### Layer 2 — plugin: requireRoles middleware In `mcp/trajectory-server/src/middleware/agent-scope.ts`. The `requireRoles` wrapper rejects MCP tool calls with the wrong `agent` field. The biggest enforcement is `validation_record`: only `agent='pr-reviewer'` is allowed, AND a `subagent_session_id` is required (per `mcp/trajectory-server/src/tools/validation.ts:107`), AND the `feedback` field must start with a load-bearing-safety prefix (`MCP available: yes` or `MCP available: no — honor-system fallback`). When bro tries to write `validation_record` directly, the middleware returns a structured `isError: true` response with a clear `precondition_failed:` message. The block message is already concise. The cost is bro's post-block recovery — usually involving re-reading `tmb_review/SKILL.md` (274 lines) to confirm proper spawn protocol. ## Evidence (verified against live source) - `mcp/trajectory-server/src/tools/validation.ts:96` — `requireRoles('validation_record', ['pr-reviewer'], ...)` - `mcp/trajectory-server/src/tools/validation.ts:107` — explicit error for missing `subagent_session_id` - `mcp/trajectory-server/src/tools/validation.ts:120` — explicit error for missing `MCP available:` prefix - CC auto-mode classifier observed blocking direct sqlite3 write on 2026-05-17 (this very session) — message includes "Permission for this action was denied by the Claude Code auto mode classifier" ## Plan The plugin can't change the CC classifier message. The plan focuses on bro's **post-block recovery cost** — the part we control. 1. **Structured recovery references in `tmb_recovery`**: replace the prose "consult feedback_mcp_recovery.md" with a 5-line decision table inline in the skill so bro doesn't re-Read memory files on block events. 2. **Block-response cache shape**: when `requireRoles` rejects, the error response should include a structured `next_action` field that names the correct tool+invocation pattern (e.g. `{"next_action": "spawn_subagent_pr_reviewer", "doc": "tmb_review §C"}`). Bro reads the field and acts; no body re-fetch needed. 3. **Audit `block_recovery_cost`**: emit an audit event on every middleware block with `content_json: {tool, agent_attempted, additional_reads_in_next_5_turns}` so we can measure whether block-events still trigger doctrine re-reads. 4. **CC auto-mode classifier — document the response pattern** in `skills/tmb_recovery/SKILL.md` so bro knows: classifier-block ≠ retry; classifier-block = re-route via the MCP write path. Should not trigger re-reading `feedback_mcp_recovery.md` — the recovery skill body already covers it. ## Acceptance criteria - L4 simulation: trigger a `requireRoles` block; verify bro recovers with the correct next action in ≤500 added context tokens (no memory-file re-reads). - New `tmb_recovery` skill section: "Block-event recovery" — table form, no narrative prose. - New audit event `block_recovery_cost` shipped; tested in L2. - Bro behavior in L5 dogfood when a block fires: zero new Read calls to feedback memory files within 3 turns of the block. ## Out of scope - Changing the CC platform auto-mode classifier message (not under plugin control). - Relaxing `requireRoles` rules (safety property unchanged). ## Note on source Previous description treated "the auto-mode classifier" as a plugin-side construct that we could compress. Wrong — CC's auto-mode classifier is platform-side. Verified by reading `mcp/trajectory-server/src/middleware/agent-scope.ts` (the plugin-side gate) and noting the CC classifier block-message in this very session. The two layers are now treated distinctly.
issue