Panout MVP goal prompt
Paste everything below the line into a fresh Claude Code or Codex session opened at /code/research/panout. It is written to be executed cold.
Goal
Build the Panout MVP: a local, metadata-only commit-boundary tool that (1) runs a small set of contracts against each commit, prints only failures, and (2) records every override (a human committing past a failing contract) and every evaluation as a hash-chained event with a stable work ID written into the commit itself, so that 30 days later the outcome (reworked or not) can be joined back to the evaluation. Ship it in the founder's own repos within 48 hours. The only clock that matters starts when the first captured commit lands; nothing else in this brief is allowed to delay it.
One-liner for orientation: Panout is the record of what your team stopped reading.
Read first
STRATEGY.md,DECISIONS.md(top 120 lines),AGENTS.md.docs/research/2026-09-03-defensibility/README.md(the idea and why it has this shape), and appendices D, F, H in the same folder (why capture must happen at commit time, why the unit of policy is the contract and not the task class, why the rework label is only an audit).prototype/panout.pyandprototype/test_panout.py. Reuse theLedgerclass (hash chain, file lock,verify),run_git,canonical_json, and therecord-claudeadapter's allow-list discipline. Do not rewrite what works; extend it.
Invariants (violating any of these is a failed MVP)
- Panout never controls, blocks, or orchestrates agents and never sits in the live agent loop.
- The human never has to log in anywhere. Repo plus terminal only. No cloud, no account.
- Metadata only. Never store prompt text, assistant text, file contents, diff bodies, command bodies, or identity fields. Paths, counts, hashes, timestamps, contract names, results, and pseudonymous IDs are allowed. The existing salted-hash pattern applies.
- Zero new habits. The hook installs once, runs on commits the user already makes, and is silent when every contract passes. A commit after a printed failure is an override and is recorded as one; it is never blocked (
--no-verifyis never required). - Python 3.10+ standard library only, as in the prototype. Linux and macOS.
Decisions already made (do not reopen)
- Unit of policy = contract. Autonomy levels, catch rates, and overrides are per contract, never per task class. Task class may be recorded as a feature; it is never a key.
- Stable work ID in the commit. Each evaluated commit gets a
Panout-Work: <id>trailer (short random ID, plusPanout-Contracts: name=pass|fail|override,...). Trailers survive GitHub squash merges because the squash body concatenates commit messages; SHA linkage does not survive, which appendix D proved. - Contracts fire often by design. Target roughly 30% of commits producing at least one contract evaluation with a non-trivial result, so the day-60 predictive test is powered. Appendix D's power note says 6% exposure needs thousands of commits.
- Fault injection is the calibration mechanism. A contract earns a level only by catching injected faults, off the hot path. Observational rework is an audit signal, not a grant.
- Metered per evaluation later; nothing paid in the MVP. Do not build billing.
Scope: what to build
1. panout init (extend the existing command)
- Creates
.panout/(ledger, config, salt) if missing; adds.panout/to.git/info/exclude. - Installs two git hooks by writing thin shims that call
python3 <path>/panout.py hook <name>:prepare-commit-msg(appends thePanout-WorkandPanout-Contractstrailers) andpost-commit(records the evaluation event with the final SHA). If a hook already exists, chain it; never overwrite. Print a reversible diff of what was changed and how to undo it. - Proposes contracts from the repo (see 2) and writes
.panout/contracts.json. Idempotent.
2. Contracts
A contract is a named, deterministic check over the staged diff and the working tree that returns pass, fail, or skip, plus a one-line reason with no file contents. Ship these built in:
tests-touch: if staged changes touch source paths, at least one test path is also staged (path rules fromAGENTS.mdor defaultstest|spec|__tests__|_test.).no-secrets: staged additions do not match a small set of high-precision secret patterns (report only the pattern name and file path, never the match).size-guard: staged additions do not exceed a configurable line budget (default 400).agent-attribution: if the commit carries an agent trailer (Co-Authored-By: Claude|Codex| Cursor|Copilot,Generated with), it also carries aPanout-Worktrailer (this one is self-satisfying via the hook; it exists so squash bodies stay attributable).custom-command: run a repo-specified command from.panout/contracts.jsonwith a timeout; exit code decides. Store only the exit code and duration.
Contracts must run in under 2 seconds total on a typical commit or be skipped with a reason.
3. Event capture at commit time
Extend the ledger event schema (bump to panout.event.v1, keep v0 readable) with: evaluation events: work ID, commit SHA, timestamp, per-contract result, override flag (true when any contract failed and the commit proceeded), harness and model if present in trailers, agent flag, path-class histogram of staged files (counts only), lines added and deleted, files changed, commits in the last 60 minutes on this branch, and, if a supported session surface is readable, session-shape metadata only (tool call count, error count, duration). Reuse the record-claude allow-list approach for session data; never read transcripts beyond counts.
4. panout status (rename or extend brief)
Terminal only. Prints: contracts installed, evaluations recorded (total and last 7 days), overrides per contract, and the exposure rate (share of commits with at least one non-skip result) against the 30% target. Prints nothing else. Must run in under one second.
5. panout audit (the day-one artifact)
Prints a table of agent-attributed commits in the last N days with: SHA, date, contracts and results, override yes/no, and, for commits older than 30 days, whether any added line was changed or deleted within 30 days (reuse the reverse-blame method in docs/research/2026-09-03-defensibility/scripts/measure.py, with -w -M -C). Label the rework column as a proxy in the header. Support --json. This is the audit trail of auto-approved agent work; it is the thing a buyer receives on day one.
6. panout inject (fault injection, minimum viable)
Off the hot path, on a scratch worktree only: take the last K accepted agent commits, apply one of three injected faults (delete a test assertion, introduce an obvious secret-shaped string, remove a staged test file from a source-touching change), run the contracts, and record per contract: injected faults presented, caught, missed. Print catch rate per contract with n. Never touch the real working tree or index. This is the only mechanism that may later grant a level; the MVP only measures and prints.
7. panout verify (keep) and panout uninstall
Uninstall removes the hook shims (restoring any chained hooks) and leaves .panout/ in place unless --purge.
Out of scope for the MVP (do not build)
Autonomy levels or auto-merge, cloud sync, any dashboard or web UI, Linear or GitHub API integration, routing or model recommendation, the .agents/ standard, decisions/ drafting, billing, Codex adapters beyond reading trailers, any LLM call.
Acceptance criteria
python3 -m unittest -v prototype/test_panout.pypasses with new tests for: trailer insertion, hook chaining, each built-in contract (pass, fail, skip), override detection, event schema v1 validation, ledger verify after 100 concurrent appends,injectnever modifying the real tree, andaudit --jsonshape.- Installed in at least three founder repos (this repo,
/code/dotfiles, and one of/code/jonesor/code/personal/dynorouter) withpanout init, and at least five real commits captured in each, at least one of them an override, verified withpanout status. - Exposure rate in
panout statusis at or above 30% across those commits, or the contracts are tuned until it is, with the tuning recorded inDECISIONS.md. panout injectreports a catch rate with n at least 10 for each built-in contract on one repo.- Hook overhead measured and printed: median under 2 seconds on 20 commits.
- A grep of the ledger for any staged file's content, any prompt text, or an email address returns nothing.
git log -5in each repo showsPanout-WorkandPanout-Contractstrailers.
Working rules
- Commit early and often to
mainin this repo; the capture clock only starts when the first hook-captured commit exists. Land a workinginitplus one contract plus the trailer before anything else, then iterate. - Keep each change small enough to review in a diff. Add a
DECISIONS.mdentry for every choice that departs from this brief, dated, with the reason. - Report faithfully at the end: what shipped, what did not, exact commands to reproduce the acceptance checks, and the measured exposure rate and hook latency. If any acceptance criterion is unmet, say which and why; do not scale the scope down silently.
- Do not contact anyone, do not publish anything, do not touch repos other than the three named.
First hour
- Read the files listed above.
- Add
hook,status,audit,inject,uninstallsubcommands as stubs; extendinit. - Implement the
Panout-Worktrailer andevaluationevent with thesize-guardcontract. - Run
panout initin this repo and make one real commit. That commit is the start of the 30-day clock; everything after it is iteration.