Frontend Challenge Content Integration

Context

The fact_challenge_content table contains pre-generated challenge content for ~144K facts across 6 styles (statement_blank, direct_question, fill_the_gap, multiple_choice, reverse_lookup, free_text). Each row includes setup_text, challenge_text, reveal_correct, reveal_wrong, correct_answer, and style-specific style_data (e.g., options for multiple choice).

Currently, the card detail UI components generate challenge content algorithmically at render time. This project switches them to consume pre-generated content from the database, with algorithmic fallback for uncovered facts. It also wires the queue integration so new facts entering the pipeline automatically get challenge content generated.

Key constraint: Algorithmic fallback must remain functional for facts without pre-generated content (CC-004).

Current State

ItemStatus
fact_challenge_content table378K+ rows, regeneration in progress for 144K facts
API endpoint for challenge contentDoes not exist
quiz-interface.tsxAlgorithmic generation only
recall-interface.tsxAlgorithmic generation only
text-input-challenge.tsxAlgorithmic generation only
Queue: GENERATE_CHALLENGE_CONTENT message typeDefined in schema, handler built in worker-facts
Queue: Auto-enqueue after IMPORT_FACTSPartially wired (seed pipeline only, not news pipeline)

Key File References

FilePurpose
apps/web/app/card/[slug]/_components/quiz-interface.tsxMultiple choice UI
apps/web/app/card/[slug]/_components/recall-interface.tsxFill-the-gap, statement blank UI
apps/web/app/card/[slug]/_components/text-input-challenge.tsxFree text UI
apps/web/app/card/[slug]/_components/challenge-reveal.tsxReveal correct/wrong feedback
apps/web/app/api/cards/[slug]/route.tsCard detail endpoint
packages/db/src/drizzle/fact-engine-queries.tsQuery layer
packages/ai/src/challenge-content.tsAI generation function
packages/ai/src/challenge-content-rules.tsValidation, constants, style list
apps/worker-facts/src/handlers/generate-challenge-content.tsQueue handler

Challenges

Wave 1: API & Data Loading

Challenge 3.1: Query Function for Challenge Content

Requirement: Add a query function that retrieves pre-generated challenge content for a given fact. Acceptance Criteria:

  • getChallengeContentForFact(factRecordId, options?) function exists in fact-engine-queries.ts
  • Returns all challenge content rows for the fact, grouped by style
  • Optional style filter parameter
  • Optional difficulty filter parameter (default: 1)
  • bun run typecheck passes Evaluation: PENDING Owner: card-ux-designer

Challenge 3.2: API Endpoint for Challenge Content

Requirement: Create or extend an API endpoint that serves pre-generated challenge content. Acceptance Criteria:

  • Endpoint at /api/cards/[slug]/challenges OR challenge content included in existing /api/cards/[slug] response
  • Returns pre-generated content keyed by challenge style
  • Includes correct_answer field for each style
  • Requires authentication (same gating as card detail)
  • Returns empty object (not error) when no pre-generated content exists Evaluation: PENDING Owner: card-ux-designer

Challenge 3.3: Type Definitions for Frontend

Requirement: Add TypeScript types for pre-generated challenge content consumed by UI components. Acceptance Criteria:

  • Type exported from @eko/shared or defined in card components
  • Covers all 6 pre-generated styles with their style_data variants
  • Includes correct_answer field
  • bun run typecheck passes Evaluation: PENDING Owner: card-ux-designer

Wave 2: UI Component Updates

Challenge 3.4: Quiz Interface — Pre-generated Content

Requirement: quiz-interface.tsx consumes pre-generated multiple_choice content when available. Acceptance Criteria:

  • Checks for pre-generated multiple_choice content before algorithmic generation
  • Uses setup_text for context display
  • Uses challenge_text for the question
  • Uses style_data.options for answer choices
  • Uses reveal_correct / reveal_wrong for feedback
  • Uses correct_answer for narrative reveal
  • Falls back to algorithmic generation when no pre-generated content exists (CC-004) Evaluation: PENDING Owner: card-ux-designer

Challenge 3.5: Recall Interface — Pre-generated Content

Requirement: recall-interface.tsx consumes pre-generated statement_blank and fill_the_gap content when available. Acceptance Criteria:

  • Checks for pre-generated content before algorithmic generation
  • Supports both statement_blank and fill_the_gap styles
  • Uses style_data.blank_answer for answer validation
  • Uses correct_answer for narrative reveal
  • Falls back to algorithmic generation when no pre-generated content exists (CC-004) Evaluation: PENDING Owner: card-ux-designer

Challenge 3.6: Text Input Challenge — Pre-generated Content

Requirement: text-input-challenge.tsx consumes pre-generated free_text and direct_question content when available. Acceptance Criteria:

  • Checks for pre-generated content before algorithmic generation
  • Supports both free_text and direct_question styles
  • Uses correct_answer for narrative reveal
  • Falls back to algorithmic generation when no pre-generated content exists (CC-004) Evaluation: PENDING Owner: card-ux-designer

Challenge 3.7: Challenge Reveal — Correct Answer Streaming

Requirement: challenge-reveal.tsx displays the correct_answer narrative with animated streaming. Acceptance Criteria:

  • Renders correct_answer with a typewriter/streaming animation
  • Falls back to existing reveal text when correct_answer is null
  • Animation respects prefers-reduced-motion
  • Works for all challenge styles Evaluation: PENDING Owner: card-ux-designer

Wave 3: Queue Integration

Challenge 3.8: Auto-enqueue for News Pipeline Facts

Requirement: Facts entering via the news pipeline (EXTRACT_FACTS) automatically enqueue GENERATE_CHALLENGE_CONTENT. Acceptance Criteria:

  • extract-facts.ts handler enqueues GENERATE_CHALLENGE_CONTENT after successful fact insertion
  • Only enqueues for facts with status pending_validation or better
  • Does not duplicate-enqueue if content already exists
  • Verified by checking queue message flow in worker logs Evaluation: PENDING Owner: queue-sre

Challenge 3.9: Validation Gate

Requirement: Challenge content generation waits until fact validation completes. Acceptance Criteria:

  • GENERATE_CHALLENGE_CONTENT is enqueued after VALIDATE_FACT succeeds (not after EXTRACT_FACTS)
  • Rejected facts do not get challenge content generated
  • Validated facts that already have challenge content are skipped
  • bun run typecheck passes Evaluation: PENDING Owner: queue-sre

Quality Tier

Verification Checklist

  • Card detail page renders pre-generated content for covered facts
  • Card detail page falls back to algorithmic generation for uncovered facts
  • correct_answer displays with streaming animation
  • No visual regression on card detail pages
  • New facts from news pipeline get challenge content auto-generated
  • bun run typecheck passes
  • bun run lint passes

Evaluation Summary

ChallengeResult
3.1 Query FunctionPENDING
3.2 API EndpointPENDING
3.3 Type DefinitionsPENDING
3.4 Quiz InterfacePENDING
3.5 Recall InterfacePENDING
3.6 Text Input ChallengePENDING
3.7 Challenge Reveal StreamingPENDING
3.8 Auto-enqueue News PipelinePENDING
3.9 Validation GatePENDING

Score: 0/9 PASS


Implementation Notes

  • Wave 1 must complete before Wave 2 — UI components need the API endpoint and types.
  • Wave 2 is parallelizable — quiz, recall, and text-input components can be updated independently.
  • Wave 3 is independent of Waves 1-2 — queue wiring doesn't depend on frontend changes.
  • The correct_answer streaming animation (Challenge 3.7) is a new UX pattern — consider adding a Storybook story.
  • Challenge numbering uses the 3.x prefix to follow the taxonomy expansion (1.x) and backfill-fact-nulls (2.x) challenge docs.