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

15 KiB
Raw Blame History

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.md at repo root
  • 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
  • T003 [P] Initialize Vue 3 + Vite + TypeScript frontend project in frontend/ via npm create vue@latest; add Axios and Pinia
  • T004 [P] Create docker-compose.yml at repo root for local dev: PostgreSQL 16 with pgvector image (pgvector/pgvector:pg16), volume, env vars
  • 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.

  • 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
  • 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: declare ChatClient bean wrapping auto-configured ChatModel, document any Spring AI 2.x @Bean wiring required for VectorStore and EmbeddingModel
  • 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)
  • 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
  • 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
  • T012 [P] Configure Vue Router in frontend/src/router/index.ts: routes for / (UploadView), /topics (TopicsView), /chat (ChatView)
  • 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

  • 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: enum PENDING, PROCESSING, READY, FAILED
  • T016 [P] [US1] Create backend/src/main/java/com/aiteacher/book/BookRepository.java: Spring Data JPA repository for Book
  • 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)
  • 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)
  • 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)
  • T020 [P] [US1] Create frontend/src/stores/bookStore.ts (Pinia): state for book list, actions fetchBooks(), uploadBook(file), deleteBook(id) using api.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 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

  • T023 [P] [US2] Create backend/src/main/java/com/aiteacher/topic/Topic.java: Java record with fields id, name, description, category
  • 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)
  • 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)
  • 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)
  • T027 [P] [US2] Create frontend/src/stores/topicStore.ts (Pinia): state for topics list and active summary, actions fetchTopics(), 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 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

  • 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, sessionId FK, role, content, sources JSONB, createdAt)
  • T032 [P] [US3] Create backend/src/main/java/com/aiteacher/chat/ChatSessionRepository.java and MessageRepository.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, 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)
  • 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)
  • T035 [P] [US3] Create frontend/src/stores/chatStore.ts (Pinia): state for active session and messages, actions createSession(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 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.

  • 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
  • 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) and frontend/Dockerfile (Node 20 build → nginx serve)
  • T041 [P] Run all three smoke tests from specs/001-neuro-rag-learning/quickstart.md against the running stack and confirm each passes
  • 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

# 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