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

107 lines
6.6 KiB
Markdown

# 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.ts``Curriculum` + `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.sentenceKey``roleKey: 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`, `pickFiveKeywords``pickKeywords`).
- `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` overrides** — `CurriculumCopy` 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 relationship**`Curriculum.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.