--- 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 10–15 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 getAll()` and `Optional 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 T001–T005 completion. All T006–T013 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 (T030–T034); frontend (T035–T037) 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