InputsSources of truth
Everything the agents produce is anchored on these files. They're hand-authored — not LLM-generated — so the system has a stable spec to converge on.
id, title, what, where, acceptance, tier (auto / ai_review / human_signoff), effort (S / M / L), and depends_on. Single source of truth for what's been merged vs pending.import type for type-only imports, .limit(1) not .single(), sky-blue palette only, no emojis, Heroicons, mock fallback, no edits to Phase 2 frozen files. Every agent reads this before touching code.{{TASK_ID}}, {{WHAT}}, {{WHERE}}, {{ACCEPTANCE}}, etc. substituted from backlog.json before dispatch.ProcessThe pipeline
An overnight build is one tour through this loop, repeated until the picker runs out of conflict-free work or a usage cap fires.
Picker selects the next batch
scripts/pick-next-task.sh scans backlog.json for tasks whose depends_on are all merged, sorts by effort (S < M < L) then module, and filters out anything that would collide with an in-flight task on a "hot file" (Settings.tsx, App.tsx, commission-engine.ts, etc.).Wave dispatched
backlog.json (status → in_progress). One agent spawned per task in an isolated git worktree. The wave gets a label like wave:wave-20260513-evening and a Teams "start" card showing all task titles.Agents work in parallel
CLAUDE.md + the dossier + its task spec, implements the feature, writes tests (≥80% coverage), runs tsc -b + vitest run in its worktree, commits, pushes a branch, and opens a PR with the wave label. Then stops.Gates run cloud-side
tsc + vitest + lint), Playwright smoke against the Vercel preview deploy, and CodeRabbit review all fire automatically. The merge bot waits for all three to be green before doing anything.Merge bot lands the PR
.github/scripts/agent-merge-bot.sh squash-merges the PR when its tier passes gates: auto tasks need CI green; ai_review tasks also need CodeRabbit ok; human_signoff tasks are labeled needs-zac and never auto-merged.Backlog + project board sync
backlog-merge-sync fires on every merge, flips the task's status to merged in backlog.json, then calls sync-project-status.sh to flip the GitHub Project board's Status column (Todo → Done).Orchestrator polls + dispatches the next wave
WorkersThe agents
Implementation agents general-purpose
One per backlog task. Spawned with isolation: "worktree" so each gets a clean checkout. Reads CLAUDE.md + the dossier, implements the feature, writes tests, opens a PR, stops. Tonight: ran 8-at-a-time in parallel.
Conflict-resolver agents on demand
Spawned when a PR has merge conflicts that the healer cron can't auto-fix. Brief: rebase against main, semantically merge hot files (append-and-keep-both for tab arrays / route lists), run tests, force-push with --force-with-lease. Proven across 4 stuck PRs tonight.
Finalizer (inline) orchestrator
When an agent's session is interrupted before commit (worktree-cwd bug, model timeout), the orchestrator finalizes work in place: runs tsc/tests, adds the smoke spec, commits, opens the PR. Used ~5 times tonight.
Healer cron every 30 min
fleet-healer.yml rebases DIRTY PRs, retriggers stuck CI runs, resets stale agent claims (>4h old) back to pending. Cloud-side, no human needed.
SafetyGuardrails
Nothing merges to main without passing all of these. Manual merges go through safe-merge.sh which enforces the same gates.
tsc -b
Strict TypeScript type-check. No any allowed. Fails the PR build if even one type error.
vitest run
Full test suite. 4,400+ tests currently. ≥80% coverage required on new code.
Playwright smoke
Hits the Vercel preview deploy on every PR. Each task adds a tests/smoke/T-XXX.spec.ts that verifies the feature renders without 5xx or page errors.
CodeRabbit review
Pro Plus, "chill" profile. Auto-reviews every PR against project-specific path instructions (RLS, migrations, commissions, AI features).
Vercel preview build
tsc -b && vite build against the PR branch. Catches drift between branches and main.
safe-merge.sh
Wraps gh pr merge. Refuses to merge if any gate above is pending or failing. Used by the orchestrator's manual sweeps so we never bypass CodeRabbit by accident.
VisibilityFeedback loops
Teams · wave cards
One "start" card when a wave dispatches (task list), one "summary" card when all PRs in the wave settle. No per-PR spam. No failure noise — channel is progress-only.
Teams · morning report
Daily 7am MDT card with PM-friendly LLM-generated prose summary (Claude Haiku), velocity stats, security wins, action items, and what's next. Auto-fires via morning-report.yml.
Public roadmap
/roadmap.html auto-refreshes every 60s from /api/backlog (live) or /backlog.json (static fallback). Shows phase progress, AI-time remaining, recent merges.
GitHub Project board
HealthDMS Backlog Status column auto-synced (Todo / In Progress / Done) via sync-project-status.sh on every merge.
Reality checkWhat's still manual
The pipeline above describes the ideal. Here's what currently still needs a human or has known rough edges:
claude -p auth on the Mac is fixed (likely fresh claude auth login), the launchd cron that would run dispatches unattended doesn't work. So today the orchestrator = a Claude session that the user kicks off with "@claude start overnight build."pwd; the finalizer recovers when it slips. Real fix lives in the Claude Code tool layer.openrouter-proxy edge function not yet deployed (gates all AI features). DocuSign / Sterling / NIPR adapters have base classes but full E2E flows are still WIP.scripts/burst-window.sh + launchd cron to run 3 bursts per night.