15 KiB
description
| 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.
- T001 Create monorepo directory structure:
backend/,frontend/,README.mdat repo root - T002 Initialize Spring Boot 4.0.5 backend Maven project with
pom.xmlinbackend/; 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 - T003 [P] Initialize Vue 3 + Vite + TypeScript frontend project in
frontend/vianpm create vue@latest; add Axios and Pinia - T004 [P] Create
docker-compose.ymlat repo root for local dev: PostgreSQL 16 with pgvector image (pgvector/pgvector:pg16), volume, env vars - T005 [P] Add
README.mdwith project description and Mermaid system-context diagram (copy diagram fromspecs/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.
- 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.passwordproperty - 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) - T008 [P] Create
backend/src/main/java/com/aiteacher/config/AiConfig.java: declareChatClientbean wrapping auto-configuredChatModel, document any Spring AI 2.x@Beanwiring required forVectorStoreandEmbeddingModel - T009 [P] Create Flyway migration
backend/src/main/resources/db/migration/V1__initial_schema.sql:book,chat_session,messagetables +idx_message_sessionindex (DDL from data-model.md; do NOT createvector_store— Spring AI handles it) - T010 [P] Create
backend/src/main/resources/topics.jsonwith 10–15 representative neurosurgery topics (id slug, name, description, category) covering Vascular, Oncology, Spine, Trauma domains - T011 [P] Create
frontend/src/services/api.ts: Axios instance withbaseURLfromVITE_API_URLenv var,authobject for Basic credentials fromVITE_APP_PASSWORDenv var - T012 [P] Configure Vue Router in
frontend/src/router/index.ts: routes for/(UploadView),/topics(TopicsView),/chat(ChatView) - T013 [P] Create
frontend/src/.env.exampleandfrontend/src/App.vuewith 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
- 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) - T015 [P] [US1] Create
backend/src/main/java/com/aiteacher/book/BookStatus.java: enumPENDING,PROCESSING,READY,FAILED - T016 [P] [US1] Create
backend/src/main/java/com/aiteacher/book/BookRepository.java: Spring Data JPA repository forBook - T017 [US1] Create
backend/src/main/java/com/aiteacher/book/BookEmbeddingService.java: usePagePdfDocumentReaderto 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 tagchunk_type=diagram; callvectorStore.add(documents)(depends on T014, T016) - T018 [US1] Create
backend/src/main/java/com/aiteacher/book/BookService.java: persistBookas PENDING, trigger async embedding viaBookEmbeddingService(@Async), update status to PROCESSING/READY/FAILED, provide list/get/delete operations; on delete cascade remove vector chunks viavectorStore.delete(filter on book_id)(depends on T017) - T019 [US1] Create
backend/src/main/java/com/aiteacher/book/BookController.java: implement all four endpoints fromcontracts/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) - T020 [P] [US1] Create
frontend/src/stores/bookStore.ts(Pinia): state for book list, actionsfetchBooks(),uploadBook(file),deleteBook(id)usingapi.ts - T021 [P] [US1] Create
frontend/src/components/BookCard.vue: display title, fileName, status badge (colour-coded), uploadedAt, delete button - T022 [US1] Create
frontend/src/views/UploadView.vue: file input (PDF only), upload button, progress/status message, book list usingBookCard; 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
- T023 [P] [US2] Create
backend/src/main/java/com/aiteacher/topic/Topic.java: Java record with fieldsid,name,description,category - T024 [P] [US2] Create
backend/src/main/java/com/aiteacher/topic/TopicConfigLoader.java:@Componentthat readstopics.jsonat startup using Jackson and exposesList<Topic> getAll()andOptional<Topic> findById(String id) - T025 [US2] Create
backend/src/main/java/com/aiteacher/topic/TopicSummaryService.java: useChatClientwithQuestionAnswerAdvisor(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 returnedChatResponse; return a DTO withsummarystring andsourceslist; if no READY books exist throwNoKnowledgeSourceException(depends on T024) - T026 [US2] Create
backend/src/main/java/com/aiteacher/topic/TopicController.java:GET /api/v1/topicsandPOST /api/v1/topics/{id}/summarypercontracts/topics-api.md; mapNoKnowledgeSourceException→ 503 (depends on T025) - T027 [P] [US2] Create
frontend/src/stores/topicStore.ts(Pinia): state for topics list and active summary, actionsfetchTopics(),generateSummary(topicId) - T028 [P] [US2] Create
frontend/src/components/TopicCard.vue: display topic name, description, category badge, "Generate Summary" button - T029 [US2] Create
frontend/src/views/TopicsView.vue: grid ofTopicCardcomponents; 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
- T030 [P] [US3] Create
backend/src/main/java/com/aiteacher/chat/ChatSession.java: JPA entity (id,topicId,createdAt) - T031 [P] [US3] Create
backend/src/main/java/com/aiteacher/chat/Message.java: JPA entity (id,sessionIdFK,role,content,sourcesJSONB,createdAt) - T032 [P] [US3] Create
backend/src/main/java/com/aiteacher/chat/ChatSessionRepository.javaandMessageRepository.java: Spring Data JPA repositories - 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, callChatClientwithQuestionAnswerAdvisor; persist both the user message and the assistant response with source metadata; throwNoKnowledgeSourceExceptionwhen no READY books (depends on T030, T031, T032) - T034 [US3] Create
backend/src/main/java/com/aiteacher/chat/ChatController.java: all four endpoints fromcontracts/chat-api.md(POST /sessions,GET /sessions/{id}/messages,POST /sessions/{id}/messages,DELETE /sessions/{id}) (depends on T033) - T035 [P] [US3] Create
frontend/src/stores/chatStore.ts(Pinia): state for active session and messages, actionscreateSession(topicId?),sendMessage(content),loadMessages(),deleteSession() - 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) - T037 [US3] Create
frontend/src/views/ChatView.vue: topic selector (optional), "New Chat" button, scrollable message list usingChatMessage, 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.
- T038 [P] Add
@RestControllerAdviceglobal exception handler inbackend/src/main/java/com/aiteacher/config/GlobalExceptionHandler.java: map validation errors → 400,NoKnowledgeSourceException→ 503, generic exceptions → 500; all responses use{ "error": "..." }shape from contracts - T039 [P] Add loading states (spinner), empty-state messages, and API error toasts to all three Vue views (
UploadView,TopicsView,ChatView) - T040 [P] Create
backend/Dockerfile(multi-stage: Maven build → JRE 21 runtime) andfrontend/Dockerfile(Node 20 build → nginx serve) - T041 [P] Run all three smoke tests from
specs/001-neuro-rag-learning/quickstart.mdagainst the running stack and confirm each passes - T042 [P] Verify
README.mdMermaid 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
# 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)
- Complete Phase 1: Setup
- Complete Phase 2: Foundational (CRITICAL)
- Complete Phase 3: User Story 1
- STOP and VALIDATE: Run Smoke Test 1 from quickstart.md
- Books are uploadable, embedded, and queryable — core infrastructure proven
Incremental Delivery
- Setup + Foundational → infrastructure ready
- US1 → upload & embed books → Demo: Library management works
- US2 → topic summaries → Demo: AI-generated summaries from books
- US3 → chat → Demo: Full interactive learning experience
- 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