Development
Development
This is the practical guide to working in the Rakkr repository. The
machine-readable version for AI coding agents lives in
AGENTS.md; the authoritative roadmap and status ledger is the
source of truth.
Workspace setup
Rakkr uses mise for toolchains and tasks. From the repo
root:
mise trustmise run setup # install pinned toolchains, then pnpm dependenciesCopy-Item .env.example .envPinned tools come from .mise.toml — do not hand-edit
lockfiles or tool versions unless a task requires it. Run the stack with
mise run services:up + mise run dev (see Quick start).
Repository layout
apps/api/ Hono controller API and API testsapps/web/ React/Vite operator console and UI testspackages/shared/ Shared TypeScript schemas / contractspackages/db/ Drizzle schema, migrations, migration verifiercrates/recorder-agent/ Rust recorder node agentdeploy/ Ansible runner, nginx, Helm chartdocs/ This documentation (+ internal baselines)fixtures/audio/ Golden speech fixture and metadatascripts/ Gate scripts, smokes, baseline verifiersArchitecture details: overview, controller API, recorder agent, web console, data model.
Gates
Use the smallest meaningful gate while iterating, then the broad gate before handing off. The full task list is in the tasks reference.
mise run check # full repository gatemise run build # build everythingTargeted:
mise run node:check node:test node:lint node:format-checkmise run rust:check rust:fmt-check rust:clippy rust:mirimise run check:locmise run check includes the baseline verifiers, Drizzle replay, TypeScript,
Node tests, lint/format, the fake-controller agent smoke, and the Rust suite
(check, rustfmt, clippy, Miri). The DB verifier needs a working Docker/Postgres.
Conventions
- Formatting follows
.editorconfig: UTF-8, LF, final newline, trim trailing whitespace, two-space indentation (Rust uses four). - File size: keep files under the 1000-LOC budget enforced by
mise run check:loc. Prefer adding a new single-concern module over growing a large file — the codebase deliberately splits files this way. - Reuse existing patterns over new abstractions; don’t introduce new frameworks or formatters without explicit need.
- Shared contracts: when the API and UI need the same shape, use
packages/sharedrather than redefining types. - Authorization is server-side. UI visibility never replaces API RBAC. Every privileged action stays RBAC-gated and audited — see Authentication & RBAC.
- Dates are stored as UTC ISO 8601 and displayed in browser-local, year-first format via the existing helpers.
- Keep generated output (
dist,target, coverage, Vite output) and local.envfiles out of commits. Drizzle migrations are committed.
Slices travel together
Keep changes narrow and complete: code, tests, docs, and migration/evidence updates ship in the same slice. Many behaviors are guarded by a baseline doc + verifier; when you change an invariant, update the matching baseline and verifier too.
Database changes
Edit packages/db/src/schema.ts first, then:
mise run db:generate # emit migration SQLmise run db:migrate # apply locallymise run db:verify # replay against a throwaway databaseReview and commit the generated SQL and metadata with the schema change. See the data model.
Git workflow
git status --short --branch # before editinggit diff --check # before committingThis repo may have in-progress user changes — don’t revert, reformat, or
overwrite unrelated files. Commit only files relevant to the slice, with concise,
imperative messages (e.g. Add recording export audit coverage). Note any
skipped hardware-only smokes in handoff. Don’t promote source-of-truth status
unless code, checks, docs, and evidence support it.