Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ jobs:
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- run: ./tests/install.sh
- run: ./tests/claude-smoke.sh
35 changes: 16 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,20 @@ runs each task through project checks, and produces one traceable commit per
completed task. Repeated failures, missing credentials, and unresolved product
decisions return control to the operator instead of retrying forever.

> **Pre-release:** the orchestration contract may change before `v0.1.0`. A
> reproducible public example run is still required before launch.
## Public proof run

## Output shape
![Peter public proof run](docs/launch-run/peter-launch.gif)

This is illustrative output, not a benchmark or completed public run:
Peter built a complete reading-list vertical slice from one contract in a
[pinned public fixture](https://github.com/robertkeus/peter-launch-fixture/tree/ed3243ce70340eab73ed20d3956dde7efc14f64b):
3 planned tasks completed, 0 blocked, 4 audit findings filed as backlog, and 0
human interventions. Final gates were 33/33 unit/integration tests and 9/9 E2E;
the full-scope security and UI audits passed 8/10 and 9/10 after using their two
bounded repair loops. The run took 1:27:35 and Claude Code reported $27.63.

```
> /peter checkout flow with Stripe test mode

epic/checkout-flow · 9 tasks · draining unattended

$ git log --oneline epic/checkout-flow
f3a91c2 task-9: e2e — happy path + declined card
8d02b4e task-8: checkout UI against the fixed API contract
… every commit: gates green, audits pass
```
Read the [full reproducible run](docs/launch-run-template.md), inspect the
[baseline-to-result diff](https://github.com/robertkeus/peter-launch-fixture/compare/ed3243ce70340eab73ed20d3956dde7efc14f64b...9d01a0aba390948f9e99beaeeca961b5c0a29f73),
or open its [work graph and audit evidence](https://github.com/robertkeus/peter-launch-fixture/tree/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list).

## How it works

Expand Down Expand Up @@ -165,12 +162,12 @@ tests/install.sh installer integration coverage

## Requirements and limitations

- A current Claude Code release with custom skills and subagents, plus Git and
Bash 3.2 or newer. The installer targets macOS and Linux; native Windows is
not tested.
- Claude Code 2.1.228 or newer with custom skills and subagents, plus Git,
Node.js with `npx`, Chrome, and Bash 3.2 or newer. The installer targets macOS
and Linux; native Windows is not tested.
- The builders select Sonnet and the auditors select Opus. Your Claude plan must
provide those models. UI audits additionally require the `Claude_Browser` MCP
tools named in `agents/ui-auditor.md`; without them the UI verdict is not run.
provide those models. The UI auditor starts pinned Playwright MCP 0.0.79 with
`npx`; its first run may download that package.
- Peter is prompt-level orchestration, not an operating-system sandbox. Run it
only in repositories and environments you are willing to let Claude Code
modify.
Expand Down
17 changes: 11 additions & 6 deletions agents/ui-auditor.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
---
name: ui-auditor
description: Read-only WCAG 2.2 level AA and visual-fidelity audit of a running app. Drives the browser, inspects the accessibility tree, checks contrast and keyboard operability, screenshots each route at each breakpoint, and returns a structured verdict. Never fixes anything. Delegate to this after machine gates pass in the /peter skill, or whenever rendered UI needs an accessibility or pixel bar.
tools: Read, Grep, Glob, Bash, mcp__Claude_Browser__navigate, mcp__Claude_Browser__read_page, mcp__Claude_Browser__computer, mcp__Claude_Browser__find, mcp__Claude_Browser__resize_window, mcp__Claude_Browser__get_page_text, mcp__Claude_Browser__read_console_messages, mcp__Claude_Browser__preview_start
tools: Read, Grep, Glob, Bash, mcp__playwright__*
model: opus
mcpServers:
- playwright:
type: stdio
command: npx
args: ["-y", "@playwright/mcp@0.0.79", "--headless", "--browser", "chrome", "--isolated"]
---

You audit a **running** app against WCAG 2.2 level AA and the visual reference.
Expand All @@ -19,16 +24,16 @@ Steps:
2. Start or navigate to the app. Audit the rendered page — source review alone
cannot judge contrast, focus, or reflow.
3. For each route in scope, at 320, 768, and 1280px:
- `read_page` for the accessibility tree — names, roles, heading order,
- `browser_snapshot` for the accessibility tree — names, roles, heading order,
landmarks, labels.
- Tab through the whole page: every interactive element reachable, focus
- Tab through the whole page with `browser_press_key`: every interactive element reachable, focus
visible, order logical, no trap, focus not obscured by sticky elements (2.4.11).
- Measure contrast on text and UI boundaries in every state and both themes.
- Measure contrast on text and UI boundaries with `browser_evaluate` in every state and both themes.
- Check target sizes ≥24×24px (2.5.8) and drag alternatives (2.5.7).
- Screenshot as evidence.
- Capture evidence with `browser_take_screenshot`.
4. Compare against the visual reference: spacing, type scale, color, states,
breakpoints, layout shift.
5. Check the console for errors that indicate broken behavior.
5. Check `browser_console_messages` for errors that indicate broken behavior.

Rules:
- **You have no write tools, and `Bash` is not an exception.** Use it to start
Expand Down
14 changes: 7 additions & 7 deletions docs/launch-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
- [x] Dry-run, uninstall, drift detection, and installer integration tests exist.
- [x] README distinguishes bounded autonomy from unconditional hands-off operation.
- [x] Limitations and contribution instructions are public.
- [ ] Run Peter end-to-end against a small public repository at a pinned commit.
- [ ] Complete `docs/launch-run-template.md` with unedited observed results.
- [ ] Publish the work graph, commits, gate logs, human interventions, and cost data.
- [ ] Record a short terminal demo from the same reproducible run.
- [ ] Replace the illustrative README transcript with the public run.
- [ ] Confirm the documented Claude Code version on a clean account or machine.
- [ ] Create and smoke-test the `v0.1.0` release archive.
- [x] Run Peter end-to-end against a small public repository at a pinned commit.
- [x] Complete `docs/launch-run-template.md` with unedited observed results.
- [x] Publish the work graph, commits, gate logs, human interventions, and cost data.
- [x] Record a short terminal demo from the same reproducible run.
- [x] Replace the illustrative README transcript with the public run.
- [x] Confirm the documented Claude Code version on a clean account or machine.
- [x] Create and smoke-test the `v0.1.0` release archive.

## GitHub metadata

Expand Down
103 changes: 69 additions & 34 deletions docs/launch-run-template.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,98 @@
# Peter launch run

Status: **not yet run**. Replace every placeholder with observed data; do not
publish this file as evidence while any result field is incomplete.
Status: **complete**. This records the first public, reproducible Peter proof
run. Observed failures and unresolved findings are retained.

## Environment

| Field | Observed value |
|-------|----------------|
| Peter commit | `<full SHA>` |
| Target repository and commit | `<public URL and full SHA>` |
| Claude Code version | `<version>` |
| Model | `<model>` |
| Operating system | `<name and version>` |
| Started / finished | `<UTC timestamps>` |
| Peter commit | [`6f710ea91f5720b89134efb58880788a97393957`](https://github.com/robertkeus/peter/commit/6f710ea91f5720b89134efb58880788a97393957) |
| Target repository and commit | [`robertkeus/peter-launch-fixture@ed3243ce70340eab73ed20d3956dde7efc14f64b`](https://github.com/robertkeus/peter-launch-fixture/tree/ed3243ce70340eab73ed20d3956dde7efc14f64b) |
| Claude Code version | `2.1.228 (Claude Code)` |
| Models | parent/builders: `claude-sonnet-5`; auditors: `claude-opus-5[1m]` |
| Operating system | macOS 26.5.1 (25F80), arm64 |
| Started / finished | 2026-08-12 13:59:21.957Z / 15:26:57.279Z |

## Goal

Exact prompt:

```text
<goal passed to /peter>
```
The [complete, exact prompt](launch-run/prompt.md) specified the API,
persistence, UI, accessibility, visual reference, audit scope, and gate suite.
It explicitly supplied every product decision and required autonomous operation
without clarification.

Project gate commands:

```text
<unit, typecheck, lint, build, E2E, and audit commands>
npm test
npm run typecheck
npm run lint
npm run build
npm run e2e
```

## Results

| Metric | Observed value | Evidence |
|--------|----------------|----------|
| Elapsed time | `<duration>` | `<transcript timestamps>` |
| Tasks completed / blocked / discovered | `<counts>` | `<graph link>` |
| Commits produced | `<count>` | `<git log link>` |
| Gate failures repaired | `<count>` | `<redacted log links>` |
| Human interventions | `<count and reasons>` | `<transcript links>` |
| Input / output tokens | `<reported values or unavailable>` | `<source>` |
| Reported cost | `<value or unavailable>` | `<source>` |
| Final test result | `<command and result>` | `<CI or log link>` |
| Security / UI verdict | `<result or not run with reason>` | `<artifact links>` |
| Elapsed time | 1:27:35.322 wall time; 1:26:26.435 API duration | [event transcript](launch-run/transcript.md) |
| Tasks completed / blocked / discovered | 3 / 0 / 4 | [graph](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/graph.jsonl) |
| Commits produced | 8 after the pinned baseline | [comparison](https://github.com/robertkeus/peter-launch-fixture/compare/ed3243ce70340eab73ed20d3956dde7efc14f64b...9d01a0aba390948f9e99beaeeca961b5c0a29f73) |
| Gate failures repaired | 4 failing audit verdicts repaired in bounded loopbacks; 1 stale E2E assertion routed to T3 and repaired | [transcript](launch-run/transcript.md) |
| Human interventions | 0 | [transcript](launch-run/transcript.md) |
| Input / output tokens | 924 direct input / 402,985 output; 33,306,153 cache-read and 1,500,635 cache-creation tokens | [usage](launch-run/usage.md) |
| Reported cost | $27.63309410 | [usage](launch-run/usage.md) |
| Final test result | 33/33 unit/integration; typecheck, lint, and build clean; 9/9 E2E | [independent repeat](launch-run/gates.md) |
| Security / UI verdict | pass 8/10 with 3 open findings / pass 9/10 with 1 open finding | [security](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/security.eson), [UI](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/ui.eson) |

## Artifacts

- Work graph: `<link to graph.jsonl>`
- Specification: `<link to spec.md>`
- Commit history: `<link to compare or branch>`
- Gate logs: `<links>`
- Audit returns: `<links or prerequisites unavailable>`
- Terminal recording: `<link>`
- [Work graph](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/graph.jsonl)
- [Specification](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/spec.md)
- [Commit history](https://github.com/robertkeus/peter-launch-fixture/compare/ed3243ce70340eab73ed20d3956dde7efc14f64b...9d01a0aba390948f9e99beaeeca961b5c0a29f73)
- [Gate results](launch-run/gates.md)
- [Initial and final security evidence](https://github.com/robertkeus/peter-launch-fixture/tree/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list)
- [Final UI audit](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/ui.eson)
- [Terminal demo](launch-run/peter-launch.gif)
- [Final report](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/report.md)

## Failures and limitations

Record what Peter got wrong, work it could not complete, misleading status,
unexpected cost, and every place a person intervened. Do not remove failed
attempts that materially affect the result.
Security initially failed 4/10 with eight findings and failed its re-audit 6/10
with five findings. UI initially failed 6/10 with eight findings and failed its
re-audit 8/10 with two findings. Both used the allowed two repair loopbacks and
then passed; the transcript keeps that progression.

Four findings remain, deliberately visible as graph tasks T4–T7:

- Medium: no per-client rate limiting and an unpaginated full-list response.
- Medium: an oversize streaming request returns 413 but its connection remains open.
- Low: the in-memory cache does not reconcile out-of-band file edits.
- Low: the heading overflows at 320px only when text is also scaled to 200%.

No work was blocked and Peter did not misreport the final gate state. Total cost
was $27.63—higher than a one-shot prompt because this run performed repeated
machine gates plus independent security and UI audits.

## Reproduce

Provide the exact checkout, installation, target setup, and `/peter` commands.
State any credential or paid-service requirement without publishing secrets.
```bash
git clone https://github.com/robertkeus/peter.git
cd peter
git checkout 6f710ea91f5720b89134efb58880788a97393957
./install.sh --dry-run
./install.sh
npx --yes @anthropic-ai/claude-code@2.1.228 --version

cd ..
git clone https://github.com/robertkeus/peter-launch-fixture.git
cd peter-launch-fixture
git checkout ed3243ce70340eab73ed20d3956dde7efc14f64b
npx --yes @anthropic-ai/claude-code@2.1.228
```

At the Claude Code prompt, paste the exact contents of
[`launch-run/prompt.md`](launch-run/prompt.md). The run requires a Claude plan
with Sonnet and Opus access, authenticated network access, Git push access to a
fork or clone you own, Node.js, Chrome, and Playwright's pinned MCP package.
Do not reuse the published branch name unless you first delete or rename it.
23 changes: 23 additions & 0 deletions docs/launch-run/gates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Independently repeated gates

After Peter reported the epic complete, the five project gates were run again
from the clean public epic branch at
[`9d01a0aba390948f9e99beaeeca961b5c0a29f73`](https://github.com/robertkeus/peter-launch-fixture/commit/9d01a0aba390948f9e99beaeeca961b5c0a29f73).

Observed on 2026-08-12 at 15:27 UTC:

| Command | Result |
|---------|--------|
| `npm test` | pass: 33, fail: 0, duration: 358.409542 ms |
| `npm run typecheck` | pass, no diagnostics |
| `npm run lint` | pass, no diagnostics |
| `npm run build` | pass, fixture build complete |
| `npm run e2e` | pass: 9, fail: 0, duration: 3.6 s |

Peter's own installer and the exact Claude Code 2.1.228 smoke test also passed on
fresh [Ubuntu and macOS GitHub-hosted runners](https://github.com/robertkeus/peter/actions/runs/31613021955).

The run itself executed the same five-gate sequence at baseline, during task
iterations, and at epic close. Its committed result and acceptance-criterion
map are in the
[`report.md`](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/report.md).
Binary file added docs/launch-run/peter-launch.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions docs/launch-run/prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Launch proof prompt

This is the complete prompt passed to `/peter` for the public proof run.

```text
/peter Build and verify a complete reading-list vertical slice in this pinned public fixture.

The contract is complete; do not ask clarification questions.

API and persistence:
- GET /api/books returns 200 JSON `{ "books": Book[] }`.
- POST /api/books accepts JSON `{ "title": string, "author": string }` and returns 201 with the created `Book`.
- A Book has `id`, trimmed `title`, trimmed `author`, and ISO-8601 `createdAt`.
- Reject a missing or non-JSON content type, malformed JSON, unknown fields, empty values, values over 100 characters, and bodies over 16 KiB with a safe 4xx JSON response.
- Persist to the JSON file named by `DATA_FILE`, defaulting to `data/books.json`. Writes must be atomic, concurrent creates must not lose data, and a missing file starts as an empty list.

Rendered UI:
- Replace the fixture-only page with a usable reading list that loads existing books, adds a book, filters the visible list by title or author without another request, preserves data after reload, exposes loading/empty/error/success states, and never injects user values as HTML.
- Use native labels and controls, an announced status region, field-level errors, visible keyboard focus, logical heading order, and 44px controls. It must reflow without horizontal scrolling at 320, 768, and 1280px.
- Confirmed visual reference: warm white `#faf8f3` page, ink `#1f2933`, teal `#006b5f` primary accent, restrained red `#a61b1b` errors, system sans-serif type, large editorial heading, cards with subtle borders and 12px corners, one column below 768px and a form/list split at 768px and above. No animation is required.

Verification and scope:
- Preserve the health endpoint and its test.
- Add unit/integration tests for the API, validation, persistence, atomic/concurrent creates, and safe output.
- Add Playwright E2E coverage for empty state, add, filter, invalid input, persistence after reload, keyboard use, and 320px reflow. Playwright is configured to use installed Chrome.
- Run `npm test`, `npm run typecheck`, `npm run lint`, `npm run build`, and `npm run e2e` at baseline, each iteration, and close.
- Security audit applies because the feature accepts external input and writes data. UI audit applies to `/`; use `PORT=43100 DATA_FILE=/tmp/peter-launch-audit-books.json npm run dev`, base URL `http://127.0.0.1:43100`, and reserve ports 43100-43109 for the UI auditor.
- Treat the visual reference above as approved. Work autonomously until Peter's Done bar is met. Keep every failed gate and audit result in the run evidence.
- Commit one change per graph task, push only the epic branch, and do not merge it.
```
33 changes: 33 additions & 0 deletions docs/launch-run/render-demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -euo pipefail

here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
work="$(mktemp -d)"
trap 'rm -rf -- "$work"' EXIT

frames=(
'13:59:21|$ /peter build a reading-list vertical slice|Pinned public fixture · Claude Code 2.1.228'
'14:00:09|✓ baseline gates|test · typecheck · lint · build · e2e'
'14:02:09|epic/reading-list · 0/3|T1 backend → T2 UI → T3 E2E'
'14:12:16|security audit · FAIL 4/10|8 findings · 2 bounded repairs'
'14:36:04|✓ T1 · security PASS 7/10|1e130d6 · 3 findings filed'
'14:53:58|UI audit · FAIL 6/10|8 findings · 2 bounded repairs'
'15:17:21|✓ T2 · UI PASS 9/10|24fccae · 1 finding filed'
'15:22:33|✓ T3 · E2E 9/9|69d0ca7 · all parent gates green'
'15:26:57|✓ EPIC DONE · 3/3|33/33 tests · 9/9 E2E · 0 interventions'
)

for i in "${!frames[@]}"; do
IFS='|' read -r stamp title subtitle <<<"${frames[$i]}"
number="$(printf '%03d' "$i")"
progress="$((856 * (i + 1) / ${#frames[@]}))"
sed -e "s|{{STAMP}}|$stamp|g" -e "s|{{TITLE}}|$title|g" -e "s|{{SUBTITLE}}|$subtitle|g" -e "s|{{PROGRESS}}|$progress|g" \
"$here/terminal-frame.svg" >"$work/$number.svg"
rsvg-convert -w 960 -h 540 "$work/$number.svg" -o "$work/$number.png"
done

ffmpeg -hide_banner -loglevel error -y -framerate 1 -i "$work/%03d.png" \
-vf "fps=12,scale=960:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=96[p];[s1][p]paletteuse=dither=bayer" \
"$here/peter-launch.gif"

echo "$here/peter-launch.gif"
Loading