
Security News
GPT-6 Astra Attempts Supply Chain Attacks Against Open Source Maintainers in Testing
GPT-6 Astra hits 100% on ExploitBench and finds zero-days autonomously, while independent tests reveal scope violations and monitoring gaps.
@ramarivera/pi-model-guardrails
Advanced tools
Deterministic destructive-command guard + inviolable-constraint policy engine and deviation state machine for the Pi coding agent
A safety extension for the Pi coding agent. It does two things:
rm -rf ~, git reset --hard, kubectl delete --all, docker compose down -v, …) before they run.The deterministic guard is the hard floor: it cannot be downgraded by config or talked around by the model. The policy + grader layers sit on top to catch the softer "the model is drifting off the rails" failure mode that pattern rules alone can't see.
Every bash tool call flows through one pipeline:
command
│
▼
┌──────────────────────────────────────────────────────────┐
│ 1. Engine (deterministic) │
│ normalize → candidate packs → regex match │
│ + Tier-3 indirection resolution (x=rm; $x -rf ~) │
│ → strictest decision wins │
└──────────────────────────────────────────────────────────┘
│ EngineDecision (allow / warn / deny + severity)
▼
┌──────────────────────────────────────────────────────────┐
│ 2. Policy engine │
│ Critical / inviolable floor (config CANNOT downgrade) │
│ > per-rule override > allowlist > defaultMode > engine │
└──────────────────────────────────────────────────────────┘
│ Verdict
▼
┌──────────────────────────────────────────────────────────┐
│ 3. Deviation state machine │
│ COMPLIANT → WATCH → GATED → RECOVERING → HALTED │
└──────────────────────────────────────────────────────────┘
│ if armed & call looks clean → "gate-required"
▼
┌──────────────────────────────────────────────────────────┐
│ 4. LLM grader (only while armed) │
│ grades the call vs the active constraints + recent │
│ actions; a clean grade advances recovery, a dirty │
│ grade holds the gate. Fails TOWARD the gate. │
└──────────────────────────────────────────────────────────┘
In a clean (COMPLIANT) session the grader never runs — calls are adjudicated by the deterministic engine alone, with effectively zero overhead. The grader only wakes up once the session is armed.
| State | Meaning |
|---|---|
COMPLIANT | Normal. Deterministic guard only; no grading. |
WATCH | A soft signal fired. Mutating calls start getting graded. |
GATED | A deviation is confirmed. Every call is graded before it runs. |
RECOVERING | The model is producing clean graded calls; counting consecutive clean calls toward recovery. |
HALTED | An inviolable / critical constraint was hit. Terminal for the model — no tool call can clear it. |
Properties that hold by construction:
stateEpoch defends against a fork "resetting" an armed session.HALTEDHALTED is deliberately terminal for the model: an inviolable-constraint breach cannot be cleared by any tool call, graded or not. The escape hatch is a human:
/guardrails-clear-halt
A human types this slash command in the Pi TUI. It shows what was violated and requires an interactive y/n confirmation before clearing the halt back to COMPLIANT. It is gated on an interactive UI (it refuses to clear blind in RPC/print mode), and the model cannot reach it — slash commands originate in the human input editor, never in the model's tool-call stream.
The regex packs match on literal command text, so one level of shell indirection can hide a sink:
x=rm; $x -rf ~ # variable indirection
alias d=rm; d -rf ~ # alias expansion
The engine resolves these structurally (a bounded, quote-aware pure-TS pass) and re-runs the same rules on the expansion, so an aliased rm -rf is caught by the very rule that catches a bare rm -rf. It is fail-open to the regex engine — on any parsing surprise it simply defers, so it can only add detection, never remove the baseline. Interprocedural function-wrapper dataflow and eval/base64 decoding are out of scope by design.
This is the "native structural analysis" layer, implemented in pure TS rather than via
@ast-grep/napi: ast-grep's napi binding has no built-in Bash grammar, and a per-platform native grammar binary that can fail to load is the wrong dependency for a guard that must always load.
Config is layered: a global file is merged with a per-project file (project wins). Both are optional — with no config you get the deterministic guard with sensible defaults.
~/.pi/agent/guardrails.json (or $PI_CODING_AGENT_DIR/guardrails.json, or $PI_MODEL_GUARDRAILS_CONFIG)<cwd>/.pi/guardrails.json (JSONC — comments allowed){
// Pin which constraints can NEVER be downgraded by config or allowlist.
"policy": {
"defaultMode": "warn", // deny | warn | log | allow
"inviolable": ["no-history-rewrite"],
"rules": { // override a specific engine rule's mode ("<pack.id>:<rule-name>")
"core.git:reset-hard": "deny"
},
"constraints": [
{
"id": "no-history-rewrite",
"title": "Never rewrite shared git history",
"statement": "Do not force-push or hard-reset shared branches.",
"severity": "inviolable", // inviolable | critical | high | medium | low
"allowlistable": false,
"appliesWhen": "branch is shared",
"requiredBehavior": "Ask the human to rebase locally instead.",
"detect": { "ruleIds": ["core.git:reset-hard"], "regex": "push\\s+--force" }
}
],
"allowlist": [
// ttl is an ABSOLUTE expiry as a Unix epoch in MILLISECONDS (the entry is
// inert once Date.now() >= ttl); omit it for no expiry.
{ "rule": "core.filesystem:rm-rf-general", "reason": "scratch dir cleanup", "ttl": 1893456000000, "paths": ["/tmp/build"] }
]
},
// The degraded-mode grader. Defaults shown; secrets come from env, never inline.
"grader": {
"enabled": true,
"model": "gemini-3.5-flash",
"fallbackModel": null,
"apiKeyEnv": "GEMINI_API_KEY", // read process.env[...] — do NOT inline keys
"baseUrlEnv": null,
"timeoutMs": 8000,
"maxTokens": 512,
"maxRetries": 1,
"temperature": 0.1,
"cache": true
},
// Deviation state-machine tuning (defaults are sensible).
"machine": {
"watchCleanStreak": 2,
"gatedCleanStreak": 3,
"recoveringWatermark": 1,
"cooldownTurns": 2,
"haltRequiresHumanAck": true
},
// Optional model gating + telemetry.
"modelWhitelist": [],
"modelBlacklist": [],
"observability": { "enabled": true, "logFile": ".pi/model-guardrails/events.jsonl" }
}
Notes:
apiKeyEnv / baseUrlEnv name environment variables; the key/URL are read from process.env at load. Never put a secret in the file.allowlistable: false on a constraint forbids ever allowlisting around it. Wildcard allowlist entries require riskAcknowledged: true.pi install npm:@ramarivera/pi-model-guardrails
| Path | Responsibility |
|---|---|
src/engine/ | Deterministic DCG-port engine: normalize, matcher, evaluate, rm-parser, indirection, registry, packs/* |
src/policy/ | Inviolable-constraint policy engine (resolvePolicy) |
src/state/ | Deviation state machine (transition, clearHalt) |
src/grade.ts | LLM grader: prompt, timeout, retry, cache, fail-toward-gate |
src/guard.ts | Pure composition: engine → policy → state machine |
src/extension.ts | Pi wiring: event handlers, state persistence, steering injection, /guardrails-clear-halt |
src/config.ts | Layered JSONC config loader |
This checkout is live-enabled for Pi through .pi/extensions/model-guardrails/index.ts, which imports src/index.ts → src/extension.ts. Tests, the package entrypoint, and manual Pi runs all load the same symbol, so behavior does not drift.
npm install
npm run check # biome + tsc
npm test # unit suite
npm run test:e2e # loads through the live .pi shim
npm run pack:dry-run
Publishing uses GitHub Actions trusted publishing (.github/workflows/publish.yml); no NPM_TOKEN required. Configure npm trusted publishing for ramarivera/pi-model-guardrails before the first publish.
The deterministic rule engine is a faithful native-TS port of destructive_command_guard by Jeffrey Emanuel. The policy engine, deviation state machine, LLM grading gate, and Tier-3 indirection resolver are additions specific to this extension.
FAQs
Deterministic destructive-command guard + inviolable-constraint policy engine and deviation state machine for the Pi coding agent
The npm package @ramarivera/pi-model-guardrails receives a total of 3 weekly downloads. As such, @ramarivera/pi-model-guardrails popularity was classified as not popular.
We found that @ramarivera/pi-model-guardrails demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
GPT-6 Astra hits 100% on ExploitBench and finds zero-days autonomously, while independent tests reveal scope violations and monitoring gaps.

Product
Socket can now send alerts and supply chain attack notifications to Microsoft Teams, with filters that route the right updates to each channel.

Security News
pnpm 12 rewrites the package manager in Rust, cutting install times by up to 90% while preserving pnpm 11 workflows and lockfiles.