Files
learning-platform/docs/implementation-plan.md
RaymondVerhoef dda20612e9 Add comprehensive documentation for employee learning platform
- Created handover document outlining design decisions and application functionality.
- Developed implementation plan detailing phased approach for service development.
- Specified ingestion service responsibilities, API surface, and processing pipeline.
2026-05-23 15:38:09 +02:00

395 lines
13 KiB
Markdown
Raw 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.
# Implementation plan
## How to use this document
Work through phases in order. Do not start phase N+1 before phase N passes
all acceptance criteria. Each phase lists the spec file to read, the steps
to execute, and the criteria that define done.
At the start of each session: state the phase and step.
At the end of each session: state completed steps and next starting point.
---
## Phase 1 — Infrastructure + ingestion service
**Spec to read:** /docs/ingestion-spec.md, /docs/data-model.md
### Steps
**1.1 — Repo scaffold**
```
app/
frontend/ (empty, Next.js init comes in phase 4)
services/
ingestion/
generation/ (empty placeholder)
curriculum/ (empty placeholder)
chat/ (empty placeholder)
progress/ (empty placeholder)
```
Create `app/services/ingestion/` with:
- package.json (dependencies from ingestion-spec.md)
- tsconfig.json (strict mode)
- .env.example (all env vars from ingestion-spec.md)
- .gitignore
**1.2 — PocketBase collections**
PocketBase runs as a binary. Create a migration script at
`app/services/ingestion/migrations/001_initial_schema.ts` that uses the
PocketBase JS SDK to create all collections defined in data-model.md:
Collections to create:
- source_documents
- themes
- topics
- micro_learnings (schema only — no data yet)
- curriculum_versions (schema only)
- curriculum_weeks (schema only)
- employee_curriculum_state (schema only)
- session_completions (schema only)
- gamification_profiles (schema only)
- badges (schema only)
- employee_badges (schema only)
- milestone_cards (schema only)
Seed the badges collection with all badge definitions from data-model.md.
**1.3 — Qdrant collections**
Create `app/services/ingestion/migrations/002_qdrant_setup.ts` that
initialises both Qdrant collections:
- source_chunks (1536 dimensions, cosine distance)
- topic_summaries (1536 dimensions, cosine distance)
**1.4 — Ingestion service scaffold**
Build the Fastify server with two routes:
- POST /ingest
- GET /status/:jobId
Use the file structure from ingestion-spec.md exactly.
**1.5 — Stage 1: text extraction**
Implement extract.ts per ingestion-spec.md:
- TXT: direct UTF-8 read
- MD: direct UTF-8 read, preserve heading markers
- PDF: pdf-parse, page break markers
**1.6 — Stage 23: chunking + cleaning**
Implement chunk.ts and clean.ts per ingestion-spec.md:
- MD: heading-based splitting
- TXT: sliding window (800 chars, 150 overlap)
- PDF: page + paragraph splitting
- Cleaning: whitespace, artefacts, minimum length filter
**1.7 — Stage 4: structure extraction**
Implement structure.ts per ingestion-spec.md:
- Claude Sonnet 4 call with system + user prompt from spec
- Zod validation of DraftKB output
- Batch handling for documents > 60 chunks
- Retry logic on parse failure
- Error handling: failed job status + reason
**1.8 — Stage 5: PocketBase write**
Implement the PocketBase write logic:
- Create Theme records (status: draft)
- Create Topic records under each Theme (status: draft)
- Resolve relationships between Topics after all records created
**1.9 — Stage 6: embeddings + Qdrant write**
Implement embed.ts:
- OpenAI text-embedding-3-small, batches of 100
- Write to Qdrant source_chunks collection
- Write to Qdrant topic_summaries collection
- Update Topic.qdrant_chunk_ids in PocketBase
**1.10 — Job status tracking**
Wire all stages into the job queue (jobs/queue.ts):
- Status transitions: queued → extracting → chunking → structuring →
writing → embedding → done / failed
- Progress counters (chunksTotal, chunksEmbedded, themesFound, topicsFound)
- GET /status/:jobId returns current state
### Acceptance criteria
- [ ] POST /ingest with a small MD file completes without error
- [ ] GET /status/:jobId returns `done` after processing
- [ ] PocketBase contains draft Theme + Topic records with correct hierarchy
- [ ] Topic.body contains AI-drafted content (not empty)
- [ ] Topic relationships are resolved (related_topics populated where applicable)
- [ ] Qdrant source_chunks contains vectors with correct payload fields
- [ ] Qdrant topic_summaries contains vectors for each published topic
- [ ] Topic.qdrant_chunk_ids is populated
- [ ] POST /ingest with a PDF file completes without error
- [ ] POST /ingest with a TXT file completes without error
- [ ] A document > 60 chunks triggers batch processing without error
- [ ] A malformed PDF returns status `failed` with reason, not an uncaught exception
- [ ] All Zod validations pass — no `any` types in codebase
---
## Phase 2 — Generation service
**Spec to read:** /docs/generation-spec.md (write this spec before starting)
### Steps
**2.1 — Generation service scaffold**
Fastify service at app/services/generation/
Routes: POST /generate, GET /status/:jobId
**2.2 — Generate all 10 types per topic**
One Claude Sonnet 4 call per type per topic.
Structured JSON output validated against Zod schemas from data-model.md.
Write to micro_learnings collection (status: generated).
**2.3 — Batch generation on theme approval**
When admin approves a Theme batch, queue generation for all Topics in that Theme.
All 10 types per Topic.
**2.4 — Admin publish flow**
Route to update micro_learning status from generated → published or rejected.
This is called by the admin app (built in phase 4).
### Acceptance criteria (to be detailed in generation-spec.md)
- [ ] All 10 micro learning types generated for a test topic
- [ ] All 10 JSON outputs validate against their Zod schemas
- [ ] Generated content written to PocketBase with status: generated
- [ ] Admin can publish or reject individual micro learnings
---
## Phase 3 — Curriculum service
**Spec to read:** /docs/curriculum-spec.md (write this spec before starting)
### Steps
**3.1 — Curriculum service scaffold**
Fastify service at app/services/curriculum/
**3.2 — Curriculum generator**
Claude Sonnet 4 reads full KB graph → produces 26-week schedule.
Written to curriculum_versions + curriculum_weeks.
**3.3 — Versioning logic**
- New version created on regeneration
- Completed weeks frozen (employee_curriculum_state.current_week used as boundary)
- Admin confirmation required before applying new version
**3.4 — Perpetual cycling**
On week 26 completion, cycle increments, new cycle starts on latest version.
Second cycle: varied sequence, surfaces unused micro learning types.
### Acceptance criteria (to be detailed in curriculum-spec.md)
- [ ] Curriculum generated from a populated KB
- [ ] 26 weeks produced, all Themes covered
- [ ] Prerequisites respected in ordering
- [ ] Regeneration does not alter completed weeks
- [ ] Admin confirmation flow works correctly
---
## Phase 4 — Frontend: admin app
**Spec to read:** /docs/frontend-spec.md (write this spec before starting)
### Steps
**4.1 — Next.js 14 scaffold**
Mobile-first, TypeScript strict, Tailwind CSS, PWA config.
Role-based routing: /admin/* and /app/* from single Next.js codebase.
**4.2 — Auth**
PocketBase auth integration. Admin role routes to /admin/*.
**4.3 — Document upload + ingestion status**
Upload UI → calls ingestion service → polls job status → shows progress.
**4.4 — Theme batch review**
Display draft Themes with their Topic list.
Approve batch / edit individual topics / reject batch.
Triggers generation service on approval.
**4.5 — Curriculum editor**
Display AI-generated curriculum (26 weeks).
Drag-to-reorder weeks. Edit Theme assignment per week.
Confirm regeneration with preview.
### Acceptance criteria (to be detailed in frontend-spec.md)
- [ ] Admin can upload a document and see ingestion progress
- [ ] Admin can approve a Theme batch
- [ ] Admin can edit a Topic before approval
- [ ] Admin can view and reorder the curriculum
- [ ] Admin can confirm a curriculum regeneration with preview
---
## Phase 5 — Frontend: employee app
**Spec to read:** /docs/frontend-spec.md (same file, employee section)
### Steps
**5.1 — Employee auth + onboarding**
PocketBase auth. Employee role routes to /app/*.
Set start date on first login → creates employee_curriculum_state record.
**5.2 — Weekly session flow**
Current week's Theme displayed.
Topics listed with available micro learning types per topic.
Employee selects type → content rendered → mark complete.
**5.3 — Knowledge library**
Browse all published Topics.
Filter by Theme, difficulty, key terms.
**5.4 — R42 chatbot**
Floating button, every screen.
Calls chat service → streams response.
Cites source topic in response.
**5.5 — Gamification profile**
GitHub-style heatmap (26-week view).
Badge display.
Streak + level + commit count.
Public leaderboard (multi-dimension).
Milestone cards in activity feed.
### Acceptance criteria (to be detailed in frontend-spec.md)
- [ ] Employee sees correct week based on start date
- [ ] Employee can complete a topic with a chosen micro learning type
- [ ] Completion is recorded and XP awarded
- [ ] Knowledge library shows all published topics with filters
- [ ] R42 responds with grounded answer and source citation
- [ ] R42 is accessible from every screen
- [ ] Heatmap renders correctly on mobile (375px)
- [ ] Leaderboard shows all employees with multi-dimension data
---
## Phase 6 — Chat service (R42)
**Spec to read:** /docs/r42-spec.md (write this spec before starting)
### Steps
**6.1 — Chat service scaffold**
Fastify service at app/services/chat/
**6.2 — Query → embed → retrieve**
Employee query embedded → Qdrant nearest-neighbour on both collections.
Boost chunks from employee's current Theme.
**6.3 — Response generation**
Top-K chunks injected into Haiku 4.5 prompt.
Response streamed to frontend.
Source Topic titles included in response.
**6.4 — Out-of-scope handling**
If retrieval confidence is below threshold, R42 responds:
"I can only answer questions based on the internal knowledge base.
This topic doesn't appear to be covered."
### Acceptance criteria (to be detailed in r42-spec.md)
- [ ] R42 answers a question about a published topic correctly
- [ ] R42 cites the source topic in its response
- [ ] R42 refuses to answer out-of-scope questions explicitly
- [ ] Response streams to frontend (not batch)
- [ ] Response latency < 3 seconds for typical queries
---
## Phase 7 — Progress service
**Spec to read:** /docs/gamification-spec.md (write this spec before starting)
### Steps
**7.1 — Progress service scaffold**
Fastify service at app/services/progress/
**7.2 — Completion recording**
Write session_completions record on topic completion.
Calculate XP (commits) per type.
**7.3 — Gamification updates**
Update gamification_profiles: commits, level, streak, types_used.
Evaluate badge conditions → write employee_badges on award.
**7.4 — Milestone cards**
Generate milestone_cards record at weeks 13 and 26.
**7.5 — Leaderboard query**
Endpoint returning all gamification_profiles for leaderboard rendering.
### Acceptance criteria (to be detailed in gamification-spec.md)
- [ ] Completion writes to session_completions
- [ ] Commits calculated and added to gamification_profile
- [ ] Level updates correctly at commit thresholds
- [ ] Streak increments on weekly completion, resets on skip
- [ ] Badge awarded when condition is met
- [ ] Milestone card created at weeks 13 and 26
- [ ] Leaderboard endpoint returns all employees with correct data
---
## Phase 8 — Integration + hardening
No new spec required.
### Steps
**8.1 — Service wiring**
Verify all services communicate through PocketBase correctly.
No direct service-to-service calls — all state through PocketBase.
**8.2 — Error handling audit**
Review all services for unhandled promise rejections, missing error states,
and uncaught exceptions. Every external call (AI API, PocketBase, Qdrant,
OpenAI) wrapped in try/catch with meaningful error logging.
**8.3 — Mobile QA**
Test all employee app flows at 375px width.
R42 floating button must not obscure content.
Heatmap must render without horizontal scroll.
**8.4 — Environment variable audit**
Verify no hardcoded values. All .env.example files complete.
**8.5 — Dockerfile update**
Update COPY path from legacy app root to /app.
This is the one manual change that connects the rebuild to the existing pipeline.
### Acceptance criteria
- [ ] Full flow works end-to-end: upload doc → approve → curriculum → employee completes session → R42 answers question → gamification updates
- [ ] No uncaught exceptions in any service under normal operating conditions
- [ ] All screens render correctly on 375px mobile
- [ ] Dockerfile builds successfully pointing at /app
- [ ] Existing pipeline deploys the rebuilt app without modification
---
## Spec files still to be written
Before starting each phase, write the corresponding spec file.
Use ingestion-spec.md as the template for structure and detail level.
| Phase | Spec file needed |
|---|---|
| 2 | /docs/generation-spec.md |
| 3 | /docs/curriculum-spec.md |
| 45 | /docs/frontend-spec.md |
| 6 | /docs/r42-spec.md |
| 7 | /docs/gamification-spec.md |
When you reach a phase without a spec: stop, draft the spec, then proceed.
Do not implement without a spec.