Enforcement floor for actions whose blast radius exceeds the project:
write-shaped MCP tools (external_writes) and machine-scoped package
operations (system_installs). Safety mode alone never authorizes them:
the mode’s decision is strengthened to at least this level (severity
order Allow < Auto < Ask < Deny). Default Auto: the intent
classifier vets the call against the user’s request — aligned runs
silently, off-task escalates — even in full_access. allow restores
the old unconditional-allow behavior per knob.
Marker embedded verbatim in every plan-mode policy-denial reason (the
policy gate rewrites the read-only mode-default deny to a plan-flavored one
while a plan is being drafted). Sibling of READ_ONLY_DENIAL_MARKER: the
message-history layer matches "blocked by policy: " + this marker to
neutralize denials once plan mode ends.
Marker embedded verbatim in every read-only policy-denial reason (see
PolicyEngine::decide). Exposed so the message-history layer can detect a
denial that a since-loosened safety mode has superseded, without
re-hardcoding the wording in a second place.
Defense-in-depth pre-check for the execute_command path: callable before
the policy engine to short-circuit obviously destructive commands. Splits the
command into the segments sh -c would run and reports true if any segment
is a destructive operation (contains_destructive_pattern), a raw network
listener / reverse-shell primitive (nc -l, socat …-listen:…), or a remote
download piped straight into a shell (curl … | sh). Tokenized and
segment-aware — not a substring match — so spacing, case, quoting, flag
bundling, and chaining can’t trivially evade it (#114). Over-blocking is the
safe direction; the authoritative boundary is still deny-by-default + the
policy engine, which this mirrors without changing its semantics.
True when command is a build/test invocation plan mode auto-allows even
though it spawns processes: every segment is either read-only or a known
build tool running a known build/test subcommand. Grounding a plan in a
real compile or test run makes plans materially better, and these commands
only write build caches (target/, test artifacts) — not the sources the
plan is about.