# pi-amq Operator Guide

This document is the installed, version-matched source for `/pi-amq-guide [topic]` and the `guide` tool. Each topic is independently bounded before it enters model or UI context.

## Overview

pi-amq has two cooperating but independent bounded contexts. The AMQ transport makes durable agent mail native inside one pi session. The WorkerRuntime supervises local pi workers through immutable contracts, a durable ledger, hard budgets, leases, and evidence Gates. AMQ may remain dormant while local workers run.

The operating rule is: the agent owns strategy; the harness owns truth. The driver chooses decomposition, roles, and follow-up work. The runtime records accepted contracts and observable facts, enforces authority and ceilings, and never turns worker prose into completion truth.

Use `/pi-amq-guide` for this overview. Available topics are `tools`, `contracts`, `gate`, `budgets`, `fleetview`, `mail`, and `troubleshooting`.

## Tools

Worker tools are atomic:

- `spawn_worker` resolves a named role, accepts one bounded contract, and launches one supervised process after durable intent.
- `list_workers` reads authoritative projections, including state, Gate blockers, budgets, revisions, and stalls.
- `collect` records and returns candidates plus Gate facts; collecting is not accepting.
- `cancel` persists cancellation intent before signaling the owned process group.
- `steer` sends conversational input to an RPC worker without changing its contract.
- `revise_contract` records an immutable revision delivered at the next inference boundary.
- `guide` reads one topic from this installed document.

`cleanup_runs` is a separate workflow-lifecycle action, not a worker-addressing
verb. It defaults to a mutation-free size report. Deletion skips non-terminal,
ambiguous, active-worker, held-lease, and corrupt-lease runs; requires TUI
confirmation or explicit headless `yes=true`; rechecks under the current
supervisor fence; and persists an audit event outside the run directories before
removing any candidate. `/pi-amq-cleanup --older-than 7d` previews the same plan;
add `--delete` and, in headless mode, `--yes` to request deletion.

`workflow_doctor` and `/pi-amq-doctor` are read-only. They cross-check readable
run ledgers against PID/start/boot/executable identity, enumerate worker-session
leases, flag unreferenced session directories and corrupt records, and report
top-level workflow disk usage. Each finding contains argv-style inspection or
recoverable quarantine suggestions. Doctor never runs a suggested command or
changes workflow state.

AMQ tools cover send, reply, inbox/thread/status/receipt inspection, presence, exact claimed reads, and DLQ inspection. They are enabled according to dormant, send-only, or receiver-owning state. There is no pipeline, parallel block, retry loop, judge primitive, or scheduler API.

In TUI, `confirm_spawns` defaults to `multi-worker-only`: concurrent proposals from one driver tool batch open one editable launch preview. Use arrows and Tab to select workers and fields; role, task, live-catalog model, difficulty, and downward-only budget edits are available. Enter accepts all displayed contracts; Esc cancels all and ledgers or launches nothing.

## Contracts

Every accepted worker contract records a request key, goal, falsifiable acceptance criteria, hard constraints, all five worker budget dimensions, workspace grant, channel, side-effect policy, and context references. Tool callers should omit worker budget for ordinary tasks; when omitted, the runtime materializes the maximum run-safe defaults in the accepted contract. Context defaults to `fresh`. `context=fork` snapshots the driver session's current leaf into a separate child session file; launch preview shows its inherited entry/byte size and branch point, the immutable contract records the parent source and branch point, and the parent session is never changed. `fork` and `continue_worker_id` are mutually exclusive. Optional facts include report shape, deterministic acceptance check, and required human approval.

Named role declarations are markdown with strict frontmatter. Builtins are `scout`, `worker`, `reviewer`, `oracle`, and `researcher`. They supply charter prose and default tier, difficulty, and capabilities. Explicit difficulty and capabilities win. User declarations at `~/.pi/agent/pi-amq/roles/*.md` override builtins; a trusted project may override both at `.pi/pi-amq/roles/*.md`. Project declarations are not read when trust is absent.

The resolved role source and fingerprint become contract provenance. A capability request is never a grant: launch authority revalidates the actual child model, tools, cwd/worktree, trust, and scrubbed environment before provider work.

RPC contracts may request directional `message_worker:<workerId-or-role>` capabilities when the run objective and launch authority grant the base `message_worker` capability. The target is not ambient addressing: an exact worker ID must exist, while a role must resolve to exactly one current worker. Unknown, self, unauthorized, detached, stale-generation, and ambiguous targets fail closed. The child-only `message_worker` tool submits a bounded message plus required correlation to the supervisor. If the recipient is in inference, delivery waits for its generation-correlated `agent_settled`; the sender is never interrupted or echoed. The Ledger stores the message hash, grant, correlation, both endpoints, and pending/delivered/indeterminate observation in both worker projections. The body is deliberately memory-only: restart reconciliation changes an undelivered pending fact to `indeterminate` and never blindly replays it. Launch preview and the mirrored prompt capsule expose every peer grant.

`fallback_models` is an ordered chain of at most four distinct live-catalog alternatives. The supervisor advances only after a child launch-validation refusal or a classified provider auth, quota/rate-limit, or capacity failure. Process creation, protocol, tool, repository, and business failures never trigger fallback. Every attempt records the actual model and the preceding reason before launch; exhausted chains remain failed. Launch preview shows the chain, while Fleet, `list_workers`, and `collect` expose the active model, attempted models, and `tier_degraded` state.

Every run has one deterministic private `artifacts/` directory beside its
ledger. The runtime creates it with mode `0700`, injects it as the first
`artifact` context ref in every worker contract, and repeats it in the immutable
prompt capsule. Workers should write cross-worker handoff files there and cite
their exact paths; ordinary workspace files remain separate. The directory is
retained until explicit run cleanup.

Launch-preview edits mutate proposal state only. Immutability starts when Enter accepts and the worker intent reaches the ledger. The accepted contract records `source`, `confirmSpawns`, preview disposition, and the exact human-edited field names.

## Gate

The Gate, not a model statement, owns legal completion. `collect` observes evidence; it does not set `done`. A successful candidate remains unaccepted until all declared predicates pass: evidence exists, structured report shape matches when declared, the acceptance check exits zero when declared, human approval is positive when required, effects are certain, and budgets are not exceeded.

Attempt states are `pending`, `running`, `blocked`, `ambiguous`, `done`, `failed`, and `cancelled`. Every RPC child receives the built-in `wait_for_input` tool independently of repository capabilities. Its non-empty `{reason, correlation}` declaration is fenced to the current attempt generation, written to the Ledger, and moves `running -> blocked` through the Gate. Silence, a natural-language question, `message_end`, and a model claim are not wait facts. A blocked attempt returns to running only when `steer.correlation`, `revise_contract.correlation`, or a directionally granted peer-message correlation exactly matches the active wait. Missing or mismatched correlations fail before input reaches the child. Blocked workers do not record silent or no-progress stall observations, and Fleet plus worker tools show the wait reason, correlation, status, and satisfying input. `ambiguous` requires explicit reconciliation evidence. Terminal facts and cancellation follow the exported transition table rather than prose inference.

## Budgets

Every budget value is either `limited(value)` or `unlimited`. Shipped finite run ceilings are 8 workers, concurrency 4, depth 3, 16 attempts, one hour, 500,000 tokens, USD 50, and 64 MiB output. Accepted worker contracts record attempts, wall-clock time, tokens, cost, and output bytes. For ordinary spawns, omit the worker budget in the tool call: wall-clock follows the remaining run deadline while token, cost, and output capacity use the maximum remaining run-safe values. An explicit worker budget may take a smaller share but must still fit the run reservation.

Unlimited run dimensions require an explicit `--worker-unlimited=<dimensions|all>` declaration and TUI confirmation before run creation. Headless unlimited requests fail closed. Unlimited never flows implicitly from a run into a worker. Usage is monotonic; crossing a worker ceiling records durable cancellation before signaling.

## FleetView

FleetView appears below the editor only after the worker runtime has at least one authoritative worker row; an ordinary pi session does not reserve empty Fleet space. Once visible, it projects the main session and workers with compact role, model, lifecycle, spend, and relative-activity rows. The detail overlay reads the current projection and bounded live session tail.

RPC workers may receive generation-fenced steer input and directionally granted peer input. Peer messages wait for the recipient inference boundary and their pending count is visible in Fleet/tool projections. A blocked row displays its exact typed-wait reason and correlation; operators must copy that correlation into the intended steer or revision. `x,x` requests cancellation and is also generation-fenced. JSON workers are one-shot and cannot be steered, receive peer grants, or declare typed waits. Fleet actions report requested outcomes; the process and Gate observations remain authoritative. Stall markers are running-only facts—the runtime never auto-nudges, retries, steers, or cancels from them.

## Mail

AMQ uses verified physical root and handle identity, one receiver lease, durable bridge journal, priority-aware delivery, exact per-envelope reply provenance, receipts, and a terminal DLQ. Ordinary workers are send-only and never compete for the receiver lease. Use exact envelope IDs when replying.

The extension can remain dormant without blocking WorkerRuntime. Dormant transport stays out of the persistent TUI footer; `/amq status` and RPC status retain its exact diagnostics. `/amq bind` performs confirmed onboarding or binds a verified existing context. `/amq status|inbox|pause|resume|ingest|takeover|dlq|trace|doctor` exposes operator actions. Authorized fresh-session mail automatically replaces the current session (pi >= 0.84.2 is required); the journal marks it `injected` once the kickoff becomes disk-visible in the replacement session, which pi may flush slightly after delivery — that in-between state is a normal `pending` record with its target already committed, not a failure. If the replacement is cancelled, its command dispatch never completes, or the kickoff cannot be found in either the replacement session or on disk, it stays pending and `/amq ingest` visibly promotes it into the current session instead.

## Troubleshooting

- If worker tools report that the runtime is unavailable, inspect the first run-budget or supervisor-lease error shown by the session. An ordinary `/reload` adopts the process-global runtime core and keeps live worker control. If the diagnostic says reload adoption was refused or the supervisor is held by the current PID, fully restart Pi once; this is expected after upgrading from a version that created the lease without the registry. Do not delete lease state to force ownership.
- If a model cannot be selected, inspect the live catalog guidance. Role names do not create models. Remove an invalid explicit model or use a supported difficulty.
- If a role is unknown or malformed, inspect the matching user declaration and, only for a trusted project, the project declaration. Overrides fail closed instead of silently falling back.
- Configure launch confirmation in `~/.pi/agent/pi-amq/config.json` with `{"confirm_spawns":"on|multi-worker-only|off"}`; a trusted project may override it in `.pi/pi-amq/config.json`. `on` always requires TUI, `multi-worker-only` requires TUI only for a grouped multi-worker proposal, and `off` skips preview. Headless requests that require preview fail before ledger or process effects.
- If an attempt is `ambiguous`, obtain reconciliation evidence; do not infer exit from a missing PID or result file.
- If AMQ is dormant, local workers still work. Bind only when messaging is needed.
- If mail is staged because fresh-session switching is unavailable, use `/amq ingest`; do not claim that a replacement occurred.
- Preview old workflow storage with `/pi-amq-cleanup --older-than <duration>` before deletion. TUI deletion always asks for confirmation even when `--yes` is present; headless deletion requires both `--delete` and `--yes`.
- Use `/pi-amq-doctor` to inspect workflow health. Re-check the exact PID identity shown by its `ps` argv before any process action; quarantine suggestions are recoverable `mv` operations and are never executed automatically.
- Use `npm test` in the installed source checkout for the fault-sensitive suite. The authoritative architecture and compatibility details remain in `docs/design.md`.
