00The pivot
A golden template DB now exists (loquent_latest), already wired with the real working state. Cloning it is strictly simpler and more complete than recreating that state in code — so the roadmap flips from "build" to "copy".
Was · build from scratch
Raw-SQL seed recreates Twilio settings, imports numbers via API, clones agents in SQL (drift risk), inserts a max plan + staff + sample rows. Lots of code to write and keep in sync.
Now · clone the golden DB
pg_dump loquent_latest | psql loquent_<branch> → just migrate → just generate. The worktree inherits everything. ~30 lines of shell, zero drift.
01What we do instead
One change, in scripts/worktree-db.sh (run by just worktree-db): replace create-empty + seed with clone-the-template. The dev login already lives inside the clone, so you sign in with your existing credentials.
pg_dump --no-owner --no-privileges loquent_latest | psql loquent_<branch> into a fresh per-branch DB.
just migrate applies only the migrations the branch adds on top of the template.
just generate re-derives the SeaORM schemas from the migrated DB.
The just seed step is gone — the template already carries a ready-to-use account.
02Why cloning wins
The golden DB already contains exactly what the from-scratch seed was laboriously recreating. Each row below is a block of the old plan that the clone makes unnecessary:
| Old seed block | With cloning |
|---|---|
| Shared Twilio env-vars + settings insert | ✅ real organization_twilio_settings row copied as-is |
| Import numbers via Twilio API | ✅ the imported phone_number comes along |
| Agent-clone SQL drift risk | ✅ all 9 ai_agent rows copied verbatim — risk gone |
| MAX plan via raw SQL | curate once in the template (whatever it holds propagates) |
| Second staff member | curate once in the template |
| Sample contacts / messages / tasks / call | real data copied; curate the template to taste |
The biggest win: no more drift
Recreating clone_system_agent_for_user in raw SQL would have needed manual upkeep forever. Cloning copies the real rows, so agents (and everything else) always match production logic.
03The golden-template model
loquent_latest becomes the single source of truth for "what a fresh worktree looks like". Whatever it contains is what every worktree inherits.
Decision: clone as-is. No enrichment script — you curate the golden DB through normal use (add a teammate via the invite flow, set a plan, build out contacts). Every later worktree inherits that automatically, with no seed code to maintain.
Want richer defaults later (e.g. the org on the MAX plan, a second staff member, more sample contacts)? Just set them up once in loquent_latest — clones pick them up from then on. The change here doesn't preclude that; it just stops baking it into code.
04New worktree-db.sh flow
Create DB (clone of template)
If loquent_<branch> exists → skip. Else createdb, verify the template exists, then pg_dump … | psql. On failure, drop the partial DB and abort (no silent half-clone).
Point .env at it
Rewrite DATABASE_URL to the per-branch DB and export it for child processes.
Migrate on top
just migrate applies the branch's pending migrations — the cloned seaql_migrations table tells SeaORM what's already done.
Generate schemas
just generate re-derives src/bases/db/schemas/ from the migrated DB.
# override the template if needed
WORKTREE_TEMPLATE_DB=loquent_latest # default
# the clone, robust even while the template has open connections:
createdb "$DB_NAME"
pg_dump --no-owner --no-privileges "$TEMPLATE_DB" \
| psql -q --set ON_ERROR_STOP=1 -d "$DB_NAME"
Sibling change: APP_HOST is left alone
The creation script worktree.sh used to overwrite APP_HOST with localhost:<port>. It no longer does — each developer keeps their own ngrok URL there (inherited verbatim from the copied .env) so Twilio webhooks / Event Streams keep reaching the running worktree. Only PORT is rewritten.
05Clone mechanism chosen: pg_dump | psql
pg_dump | psql · chosen
Works even while loquent_latest has active connections (your main dx serve). --no-owner --no-privileges keep it role-agnostic; ON_ERROR_STOP=1 fails loudly. ~1 s for 17 MB.
createdb -T · not chosen
One fast command, but CREATE DATABASE … TEMPLATE errors if anything is connected to the template — fragile once main runs against loquent_latest.
06Migrations on top of the clone
The template tracks the migration HEAD it was last migrated to. A branch usually adds migrations, which apply cleanly on top.
Keep the template fresh
If loquent_latest drifts far behind main, a clone carries old data shapes that newer migrations must transform. Re-point/refresh the template periodically (it's the same golden DB you use daily, so this is mostly automatic).
07Verification passed
Smoke-tested the exact pipeline against the live template (cloned into a throwaway DB, compared, dropped):
clone pipeline: OK
source contacts=3 agents=9 phones=1
clone contacts=3 agents=9 phones=1
seaql_migrations carried over: 297 applied
Row counts match and the migration ledger comes across intact, so the on-top just migrate applies only what's new. bash -n on the rewritten script: clean.
08Decisions & scope
How to copy the template into the per-branch DB?
pg_dump | psql— robust while the template is in use.createdb -T— faster, but needs exclusive access.- Auto (try -T, fall back to dump) — more script complexity.
What does every cloned worktree start with?
- Clone as-is — mirror
loquent_latest; curate it through normal use. - Enrich the template once (max plan + staff + 10 contacts).
- Keep a from-scratch fallback seed for template-less machines.
Out of scope YAGNI
- Enriching the template (do it ad-hoc in the golden DB if/when wanted).
- A fallback seed for machines without
loquent_latest— the script errors with guidance instead. - PR-preview seeding — still
seed_preview's separate job, untouched.
09Retired design archive
The earlier from-scratch seed plan is superseded by cloning. Kept here only as a record of what it covered — none of it ships:
- Shared-Twilio
seed.envvars +organization_twilio_settingsinsert - Importing numbers via the Twilio
IncomingPhoneNumbersAPI - Raw-SQL clones of the 4 default AI agents (mirroring
clone_system_agent_for_user) - DB-driven Enterprise subscription +
org_budget+ Stripe sandbox keys - Second staff member +
staff_presence - 10 contacts with one rich contact (SMS thread, tasks, notes, call)
If a template-less path is ever needed (new machine, CI without a golden DB), this archived plan is the blueprint to revive — but the current direction assumes loquent_latest exists.