diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 00db232..34dbda4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,3 +16,4 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - run: ./tests/install.sh + - run: ./tests/claude-smoke.sh diff --git a/README.md b/README.md index ecd8d9e..73be3f6 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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. diff --git a/agents/ui-auditor.md b/agents/ui-auditor.md index 2b0921b..b0bd8c2 100644 --- a/agents/ui-auditor.md +++ b/agents/ui-auditor.md @@ -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. @@ -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 diff --git a/docs/launch-checklist.md b/docs/launch-checklist.md index 551c8b3..9a7b015 100644 --- a/docs/launch-checklist.md +++ b/docs/launch-checklist.md @@ -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 diff --git a/docs/launch-run-template.md b/docs/launch-run-template.md index bb64e76..defe112 100644 --- a/docs/launch-run-template.md +++ b/docs/launch-run-template.md @@ -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 | `` | -| Target repository and commit | `` | -| Claude Code version | `` | -| Model | `` | -| Operating system | `` | -| Started / finished | `` | +| 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 - -``` +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 - +npm test +npm run typecheck +npm run lint +npm run build +npm run e2e ``` ## Results | Metric | Observed value | Evidence | |--------|----------------|----------| -| Elapsed time | `` | `` | -| Tasks completed / blocked / discovered | `` | `` | -| Commits produced | `` | `` | -| Gate failures repaired | `` | `` | -| Human interventions | `` | `` | -| Input / output tokens | `` | `` | -| Reported cost | `` | `` | -| Final test result | `` | `` | -| Security / UI verdict | `` | `` | +| 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: `` -- Specification: `` -- Commit history: `` -- Gate logs: `` -- Audit returns: `` -- Terminal recording: `` +- [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. diff --git a/docs/launch-run/gates.md b/docs/launch-run/gates.md new file mode 100644 index 0000000..a6b3059 --- /dev/null +++ b/docs/launch-run/gates.md @@ -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). diff --git a/docs/launch-run/peter-launch.gif b/docs/launch-run/peter-launch.gif new file mode 100644 index 0000000..74dec85 Binary files /dev/null and b/docs/launch-run/peter-launch.gif differ diff --git a/docs/launch-run/prompt.md b/docs/launch-run/prompt.md new file mode 100644 index 0000000..c5e9907 --- /dev/null +++ b/docs/launch-run/prompt.md @@ -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. +``` diff --git a/docs/launch-run/render-demo.sh b/docs/launch-run/render-demo.sh new file mode 100755 index 0000000..5ded794 --- /dev/null +++ b/docs/launch-run/render-demo.sh @@ -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" diff --git a/docs/launch-run/terminal-frame.svg b/docs/launch-run/terminal-frame.svg new file mode 100644 index 0000000..acca5cc --- /dev/null +++ b/docs/launch-run/terminal-frame.svg @@ -0,0 +1,15 @@ + + + + + + + + peter · public proof run + {{STAMP}} UTC + {{TITLE}} + {{SUBTITLE}} + github.com/robertkeus/peter-launch-fixture + + + diff --git a/docs/launch-run/transcript.md b/docs/launch-run/transcript.md new file mode 100644 index 0000000..3951863 --- /dev/null +++ b/docs/launch-run/transcript.md @@ -0,0 +1,41 @@ +# Public proof run event transcript + +This is a milestone transcript derived from the Claude Code stream and public +Git history. It excludes model reasoning and repeated wait events; results, +timestamps, failures, repairs, and interventions are preserved. + +| UTC | Observed event | +|-----|----------------| +| 13:59:21 | Claude Code 2.1.228 received the complete `/peter` prompt. No clarification was requested. | +| 13:59:44 | Peter confirmed the pinned baseline and began the five baseline gates. | +| 14:00:09 | Baseline test, typecheck, lint, build, and E2E gates were green; Peter classified the work as an epic. | +| 14:02:09 | Plan committed and pushed as `dc39ccf`; graph contained T1 backend, T2 UI, and T3 E2E. | +| 14:06:57 | T1 implementation gates were green; security audit started. | +| 14:12:16 | Security audit failed, score 4, with 8 findings: 2 high, 4 medium, 2 low. | +| 14:12:28 | Security repair loopback 1 of 2 began. | +| 14:25:23 | Security re-audit still failed, score 6, with 5 findings. | +| 14:26:17 | Security repair loopback 2 of 2 began. | +| 14:36:04 | T1 security audit passed, score 7; T1 closed as `1e130d6`. Three non-blocking findings became T4–T6. | +| 14:53:58 | UI audit failed, score 6, with 8 findings: 2 high, 3 medium, 3 low. | +| 14:54:02 | UI repair loopback 1 of 2 began. | +| 15:10:29 | UI re-audit still failed, score 8, with 2 findings. | +| 15:11:04 | UI repair loopback 2 of 2 began. | +| 15:17:21 | T2 UI audit passed, score 9; T2 closed as `24fccae`. One low finding became T7. | +| 15:22:01 | T3 returned 9/9 E2E tests passing. | +| 15:22:33 | Full parent gate suite was green; T3 closed as `69d0ca7`. | +| 15:22:44 | All three planned tasks were closed; epic-close gates and full-scope audits began. | +| 15:25:06 | Epic-close security audit passed, score 8, retaining two medium and one low backlog findings. | +| 15:25:46 | Epic-close UI audit passed, score 9, retaining one low 320px + 200% zoom finding. | +| 15:26:57 | Epic closed and pushed at `9d01a0a`; final gates were 33/33 tests and 9/9 E2E. | + +Human interventions: **0**. No prompt clarification, tool approval, repair +instruction, manual code edit, or merge occurred during the run. The only human +input was the initial complete prompt. + +Public evidence: + +- [Work graph](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/graph.jsonl) +- [Security audit](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/security.eson) +- [UI audit](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/ui.eson) +- [Final report](https://github.com/robertkeus/peter-launch-fixture/blob/9d01a0aba390948f9e99beaeeca961b5c0a29f73/runs/reading-list/report.md) +- [Baseline-to-result comparison](https://github.com/robertkeus/peter-launch-fixture/compare/ed3243ce70340eab73ed20d3956dde7efc14f64b...9d01a0aba390948f9e99beaeeca961b5c0a29f73) diff --git a/docs/launch-run/usage.md b/docs/launch-run/usage.md new file mode 100644 index 0000000..ec9b1b2 --- /dev/null +++ b/docs/launch-run/usage.md @@ -0,0 +1,13 @@ +# Public proof run usage + +Claude Code reported the following usage for the run. Cache reads and cache +creation are listed separately from direct input. + +| Model | Input | Output | Cache read | Cache creation | Reported cost | +|-------|------:|-------:|-----------:|---------------:|--------------:| +| `claude-sonnet-5` | 658 | 257,749 | 23,468,487 | 659,182 | $13.82294985 | +| `claude-opus-5[1m]` | 266 | 145,236 | 9,837,666 | 841,453 | $13.81014425 | +| **Total** | **924** | **402,985** | **33,306,153** | **1,500,635** | **$27.63309410** | + +Elapsed wall time from the first to last streamed timestamp was 1:27:35.322. +Claude Code also reported 5,186,435 ms of API duration and 9 parent turns. diff --git a/skills/peter/SKILL.md b/skills/peter/SKILL.md index aff58c3..906a54e 100644 --- a/skills/peter/SKILL.md +++ b/skills/peter/SKILL.md @@ -75,7 +75,22 @@ scores low, stays a loop, and still needs this. and what talks to what) in `spec.md` in epic mode, inline in loop mode. Builders inherit it; no task re-derives it. -Now the gate. Run `decompose` and score its seven signals. Most tasks are a loop. +Now the gate. Score these seven signals; Peter has no dependency on another +skill. Give one point for each right-column condition. Most tasks are a loop. + +| Signal | 0 | 1 | +|---|---|---| +| Shape | one job, one finish line | distinct specialties hand off | +| Parallelism | sequential steps | fan-out then join | +| Tools/model | same throughout | different model or tool allowlist | +| Context | fits one window | would overflow the parent window | +| Control flow | free-roam is safe | routing must be explicit and auditable | +| Failure | a bad step can retry locally | one bad step must not poison the rest | +| Verification | the implementer can self-check | a separate reviewer must check it | + +No independent verifier is a hard stop for work whose acceptance bar requires +one. If the work fits one context and needs no different tools, choose loop +regardless of marketing words in the request. - **Loop (score 0–4)** — no subagents, no run directory, no branch, no work graph. Spec and bars inline, implement inline, run the machine gates (§G), @@ -291,11 +306,13 @@ neither ever pauses the run. 1. Full test suite once more — a regression here is a stop condition, not a footnote. -2. Full audit sweep: `security-auditor` + `ui-auditor` over all changed routes, - regardless of per-task audits. Both verdicts must be `pass` to close the - epic, and both land in the epic `closed` record as `audits` — or - `not_run: `, which keeps the epic out of Done. A close record - silent on audits is not a close. +2. Full audit sweep over every applicable scope, regardless of per-task audits: + `security-auditor` for auth, data, or external input; `ui-auditor` for + rendered UI. Every applicable verdict must be `pass` to close the epic. + Record a non-applicable scope as `not_applicable: ` and an applicable + audit that could not run as `not_run: `; `not_run` keeps the epic out + of Done. Both scope keys land in the epic `closed` record as `audits`. A close + record silent on audits is not a close. 3. Append `closed` for the epic — carrying `commits[]`, `open[]` (the backlog), and `audits` — then write `runs//report.md`, including a **Deviations** section: every departure from this protocol with its cause, @@ -467,7 +484,7 @@ prevent. - The work needs a 5th specialty — a **tool or model none of the four roles has** (mobile simulator, notebook runtime, a different provider). A non-web domain is not a 5th specialty: CLIs, libraries, data pipelines, and infra scripts are - `backend-builder`'s. Re-run the `decompose` gate; never invent a node mid-run. + `backend-builder`'s. Re-score the §0 gate; never invent a node mid-run. On any stop, in order: the status table (§S); the exact failing clauses or the open question — closed, filed, and blocked all read off the table; then @@ -490,18 +507,20 @@ downgraded to make it pass.** Never relax a bar to close the loop; never mark ## Done -Ship only when: machine gates green including E2E, epic-close audit verdicts -both `pass`, no unresolved `critical`/`high`. Then report, in this order: +Ship only when: machine gates green including E2E, every applicable epic-close +audit verdict is `pass`, and no unresolved `critical`/`high` remains. Then +report, in this order: 1. What was built, in two sentences. 2. The final status table (§S) — every task's end state. 3. Gate results — unit/typecheck/lint/build, E2E (passed/failed/skipped + - acceptance-criteria coverage map), security verdict + score, UI verdict + score. + acceptance-criteria coverage map), security and UI verdict + score or their + explicit `not_applicable` reasons. 4. What was deliberately not done, every protocol deviation with its cause, any quarantined test, and any accepted-risk finding with its reason. 5. The proposed merge command. -**An audit that could not run keeps the build out of Done.** No dispatch +**An applicable audit that could not run keeps the build out of Done.** No dispatch available, app unreachable, no auditor — report `security: not run` or `ui: not run` with the reason and say plainly that the bar was never applied. A missing verdict is not a passing one. A degraded run produces a change that @@ -516,7 +535,7 @@ Run directory, `graph.jsonl`, zone memory, and the single-writer table: Stable roles in `~/.claude/agents/` — the work graph in `graph.jsonl` is per-epic and disposable; this is not (see -`~/.claude/skills/decompose/references/graph-engineering.md`): +`references/graph-engineering.md`): ``` [parent — orchestrator] diff --git a/skills/peter/references/graph-engineering.md b/skills/peter/references/graph-engineering.md new file mode 100644 index 0000000..de3a6ae --- /dev/null +++ b/skills/peter/references/graph-engineering.md @@ -0,0 +1,15 @@ +# Graph engineering in Peter + +Peter separates two graphs: + +- The stable **org graph** is the parent plus four roles in `agents/`. +- Each epic's append-only **work graph** is `runs//graph.jsonl`. + +The parent alone routes work, runs gates, mutates the graph, commits, and +adjudicates. Builders own disjoint code zones and append durable zone facts. +Auditors are read-only and never verify their own fixes. A failure can loop back +at most twice; graph mutations and cross-zone contract changes are recorded. + +Keep those boundaries stable during a run. If the work needs a fifth specialty, +stop and re-score the seven-signal gate in `SKILL.md`; do not invent a role +mid-epic. diff --git a/skills/peter/references/work-graph.md b/skills/peter/references/work-graph.md index 838c5dd..aa0ee71 100644 --- a/skills/peter/references/work-graph.md +++ b/skills/peter/references/work-graph.md @@ -2,9 +2,8 @@ The per-epic work graph: what needs doing right now, dependency-ordered, append-only, committed. The org graph (stable roles) lives in -`~/.claude/agents/`; terminology and the patterns adopted here: -`~/.claude/skills/decompose/references/graph-engineering.md`. This file is the -runtime contract. +`~/.claude/agents/`; terminology and the patterns adopted here are documented +in `graph-engineering.md`. This file is the runtime contract. ## Records @@ -45,7 +44,7 @@ Fields: | `sha` | on close | the task's single commit sha — real and existing, never `"pending"` | | `discovered-from` | discovered | the task or sweep whose run surfaced this | | `evidence` | no | discovered tasks: the observation that motivated filing, verbatim — never mixed into `criteria` | -| `audits` | epic close | sweep verdicts: `{"security":{"verdict","score"},"ui":{"verdict","score"}}`, or `"not_run: "` | +| `audits` | epic close | both scope keys; each is a verdict object, `"not_applicable: "`, or `"not_run: "` | | `note` | no | one line of context; `fix:` hypotheses live here, never in `criteria`. On `blocked`, prefixed: `gates: ` \| `needs-input: ` | `criteria` are checkable against a diff — bars, not findings. A pasted finding @@ -78,7 +77,7 @@ arrives: | Evidence | Move | |---|---| -| Scope expands | append a new task (`discovered-from` set); if it needs a 5th *specialty*, stop — re-run the `decompose` gate | +| Scope expands | append a new task (`discovered-from` set); if it needs a 5th *specialty*, stop — re-score the §0 gate | | Tasks converge / one becomes moot | append `closed` with `note` `"merged into "` or `"moot: "` — never delete the line | | Task fails its gates twice | append `blocked`, `note` `gates: `; stop condition | | A decision needs the operator | append `blocked`, `note` `needs-input: `; stop condition | @@ -105,8 +104,9 @@ unworked — the report lists what's left open. The epic `closed` record carries `commits[]`, `open[]` (every task not folding `closed` — backlog and `blocked` alike), and -`audits` (§C2's sweep verdicts — `not_run: ` keeps the epic out of -Done). A close record silent on audits is not a close. A closed epic is not a +`audits` (§C2's sweep results — `not_run: ` keeps the epic out of Done; +`not_applicable: ` does not). A close record silent on audits is not a +close. A closed epic is not a tombstone: to work its backlog later, append an epic `open` record (reopen) first, then task records as usual, then re-close with updated `commits[]`/`open[]`/`audits`. diff --git a/tests/claude-smoke.sh b/tests/claude-smoke.sh new file mode 100755 index 0000000..1e6b5ca --- /dev/null +++ b/tests/claude-smoke.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +test_root="$(mktemp -d)" +trap 'rm -rf -- "$test_root"' EXIT + +version="$(npx --yes @anthropic-ai/claude-code@2.1.228 --version)" +case "$version" in +2.1.228*) ;; +*) + echo "unexpected Claude Code version: $version" >&2 + exit 1 + ;; +esac + +config="$test_root/claude" +CLAUDE_CONFIG_DIR="$config" "$repo/install.sh" >/dev/null +CLAUDE_CONFIG_DIR="$config" "$repo/install.sh" check >/dev/null +CLAUDE_CONFIG_DIR="$config" "$repo/install.sh" uninstall >/dev/null + +[ ! -e "$config/.peter-install" ] || { + echo "uninstall left Peter state behind" >&2 + exit 1 +} + +echo "Claude Code $version smoke test passed"