Files
ai-teacher/specs/001-neuro-rag-learning/tasks.md
2026-03-31 20:58:47 +02:00

199 lines
15 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.
---
description: "Task list for Neurosurgeon RAG Learning Platform"
---
# Tasks: Neurosurgeon RAG Learning Platform
**Input**: Design documents from `/specs/001-neuro-rag-learning/`
**Prerequisites**: plan.md ✅, spec.md ✅, research.md ✅, data-model.md ✅, contracts/ ✅, quickstart.md ✅
**Tests**: Not requested — smoke tests defined in quickstart.md are the validation gate (Principle V).
**Organization**: Tasks are grouped by user story to enable independent implementation and testing.
## Format: `[ID] [P?] [Story?] Description`
- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (US1, US2, US3)
- File paths are relative to repository root
---
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Monorepo scaffolding, README, and local dev tooling.
- [x] T001 Create monorepo directory structure: `backend/`, `frontend/`, `README.md` at repo root
- [x] T002 Initialize Spring Boot 4.0.5 backend Maven project with `pom.xml` in `backend/`; add Spring AI BOM 2.0.0-M4, `spring-ai-starter-vector-store-pgvector`, `spring-ai-pdf-document-reader`, `spring-ai-starter-openai`, Spring Security, Spring Data JPA, Flyway, PostgreSQL driver
- [x] T003 [P] Initialize Vue 3 + Vite + TypeScript frontend project in `frontend/` via `npm create vue@latest`; add Axios and Pinia
- [x] T004 [P] Create `docker-compose.yml` at repo root for local dev: PostgreSQL 16 with pgvector image (`pgvector/pgvector:pg16`), volume, env vars
- [x] T005 [P] Add `README.md` with project description and Mermaid system-context diagram (copy diagram from `specs/001-neuro-rag-learning/quickstart.md`) — required by Constitution Principle IV
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Core infrastructure that ALL user stories depend on.
**⚠️ CRITICAL**: No user story work can begin until this phase is complete.
- [x] T006 Configure `backend/src/main/resources/application.properties`: datasource URL/credentials, Spring AI pgvector dimensions (1536) + COSINE_DISTANCE + HNSW + initialize-schema=true, OpenAI API key + model names, `app.auth.password` property
- [x] T007 [P] Create `backend/src/main/java/com/aiteacher/config/SecurityConfig.java`: HTTP Basic auth, single in-memory user (`neurosurgeon` / `${app.auth.password}`), all requests authenticated, CSRF disabled (REST API)
- [x] T008 [P] Create `backend/src/main/java/com/aiteacher/config/AiConfig.java`: declare `ChatClient` bean wrapping auto-configured `ChatModel`, document any Spring AI 2.x `@Bean` wiring required for `VectorStore` and `EmbeddingModel`
- [x] T009 [P] Create Flyway migration `backend/src/main/resources/db/migration/V1__initial_schema.sql`: `book`, `chat_session`, `message` tables + `idx_message_session` index (DDL from data-model.md; do NOT create `vector_store` — Spring AI handles it)
- [x] T010 [P] Create `backend/src/main/resources/topics.json` with 1015 representative neurosurgery topics (id slug, name, description, category) covering Vascular, Oncology, Spine, Trauma domains
- [x] T011 [P] Create `frontend/src/services/api.ts`: Axios instance with `baseURL` from `VITE_API_URL` env var, `auth` object for Basic credentials from `VITE_APP_PASSWORD` env var
- [x] T012 [P] Configure Vue Router in `frontend/src/router/index.ts`: routes for `/` (UploadView), `/topics` (TopicsView), `/chat` (ChatView)
- [x] T013 [P] Create `frontend/src/.env.example` and `frontend/src/App.vue` with top navigation bar linking to all three routes
**Checkpoint**: Foundation ready — user story implementation can begin.
---
## Phase 3: User Story 1 — Book Upload & Precise Embedding (Priority: P1) 🎯 MVP
**Goal**: User uploads a PDF, it is processed (text + diagram captions embedded into pgvector), and the book appears as "Ready" in the library.
**Independent Test**: Upload any medical PDF → observe status PENDING → PROCESSING → READY → query a topic question that can only be answered from that book and confirm a sourced answer is returned (Smoke Test 1, quickstart.md).
### Implementation for User Story 1
- [x] T014 [P] [US1] Create `backend/src/main/java/com/aiteacher/book/Book.java`: JPA entity matching data-model.md (`id`, `title`, `fileName`, `fileSizeBytes`, `pageCount`, `status`, `errorMessage`, `uploadedAt`, `processedAt`)
- [x] T015 [P] [US1] Create `backend/src/main/java/com/aiteacher/book/BookStatus.java`: enum `PENDING`, `PROCESSING`, `READY`, `FAILED`
- [x] T016 [P] [US1] Create `backend/src/main/java/com/aiteacher/book/BookRepository.java`: Spring Data JPA repository for `Book`
- [x] T017 [US1] Create `backend/src/main/java/com/aiteacher/book/BookEmbeddingService.java`: use `PagePdfDocumentReader` to parse PDF page-by-page; add metadata (`book_id`, `book_title`, `page`, `chunk_type`); detect diagram captions via regex (`^(Figure|Fig\.|Table|Diagram)\s+[\d.]+`) and tag `chunk_type=diagram`; call `vectorStore.add(documents)` (depends on T014, T016)
- [x] T018 [US1] Create `backend/src/main/java/com/aiteacher/book/BookService.java`: persist `Book` as PENDING, trigger async embedding via `BookEmbeddingService` (`@Async`), update status to PROCESSING/READY/FAILED, provide list/get/delete operations; on delete cascade remove vector chunks via `vectorStore.delete(filter on book_id)` (depends on T017)
- [x] T019 [US1] Create `backend/src/main/java/com/aiteacher/book/BookController.java`: implement all four endpoints from `contracts/books-api.md` (`POST /api/v1/books`, `GET /api/v1/books`, `GET /api/v1/books/{id}`, `DELETE /api/v1/books/{id}`); validate PDF content-type; reject non-PDF with 400 (depends on T018)
- [x] T020 [P] [US1] Create `frontend/src/stores/bookStore.ts` (Pinia): state for book list, actions `fetchBooks()`, `uploadBook(file)`, `deleteBook(id)` using `api.ts`
- [x] T021 [P] [US1] Create `frontend/src/components/BookCard.vue`: display title, fileName, status badge (colour-coded), uploadedAt, delete button
- [x] T022 [US1] Create `frontend/src/views/UploadView.vue`: file input (PDF only), upload button, progress/status message, book list using `BookCard`; poll book status every 5 s while any book is PENDING or PROCESSING (depends on T020, T021)
**Checkpoint**: User Story 1 fully functional — upload a PDF and observe it reach READY status.
---
## Phase 4: User Story 2 — Topic-Guided Summary (Priority: P2)
**Goal**: User selects a topic from the predefined list; system generates a sourced summary cross-referencing all READY books.
**Independent Test**: With ≥1 READY book, select a relevant topic → summary generated in < 30 s with source citations → select unrelated topic → system responds with "no relevant content found" (Smoke Test 2, quickstart.md).
### Implementation for User Story 2
- [x] T023 [P] [US2] Create `backend/src/main/java/com/aiteacher/topic/Topic.java`: Java record with fields `id`, `name`, `description`, `category`
- [x] T024 [P] [US2] Create `backend/src/main/java/com/aiteacher/topic/TopicConfigLoader.java`: `@Component` that reads `topics.json` at startup using Jackson and exposes `List<Topic> getAll()` and `Optional<Topic> findById(String id)`
- [x] T025 [US2] Create `backend/src/main/java/com/aiteacher/topic/TopicSummaryService.java`: use `ChatClient` with `QuestionAnswerAdvisor(vectorStore)` to generate a topic summary; build a system prompt instructing the LLM to answer only from retrieved context and cite sources; extract source metadata (`book_title`, `page`) from returned `ChatResponse`; return a DTO with `summary` string and `sources` list; if no READY books exist throw `NoKnowledgeSourceException` (depends on T024)
- [x] T026 [US2] Create `backend/src/main/java/com/aiteacher/topic/TopicController.java`: `GET /api/v1/topics` and `POST /api/v1/topics/{id}/summary` per `contracts/topics-api.md`; map `NoKnowledgeSourceException` → 503 (depends on T025)
- [x] T027 [P] [US2] Create `frontend/src/stores/topicStore.ts` (Pinia): state for topics list and active summary, actions `fetchTopics()`, `generateSummary(topicId)`
- [x] T028 [P] [US2] Create `frontend/src/components/TopicCard.vue`: display topic name, description, category badge, "Generate Summary" button
- [x] T029 [US2] Create `frontend/src/views/TopicsView.vue`: grid of `TopicCard` components; on summary request show loading spinner, then render summary text with collapsible sources list (book title + page); show friendly message when no books are available (depends on T027, T028)
**Checkpoint**: User Stories 1 AND 2 independently functional.
---
## Phase 5: User Story 3 — Knowledge Deepening Chat (Priority: P3)
**Goal**: User starts a chat session (optionally tied to a topic), asks multi-turn questions grounded in uploaded books; system declines gracefully for out-of-scope queries.
**Independent Test**: Start session → ask sourced question → confirm citation → ask follow-up referencing prior turn → confirm context maintained → ask out-of-scope question → confirm graceful refusal → clear conversation (Smoke Test 3, quickstart.md).
### Implementation for User Story 3
- [x] T030 [P] [US3] Create `backend/src/main/java/com/aiteacher/chat/ChatSession.java`: JPA entity (`id`, `topicId`, `createdAt`)
- [x] T031 [P] [US3] Create `backend/src/main/java/com/aiteacher/chat/Message.java`: JPA entity (`id`, `sessionId` FK, `role`, `content`, `sources` JSONB, `createdAt`)
- [x] T032 [P] [US3] Create `backend/src/main/java/com/aiteacher/chat/ChatSessionRepository.java` and `MessageRepository.java`: Spring Data JPA repositories
- [x] T033 [US3] Create `backend/src/main/java/com/aiteacher/chat/ChatService.java`: create/delete sessions; send user message — retrieve full session history, build multi-turn prompt, call `ChatClient` with `QuestionAnswerAdvisor`; persist both the user message and the assistant response with source metadata; throw `NoKnowledgeSourceException` when no READY books (depends on T030, T031, T032)
- [x] T034 [US3] Create `backend/src/main/java/com/aiteacher/chat/ChatController.java`: all four endpoints from `contracts/chat-api.md` (`POST /sessions`, `GET /sessions/{id}/messages`, `POST /sessions/{id}/messages`, `DELETE /sessions/{id}`) (depends on T033)
- [x] T035 [P] [US3] Create `frontend/src/stores/chatStore.ts` (Pinia): state for active session and messages, actions `createSession(topicId?)`, `sendMessage(content)`, `loadMessages()`, `deleteSession()`
- [x] T036 [P] [US3] Create `frontend/src/components/ChatMessage.vue`: render a single message bubble (user vs assistant styling); for assistant messages render inline source chips (book title + page)
- [x] T037 [US3] Create `frontend/src/views/ChatView.vue`: topic selector (optional), "New Chat" button, scrollable message list using `ChatMessage`, text input + send button, "Clear conversation" button; auto-scroll to latest message (depends on T035, T036)
**Checkpoint**: All three user stories independently functional and testable.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Error handling, UX polish, Dockerfiles, and final smoke-test validation.
- [x] T038 [P] Add `@RestControllerAdvice` global exception handler in `backend/src/main/java/com/aiteacher/config/GlobalExceptionHandler.java`: map validation errors → 400, `NoKnowledgeSourceException` → 503, generic exceptions → 500; all responses use `{ "error": "..." }` shape from contracts
- [x] T039 [P] Add loading states (spinner), empty-state messages, and API error toasts to all three Vue views (`UploadView`, `TopicsView`, `ChatView`)
- [x] T040 [P] Create `backend/Dockerfile` (multi-stage: Maven build → JRE 21 runtime) and `frontend/Dockerfile` (Node 20 build → nginx serve)
- [x] T041 [P] Run all three smoke tests from `specs/001-neuro-rag-learning/quickstart.md` against the running stack and confirm each passes
- [x] T042 [P] Verify `README.md` Mermaid diagram renders correctly on GitHub and matches actual deployed architecture (Constitution Principle IV compliance check)
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: No dependencies — start immediately. T002, T003, T004, T005 can all run in parallel after T001.
- **Foundational (Phase 2)**: Depends on T001T005 completion. All T006T013 can run in parallel after T002 and T003.
- **User Story 1 (Phase 3)**: Depends on Phase 2 — BLOCKS Phases 4 and 5.
- **User Story 2 (Phase 4)**: Depends on Phase 3 (needs READY books to exist and VectorStore to be populated).
- **User Story 3 (Phase 5)**: Depends on Phase 2; can start in parallel with Phase 4 for back-end tasks (T030T034); frontend (T035T037) needs Phase 3 complete for book availability.
- **Polish (Phase 6)**: Depends on all story phases complete.
### Within Each User Story
- Entities/repositories before services
- Services before controllers (backend)
- Stores before views (frontend)
- Backend and frontend tasks for the same story can proceed in parallel
### Parallel Opportunities
```bash
# Phase 1 — after T001:
T002 (backend init) || T003 (frontend init) || T004 (docker-compose) || T005 (README)
# Phase 2 — after T002 + T003:
T006 (app.properties) → T007 (security) || T008 (AI config) || T009 (Flyway) || T010 (topics.json)
T011 (api.ts) || T012 (router) || T013 (App.vue)
# Phase 3 — US1 backend + frontend in parallel:
T014 (Book entity) || T015 (enum) || T016 (repo) → T017 (EmbeddingService) → T018 (BookService) → T019 (BookController)
T020 (bookStore) || T021 (BookCard) → T022 (UploadView)
# Phase 4 — US2:
T023 (Topic record) || T024 (TopicConfigLoader) → T025 (TopicSummaryService) → T026 (TopicController)
T027 (topicStore) || T028 (TopicCard) → T029 (TopicsView)
# Phase 5 — US3:
T030 (ChatSession) || T031 (Message) || T032 (repos) → T033 (ChatService) → T034 (ChatController)
T035 (chatStore) || T036 (ChatMessage) → T037 (ChatView)
```
---
## Implementation Strategy
### MVP First (User Story 1 Only)
1. Complete Phase 1: Setup
2. Complete Phase 2: Foundational (CRITICAL)
3. Complete Phase 3: User Story 1
4. **STOP and VALIDATE**: Run Smoke Test 1 from quickstart.md
5. Books are uploadable, embedded, and queryable — core infrastructure proven
### Incremental Delivery
1. Setup + Foundational → infrastructure ready
2. US1 → upload & embed books → **Demo: Library management works**
3. US2 → topic summaries → **Demo: AI-generated summaries from books**
4. US3 → chat → **Demo: Full interactive learning experience**
5. Polish → production-ready POC
---
## Notes
- `[P]` tasks have no blocking dependencies on incomplete tasks in the same phase — safe to run in parallel
- `[US1/2/3]` label maps task to specific user story for traceability
- Backend and frontend phases within each story can run in parallel if two developers are available
- Commit after each checkpoint to preserve independently testable increments
- Tests are not generated (not requested); smoke tests in quickstart.md serve as the validation gate