How an idea becomes a tracked, buildable project on this machine — vault planning compiles into a dependency-aware issue graph, scaffolds its own repo, and is drained by an autonomous beads subagent. One command per stage; the contract between stages is deterministic.
Five stages. Each has one entry command and emits a typed artifact the next stage consumes. Nothing is hand-carried between stages — the vault PRD compiles into beads issues the same way every time.
The whole point of this flow: from the moment a project is created, everything about it lives somewhere you can reach from any machine — local laptop or a cloud box. Three things must travel, not just the code:
Code → GitHub · Deploy → Vercel (linked, env in all scopes) · Tasks → beads (in git + a cloud Dolt remote)
Clone the repo on any machine and you get the app, the deploy wiring, and the full issue backlog — no "but the tasks were on my other laptop." That requirement is exactly why Stage 3 includes Vercel + env, and why beads must reach a remote (below).
The PRD is the contract between thinking (vault) and execution (code). It lives at 2. Areas/Product Manager/PRDs/<Name>.md and follows a schema strict enough that a script can read it.
folder: join keyFrontmatter folder: names the repo directory — it's how the PRD binds to its code. folder: myrp-build-web → ~/code/myrp-build-web. This is the thread that ties spec to build.
A PRD without this section is not seedable. It forces three decisions before any issue exists — so scope is locked, not discovered mid-build:
Auth = none (stateless marketing site) · Freemium = display-only (purchase lives in the app) · 5 core features (landing, pricing, download, docs, audience capture). The whole site is "built from source" — content derived from the real myrp-build app, the same way braynee-web derives from hooks.json.
This is the magic step. prd-seed.mjs reads the Acceptance Criteria section and turns each line into a beads issue, deterministically. The format is the API.
# The seed contract — one line → one `bd create` ### Milestone: MVP - [ ] **[P0] Pricing page** — tiers from data/plans.ts; CTA = Download. No Stripe. └─────┘ └──────────┘ └──────────────────────────────────────────┘ priority bd title bd description
| In the PRD | Becomes |
|---|---|
[P0]…[P3] | priority (critical→low) |
title before — | bd title |
body after — | bd description |
### Milestone: X | label milestone:X |
| other lines | ignored |
P0 critical P1 high
P2 medium P3 low
The seeder also auto-adds a milestone gate: it wires dependencies so the Quality & Deploy issues block on the feature work.
Beyond your hand-written criteria, the seeder appends a Definition-of-Done molecule (the ship-pipeline gate, see §6) and adds dependency edges so the graph reflects real build order:
node prd-seed.mjs "myRP-build-Website" --dry-run # always preview first … Done. 28/28 issues would be created, 8 dep edge(s) would be added.
23 hand-written criteria + 5 auto-injected DoD issues = 28 beads issues, 8 dependency edges, across milestones MVP · v1.1 · v2 · Quality&Deploy. The PRD frontmatter flipped to seeded: true, seeded_count: 28 — so it can never be silently double-seeded.
Order matters: scaffold → bd init → seed → wire to Vercel. Each project is its own repo — never a monorepo, never nested in a parent — and creating the repo is not finished until it's connected to Vercel with env vars set across every scope.
# 1 · scaffold the app (Next.js App Router + TS + Tailwind) npx create-next-app@latest myrp-build-web --typescript --tailwind --app … # 2 · own git repo for THIS project (not the parent folder) git init -b main # 3 · beads, pointed at the shared Dolt server bd init --shared-server --external --prefix myrp-web --role maintainer # 4 · seed (stage 2) node prd-seed.mjs "myRP-build-Website" # 5 · create + push the standalone GitHub repo gh repo create hamchowderr/myrp-build-web --private --source=. --remote=origin --push
Repo creation isn't done at gh repo create. The repo must be connected to Vercel (so every push deploys) and have its environment variables set across all three scopes — production, preview, development — with values injected from Infisical or Agent Vault, never typed or committed.
# 6 · link the project + connect the GitHub repo (push → auto-deploy) vercel link vercel git connect # branch push → preview · main → production # 7 · set each var across ALL THREE scopes — value injected, never printed. # Infisical injects → piped straight into vercel env add (encrypted, not logged) infisical run --recursive --silent -- bash -c '\ printf "%s" "$NEWSLETTER_API_KEY" | vercel env add NEWSLETTER_API_KEY production preview development' # …repeat per secret. Agent Vault path: wrap the CLI via the VPS broker (HTTPS_PROXY recipe) # for VPS-brokered creds. Either way the value never lands in the transcript or a file. # 8 · pull a local .env.local for dev (placeholders only ship in .env.example) vercel env pull .env.local
| Scope | Used by |
|---|---|
production | the live main deploy |
preview | every feature-branch preview URL |
development | vercel dev / local pull |
A var missing from preview is the classic "works on prod, broken on the PR preview" bug.
infisical run --recursive --silent injects at runtime.Rule: confirm a secret by mask (type/length), never by value. Never infisical secrets/get/export — those print.
A repo with no Vercel link and no env is a half-created project — the first preview deploy will fail on a missing key. Treating link + env-everywhere as part of repo creation means the very first push already produces a working preview. (In the DoD gate, §6, these are phases 4–5.)
This session hit a stray empty git repo at ~/code itself. Because the projects-root was accidentally a repo, create-next-app saw "already in git" and skipped making one for the project — so setup commits landed in the wrong place. Fix: move the stray .git aside (preserved, never deleted), then git init the project on its own. Always verify git rev-parse --show-toplevel points at the project, not a parent.
Beads is the single source of truth for tasks. It mirrors two more ways so the agent's list, the live UI, and the vault never drift apart.
beads-todo hook fires on every bd state change to keep it in sync.Why three? Each serves a different reader: the agent queries beads, the human in the terminal watches TodoWrite, and the vault / future sessions read TaskNotes. Writing once to beads fans out to all three — this session, the seed reported TaskNotes: 28 new mirrored automatically.
braynee:autopilot is the engine that turns a seeded backlog into shipped work without hand-holding. It runs a tight loop and is CLI-only (no MCP) for reliability.
loop: bd ready → pick the next unblocked issue (deps satisfied) bd update --status in_progress → claim it (also mirrors to TodoWrite) …execute the work… → write code, run tests, commit on a feature branch bd close --reason "…" → done; unblocks dependents repeat # stops on: empty queue · failed claim · 3 consecutive failures
bd ready only surfaces issues whose blockers are closed, so the graph enforces build order (features before the DoD gate).bd update --add-note), surviving context compaction. A fresh session resumes from bd list --status in_progress."autopilot", "drain the queue", "work the backlog" → spawns the subagent. For myrp-build-web, the first ready P0s are Source-derived content data layer, Marketing landing, Pricing, Download.
Every project under ~/code inherits one DoD, auto-seeded as that Quality&Deploy molecule. DONE = CI green + a live preview deploy. Production promotion is always a separate, human-gated step — an agent never pushes to prod.
| # | Phase | What |
|---|---|---|
| 1 | Local build | scaffold per defaults; biome check clean; it builds |
| 2 | Test gate (pre-commit) | Tier 1: Vitest + Supertest, fully mocked, AIMock at the LLM boundary |
| 3 | Repo | gh repo create --private; work a feature/* branch — never commit to main |
| 4–5 | Link + env | vercel link; vercel env add across prod/preview/dev — secrets via Infisical, never pasted |
| 6 | CI gate | GitHub Actions runs full tiers (Vitest + Supertest + Playwright) with AIMock; green on the PR |
| 7 | Preview | push branch → Vercel preview deploy; capture the URL |
| 8 | DNS (if custom domain) | Cloudflare scoped token + API; else use the *.vercel.app URL |
Real API keys are the last tier, never the first.
The gate narrows itself: no custom domain → skip phase 8; no LLM in the loop → AIMock not required. State any deviation in the PRD.
⚠ For a static marketing site like myrp-build-web, the AIMock/Supertest parts of the auto-seeded gate don't apply — trim those issues to fit (lint + Playwright + preview).
"Tasks reachable from anywhere" is a real requirement with a real mechanism. Beads rides on Dolt — a MySQL-compatible database with git-style version control (history, diffs, branches, push/pull to a remote). That last property is what lets the issue graph leave this laptop.
bd auto-exports the whole issue graph to .beads/issues.jsonl, committed with the repo. Clone anywhere → the backlog comes with it (bd auto-imports on first use). This is wired today.~/.beads/shared-server/ (this run: port 3308); each gets its own DB (myrp_web). bd init --shared-server --external joins it — fewer orphan processes, one local home for live queries.chowderr namespace so it pulls across machines. The repo is auto-created via the DoltHub REST API (token in Infisical prod), then bd dolt remote add + bd dolt push. This completes "anywhere."① 28 issues committed as issues.jsonl in the GitHub repo · ② live in the local shared Dolt server (db myrp_build_web) · ③ pushed to chowderr/myrp_build_web on DoltHub (public, 28 issues verified via the SQL API). The DoltHub repo was auto-created programmatically: POST /api/v1alpha1/database with the DOLTHUB_API_TOKEN (Infisical prod) → bd dolt remote add origin chowderr/myrp_build_web → bd dolt push. Note: there is no otaku-solutions org on DoltHub — DBs live under the personal chowderr namespace.
The DoltHub remote (otaku-solutions org) is owner-specific cloud infrastructure — Chowderr's account, Chowderr's convenience for working across machines. When this project (or this whole workflow) is shared with anyone else, the DoltHub sync must not be a dependency. A collaborator clones the GitHub repo and is fully operational on tiers ① + ②: the issues.jsonl in git gives them the backlog, and a local bd init gives them their own engine. No DoltHub account, no otaku-solutions access, no paid tier required. This mirrors the standing rule that the tooling ships zero user-specific paid-tool dependencies — bake the cloud remote in for yourself, but the shared workflow degrades cleanly without it.
git rev-parse --show-toplevel before committing. No accidental parent repos.infisical run / Agent Vault — never print, paste, or commit values.--dry-run shows every bd create before it touches the tracker..git), move it aside recoverably and surface it — don't destroy what you didn't create.