Permissions as contract clauses, not machine settings.
PlutoGate is an orchestrator with a memory gate for AI agents: it turns a goal into
verifiable task contracts (a PIANO.md file), and submits every agent action to
approval against that contract, default-deny, with an audit trail. An action the
contract does not foresee writes nothing.
Developers use AI everywhere and trust it less every year: 66% cite "almost right,
but not quite" output as their #1 frustration, and 76% won't delegate deployment to
AI at all (Stack Overflow Developer Survey 2025). Existing tools, observability,
evaluation; watch and judge after the action happens. PlutoGate puts the gate before:
same contract + same action → same verdict, on any machine, with any model.
The verdict is a function of two readable things: verdict = f(contract, action).
Goal ──▶ Contract (PIANO.md) ──▶ Gate ──▶ Audit log
task contracts: default-deny: append-only, with provenance,
deliverable, unknown action all three outcomes: committed,
acceptance criteria, becomes a queued, and denied — the last
dependencies PROPOSAL one with its reason
│
▼
Queue ──▶ human ✔ ──▶ canonical memory
PROPOSTE-<date>.md, decided one at a time,
each decision recorded with who and when
A denied action writes nothing to the canonical memory; but it is recorded in the audit log, with its reason. A refusal that leaves no trace is a silence, and silences are what an audit log exists to prevent.
The orchestrator and the gate currently run inside the author's working system; extracting them into this repository is the current milestone. What exists today is observed behavior:
- Default-deny, tested: 10/10 unknown actions stopped as proposals, 0 implicit
writes (
TEST-ZERO-TRUST, regenerated byrun_proof.py). - Append-only audit log of all three outcomes: committed, queued, and denied (each with its reason), with provenance and atomic writes. Honest boundary: the log is not yet immutable.
- The human ✔ is a command, not a gesture: every proposal carries an id, the
queue renders to
PROPOSTE-<date>.md, and a local CLI applies ✔/✗ to the canonical memory, recording who decided and when. Deciding twice is refused, not re-applied. It is deliberately not an MCP tool: exposed as one, the agents the gate exists to constrain could approve their own proposals. - PIANO.md as a real work contract: 17 real plans currently governing the author's projects, including the plan that governs this repository. This is evidence of use, not of efficacy: the plans are private and no third party can check them.
- Executable verification of acceptance criteria. Only feasible for criteria that carry a command; criteria written in prose stay a human check, and will be marked as such rather than pretended away.
- Authenticated identity. Both
agente(who proposes) and--decisore(who approves) are declared strings, not verified identities. The gate proves classification, not who asked. - Content rules. The gate classifies on the action name; it does not inspect target or value. It protects the namespace, not the payload a non-cooperative agent can call a permitted action with an impermissible value.
- A store that survives concurrent writers. The document is rewritten whole on
every commit, with no lock: two writers can lose an update. A working file-lock
prototype exists but depends on
msvcrt, so it is Windows-only, which does not meet this project's own definition of done. - Packaged, installable release. The gate is packageable today; the orchestrator lives outside this repository, and extracting it is the actual milestone.
Core under MIT.
See CHANGELOG.md.