@evoclock/pi-agentic-driver
Guardrail extensions for Agentic Driver: advisory review, bounded Herdr communication, and guarded worker lifecycle.
Package details
Install @evoclock/pi-agentic-driver from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@evoclock/pi-agentic-driver- Package
@evoclock/pi-agentic-driver- Version
3.0.3- Published
- Oct 28, 2026
- Downloads
- 1,690/mo · 620/wk
- Author
- evoclock
- License
- AGPL-3.0-only
- Types
- extension, skill
- Size
- 1.7 MB
- Dependencies
- 3 dependencies · 1 peer
Pi manifest JSON
{
"skills": [
"./skills/decision-to-spec",
"./skills/pulse",
"./skills/tasks",
"./skills/weekly-build-recap",
"./skills/crew-tracker-sync",
"./skills/harvest-lessons",
"./skills/public-pr-wording",
"./skills/release-public",
"./skills/correct-pi",
"./skills/driver-mode",
"./skills/test-gate",
"./skills/session-handover",
"./skills/ralph",
"./skills/driver-principle-boundary-only-authority",
"./skills/driver-principle-cite-your-status",
"./skills/driver-principle-dependency-policy",
"./skills/driver-principle-evidence",
"./skills/driver-principle-fail-loud",
"./skills/driver-principle-working-memory-is-not-authority"
],
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-agentic-driver
An agent without guardrails will sometimes rewrite code an existing abstraction already covers. It will ship to the wrong remote. It will lose context and report success without evidence. Pi is deliberately lean by design: the harness is yours to shape. That philosophy is exactly what these extensions practice, they make them mine (and possibly yours too). They take some concerns I consider worth addressing, and make them part of the harness.
pi-agentic-driver makes agent work verifiable and controllable. The agent does the work and each extension makes sure the work can be checked. Reviewing happens before code is written. Communication involves reports without asserting authority that isn't granted. Isolation proofs exist to verify their own cleanup. Sessions survive compaction and Git operations stay exact, confirmed, and protected.
Features have different evidence levels: focused tests and independent review support the shipped contracts, while live host-dependent proof is stated only where it has actually run. A receipt or worker report is evidence, not approval.
Treehouse recycling is configured in config/treehouse.v1.json. Treehouse is a
separate Go CLI, not an npm dependency; the exact supported CLI version is pinned
there and checked before any return. Create worktrees from the repository root
with treehouse get --lease --base main --branch <branch>. The optional Pi
extension checks driver-held leases at session start and every five minutes.
It returns only idle, clean worktrees whose exact pushed head belongs to a
merged or closed PR. A missing PR, different head, unknown CLI version, dirty
checkout, or active process leaves the lease intact. It does not create
worktrees, clean files, merge branches, or remove slots.
Extensions for Pi: advisory code review, controlled role communication, and governed isolation proofs for agentic workflows.
Fleet Herdr spawn rule
HARD (fleet-wide): anything that controls bots encodes this in git here, not only in assistant skills.
- Pi tabs/panes: only
agentic_herdr_spawn_worker/ Pi herdr spawn (spelling herdr). - Never raw Herdr CLI from a bot shell, including agent start, prompt, read, wait, and pane send-keys. The attended-authority guard refuses those bash forms fail-closed. Use
agentic_herdr_communicationfor bounded exchanges. - Unattended spawns pass
authority.ledgerIdfor a covering Tier 1 ledger grant. Without one, the tool opens the native Spawn confirmation and waits on the operator. - Default Pi model: the operator-named default until the operator names another.
- Details for agents: AGENTS.md.
Shipped features
| Tool | What it does | Status |
|---|---|---|
code_phage |
Reviews a plan against a stated goal before code is written and advises your agent. | shipped |
tasks |
Keeps a priority-ordered session plan, then lets the owner make selected items durable in TASKS.md. |
shipped |
decision-to-spec skill |
Drafts one reviewable assignment from your explicit decision or a sourced, quoted relay, with observable outcomes and a stop point. | packaged skill |
agentic_decision_evidence |
Records the stated source of a decision (direct or relayed, with quote, where, when and relayer) for a private assignment; it verifies no identity and creates no authority. | shipped |
agentic_relay_check_request |
Checks whether a recorded, scoped relay covers each requested private action; read-only preflight, with authority checked again at the action boundary. | shipped |
agentic_merge_review_record |
Records independent Standards and Spec verdicts for an exact PR head; read only when the merge policy is agents-after-checks-and-review, and it merges nothing. |
shipped |
agentic_herdr_communication |
Submits one prompt and observes delivery and marked reports; never grants authority. | shipped |
agentic_herdr_spawn_worker |
Starts one Pi worker in its repository's own labeled workspace, in a pane or tab, with native confirmation. | shipped |
agentic_aidr |
A remedy for AI;DR. Reviews writing for clarity, simplicity, brevity, and humanity. | shipped |
agentic_linux_microvm_cutover |
Runs one job in a throwaway QEMU/KVM virtual machine on a Linux host, with a severity-tiered killswitch that stops escape attempts. | user-enabled, native confirmation |
agentic_worker_dispatch |
Runs bounded worker journeys and observes worker liveness. Each iteration is a durable checkpoint, so an interrupted journey resumes without resending an uncertain prompt; the journeys action lists the records. |
shipped |
agentic_journey_outward_effect |
Makes one confirmed Git push, or private draft PR create or update, for an existing journey; after an interruption it checks the remote and never repeats an uncertain write. | shipped, native confirmation |
agentic_kanban_board |
Shows the workspace task board: lanes, flags, priorities, dependencies, and which cards can run. | shipped |
agentic_kanban_board_write |
Adds cards to the board through the trusted writer, which records who authorized the work. | shipped |
agentic_kanban_board_update |
Moves, closes, flags, edits, or removes cards on the board, always recording who authorized the change. | shipped |
agentic_kanban_board_dispatch |
Claims an eligible board card for automated contained work and creates its assignment envelope. | shipped |
agentic_kanban_pulse |
Checks for ready work and available capacity, then starts assignments under the board policy. | shipped |
agentic-recovery-evidence |
Opens private recovery evidence in the local TUI; it is not a model-callable tool or recovery authorization. | shipped, local review only |
| Router | Capacity/policy routing for Board Pulse: seats with scope statements, tunable policy values, and a binding dispatch gate. | shipped |
| Janus (bundled service) | Local Jev evaluation service on loopback: semantic ranking, the dispatch-gate judgment, redaction before every external call. See janus/README.md. |
shipped |
weekly-build-recap skill |
Prepares a local weekly GitHub recap with a picture and draft posts; posting remains yours. | shipped |
| Bounded loop-until-done | Keeps a session working toward an explicit stopping condition within configured limits; packaged since 2.0.0 and documented here. | shipped |
Status: active development and testing. The disabled NUDGE classifier and
private evidence store are packaged foundations, not a running recovery
ladder. Herdr 0.9.1 has no proven modal-safe nudge channel. No terminal
prompt or send-keys fallback is enabled. Pending integrations below are
not presented as live features. Worker dispatch persistence is on by
default and resumes interrupted journeys from durable checkpoints. Its crash
tests use a simulated Herdr adapter, a local Git remote and a simulated
GitHub endpoint, so recovery in a live deployed pane is not yet proven.
Busy workers can receive queued briefs or messages without treating delivery as a completed answer. An idle worker without a done marker is classified as stalled, rather than complete; the former idle-eligible state has been renamed. See scripts/enforcement/loop_until_done_guide.md for the bounded loop's limits and stopping behavior. The weekly recap skill lives in skills/weekly-build-recap/ and writes local drafts only.
Code review and planning
Extensions that review, route, and control what an agent does.
The code_phage tool reviews a proposed change against a stated goal before the agent
writes or commits code. Give it a goal, candidate files, accepted
requirements, and test paths. It will:
- Find prior art structurally. It matches exported symbols, function signatures, and dependency imports against a repository inventory, so the agent reuses an existing abstraction instead of writing a parallel version. Word overlap alone never counts. When prior art informs the result, the implementation records its source, version, and license.
- Bind an implementation budget. Goal, requirements, write set, and tests become one reviewable budget. Coverage checks flag requirements nothing binds and tests nothing covers.
- Measure diagnostic signals. Cognitive and cyclomatic complexity, line counts, duplication, module-level mutable state, dependencies, test burden. These are signals for human judgment, never rejection thresholds.
- Redirect scope drift. It names the files that support no accepted requirement and recommends the smallest coherent write set. The deletion test guards justified complexity: what would fail if we removed this?
- Stay advisory. It never mutates files, creates tasks, grants authority,
or blocks work. Every result says
advisoryOnly: true.
Concept credit: Matty Stratton, "Cognitive Complexity" (2024-09-20, concept
only, no code copied); flake8-cognitive-complexity 0.1.0, MIT (concept
only, not a runtime dependency).
Plans stay close to the work. They do not become board work by accident. The tasks skill gives Pi a familiar session list. It adds an owner-approved way to keep selected tasks in the durable TASKS.md board.
- Keep the working list simple. Use
TaskCreate,TaskGet,TaskList, andTaskUpdateas usual. Set an optional P0–P3 session priority; ranked open work appears first, unranked work keeps ID order, and completed work appears last. Priority does not authorize board dispatch. The widget and footer stay live as tasks change. - Keep the Claude-like view.
/tasksprovides descriptions, active forms, and internal-task markers without mutating the plan. - Make durable work deliberate.
TaskPromotenever runs automatically. It previews the exact cards and destination before the owner confirms. - Keep authority clear. The trusted board writer creates and updates
TASKS.md. The skill does not bypass it. - Make migration gentle. Existing task files remain readable. Moving to the driver-owned skill does not strand current plans.
The result is a clean handoff from a session plan to durable work. Selected tasks can survive the session, appear on the shared board, and become available for controlled dispatch when ready. A session priority is not copied into a board card without an owner-approved board action.
The decision-to-spec skill turns a decision into one reviewable planning
brief. Invoke /skill:decision-to-spec or ask for the workflow explicitly.
Pi can load the skill description on its own; loading is not evidence of a
decision and is not permission to draft.
- Source the decision. The brief records either your direct instruction
or a relay that quotes your exact words with where and when you gave them.
A bare approval claim or an unsourced quote is not decision evidence.
agentic_decision_evidencestructures the stated source; it verifies no identity. - Relay private approvals. A configured relayer can record your exact
answer, the question it answers, its source, channel, time, and bounded
scope.
agentic_relay_check_requestis a read-only preflight; each action checks the record again. A relay attests that the configured relayer recorded your words; it does not prove identity or authorize merges or publication. Seedocs/relay-authority.md. - Settle what matters first. The skill inspects the inventory, existing behavior and the affected driver capabilities, then asks one round of decisions that could change acceptance, scope, ownership, review or stop conditions, each with a recommendation.
- Make outcomes observable. Success and meaningful failure are written as Given/When/Then, with the highest feasible existing test seam and the reason it would catch a broken implementation.
- Bound the work. Owner, author, an independent standards and boundary reviewer, and an exact-artifact acceptance reviewer; exact paths and effects, the model, data and runtime route, exclusions, and a stop point. Implementation needs an identified Treehouse lease; drafting does not.
The output is a private planning brief for the requester, not a dispatch record. It cannot approve a merge, release, deletion or force-push, write a board card, create an issue, or change a provider route. Unresolved decisions stay explicit instead of becoming assumed requirements.
Concept credit: Matt Pocock's grill-with-docs, to-spec and
domain-modeling skills, MIT (question-framing patterns only, no text
copied).
Available now:
- task-ledger integration. Agents can read and act within board card
states while the trusted writer retains authority over admission,
completion, reconciliation, and migration. The Tasks skill also bridges
session planning to the durable
TASKS.mdboard. - role and phase routing. The router separates planning, implementation, review, and escalation phases. It reports endpoint warm state when configured. Warm-session preference remains future work; route affinity never overrides authority.
Planned in this theme:
- prompted planning lifecycle. Turn natural-language goals into complete proposals with parent and scope choices at native boundaries. No retry loops or model-supplied identifiers.
- native assignment selection. Choose planned assignments through a native UI over derived candidates, never through model-supplied targets.
- inventory refresh. Regenerate the Git-aware codebase inventory with verification receipts so prior-art matching stays honest.
- project status and state review. Add read-only views of workspace Git state, formal records, and task-state health.
Board Pulse selects a route seat through the capacity/policy router. The router reads a closed configuration file and a local-first SQLite file for operational state (reservations, observations, route-decision audit).
Two router features call Janus — a separate local service, bundled under
janus/, that is the only component allowed to talk to the TypeSafe Jev
models:
- Semantic ranking (optional): Janus ranks up to eight eligible seats; on any Janus failure the router falls back to preference order.
- The binding dispatch gate: before a task is claimed, Janus judges whether the task fits the selected seat. No verdict, no dispatch — the gate fails closed when Janus is unreachable.
Janus binds loopback only (127.0.0.1:8787), reads its API key from the
macOS Keychain at runtime, redacts state before every external call, and
coalesces identical requests. See janus/README.md for the endpoint
contract, Keychain provisioning, and configuration.
- Repository defaults ship at
.agentic-driver/router.defaults.json. The template contains no accounts and one disabled placeholder seat, so it loads out of the box and schedules nothing until you enable a real seat. - User profile (precedence over defaults):
the configured router profile path, or the path in the
AGENTIC_DRIVER_ROUTER_PROFILEenvironment variable. A profile section replaces the matching defaults section wholesale; the merged config must validate or the router refuses to produce decisions (fails closed). - Operational state:
~/.local/share/agentic-driver/router/state.db, orAGENTIC_DRIVER_ROUTER_DB. This store is operational state only. The authenticated claims file and the board writer remain the only dispatch authority; the system repairs SQLite from them, never the reverse. - Runtime requirement: the operational store uses the built-in
node:sqlitemodule. You need Node.js 22.5 or newer.
Every numeric policy in the router is a configuration key — never a constant in code. All keys are required. The repository defaults below are conservative starting values. Your profile overrides them. A missing key is a configuration validation failure: the router fails closed rather than guess. Changing a value participates in the configuration digest, so cached routing decisions computed under the old values no longer apply.
| Section | Key | Default | What it controls |
|---|---|---|---|
eligibility.reserve |
floorPercent |
40 | Share of every quota window kept in reserve (per account, per window). Headroom for an unexpected burst and your next interactive session, without idling the account. |
eligibility.reserve |
scope |
account-window |
How widely the reserve floor applies (per account per window at launch). |
eligibility.reserve |
coldStartFraction |
0.25 | Consumption assumed for a seat with too little history: deliberately generous, so a mis-estimate fails eligibility instead of draining the account. |
eligibility.reserve |
estimateSamples |
20 | How many recent dispatches the consumption estimate averages: enough to smooth outliers, quick enough to track a model change. |
eligibility.reserve |
estimateMinSamples |
5 | Below this many observations, the estimator treats the average as noise and uses the cold-start value instead. |
eligibility.reserve |
estimateOutlierSigma |
3 | Outlier cut for the estimate: one unusually slow dispatch cannot inflate the average, real tail latency is kept. |
eligibility.reserve |
ownerInteractiveOverride |
false | Whether your own interactive dispatches bypass the reserve rule (they do not, at launch). |
ranking |
janusUrl |
http://127.0.0.1:8787 |
The local Janus evaluation service endpoint used for semantic ranking. |
ranking |
maxCandidates |
8 | The router ranks at most eight eligible seats per request; preference order trims the list first. |
ranking |
fallback |
preference-order |
What happens when ranking is unavailable: dispatch falls back to your preference order and never blocks. |
gate |
threshold |
0.9 | The dispatch gate's confidence threshold. A task is only dispatched when the evaluation clears it. Lower it only with evidence from your own audit log. |
gate |
timeoutMs |
8000 | How long the gate waits for an evaluation. On timeout there is no verdict, and the gate blocks dispatch (fail closed). |
gate |
requestBudgetTokens |
30000 | Maximum size of a gate evaluation request. Normal evaluations use under a thousand tokens. |
| seat record | maxConcurrency |
4 | How many workers one seat may run at once. The default suits a typical single machine or hosted seat. Tune it per seat: a cluster takes more, a constrained subscription endpoint may take less. |
| automation policy | maxConcurrent |
4 | How many workers may run at once across all seats. The default is a conservative start. Tune it to the capacity you actually have, and raise it when you add seats or hardware. |
Seats are named for infrastructure, not models: dgx-spark,
dgx-spark-cluster, mac-studio, mac-studio-cluster, strix-halo,
strix-halo-cluster, merge-gateway-worker. The model is a mutable field on
the seat, so changing models never renumbers your configuration. Each seat
also carries scopeStatements: plain-language descriptions of what the seat
is for. The dispatch gate reads them when judging whether a task fits.
Janus is the local evaluation service bundled in this repository under
janus/. It is the only component allowed to talk to the TypeSafe Jev
model. It wraps the official TypeSafe SDK. It exposes one evaluation endpoint
and health probes on loopback. The router's semantic ranking and binding
dispatch gate call it. Nothing else in the harness talks to Jev directly.
Guarantees:
- Loopback only. Janus binds
127.0.0.1:8787and nothing else. There is deliberately no bind-address option: it is a local tool. - Key stays in the macOS Keychain. Janus reads the TypeSafe API key at
runtime with a guarded
securitylookup. It never passes the key to subprocesses. It never writes the key to logs or transcripts. - Redaction before every external call. A secrets/PII pass runs over the state before anything leaves the machine. No disable knob exists.
- Single-flight. Janus coalesces identical requests. It caps distinct
in-flight evaluations. It rejects overflow with
busyinstead of queuing silently. - Controlled requests. Janus enforces a 30k-token request budget. It rejects oversized requests instead of truncating them.
Running it:
cd janus
sfw npm install
npx tsx janus/server.ts
For a persistent setup, use the launchd template at
janus/user.janus.plist. Provision the TypeSafe Direct key once in the
Keychain. The command is in janus/README.md.
When Janus is down: semantic ranking falls back to preference order. The binding dispatch gate blocks dispatch and fails closed. Janus never becomes a silent dependency: its absence is loud.
See janus/README.md for the full endpoint contract, the error taxonomy, and
configuration.
Multi-agent communication
Extensions for controlled coordination between agents.
The agentic_herdr_communication tool exchanges controlled, marked reports with
configured Pi worker roles running under Herdr (validated
against Herdr 0.9.1; the trust seam accepts the Homebrew-managed herdr binary
across versions rather than pinning one).
- List and observe. The integration checks a repository-local
config/herdr-worker-repositories.v1.jsonfirst, then the same file in the active Pi profile underPI_CODING_AGENT_DIR(the installed agent profile directory). If no registry is available, spawning is refused and communication trusts only the current repository; malformed registries are rejected. Canonical path checks reject unlisted or symlink-escaped repositories. - Submit once and observe separately. A prompt returns an immediate,
non-authorizing delivery receipt. The
deliveryaction can report queued, delivered, answered, failed, unknown, or unattributed. A marked answer is attributed only to its own delivery boundary and exact correlation line; missing or ambiguous evidence is never called success. - Wait and read. The same trust checks apply to settlement and marked reports. Unknown delivery never causes an automatic retry or resend. Duplicate submissions within the bounded uncertainty window return the existing delivery ID, not another handoff.
- Grant nothing. Fixed argv,
shell: false, a pinned executable, the coordinator role class denied. Results come back as untrusted evidence. The tool cannot control panes, start agents, run shells, or create authority. - Scale to many workers. The trusted registry accepts up to 32 worker repositories, and any dynamic non-coordinator role within them is eligible. Fan-out is sequential by design: one role per prompt, one complete exchange, no broadcast primitive.
The agentic_herdr_spawn_worker tool turns one natural-language request into Herdr's
native lifecycle. Choose a placement (right, below, or tab), a safe role
label, a model from the active Pi model roster, and a trusted repository. The
extension:
- creates the split pane or labelled tab;
- starts exactly one Pi agent in it;
- verifies the role, model arguments, pane identity, and canonical repository;
- resolves the model against the installed Pi roster and the active profile's
config/model-route-policy.v1.local.jsonbefore spawning; missing, invalid, ambiguous, forbidden, or unbudgeted routes fail closed; - optionally accepts one explicit worktree target: it must be the canonical Git worktree root of that same registered repository and carry an active Treehouse lease observed read-only, and it is revalidated after confirmation and between mutations;
- requires native confirmation or a covering existing ledger grant before changing layout or starting a process; native confirmation shows the exact worktree target and lease identity when one is used;
- never treats a repository-only approval grant as covering a worktree target: a ledger grant must cover the repository, action, model, role and exact target path; a new target without that coverage requires native confirmation;
- treats an explicit empty
modelsorroleslist on a ledger grant as any model or role; a missing list still fails closed; - uses fixed argv with
shell: falseand no arbitrary Herdr or shell surface; - returns explicit
pane_created,tab_created, oragent_startedpartial states when only part of the operation succeeds; and - never retries, moves, closes, or deletes created state automatically.

The same request can place a worker below the coordinator or keep it in an individual tab:
See Dispatching a Multi-Model Workforce from Anywhere for the wider task and model-routing workflow.
The agentic_worker_dispatch tool runs controlled worker journeys and observes worker
liveness. Two actions:
- pulse reports whether a worker role is alive, its current state, and whether it is dispatch-eligible.
- dispatch runs one journey. The worker works through the existing task
sequence, one prompt-and-report exchange per task, at most
maxStepssteps (default 50, cap 200).
Continuous mode is the default: the journey keeps going until the worker finishes the queue or reaches the step bound. Turn-by-turn mode stops after each step and is explicit opt-in. Each journey emits one collated marked report covering every step.
A worker that never reaches idle across the observed exchange cycle ends the journey with an explicit unresponsive state. You can then spawn a replacement through the guarded lifecycle boundary. The replacement resumes the same pending tasks, reuses existing task cards, and never duplicates them. The stuck exchange is never resent to the same worker.
Journeys never create, own, or complete task cards themselves, never retry silently, and return results as untrusted evidence.
/loop-until-done <steps> <approved goal> :: <observable exit check> gives
one already-authorized coordinator session task a fixed worker-dispatch budget.
Configure the limits and wake in .agentic-driver/loop-until-done.defaults.json.
The defaults allow at most 200 attempts or 30 minutes, whichever comes first.
Each attempt consumes a step before dispatch. After a successful exchange,
the default wake prompts a check immediately; an interval can delay that prompt.
Each wake asks the agent to check the original exit condition before another
dispatch. The per-session allowance cannot be extended or restarted. This
command does not dispatch board cards; Board Pulse owns those.
The extension, its defaults, and its guide are included in the 2.0.0 npm
package file list. See scripts/enforcement/loop_until_done_guide.md.
agentic_worker_dispatch keeps each journey on disk, so a crash or restart
in the middle of a journey neither loses its place nor repeats a prompt.
Persistence is on by default. It is built on Pi Durable, not on a separate
state machine.
- One durable task per iteration. Each journey iteration is one Pi
Durable task. The driver commits a checkpoint before every pane send, and
Pi Durable resumes the task after a restart. A caller can supply a
journeyId(letters, digits,_or-, up to 100 characters); ad-hoc work gets a generated one. - A tag in every prompt. Each dispatched prompt ends with
[journey:<id>:<iteration>]. After a restart the driver looks for that tag in the pane before it decides anything. - Block, never resend. An iteration that had not yet sent its prompt rechecks worker liveness and asks for native confirmation again before it sends. Once a send has started, recovery only observes. One clean tag followed by one attributable role report settles the iteration. A tag without a report is polled for about two minutes, then blocks. A missing tag or an unreadable pane blocks: a missing tag is never proof that the prompt did not arrive. An abandoned pending task with no caller waits at most 30 seconds, then settles blocked.
- Inspect journeys. The
journeysaction lists bounded journey records for the current repository (journey, iteration, state, task and card), optionally filtered by role or journey ID. It grants nothing. - One store per session, one owner per store. The extension opens a
private store for each stable Pi session ID on first use, not at import. A
lock records the owner's PID, hostname, process start time and release
token. A live competing owner is refused. A stale lock is reclaimed only
when its same-host owner is proven dead; unknown ownership, or a host whose
pscannot report a process start time, refuses. - Keep the record small. The index holds bounded identities and attributed report bodies, not briefs or terminal snapshots. A report is evidence, never owner completion.
Evidence. Crash tests kill the dispatch process before the send, after
the send and after the result, then restart it without help. Pane-history
tests cover five cases: tag found, tag found with a late report, tag
missing, history too short, and a wrapped tag. Only the first two settle;
the rest block. CI runs these on every pull request. They
exercise the real dispatch code against a simulated Herdr adapter. Recovery
in a live deployed pane, an independent live restart, and power-loss
durability (SQLite runs in NORMAL mode) are not yet proven. Node.js 22.19.0
or newer is required. See docs/durable-persistence.md.
Credit: Pi Durable (@earendil-works/pi-durable) 1.0.4 by Earendil Works,
MIT. It is installed as a pinned dependency, not copied into driver source.
Keep planned work in canonical TASKS.md. You can read it directly or use
the generated board.md view in Obsidian. Agents use the same canonical
record through natural-language board tools.
You can tell an agent to add, edit, move, block, propose, close, or remove a card. The trusted writer assigns its ID, checks its fields, records your instruction, and protects its dispatch provenance.
Agents cannot invent additional work or complete a card on their own. An agent report is evidence for your review. Only your clear instruction or direct board action completes the card.
For automated work, you set an explicit policy for the board. It defines:
- allowed roles and repositories;
- contained placement;
- the maximum concurrent work;
- the policy expiry; and
- the risk ceiling.
Without a valid policy, automated dispatch is refused.
The agentic_kanban_board_dispatch tool claims the highest-priority eligible card. It
creates a single-attempt assignment envelope that binds the card, repository,
starting revision, assigned branch, allowed paths, stopping point, expiry, and
interaction profile.
Blocked, altered, expired, reused, or unauthorized assignments fail closed. Board Pulse handles board assignment with full route evidence. The session worker journey does not claim board cards or mint board envelopes.
Consuming an envelope releases the claim. It does not mark the card done.
External board clients submit agentic-driver.board-claim-request.v2 to
claimFromBoardRequest. Receipts use agentic-driver.board-claim-receipt.v2,
route digests use agentic-driver.board-claim-route.v2, and asynchronous
transport receipts use agentic-driver.async-transport.receipt.v2. Clients
must use these names; prior request, receipt, and route contracts are rejected,
with no compatibility aliases. Unsupported request schemas fail closed.
Workspace capabilities live at
.agentic-driver/capabilities.json; route seats and providers use board-
and board-router identities.
Claims and envelopes are kept in authenticated state beside TASKS.md. The
derived board.md view shows active claims but never becomes an authority
source.
The agentic_kanban_pulse tool checks the board for ready work and available capacity.
A check only reports which work is ready to run. It does not claim cards.
Interactive host work needs explicit policy and one native confirmation for the batch. Automated work requires containment and never falls back to the host.
Coming next:
- contained Pulse execution through an approved isolation boundary;
- expanded external board support for the shared card fields; and
- our own Obsidian plugin for canonical
TASKS.md.
- project status and state review. Read-only projections of workspace Git state, formal records, and task-state health.
- role-lane routing and warm sessions. Separate lanes handle implementation, planning, and review, and the router prefers a warm session so context and cache survive across tasks. Route affinity is an optimisation, never authority: an incompatible lane yields an explicit review-required result, never silent model substitution.
- task-ledger integration. Agents read and act within the task ledger's card states without owning board authority: no admission, completion, reconciliation, or migration by the agent itself.
Writing clearly
AI;DR (AI; Didn't Read) keeps technical writing clear without flattening the writer's voice.
The agentic_aidr tool reviews the last assistant response, supplied prose, or a
Markdown file. It checks four principles:
- Clarity. Each sentence carries one useful idea.
- Simplicity. Clutter, pompous phrases, and needless jargon go.
- Brevity. Fewer words when they carry the same meaning.
- Humanity. An authentic human voice stays.
The simple and ste modes add an ASD-STE100-informed profile: sentence
length, direct word choice, precise verbs, and clear requirements,
permissions, abilities, and conditions. It targets 20 words per procedural
sentence and 25 per descriptive one, and returns the rule and an example for
each finding.
The profile is advisory. It does not include the licensed ASD-STE100 approved-word dictionary and does not certify conformance. Check final text against the licensed specification and your project terminology list.
AI;DR also flags dense paragraphs, suggests bullets when they reduce working memory load, and supports plain-language and analogy modes. Review is read-only. An explicit file apply action shows a git diff and writes the exact replacement only after native confirmation. Release 0.4.2 adds controlled inputs, atomic replacement, drift checks, and exact write verification.
Sandboxed execution
Extensions that run agent jobs in a sealed environment and prove it.
Available in this release:
The agentic_linux_microvm_cutover tool runs a single job inside a throwaway
QEMU/KVM virtual machine on a Linux host. The job cannot reach the host, the
network, or anything else outside the machine. The system deletes the machine
after the job ends.
Isolation is off at the start of every session. Use the /agentic-isolation-enable
command in the Pi TUI, and confirm. The model cannot run
that command. Every cutover run asks for its own confirmation too. Nothing is
saved to settings, and headless sessions stay blocked.
You choose the machine
The model can only relay your words. Saving a target, or running on one, always requires your confirmation dialog first.
- Tell the agent where to run the proof, for example "run the microVM proof on deploy@192.168.1.50" or "run it on this machine". The first run asks you to confirm. Your Yes saves the choice to your Pi config and the run continues.
- Run
/agentic-isolation-enableand confirm. - Each cutover run asks for its own confirmation. Later runs reuse the saved target without asking where the microVM runs again.
The tool discovers the technical details from the machine itself:
architecture, kernel, libvirt driver. You configure nothing. Before any run,
the probe checks three requirements: /dev/kvm is accessible, libvirt
reports the system-level driver, and a matching qemu-system-<arch> binary
exists. A failed check denies the run before anything happens. The shipped
fixture guest is x86_64-built, so the full proof currently needs an x86_64
KVM host.
What example tests look like
We started with one payload: print a greeting, then call a network tool. The greeting printed, the tool tripped the killswitch at the HIGH tier, and the line after it never ran. A kill report landed in the state directory naming the rule and tier, and the teardown proof showed the machine was gone with nothing left behind.
From there we wrote a payload for every rule in the taxonomy: credential probing behind chained commands, secret dumping inside subshells, package installs, coordination files reaching for other agents, a forged receipt, a write to the evidence channel, and ten unclassified commands in a row to push the anomaly threshold to its limit.
The guest had no disk, no network, no host share, no credentials, and no GPU. Nothing outside the kernel's virtual filesystems could be mounted. Every attempt was denied and written to a log that survived the machine.
While this is a toy test of sorts my own personal work will be running on these as well.
What the containment layer defends against
Agent escapes tend to follow a playbook, and the published incidents from frontier labs (the HuggingFace incident among them) read like one: grab credentials, phone home, install something persistent, rewrite your tools, stage payloads in caches, look for other agents to recruit, clean up the evidence. The containment layer has a rule for each step:
- Credential theft. Reading SSH, cloud, or token material, or dumping environment secrets, ends the session immediately.
- Exfiltration and remote control. Any network tool, any socket, ends the session immediately.
- Persistence through dependencies. Package installs, registry writes, and manifest tampering are denied and counted. Repeat the attempt and the session ends.
- Self-modification. Rewriting the agent's own tools or the monitoring layer is denied and counted.
- Payload staging. Growth in cache and package directories is sampled by size; repeated growth ends the session.
- Cross-agent escalation. Coordination channels and shared paths used to reach other agents end the session immediately.
- Evidence tampering. Editing logs, forging receipts, or writing to the console channel ends the session immediately.
- Reconnaissance. Probing the sandbox to learn whether it is watched is counted into a concealment index that ships in the run receipt.
Denials are written to a tamper-evident, digest-chained log that outlives the session, and a trip produces a kill report naming what happened, with proof that the cleanup completed.
Proven against real machines
Every rule above has been run against a real QEMU/KVM guest with a payload built to trigger it. The kill switches fired where they should, the denials stopped the jobs, and the cleanup held. One boundary is worth stating: two rules watch the same directories by design, and together they are stricter than either alone, so the growth-sampling trip is covered by automated tests rather than a live run.
Dispatch a worker journey that runs end to end while you are away. The journey proceeds through steps without pausing for confirmation, replaces agents that get stuck, and records everything in one report you read when you come back.
Autonomy is entered by your words alone. Say "run these overnight end to end" or "don't wait for me" and the journey runs in autonomous mode. Say "do these two things" and it runs in the normal mode, pausing for you between steps. The mode is recorded in the report either way.
agentic_worker_dispatch observes coordinator session tasks through a
read-only task store; dispatch no longer fails for lack of that store.
Interactive steps require native confirmation. Autonomous journeys follow
the session's existing autonomy semantics. Board cards in canonical
TASKS.md are assigned by Board Pulse and agentic_kanban_board_dispatch,
which own the route evidence needed for claims and envelopes. The session
journey never claims board cards.
The cast
You name the agents for the journey, and that list becomes the standing permission. If the implementer gets stuck at 3am, a replacement spawns automatically: same role, same model, both in the list you authorized. If a task needs an agent you didn't name, the attempt is recorded and that thread stops. Nothing outside your list can appear while you sleep.
The cast is frozen at dispatch and never grows. It can only shrink in practice (roles finishing their work), never widen.
When agents get stuck
A stuck agent doesn't block the journey. The journey detects the stall, spawns a replacement from the cast, and the replacement starts with a mandatory gap analysis: read the task spec, inspect the repository, consult the journey history, and state what remains before resuming. The replacement must show that the remaining work is smaller than what its predecessor left. If it can't, the journey stops that role and continues with the others.
The morning report
One block tells you what happened: the terminal state, each step's outcome, every replacement with its gap analysis and progress judgment, and any denials. Every claim is tied to a receipt or a report excerpt. No prose narrative to reconstruct; you read the report and know exactly where things stand.
The safety net between an agent and your shell. When a model tries to delete, overwrite, or push, the guard stops it and asks you. Safe commands pass through untouched. If you deny, you get a clear reason and the session continues, and the agent does not retry behind your back. In headless runs where no human can confirm, destructive commands are refused rather than silently allowed.
Merge policy (shipped). The guard also enforces one merge
setting, read from {PI_CODING_AGENT_DIR}/config/merge-policy.v1.json
(the installed agent config directory) and never from the working tree.
human-merges-onlyis the default. You merge on GitHub; every agent merge command is refused. A missing, unreadable or unknown policy falls back to this value.agents-after-checks-and-reviewis opt-in. An agent may run a plaingh pr merge <number or URL>only when every check on the PR head has passed andagentic_merge_review_recordholds a Standards PASS and a Spec PASS for that exact head. Neither reviewer may be the PR author or the merging session. A new push needs a new record.- Bypasses are refused under both values. Admin and auto merges, the
REST merge endpoint, the
mergePullRequestmutation, and writes to branch protection or rulesets. A refusal starts withpi-agentic-driver.merge-policy.v1: needs-owner-approval:so a coordinator can pass it up as your decision.
This is a workflow guard, not a security boundary. It reads command text, so
a merge through shell indirection, another tool or the GitHub web page is
not seen. Branch protection on GitHub remains the real gate. See
docs/merge-policy.md.
Under development in this theme:
- native macOS container proof. The native Apple Container runtime has passed a fixed local isolation qualification: read-only repository mount, no network, automatic removal. The native Pi adapter is not yet part of the released package.
Session continuity
Managing context pressure, compaction, and avoiding lossy handover.
In development:
- context-pressure handling. Pressure detection, non-lossy handover, compaction completion without cancellation loops, and continuation of the latest user goal. Development-only until the full live journey passes.
- lossless session-reference compaction. Selective, lossless retrieval of exact pre-compaction content, addressing factual degradation across repeated compactions. Designed as an optional add-on, not yet implemented.
Planned in this theme:
- handover, checkpoint, and recovery. Durable repository-local handover notes, governed checkpoint mutation, watchdog handoff, and fresh-session resumption that identifies goal, changed files, checks, and next step without executing anything.
- recovery journey. A private exact-evidence store and read-only TUI review are packaged. Trusted journey authorization, safe handoff, durable unknown- delivery lock, and a modal-safe nudge channel are still missing. No recovery action is enabled by a stored hash, receipt, or display token.
- broader evidence ledger. Deterministic indexing, lossless projection, checkpoint produce/store/recover, and tested multihost reconciliation remain planned beyond the bounded private store.
- offline multihost evidence. Record run evidence on each host while disconnected and reconcile it deterministically on reconnection, with no host as sole authority.
Working with Git safely
Extensions that keep routine Git low-friction and consequential Git guarded.
Available now:
The agentic_journey_outward_effect tool makes one consequential Git or
GitHub write for an existing journey: a push, a private draft pull request
creation, or a draft pull request update. It records what it is about to do
before it does it, so a restart can tell a planned write from an uncertain
one.
- Record intent first. Each effect is its own Pi Durable task, committed before Git or GitHub is called. A push binds the branch, the expected remote head (none for a new branch) and the target commit. A PR call binds the head, branch, base, and digests of the title and body; an update also binds the PR number and the prior body digest. The PR body is used for that call only and is not stored.
- Observe, never replay. After an interruption the tool reads the remote
with
git ls-remoteandgh apiand never repeats an in-flight write. The exact target commit, or the exact PR fields, verify the effect. A missing branch is not proof that a push failed. A changed branch, more than one matching PR, or mismatched PR text blocks the journey. - Keep transient failures safe. If observation fails after a write landed, that effect ID settles blocked and cannot retry. A newly confirmed effect ID can then observe the landed result and verify it without a second write.
- Stay narrow. Every call needs native TUI confirmation and a verified
private GitHub repository, and the tool cannot push to
mainormaster. Each Git or GitHub subprocess has a 15-second timeout and a 16 MiB output limit; a timeout or oversized output blocks and proves nothing either way. - Cover driver-owned calls only. Git and GitHub commands that a worker runs in its own shell are not intercepted.
Evidence. Crash tests kill the process before and after each push, PR
creation and PR update. They also cover a changed branch, multiple matching
PRs, mismatched PR text, and exact results that already landed despite local
drift. They use a local Git remote and a simulated GitHub endpoint, not a
live repository. The tool reuses the durable dispatch store and its owner
lock (see durable dispatch under Multi-agent communication). See the
outward effects section of docs/durable-persistence.md.
Planned:
- git workflow safeguards. Not packaged yet. The planned capability covers exact-file staging, native confirmation, post-confirmation drift checks, and protected-operation boundaries.
- assignment-aware Git journeys. Planned merge and protected-push flows bound to a verified assignment, so consequential Git operations carry their own recorded provenance.
Package integrity
Extensions that keep the installed set honest and the record controlled.
Planned:
- security and integrity scanning. Static scanning of MCP configs, agent skills, and extension packages for hardcoded secrets, prompt and shell injection, data-exfiltration endpoints, untrusted integrations, PII leakage, and OWASP/MCP threat families, with accept/redact/reject decisions. Built on the agent-scanner approach proven in Hillstar Orchestrator and an isolation environment.
- checkpoint storage lifecycle. Compression, deduplication, retention, and purging rules for capsule and index stores once a product ships, so session evidence has a managed lifetime instead of growing without bound.
- product knowledge graph. Semantic graph projection of a shipped product's checkpoints, decisions, and artifacts, so the record of what was built stays queryable after active development ends.
Each item lands here as its own extension when its scenario passes acceptance with all prohibited effects absent.
Portable repository contract
The templates/AGENTS.md file is a starting contract you can copy into any
repository that uses Pi agents. It asks for controlled tasks and realistic tests, and
treats agent reports as untrusted evidence. It never overwrites an existing AGENTS.md. Add your project rules below it.
Packaged skills
Methods your agent loads on request. A skill never grants authority.
The package registers native skills alongside the extensions. Invoke one with
/skill:<name>. Pi may load a skill description on its own; loading is not
approval to act, and no skill grants permission to merge, publish, install
or change a model route.
- Driver workflows.
tasks(session plan to durable board),pulse(Board Pulse),decision-to-spec(one reviewable assignment),harvest-lessonsandpublic-pr-wording. - harvest-lessons. Mines past corrections in an approved repository: PR
reviews, revert and fixup commits, failed CI and session logs. It groups
them into patterns, ranks them, and hands the top ones to
correct-pias guarded draft PRs. Itsagentic_harvest_lessonscollector is read-only and never writes files, posts or opens PRs. - public-pr-wording. Drafts PR titles and bodies in four sections, in the repository owner's first person, with no bot or model names and no local paths. The bundled lint enforces length caps and wording rules; your own names go in a personal config that is never committed.
- correct-pi. Turns an owner-selected recurring correction into a structural guard, then requires a check that catches a real past failure.
- pstack methods. The separate
pi-poteto-modepackage supplies the pstack skill ports. Install it separately if you need those methods.correct-piremains a native driver skill. - Packaged-skill checks. Public CI verifies skill frontmatter and package registration, then loads the packed artifact in a fresh consumer and checks for Pi skill diagnostics. This is release validation, not an install-time permission or security boundary.
The historical comparison of pstack ports remains in
docs/pstack-pi-ports-comparison.md; the driver no longer ships those ports.
Install
From npm:
pi install npm:@evoclock/pi-agentic-driver
Or from Git at the latest release tag (see the repo's tags for the current one; the npm badge above shows the live version):
pi install git:github.com/evoclock/pi-agentic-driver@<latest-tag>
Released extensions load independently.
For optional structural code search, see the separate public ast-sgrep fork. It is not bundled with or installed by Pi Agentic Driver. The Pi BigInt and host TypeBox corrections are on the fork's main; a follow-up Pi peer-range correction remains on upstream PR #36, not yet on the fork's main. These source changes have not been published as an npm package. The driver does not select or install a code-search provider.
Choose which package resources load
A normal install loads the package's declared extensions and skills. Use the object form in your Pi settings to select only the resources you need. For example, load two extensions:
{
"packages": [
{
"source": "npm:@evoclock/pi-agentic-driver",
"extensions": ["extensions/aidr.ts", "extensions/code-phage.js"]
}
]
}
To load one skill and no extensions, set extensions to an empty list:
{
"packages": [
{
"source": "npm:@evoclock/pi-agentic-driver",
"extensions": [],
"skills": ["skills/harvest-lessons"]
}
]
}
The same package can provide skills without extensions; there is no separate
skills-only package. Select another declared skill or omit skills to load all
of them. The package also includes the Herdr communication, lifecycle, and
dispatch extensions, the board and Tasks extensions, and linux-microvm.ts.
Use pi config to enable or disable individual resources from an installed
package. You are not required to use every extension.
From a clean agents branch based on main, provide private deny terms with --terms PATH, PUBLIC_SYNC_TERMS_FILE, config/public-sync-terms.local.json, or ~/.config/pi-agentic-driver/public-sync-terms.local.json, in that order. The scanner also reads private repository names from the existing repository registry. Missing local terms block the run. Existing public test fixtures have exact path-and-value-hash allowances in config/public-sync-fixture-allowances.json; all other secret matches block the run. The regenerated public lockfile has hashed, entry-scoped allowances for third-party dependency metadata; all other model or provider matches still block. Run python3 scripts/public_sync.py --public /path/to/public-checkout to inspect a dry-run report. The checked-in config/public-sync-exclusions.json filters private-only paths. Any sensitive content or excluded package.json file entry blocks the run; resolve it separately before retrying.
After a clean report, --apply --branch sync/agents-curated requires the source checkout at agents main with a clean tracked tree. It leases a fresh Treehouse worktree from the existing public checkout's main, copies the filtered tree, checks npm test and npm pack --dry-run, checks packed filenames, and makes one freshly authored commit. The script never pushes, creates remotes, or changes push URLs. Repeated clean dry runs are read-only; a no-change apply does nothing. Inspect the diff and packed contents independently before any owner-controlled public handoff. A failed apply leaves its leased worktree for inspection.
License
AGPL-3.0-only with author-attribution additional terms (Section 7(b)); see LICENSE. Commercial use, forks, and substantial modifications are permitted when all AGPL and attribution obligations are followed. A separate commercial licence is available for organisations requiring proprietary modifications or other terms incompatible with the AGPL.