Skip to content

Tight dev loop

One-command full-stack dev with backend hot-reload + frontend HMR.

./scripts/dev.sh
Brings up: compose stores + migrations (via start-compose.sh) → demo seed → gateway with uvicorn --reload (backend code hot-reloads) → frontend vite (HMR) pointed at the gateway → tails both logs. Ctrl-C stops the gateway + frontend (the compose stores keep running).

  • URLs: gateway http://localhost:8088 (:8000 is taken by another local app), frontend http://localhost:5174.
  • Options: --fe-mocks (run the SPA on MSW mocks instead of live), --no-fe, --no-seed, --gateway-port N. The frontend's gateway base comes from web/brain-builder/.env.development.local (which dev.sh writes) + inline env — note Vite ranks .env.development above .env.local, so the .local for the current mode (.env.development.local) is what reliably overrides it.
  • ./scripts/dev-down.sh stops the app processes; --stores also tears down compose.

What auto-runs / how to iterate

  • Backend code change → the gateway hot-reloads (no restart). (Once Phase 6 adds app Dockerfiles, dev.sh would build/restart that container instead.)
  • Frontend change → vite HMR reflects it immediately.
  • Schema change (models/migrations) → run alembic upgrade head (or ./scripts/start-compose.sh re-runs it), or wipe + reseed:
    ./scripts/reset-db.sh            # alembic downgrade base -> upgrade head -> bb seed-demo
    ./scripts/reset-db.sh --purge    # also clears data/git + data/lightrag (corpus + file lens)
    
    reset-db.sh is local-guarded (refuses unless DATABASE_URL is localhost; --force to override) and prompts unless -y.

Seeding

bb seed-demo (idempotent) provisions the demo: the four accounts (see docs/api/gateway.md) + the Meridian tenant end-to-end (brain → approved corpus → certified/published version → one pending change set). Safe to re-run; each step skips if already present.

Fast checks

./scripts/check.sh          # ruff + mypy + unit pytest + contract-check
./scripts/check.sh --all    # + frontend typecheck/lint + alembic migration-drift check (needs local stack)
./scripts/contract-check.sh # FE↔gateway drift only: every SPA /v1 path must have a gateway route
contract-check parses every /v1/... path the SPA references and asserts the gateway exposes a matching route (catches the missing/renamed-endpoint drift, e.g. the /coverage gap found during the joint integration). Allowlist intentional exceptions in scripts/_contract_check.py.

Migrations: change a model → migrate

Default workflow: whenever an ORM model changes, create + apply the Alembic migration as part of that change (never leave the schema un-migrated). Migrations are Postgres-targeted (some use ::json default casts) — they don't run on SQLite; unit tests use Base.metadata.create_all, so a migration round-trip is validated on Postgres (or via reset-db / a scratch DB), not the unit suite. ./scripts/check.sh --all runs alembic check against the local DB to flag a model that drifted from its migrations.