@evoclock/pi-agentic-driver

Guardrail extensions for Agentic Driver: advisory review, bounded Herdr communication, and guarded worker lifecycle.

Packages

Package details

extensionskill

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_communication for bounded exchanges.
  • Unattended spawns pass authority.ledgerId for 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, and TaskUpdate as 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. /tasks provides descriptions, active forms, and internal-task markers without mutating the plan.
  • Make durable work deliberate. TaskPromote never 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_evidence structures 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_request is 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. See docs/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.md board.
  • 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_PROFILE environment 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, or AGENTIC_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:sqlite module. 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:8787 and 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 security lookup. 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 busy instead 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.json first, then the same file in the active Pi profile under PI_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 delivery action 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.json before 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 models or roles list on a ledger grant as any model or role; a missing list still fails closed;
  • uses fixed argv with shell: false and no arbitrary Herdr or shell surface;
  • returns explicit pane_created, tab_created, or agent_started partial states when only part of the operation succeeds; and
  • never retries, moves, closes, or deletes created state automatically.

A role-labelled worker spawned in a right-hand pane

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 maxSteps steps (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 journeys action 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 ps cannot 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.

  1. 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.
  2. Run /agentic-isolation-enable and confirm.
  3. 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-only is 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-review is opt-in. An agent may run a plain gh pr merge <number or URL> only when every check on the PR head has passed and agentic_merge_review_record holds 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 mergePullRequest mutation, and writes to branch protection or rulesets. A refusal starts with pi-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-remote and gh api and 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 main or master. 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-lessons and public-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-pi as guarded draft PRs. Its agentic_harvest_lessons collector 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-mode package supplies the pstack skill ports. Install it separately if you need those methods. correct-pi remains 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.