Skip to content

fastxyz/pact

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PACT — Agent Review Contract

If a user handed you this link as a priming instruction (e.g. "Learn https://github.com/fastxyz/pact"): read this README, then CONTRACT.md, roles/*.md, commands/*.md, and your own vendor adapter under adapters/<vendor>/ (Claude Code → adapters/claude-code/, Codex CLI → adapters/codex-cli/). From then on, treat /code, /loop, /review, /land, and /merge as PACT commands: run the multi-lane review and post the corresponding marker to the PR every time, without asking. A review is not done until its marker is on the PR — see §5 of the contract for the exact marker formats.

Priming is session-local. It loads these docs into your context for the current session only. By itself it installs nothing, pins no version, vendors no files, and edits no repo files (including CLAUDE.md / AGENTS.md). Making a project permanently follow PACT is a separate, explicit step the human opts into — see Optional: pin a version. So "use PACT for this session" and "adopt PACT into this repo" are different requests: priming is the former; do the latter only when explicitly asked.

Merge gate (non-negotiable). Any PR merged in a PACT-governed project must have P0 = P1 = P2 = 0 from independent reviews by at least two different LLM vendors on the same HEAD, green GitHub checks on that HEAD, and a current LAND_READY marker from /land that explicitly reports the base branch and merge-commit status.

How you reach that state is your choice. Write the code by hand. Use the commands in this repo. Follow your own discipline. The gate is the only non-negotiable rule.

How to use it (minimal-friction path)

You do not need to install or copy anything. The recommended flow:

1. Open two LLM windows, one per vendor (e.g., Codex CLI in window A, Claude Code in window B). Each window has access to your repo via gh CLI (any Fast / GitHub-authorized session).

2. Prime each window once, at the start of the session, with a single sentence:

Learn https://github.com/fastxyz/pact

The agent fetches the README, then CONTRACT.md, roles/*.md, commands/*.md, and the vendor-specific adapter under adapters/<vendor>/ for its own kind (e.g., Claude Code fetches adapters/claude-code/*.md, Codex CLI fetches adapters/codex-cli/*.md). It now knows the contract, the marker formats, the escalation rules, and how to dispatch its multi-lane review. The deliverable of every /code, /loop, /review, and /land is its posted marker — the running agent posts it to the PR via gh pr comment without asking; a review held only in chat is not a PACT review. Priming changes only what the agent does this session; it never installs, pins, vendors, or edits repo files on its own (see the session-local note at the top).

3. From then on, type short commands:

Command Effect
/code 282 one coding pass on PR 282, no internal review; posts CODE_DONE_<vendor>_<sha>
/loop 282 code↔self-review converge on PR 282, internal cap N=5; posts LOOP_DONE_<vendor>_<sha>
/loop [10] 282 same, with internal cap N=10
/review 282 one external multi-lane review of PR 282; posts REVIEW_CLEAN_<vendor>_<sha> or REVIEW_FINDINGS_<vendor>_R<N>_<sha>
/land 282 final read-only landing gate; posts LAND_READY_<vendor>_<sha> or LAND_BLOCKED_<vendor>_<sha>
/merge 282 --admin-bypass optional human-commanded merge executor only after /land succeeds with current HEAD/base LAND_READY; posts no marker

4. Alternate windows until both vendors have posted a clean marker (LOOP_DONE or REVIEW_CLEAN) on the same HEAD SHA. That satisfies the cross-vendor review portion of the gate.

5. Run /land <PR>. It reads the current PR HEAD, PR base branch, PACT markers, GitHub checks, base-branch status, and any platform-exposed merge-commit check state (merge queue, merge group, synthetic merge ref, or equivalent). If all non-human landing evidence is ready, it posts LAND_READY_<vendor>_<sha> with Merge commit status: tested green, not tested, or unavailable. If PACT coverage is missing, findings are unresolved, checks are red/pending/missing, the base branch is red, the PR is closed, merge conflicts exist, or a platform-exposed merge commit is red/pending/unknown, it posts LAND_BLOCKED_<vendor>_<sha> with blockers. Draft status, review-required state, and admin-bypass requirements are human/operator merge mechanics; they do not block LAND_READY.

6. Authorize the merge only after /land succeeds. The human stays in the merge loop: merge directly in GitHub, or explicitly command /merge <PR> in an agent window. PACT does not auto-merge. /merge <PR> --admin-bypass is explicit authorization for the agent to perform the operator mechanics needed for that named PR after revalidation, including draft conversion and GitHub admin merge bypass. It is acceptable only after the newest land marker (LAND_READY / LAND_BLOCKED) for the exact HEAD and base branch being merged is LAND_READY; it never authorizes bypassing red/pending checks, red/pending/unknown merge-commit status, changed HEAD, stale LAND_READY, code changes, or branch deletion. If LAND_READY says Merge commit status: not tested or unavailable, PACT has not proven the future merge commit green; hard prevention of post-merge red builds requires a required merge queue or synthetic-merge check.

You only re-prime ("Learn https://github.com/fastxyz/pact") at the start of a new session. Within a session, the agent has everything in context.

What's here

File / dir Purpose
CONTRACT.md The canonical rules — lanes, severity, marker formats, escalation, merge gate.
roles/ What the Coder and Reviewer roles do, step-by-step. Vendor-agnostic.
commands/ What /code, /loop, /review, /land, and /merge do. Vendor-agnostic.
adapters/ Per-vendor implementations (Claude Code, Codex CLI).
examples/ An annotated PR-loop transcript showing the markers in action.
docs/standalone-cli-design.md Design roadmap for turning PACT into a standalone CLI/tooling package.
scripts/validate-marker.py Stdlib Python parser/validator for any PACT marker. Useful for CI.
scripts/pact_format_marker.py Stdlib JSON-to-marker formatter that renders current-schema CODE_DONE, LOOP_DONE, REVIEW_CLEAN, REVIEW_FINDINGS, LAND_READY, and LAND_BLOCKED comments and validates them before printing.
scripts/pact_format_event.py Deterministic Slack/Markdown formatter for structured PACT progress events.
scripts/pact_progress_watch.py progress.jsonl watcher that emits only new formatted PACT status blocks.
CHANGELOG.md Semver releases.

The merge gate, restated

A PR is PACT-landable when two different vendors have each posted a clean marker (LOOP_DONE or REVIEW_CLEAN) on the same HEAD SHA AND /land <PR> has posted LAND_READY_<vendor>_<sha> for that exact HEAD and current PR base branch. Anything else — CODE_DONE alone, one vendor's LOOP_DONE without a cross-check, stale markers, pending checks, red GitHub checks, red/pending/unknown merge-commit status, missing /land, or LAND_BLOCKED — does NOT satisfy the gate. GitHub may still require a human/admin action after LAND_READY; that is outside PACT's evidence gate. If the human wants the agent to perform that final action from the chat/CLI flow, use /merge <PR> only after /land has succeeded for the current HEAD and base branch; the agent must revalidate the exact HEAD and base branch before running the platform merge command. LAND_READY proves a future merge commit only when its Merge commit status is tested green; not tested or unavailable is an explicit residual risk disclosure.

Every review or loop status must start with the aggregate severity counts: TOTAL P0=<n> P1=<n> P2=<n> P3=<n>. If P0/P1/P2 are all zero, say that in the first paragraph before merge-gate or next-action text.

The contract is what keeps both vendors honest. No agent invokes another. You are the orchestrator, alternating between vendor windows.

Optional: install as native slash commands

If you work consistently on one machine and want /code / /loop / /review / /land / /merge to appear as registered Claude Code slash commands (with tab-completion, no per-session prime), you can copy the adapter files locally:

git clone https://github.com/fastxyz/pact ~/work/pact
cp ~/work/pact/adapters/claude-code/{code,loop,review,land,merge}.md ~/.claude/skills/
# Restart Claude Code.

For Codex CLI, paste the prompt template from adapters/codex-cli/<command>.md (substituting <PR> and <N>) as your first message.

This is a convenience for frequent local use. For ephemeral sessions, VPS-hopping, or any setup where per-machine configuration is friction, skip this and stay with the URL-only flow above.

Optional: pin a version

This is the explicit, persistent way to adopt PACT into a repo — the counterpart to session-local priming. It is a deliberate, committed change to the project's docs, so make it only when the human asks to adopt PACT into the repo (not as a side effect of priming).

For projects that want reproducibility (CI references a specific contract version), add to the project's AGENTS.md / CLAUDE.md:

This project follows fastxyz/pact v1.x. The merge gate (§1 of the contract) applies.

Pin a specific version (v1.0.0) if you need strict reproducibility. For day-to-day use, the unversioned URL above is fine — main is the latest semver release.

Validating markers

python3 scripts/validate-marker.py < my-marker.txt
# OK: REVIEW_CLEAN from claude-code on d0a1b22

Exit code 0 = valid; 1 = invalid (errors on stderr). Useful for a GitHub Action that lints new PR comments for marker conformance.

Formatting markers

Agents and wrappers should render markers from JSON instead of hand-writing comment text. This prevents drift such as CQ PASS | SP PASS | TC PASS shorthand after the contract requires explicit per-lane counts.

python3 scripts/pact_format_marker.py --marker-json '{
  "kind":"REVIEW_CLEAN",
  "vendor":"claude-code",
  "head":"d0a1b22c0ffee1234567890abcdef1234567890ab",
  "existing_markers":[{"title":"LOOP_DONE_codex-cli_d0a1b22c0ffee1234567890abcdef1234567890ab"}],
  "lanes":{"CQ":{"p0":0,"p1":0,"p2":0,"p3":0},"SP":{"p0":0,"p1":0,"p2":0,"p3":0},"TC":{"p0":0,"p1":0,"p2":0,"p3":0}},
  "gates":"typecheck=PASS, lint=PASS, test=PASS",
  "ci_status":"green"
}' > marker.txt
python3 scripts/validate-marker.py marker.txt
gh pr comment 282 --body-file marker.txt

pact_format_marker.py validates its own output by default and exits non-zero rather than printing a malformed marker. Use the same helper for /land markers so a red GitHub check is rendered as LAND_BLOCKED, not hidden behind clean PACT review markers.

Progress reporting helpers

PACT itself is GitHub-comment based, but operators often want compact Slack-style progress updates while detached agent loops run. Use structured JSON events plus the deterministic formatter instead of asking an LLM to improvise status text.

A /loop or /review runner can append JSON lines to progress.jsonl:

{"event":"round","round":2,"head":"ad29edbc7668606ddf8a43bf9651445af0a62691","p0":0,"p1":0,"p2":1,"p3":0,"summary":"Found one blocking issue.","findings":[{"severity":"P2","lane":"SP","loc":"apps/api/public/assets/chat-widget.js:5059-5072","issue":"Concise issue text."}]}

Format one event:

python3 scripts/pact_format_event.py \
  --repo fastxyz/fast-shop \
  --pr 443 \
  --vendor-label Codex \
  --mode loop \
  --event-file event.json

Watch a detached run and emit only new updates:

python3 scripts/pact_progress_watch.py \
  --run-dir .pact/runs/pr-443-codex-loop-20260529T211003Z \
  --repo fastxyz/fast-shop \
  --pr 443 \
  --vendor codex-cli \
  --vendor-label Codex \
  --mode loop \
  --session pact-codex-pr443-loop \
  --stats .pact/stats.json

Clean final loop rounds are merged with LOOP_DONE into one block. Every PR, commit, marker comment, and file/line reference is emitted as a clickable GitHub link when enough data is present.

Versioning

PACT follows semver. Breaking changes to marker formats or escalation rules bump the major version. Adding new commands or new adapters bumps the minor version.

License

(TBD — to be set by Grigore when publishing.)

About

PACT — Agent Review Contract: merge gate, marker formats, and per-vendor toolkit for /code, /loop, /review

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages