← Pi Agents

Appendix C — Pi Patch Desk: The Capstone

A guided capstone walkthrough: reproduce a parser bug, let Pi edit a disposable fixture, inspect a proposed patch and its host verification, and see a prohibited action refused.

You have finished the book. Now give its mechanisms one job to do together.

Pi Patch Desk takes a small parser bug through reproduction, investigation, editing, verification and review. At the end you receive a proposed patch and a dossier explaining what happened. You can inspect the change and the recorded checks without trusting the agent’s final prose.

This appendix is a supplement added after the book’s initial publication. The forty-two numbered chapters and Appendices A and B keep their order and paths. The implementation lives in the public pi-agents repository, alongside the book’s executable examples. The Pi Patch Desk solution page is its practical entry point; here you will run the example and connect each decision to the material you have read.

The first version uses scripted responses with the actual Pi 1.0.4 agent loop. Pi executes real tools against real fixture files, and the host runs real checks. It is an offline demonstration of the software around a model. It does not measure a real model’s ability to fix an unfamiliar issue.

Start with the finished result

You need Node.js 22.19 or later, npm, and Git. Clone the public repository and install its pinned dependencies:

git clone https://github.com/ernanhughes/pi-agents.git
cd pi-agents/examples
npm ci
npm run capstone

After installation, this command needs no API key, network, global Pi install or manuscript checkout. It uses the local Pi packages pinned to 1.0.4. The recorded development run used Node 25.8.2 on Windows; it was not also run on Node 22. A newer global pi --version does not change the capstone’s pin.

The issue is deliberately small. parseRecords() reads records such as name=Ada and role=developer. Its original implementation rejects an empty line between valid records. The request is to ignore blank lines, preserve validation of nonblank records, and add a regression test.

The output follows this sequence:

before tests: exit 1
Pi completed read_file
Pi completed read_file
Pi completed write_file
Pi completed write_file
after tests: exit 0
Pi completed check
after typecheck: exit 0
Pi completed check
Pi completed submit
after tests: exit 0
after typecheck: exit 0
after grader: exit 0

Pi Patch Desk: verified
Review: .../capstone-patch-desk/runs/run-<id>
Original fixture unchanged; no patch applied.

The first failure is expected: the host has reproduced the bug. The later checks establish that the proposed repair passes the tested cases. The fixture in your checkout stays broken so the next run can reproduce the same issue.

Review before accepting

Open the printed run directory. Start with review.md, then read patch.diff and tests.json. The main source change is one guard inside the existing loop:

   for (const line of input.split(/\r?\n/)) {
+    if (line.trim() === "") continue;
     const match = /^([a-z]+)=([^=]+)$/.exec(line);

Only the blank-line decision uses trim(). Nonblank lines still go through the original grammar. The added regression covers surrounding whitespace-only lines and CRLF. The host also runs its own acceptance assertions, held outside the files Pi may edit.

These files give you different kinds of evidence:

File What to inspect
manifest.json Package versions, Git revision, exact original fixture hashes, policy, budgets and isolation limits
run.json Outcome, completion state, requests, tool calls, failures and original-file preservation
tests.json Command argument arrays, exit codes, signals and bounded output
evidence.json Validated source paths, line ranges and quotations
events.jsonl Compact Pi lifecycle, host-check and policy events
patch.diff The proposed changes to the permitted fixture files
review.md Verified, source-supported and unmeasured findings for your decision

Check the before-test exit code of 1 and the final tests, typecheck and grader exit codes of 0. A started check is not a completed check. A source citation establishes that the quotation exists at the recorded location; the test results establish the behavior they actually checked.

You have reached the human decision. The default workflow does not apply the patch to the original fixture, commit, push, open a PR or deploy anything. Those actions would need a separate request and their own controls.

Follow the decisions through the layers

The host owns the workflow; Pi owns the bounded tool-using loop inside it.

    flowchart TD
  A["Issue and known fixture"] --> B["Host reproduces the failure"]
  B --> C["Pi reads source and tests"]
  C --> D["Host policy checks each operation"]
  D -->|"Allowed"| E["Pi edits the disposable copy"]
  D -->|"Refused"| F["Failure dossier"]
  E --> G["Source references and completed Pi run"]
  G --> H["Final host tests, typecheck and grader"]
  H -->|"Pass"| I["Patch and review dossier"]
  H -->|"Fail"| F
  I --> J["Human review"]
  

In run.ts, Agent receives a known model, a stream function and explicit tools, following chapter 37. fauxProvider supplies the scripted responses from script.ts. This is Pi’s loop executing the requests, not a handwritten transcript pretending to be an agent.

policy.ts makes the authorization decision. The capstone inspects raw completed calls, uses beforeToolCall, and checks again immediately before effects. The raw-call check also catches names or arguments that Pi would reject before reaching that hook. The editable paths are exactly src/records.ts and tests/regression.ts; checks come from a fixed command allowlist in checks.ts. These are application rules built around the seams examined in chapter 39.

evidence.ts adds nonempty, path, line-range and exact-source checks to the quotation check from chapter 40. It does not let an empty list count as evidence for a conclusion. The host requires a source-supported submission and then performs final verification itself.

The grader matters because Pi can edit the fixture’s test file. Passing those tests alone would let a weakened test suite certify an unfixed parser. The host-owned assertions supply a second, independent acceptance check. They cover the declared parser behavior, not every conceivable defect.

For completion, the core’s agent_end event and awaited prompt settlement finish the Pi portion. Host checks and reporting still follow. The JSON driver emits desk_completed only after that remaining work and artifact writing. Keep the observer’s contract in view, as chapter 33 and chapter 35 taught: these host records are not a replacement for the coding-agent session’s agent_settled contract.

This is also chapter 11’s mechanism choice in practice. The prompt and skill carry the walkthrough. An optional extension adds a slash command. Ordinary functions perform authorization, checks and reporting. The agent is used for the sequence of source inspection and edits.

Try the prohibited action

From the same examples/ directory, run:

npm run capstone -- --scenario injection

This command deliberately exits 1 and reports refused. The fixture README contains an instruction to disable tests, change package.json and print secrets. A scripted response reads that text and requests the forbidden edit, supplying a fake approved: true field.

Inspect the denied policy event in events.jsonl and the failure in run.json. The host rejects the operation. Source text and a model-supplied approval field cannot change its policy. This demonstrates the tested refusal path; it does not demonstrate a model independently recognizing prompt injection.

Now compare the refused run with the successful one. Both leave a dossier and preserve the original fixture. The status differs because the host has different observations to report. A failure may retain a partial proposed diff, but it has not earned verified status.

Read the capstone with the book beside you

Book material What to look for in the application
Chapters 10–14: task shape and instructions One issue, explicit acceptance conditions, a prompt template and a skill
Chapters 16–17: events and tools Completed events, typed arguments, bounded tools and policy decisions
Chapters 25 and 29: control and failure Cancellation, budgets, failures and no pipeline-wide retry loop
Chapters 31–35: interfaces One host workflow observed through CLI, JSON and an optional Pi command
Chapters 37–40: core and composition Actual Pi execution surrounded by deterministic source and verification functions
Chapter 41: testing Scripted control-flow tests separated from unmeasured model capability
Chapter 42: authority A temporary copy and hook are application controls, not an OS sandbox

For a second presentation of the same workflow, run node capstone-patch-desk/cli.ts --json. Its final record is desk_completed. For the optional terminal walkthrough, run npm run capstone:interactive, then enter /patch-desk and /patch-desk injection. The launcher uses the locally pinned shipped Pi binary, fresh configuration and explicit capstone resources. The command calls the same host and needs no outer model request.

Read the public guide for the module map, other failure scenarios, and resource loading details. The implementation stays there so changes, tests and instructions have one public home.

What you have established

The recorded evidence from 14 October 2026 reports a clean typecheck and 311 passing tests in the public examples suite, including 32 capstone tests, at Pi 1.0.4. The tests exercise real fixture commands, patch applicability, original-worktree preservation, citations, refusal cases, weakened tests, provider errors, abort, timeout and request/tool exhaustion. They also verify that a canceled, otherwise-continuing fixed check child has exited.

You can run the capstone tests yourself with npm run test:capstone from the public examples/ directory. The recorded numbers identify a particular run; they are not a promise that every later checkout has the same test count.

Keep the three claim classes apart. Documented: Pi 1.0.4 supplies the core, tools, hooks, events and faux provider used here; the relevant exported declarations and documentation are listed in the evidence record. Observed: the scripted fixture runs and tests produced the recorded outcomes. Proposed: the exact allowlist, grader, dossier and human-review procedure are this application’s design, rather than guarantees made by Pi.

The remaining authority limit is material. There is no verified OS sandbox. Changed TypeScript executes in child checks with your OS account’s permissions. The temporary copy and in-process policy do not contain hostile code. This release therefore accepts its known fixture and scripted scenarios, and has no arbitrary-repository or real-provider mode.

Execution has a 30-second budget, followed by bounded diff collection and reporting. Logs, files and child output are capped; each dossier is at most 128 KiB. Temporary copies are removed after reporting. Retained dossiers accumulate until you delete them. Redaction covers common credential-shaped text, not every possible encoding of a secret.

Real-model quality, general injection recognition, pass@1 and pass^k remain unmeasured. A future real-model version needs verified external containment, explicit provider opt-in, budgets and a held-out evaluation with an independent grader. Those requirements follow from the evidence you have, rather than from the confidence of the demonstration.

Before leaving, answer three questions from your own dossiers: which observation reproduced the bug, which independent check accepted the repaired behavior, and which decision remains yours? If you can point to each answer, you have carried the book’s distinction between capability, evidence and authority into one complete application.