Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions personas/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,27 @@ JSON ones — enough to break pattern-based `permission.task` rules without a
warning. The same ordering means the blocks below override `opencode.json`; if
you centralize permissions there, strip them.

**Declare only what differs from the baseline.** A frontmatter `permission:`
key replaces the corresponding block in `opencode.json` rather than merging
into it. A config with a real deny-list there — `~/.ssh/**`, `*secrets*`,
`rm -rf *`, `sudo *` — loses it for any agent whose frontmatter says
`edit: allow` or `bash: allow`. So the router and the executor declare nothing
but `task:`, and inherit every restriction the JSON already imposes. Override a
key only to tighten it.

**`task: deny` on both subagents.** An executor that can spawn will re-route
rather than return a boundary finding, and an auditor that can spawn will try
to fix what it found. Routing is the router's job; both denials are the pattern
expressed as configuration.

**The auditor's bash patterns.** `"*": ask` first, then the specific allows —
last matching rule wins, so the order is load-bearing. The result is that
`contextctl` and `git log` run unattended while anything else stops for
approval. Note what this does *not* buy: `bash` is a write vector regardless,
**The auditor's bash patterns.** `"*": deny` first, then the specific allows —
last matching rule wins, so the order is load-bearing. `contextctl` and
`git log` run unattended; nothing else runs at all. Deny rather than ask,
because this block replaces the JSON `bash` rules and a catch-all `ask` would
downgrade every hard deny there to a prompt. The auditor's command set is
known, so denying the rest costs nothing.

Note what this does *not* buy: `bash` is a write vector wherever it is allowed,
so the auditor's read-only property rests on `edit: deny` plus its prompt.
Same rule as the pattern itself — coordination, not authorization.

Expand Down
2 changes: 1 addition & 1 deletion personas/context-auditor.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ permission:
edit: deny
task: deny
bash:
"*": ask
"*": deny
"contextctl *": allow
"go run *contextctl.go *": allow
"git log *": allow
Expand Down
2 changes: 0 additions & 2 deletions personas/context-executor.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ description: >-
mode: subagent
temperature: 0.1
permission:
edit: allow
bash: allow
task: deny
---

Expand Down
2 changes: 0 additions & 2 deletions personas/context-router.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ description: >-
mode: primary
temperature: 0.1
permission:
edit: allow
bash: allow
task: allow
---

Expand Down