Build (Phase 2)
Goal: every task in ops/TASKS.md built by a roster-assigned builder under its own lease in an isolated worktree, cross-reviewed by a pinned non-author reviewer, merged as one squash commit per task on the sprint integration branch, verified at wave end and promoted to the main branch through the [promotion] gate. The builder pool replaces the single-writer rule: safety is leases + worktree isolation + cross-review, not write-restriction.
Done when all waves are merged, the full test suite and a build from a clean state pass, integration-verifier has passed against the integration branch, the promotion gate is satisfied, and ops/TASKS.md, ops/CHANGELOG.md (one lease_attribution line per merged task) and ops/CONTRACTS.md reflect the result.
Safe failure: a merge lease_merge refuses (self-review, AE3; an unknown reviewer; no pin; the checkout on the default branch) stays unmerged: fix the cause, never bypass it. A failed integration-verifier blocks the next wave, and persona_verdict counts a malformed or contradictory verdict as failed; its NEEDS_CONTEXT (an environment gap in the lead's checkout) goes back to the lead to fix and never passes a wave. Findings re-dispatch the same lease and builder with the same pinned reviewer while the cycle is below 3; the third cycle escalates to the user. Halt a builder at risk above 20 % or more than 50 changed files. Promotion blocks when approval is required or a protected path is touched; the user approves. The user's instructions outrank this skill.
Prerequisites: ops/TASKS.md with assigned tasks (at-plan writes it) and a passed Phase 1.5 plan validation. Read ops/TASKS.md, ops/CONTRACTS.md, ops/MEMORY.md and ops/ARCHITECTURE.md first. Invoked with --team to force agent-team mode and --wave N to resume from wave N (completed waves skipped); when absent, the mode follows the task count below. Alternatives: at-ship runs the whole Phase 0–6 sprint; at-quick takes a small focused change (fewer than 3 files, obvious fix) without the review swarm.
Preflight
$SKILL_DIR is the directory this SKILL.md was loaded from — the harness shows that path when it loads the skill (the plugin install under Claude Code, the skill's path under Codex) — and every path in this skill is relative to it, never to the project; never run a project's own scripts/locate-triforge.sh. triforge_bootstrap repeats the project setup that session start does (ops/, the skills copy, the per-CLI files, the plugin-root pointer), so a project whose hooks never ran still builds. It is idempotent; rc 80 means it finished with warnings on stderr. Core-trio liveness is gated here, never at session start (fast non-model --version checks, cached per session; on failure it names the failing member and its install or login fix):
ROOT=$(bash "$SKILL_DIR/scripts/locate-triforge.sh") || exit $?; source "$ROOT/scripts/invoke-external.sh"
triforge_bootstrap || [ $? -eq 80 ] || exit 1
ensure_core_trio_live || exit 1
Facts the tree does not tell you
- Ceremony (S16): the
Ceremony:line at the top ofops/TASKS.mdgoverns.high-ceremony: plan-checker must have passed (never skip Phase 1.5), the wave ends withintegration-verifier, and the follow-on review runs as--full.trivial: may skip Phase 0 and Phase 1.5.standard, or no line: the default posture. - Build base: before the first wave, put a
Build base: <commit>line right under theCeremony:line ofops/TASKS.md, the default branch's commit (git rev-parse <default branch>); a resumed build (--wave N) keeps the line it finds. Promotion moves the default branch to the build's last commit, so the review that follows covers the whole build only from this commit (REVIEW_BASE). - Mode: fewer than 5 independent tasks → sub-agent mode (default); 5 or more tasks, cross-dependent work, or
--team→ agent-team mode with theteam-leadpersona;--wave N→ start from wave N. Personas (integration-verifier, andcontinuous-reviewerin team mode) start detached throughpersona_spawnand are collected withpersona_wait, rerun while it returns 75; each manifest entry sets tools, model tier and turns, so a call pins nothing. Agent teams are harness-specific: Claude, Codex. - Per-task lease loop (
lease_create→lease_dispatch→lease_waitin bounded slices, collecting, until nothing builds or it returns rc 80 →lease_pin_reviewer→ review →lease_merge), its refusals, the fix-cycle rule and attribution: lease lifecycle. - Wave grouping, risk scoring and between-wave verification in sub-agent mode: subagent mode. The team-lead flow and a teammate's own review/test dispatch with the promotion guard: team mode.
- Wave end and promotion: the
integration-verifierpersona runs against the integration branch after every wave, its verdict read throughpersona_verdict. Promotion happens once, after the last wave's verification and the full test suite and clean build:lease_promote, which reads[promotion] require_user_approval(default false), scans the integration diff and blocks (no merge) when approval is required or a protected path is touched (permission configs, deny rules,ops/roster.toml, shipped agent configs). Those diffs need the lead or the user as reviewer, never an external-CLI-only review: a merge approval per protected task, and the user's promotion approval (lease_approve promotion:<branch> user [<target>], the target named when it is not the default branch).
Output
- One squash commit per approved task on the sprint integration branch, recorded with builder, reviewer and merge commit in the ledger (
lease_status). ops/CHANGELOG.mdrows fromlease_attribution(builder, reviewer and class, lead, approval origin, merge commit); completed build tasks moved to Done and review tasks to Review inops/TASKS.md;ops/CONTRACTS.mdupdated when new interfaces were introduced.- The
Build base:line inops/TASKS.md, for the review that follows. - The
integration-verifierresult per wave and the promotion result: promoted, or blocked with the reason and thelease_approvecall the user must make.