- Add required
Base branch:toLAND_READYandLAND_BLOCKEDmarkers. The formatter now emits it, and the validator rejects land markers that omit it. - Clarify that
/landproves readiness for the exact current HEAD and the PR's current base branch, so PRs targeting branches such asdevare handled by the same PACT flow without assumingmain. - Require
/mergeto reject a current-HEADLAND_READYmarker when its recordedBase branch:no longer matches the PR's current base branch.
- Add a prime block at the top of
README.mdaddressed to an agent that was handed the repo link: read the contract + vendor adapter, then run/code/loop/review/land/mergeas PACT commands and post the marker to the PR every time, without asking. Closes a failure mode where an agent did a clean review but withheld the marker because the trigger looked like a generic chat review. - State explicitly that priming is session-local: by itself it installs nothing, pins no version, vendors no files, and edits no repo files (
CLAUDE.md/AGENTS.md). Separates "use PACT for this session" (priming) from "adopt PACT into this repo" (the explicit, committed pin step), so an "adopt"-style instruction is not misread as authorization to modify project docs. - Reinforce in the priming step that the deliverable of every marker-producing command is the posted marker, and frame "Optional: pin a version" as the persistent-adoption counterpart. No marker schema, lane, severity, escalation, or merge-gate change.
- Add required
Merge commit status:toLAND_READYandLAND_BLOCKEDmarkers. The formatter now emits it, and the validator rejects land markers that omit it. - Document the PR-head-vs-future-merge-commit distinction:
LAND_READYproves the current PR HEAD and base branch, but it proves the future merge commit only when the status saystested green. If the platform exposes a merge queue, merge group, synthetic merge ref, or equivalent pre-merge commit check and it is red/pending/unknown,/landmust postLAND_BLOCKED. - Clarify that
not tested/unavailablemerge-commit status is an explicit residual risk disclosure, not proof of post-merge CI. Repositories that need hard prevention of post-merge red builds should require a merge queue or synthetic-merge check.
- Add
/merge <PR> [--admin-bypass] [--squash|--merge|--rebase] [--wait-deploy]as an optional merge executor only after/landhas completed successfully for the current HEAD by postingLAND_READY. It posts no marker; it revalidates the current PR HEAD, PACT comments, GitHub checks, open/conflict-free state, and newest exact-HEAD land marker before invoking the platform merge command. - Clarify that agents still never merge autonomously. A merge through
/mergeis allowed only when the human explicitly commands it in the current turn; the agent is acting as the human-operator execution interface. Admin bypass requires an explicit--admin-bypassrequest and a successful current-HEAD/landresult for the exact HEAD being merged. When supplied,--admin-bypassalso authorizes required operator mechanics for that named PR, including draft conversion, followed by a fresh HEAD/check/LAND_READYrevalidation before merge. - Document head-pinned merge execution (
gh pr merge --match-head-commit <sha>), no branch deletion unless explicitly requested, and optional deploy-wait/reporting behavior. No marker schema, lane, severity, or review-gate change.
- Add
/land <PR> [--fix-red-base]as the mandatory final read-only readiness gate before human merge. It inspects current-HEAD PACT markers, unresolved findings, GitHub checks, and base-branch status, then postsLAND_READYorLAND_BLOCKED. - Add
LAND_READYandLAND_BLOCKEDmarker schemas plus validator/formatter support.LAND_BLOCKEDmay reportPACT: PASSwithGitHub checks: FAIL, preserving the exact failure mode where two vendors were clean but Browser E2E was red. - Update README, CONTRACT, and vendor adapters so admin bypass is allowed only after a current
LAND_READYmarker for the exact HEAD being merged. Clarify that draft status, review-required state, approval requirements, and admin-bypass mechanics do not blockLAND_READYonce PACT markers, current-HEAD checks, and base status are green.
- Add
scripts/pact_format_marker.py, a stdlib JSON-to-marker formatter forCODE_DONE,LOOP_DONE,REVIEW_CLEAN, andREVIEW_FINDINGScomments. It emits the current CONTRACT §5 schema, validates its own output withscripts/validate-marker.pyby default, and refuses clean markers with nonzero P0/P1/P2 counts. - Add formatter tests covering clean loop markers, clean review markers with existing-marker enumeration, findings markers with computed lane counts, and rejection of malformed clean-marker payloads.
- Document the marker formatter in
README.mdand direct/loopand/reviewcommand implementations to prefer it over hand-written marker text, preventing drift such asCQ PASS | SP PASS | TC PASSshorthand.
No marker schema, lane, severity, escalation, or merge-gate change.
- Add
scripts/pact_format_event.py, a stdlib formatter that converts structured PACT progress JSON events into compact Slack/Markdown blocks with clickable PR, marker-comment, commit, and file/line links. - Add
scripts/pact_progress_watch.py, aprogress.jsonlwatcher for detached/loopand/reviewruns. It remembers reported lines, merges a clean final round withLOOP_DONE, and emits only new progress blocks suitable for cron/no-agent delivery. - Document structured progress events and the watcher/formatter workflow in
README.md.
No marker schema, lane, severity, escalation, or merge-gate change.
- New paragraph in CONTRACT §5: "Marker authorship: GitHub author ≠ vendor". Every PACT marker is posted via
gh pr commentfrom the human operator's GitHub account, so all marker comments on a given PR share the sameauthorLogin. The authoritative vendor attribution is the marker title's<vendor>token and theVendor:field in the body — never the GitHub author. Concluding "the other vendor hasn't reviewed yet" because every comment is authored by the same human is the canonical PACT misread; this paragraph closes that confusion. commands/review.mdstep 2 reinforced. When enumerating existing markers on HEAD, identify them by title prefix andVendor:field, not byauthorLogin. The instruction now points at the new CONTRACT §5 paragraph.
Docs-only — no marker schema, lane, severity, escalation, or merge-gate change. Existing markers on existing PRs remain valid; agents that re-fetched main will read the clarified rule automatically.
Adds: workspace isolation for parallel PRs, explicit fluid-role model, explicit push-vs-merge boundary
- New CONTRACT §4a "Workspace isolation" (mandatory). Every
/code,/loop, and/reviewsession must run in its own isolated git worktree bound to exactly one PR's branch — never shared across PRs, never shared across two sessions running at the same time — and must fetch/fast-forward to the PR's latest pushed HEAD before coding. This is the rule that lets many PRs run in parallel (and two vendors advance one PR) without clobbering each other's uncommitted work.commands/code.md,commands/loop.md,commands/review.md, androles/coder.mdeach gain a Workspace note pointing at §4a. - CONTRACT §4 clarified: roles are activities, not vendor assignments. Either vendor may write/modify the code and either may review it, in any order, across or within rounds (both vendors can land fixes in the same round); each review is attributed to its vendor via the marker
Vendor:field. The sole invariant remains the merge gate (§1): two different vendors' clean reviews on the same final HEAD. - CONTRACT §7 clarified: agents push, only humans merge. Pushing commits and posting markers are normal autonomous parts of the commands (that is how the other vendor gets a HEAD to review); an agent never waits for permission to push. Merging — landing the PR into the base branch — was reserved to the human operator in this release line; later versions add an explicit human-commanded
/mergeexecutor without permitting autonomous agent merges. - Adapter + canonical fetch URLs repointed from a pinned tag to
main.adapters/{claude-code,codex-cli}/{code,loop,review}.mdand the contract's own Canonical URL now fetch…/fastxyz/pact/main/…instead of a hardcoded version tag, so future contract clarifications reach agents immediately without per-release URL churn. Pin a tag only when strict reproducibility is needed (see README). Version tags remain as historical records.
No changes to marker schemas, lanes, severities, escalation triggers, or the merge-gate definition itself.
LOOP_DONE,REVIEW_CLEAN, andREVIEW_FINDINGSfirst lines now must include aggregate P0/P1/P2/P3 totals followed by CQ/SP/TC per-category P0/P1/P2/P3 counts immediately after the marker title. The validator rejects markers that omit these first-line counts or whose aggregate or per-category totals disagree with the per-lane counts. This is intended to make severity visible at a glance in PR comments, especially for Codex-style review summaries.- Every
/reviewresult,/loopround status, cap-exhausted halt, duplicate-guard exit, and final user response after a review/loop marker now must start its first paragraph withTOTAL P0=<n> P1=<n> P2=<n> P3=<n>.When P0/P1/P2 are zero, it must explicitly sayP0/P1/P2 are zerobefore merge-gate or next-action text. /loopnow must print user-facing P0/P1/P2/P3 statistics at the start and finish of every internal round, with aggregate counts first and CQ/SP/TC per-category counts second. This keeps loop progress centered on the user's goal: understanding whether P0/P1/P2 blockers remain, not narrating commits or low-level execution details.
v1.0.5 added a "round-zero check" to commands/review.md that fired when a different-vendor REVIEW_CLEAN/LOOP_DONE existed on the current HEAD and exited without posting — on the premise that "the merge gate is already satisfied." That premise is wrong: CONTRACT §1 requires TWO different vendors' clean markers, not one. A different-vendor clean marker alone leaves the gate at 1/2; this vendor's review is exactly what produces the second vote.
If v1.0.5's round-zero had actually fired on a real PR with only one prior vendor's clean marker, the running vendor would have exited without contributing the second vote and the merge gate would have been stuck at 1/2 indefinitely. The check was caught by the very PR audit it was meant to validate (fastxyz/fast-shop, 2026-05-26) before any agent applied it in anger.
v1.0.6 replaces v1.0.5's broken round-zero check with a narrow same-HEAD duplicate guard (commands/review.md step 3):
- Fires ONLY when
REVIEW_CLEAN_<this-vendor>_<sha>orLOOP_DONE_<this-vendor>_<sha>already exists on the current HEAD AND there are no unresolved REVIEW_FINDINGS. The condition is about THIS vendor's own prior coverage, not about another vendor's. - When it fires, this vendor has already cast its vote on this HEAD; re-posting is a same-vendor duplicate, not a fresh vote. The guard prints "This vendor already cleared HEAD
<sha>at " plus a state-derived merge-gate status line and exits without posting. - A different vendor's clean marker on its own NEVER triggers the guard — this vendor's review is still needed to contribute the second vote.
The actual fix for the original "wrong closing line" failure mode is kept: the required Existing markers on HEAD: field in CONTRACT §5 (REVIEW_CLEAN + REVIEW_FINDINGS schemas, unchanged from v1.0.5) plus the state-derived closing-line spec in commands/review.md step 9 (three cases enumerated). When the agent enumerates prior markers as a precondition for posting, the closing line cannot template "needs another vendor" while a prior vendor's marker is sitting in the body.
Asymmetric with /loop's round-zero on purpose. /loop's round-zero exit POSTS LOOP_DONE (with Internal rounds taken: 0) because that IS how a /loop invocation contributes to the merge gate when there's no Coder work to do — a real review with zero rounds, still a vote. /review's same-HEAD duplicate guard is different: this vendor has ALREADY posted its vote on this HEAD; re-posting would be a same-vendor duplicate. v1.0.5 modeled /review's round-zero on /loop's shape but dropped the "still post the marker" half, which is the half that contributes to the gate.
No changes to marker schemas, lane structure, severities, escalation triggers, or the merge gate definition. The Existing markers on HEAD field and validator enforcement remain (v1.0.5).
Failure mode. An agent runs /review <PR> without first reading the PR's existing markers, posts its own REVIEW_CLEAN, and closes with the templated "needs another vendor's clean marker on this HEAD" line — even when a different vendor's clean marker already covers that exact HEAD and the merge gate was satisfied minutes earlier. Wasted compute, duplicate marker on the PR, and a closing line that contradicts the actual gate state. Observed at least twice in real use of fastxyz/pact v1.0.4 (claude-code adapter).
Two changes close it:
commands/review.md— add a "round-zero check" step (new step 3, between "read PR state" and "compute R counter") that mirrors/loop's round-zero check from v1.0.3. If a different-vendorREVIEW_CLEAN_*orLOOP_DONE_*exists on the current HEAD AND no unresolvedREVIEW_FINDINGS_*exist anywhere on the PR, the merge gate is already satisfied — print "Merge gate satisfied on HEAD<sha>" and EXIT. Do not run the lanes, do not run local gates, do not post a marker. Force-override available via/review <PR> --cross-verifywhen the user has a substantive reason to triple-check.commands/review.md— closing line MUST be derived from the marker body'sExisting markers on HEADfield, never from a template. Three cases enumerated (this clean + prior clean = gate satisfied; this clean alone = needs other vendor; findings = run /code or /loop).CONTRACT.md— add the requiredExisting markers on HEAD:field to bothREVIEW_CLEANandREVIEW_FINDINGSmarker schemas. The field enumerates every prior marker on the current HEAD (with ISO timestamps). The reviewer cannot post a marker without producing this list, which forces the round-zero check to be observed in practice even if the agent skipped step 3.
The two changes are intentionally redundant — they catch the same failure at different layers. The round-zero check prevents the redundant marker in the common case. The required schema field catches the residual case where the agent forgets the round-zero check too: it cannot fill out the marker body without enumerating prior markers, which surfaces the duplicate before posting.
Round-zero exit added to edge cases. commands/review.md Edge cases now explicitly documents the round-zero exit as the canonical "second vendor confirms gate already met" path — the symmetric counterpart to /loop's round-zero exit from v1.0.3. /review is the appropriate command when the user wants a literal review with no Coder phase even allocated; the round-zero check makes the two effectively equivalent when there's nothing to review.
No changes to marker types, severities, lanes, escalation triggers, or the merge gate definition. v1.0.4 agents continue to work; v1.0.5 adds a required field (gracefully detectable — missing field is a contract violation, validator updated).
commands/loop.md— add a "round-zero check" step that explicitly skips the Coder phase when the latest PR marker is a clean marker (REVIEW_CLEAN / LOOP_DONE) from any vendor AND no unresolved REVIEW_FINDINGS exist. Without this, a strict-vs-lenient reading of step 5a ("Coder phase: implement code, run gates, push") could let a lenient agent push speculative changes when there's nothing to address — which would (a) stale the prior vendor's clean marker, (b) waste compute, (c) risk introducing new bugs the prior vendor would then have to re-flag.commands/loop.md— explicit "Round-zero exit" edge case documenting thatInternal rounds taken: 0is the correct LOOP_DONE state when a different vendor's clean marker already covers the existing HEAD AND this vendor's self-review also finds it clean. This is the canonical "second vendor confirms first vendor's clean review" path.commands/loop.md— print-to-user note distinguishing the round-zero case from the normal case: when /loop's round-zero check fires AND a different vendor has already posted a clean marker, the merge gate is satisfied immediately; the user should be told that rather than "switch to another vendor's CLI and run /review".roles/coder.md— add a "Trigger (when the Coder is allowed to act)" section enumerating the three conditions under which the Coder may act (unresolved findings, initial R1, same-loop self-review findings). Forbids speculative pushes outside these conditions.
No changes to CONTRACT.md, marker formats, escalation triggers, or merge gate. Existing correct agents continue to work; the clarification removes a reading ambiguity that could cause lenient agents to push speculative commits and stale prior vendor clean markers.
commands/code.md— clarify that/codeaccepts findings from ANY vendor (different OR same), not only from a cross-vendor REVIEW_FINDINGS marker. Prior wording ("from a different vendor", "from another vendor") could be misread by a strict agent as a hard restriction, breaking composability with/reviewin the same vendor's window. The merge gate (§6) is enforced at the gate, not at the source of findings.commands/loop.md— same clarification on the "ingest cross-vendor findings" step; add an "Equivalence to manual composition" note explaining that/loopis the automated form of alternating/review+/codein one vendor's window, and the two produce semantically equivalent results.
No changes to CONTRACT.md, marker formats, escalation triggers, or merge gate. Existing agents continue to work; the clarification only removes a reading ambiguity that could cause stricter agents to refuse valid same-vendor /code invocations.
README.md— reframe the primary usage as the URL-only path: prime each session once with "Learn https://github.com/fastxyz/pact", then issue short commands like/code 282,/loop [10] 282,/review 282. No local install needed. The "install as native slash commands" path is demoted to an Optional section for frequent local use. This better matches ephemeral / VPS-hopping / fresh-session workflows where per-machine setup is friction.- No content changes to
CONTRACT.md,roles/,commands/, oradapters/. Behavior identical to v1.0.0.
Initial release.
CONTRACT.md— canonical rules: 3 lanes (CQ/SP/TC), 5 severities (P0/P1/P2/P3/Nit), 4 marker types (CODE_DONE, LOOP_DONE, REVIEW_CLEAN, REVIEW_FINDINGS), escalation triggers, disagreement protocol, merge gate.roles/coder.md,roles/reviewer.md— vendor-agnostic role definitions.commands/code.md,commands/loop.md,commands/review.md— vendor-agnostic command specs.
adapters/claude-code/— Claude Code skill files for/code,/loop,/review.adapters/codex-cli/— Codex CLI prompt templates for/code,/loop,/review.
scripts/validate-marker.py— stdlib Python marker validator with unittest suite.
README.md— leads with the merge gate; installation + opt-in instructions.examples/annotated-pr-loop-transcript.md— worked example of tight (/loop+/review) and granular (/code+/review) flows.