feat: add readonly mode with bash safety and spawn child filtering#7
feat: add readonly mode with bash safety and spawn child filtering#7ofriw wants to merge 10 commits into
Conversation
…acklist and git allowlist
…with TUI indicator
…and spawn child filtering
…only when no branch entries exist
…, and TUI warning
…ion, and redirect analysis
…ges, and CLI flag behavior
|
Summary: GH-2’s readonly-mode safety value is aligned, but concrete bash mutation bypasses and a no-UI toggle crash mean the PR should not merge as-is. Business / Product AssessmentVerdict: REQUEST CHANGES Strengths
In Scope Issues
Out of Scope Issues
Technical AssessmentVerdict: REQUEST CHANGES Input Boundary Shape Risk AssessmentStatus: Triggered Strengths
In Scope Issues
Out of Scope Issues
Reusability
review generated with CURe v. 0.7.3 · multi-stage - stages: 4 · sha 6540936 · model gpt-5.5/high · tok 8m/82k/8m · session agenticoding-pi-agenticoding-pr7-20260528-053241-21cc · 16m32s |
Note: This PR was generated by an AI agent. If you'd like to talk with other humans, drop by our Discord!
Readonly Mode — review summary
This PR adds a readonly mode to the extension that blocks
write/edittool calls and destructive bash commands, both for the parent agent and spawned children. It's a safety mechanism — think "guard rails" rather than a security boundary — designed to prevent accidental file mutations during exploratory or debugging sessions. Closes #2.What changed (~1210 lines across 6 files):
readonly-bash.ts(new) — bash classifier using a destructive-command blacklist (rm, mv, sudo, redirects, package managers, editors, etc.) and a three-tier git allowlist that distinguishes immutable (diff/log/status) from mutable (add/commit/push) subcommands, with mixed-command predicates for things likereflog,branch, andstash.index.ts— toggle command (/readonly), keyboard shortcut (ctrl+shift+r, idle-gated), CLI flag (--readonly), runtimetool_callblocking forwrite/edit/destructive-bash, one-shot ON/OFF nudges injected via thecontexthook, and rehydration logic forsession_start/session_tree.state.ts— two new fields (readonlyEnabled,readonlyNudgePending), initialized increateState()and cleared inresetState().tui.ts— 🔒 readonly status indicator on the status bar.spawn/index.ts— child tool filtering (dropswrite/editwhen readonly is active), appends a readonly bash override that rejects destructive commands viaspawnHook, and rewrites child authority wording from "same authority as the parent" to "read-only authority".agenticoding.test.ts— 18 new test blocks covering bash classification, toggle/TUI behavior, tool_call blocking, spawn child filtering, session rehydration, CLI flag override, nudge delivery semantics, shortcut gating, and state reset.Key design decision: rather than the canonical pi pattern of calling
setActiveTools()to removewrite/editfrom the parent's tool list, this uses runtime enforcement via thetool_callevent handler. This keeps the parent's active tool set stable across toggles — avoiding cache invalidation of the parent's tool definitions (whichsetActiveTools()would trigger). The tradeoff is that the LLM may still seewrite/editin its tool list even when they're blocked, but the context nudges compensate by making the LLM aware of the restriction.No breaking changes — readonly mode is opt-in via
/readonly,ctrl+shift+r, or--readonly. Existing behavior is unaffected when disabled. Session persistence usesappendEntryentries on the branch, which cleanly survive/resume,/fork, and/cloneboundaries.Attached is an agent optimized description of the changes in this PR - AGENT_REVIEW.md