Files
learning-platform/docs/curriculum-spec.md
RaymondVerhoef 07af2783dc
All checks were successful
On Push to Main / test (push) Successful in 1m33s
On Push to Main / publish (push) Successful in 1m31s
On Push to Main / deploy-dev (push) Successful in 2m3s
Add comprehensive documentation for key organizational aspects
- Introduced "Pension Scheme & Benefits" detailing secondary employment benefits and pension specifics.
- Created "Roles & Accountabilities" outlining the Holacracy role structure and responsibilities within Respellion.
- Added "Security" section covering GDPR compliance and workplace safety protocols.
- Established "Spending and Contracting" policy detailing expense categories and submission processes.
- Documented "Who We Are" to define Respellion's identity, services, and operational model under Holacracy and ISO 9001.
2026-05-27 08:24:56 +02:00

87 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Curriculum spec: 26-week per-user cycle
The curriculum sequences the knowledge base into a 26-week schedule. Every
employee runs their **own** cycle, starting when they enroll. Implemented in
`src/lib/curriculumService.js`; admin UI in
`src/components/admin/CurriculumManager.jsx`.
---
## Data
- **`curriculum_versions`** — generated schedules. Lifecycle `draft → active →
superseded`; exactly one `active`. The `schedule` JSON is an array of 26 week
objects: `{ week_number (126), theme, topic_ids[], estimated_duration (1545),
week_rationale }`. `coverage_stats` records theme/topic coverage.
- **`topics`** — supply `theme`, `complexity_weight` (15), and `difficulty` as
generation input.
---
## Topic enrichment (prerequisite)
Generation needs themed, weighted topics. `enrichTopicsForCurriculum()` finds
topics missing a `theme` (excluding `type='fact'` and `learning_relevance='exclude'`)
and, in batches of 20, calls Claude with `emit_topic_enrichment` to assign
`theme`, `complexity_weight`, and `difficulty`. Triggered from the Curriculum tab.
---
## Generation
`generateCurriculumDraft(reason)`:
1. Group learning topics by `theme` (`buildThemeTopicMap`), sorted by
`complexity_weight` ascending.
2. Build a prompt describing themes and their topic ids. If there are more than 26
themes, the model is instructed to **merge** closely related themes.
3. `callLLM` (standard tier, `maxTokens: 8192`, temp 0) with forced
`emit_curriculum_schedule`. Up to 2 attempts; on validation failure the errors
are fed back into the retry prompt.
4. Validate (`validateSchedule`): exactly 26 weeks, correct `week_number` sequence,
durations 1545, every `topic_id` exists, ≥1 topic per week. Unscheduled themes
are warnings, not hard errors.
5. Supersede any existing draft and store the new `draft` version with coverage stats.
`confirmVersion(versionId, adminUserId)` activates a draft (and supersedes the old
active version); `rejectVersion` discards a draft.
---
## Per-user scheduling (the cycle)
The cycle is **detached from the calendar**. Enrollment sets
`team_members.curriculum_started_at` (see `docs/frontend-spec.md` for onboarding).
`AppContext` derives the user's position:
```js
getPersonalWeekNumber(startedAt) // floor(daysSinceStart / 7) + 1, ≥1 (0 if not enrolled)
getCurriculumWeek(personalWeek) // ((n - 1) % 26) + 1 → 1..26 slot
getCurriculumCycle(personalWeek) // floor((n - 1) / 26) + 1 → 1, 2, 3, ...
```
- Week 1 begins the day the employee enrolls.
- After week 26 the cycle restarts at week 1 with the **same** content.
- `state.weekNumber` (the absolute counter) is `0` until the user enrolls; pages are
gated behind onboarding so they never render with week 0.
---
## Content & progress for a week
- `getCurrentWeekContent(personalWeek)` reads the active version's schedule, maps the
26-week slot to its `topic_ids`, and returns `{ cycle, weekNumber, theme, topics,
estimatedDuration, rationale }`.
- `getAssignedTopic(userId, week)` returns the week's primary topic, falling back to
a deterministic hash of `userId:week` when no curriculum is active. **Keep the
fallback.**
- `getYearProgress(userId, personalWeek)` computes completion for the current cycle.
---
## Notes
- There is no shared "current week" and no `admin:current_week` setting.
- Regeneration produces a new version; activating it changes future weeks for all
users. Completion history (`micro_learning_completions`) is append-only and never
rewritten.