# Build Orchestration Protocol

How multiple agents build the 177 specs in `registry.json` without stepping on each
other, building out of order, or drifting on shared interfaces. Read this fully before
claiming any task.

## Source of truth

- **`registry.json`** — the authoritative build DAG. `tasks[].depends_on` decides build
  order. Spec `**Depends on:**` headers are documentation; where they disagree, the
  registry wins. Regenerate only via `node tools/build-plan-registry.mjs` (deterministic).
- **`status/<slug>.json`** — runtime status for one task. The only file an agent mutates
  to coordinate. Never put wave/dependency data here; that lives in the registry.
- **`tasks/<slug>.md`** — the implementation plan for one spec. Authored once, then
  consumed by the building agent.

## Task lifecycle

Each `status/<slug>.json` moves through:

```
PENDING  →  WORKING  →  COMPLETED
                    ↘  BLOCKED   (only if a dependency failed / plan is wrong)
```

- `PENDING` — not started.
- `WORKING` — an agent has claimed it. Set `claimed_by` (agent id) and `started_at`.
- `COMPLETED` — spec built, committed, and self-verified. Set `completed_at`.
- `BLOCKED` — cannot proceed; put the reason in `notes`. Surfaces to the orchestrator.

## Claiming a task (the dependency gate)

An agent may claim task `T` only when **every** slug in `registry.tasks[T].depends_on`
has `status == COMPLETED` in its `status/<slug>.json`. This is the hard gate that
prevents building a module before its foundation exists.

1. Read `registry.json`; pick a `PENDING` task whose `depends_on` are all `COMPLETED`.
2. Re-read its `status/<slug>.json`; if still `PENDING`, write `WORKING` + `claimed_by`
   + `started_at`. (Last-writer-wins claim; if two agents race, the later one picks
   another task.)
3. Build per `tasks/<slug>.md`.
4. On success: commit, then write `COMPLETED` + `completed_at`.
5. On failure: write `BLOCKED` + `notes`; do not leave it `WORKING`.

Resumability: on restart, an agent scans `status/` — anything `WORKING` with no recent
progress can be reclaimed; `COMPLETED` is skipped; `PENDING` with satisfied deps is fair game.

## Waves

`registry.tasks[].wave` is the topological layer (0 = `foundation-monorepo`, the root).
Waves are a *scheduling hint* for parallelism: all tasks in wave N have all deps in
waves < N, so a wave can run concurrently once the prior waves are `COMPLETED`. The
dependency gate above is what's binding; waves just tell you how wide you can fan out.

## Cross-cutting authority (non-negotiable for every task)

These are not tasks — they are standing constraints every plan author and builder honors:

- **Dialect** (`registry.dialect`): Neon Postgres via Hyperdrive — **not D1, not SQLite**.
  UUID PKs `gen_random_uuid()`, `*_id` FKs UUID→UUID, `*_at` TIMESTAMPTZ, BOOLEAN, JSONB,
  enums as `TEXT ... CHECK (...)`. Never reintroduce integer PKs or SQLite types.
- **Audit spec** (`registry.cross_cutting_specs`): security > a11y > i18n/RTL > performance
  requirements are already embedded in the specs (CSP, timing-safe equality, aria roles,
  RTL, reduced-motion). Preserve them; do not strip them when transcribing a spec to a plan.

## Cycle cuts

`registry.cycle_cuts` records the 4 dependency back-edges removed to make the DAG acyclic,
each with a reason. The dropped edge is a soft/documentation relationship, not a build
prerequisite — build in the order the registry encodes, not what the spec header suggests.
