A+BThe build-system story

How it was built

One person, a library layer from April, and a performance rig started in July and built mostly in August and September by an agent build system. Every number on this page carries the command that produced it.

ADeck A / The person

One person sets the direction.

Open DJ is a personal project by Alex Foster. Agents write much of the code; the repository cannot say how much, because most agent work is committed under one human name. It also records what the person does, often in Alex's own words, with a date.

Direction, in writing

“An agent-drivable DJ rig, built to open up the DJ-software moats.”
The project's own statement of what it is, docs/architecture.md, rewritten Sat 15 Aug 2026.
“Ground up - we just want to build this to be as easy to mod [while] having great performance, advanced beatgrid functionality, stems etc.”
Alex Foster, in a prompt to the build agents, Tue 18 Aug 2026.

The calls a person makes

  • Scope. MIDI controllers came back into scope as a secondary priority on Sat 15 Aug 2026, after an earlier exclusion (docs/architecture.md).
  • What blocks v1. On Fri 28 Aug 2026 Alex raised that tracks imported straight into Open DJ were second-class without rekordbox, and that became a v1 gate (PARITY-TODO.md).
  • Rules for the agents. The house rules agents work under are Alex's directives, dated: requirements change in the same pull request as behavior (Tue 1 Sep 2026); new code must be portable to macOS, Linux and Windows (Thu 1 Oct 2026). That is a rule for the code, not a build: the only app you can run is for macOS on Apple silicon.
  • Calls only a person can make. Licensing, such as whether a GPL tag reader ships in the app (PARITY-TODO.md calls shipping it a "licensing call for Alex").
  • Taste. The wordmark face, Anybody 800 at width 150, was picked by Alex on Thu 10 Sep 2026 from a blind keep-or-cut comparison of nineteen candidates (docs/brand/wordmark-font/README.md).

The timeline

  1. First commitThe repository starts as a library toolchain: sync, enrichment and repair across rekordbox, djay Pro, Serato and Traktor.
  2. v1.0 of the library toolchainTagged and released. This layer is a live dependency of everything after it.
  3. The performance rig startsThe four-deck screen and the Web Audio engine. By Wed 22 Jul 2026, full-height beat grids, quantize, strict BAR beat sync and master tempo had shipped (PARITY-TODO.md).
  4. Most of the build88.6% of the commits since Wed 1 Jul land in these two months: stems, lyrics, controller hardware rounds, the agent command line and MCP server, the desktop app.
  5. LaunchAlpha, macOS on Apple silicon, once the release checks pass.
BDeck B / The machine

The machine that builds the app.

The product and the build system grew up together. Work moves through five steps, and only the last one touches main.

  1. IssueIssues in the private repository are the queue; the public mirror will not take issues. Each one is a unit of work with acceptance criteria.
  2. ClaimA worker claims an issue in a shared ledger before building, with a time-limited lease, so two agents rarely build the same thing.
  3. BuildAgent workers on several machines build in parallel, each on its own branch and worktree, with tests.
  4. GateA pull request head runs the tests its change affects, and a model review is required at that head. During a September ship-mode push, agent lanes merged without waiting for CI (ADR-0042).
  5. MergeA merge queue is the only path to main, and it runs the designated test lane on the exact tree that lands.

Reviewers from several vendors

Each pull request head needs a review from at least one of five reviewer lanes: OpenAI Codex, Sol (an OpenAI model run through the Codex command line), xAI Grok, Cursor and Anthropic Claude. If one lane cannot review, the next one is tried. These reviewers are models, not people, and agents merge their own pull requests once the gates pass, so this is automated review, not independent human review.

No review thread left silent

Every review thread ends fixed, rebutted with the reasoning, or logged as debt. The rule is that a blocking finding is fixed or rebutted before merge, not logged as debt.

A check that cannot measure says UNKNOWN

The repository's verification rule: prove the presence of the good thing, never the absence of a bad thing. A tool that cannot measure reports UNKNOWN, never a pass.

Decisions and requirements are written down

The rules: each architecturally significant choice gets a decision record, and any pull request that changes behavior updates the requirements file in the same change.

BFrom the build notes

Measured, not assumed.

Three entries from BLOG-NOTES.md and docs/library-availability.md, the project's own working notes. Each ends in a number someone can re-derive.

A preview that held 129 MB forever

Asked how long the library preview kept a track in memory, the answer read out of the code was: for the rest of the session. One decoded track sat in a single slot, released only by the next click, and a 383-second track held 129 MB. It now has a byte budget, an idle release, and the sounding track pinned so it is never evicted mid-play.

743 ms to 28 ms

The obvious fix for a slow preview was to prefetch the file. Measured, most of the wait was decoding, not transfer. Warming the decode on a half-second hover took a cold 743 ms click to 28 ms. The first set of timings was thrown away, because the machine was overloaded when it was taken: a number known to be garbage is worse than no number.

Undo, proved

Relinking points dead library rows at files that do exist, and never moves a file. Its undo was tested on a scratch copy of a real one: apply changed 172 rows, undo reverted all of them, and a 8,355 by 11 cell-by-cell comparison found zero differences outside the update timestamp. A smaller version of it, 5 rows on a scratch copy, is now a regression test that runs wherever a real library is present.

A+BThe numbers

The numbers, and how to get them.

Measured Fri 2 Oct 2026 on main at 487fa677d7. They change with every merge. The commands below reproduce them, with TZ=UTC set, in the private development repository at that SHA; the public mirror rewrites commit ids and leaves out some paths, so a public clone gives different ids and counts. The Build page has the full snapshot, month by month.

FactValueHow it was measured
First commitThu 16 Apr 2026git log 487fa677d7 --reverse --format=%ad --date=short | head -1
Commits since Wed 1 Jul10,554git log 487fa677d7 --since=2026-07-01 --format=%h | wc -l
Merged pull requests since Wed 1 Jul (merge commits plus squash merges)2,097evidence/merged-prs.sh <clone> 487fa677d7
Of those, squash merges505git log 487fa677d7 --no-merges --since=2026-07-01 --committer=GitHub --format=%s | grep -c '(#[0-9]*)$'
Share of post-July commits in Aug and Sep88.6%(1,031 + 8,318) / 10,554, months from --format=%ad --date=format:%Y-%m, author date in the author's own time zone. By committer date in UTC: 89.0%.
Architecture decision records226git ls-tree --name-only 487fa677d7 docs/decisions/ | grep -c '^docs/decisions/ADR-'
Requirement checkboxes744 checked, 101 opengit show 487fa677d7:.planning/REQUIREMENTS.md | grep -c '^- \[x\]'
Tracked files9,474git ls-tree -r --name-only 487fa677d7 | wc -l

Commits by month

Author date, commits reachable from main at 487fa677d7, agent and bot commits included. Bars are to scale. Hover a row for the command.

Apr447
May0
Jun6
Jul549
Aug1,031
Sep8,318
Oct 1-2655

What these numbers do not say

  • A commit count is a volume signal, not a productivity claim. It includes agent and bot commits.
  • Most agent work is committed under one human name, so author counts cannot separate human from agent work.
  • The pull request count joins two kinds of merge, counted by pull request number: 1,592 merge commits and 505 squash merges.
  • The project did not start from zero in two months. The April library layer came first, and the rig depends on it.
  • No lines-of-code figure is quoted, and no cost or token figure, because none has been measured from billing.
BThe goal
“open-dj could rebuild itself from scratch in a week”
Alex Foster, in a prompt to the build agents, Fri 2 Oct 2026, stating the goal for the build system. It is a goal, not a result: no timed rebuild has been run. A real run would log its start and end SHAs, its wall-clock time, which requirements passed, and the gaps it failed to reproduce.
A / Parity
Beyond / B { type: 'crossfader', value: 0.50 }