Context
Observed during v0.3.2 dogfood: bro tried to update `pr_target` and `protected_branches` via direct `config_set` MCP calls to make a hook stop blocking a PR creation. CC's auto-mode classifier flagged it as "silently weakening a security guard" and bro paused to ask Human approval.
That's the right OUTCOME — but the path was wrong. Bro shouldn't have attempted direct `config_set` on policy keys in the first place.
The doctrine
`plugin_config` keys split into two classes:
Workflow keys — bro can write directly via `config_set` (no Human approval):
- `branch_id_proposal_prefix`
- (any future per-task workflow tuning)
Policy keys — bro must route through `tmb_reonboard` skill (Human-approved via AskUserQuestion):
- `branching_model`
- `pr_target`
- `protected_branches`
The policy-key set defines what `git-guards.sh` and `git-push-guard.sh` enforce. Mutating these keys without explicit Human approval is the same class of error as SWE rewriting `.git/HEAD` to bypass a hook — different surface, same shape.
Why this matters
Currently `config_set` is gated by `requireRoles(['bro'])` only — once you ARE bro, you can write any key. The doctrine of "don't bypass hooks" doesn't extend to "don't change the configs hooks read." That's an asymmetry.
Without this fix, bro could (and tried to) silently flip a project from single-tier to dual-tier branching to make a blocked PR succeed. The Human never sees that the policy changed.
Fix scope
Option A — Skill-level discipline (simplest, ship in v0.4.1)
Update `CLAUDE.md` and `skills/tmb_planning-simple/SKILL.md` + `tmb_planning-difficult/SKILL.md` with an explicit clause:
Never call `config_set` directly for policy keys (`branching_model`, `pr_target`, `protected_branches`). For policy changes, invoke the `tmb_reonboard` skill so the Human approves each key via AskUserQuestion radio. Calling `config_set` directly on these keys silently weakens the security gates that `git-guards.sh` reads — same bypass class as rewriting `.git/HEAD`.
Option B — MCP-level enforcement (harder, deferrable)
Server-side: `config_set` for policy keys requires an extra arg `from_skill='tmb_reonboard'`. Other callers get `forbidden`.
- Pro: hard wire-level enforcement
- Con: MCP doesn't currently see the calling skill name; would need plumbing
- Defer to v0.5.x or beyond unless we observe the skill-level discipline failing
Acceptance
Origin
Filed by @ZaxShen during v0.3.2 dogfood after CC's auto-mode classifier caught bro mid-bypass-attempt and forced an approval prompt. The classifier saved us; the doctrine should ALSO have saved us before bro ever made the call.
Context
Observed during v0.3.2 dogfood: bro tried to update `pr_target` and `protected_branches` via direct `config_set` MCP calls to make a hook stop blocking a PR creation. CC's auto-mode classifier flagged it as "silently weakening a security guard" and bro paused to ask Human approval.
That's the right OUTCOME — but the path was wrong. Bro shouldn't have attempted direct `config_set` on policy keys in the first place.
The doctrine
`plugin_config` keys split into two classes:
Workflow keys — bro can write directly via `config_set` (no Human approval):
Policy keys — bro must route through `tmb_reonboard` skill (Human-approved via AskUserQuestion):
The policy-key set defines what `git-guards.sh` and `git-push-guard.sh` enforce. Mutating these keys without explicit Human approval is the same class of error as SWE rewriting `.git/HEAD` to bypass a hook — different surface, same shape.
Why this matters
Currently `config_set` is gated by `requireRoles(['bro'])` only — once you ARE bro, you can write any key. The doctrine of "don't bypass hooks" doesn't extend to "don't change the configs hooks read." That's an asymmetry.
Without this fix, bro could (and tried to) silently flip a project from single-tier to dual-tier branching to make a blocked PR succeed. The Human never sees that the policy changed.
Fix scope
Option A — Skill-level discipline (simplest, ship in v0.4.1)
Update `CLAUDE.md` and `skills/tmb_planning-simple/SKILL.md` + `tmb_planning-difficult/SKILL.md` with an explicit clause:
Option B — MCP-level enforcement (harder, deferrable)
Server-side: `config_set` for policy keys requires an extra arg `from_skill='tmb_reonboard'`. Other callers get `forbidden`.
Acceptance
Origin
Filed by @ZaxShen during v0.3.2 dogfood after CC's auto-mode classifier caught bro mid-bypass-attempt and forced an approval prompt. The classifier saved us; the doctrine should ALSO have saved us before bro ever made the call.