RaonNuri_Public_Documents/REFACTOR-NOTES.md
2026-08-11 05:50:34 +00:00

6.6 KiB

Studio Curriculum Refactor — Notes

Branch: feat/studio-curriculum

Phase 1 (prior, by remover)

  • c977e0b chore: remove gamification curriculum/lesson feature — removed the unrelated gamification Curriculum/Lesson feature, freeing the Curriculum name and src/types/curriculum.ts path. tsc/build green.

Phase 2 (this work) — data-driven studio Curriculum (회차) entity

Three green-gated steps, commit after each (tsc --noEmit = 0):

  • 2-1 a4aa1db feat(studio): add Curriculum entity, role icon registry, 3학년 1회차 seed

    • src/types/curriculum.tsCurriculum + CurriculumRole/Meta/AI/Rewards/Copy (+ Localized<T>). Stages are NOT modeled here (fixed at 6 — locked decision).
    • src/components/writing/studio/roleIconRegistry.ts — string icon key → IconType (mapPin/heart/question/default).
    • src/data/studioCurricula/grade3-session1.ts — seed; role label/guide/placeholder/examples copied verbatim from messages/*.json; ai.keywordCount = 5; meta from the lesson plan (ko; en/ja = ko + // TODO i18n).
    • Pure addition; studio did not consume it yet.
  • 2-2 3536c8d feat(studio): make writing frame data-driven via Curriculum roles

    • Removed the StudioSentenceKey union + STUDIO_SENTENCE_ORDER.
    • Generalized every Record<StudioSentenceKey, …>Record<string, …> (StudioSegment/SuggestResponse.bySentence, StudioResult.sentencesV1/V2, StudioCompleteRequest.sentencesV1/V2, segment/suggest request key, flow state sentencesV2, tokensBySentence, stage props).
    • StudioBlank.sentenceKeyroleKey: string (no back-compat — locked decision).
    • templates.ts (studioBlankId/getStudioBlanks/composeStudioSentences) now takes CurriculumRole[] (slotId-driven). studioRoleMeta.ts deleted.
    • studioService.ts: SEGMENT_SCHEMA/SUGGEST_SCHEMA built at runtime from role keys (Gemini structured output); emptyTokenMap/emptySuggestionMap and all loops derive from the role keys carried by the request; keywordCount injected (was STUDIO_KEYWORD_COUNT, pickFiveKeywordspickKeywords).
    • segmentation.ts/suggestion.ts: output-key instruction generated from role keys.
    • Routes resolve the Curriculum from curriculumId and add manual runtime key-validation (repo's existing validationErrorResponse style, not zod):
      • analyze — feeds ai.keywordCount.
      • segment/suggest — reject sentences whose key is not a curriculum role key.
      • complete — require all role keys present in sentencesV1/V2; <p> body assembly + safeSentences iterate role keys in frame order; roleKey saved.
    • page.tsx + stages render from state.curriculum.frame.roles via roleIconRegistry; studio loads the Curriculum with getCurriculum(?curriculumId=) → falls back to the grade3-session1 seed.
    • 3학년 1회차 renders identically to before. tsc 0, npm run build exit 0.
    • New code-seed registry: src/data/studioCurricula/index.ts (getCurriculum, getCurriculumRoleKeys, DEFAULT_CURRICULUM_ID).
  • 2-3 feat: data-driven studio Curriculum entity (3학년 1회차 seed)

    • ICU-templated copy in messages/{ko,en,ja}.json, values fed from data:
      • complete.title {session}meta.sessionOrdinal
      • keywords.title {count}ai.keywordCount
      • secondWriting.subtitle {count}frame.roles.length
    • Removed migrated keys from all three locales: studio.roles.*, studio.firstWriting.{guides,placeholders,examples}. Platform-chrome keys kept (stepper, reward, actions, imageUpload, etc.). CRLF + tab + trailing newline preserved; key sets identical across the 3 locales (2080 each).
    • tsc 0, build exit 0.

What is data-driven now

  • Writing-frame roles (key/slotId/icon/label/guide/placeholder/examples) — variable count & names, sourced from Curriculum.frame.roles.
  • AI keyword count (ai.keywordCount), AI structured-output schemas & prompt output keys (built from role keys at runtime).
  • Session/count copy (complete.title/keywords.title/secondWriting.subtitle) via ICU + data.
  • Lesson-plan meta (sessionLabel/topic/objective/achievementStandard/flow/materials/ emotionCards) — present as data on the entity.

What is intentionally FIXED (not data-driven)

  • The 6-stage flow STUDIO_STAGE_ORDER / goNext / StageStepper and stepper.* i18n labels (locked decision: stages fixed at 6).
  • Reward UI engine + default motion/sprite preset pools (rewards left undefined → shared platform pool).

STOP points (product decisions — NOT built, per locked decisions)

  1. Management layer — no Firestore curriculums collection, CRUD API, teacher authoring console, or security rules. Curricula live only as code seeds today. A real authoring flow needs a schema + rules + UI decision.
  2. Curriculum entry/routing — studio reads ?curriculumId= and falls back to grade3-session1. How students actually receive a curriculumId (team assignment link / home card / Topic linkage) is undecided.

    Resolved 2026-08-10 — a student arrives from the class session. The notice board and the classroom both link with the in-progress session's teamId+topicId, and _flow/liveCurriculum.ts overlays the live week/topic onto the code seed. Note that meta.sessionOrdinal (2-3 above) is now seeded from TeamSession.order — the confirmed class number — rather than being the seed's own constant. There is no "assignment link"; assignments were deleted (see DATA_MODELS.md → TeamSession).

  3. Existing published works — NO back-compat/migration was built (locked decision #2). Old studio writings stored with situation/emotion/reason keys and blanks[].sentenceKey may not render correctly under the new roleKey shape. If preserving old works matters, a migration/back-fill is required.
  4. Multilingual authorship for meta — en/ja for meta are ko + // TODO i18n (meta is data-only, not surfaced in UI yet). Translation authorship is out of scope.
  5. copy overridesCurriculumCopy type exists but the seed leaves it undefined; ICU templates live in i18n. Per-curriculum copy override wiring is not built (not needed for the seed).
  6. Topic relationshipCurriculum.topicId? left as an optional aggregation FK; Topic itself unchanged.

Verify

  • npx tsc --noEmit → 0 errors.
  • npm run build → exit 0 (run after Remove-Item -Recurse -Force .next once to clear a stale route-validator cache).
  • Pre-existing unrelated lint warnings may remain; none introduced.