CurioQuest

wiki/status/2026-06-04-intake-module-build-status.md

Intake Module Build Status — 2026-06-04

Status

Module 1 Intake is now implemented as the first screen of the Operator Console and persists valid submissions before starting a factory run.

2026-06-04 Visual Alignment Update

The Intake screen was refactored to more closely match docs/mockup/intakeForm-mockup.png while preserving later product decisions:

  • Dark teal CurioQuest Factory app bar and centered workflow rail.
  • Compact numbered panels for Hero, Cast, Guide, and Curriculum & setting.
  • Dense inline form controls and interest chips.
  • Desktop topic cards with mobile dropdown fallback.
  • Mockup-style right rail with Brief health, circular score, order preview, notes, and primary run action.
  • No user-facing Format section, no locked delivery chips, and no print controls.

What Is Built

  • App shell at / with workflow rail and intake as the first screen.
  • Intake form aligned to the approved mock-up direction.
  • Controlled dropdown-backed inputs for hero appearance, cast appearance, pet kind, topic, and Georgia pilot location.
  • Interest constraints: max 2 interests, max 50 characters each.
  • Curriculum topic picker backed by GET /curriculum/catalog?grade=....
  • Backend CreationBrief contract updated for the pilot intake shape.
  • book_format and enrollment are no longer user-facing; backend defaults them internally to digital and single.
  • Durable Supabase/Postgres intake storage added to services/operator-api.

Durable Storage

The operator API has one runtime intake database: Supabase/Postgres.

public.intake_submissions

Table:

intake_submissions

Saved fields:

intake_id
run_id
created_at
hero_first_name
hero_age
grade_mode
grade
grade_transition
effective_grade
topic
city_region
subject
language
brief_json

The full validated CreationBrief is stored in brief_json for replay/audit. Searchable columns are duplicated for operational lookup.

Supabase/Postgres status:

  • Postgres adapter is implemented with psycopg.
  • The API creates public.intake_submissions and indexes on startup with CREATE TABLE IF NOT EXISTS.
  • .env.local must provide DATABASE_URL.
  • Tests inject a fake IntakeStore; there is no SQLite intake implementation or runtime selector.
  • Live Supabase smoke is blocked until DATABASE_URL uses a Supabase pooler URI. The current direct URL is port 5432, and this Mac cannot route to the direct IPv6 database endpoint. Use Supabase Session Pooler or Transaction Pooler, with sslmode=require if Supabase does not include it automatically.

API Contract

  • POST /runs validates the brief, saves an intake row, starts the background factory run, and returns:
{
  "run_id": "...",
  "intake_id": "...",
  "status": "running"
}
  • GET /intakes/{intake_id} returns the saved durable intake submission.
  • GET /runs/{run_id} remains the run progress endpoint.

Key Files

  • apps/operator-console/src/components/intake/IntakePage.tsx
  • apps/operator-console/src/components/intake/IntakeForm.tsx
  • apps/operator-console/src/components/intake/BriefSummary.tsx
  • apps/operator-console/src/components/intake/TopicPicker.tsx
  • apps/operator-console/src/lib/brief.ts
  • apps/operator-console/src/lib/intakeOptions.ts
  • apps/operator-console/src/lib/api.ts
  • services/book-factory/src/book_factory/models/brief.py
  • services/operator-api/src/operator_api/intake_store.py
  • services/operator-api/src/operator_api/routes.py
  • services/operator-api/src/operator_api/app.py
  • services/operator-api/src/operator_api/models.py

Verification

Last verified on 2026-06-04:

PYTHONPATH="src:../curriculum-service/src:../book-factory/src" python3 -m pytest tests -q
45 passed

python3 -m pytest services/book-factory/tests/unit/test_brief.py -q
26 passed

npm run typecheck
passed

npm run lint
passed

Notes For Parallel Agents

  • Restart operator-api after pulling these changes so the app initializes the configured IntakeStore.
  • Hosted Supabase testing requires a pooler DATABASE_URL; direct Supabase database URLs can fail locally because the direct endpoint is IPv6-only unless IPv4 is enabled on the Supabase project.
  • Existing runs still live in the in-memory RunStore and filesystem run artifacts; the durable Supabase/Postgres storage is for submitted intake briefs.
  • Print fulfillment remains out of scope for Intake. Print should be modeled later as a separate capability/order flow attached to an existing generated book.
  • Curriculum catalog remains a prerequisite for topic selection; empty catalog should block a valid intake submission from the UI.