# @thanh01.pmt/curriculum-kit

A high-fidelity AI curriculum and pedagogical content generation engine powered by **Vercel AI SDK**, **Zod**, and Bloom-aligned standards.

## 🌟 Overview
`@thanh01.pmt/curriculum-kit` transforms Roadmaps and Learning Paths from the Knowledge Graph (`knowledge-tree`) into rich, multi-modal educational materials:
- **`LESSON.md`**: Master Lesson Design Plan & Teaching Flow.
- **`ACT.md`**: Step-by-step hands-on activities with BOM (Hardware, Software, Consumables) and safety warnings.
- **`CODE`**: Starter code, solution code, and automated test cases.
- **`WKS.md`**: Scaffolded worksheets following the Gradual Release Model (I Do $\rightarrow$ We Do $\rightarrow$ You Do).
- **`SLIDE.md`**: 15-slide Marp presentation deck.
- **`HANDOUT.md`**: Instant-reference student cheat sheets (5-Second Rule).
- **`GUIDE.md`**: Teacher guides with misconception handling and rubrics.
- **`QUIZ`**: Bloom-aligned assessment questions consumable by `@thanh01.pmt/interactive-quiz-kit`.

## 📁 Architecture & Documentation
- **Architecture Decision Record:** [`docs/adrs/ADR-0001-curriculum-kit-architecture.md`](./docs/adrs/ADR-0001-curriculum-kit-architecture.md)
- **Implementation Plan & DoD:** [`docs/plans/implementation-plan-and-dod.md`](./docs/plans/implementation-plan-and-dod.md)

## 🌐 Language Policy
- **100% English Canonical Prompts:** All system instructions and prompt builders are written strictly in English.
- **Strict Target Output Language:** Every generation flow accepts `language` (`"vi"`, `"en"`, etc.), and the AI strictly outputs pedagogical explanations in the requested language while preserving international technical syntax and keywords.

## 🧮 Planner Internals (P52, 2026-09-18)

`buildCurriculumPlan` turns a `CurriculumFeed` into a session plan in three ordered stages. All three are pure functions of the feed — no LLM calls.

### 1. Depth reconcile — `reconcilePlanDepth` (services/depthReconciler.ts)

Runs **before** unit building/packing, only when `total_sessions` is fixed. When the bottom-up minute total exceeds the course budget (`total_sessions × session minutes × (1 − overhead_ratio)`), the planner previously had only one direction: stretch time (part-sessions). The reconciler adds the missing one — **lower knowledge depth along the Bruner spiral (SIO → CIO → ULO)** instead of cutting phases.

- **Downgrade priority (least pedagogical loss first):** (1) `advanced` revisit nodes (`__ADVxx` ids), (2) SIO→CIO on leaf concepts, (3) SIO→CIO on non-leaf non-core, (4) CIO→ULO on leaf, (5) CIO→ULO on non-leaf non-core; within a tier, largest `minutes_saved` first. Leaf-ness is computed at the **concept level** (`classifyDepthCandidates`: a concept is a leaf when no other concept lists it as a prerequisite; `__ADV`/`__PREV` ids map back to their base).
- **Absolute exclusions:** `is_core` concepts (Master-Tree core — escalate instead), non-concept nodes (product steps are build work, not knowledge depth), and nodes with **no declared `depth_hint`** (never guess).
- **Bound:** fixed-point loop capped at 5 rounds; mutates only `minutes`/`depth_hint` — no edges added/removed, no order changes, so the teaching-order invariant is preserved by construction.
- **Escalation:** when candidates are exhausted while still over budget, returns `escalate: true` + `deficitMinutes`; the planner surfaces a `budget_escalation: … human review required` warning — it **never silently cuts a phase**.

### 2. Unit building + checkpoint-aware session cutting — `packUnitSessions`

Bins nodes into sessions at the content budget. When the next node would overflow, `cutBackToCheckpoint` searches for the **latest node whose cumulative minutes fall inside the window `[budget × (1 − SESSION_CUT_TOLERANCE), budget]`** (`SESSION_CUT_TOLERANCE = 0.15`, constants/pedagogy.ts) that carries a **`user_visible_deliverable`** (projected from the ProjectGraph step's `outcome.user_visible` by domain-kit). The cut lands on that checkpoint; displaced nodes are requeued in teaching order (nothing is dropped, wall-clock never exceeds the session length). Oversized nodes keep the existing multi-part split. **No checkpoint inside the window → raw minute cut + a `no-checkpoint-within-tolerance` warning** (the future hook for `scaffold_candidates`).

### 3. ZPD audit

The single ZPD/overload audit pass runs **after** reconcile and packing, so it always sees the final node set — the reconciler cannot invalidate it by construction (it only shrinks minutes/depth, never adds new-concept events).

Planning nodes carry the reconcile inputs from the feed: `depth_variants` ({ulo, cio, sio} minute estimates), `depth_scaffold_candidates`, and `is_core`. See the domain-kit README (Schemas → `FeedNode`) for the feed-side contract.
