omp packages

pi-permission-review1.0.0

Review recently denied tool calls in pi, allow one, remember it, or write a real policy rule — then retry the call.

leourbina Published 8 days ago MIT ~391 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

pi-permission-review

CI npm

/permissions — review recently denied tool calls in pi, allow one, remember it, or write a real policy rule, then retry the call.

The gap this fills: @gotgenes/pi-permission-system logs every denial, but nothing reads that log back to you. With verdicts: "allow-deny" a refusal is silent — no dialog, no trace in the transcript. This extension turns those refusals into a list you can act on.

Install

pi install npm:@gotgenes/pi-permission-system   # the gate (required)
pi install npm:pi-permission-review             # this extension

Then, in ~/.pi/agent/extensions/pi-permission-system/config.json, put the review link first in the chain:

{
  "authorizerChain": ["review-approvals", "permission-judge"],
  "verdicts": "allow-deny"
}

Order matters: the review link must be consulted before the judge, or a judge denial lands before an approval can allow it.

verdicts must be "allow-deny" or "allow-deny-defer" for denials to happen at all. With "allow-defer" refusals become prompts, and with "yoloMode": true every ask is approved before the chain runs — this extension then has nothing to show.

Restart pi or run /reload.

Use

Run something the gate refuses, then /permissions.

Key Action
↑ ↓ / j k move
tab / ⇧tab Denied · Remembered · Session
enter / a approve + retry, this session only
r remember in approvals.json + retry
w write a policy rule, reload, then retry
d delete a remembered approval
e edit a remembered pattern
ctrl+o expand the wrapped command
esc close

Acting on a row removes it: the Denied tab is a queue of outstanding refusals, not a log. If the retry is refused again, the new denial appears as a fresh row.

Unavailable actions are dimmed rather than hidden: on a policy denial, a and r cannot work, because no chain link can lift a rule.

How it works

Two mechanisms, because the gate has two kinds of refusal:

resolution Surfaces Undo
authorizer_denied bash, mcp, skill, … the link named review-approvals allows it
policy_deny, user_denied path, external_directory, any rule match a rule is written to the policy config, then ctx.reload()

A rule write cannot be applied before the reload, and the retry must survive the reload, so the retry is parked in pending-retry.json and consumed on the next session_start.

Denials are collected from the permissions:decision broadcast, not from the review log: the log is shared by every pi session on the machine and carries no session id on denial entries, so it cannot tell whose refusals those are. The broadcast fires on this session's own bus.

State

Kept in ~/.pi/agent/permission-review/ (respects PI_CODING_AGENT_DIR), never inside the package:

File Purpose
approvals.json remembered calls and patterns, with scope and sessionId
denials.json this session's denial feed, so /reload does not empty the panel
pending-retry.json one-shot retry that survives a reload

Every approval appends permissions-review.approved to the gate's own review log, and every use of an approval appends permissions-review.allowed, so there is one chronological trail of who allowed what.

Guardrails

  • never writes yoloMode, never broadens the policy to "*": "allow"
  • remembered bash patterns are limited to the exact command, or one leading word plus *
  • filesystem rules are only ever the exact path, never a glob
  • an unreadable or corrupt store is treated as empty: no crash, no accidental allow

Limitations

  • Review is per session. Refusals from other pi sessions are never listed.
  • Reviewer probability scores are not shown: the gate records them only for deferred asks.
  • Subagent child sessions are separate nodes and register their own link; a remembered approval still covers them, since the store is read from disk.
  • The panel needs interactive TUI mode.

Releases

Versions are cut by release-please. Commit to main with Conventional Commits — feat:, fix:, docs:, refactor: — and release-please opens a release PR that bumps package.json, rewrites CHANGELOG.md, and tags the commit when merged. The tag triggers a publish job that runs node scripts/check-manifest.mjs and then npm publish --provenance.

CI on every push and PR runs the same manifest check plus npm pack --dry-run, which catches a manifest pi would refuse to load before it reaches the registry.

Publishing needs an NPM_TOKEN repository secret (an npm automation token). Provenance uses the workflow's id-token: write permission, which is already set.

Uninstall

pi remove npm:pi-permission-review
# then set "authorizerChain": ["permission-judge"]
rm -rf ~/.pi/agent/permission-review

License

MIT