feat(pi): provision the pi permission-guard extension (pi permission parity) - #171
Open
alex-mextner wants to merge 4 commits into
Open
feat(pi): provision the pi permission-guard extension (pi permission parity)#171alex-mextner wants to merge 4 commits into
alex-mextner wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ca1dc0c4ab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
alex-mextner
force-pushed
the
feat/pi-permission-guard
branch
from
July 18, 2026 11:39
6de9602 to
ff99905
Compare
alex-mextner
added a commit
that referenced
this pull request
Jul 18, 2026
… overrides Two review findings on the pi permission-guard extension: 1. permissions.kind schema/wizard/JSON-schema choices were missing 'pi' even though the validator and planner already accepted/provisioned it — only hand-editing rig.yaml could enable the path. Added to riglib/schema.py, riglib/config_schema.py, and regenerated schema/rig.schema.json. 2. _build_pi_extension always built the baked default policy, ignoring the cascaded permissions.deny/ask overrides — a user declaring deny: [] / ask: [] (the established 'empty replaces the baseline' convention) silently kept getting the full baseline reconciled. Honor an explicit empty override per role; a populated override is in claude-code's rule-string dialect (which doesn't translate to pi's structured rule dicts) so it's dropped with a visible plan note instead of silently diverging from the declared config. Also note when the allowlist-only keys (tools/extra/disable/allow) are set for pi, which has no additive allowlist. Addresses review findings on PR #171.
alex-mextner
force-pushed
the
feat/pi-permission-guard
branch
from
July 18, 2026 14:42
ff99905 to
294167e
Compare
…parity)
pi ships no built-in permission system — it runs bash with the user's own
privileges. The agent-tools `permission-guard` pi extension delivers deny/ask on
the bash tool, but only if rig installs it and writes the policy it reads. This is
the rig half of pi permission parity.
- catalog: discover `pi-extensions/<name>/` (requires an index.ts entry).
- plan: for `permissions.kind: pi` (or a pi harness), emit a `provision_pi_extension`
action carrying the extension carrier, the install dir, the policy file path, and
the resolved policy document (the same deny/ask baseline claude-code encodes, in
the extension's flag-anywhere dialect): deny raw PR merges, force pushes, hook
bypass commits, root file removal, screencapture; ask before broad process kills
and hard resets.
- runner: `_do_provision_pi_extension` copies the extension into pi's extensions dir
and writes the rig-owned policy JSON — idempotent (skip-if-identical), backup-on-
conflict, error surfaced over backup.
- drift: `_check_pi_extension` reports missing/modified for both artifacts.
- permissions: pi is no longer an N/A skip — `harness_permission_extension("pi")`
+ `pi_policy_document()` (deep-copied baseline). config.validate accepts
`permissions.kind: pi`.
- harness_skills: add `pi_agent_dir()`/`pi_user_path()` (honor PI_CODING_AGENT_DIR)
and FIX pi's global instruction path (`~/.pi/agent/AGENTS.md`, not `~/.config/pi`).
Cross-repo: the extension lives in agent-tools PR #294
(alex-mextner/agent-tools#294); this PR is the rig
provisioning half and depends on that extension being in the agent-tools catalog.
Closes #170
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When both the extension dir and the policy file conflict, ActionResult carries one structured backup slot but neither restore path is lost — both appear in the result detail. Adds the missing double-conflict coverage (review follow-up). Closes #170 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… overrides Two review findings on the pi permission-guard extension: 1. permissions.kind schema/wizard/JSON-schema choices were missing 'pi' even though the validator and planner already accepted/provisioned it — only hand-editing rig.yaml could enable the path. Added to riglib/schema.py, riglib/config_schema.py, and regenerated schema/rig.schema.json. 2. _build_pi_extension always built the baked default policy, ignoring the cascaded permissions.deny/ask overrides — a user declaring deny: [] / ask: [] (the established 'empty replaces the baseline' convention) silently kept getting the full baseline reconciled. Honor an explicit empty override per role; a populated override is in claude-code's rule-string dialect (which doesn't translate to pi's structured rule dicts) so it's dropped with a visible plan note instead of silently diverging from the declared config. Also note when the allowlist-only keys (tools/extra/disable/allow) are set for pi, which has no additive allowlist. Addresses review findings on PR #171.
alex-mextner
force-pushed
the
feat/pi-permission-guard
branch
from
July 22, 2026 16:24
db993e9 to
144a178
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Provisions the pi
permission-guardextension so pi-harness repos get the same deny-dangerous / ask-risky command belt the other harnesses get. pi ships no built-in permission system (it runs bash with the user's own privileges); its extension API can intercept the bash tool pre-execution, which is the sanctioned parity mechanism.This is the rig half. The extension itself lives in agent-tools:
➡️ Cross-repo dependency: alex-mextner/agent-tools#294 (the
permission-guardextension). This PR installs that extension into pi's extensions dir and writes the policy it reads; it needs the extension present in the agent-tools catalog. Do not merge before #294.The engine path (one engine, two front-ends — unchanged)
riglib/catalog.py): discoverspi-extensions/<name>/(requires anindex.tsentry) → categorypi_extensions.riglib/plan.py): forpermissions.kind: pi(or a pi harness), emits aprovision_pi_extensionaction carrying the extension carrier, the install dir, the policy-file path, and the resolved policy document (baseline in the extension's flag-anywhere dialect: deny raw PR merges / force pushes / hook-bypass commits / root file removal / screencapture; ask before broad process kills and hard resets).riglib/actions/runner.py):_do_provision_pi_extensioncopies the extension into pi'sextensions/dir and writes the rig-owned policy JSON — idempotent (skip-if-identical), backup-on-conflict,errorsurfaced overbacked_up.riglib/drift.py):_check_pi_extensionreports missing/modified for both the extension dir and the policy file.riglib/permissions.py): pi is no longer an N/A skip —harness_permission_extension("pi")+pi_policy_document()(deep-copied baseline).config.validatenow acceptspermissions.kind: pi.riglib/harness_skills.py): addspi_agent_dir()/pi_user_path()(honorPI_CODING_AGENT_DIR) and fixes pi's global instruction path (~/.pi/agent/AGENTS.md, not the wrong~/.config/pi/AGENTS.md).Proof it works end-to-end in real pi
tests/test_pi_extension.py), full suite1933 passed(only the pre-existing toleratedtest_tmux_e2e_gatingflake fails).RIG_AGENT_TOOLS_SOURCE=… bash tests/smoke.sh --fastgreen (full real-catalog dry-run, zero unknown items).provision_pi_extensioninstalled the extension + policy into a tempPI_CODING_AGENT_DIR; pi (driven by a deterministic faux provider) auto-discovered the extension and blockedgit push --forcewithisError:trueand the exact deny reason — the side-effect marker (only created if the command executes) was absent. Fail-closed (missing/malformed policy → baked baseline blocks) and ask-non-interactive→block also verified live.Not included
Does not merge. Off-scope matcher limitations (shell-wrapper / substitution / leading-redirect obfuscation) are documented in the extension README on #294 and remain the domain of the deeper argv-level agent-hooks.
🤖 Generated with Claude Code