From ec16c9d55221580f833b09f223a78766ec68ea88 Mon Sep 17 00:00:00 2001 From: Ronald Roy Date: Thu, 5 Feb 2026 21:22:28 -0800 Subject: [PATCH] docs: Update all documentation for Next.js/SSE migration All .lore/ reference docs, README, and copilot-instructions still referenced the pre-migration Hono/WebSocket architecture. This updates every stale reference to reflect the current Next.js App Router + SSE stack (PR #458). Changes across 55 files: - Rewrite all frontend/src/ paths to nextjs/ - Replace WebSocket protocol sections with REST/SSE endpoints - Remove references to deleted files (websocket-handler.ts, Hono handlers, server.ts) - Archive 12 outdated .lore/ documents (WebSocket-era designs, diagrams, specs, research) - Rename 3 auto-generated plan files to descriptive names - Delete unused test-vault-widgets fixture (15 files) - Update lore-agents registry with 4 new agents - Fix frontmatter statuses and tags across 10 documents Co-Authored-By: Claude Opus 4.6 --- .github/copilot-instructions.md | 24 +++---- .../active-session-controller.md | 6 +- .../adr-0001-server-side-session-messages.md | 0 .../communication-layer.md | 2 +- .../daily-planning-science.md | 2 +- .../index.md => _archive/excavation-index.md} | 2 +- .../session-auto-resume.md | 2 +- ...session-viewport-separation-brainstorm.md} | 2 +- .../session-viewport-separation-spec.md} | 6 +- .../single-websocket-consolidation.md | 4 +- .../vi-mode-implementation.md | 0 .../vi-mode-pair-writing-work.md} | 0 .../websocket-connection-lifecycle.md | 2 +- .lore/lore-agents.md | 26 ++++--- .lore/plans/daily-prep-system.md | 2 +- ...ng-pinwheel.md => nextjs-consolidation.md} | 2 +- ...ing-giraffe.md => nextjs-test-coverage.md} | 8 +++ ...lurry.md => pairwriting-discussion-fix.md} | 8 +++ .lore/plans/vi-mode-pair-writing.md | 4 +- .../_infrastructure/card-generator.md | 29 ++++---- .../_infrastructure/configuration.md | 6 +- .lore/reference/_infrastructure/extraction.md | 26 +++---- .../_infrastructure/system-settings.md | 62 ++++++++--------- .../_infrastructure/vault-selection.md | 50 ++++++-------- .lore/reference/_overview.md | 20 +++--- .lore/reference/capture.md | 8 +-- .lore/reference/home-dashboard.md | 45 ++++--------- .lore/reference/inspiration.md | 4 +- .lore/reference/navigation-bar.md | 14 ++-- .lore/reference/pair-writing.md | 50 +++----------- .lore/reference/recall.md | 14 ++-- .lore/reference/spaced-repetition.md | 4 +- .lore/reference/task-list.md | 10 +-- .lore/reference/think.md | 67 ++++++++++--------- .lore/retros/ask-question-dialog-sizing.md | 2 +- .lore/retros/daily-prep-frontmatter-fix.md | 2 +- .lore/retros/daily-prep-system.md | 6 +- .lore/retros/next-js-migration.md | 6 +- .../retros/single-websocket-consolidation.md | 4 +- .lore/retros/vi-mode-pair-writing.md | 4 +- .lore/specs/daily-prep.md | 4 +- .lore/specs/vi-mode-pair-writing.md | 4 +- README.md | 30 ++++----- .../widgets/collection-stats.yaml | 24 ------- .../.memory-loop/widgets/note-similarity.yaml | 22 ------ .../.memory-loop/widgets/rating-meter.yaml | 25 ------- .../.memory-loop/widgets/status-table.yaml | 20 ------ .../__fixtures__/test-vault-widgets/CLAUDE.md | 14 ---- .../notes/archived-ideas.md | 24 ------- .../notes/book-review-atomic.md | 28 -------- .../notes/meeting-notes-jan.md | 25 ------- .../notes/no-frontmatter.md | 4 -- .../notes/partial-frontmatter.md | 9 --- .../notes/personal-goals.md | 28 -------- .../test-vault-widgets/notes/project-alpha.md | 21 ------ .../test-vault-widgets/notes/recipe-pasta.md | 32 --------- .../test-vault-widgets/notes/research-ai.md | 24 ------- .../notes/tech-stack-notes.md | 30 --------- 58 files changed, 267 insertions(+), 636 deletions(-) rename .lore/{design => _archive}/active-session-controller.md (96%) rename docs/adr/0001-server-side-session-messages.md => .lore/_archive/adr-0001-server-side-session-messages.md (100%) rename .lore/{reference/_infrastructure => _archive}/communication-layer.md (99%) rename .lore/{research => _archive}/daily-planning-science.md (99%) rename .lore/{excavations/index.md => _archive/excavation-index.md} (99%) rename .lore/{diagrams => _archive}/session-auto-resume.md (99%) rename .lore/{brainstorm/session-viewport-separation.md => _archive/session-viewport-separation-brainstorm.md} (99%) rename .lore/{specs/session-viewport-separation.md => _archive/session-viewport-separation-spec.md} (91%) rename .lore/{design => _archive}/single-websocket-consolidation.md (98%) rename .lore/{research => _archive}/vi-mode-implementation.md (100%) rename .lore/{work/vi-mode-pair-writing.md => _archive/vi-mode-pair-writing-work.md} (100%) rename .lore/{diagrams => _archive}/websocket-connection-lifecycle.md (99%) rename .lore/plans/{vectorized-hopping-pinwheel.md => nextjs-consolidation.md} (99%) rename .lore/plans/{swirling-toasting-giraffe.md => nextjs-test-coverage.md} (97%) rename .lore/plans/{concurrent-imagining-flurry.md => pairwriting-discussion-fix.md} (95%) delete mode 100644 backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/collection-stats.yaml delete mode 100644 backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/note-similarity.yaml delete mode 100644 backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/rating-meter.yaml delete mode 100644 backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/status-table.yaml delete mode 100644 backend/__fixtures__/test-vault-widgets/CLAUDE.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/archived-ideas.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/book-review-atomic.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/meeting-notes-jan.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/no-frontmatter.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/partial-frontmatter.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/personal-goals.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/project-alpha.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/recipe-pasta.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/research-ai.md delete mode 100644 backend/__fixtures__/test-vault-widgets/notes/tech-stack-notes.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 59b2bfe4..4da21659 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,18 +1,18 @@ # Copilot Instructions -- **Scope**: Memory Loop is a Bun monorepo (backend Hono server, React 19 frontend, shared Zod protocol). Core protocol schemas live in [shared/src/protocol.ts](shared/src/protocol.ts) and are the source of truth for WebSocket message types. -- **Dev commands**: From repo root run `bun install`; `bun run dev` spins up both apps; `bun run test` runs backend then frontend; `bun run typecheck` and `bun run lint` fan out to all workspaces. Backend-only dev is `bun run --cwd backend dev`; frontend-only is `bun run --cwd frontend dev`. -- **Environments**: Requires `VAULTS_DIR` pointing at folders containing a `CLAUDE.md` per vault. Optional `MOCK_SDK=true` disables real Anthropic calls; backend serves on `PORT`/`HOST` (defaults 3000/0.0.0.0). Production uses `bun run build` then [scripts/launch.sh](scripts/launch.sh). -- **Backend shape**: Hono app in [backend/src/server.ts](backend/src/server.ts) exposes `/api/health`, `/api/vaults`, `/api/sessions/:vaultId`, vault asset passthrough under `/vault/:vaultId/assets/*` (image-only with traversal checks), and WebSocket `/ws` (per-connection handler instance). Static frontend is served from `frontend/dist`. -- **WebSocket flow**: Handler in [backend/src/websocket-handler.ts](backend/src/websocket-handler.ts) validates messages with `safeParseClientMessage`, routes by `type`, and emits JSON-serialized server messages. Streaming responses emit `response_start` → `response_chunk`* → `response_end`; tool invocations stream `tool_start`/`tool_input`/`tool_end`. Abort calls interrupt active queries. -- **Sessions**: Claude Agent SDK sessions are created/resumed via [backend/src/session-manager.ts](backend/src/session-manager.ts) with defaults in `DISCUSSION_MODE_OPTIONS` (auto-allowed read tools, `permissionMode=acceptEdits`, streaming enabled). Session metadata persists to `~/.memory-loop/sessions/*.json` and is pruned to the most recent five per vault; IDs are validated to avoid traversal. +- **Scope**: Memory Loop is a Bun monorepo (backend library, Next.js 15 App Router frontend, shared Zod schemas). Core types live in [shared/src/types.ts](shared/src/types.ts) and are the source of truth for API and SSE event types. +- **Dev commands**: From repo root run `bun install`; `bun run --cwd nextjs dev` starts the Next.js dev server on port 3000; `bun run test` runs all workspaces sequentially; `bun run typecheck` and `bun run lint` fan out to all workspaces. +- **Environments**: Requires `VAULTS_DIR` pointing at folders containing a `CLAUDE.md` per vault. Optional `MOCK_SDK=true` disables real Anthropic calls; Next.js serves on `PORT`/`HOSTNAME` (defaults 3000/0.0.0.0). Production uses `bun run --cwd nextjs build` then [scripts/launch.sh](scripts/launch.sh). +- **Backend shape**: Backend is a library (no HTTP server) consumed by Next.js API routes. Domain logic lives in [backend/src/](backend/src/): session management, vault operations, streaming, note capture, file browsing. Next.js API routes in [nextjs/app/api/](nextjs/app/api/) are thin wrappers that call backend functions. +- **SSE streaming**: AI chat uses SSE via POST to `/api/chat`. The [Active Session Controller](nextjs/lib/controller.ts) is a singleton (survives Next.js HMR via globalThis) that manages the live SDK connection. Frontend sends prompts via REST, reads the SSE stream for incremental responses. Stop/permission/answer requests are separate REST calls alongside the stream. +- **Sessions**: Claude Agent SDK sessions are created/resumed via [backend/src/session-manager.ts](backend/src/session-manager.ts). Session metadata persists to vault metadata directory and is pruned to the most recent five per vault; IDs are validated to avoid traversal. - **Vault discovery and goals**: [backend/src/vault-manager.ts](backend/src/vault-manager.ts) scans `VAULTS_DIR` for directories containing `CLAUDE.md`, extracts the first `#` heading as the vault name, detects inbox paths from common patterns, and optionally loads goals from `06_Metadata/memory-loop/goals.md`. Goals are parsed into sections with a 9-item cap. - **Note capture**: [backend/src/note-capture.ts](backend/src/note-capture.ts) writes to `00_Inbox/YYYY-MM-DD.md` (creates inbox as needed), appends under `## Capture` with `- [HH:MM] text`, preserves existing content, and normalizes CRLF. Empty text returns a protocol error. - **File browsing**: [backend/src/file-browser.ts](backend/src/file-browser.ts) whitelists markdown reads only, rejects symlinks, enforces vault-boundary checks (`realpath`), and truncates reads >1MB. Directory listings skip dotfiles and sort dirs-first. - **Inspiration**: [backend/src/inspiration-manager.ts](backend/src/inspiration-manager.ts) pulls contextual prompts from `06_Metadata/memory-loop/contextual-prompts.md` (weekday-only generation) and weekly quotes from `06_Metadata/memory-loop/general-inspiration.md`. Context gathering prioritizes recent daily notes and project/area README/index files with a 3200-char budget. -- **Frontend state**: [frontend/src/contexts/SessionContext.tsx](frontend/src/contexts/SessionContext.tsx) is the single source of truth (useReducer). Modes: home, note, discussion, browse. Vault ID and browser path persist via localStorage; messages are server-sourced only. Pinned folders are stored per-vault locally. -- **WebSocket client**: [frontend/src/hooks/useWebSocket.ts](frontend/src/hooks/useWebSocket.ts) builds the ws URL from the current origin, validates server messages with `safeParseServerMessage`, and auto-reconnects with exponential backoff. `useServerMessageHandler` in SessionContext consumes `session_ready`/`response_*` events and updates state. -- **UI composition**: Root shell in [frontend/src/App.tsx](frontend/src/App.tsx) gates on vault selection (`VaultSelect`), then renders mode-specific components (`HomeView`, `NoteCapture`, `Discussion`, `BrowseMode`) with header actions for new session and vault switch dialogs. -- **Testing**: Backend `bun run test` iterates all files under [backend/src/__tests__](backend/src/__tests__), often using temp dirs and mocked SDK. Frontend tests use `@testing-library/react` with happy-dom from [frontend/src/test-setup.ts](frontend/src/test-setup.ts). Protocol tests live in [shared/src/__tests__/protocol.test.ts](shared/src/__tests__/protocol.test.ts). -- **Testing constraints**: Tests cannot run in parallel (filesystem contention causes flaky failures). Do not use `mock.module()` (causes infinite loops in Bun); use dependency injection instead. The SDK uses a provider pattern ([backend/src/sdk-provider.ts](backend/src/sdk-provider.ts)) where only `index.ts` calls `initializeSdkProvider()`; tests use `configureSdkForTesting(mockFn)` to prevent accidental API calls. -- **Common pitfalls**: WebSocket endpoints expect JSON matching protocol discriminators; invalid JSON returns `VALIDATION_ERROR`. File reads must be `.md` relative to vault root. When mocking, set `MOCK_SDK=true` before starting the backend; otherwise the SDK will try to spawn Claude Code. +- **Frontend state**: [nextjs/contexts/SessionContext.tsx](nextjs/contexts/SessionContext.tsx) is the single source of truth (useReducer). Modes: home, note, discussion, browse. Vault ID and browser path persist via localStorage; messages are server-sourced only. Pinned folders are stored per-vault locally. +- **SSE client**: [nextjs/hooks/useChat.ts](nextjs/hooks/useChat.ts) sends a POST to `/api/chat`, reads the SSE response stream, and dispatches events to SessionContext. Event types include `session_ready`, `response_chunk`, `tool_start`/`tool_end`, `request_permission`, and `ask_question`. +- **UI composition**: Root shell in [nextjs/app/page.tsx](nextjs/app/page.tsx) gates on vault selection (`VaultSelect`), then renders mode-specific components (`HomeView`, `NoteCapture`, `Discussion`, `BrowseMode`) with header actions for new session and vault switch dialogs. +- **Testing**: Backend tests use Bun's test runner under [backend/src/__tests__](backend/src/__tests__), often using temp dirs and mocked SDK. Next.js tests use `@testing-library/react` with happy-dom via [nextjs/test-setup.ts](nextjs/test-setup.ts). Shared tests live in [shared/src/__tests__](shared/src/__tests__). +- **Testing constraints**: Tests cannot run in parallel (filesystem contention causes flaky failures). Do not use `mock.module()` (causes infinite loops in Bun); use dependency injection instead. The SDK uses a provider pattern ([backend/src/sdk-provider.ts](backend/src/sdk-provider.ts)); tests use `configureSdkForTesting(mockFn)` to prevent accidental API calls. +- **Common pitfalls**: File reads must be `.md` relative to vault root. When mocking, set `MOCK_SDK=true`; otherwise the SDK will try to spawn Claude Code. SSE events are newline-delimited JSON with `data:` prefix. diff --git a/.lore/design/active-session-controller.md b/.lore/_archive/active-session-controller.md similarity index 96% rename from .lore/design/active-session-controller.md rename to .lore/_archive/active-session-controller.md index 890fac95..a6e9dcf5 100644 --- a/.lore/design/active-session-controller.md +++ b/.lore/_archive/active-session-controller.md @@ -1,10 +1,10 @@ --- title: Active Session Controller interface date: 2026-02-03 -status: draft +status: implemented tags: [architecture, interface-design, session-management, pub-sub] modules: [active-session-controller, websocket-handler, session-manager] -related: [.lore/specs/session-viewport-separation.md] +related: [.lore/_archive/session-viewport-separation-spec.md] --- # Design: Active Session Controller Interface @@ -13,7 +13,7 @@ related: [.lore/specs/session-viewport-separation.md] Design the interface for Active Session Controller - the new component that owns the live SDK connection and lets viewports (WebSocket connections) subscribe/unsubscribe. -See [Spec: session-viewport-separation](.lore/specs/session-viewport-separation.md) for requirements. +See [Spec: session-viewport-separation](.lore/_archive/session-viewport-separation-spec.md) for requirements. ## Constraints diff --git a/docs/adr/0001-server-side-session-messages.md b/.lore/_archive/adr-0001-server-side-session-messages.md similarity index 100% rename from docs/adr/0001-server-side-session-messages.md rename to .lore/_archive/adr-0001-server-side-session-messages.md diff --git a/.lore/reference/_infrastructure/communication-layer.md b/.lore/_archive/communication-layer.md similarity index 99% rename from .lore/reference/_infrastructure/communication-layer.md rename to .lore/_archive/communication-layer.md index 995d91cc..21b9e3ce 100644 --- a/.lore/reference/_infrastructure/communication-layer.md +++ b/.lore/_archive/communication-layer.md @@ -1,7 +1,7 @@ --- title: Communication Layer Infrastructure date: 2026-01-28 -status: current +status: outdated tags: [websocket, rest-api, protocol, streaming] modules: [websocket-handler, server, protocol] --- diff --git a/.lore/research/daily-planning-science.md b/.lore/_archive/daily-planning-science.md similarity index 99% rename from .lore/research/daily-planning-science.md rename to .lore/_archive/daily-planning-science.md index d8ee96e0..2a4c3c5f 100644 --- a/.lore/research/daily-planning-science.md +++ b/.lore/_archive/daily-planning-science.md @@ -2,7 +2,7 @@ title: Science of Daily Planning and Morning Rituals date: 2026-02-02 status: archived -tags: [daily-planning, productivity, psychology, behavioral-economics, energy-management] +tags: [daily-planning, productivity, psychology, behavioral-economics, energy] related: [.lore/brainstorm/daily-prep-system.md] --- diff --git a/.lore/excavations/index.md b/.lore/_archive/excavation-index.md similarity index 99% rename from .lore/excavations/index.md rename to .lore/_archive/excavation-index.md index 66ccbdc6..8224f9e8 100644 --- a/.lore/excavations/index.md +++ b/.lore/_archive/excavation-index.md @@ -1,7 +1,7 @@ --- title: Excavation Index date: 2026-01-28 -status: current +status: outdated tags: [excavation, index, documentation] --- diff --git a/.lore/diagrams/session-auto-resume.md b/.lore/_archive/session-auto-resume.md similarity index 99% rename from .lore/diagrams/session-auto-resume.md rename to .lore/_archive/session-auto-resume.md index aa38233a..e098fe88 100644 --- a/.lore/diagrams/session-auto-resume.md +++ b/.lore/_archive/session-auto-resume.md @@ -1,7 +1,7 @@ --- title: Session Auto-Resume Flow date: 2026-01-28 -status: current +status: outdated tags: [architecture, session, websocket, rest-api] modules: [session-manager, vault-select] --- diff --git a/.lore/brainstorm/session-viewport-separation.md b/.lore/_archive/session-viewport-separation-brainstorm.md similarity index 99% rename from .lore/brainstorm/session-viewport-separation.md rename to .lore/_archive/session-viewport-separation-brainstorm.md index a10fa5a2..08eb4c76 100644 --- a/.lore/brainstorm/session-viewport-separation.md +++ b/.lore/_archive/session-viewport-separation-brainstorm.md @@ -1,7 +1,7 @@ --- title: Session and viewport separation date: 2026-02-03 -status: open +status: parked tags: [architecture, websocket, session-management, separation-of-concerns] modules: [websocket-handler, session-manager] --- diff --git a/.lore/specs/session-viewport-separation.md b/.lore/_archive/session-viewport-separation-spec.md similarity index 91% rename from .lore/specs/session-viewport-separation.md rename to .lore/_archive/session-viewport-separation-spec.md index 8153c6df..bcf278a3 100644 --- a/.lore/specs/session-viewport-separation.md +++ b/.lore/_archive/session-viewport-separation-spec.md @@ -4,7 +4,7 @@ date: 2026-02-03 status: draft tags: [architecture, websocket, session-management, separation-of-concerns, refactor] modules: [websocket-handler, session-manager, active-session-controller] -related: [.lore/brainstorm/session-viewport-separation.md] +related: [.lore/_archive/session-viewport-separation-brainstorm.md] --- # Spec: Session Viewport Separation @@ -84,5 +84,5 @@ Three distinct components with clear ownership: ## Context - [Brainstorm: Session and Viewport Separation](/.lore/brainstorm/session-viewport-separation.md) -- [Diagram: WebSocket Connection Lifecycle](/.lore/diagrams/websocket-connection-lifecycle.md) -- [Reference: Communication Layer](/.lore/reference/_infrastructure/communication-layer.md) +- [Diagram: WebSocket Connection Lifecycle](/.lore/_archive/websocket-connection-lifecycle.md) (archived - WebSocket replaced by SSE) +- [Reference: Communication Layer](/.lore/_archive/communication-layer.md) (archived - WebSocket replaced by SSE) diff --git a/.lore/design/single-websocket-consolidation.md b/.lore/_archive/single-websocket-consolidation.md similarity index 98% rename from .lore/design/single-websocket-consolidation.md rename to .lore/_archive/single-websocket-consolidation.md index 4ee99b2f..9b27da00 100644 --- a/.lore/design/single-websocket-consolidation.md +++ b/.lore/_archive/single-websocket-consolidation.md @@ -1,10 +1,10 @@ --- title: Single WebSocket Consolidation date: 2026-02-03 -status: implemented +status: superseded tags: [websocket, architecture, rest-api, migration] modules: [websocket-handler, app, discussion, session-context] -related: [.lore/specs/session-viewport-separation.md, .lore/reference/_infrastructure/communication-layer.md] +related: [.lore/_archive/session-viewport-separation-spec.md, .lore/_archive/communication-layer.md] --- # Design: Single WebSocket Consolidation diff --git a/.lore/research/vi-mode-implementation.md b/.lore/_archive/vi-mode-implementation.md similarity index 100% rename from .lore/research/vi-mode-implementation.md rename to .lore/_archive/vi-mode-implementation.md diff --git a/.lore/work/vi-mode-pair-writing.md b/.lore/_archive/vi-mode-pair-writing-work.md similarity index 100% rename from .lore/work/vi-mode-pair-writing.md rename to .lore/_archive/vi-mode-pair-writing-work.md diff --git a/.lore/diagrams/websocket-connection-lifecycle.md b/.lore/_archive/websocket-connection-lifecycle.md similarity index 99% rename from .lore/diagrams/websocket-connection-lifecycle.md rename to .lore/_archive/websocket-connection-lifecycle.md index 2328d13d..c484d7ef 100644 --- a/.lore/diagrams/websocket-connection-lifecycle.md +++ b/.lore/_archive/websocket-connection-lifecycle.md @@ -1,7 +1,7 @@ --- title: WebSocket Connection Lifecycle date: 2026-01-28 -status: current +status: outdated tags: [architecture, websocket, connection, reconnect] modules: [websocket-handler, use-websocket] --- diff --git a/.lore/lore-agents.md b/.lore/lore-agents.md index 12452c60..2877507a 100644 --- a/.lore/lore-agents.md +++ b/.lore/lore-agents.md @@ -1,6 +1,6 @@ --- title: Lore Agents Registry -date: 2026-01-29 +date: 2026-02-05 status: current tags: [agents, registry, tooling] --- @@ -9,7 +9,7 @@ tags: [agents, registry, tooling] Specialized agents available for lore-development work in this project. -Last updated: 2026-01-29 +Last updated: 2026-02-05 ## Discovery @@ -17,12 +17,21 @@ Last updated: 2026-01-29 |-------|---------|-------------| | `Explore` | Fast codebase exploration | Finding files by patterns, searching code for keywords, answering questions about Memory Loop structure | | `lore-development:surface-surveyor` | Entry point discovery | Finding where features start during excavation (e.g., tracing a mode from NavBar to View component) | +| `lore-development:lore-researcher` | Searches lore frontmatter for related prior work | Before starting new specs or designs, to surface what's already been explored | + +## Documentation Review + +| Agent | Purpose | When to Use | +|-------|---------|-------------| +| `lore-development:spec-reviewer` | Fresh-context spec review for clarity issues | After completing a spec, when requirements feel ambiguous | +| `lore-development:design-reviewer` | Fresh-context design review for weak decisions | After completing a design, when technical approach feels uncertain | +| `lore-development:fresh-lore` | Fresh-context analysis from outside accumulated context | When too deep in the weeds to think clearly, need a second opinion | ## Architecture | Agent | Purpose | When to Use | |-------|---------|-------------| -| `Plan` | Software architect for implementation design | Planning new features, choosing between approaches (REST vs WebSocket), architectural trade-offs | +| `Plan` | Software architect for implementation design | Planning new features, choosing between approaches, architectural trade-offs | ## Code Quality @@ -31,8 +40,7 @@ Last updated: 2026-01-29 | `pr-review-toolkit:code-reviewer` | Project guideline adherence | Before commits, after implementing features | | `pr-review-toolkit:code-simplifier` | Simplifies code for clarity | Refactoring hooks, reducing component complexity | | `pr-review-toolkit:comment-analyzer` | Comment accuracy and maintainability | Reviewing JSDoc comments, protocol documentation | -| `pr-review-toolkit:type-design-analyzer` | Type design analysis | Reviewing new Zod schemas, WebSocket message types | -| `code-simplifier:code-simplifier` | Code clarity and consistency | Refining recently modified code | +| `pr-review-toolkit:type-design-analyzer` | Type design analysis | Reviewing new Zod schemas, SSE event types | ## Testing @@ -44,12 +52,12 @@ Last updated: 2026-01-29 | Agent | Purpose | When to Use | |-------|---------|-------------| -| `pr-review-toolkit:silent-failure-hunter` | Identifies silent failures | Reviewing WebSocket error handling, API fallbacks, catch blocks | +| `pr-review-toolkit:silent-failure-hunter` | Identifies silent failures | Reviewing SSE streaming error handling, API fallbacks, catch blocks | ## Project-Specific Notes - **Testing is mandatory**: Always consult `pr-review-toolkit:pr-test-analyzer` before marking work complete -- **Protocol changes**: When modifying `shared/src/protocol.ts`, use `pr-review-toolkit:type-design-analyzer` to review Zod schema design -- **WebSocket handlers**: Consult `silent-failure-hunter` for any changes to `websocket-handler.ts` or error handling paths +- **Schema changes**: When modifying `shared/src/types.ts`, use `pr-review-toolkit:type-design-analyzer` to review Zod schema design +- **SSE streaming**: Consult `silent-failure-hunter` for any changes to SSE chat endpoint or error handling paths - **SDK integration**: The Claude Agent SDK provider pattern requires careful review; use `code-reviewer` for any `sdk-provider.ts` changes -- **Monorepo context**: When exploring, remember the three workspaces (backend, frontend, shared) have distinct concerns +- **Monorepo context**: Three workspaces (backend, nextjs, shared). Backend is a library consumed by Next.js API routes. No standalone server. diff --git a/.lore/plans/daily-prep-system.md b/.lore/plans/daily-prep-system.md index 6f2db7c8..907b5438 100644 --- a/.lore/plans/daily-prep-system.md +++ b/.lore/plans/daily-prep-system.md @@ -2,7 +2,7 @@ title: Daily Prep System Implementation Plan date: 2026-02-02 status: executed -tags: [skill-development, ui-component, rest-api, ground-tab] +tags: [skill-development, ui, rest-api, ground-tab] modules: [daily-prep-manager, session-actions-card, home-view, daily-prep-skill, daily-debrief-command] related: [.lore/specs/daily-prep.md] --- diff --git a/.lore/plans/vectorized-hopping-pinwheel.md b/.lore/plans/nextjs-consolidation.md similarity index 99% rename from .lore/plans/vectorized-hopping-pinwheel.md rename to .lore/plans/nextjs-consolidation.md index f141a725..2b072a64 100644 --- a/.lore/plans/vectorized-hopping-pinwheel.md +++ b/.lore/plans/nextjs-consolidation.md @@ -1,7 +1,7 @@ --- title: Consolidate to Single Next.js Application date: 2026-02-05 -status: complete +status: executed tags: [migration, next-js, consolidation, maintainability] modules: [nextjs, backend] related: diff --git a/.lore/plans/swirling-toasting-giraffe.md b/.lore/plans/nextjs-test-coverage.md similarity index 97% rename from .lore/plans/swirling-toasting-giraffe.md rename to .lore/plans/nextjs-test-coverage.md index e8a48030..d890482c 100644 --- a/.lore/plans/swirling-toasting-giraffe.md +++ b/.lore/plans/nextjs-test-coverage.md @@ -1,3 +1,11 @@ +--- +title: "Next.js test coverage to 80%+" +date: 2026-02-05 +status: executed +tags: [testing, coverage, next-js, dom-environment, websocket-cleanup] +modules: [nextjs] +--- + # Plan: Next.js Test Coverage to 80%+ ## Current State diff --git a/.lore/plans/concurrent-imagining-flurry.md b/.lore/plans/pairwriting-discussion-fix.md similarity index 95% rename from .lore/plans/concurrent-imagining-flurry.md rename to .lore/plans/pairwriting-discussion-fix.md index 82683f07..3bf73e96 100644 --- a/.lore/plans/concurrent-imagining-flurry.md +++ b/.lore/plans/pairwriting-discussion-fix.md @@ -1,3 +1,11 @@ +--- +title: Fix PairWriting actions not appearing in Discussion +date: 2026-02-05 +status: executed +tags: [bug-fix, pair-writing, discussion, sse, ref-forwarding] +modules: [pair-writing, discussion, use-chat] +--- + # Plan: Fix PairWriting Actions Not Appearing in Discussion ## Bug diff --git a/.lore/plans/vi-mode-pair-writing.md b/.lore/plans/vi-mode-pair-writing.md index df240d88..5df496b3 100644 --- a/.lore/plans/vi-mode-pair-writing.md +++ b/.lore/plans/vi-mode-pair-writing.md @@ -4,7 +4,7 @@ date: 2026-01-29 status: executed tags: [vi-mode, pair-writing, modal-editing, keyboard] modules: [pair-writing-editor, use-vi-mode] -related: [.lore/specs/vi-mode-pair-writing.md, .lore/research/vi-mode-implementation.md] +related: [.lore/specs/vi-mode-pair-writing.md, .lore/_archive/vi-mode-implementation.md] --- # Plan: Vi Mode for Pair Writing @@ -12,7 +12,7 @@ related: [.lore/specs/vi-mode-pair-writing.md, .lore/research/vi-mode-implementa ## Context - **Spec**: `.lore/specs/vi-mode-pair-writing.md` -- **Research**: `.lore/research/vi-mode-implementation.md` +- **Research**: `.lore/_archive/vi-mode-implementation.md` - **Integration target**: `PairWritingMode.tsx` and `PairWritingEditor.tsx` ## Approach diff --git a/.lore/reference/_infrastructure/card-generator.md b/.lore/reference/_infrastructure/card-generator.md index 1dccc0ad..9ff98de3 100644 --- a/.lore/reference/_infrastructure/card-generator.md +++ b/.lore/reference/_infrastructure/card-generator.md @@ -218,20 +218,21 @@ Both checked before starting any pass. Cleared on completion (even on error). | `backend/src/spaced-repetition/card-discovery-scheduler.ts` | Scheduling passes | | `backend/src/spaced-repetition/card-generator-config.ts` | Config management | | `backend/src/spaced-repetition/card-manager.ts` | Card file CRUD | -| `backend/src/handlers/card-generator-handlers.ts` | WebSocket message handlers | -| `frontend/src/components/settings/CardGeneratorEditor.tsx` | Config UI | - -### WebSocket Messages - -| Message | Purpose | -|---------|---------| -| `get_card_generator_config` | Load config + requirements + usage | -| `save_card_generator_requirements` | Save requirements override | -| `save_card_generator_config` | Save byte limit | -| `reset_card_generator_requirements` | Delete override, restore default | -| `trigger_card_generation` | Start manual pass | -| `get_card_generation_status` | Check progress | -| `card_generation_status` | Progress updates (server → client) | +| `nextjs/app/api/config/card-generator/route.ts` | REST API: get/save config | +| `nextjs/app/api/config/card-generator/trigger/route.ts` | REST API: manual trigger | +| `nextjs/app/api/config/card-generator/status/route.ts` | REST API: generation status | +| `nextjs/app/api/config/card-generator/requirements/route.ts` | REST API: reset requirements | +| `nextjs/components/vault/CardGeneratorEditor.tsx` | Config UI | + +### REST API + +| Method | Endpoint | Purpose | +|--------|----------|---------| +| GET | `/api/config/card-generator` | Load config + requirements + usage | +| PUT | `/api/config/card-generator` | Save requirements and/or byte limit | +| DELETE | `/api/config/card-generator/requirements` | Delete override, restore default | +| POST | `/api/config/card-generator/trigger` | Start manual pass | +| GET | `/api/config/card-generator/status` | Check generation progress | ## Startup Behavior diff --git a/.lore/reference/_infrastructure/configuration.md b/.lore/reference/_infrastructure/configuration.md index b77c28cb..464c56ec 100644 --- a/.lore/reference/_infrastructure/configuration.md +++ b/.lore/reference/_infrastructure/configuration.md @@ -130,12 +130,12 @@ Badges are colored chips displayed on vault cards. | File | Role | |------|------| -| `frontend/src/components/vault/ConfigEditorDialog.tsx` | Edit dialog UI | -| `frontend/src/components/vault/VaultSelect.tsx` | Opens dialog, handles save | +| `nextjs/components/vault/ConfigEditorDialog.tsx` | Edit dialog UI | +| `nextjs/components/vault/VaultSelect.tsx` | Opens dialog, handles save | | `backend/src/routes/config.ts` | REST endpoint | | `backend/src/handlers/config-handlers.ts` | Update handler | | `backend/src/vault-config.ts` | Load/save/defaults | -| `shared/src/protocol.ts` | Zod schemas | +| `shared/src/types.ts` | Zod schemas | ### API diff --git a/.lore/reference/_infrastructure/extraction.md b/.lore/reference/_infrastructure/extraction.md index 274dee6d..25b6d8da 100644 --- a/.lore/reference/_infrastructure/extraction.md +++ b/.lore/reference/_infrastructure/extraction.md @@ -37,7 +37,7 @@ Transcripts Claude SDK Global Memory ### Manual - **Settings Dialog** → Extraction Prompt tab → "Run Extraction" button -- Sends `trigger_extraction` WebSocket message +- Calls `POST /api/config/extraction-prompt/trigger` - Same pipeline as scheduled, just user-initiated ## Pipeline Steps @@ -166,25 +166,27 @@ Users can directly edit `~/.claude/rules/memory.md`: | File | Role | |------|------| -| `backend/src/index.ts` | Scheduler initialization on startup | +| `nextjs/instrumentation.ts` | Scheduler initialization on startup | | `backend/src/extraction/extraction-manager.ts` | Pipeline orchestration, scheduling | | `backend/src/extraction/fact-extractor.ts` | Claude SDK interaction, prompt building | | `backend/src/extraction/memory-writer.ts` | Sandbox ops, size enforcement, atomic writes | | `backend/src/extraction/extraction-state.ts` | State persistence, checksum tracking | | `backend/src/extraction/transcript-reader.ts` | Transcript discovery, frontmatter parsing | -| `backend/src/handlers/memory-handlers.ts` | WebSocket handlers for manual trigger | +| `nextjs/app/api/config/extraction-prompt/route.ts` | REST API: get/save/reset prompt | +| `nextjs/app/api/config/extraction-prompt/trigger/route.ts` | REST API: manual trigger | +| `nextjs/app/api/config/memory/route.ts` | REST API: get/save memory.md | | `backend/src/prompts/durable-facts.md` | Default extraction prompt | -### WebSocket Messages +### REST API -| Message | Direction | Purpose | -|---------|-----------|---------| -| `trigger_extraction` | Client → Server | Manual extraction run | -| `extraction_status` | Server → Client | Progress/completion/error updates | -| `get_extraction_prompt` | Client → Server | Load current prompt | -| `extraction_prompt_content` | Server → Client | Return prompt content | -| `save_extraction_prompt` | Client → Server | Save custom prompt | -| `reset_extraction_prompt` | Client → Server | Delete override, use default | +| Method | Endpoint | Purpose | +|--------|----------|---------| +| GET | `/api/config/extraction-prompt` | Load current prompt + override status | +| PUT | `/api/config/extraction-prompt` | Save custom prompt | +| DELETE | `/api/config/extraction-prompt` | Delete override, use default | +| POST | `/api/config/extraction-prompt/trigger` | Manual extraction run | +| GET | `/api/config/memory` | Load memory.md content | +| PUT | `/api/config/memory` | Save memory.md content | ### Configuration (Environment) diff --git a/.lore/reference/_infrastructure/system-settings.md b/.lore/reference/_infrastructure/system-settings.md index e62cf611..e5e280d1 100644 --- a/.lore/reference/_infrastructure/system-settings.md +++ b/.lore/reference/_infrastructure/system-settings.md @@ -63,16 +63,14 @@ Customize the prompt used by the nightly extraction pipeline to identify durable - **Reset to Default**: Deletes override, reverts to built-in prompt - **Run Extraction**: Manual trigger for testing -### API (WebSocket) +### API (REST) -| Message | Direction | Purpose | -|---------|-----------|---------| -| `get_extraction_prompt` | → Server | Load current prompt | -| `extraction_prompt_content` | ← Server | Return content + isOverride | -| `save_extraction_prompt` | → Server | Save custom prompt | -| `reset_extraction_prompt` | → Server | Delete override | -| `trigger_extraction` | → Server | Run extraction now | -| `extraction_status` | ← Server | Progress/completion updates | +| Method | Endpoint | Purpose | +|--------|----------|---------| +| GET | `/api/config/extraction-prompt` | Load current prompt + isOverride | +| PUT | `/api/config/extraction-prompt` | Save custom prompt | +| DELETE | `/api/config/extraction-prompt` | Delete override, restore default | +| POST | `/api/config/extraction-prompt/trigger` | Run extraction now | ### Storage - **Default**: Built into code (`backend/src/prompts/durable-facts.md`) @@ -89,17 +87,15 @@ Configure flashcard generation from vault notes. - **Usage bar**: Shows bytes processed this week vs limit - **Run Generator**: Manual trigger (disabled if weekly limit reached) -### API (WebSocket) +### API (REST) -| Message | Direction | Purpose | -|---------|-----------|---------| -| `get_card_generator_config` | → Server | Load requirements + config + usage | -| `card_generator_config_content` | ← Server | Return all settings | -| `save_card_generator_requirements` | → Server | Save custom requirements | -| `save_card_generator_config` | → Server | Save byte limit | -| `reset_card_generator_requirements` | → Server | Delete override | -| `trigger_card_generation` | → Server | Run generation now | -| `card_generation_status` | ← Server | Progress with filesProcessed, cardsCreated | +| Method | Endpoint | Purpose | +|--------|----------|---------| +| GET | `/api/config/card-generator` | Load requirements + config + usage | +| PUT | `/api/config/card-generator` | Save requirements and/or byte limit | +| DELETE | `/api/config/card-generator/requirements` | Delete override, restore default | +| POST | `/api/config/card-generator/trigger` | Run generation now | +| GET | `/api/config/card-generator/status` | Check generation progress | ### Storage - **Default requirements**: Built into code @@ -112,22 +108,18 @@ Configure flashcard generation from vault notes. | File | Role | |------|------| -| `frontend/src/components/vault/SettingsDialog.tsx` | Dialog shell with tabs | -| `frontend/src/components/vault/MemoryEditor.tsx` | Memory tab content | -| `frontend/src/components/vault/ExtractionPromptEditor.tsx` | Extraction tab content | -| `frontend/src/components/vault/CardGeneratorEditor.tsx` | Card Generator tab content | -| `frontend/src/hooks/useMemory.ts` | REST client for memory | -| `backend/src/routes/memory.ts` | Memory REST endpoints | -| `backend/src/handlers/memory-handlers.ts` | Extraction WebSocket handlers | -| `backend/src/handlers/card-generator-handlers.ts` | Card Generator WebSocket handlers | +| `nextjs/components/vault/SettingsDialog.tsx` | Dialog shell with tabs | +| `nextjs/components/vault/MemoryEditor.tsx` | Memory tab content | +| `nextjs/components/vault/ExtractionPromptEditor.tsx` | Extraction tab content | +| `nextjs/components/vault/CardGeneratorEditor.tsx` | Card Generator tab content | +| `nextjs/hooks/useMemory.ts` | REST client for memory | +| `nextjs/app/api/config/memory/route.ts` | Memory REST endpoints | +| `nextjs/app/api/config/extraction-prompt/route.ts` | Extraction REST endpoints | +| `nextjs/app/api/config/card-generator/route.ts` | Card Generator REST endpoints | ### Communication Pattern -| Tab | Protocol | Reason | -|-----|----------|--------| -| Memory Editor | REST | Simple CRUD, no streaming | -| Extraction Prompt | WebSocket | Manual trigger streams status updates | -| Card Generator | WebSocket | Manual trigger streams progress | +All three tabs use REST. Manual triggers (extraction, card generation) return results synchronously in the response rather than streaming progress. ### Override Pattern @@ -149,11 +141,11 @@ Both Extraction Prompt and Card Generator use the same pattern: - User edits content - Clicks Save → PUT to server 5. User clicks "Extraction Prompt" tab - - Sends get_extraction_prompt via WebSocket + - Fetches prompt via GET /api/config/extraction-prompt - Shows current prompt with Custom/Default badge - Can edit, save, reset, or trigger manual run 6. User clicks "Card Generator" tab - - Sends get_card_generator_config via WebSocket + - Fetches config via GET /api/config/card-generator - Shows requirements + byte limit slider + usage bar - Can edit requirements, adjust limit, or trigger manual generation 7. Clicks X or outside dialog to close @@ -173,4 +165,4 @@ Both Extraction Prompt and Card Generator use the same pattern: - Memory.md is read by Claude at conversation start (context injection) - Manual triggers are for testing; normal operation is scheduled (3am extraction, 4am cards) - Status updates auto-clear after 5 seconds on success -- VaultSelect routes WebSocket messages to correct editor via message type filtering +- Each editor tab manages its own REST calls independently diff --git a/.lore/reference/_infrastructure/vault-selection.md b/.lore/reference/_infrastructure/vault-selection.md index 18148af4..af684c4a 100644 --- a/.lore/reference/_infrastructure/vault-selection.md +++ b/.lore/reference/_infrastructure/vault-selection.md @@ -74,13 +74,10 @@ The app has two different gear buttons that open different dialogs: | Entry | Type | Handler | |-------|------|---------| -| App mount (no vault) | Frontend | `App.tsx` → `AppShell` renders `VaultSelect` | -| GET /api/vaults | REST | `backend/src/server.ts:228` | -| GET /api/sessions/:vaultId | REST | `backend/src/server.ts:242` | -| POST /api/vaults/:id/setup | REST | `backend/src/routes/config.ts:114` | -| select_vault | WebSocket | `backend/src/websocket-handler.ts` | -| resume_session | WebSocket | `backend/src/websocket-handler.ts` | -| create_vault | WebSocket | `backend/src/websocket-handler.ts` | +| App mount (no vault) | Frontend | `app/page.tsx` → `AppShell` renders `VaultSelect` | +| GET /api/vaults | REST | `nextjs/app/api/vaults/route.ts` | +| GET /api/sessions/:vaultId | REST | `nextjs/app/api/sessions/[vaultId]/route.ts` | +| POST /api/vaults/:id/setup | REST | `nextjs/app/api/vaults/[vaultId]/setup/route.ts` | ## Implementation @@ -88,16 +85,16 @@ The app has two different gear buttons that open different dialogs: | File | Role | |------|------| -| `frontend/src/App.tsx` | AppShell decides VaultSelect vs MainContent | -| `frontend/src/components/vault/VaultSelect.tsx` | Main selection UI, auto-resume logic | -| `frontend/src/components/vault/AddVaultDialog.tsx` | New vault creation dialog | -| `frontend/src/components/vault/ConfigEditorDialog.tsx` | Settings editor | -| `frontend/src/contexts/SessionContext.tsx` | Stores selected vault, handles session_ready | -| `frontend/src/contexts/session/storage.ts` | localStorage persistence | +| `nextjs/app/page.tsx` | AppShell decides VaultSelect vs MainContent | +| `nextjs/components/vault/VaultSelect.tsx` | Main selection UI, auto-resume logic | +| `nextjs/components/vault/AddVaultDialog.tsx` | New vault creation dialog | +| `nextjs/components/vault/ConfigEditorDialog.tsx` | Settings editor | +| `nextjs/contexts/SessionContext.tsx` | Stores selected vault, session state | +| `nextjs/contexts/session/storage.ts` | localStorage persistence | +| `nextjs/lib/controller.ts` | Active Session Controller (SDK orchestration) | | `backend/src/vault-manager.ts` | Discovery, parsing, creation | | `backend/src/vault-config.ts` | .memory-loop.json handling | | `backend/src/session-manager.ts` | Session lifecycle | -| `backend/src/websocket-handler.ts` | Message routing | ### Vault Discovery @@ -150,30 +147,25 @@ Client Server │ { sessionId: "..." | null } │ │<──────────────────────────────│ │ │ - │ WS: select_vault/resume │ + │ POST /api/chat │ + │ (vaultId, sessionId, prompt) │ │──────────────────────────────>│ │ │ - │ WS: session_ready │ - │ (sessionId, messages, │ - │ slashCommands) │ + │ SSE stream (events) │ │<──────────────────────────────│ ``` -Sessions are stored in-memory on the server. They survive WebSocket disconnect/reconnect but not server restart. +Sessions are stored in-memory on the server via the Active Session Controller singleton. They survive page refresh (restored from localStorage + session API) but not server restart. ### Auto-Resume On VaultSelect mount: -1. Check WebSocket connected -2. Load `memory-loop.vault` from localStorage -3. Find vault in discovered list -4. Trigger normal selection flow (check session → resume or create) +1. Load `memory-loop.vault` from localStorage +2. Find vault in discovered list +3. Call `GET /api/sessions/:vaultId` to check for existing session +4. Set vault + session in SessionContext 5. Track attempt to prevent loops -### Reconnection Handling - -When WebSocket reconnects after disconnect, MainContent re-sends `select_vault` to restore server-side context. The vault info is already in SessionContext from localStorage. - ## Configuration (.memory-loop.json) All fields optional: @@ -212,7 +204,7 @@ All fields optional: ## Diagrams -- [Session Auto-Resume Flow](../../diagrams/session-auto-resume.md) - How vault selection triggers session lookup and establishment +- [Session Auto-Resume Flow](../../_archive/session-auto-resume.md) - How vault selection triggers session lookup and establishment (archived, pre-migration) ## Setup Wizard @@ -287,6 +279,6 @@ Setup is idempotent: - Vault ID is the directory name (sanitized for URL safety) - Creating a vault converts title to safe directory name: "My Vault!" → "my-vault" -- Session persists server-side by vaultId, not WebSocket connection +- Session persists server-side by vaultId via Active Session Controller singleton - The `setup-complete` marker controls badge display and button text - Health issues can block vault readiness (shown in HealthPanel) diff --git a/.lore/reference/_overview.md b/.lore/reference/_overview.md index 43575671..4e0f519f 100644 --- a/.lore/reference/_overview.md +++ b/.lore/reference/_overview.md @@ -45,12 +45,12 @@ See [Navigation Bar](./navigation-bar.md) for implementation details and [GCTR M ### Monorepo Structure ``` -backend/ # Hono server + Claude Agent SDK -frontend/ # React 19 + Vite SPA -shared/ # Zod schemas for type-safe messages +nextjs/ # Next.js 15 App Router (UI + API routes + SSE streaming) +backend/ # Library: Claude Agent SDK, vault operations, schedulers +shared/ # Zod schemas and TypeScript types ``` -The backend runs from TypeScript source (no build step). The frontend builds to static files served by the backend. +The backend is a library consumed by Next.js API routes. It contains domain logic but no HTTP server of its own. Next.js handles both serving the UI and exposing REST/SSE endpoints. ### Communication @@ -58,12 +58,12 @@ Two channels connect frontend and backend: | Channel | Used For | |---------|----------| -| **REST API** | Stateless operations: file CRUD, search, config, cards | -| **WebSocket** | Streaming: AI responses, tool execution display, session state | +| **REST API** (Next.js API routes) | Stateless operations: file CRUD, search, config, cards | +| **SSE** (Server-Sent Events) | AI chat streaming via POST `/api/chat` | -This split is deliberate. REST handles most operations cleanly. WebSocket handles the cases where you need real-time feedback (watching Claude think) or bidirectional communication (session establishment). +The frontend sends a prompt via REST, then reads the SSE stream for incremental responses. Stop, permission, and answer requests are separate REST calls alongside the stream. All session management (select vault, resume, new session) is REST. -See [Communication Layer](./_infrastructure/communication-layer.md) for protocol details. +See [Communication Layer](../_archive/communication-layer.md) for historical protocol details (archived, pre-migration). ### Vaults @@ -79,7 +79,7 @@ See [Vault Selection](./_infrastructure/vault-selection.md) and [Configuration]( 1. **This document** - You're reading it 2. **[Navigation Bar](./navigation-bar.md)** - The GCTR framework in code -3. **[Communication Layer](./_infrastructure/communication-layer.md)** - How frontend/backend talk +3. **[Communication Layer](../_archive/communication-layer.md)** - How frontend/backend talked (archived, pre-migration) ### The Four Modes @@ -150,4 +150,4 @@ The excavation is ongoing. Gaps include: - **Search** - File and content search in Recall - **Holiday Themes** - Seasonal visual variations -Check [excavations/index.md](../excavations/index.md) for current status. +Check [excavation index](../_archive/excavation-index.md) for historical status (archived). diff --git a/.lore/reference/capture.md b/.lore/reference/capture.md index fc4f1472..7b9d41b4 100644 --- a/.lore/reference/capture.md +++ b/.lore/reference/capture.md @@ -107,9 +107,9 @@ attendees: [] | File | Role | |------|------| -| `frontend/src/components/capture/NoteCapture.tsx` | Main UI component | -| `frontend/src/hooks/useCapture.ts` | REST API client | -| `frontend/src/hooks/useMeetings.ts` | Meeting operations | +| `nextjs/components/capture/NoteCapture.tsx` | Main UI component | +| `nextjs/hooks/useCapture.ts` | REST API client | +| `nextjs/hooks/useMeetings.ts` | Meeting operations | | `backend/src/note-capture.ts` | Daily note logic | | `backend/src/meeting-capture.ts` | Meeting note logic | | `backend/src/routes/capture.ts` | Capture endpoint | @@ -186,6 +186,6 @@ Captures appear in the Recent Activity section on Ground: - No file upload in Capture (exists elsewhere but not integrated here) - No voice input/speech-to-text -- Meeting state stored server-side, survives WebSocket reconnects +- Meeting state stored server-side, survives browser refresh - Section-based appending keeps captures separate from other daily note content - Auto-growing textarea (starts at 3 rows) for better mobile UX diff --git a/.lore/reference/home-dashboard.md b/.lore/reference/home-dashboard.md index dc679413..491e57da 100644 --- a/.lore/reference/home-dashboard.md +++ b/.lore/reference/home-dashboard.md @@ -27,8 +27,8 @@ This is a **container feature**. It orchestrates widgets from several sub-featur | Entry | Type | Handler | |-------|------|---------| -| Mode = "home" | Frontend routing | `frontend/src/App.tsx:243` | -| Tab click | UI | `frontend/src/components/shared/ModeToggle.tsx` | +| Mode = "home" | Frontend routing | `nextjs/app/page.tsx` | +| Tab click | UI | `nextjs/components/shared/ModeToggle.tsx` | | GET /api/vaults/:id/goals | REST | `backend/src/routes/home.ts:84` | | GET /api/vaults/:id/inspiration | REST | `backend/src/routes/home.ts:108` | | GET /api/vaults/:id/tasks | REST | `backend/src/routes/home.ts:146` | @@ -41,13 +41,16 @@ This is a **container feature**. It orchestrates widgets from several sub-featur | File | Role | Lines | |------|------|-------| -| `frontend/src/components/home/HomeView.tsx` | Main orchestrator | 282 | -| `frontend/src/components/home/GoalsCard.tsx` | Goals markdown display | 70 | -| `frontend/src/components/home/HealthPanel.tsx` | Backend issues display | 172 | -| `frontend/src/components/home/RecentActivity.tsx` | Captures and discussions | 328 | -| `frontend/src/hooks/useHome.ts` | Goals, inspiration, tasks API | - | -| `frontend/src/hooks/useCapture.ts` | Recent activity fetching | - | -| `frontend/src/hooks/useSessions.ts` | Session operations | - | +| `nextjs/components/home/HomeView.tsx` | Main orchestrator | - | +| `nextjs/components/home/GoalsCard.tsx` | Goals markdown display | - | +| `nextjs/components/home/RecentActivity.tsx` | Captures and discussions | - | +| `nextjs/components/home/InspirationCard.tsx` | Daily prompts and quotes | - | +| `nextjs/components/home/SpacedRepetitionWidget.tsx` | Card review queue | - | +| `nextjs/components/home/SessionActionsCard.tsx` | Debrief buttons | - | +| `nextjs/components/home/VaultInfoCard.tsx` | Vault name and info | - | +| `nextjs/hooks/useHome.ts` | Goals, inspiration, tasks API | - | +| `nextjs/hooks/useCapture.ts` | Recent activity fetching | - | +| `nextjs/hooks/useSessions.ts` | Session operations | - | | `backend/src/routes/home.ts` | REST endpoints | 236 | | `backend/src/vault-manager.ts` | Goals file reading | - | @@ -84,28 +87,6 @@ This is a **container feature**. It orchestrates widgets from several sub-featur | View capture | Browse | Daily note file path | | Resume discussion | Discussion | Restores session by ID | -## Health Panel - -Displays backend health issues (file watcher failures, config problems, etc.). - -### Issue Display - -Issues appear in a collapsible panel with: -- Issue severity icon -- Description text -- Dismiss button - -### Dismissal - -Health issues are managed per-WebSocket session. Two dismissal paths: - -| Channel | Endpoint | Effect | -|---------|----------|--------| -| WebSocket | `dismiss_health_issue` message | Immediate removal from session state | -| REST | `DELETE /health-issues/:issueId` | Acknowledged but requires WebSocket for actual removal | - -The REST endpoint exists for API completeness but returns a note: "Dismiss via WebSocket for immediate effect." - ## Connected Features | Feature | Relationship | Spec | @@ -118,7 +99,7 @@ The REST endpoint exists for API completeness but returns a note: "Dismiss via W ## Notes -- Home loads data via REST API on mount, not WebSocket (migrated in TASK-010/011) +- Home loads all data via REST API on mount - Error handling uses graceful degradation for inspiration (fallback quote on failure) - SpacedRepetitionWidget is the most complex component (558 lines) and warrants its own spec - Recent Activity fetches on mount but doesn't auto-refresh; data can become stale diff --git a/.lore/reference/inspiration.md b/.lore/reference/inspiration.md index c65f89b9..b01622dd 100644 --- a/.lore/reference/inspiration.md +++ b/.lore/reference/inspiration.md @@ -151,8 +151,8 @@ Older items are pruned when pool exceeds `maxPoolSize`. |------|------| | `backend/src/inspiration-manager.ts` | Generation, parsing, selection | | `backend/src/routes/home.ts` | REST endpoint | -| `frontend/src/components/home/InspirationCard.tsx` | Display component | -| `frontend/src/hooks/useHome.ts` | API client | +| `nextjs/components/home/InspirationCard.tsx` | Display component | +| `nextjs/hooks/useHome.ts` | API client | ### API diff --git a/.lore/reference/navigation-bar.md b/.lore/reference/navigation-bar.md index ffaa18d0..716b5d46 100644 --- a/.lore/reference/navigation-bar.md +++ b/.lore/reference/navigation-bar.md @@ -36,8 +36,8 @@ This vocabulary teaches the practice while using the app. The sigils (🪨🪶 | Entry | Type | Handler | |-------|------|---------| -| Always visible in header | Component | `frontend/src/components/shared/ModeToggle.tsx` | -| Mode state | Context | `frontend/src/contexts/SessionContext.tsx` | +| Always visible in header | Component | `nextjs/components/shared/ModeToggle.tsx` | +| Mode state | Context | `nextjs/contexts/SessionContext.tsx` | ## Implementation @@ -45,11 +45,11 @@ This vocabulary teaches the practice while using the app. The sigils (🪨🪶 | File | Role | |------|------| -| `frontend/src/components/shared/ModeToggle.tsx` | Component rendering and click handling | -| `frontend/src/components/shared/ModeToggle.css` | Styles: glass morphism, selected state, sigil treatment | -| `frontend/src/contexts/SessionContext.tsx` | Mode state via `useReducer` pattern | -| `frontend/src/contexts/session/types.ts` | `AppMode` type definition | -| `frontend/src/App.tsx` | Renders `ModeToggle` in header, conditionally renders mode views | +| `nextjs/components/shared/ModeToggle.tsx` | Component rendering and click handling | +| `nextjs/components/shared/ModeToggle.css` | Styles: glass morphism, selected state, sigil treatment | +| `nextjs/contexts/SessionContext.tsx` | Mode state via `useReducer` pattern | +| `nextjs/contexts/session/types.ts` | `AppMode` type definition | +| `nextjs/app/page.tsx` | Renders `ModeToggle` in header, conditionally renders mode views | ### Data diff --git a/.lore/reference/pair-writing.md b/.lore/reference/pair-writing.md index 388efded..d7d1b4bb 100644 --- a/.lore/reference/pair-writing.md +++ b/.lore/reference/pair-writing.md @@ -110,49 +110,19 @@ This means Quick/Advisory Actions are visible in your conversation history along | File | Role | |------|------| -| `frontend/src/components/pair-writing/PairWritingMode.tsx` | Main container | -| `frontend/src/components/pair-writing/PairWritingEditor.tsx` | Text editor | -| `frontend/src/components/pair-writing/PairWritingToolbar.tsx` | Controls | -| `frontend/src/components/shared/EditorContextMenu.tsx` | Action menu | -| `frontend/src/hooks/usePairWritingState.ts` | State (content, snapshot) | -| `frontend/src/hooks/useTextSelection.ts` | Selection with context | -| `backend/src/handlers/pair-writing-handlers.ts` | Action handlers | +| `nextjs/components/pair-writing/PairWritingMode.tsx` | Main container | +| `nextjs/components/pair-writing/PairWritingEditor.tsx` | Text editor | +| `nextjs/components/pair-writing/PairWritingToolbar.tsx` | Controls | +| `nextjs/components/shared/EditorContextMenu.tsx` | Action menu | +| `nextjs/hooks/usePairWritingState.ts` | State (content, snapshot) | +| `nextjs/hooks/useTextSelection.ts` | Selection with context | | `backend/src/pair-writing-prompts.ts` | Prompt templates | -### WebSocket Messages - -**Client → Server**: - -```typescript -// Quick Action (Tighten, Embellish, Correct, Polish) -{ - type: "quick_action_request", - action: "tighten" | "embellish" | "correct" | "polish", - selection: string, - contextBefore: string, - contextAfter: string, - filePath: string, - selectionStartLine: number, - selectionEndLine: number, - totalLines: number -} - -// Advisory Action (Validate, Critique, Compare, Discuss) -{ - type: "advisory_action_request", - action: "validate" | "critique" | "compare" | "discuss", - selection: string, - contextBefore: string, - contextAfter: string, - filePath: string, - selectionStartLine: number, - selectionEndLine: number, - totalLines: number, - snapshotSelection?: string // Only for "compare" -} -``` +### Action Delivery + +Actions are formatted as chat messages and sent through the regular SSE chat stream (POST `/api/chat`). The component formats the action type, selected text, and surrounding context into a structured prompt, then sends it via `sendMessageRef`. Claude responds through the same SSE stream used for normal conversations. -**Server → Client**: Standard streaming messages (response_start, response_chunk, tool_start, etc.) +**Server → Client**: Standard SSE streaming events (response_start, response_chunk, tool_start, etc.) ### SDK Configuration diff --git a/.lore/reference/recall.md b/.lore/reference/recall.md index 797fe1ab..69082b3d 100644 --- a/.lore/reference/recall.md +++ b/.lore/reference/recall.md @@ -153,13 +153,13 @@ Multi-layer defense: | File | Role | |------|------| -| `frontend/src/components/browse/BrowseMode.tsx` | Main container | -| `frontend/src/components/browse/FileTree.tsx` | Directory tree | -| `frontend/src/components/browse/SearchHeader.tsx` | Search input | -| `frontend/src/components/browse/SearchResults.tsx` | Search results | -| `frontend/src/components/browse/viewers/MarkdownViewer.tsx` | Markdown rendering | -| `frontend/src/hooks/useFileBrowser.ts` | REST client | -| `frontend/src/hooks/useSearch.ts` | Search REST client | +| `nextjs/components/browse/BrowseMode.tsx` | Main container | +| `nextjs/components/browse/FileTree.tsx` | Directory tree | +| `nextjs/components/browse/SearchHeader.tsx` | Search input | +| `nextjs/components/browse/SearchResults.tsx` | Search results | +| `nextjs/components/browse/viewers/MarkdownViewer.tsx` | Markdown rendering | +| `nextjs/hooks/useFileBrowser.ts` | REST client | +| `nextjs/hooks/useSearch.ts` | Search REST client | | `backend/src/routes/files.ts` | File REST endpoints | | `backend/src/file-browser.ts` | Core file operations | | `backend/src/search/search-index.ts` | Search implementation | diff --git a/.lore/reference/spaced-repetition.md b/.lore/reference/spaced-repetition.md index 3f15862d..51f7a6e4 100644 --- a/.lore/reference/spaced-repetition.md +++ b/.lore/reference/spaced-repetition.md @@ -199,8 +199,8 @@ Cards you struggle with get lower ease factors and shorter intervals. | File | Role | |------|------| -| `frontend/src/components/home/SpacedRepetitionWidget.tsx` | Review UI (558 lines) | -| `frontend/src/hooks/useCards.ts` | REST API client | +| `nextjs/components/home/SpacedRepetitionWidget.tsx` | Review UI (558 lines) | +| `nextjs/hooks/useCards.ts` | REST API client | | `backend/src/spaced-repetition/card-generator.ts` | LLM extraction | | `backend/src/spaced-repetition/sm2-algorithm.ts` | Interval calculation | | `backend/src/spaced-repetition/card-storage.ts` | File I/O, parsing | diff --git a/.lore/reference/task-list.md b/.lore/reference/task-list.md index 46f13241..25e45c72 100644 --- a/.lore/reference/task-list.md +++ b/.lore/reference/task-list.md @@ -152,13 +152,13 @@ Count only considers `[x]` as "completed" for numerator. | File | Role | |------|------| -| `frontend/src/components/browse/TaskList.tsx` | Main component (672 lines) | -| `frontend/src/components/browse/TaskList.css` | Styling | -| `frontend/src/components/browse/BrowseMode.tsx` | Container, view toggle | -| `frontend/src/hooks/useHome.ts` | REST client (`getTasks`, `toggleTask`) | +| `nextjs/components/browse/TaskList.tsx` | Main component (672 lines) | +| `nextjs/components/browse/TaskList.css` | Styling | +| `nextjs/components/browse/BrowseMode.tsx` | Container, view toggle | +| `nextjs/hooks/useHome.ts` | REST client (`getTasks`, `toggleTask`) | | `backend/src/task-manager.ts` | Task discovery and parsing | | `backend/src/routes/home.ts` | REST endpoints | -| `shared/src/protocol.ts` | `TaskEntry`, `TaskCategory` schemas | +| `shared/src/types.ts` | `TaskEntry`, `TaskCategory` schemas | ### REST API diff --git a/.lore/reference/think.md b/.lore/reference/think.md index d81ebdba..bb9e9219 100644 --- a/.lore/reference/think.md +++ b/.lore/reference/think.md @@ -3,7 +3,7 @@ title: Think Feature date: 2026-01-28 status: current tags: [think, ai-conversation, streaming, claude-sdk, gctr] -modules: [discussion, session-manager, websocket-handler] +modules: [discussion, session-manager, active-session-controller] --- # Feature: Think @@ -42,38 +42,37 @@ Think is the AI conversation interface. Chat with Claude about your vault, ask q ``` User types message ↓ -Frontend: addMessage(user), send WebSocket +Frontend: addMessage(user), POST /api/chat ↓ -Backend: create/resume session with Claude SDK +Controller: create/resume session with Claude SDK ↓ Claude SDK: generates response ↓ -Backend: streams events via WebSocket +Controller: streams SessionEvents via SSE ↓ -Frontend: renders incrementally +Frontend (useChat): renders incrementally ↓ -Backend: saves to session metadata + transcript +Controller: saves to session metadata + transcript ``` -## WebSocket Protocol +## SSE Streaming Protocol -### Client → Server +The frontend sends a prompt via `POST /api/chat` with vaultId, optional sessionId, and the prompt text. The response is an SSE stream of typed events. -| Message | Purpose | -|---------|---------| -| `select_vault` | Associate connection with vault | -| `resume_session` | Continue existing conversation | -| `new_session` | Start fresh (clears context) | -| `discussion_message` | Send user message to Claude | -| `abort` | Stop current response | -| `tool_permission_response` | Allow/deny tool execution | -| `ask_user_question_response` | Answer Claude's questions | +### REST Endpoints -### Server → Client +| Method | Endpoint | Purpose | +|--------|----------|---------| +| POST | `/api/chat` | Send message, receive SSE stream | +| POST | `/api/chat/{sessionId}/abort` | Stop current response | +| POST | `/api/chat/{sessionId}/permission/{toolUseId}` | Allow/deny tool execution | +| POST | `/api/chat/{sessionId}/answer/{toolUseId}` | Answer Claude's questions | +| GET | `/api/sessions/{vaultId}` | Resume: get latest session info | -| Message | Purpose | -|---------|---------| -| `session_ready` | Session established, includes history if resuming | +### SSE Event Types (Server → Client) + +| Event | Purpose | +|-------|---------| | `response_start` | Claude started responding | | `response_chunk` | Incremental text content | | `response_end` | Response complete, includes context usage | @@ -167,19 +166,19 @@ Click to expand and see full input/output: ### Permission Dialogs Some tools require approval: -1. Backend sends `tool_permission_request` +1. SSE stream emits `tool_permission_request` event 2. Modal shows tool name and parameters 3. User clicks Allow or Deny -4. Frontend sends `tool_permission_response` -5. Backend continues or aborts +4. Frontend calls `POST /api/chat/{sessionId}/permission/{toolUseId}` +5. Controller continues or aborts ### AskUserQuestion Claude can ask structured questions: -1. Backend sends `ask_user_question_request` (1-4 questions) +1. SSE stream emits `ask_user_question_request` event (1-4 questions) 2. Each question has options (2-4 choices) 3. User selects answers -4. Frontend sends `ask_user_question_response` +4. Frontend calls `POST /api/chat/{sessionId}/answer/{toolUseId}` ## Model Selection @@ -213,15 +212,17 @@ Passed to Claude SDK when creating session. | File | Role | |------|------| -| `frontend/src/components/discussion/Discussion.tsx` | Main UI | -| `frontend/src/components/discussion/ConversationPane.tsx` | Message display | -| `frontend/src/components/discussion/SlashCommandAutocomplete.tsx` | Command popup | -| `frontend/src/components/discussion/ToolDisplay.tsx` | Tool invocation cards | -| `frontend/src/components/discussion/FileAttachButton.tsx` | Attachment UI | -| `backend/src/websocket-handler.ts` | Message routing, streaming | +| `nextjs/components/discussion/Discussion.tsx` | Main UI | +| `nextjs/components/discussion/MessageBubble.tsx` | Message display | +| `nextjs/components/discussion/SlashCommandAutocomplete.tsx` | Command popup | +| `nextjs/components/discussion/ToolDisplay.tsx` | Tool invocation cards | +| `nextjs/components/discussion/FileAttachButton.tsx` | Attachment UI | +| `nextjs/hooks/useChat.ts` | SSE chat client | +| `nextjs/lib/controller.ts` | Active Session Controller (SDK orchestration) | +| `nextjs/app/api/chat/route.ts` | SSE chat endpoint | | `backend/src/session-manager.ts` | Session CRUD, SDK integration | | `backend/src/transcript-manager.ts` | Transcript file writing | -| `shared/src/protocol.ts` | Zod schemas for all messages | +| `shared/src/types.ts` | Zod schemas | ### Claude SDK Integration diff --git a/.lore/retros/ask-question-dialog-sizing.md b/.lore/retros/ask-question-dialog-sizing.md index 25cd30bc..89a4c28b 100644 --- a/.lore/retros/ask-question-dialog-sizing.md +++ b/.lore/retros/ask-question-dialog-sizing.md @@ -2,7 +2,7 @@ title: Match dialog display area to page context date: 2026-02-02 status: complete -tags: [css, ui, responsive, dialog, communication] +tags: [css, ui, responsive, dialog] modules: [ask-user-question-dialog] --- diff --git a/.lore/retros/daily-prep-frontmatter-fix.md b/.lore/retros/daily-prep-frontmatter-fix.md index 3f13f0f3..371a3911 100644 --- a/.lore/retros/daily-prep-frontmatter-fix.md +++ b/.lore/retros/daily-prep-frontmatter-fix.md @@ -2,7 +2,7 @@ title: Passive references fail under context degradation date: 2026-02-04 status: complete -tags: [skill-authoring, context-degradation, progressive-disclosure, bug-fix] +tags: [skill-development, context-degradation, progressive-disclosure, bug-fix] modules: [daily-prep-skill] related: [.lore/specs/daily-prep.md, .lore/retros/daily-prep-system.md] --- diff --git a/.lore/retros/daily-prep-system.md b/.lore/retros/daily-prep-system.md index 981e8819..77d983e7 100644 --- a/.lore/retros/daily-prep-system.md +++ b/.lore/retros/daily-prep-system.md @@ -2,9 +2,9 @@ title: Emergent requirements in daily prep implementation date: 2026-02-02 status: complete -tags: [skill-development, ui-component, iterative-design, lore-workflow] +tags: [skill-development, ui, iterative-design, lore-workflow] modules: [daily-prep-manager, session-actions-card, ask-user-question-dialog, home-view] -related: [.lore/brainstorm/daily-prep-system.md, .lore/research/daily-planning-science.md, .lore/specs/daily-prep.md, .lore/plans/daily-prep-system.md] +related: [.lore/brainstorm/daily-prep-system.md, .lore/_archive/daily-planning-science.md, .lore/specs/daily-prep.md, .lore/plans/daily-prep-system.md] --- # Retro: Daily Prep System (#443) @@ -50,6 +50,6 @@ Built a skill-based bookend planning system for morning commitment and evening r - Issue/PR: #443 - Plan: `.lore/plans/daily-prep-system.md` - Brainstorm: `.lore/brainstorm/daily-prep-system.md` -- Research: `.lore/research/daily-planning-science.md` +- Research: `.lore/_archive/daily-planning-science.md` - Spec: `.lore/specs/daily-prep.md` - Skill: `backend/src/skills/daily-prep/SKILL.md` diff --git a/.lore/retros/next-js-migration.md b/.lore/retros/next-js-migration.md index 776b3085..844b0755 100644 --- a/.lore/retros/next-js-migration.md +++ b/.lore/retros/next-js-migration.md @@ -4,7 +4,7 @@ date: 2026-02-05 status: complete tags: [architecture, refactor, next-js, sse, websocket, state-management, race-condition] modules: [session-context, discussion, pair-writing, active-session-controller, useChat] -related: [.lore/brainstorm/next-js-migration.md, .lore/plans/vectorized-hopping-pinwheel.md] +related: [.lore/brainstorm/next-js-migration.md, .lore/plans/nextjs-consolidation.md] --- # Retro: Next.js Migration @@ -25,7 +25,7 @@ Migrated Memory Loop from Vite SPA + Hono backend to Next.js 15 App Router. Repl - **Dual useChat instances weren't caught during migration.** PairWritingMode kept its own `useChat(vault)` call when Discussion already had one. The migration focused on "does each component render" but didn't verify that actions from one component appeared in another's conversation. Integration-level testing (component A triggers action, component B shows result) would have caught this during migration rather than in production. - **session_ready race condition was a design flaw, not a migration artifact.** The pattern of "backend sends history, then appends user message" creates an inherent race. This existed conceptually in the WebSocket version too, it just wasn't triggered because WebSocket message ordering was different. The fix (only apply server history when local state is empty) is correct but brittle. The real fix would be for the backend to not send stale history on a message-bearing request. -- **Plan file got reused for a different purpose.** `concurrent-imagining-flurry.md` was originally the Hono removal plan, then got overwritten with the PairWriting fix plan. Plan files should be immutable records of what was planned. New plans need new files. +- **Plan file got reused for a different purpose.** `pairwriting-discussion-fix.md` (originally `concurrent-imagining-flurry.md`) was originally the Hono removal plan, then got overwritten with the PairWriting fix plan. Plan files should be immutable records of what was planned. New plans need new files. ## Lessons Learned @@ -37,5 +37,5 @@ Migrated Memory Loop from Vite SPA + Hono backend to Next.js 15 App Router. Repl ## Artifacts - `.lore/brainstorm/next-js-migration.md` - Original architecture analysis -- `.lore/plans/vectorized-hopping-pinwheel.md` - Migration execution plan +- `.lore/plans/nextjs-consolidation.md` - Migration execution plan - PR #458 - The complete migration PR diff --git a/.lore/retros/single-websocket-consolidation.md b/.lore/retros/single-websocket-consolidation.md index 7dddf4a7..d7965078 100644 --- a/.lore/retros/single-websocket-consolidation.md +++ b/.lore/retros/single-websocket-consolidation.md @@ -4,7 +4,7 @@ date: 2026-02-04 status: complete tags: [websocket, rest-api, testing, refactor, architecture] modules: [websocket-handler, health-panel, vault-select, app] -related: [.lore/design/single-websocket-consolidation.md] +related: [.lore/_archive/single-websocket-consolidation.md] --- # Retro: Single WebSocket Consolidation @@ -33,6 +33,6 @@ Migrated non-streaming operations from WebSocket to REST API, leaving only Discu ## Artifacts -- Design: `.lore/design/single-websocket-consolidation.md` +- Design: `.lore/_archive/single-websocket-consolidation.md` - PR: #452 - Commits: `befb0c0` (implementation), `dc8ba6d` (tests) diff --git a/.lore/retros/vi-mode-pair-writing.md b/.lore/retros/vi-mode-pair-writing.md index 081e0358..239f4059 100644 --- a/.lore/retros/vi-mode-pair-writing.md +++ b/.lore/retros/vi-mode-pair-writing.md @@ -51,7 +51,7 @@ Added vi-style modal editing to Pair Writing mode. Implementation includes Norma - Spec: `.lore/specs/vi-mode-pair-writing.md` - Plan: `.lore/plans/vi-mode-pair-writing.md` -- Work breakdown: `.lore/work/vi-mode-pair-writing.md` -- Research: `.lore/research/vi-mode-implementation.md` +- Work breakdown: `.lore/_archive/vi-mode-pair-writing-work.md` +- Research: `.lore/_archive/vi-mode-implementation.md` - Issue: #394 - PR: #433 diff --git a/.lore/specs/daily-prep.md b/.lore/specs/daily-prep.md index 850bc9b5..1724fead 100644 --- a/.lore/specs/daily-prep.md +++ b/.lore/specs/daily-prep.md @@ -2,9 +2,9 @@ title: Daily Prep System date: 2026-02-02 status: implemented -tags: [daily-planning, bookend, energy, commitment, ground-tab, skill] +tags: [daily-planning, bookend, energy, commitment, ground-tab, skill-development] modules: [home-view, vault-info-card, session-actions-card, daily-prep-skill, daily-debrief-skill, routes-daily-prep] -related: [.lore/brainstorm/daily-prep-system.md, .lore/research/daily-planning-science.md] +related: [.lore/brainstorm/daily-prep-system.md, .lore/_archive/daily-planning-science.md] --- # Spec: Daily Prep System diff --git a/.lore/specs/vi-mode-pair-writing.md b/.lore/specs/vi-mode-pair-writing.md index c26b0586..924eca2d 100644 --- a/.lore/specs/vi-mode-pair-writing.md +++ b/.lore/specs/vi-mode-pair-writing.md @@ -4,7 +4,7 @@ date: 2026-01-29 status: implemented tags: [vi-mode, pair-writing, modal-editing, keyboard, requirements] modules: [pair-writing-editor, use-vi-mode, vault-config] -related: [.lore/research/vi-mode-implementation.md] +related: [.lore/_archive/vi-mode-implementation.md] --- # Spec: Vi Mode for Pair Writing @@ -70,5 +70,5 @@ Add vi-style modal editing to Pair Writing mode. When enabled via vault configur ## Context -- Research: `.lore/research/vi-mode-implementation.md` +- Research: `.lore/_archive/vi-mode-implementation.md` - Issue: #394 diff --git a/README.md b/README.md index e9015702..81471779 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ cp .env.example .env bun run dev ``` -Open in your browser. +Open in your browser. ## Configuration @@ -62,8 +62,8 @@ Open in your browser. ```bash VAULTS_DIR=/path/to/vaults # Optional: defaults to ./vaults at project root -PORT=3000 # Backend port (default: 3000) -HOST=0.0.0.0 # Bind address (default: 0.0.0.0) +PORT=3000 # Server port (default: 3000) +HOSTNAME=0.0.0.0 # Bind address (default: 0.0.0.0) MOCK_SDK=true # Test without API calls ``` @@ -98,22 +98,20 @@ All paths are relative to the vault root. Path traversal outside the vault is re ## Commands ```bash -bun run dev # Start dev servers (backend + frontend) -bun run build # Build for production -bun run test # Run tests -bun run typecheck # TypeScript checking -bun run lint # ESLint +bun run --cwd nextjs dev # Start Next.js dev server (:3000) +bun run --cwd nextjs build # Build for production +bun run test # Run all tests (sequential) +bun run typecheck # TypeScript checking +bun run lint # ESLint ``` ### Production ```bash -bun run build +bun run --cwd nextjs build ./scripts/launch.sh ``` -The backend runs from TypeScript source (not bundled) because Claude Agent SDK requires it. - ## Network Access Access from other devices on your network: @@ -123,7 +121,7 @@ Access from other devices on your network: hostname -I | awk '{print $1}' # Access from phone/tablet -http://YOUR_IP:5173 +http://YOUR_IP:3000 ``` ## Documentation @@ -140,12 +138,12 @@ http://YOUR_IP:5173 ``` memory-loop/ -├── backend/ # Hono server + Claude Agent SDK -├── frontend/ # React 19 + Vite -└── shared/ # Zod schemas for type-safe messages +├── nextjs/ # Next.js 15 App Router (UI + API routes + SSE streaming) +├── backend/ # Library: Claude Agent SDK, vault operations, schedulers +└── shared/ # Zod schemas and TypeScript types ``` -Two communication channels: REST API for stateless operations (file CRUD, search, config) and WebSocket for streaming (AI responses, tool execution, session state). Both use Zod-validated message schemas. +REST API (Next.js API routes) for stateless operations (file CRUD, search, config) and SSE for AI chat streaming. Backend is a library consumed by the API routes, not a standalone server. ## License diff --git a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/collection-stats.yaml b/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/collection-stats.yaml deleted file mode 100644 index 9bdd02a2..00000000 --- a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/collection-stats.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Collection Statistics Widget -# A ground widget that aggregates data across all notes - -name: Note Statistics -type: aggregate -location: ground -source: - pattern: "notes/**/*.md" -fields: - total_notes: - count: true - total_rating_sum: - sum: rating - average_rating: - avg: rating - min_rating: - min: rating - max_rating: - max: rating - rating_stddev: - stddev: rating -display: - type: summary-card - title: Collection Overview diff --git a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/note-similarity.yaml b/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/note-similarity.yaml deleted file mode 100644 index 8984d3fd..00000000 --- a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/note-similarity.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Note Similarity Widget -# A recall widget that shows similar notes when viewing a specific note - -name: Similar Notes -type: similarity -location: recall -source: - pattern: "notes/**/*.md" -dimensions: - - field: tags - weight: 0.6 - method: jaccard - - field: rating - weight: 0.3 - method: proximity - - field: category - weight: 0.1 - method: jaccard -display: - type: list - limit: 5 - title: Related Notes diff --git a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/rating-meter.yaml b/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/rating-meter.yaml deleted file mode 100644 index 710a9a72..00000000 --- a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/rating-meter.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Rating Meter Widget -# A recall widget showing a single note's rating as a meter - -name: Rating Score -type: aggregate -location: recall -source: - pattern: "notes/**/*.md" -fields: - current_rating: - expr: "this.rating" - normalized_rating: - expr: "safeDivide(this.rating, 10) * 100" -display: - type: meter - min: 0 - max: 100 - title: Rating -editable: - - field: rating - type: slider - label: Rating - min: 1 - max: 10 - step: 1 diff --git a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/status-table.yaml b/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/status-table.yaml deleted file mode 100644 index 8bf02f75..00000000 --- a/backend/__fixtures__/test-vault-widgets/.memory-loop/widgets/status-table.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# Status Table Widget -# A ground widget showing notes organized by status - -name: Notes by Status -type: aggregate -location: ground -source: - pattern: "notes/**/*.md" -fields: - note_count: - count: true - avg_rating: - avg: rating -display: - type: table - columns: - - Title - - Status - - Rating - title: All Notes diff --git a/backend/__fixtures__/test-vault-widgets/CLAUDE.md b/backend/__fixtures__/test-vault-widgets/CLAUDE.md deleted file mode 100644 index aa4e6d9e..00000000 --- a/backend/__fixtures__/test-vault-widgets/CLAUDE.md +++ /dev/null @@ -1,14 +0,0 @@ -# Test Vault for Widget System - -This vault contains sample data for testing the widget system. - -## Goals - -- Demonstrate widget aggregation -- Test similarity computation -- Validate various display types - -## Structure - -- `notes/` - Sample markdown files with frontmatter -- `.memory-loop/widgets/` - Widget configuration files diff --git a/backend/__fixtures__/test-vault-widgets/notes/archived-ideas.md b/backend/__fixtures__/test-vault-widgets/notes/archived-ideas.md deleted file mode 100644 index 2de1d7eb..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/archived-ideas.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Archived Ideas -date: 2024-06-01 -tags: - - ideas - - archived -rating: 4 -status: archived -category: notes ---- - -# Archived Ideas - -## Old Project Concepts - -These ideas were considered but not pursued. - -- Mobile app for plant care -- Automated email sorter -- Recipe recommendation engine - -## Lessons Learned - -Sometimes saying no is the right choice. diff --git a/backend/__fixtures__/test-vault-widgets/notes/book-review-atomic.md b/backend/__fixtures__/test-vault-widgets/notes/book-review-atomic.md deleted file mode 100644 index 600a9b21..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/book-review-atomic.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Book Review - Atomic Habits -date: 2025-02-05 -tags: - - book - - review - - personal - - habits -rating: 10 -status: published -category: personal ---- - -# Atomic Habits Review - -## Key Takeaways - -1. Small habits compound over time -2. Identity-based habits are more effective -3. Environment design matters - -## Favorite Quotes - -> "You do not rise to the level of your goals. You fall to the level of your systems." - -## Rating: 10/10 - -Highly recommended for anyone looking to improve their habits. diff --git a/backend/__fixtures__/test-vault-widgets/notes/meeting-notes-jan.md b/backend/__fixtures__/test-vault-widgets/notes/meeting-notes-jan.md deleted file mode 100644 index ac6a1a68..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/meeting-notes-jan.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: January Meeting Notes -date: 2025-01-10 -tags: - - meeting - - notes - - team -rating: 6 -status: published -category: work ---- - -# January Team Meeting - -## Attendees - -- Alice -- Bob -- Charlie - -## Discussion Points - -- Q1 planning -- Resource allocation -- Timeline review diff --git a/backend/__fixtures__/test-vault-widgets/notes/no-frontmatter.md b/backend/__fixtures__/test-vault-widgets/notes/no-frontmatter.md deleted file mode 100644 index 2b8ce54d..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/no-frontmatter.md +++ /dev/null @@ -1,4 +0,0 @@ -# Note Without Frontmatter - -This file intentionally has no YAML frontmatter. -It tests how the widget system handles missing fields. diff --git a/backend/__fixtures__/test-vault-widgets/notes/partial-frontmatter.md b/backend/__fixtures__/test-vault-widgets/notes/partial-frontmatter.md deleted file mode 100644 index 3cf81047..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/partial-frontmatter.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Partial Frontmatter Note -date: 2025-04-01 ---- - -# Partial Frontmatter - -This note only has some frontmatter fields. -Missing: tags, rating, status, category. diff --git a/backend/__fixtures__/test-vault-widgets/notes/personal-goals.md b/backend/__fixtures__/test-vault-widgets/notes/personal-goals.md deleted file mode 100644 index 1ad3cedc..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/personal-goals.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Personal Goals 2025 -date: 2025-01-01 -tags: - - personal - - goals - - planning -rating: 7 -status: published -category: personal ---- - -# Personal Goals for 2025 - -## Health - -- Exercise 3x per week -- Better sleep schedule - -## Learning - -- Read 20 books -- Learn a new programming language - -## Relationships - -- Monthly family dinners -- Weekly friend meetups diff --git a/backend/__fixtures__/test-vault-widgets/notes/project-alpha.md b/backend/__fixtures__/test-vault-widgets/notes/project-alpha.md deleted file mode 100644 index e4209519..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/project-alpha.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Project Alpha -date: 2025-03-15 -tags: - - project - - development - - priority -rating: 8 -status: published -category: work ---- - -# Project Alpha - -This is the main project file for Alpha initiative. - -## Goals - -- Complete phase 1 -- Review architecture -- Deploy to staging diff --git a/backend/__fixtures__/test-vault-widgets/notes/recipe-pasta.md b/backend/__fixtures__/test-vault-widgets/notes/recipe-pasta.md deleted file mode 100644 index cd07e28a..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/recipe-pasta.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Homemade Pasta Recipe -date: 2024-12-15 -tags: - - recipe - - cooking - - personal -rating: 8 -status: published -category: personal ---- - -# Homemade Pasta - -## Ingredients - -- 2 cups flour -- 3 eggs -- 1 tsp salt -- 1 tbsp olive oil - -## Instructions - -1. Make a well in the flour -2. Add eggs and mix -3. Knead for 10 minutes -4. Rest for 30 minutes -5. Roll and cut - -## Notes - -Best served with fresh tomato sauce. diff --git a/backend/__fixtures__/test-vault-widgets/notes/research-ai.md b/backend/__fixtures__/test-vault-widgets/notes/research-ai.md deleted file mode 100644 index 27578dd8..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/research-ai.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: AI Research Notes -date: 2025-02-20 -tags: - - research - - ai - - technology -rating: 9 -status: draft -category: research ---- - -# AI Research - -## Key Findings - -- LLMs show promising results -- Fine-tuning improves accuracy -- RAG provides better context - -## References - -- Paper A -- Paper B diff --git a/backend/__fixtures__/test-vault-widgets/notes/tech-stack-notes.md b/backend/__fixtures__/test-vault-widgets/notes/tech-stack-notes.md deleted file mode 100644 index ff84f33b..00000000 --- a/backend/__fixtures__/test-vault-widgets/notes/tech-stack-notes.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Tech Stack Notes -date: 2025-03-01 -tags: - - technology - - development - - notes -rating: 7 -status: draft -category: work ---- - -# Technology Stack - -## Frontend - -- React 19 -- TypeScript -- Vite - -## Backend - -- Bun runtime -- Hono framework -- SQLite - -## Infrastructure - -- Docker -- GitHub Actions