Your first day
Get the application running, trace one review edit, and make a small change with the right checks.
1. Run a development copy
Use Bun for installs, scripts, and unit tests. Docker is optional if you already have a development PostgreSQL database. These commands run from the repository root. Use a separate local database for tests that edit reviews.
bun install --frozen-lockfile # Optional: start the Postgres service defined in docker-compose.yml docker compose up -d db
Create or update the ignored .env. For the supplied local container, use the
connection below. Obtain Clerk development keys for the project; the repository does not
contain them.
DATABASE_URL=postgresql://qccrm:development@localhost:5432/qccrm NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=<development publishable key> CLERK_SECRET_KEY=<development secret key> DOCUMENT_STORAGE=local
bun run db:status bun run db:migrate bun run scripts/seed-snap-negative.ts --no-reset --dry-run bun run scripts/seed-snap-negative.ts --no-reset bun run dev
db:status exits nonzero when migrations are pending; inspect its output
before migrating. Current code needs migrations through 0008. Non-reset
seeding skips matching business identities; published-policy or sample-month conflicts
fail. bun run db:seed includes --reset and deletes review and
inbox data for all programs in the selected database. It is not the ordinary
setup command for a shared database. Production target details are in
Data loading.
2. Sign in and open a review
Open http://localhost:3000. A Clerk user needs public metadata with a valid
role, string staffId, and program: "SNAP". For an
examiner matching the demo dataset, use staff 101; supervisor
201 has subordinate IDs 101 through 104. The full
graph is in src/lib/auth/roster.ts. Account Setup means this metadata is missing or invalid.
Use Reviews or Search to open a row. Copy its UUID URL when needed; the review number alone is not a URL. View as requires a Clerk development instance and roster accounts. The Playwright localhost session bypass is configured by tests, not needed for normal sign-in.
- As an examiner, open an Active review, edit a name or address, click Save, and reload to confirm persistence.
- In Computation, edit a column and Save that column. Apply Final Results is separate and requires no unsaved column drafts.
- Read Activity and the role/state lock message. A supervisor can review an assigned examiner’s work but cannot edit the examiner’s facts.
3. Trace that edit
Read these files in order. Search for the listed symbol rather than reading each whole file first.
| Layer | Source and entry point |
|---|---|
| Input |
src/features/reviews/workspace.tsx
— identity handler calls perform.
|
| Client state |
src/features/reviews/provider.tsx
— perform, draft queue, flush.
|
| Input contract |
src/features/reviews/command-schema.ts
— identity variant.
|
| Domain rules |
src/features/reviews/commands.ts
— execute, case "identity".
|
| HTTP boundary |
src/app/api/reviews/[reviewKey]/route.ts
— POST replaces client actor and timestamp.
|
| Save coordination |
src/features/reviews/persistence.ts
— saveCommands, appendReview.
|
| Database |
src/lib/db/review-store.ts
— snapshot insert and index update in append.
|
In browser developer tools, inspect the command POST. Its version is the last
saved database version; requestId identifies that save attempt. The response
is the saved review. A 409 loads the server copy and clears local drafts; it is not an
automatic merge.
4. Make a bounded change
A suitable first change is a field label, a small layout correction, or a clearly specified input rule. For example, adding a validation rule means updating the shared schema or program validator, covering an accepted and rejected example, and checking the corresponding UI message. Changing only a disabled button does not enforce a rule on the server.
| Change | Follow through |
|---|---|
| Label or display | Workspace component or field catalog → verify the affected screen; preserve stored codes. |
| Stored fact / command | Types and defaults → command-schema → execute → UI; consider received snapshots, revision invalidation, search registry, and old stored reviews. |
| List field or filter | Query schema → scoped store select/filter → response type → UI. A new index column also needs migration and existing-row population. |
| Calculation or check | Version dispatcher and program implementation → boundary examples → Final and report effects. Preserve behavior of already bound versions. |
| Report eligibility | Shared downstream gate → append projection → backfill → report and export checks. |
5. Choose the checks
bun run typecheck bun run lint bun run fmt:check bun run test
bunfig.toml limits Bun’s test discovery to src. Database
integration tests normally skip unless explicitly enabled. A passing unit suite alone does
not verify database or browser behavior.
| Changed area | Additional check |
|---|---|
| Review command / persistence |
bun test src/features/reviews/commands.test.ts
src/features/reviews/persistence.test.ts
|
| Database query / migration |
QC_DB_INTEGRATION=1 bun test src/lib/db against a dedicated test
database; these tests include writes and cleanup.
|
| Interactive screen |
Install browsers with bunx playwright install chromium firefox, then
use bun run test:e2e e2e/snap-negative.spec.ts or the relevant spec.
|
| Production rendering |
bun run build; Playwright also builds and starts its own production
server.
|
| Performance-sensitive change |
Performance guide and
bun run test:perf.
|
Playwright uses port 3001 by default, one worker, and the configured database. Tests can
mutate the demo baseline. Do not run competing suites against that database or build into
.next while another server depends on it.
When something fails
| Symptom | First place to inspect |
|---|---|
| Account Setup or 403 | Clerk public metadata, scope.ts, command role/state gates. |
| Review 404 | UUID URL, seeded business identity, migration 0007; GET never creates a missing review. |
| Save conflict | POST 409 and current; reread the server copy before editing. |
| Database 503 |
Connection target and db:status; migration diagnostics go to
test-results/database/.
|
| Final Results stale |
Saved scenarios and facts.inputsRevision; save drafts, then apply
Final again.
|
| PDF failure |
DOCUMENT_STORAGE; local mode uses .demo-documents.
Hosted setup requires bucket credentials and CORS.
|
| Supervisor cannot approve a non-drop |
Known PEC_ROUTING_PENDING policy gap; do not bypass it to complete a
demo journey.
|
By the end of the day, you should be able to locate a screen’s command, explain its access and save checks, run a relevant test, and verify one small change after reload.