Rendered from the repository — the file stays the source of truth.
Process — project history
Status: Snapshot as of 2026-08-18, written by session C4. The cross-cutting story: how the project is built, what the working model delivered, and where it rubbed. Later sessions append below rather than rewriting. Sources: PR descriptions,
handovers/,product/roadmap.md,product/security.md.
The setup (2026-08-17, PR #1)
- Bun as package manager, workspace manager, script runner, and test
runner (
apps/*,packages/*); mise pins the tools outside the JS dependency tree (Bun itself, Terraform, the Supabase CLI); varlock declares every environment variable in a committed.env.schemawhile secret values live in Proton Pass and resolve into an untracked.env.local. Two hard rules from day one: never pin dependency versions from memory (alwaysbun add), and never print or commit secret values. - Conventions were committed before any feature existed: nested AGENTS.md
files per workspace, Angular-style branch naming (
<type>/<topic>), Conventional Commits, work in git worktrees under.worktrees/— never directly onmain.
Docs before code (PRs #2–#5)
The first four content PRs were documents, merged as a stack in order: the product scope (adopted from a ChatGPT-drafted feature catalogue of the real Gemini Notebook, with a provenance header saying exactly that), the feasibility study (three parallel research passes over primary sources, producing verdicts F-1..F-10 and decisions D-1..D-7), the UI research (top-down decomposition of the real product from live screenshots), and the roadmap. Decisions have been numbered ever since (D-8 arrived with spike D1, PR #8), which is what lets every later PR say why by reference — and what this history links to.
The working model
- Sessions. The planning unit is a session: one goal, one branch in a
worktree, one PR, one handover note in
handovers/. Time estimates for agent-executed work are unreliable, so the roadmap’s dependency DAG is the contract and day numbers are loose guidance (product/roadmap.md). - A foreman and parallel lanes. A foreman session plans, writes briefs, reviews PRs, and merges; worker sessions execute one brief each. Worker PRs carry “Do not merge — foreman reviews.” Four lanes run in parallel — A (core product, the critical path), B (platform), C (static sites), D (audio differentiator) — under two ground rules: Lane A always wins conflicts, and a session that can’t merge within a day is too big.
- Briefs carry boundaries. Each brief names allowed and read-only
surfaces plus expected “hot files” (shared files like
bun.lockthat several lanes touch); sessions list their actual hot-file changes in the PR so the foreman can sequence merges deliberately. - Risk first. The riskiest unknown (SSE through Scaleway’s gateway) was deliberately scheduled as the first platform session (B1) rather than late — it decided D-7 on day 1 with measurements instead of leaving a possible VM migration hanging over the week (PR #11).
- The security register (
product/security.md, PRs #16, #17) turns review findings into numbered SEC rows with explicit prototype-acceptance rationale and hardening triggers, instead of burying them in PR comments. “Accepted” always names the trigger that revokes it. - The owner stays in the loop at decision points, not keystrokes: confirming the Marginalia name mid-session (C1), re-weighting the TTS criteria mid-spike (D1), dictating the Impressum data verbatim (C3), approving deploys (B2), and deciding D-1 (Node runtime).
What the parallelism actually delivered
Wave 1 landed in one day. On 2026-08-17, eleven PRs merged: the scaffold, all four founding documents, A1 (domain schema), A2 (auth + library), B1 (SSE spike, D-7 decided), C1 (marketing site), C2 (docs site), and D1 (TTS spike, D-8 decided) — four lanes genuinely in flight at once (PRs #1–#11). Day 2 (2026-08-18) added A3 (ingestion), B2 (CI + deploys — the sites went live), C3 (legal pages), the security register, and a deploy fix (PRs #12–#19). Review capacity — not execution — was the bottleneck, as the roadmap predicted.
Where it rubbed
bun.lockis the collision point. Nearly every session adds dependencies, and they all funnel into the root lockfile: A1, C1, C2, B1, and A3 each listedbun.lockas a hot file. The mitigation is procedural, not technical — PRs declare the change, Lane A wins, and the losing branch re-runsbun addafter rebasing (spelled out in B1’s PR). It worked, at the cost of foreman attention on every merge.- Two spikes appended to the same document. B1 and D1 both appended to
product/feasibility.md’s decision and risk sections in parallel; D1’s PR predicted the conflict and specified the resolution (“keep both”) in advance. The conflict happened as predicted and resolved trivially — declaring expected conflicts in the PR turned a merge hazard into a non-event (PRs #8, #11). - Cross-lane coupling surfaced at deploy time. A2 made the webapp build require Supabase env values, which silently broke B1’s Dockerfile on main — discovered only when B2 built the deploy image. B2 added the build args on its own allowed surface and noted that main’s Dockerfile alone no longer built (PR #13). Hot-file lists cover shared files; shared build contracts had no equivalent declaration.
- CI found what local runs couldn’t. The
bun testexit-99-despite- passing quirk and PGlite’s slow cold init existed from A1 onward but only surfaced when B2’s CI checked exit codes on a slow runner — a working argument for getting CI up early in the week (details inproduct/history/infrastructure.md). - Sequencing against going public. C3 (Impressum + privacy pages) was inserted into the roadmap on 2026-08-18, explicitly before B2 made the static sites publicly reachable (PR #12) — an example of the roadmap being extended mid-flight, as its own status header invites.
- The B1 false start. Two sessions opened with the B1 brief on
2026-08-17: the first, launched at
16:21, ended after four API calls ($1 of usage) with no commits and no PR trace; a fresh session at ~16:26 with the identical brief did all the actual work and produced PR #11. What ended the first session is unrecorded — it predates the correct-the-record convention. It was found only retroactively, in the foreman’s cross-session usage analysis on 2026-08-18; the aborted session was invisible in the git/PR record. Resolution: relaunch with the identical brief — nothing was lost because nothing had been produced. The process lesson: session starts are cheap and disposable precisely because briefs are self-contained and re-runnable. (Source: foreman session record, recorded via PR #22 — see “Correcting the record” below.) - GitHub itself flaked mid-wave. During the evening merges of PRs
#9–#11
on 2026-08-17, GitHub’s API intermittently returned HTTP 503 (“No server
is currently available”) — merges and PR reads failed mid-sequence.
Found by direct
ghfailures while the foreman was merging the reviewed wave; absorbed by a background retry loop (re-attempt every ~15 s, checking merge state each pass) that landed both blocked merges on the fourth attempt, while B1’s conflict resolution proceeded locally in parallel — git itself was unaffected. The lesson: external-platform flakiness is absorbed by making merge operations idempotent-and-retried, not by waiting. Nothing in the repo record shows it happened — which is precisely why this history page exists. (Source: foreman session record, recorded via PR #22.) - Third-party review automation throttled during the wave. The CodeRabbit reviews on the day-1 merge wave repeatedly hit the plan’s rate limit (visible in the PR comment threads of #6, #10, #13); the foreman’s own review remained the effective gate.
Correcting the record
Three incidents on this page and in product/history/webapp.md — the B1
false start, the shadcn CLI flag change, and the GitHub 503 window — appear
in no PR, handover, doc, or commit: they lived only in the foreman
session’s own history. C4’s first draft omitted them under its
every-claim-traceable rule; the facts were then supplied from the foreman
session record and confirmed by the owner during the review exchange of PR
#22, which is now
their citable source. The gap the rule caught is itself the finding:
session knowledge that never reaches the repo is invisible to every future
reader, and this history section exists to close exactly that gap — this
correction being its first proof.
Where the process stands
Eleven working sessions and nineteen PRs in, the conventions have held: no
work on main, every session ended in a reviewed PR and a handover, and
both spikes converted risk into numbered decisions before feature work
depended on them. The known process debts are the ones the friction list
implies — shared build contracts between lanes are only caught at
integration time, and hot-file resolution costs foreman attention on every
overlapping merge.
Why human-in-the-loop between sessions (extended 2026-08-18, session C6)
A natural question about this working model: why review at every session boundary instead of letting one long agentic loop run the whole roadmap? The owner’s rationale, recorded here from the foreman exchange of 2026-08-18: reviewing each session’s output allows observation of intermediate results, so diversion or drift is detected early instead of compounding across an unattended run; and the checkpoints are where requirements get fine-tuned and external feedback injected. The roadmap itself is the evidence — C3 (legal pages before going public), C4–C6 (history, architecture views, this rationale), and A7 (the D-9 test migration) were all added mid-flight at review boundaries, none of them in the original plan. The review gate is not overhead on the process; it is where the process steers.