12. Build record
This plan ran. It is not a queue. Every wave it named has a package in this repository. Read it to see why the tree looks like this, not to pick a next task.
The leftover names are follow-ups, not items waiting in this schedule. create-avelon is not in the repository. Vigil, Peal, Moot, Banner, and Lantern are named and not built. The first public npm line is a human action. See docs/16-releases.md.
The schedule was set by three things that do not compress:
- Contract freeze. Parallel agents cannot negotiate interfaces mid-flight. Twenty agents building against an unfrozen
QueryIRproduce twenty incompatible packages that each pass their own tests. - Verification against live services. RLS enforcement, PostgREST embed depth, pgmq visibility timeouts, Bun on Vercel. Wall-clock bound regardless of how many agents run.
- Review bandwidth. Agents produce competent-average by default. The TUI feel, the error message wording, and the docs voice decide whether anyone loves this. That work does not parallelize.
Dependency graph
S1 decisions ──▶ S2 contract freeze ──┬──▶ S3 conformance suites ──▶ Wave A (drivers)
│ │
└──▶ Wave B (core subsystems) ───────┤
▼
S4 integration
│
▼
Wave C (surface)
│
▼
Wave D (launch)
Serial spine
S1. Decisions locked
Owner was the human. Output is docs/02-decisions.md with chosen answers and runner-ups, and the umbrella name Avelon.
This blocked everything. The name blocked the scope, which blocked every package name.
S2. Contract freeze
Owner was the human plus an adversarial review loop. This was the gate.
Frozen and published in @avelonjs/core at s2-contract-freeze:
QueryIRandPredicateAdapter- All sixteen driver contracts and their capability shapes
- The error taxonomy
- The capability narrowing type machinery
HttpRequest,ActionResult,ViewResult- The event and listener contracts
Acceptance that landed: @avelonjs/core typechecks, every contract has a doc comment, and the capability narrowing spike passes with every @ts-expect-error firing.
Nothing downstream started before this landed. A contract edited later to unblock one package still silently breaks every package built against the original. That rule did not expire.
S3. Conformance suites
Landed in @avelonjs/conformance before the drivers. One suite per contract. These were the acceptance criteria that let Wave A run without a human reading each driver.
Acceptance that landed: each suite runs green against its fake and red against a deliberately broken stub.
S4. Integration
Landed in @avelonjs/s4. The vertical slice end to end: a Post resource with routes, controller, request, model, ward, policy, views, one event with a queued listener, running on both database drivers.
Gazette later proved the same slice inside a real application. The failure mode this milestone existed to catch was twenty green packages that do not compose.
M0 spike
Ran before S2 and informed it. Prove what can kill the design, build no features. The findings live in .avelon/checkpoints/checkpoint-1.md. D25 through D28 closed the escalations. Bun as the Vercel function runtime stayed unverified and is still opt-in. See docs/11-runtime.md.
| # | Assumption | Fails if | Falls back to |
|---|---|---|---|
| 1 | Domain directories colocated inside Next's app/ survive next build and never route | any domain directory becomes reachable as a URL | src/app router, domain code renamed |
| 2 | Generated server actions dispatch to a controller class and return validation state | action serialization rejects the pattern | route handlers plus _method |
| 3 | Bun runtime on Vercel serves Next with ISR and middleware | any of the three breaks | Node runtime, Bun for tooling only |
| 4 | A ward compiles to RLS and the same predicate scopes a query identically | results diverge on any fixture | wards become client-side only, RLS documented as manual |
| 5 | Throwaway Hono adapter serves the same controllers | the contract needs Next-shaped concepts | adapter abstraction dropped, Next-only |
| 6 | The query IR compiles for both Supabase and Postgres with identical results | the IR cannot express one driver's needs | IR redesigned before S2, not after |
Assumptions 4 and 6 ran against a live database. No mocks.
Wave A: drivers
Landed after S3. Acceptance was conformance green.
| Package | Implements | Notes |
|---|---|---|
@avelonjs/supabase database | database | includes the ward-to-RLS compiler |
@avelonjs/supabase identity | identity | |
@avelonjs/supabase social | social | |
@avelonjs/supabase tokens | tokens | |
@avelonjs/supabase storage | storage | |
@avelonjs/supabase queue | queue | pgmq plus the drain worker |
@avelonjs/postgres | database | transactions, deep relations, window functions |
@avelonjs/neon | database, identity, social, tokens, storage, queue | Neon Auth + S3; database wraps @avelonjs/postgres |
@avelonjs/resend | ||
| fakes | all sixteen | one agent, mechanical, in @avelonjs/conformance |
Wave B: core subsystems
Landed in @avelonjs/core and @avelonjs/orm, gated only on S2.
| Package | Scope |
|---|---|
| query IR builder | predicate construction, relation planning |
| Scrivener | models, relations, scopes, casts, timestamps, soft deletes, lifecycle hooks |
| ward compiler | predicate to SQL policy, predicate to IR injection, drift detection |
| events | dispatch, priority ordering, propagation halt, afterCommit, until |
| errands | job contract, three delivery modes, retry, failure table |
| policies and gate | registration, authorize, can |
| requests | Zod integration, error shaping, authorize hook |
| config resolution | driver wiring, environment merge, capability matrix |
| error taxonomy | base classes, cause chaining, adapter mapping |
Wave C: surface
Landed after S4.
| Package | Scope |
|---|---|
@avelonjs/next | route codegen, action dispatch, page wrapper, middleware bridge |
| hono spike | throwaway, proved the contract, never shipped. D26 revised write routes and views. |
@avelonjs/cli | TUI, every generator, stubs, doctor, tinker |
@avelonjs/bailiff | every rule with reasons and autofixes |
| assay | test harness, HTTP helpers, factories, seeds |
Wave D: launch
Landed in this repository.
| Item | Scope |
|---|---|
| docs site | the Avelon vocabulary and command map is the landing page, not a sub-page |
| example app | Isle Gazette, a complete application, not a todo list |
| docs app | the same Markdown, served as an Avelon app |
docs:check | README linting for packages |
| driver authoring guide | how to write and certify a driver |
| npm publish | lockstep pack of @avelonjs/*. First public line is still a human 0.1.0. |
What did not land
create-avelon. D19 said the framework is a dependency. Copyexamples/gazetteuntil the scaffolder exists.- Vigil, Peal, Moot, Banner, Lantern. Named. Not built.
- Bun as the Vercel function runtime. Local Bun serving passed. Live Vercel did not run.
How work was accepted
Every package used this bar. New work still uses it. See AGENTS.md.
Title
Scope: what is in, what is explicitly out
Depends on: contract or package names, never "the other agent's work"
Acceptance:
- bun test green, including conformance for any contract implemented
- tsc --noEmit clean under strict
- reeve bailiff clean
- named integration test passes
- reeve docs:check clean
Escalate if: the specific conditions that mean stop and ask
If acceptance required a human to exercise judgment about whether the result was correct, it was not a package task. It was a design decision and it belongs in docs/02-decisions.md.
Estimate
Historical. Do not re-estimate from this page.
Two to three weeks wall clock was the figure, and almost none of it was typing.
- S1 and S2 were a day or two of focused human attention.
- M0 was wall-clock bound by live service verification.
- Waves A and B were compute plus review queue depth.
- S4 is where the estimate lived.
- Waves C and D were fast but taste-bound, and taste does not parallelize.
The previous seventeen-week figure assumed human implementation. Roughly twelve of those weeks were implementation and five were judgment. Only the twelve collapsed.