Overview
When the admission gate returns a blocking or rejected decision, the watcher can apply file and runtime side effects. The exact behavior depends on the target type and on gateway.watcher.*.take_action.
Quarantine mechanics
For skills and plugins, quarantine copies the artifact into the configured quarantine directory and removes the original path:
| Target | Quarantine path |
|---|---|
| Skill | quarantine_dir/skills/NAME |
| Plugin | quarantine_dir/plugins/NAME |
The Go enforcers use copy-then-remove, not an atomic rename. If copy succeeds but removal fails, the code returns the quarantine destination along with the removal error.
For MCPs, enforcement edits the OpenShell policy through MCPEnforcer: blocked endpoints are added to denied_endpoints, allowed endpoints are moved to allowed_endpoints, and a running OpenShell process gets policy reload.
Restore
defenseclaw skill restore example-skill
defenseclaw plugin restore example-plugin --path ~/.defenseclaw/plugins/example-plugin
restore uses the source path recorded in the policy/action store unless --path is supplied. The Python CLI clears the quarantine state after a successful restore.
Block and allow state
List state is managed by the existing CLI commands:
defenseclaw skill block example-skill --reason "policy violation"
defenseclaw skill allow example-skill --reason "reviewed exception"
defenseclaw plugin block example-plugin --reason "policy violation"
defenseclaw mcp block https://mcp.example.com/sse --reason "policy violation"
These commands are the supported operator overrides. There are no --force or --reason flags on skill restore; use --path only when the recorded source path is missing or intentionally overridden.