docs: create roadmap (5 phases)

This commit is contained in:
local
2026-03-27 01:21:35 +00:00
parent 81bcc49bae
commit 7962df1094
4 changed files with 317 additions and 17 deletions

View File

@@ -77,26 +77,26 @@ Which phases cover which requirements. Updated during roadmap creation.
| Requirement | Phase | Status |
|-------------|-------|--------|
| CHAT-01 | | Pending |
| CHAT-02 | | Pending |
| CONV-01 | | Pending |
| CONV-02 | | Pending |
| CONV-03 | | Pending |
| CONV-04 | | Pending |
| DISP-01 | | Pending |
| DISP-02 | | Pending |
| DISP-03 | | Pending |
| UI-01 | | Pending |
| UI-02 | | Pending |
| UI-03 | | Pending |
| CODE-01 | | Pending |
| CODE-02 | | Pending |
| CHAT-01 | Phase 3 | Pending |
| CHAT-02 | Phase 3 | Pending |
| CONV-01 | Phase 2 | Pending |
| CONV-02 | Phase 2 | Pending |
| CONV-03 | Phase 2 | Pending |
| CONV-04 | Phase 2 | Pending |
| DISP-01 | Phase 4 | Pending |
| DISP-02 | Phase 4 | Pending |
| DISP-03 | Phase 4 | Pending |
| UI-01 | Phase 5 | Pending |
| UI-02 | Phase 5 | Pending |
| UI-03 | Phase 5 | Pending |
| CODE-01 | Phase 1 | Pending |
| CODE-02 | Phase 1 | Pending |
**Coverage:**
- v1 requirements: 14 total
- Mapped to phases: 0
- Unmapped: 14 ⚠️
- Mapped to phases: 14
- Unmapped: 0 ✓
---
*Requirements defined: 2026-03-27*
*Last updated: 2026-03-27 after initial definition*
*Last updated: 2026-03-27 after roadmap creation — all 14 requirements mapped*

91
.planning/ROADMAP.md Normal file
View File

@@ -0,0 +1,91 @@
# Roadmap: Chat Agent WebApp
## Overview
Five phases take this project from an empty solution to a complete personal AI chat application. Each phase introduces one Blazor concept and delivers something verifiable. The dependency chain is strict: the WASM/API architecture must exist before storage, storage before conversations, conversations before AI, AI before display polish, and display before UI completeness. Streaming is deferred to v2. The result is a working, well-understood chat interface where every line of code is intentional and explained.
## Phases
**Phase Numbering:**
- Integer phases (1, 2, 3): Planned milestone work
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
Decimal phases appear between their surrounding integers in numeric order.
- [ ] **Phase 1: Architecture Foundation** - Two-project solution scaffold with WASM/API split and shared models; establishes the tutorial commenting convention
- [ ] **Phase 2: Conversation Storage** - JSON file persistence and full conversation CRUD via repository pattern and Minimal API endpoints
- [ ] **Phase 3: Basic AI Chat** - End-to-end chat loop (send message → OpenAI → display response) without streaming
- [ ] **Phase 4: Message Display** - Markdown rendering, syntax-highlighted code blocks, and copy-to-clipboard
- [ ] **Phase 5: UI Polish** - Sidebar layout, chat input area, and responsive design across screen sizes
## Phase Details
### Phase 1: Architecture Foundation
**Goal**: The solution structure is locked in and the critical boundaries (no API key in WASM, no file I/O in WASM, no direct OpenAI calls from WASM) are architecturally enforced before any feature code is written
**Depends on**: Nothing (first phase)
**Requirements**: CODE-01, CODE-02
**Success Criteria** (what must be TRUE):
1. Running `dotnet run` on both projects starts WASM client and API server without errors
2. A test HTTP request from the WASM client reaches the API server and returns a response (CORS working)
3. The shared models library is referenced by both projects with no duplication of DTOs
4. Running `dotnet publish` on the WASM project completes with no IL trim warnings
5. Every file introduced contains inline comments explaining the Blazor concept it demonstrates
**Plans**: TBD
**UI hint**: yes
### Phase 2: Conversation Storage
**Goal**: Users can create, switch between, and delete conversations that persist to disk and survive app restarts — with no AI integration yet
**Depends on**: Phase 1
**Requirements**: CONV-01, CONV-02, CONV-03, CONV-04
**Success Criteria** (what must be TRUE):
1. User can create a new conversation and see it appear in the conversation list
2. User can click a conversation in the list and switch to it (conversation content loads)
3. User can delete a conversation and see it removed from the list
4. After closing and reopening the browser, all conversations and their messages are still present
**Plans**: TBD
### Phase 3: Basic AI Chat
**Goal**: Users can send a message and receive an AI response in the active conversation, with the full request/response cycle working end-to-end
**Depends on**: Phase 2
**Requirements**: CHAT-01, CHAT-02
**Success Criteria** (what must be TRUE):
1. User can type a message, press send, and see their message appear in the chat area
2. User receives an AI response from OpenAI GPT displayed in the chat area
3. The conversation history is preserved across the full exchange and saved to disk
4. The OpenAI API key is never present in any WASM project file or browser network request
**Plans**: TBD
### Phase 4: Message Display
**Goal**: AI responses render as readable, formatted content — not raw markdown strings — with syntax-highlighted code and one-click copy
**Depends on**: Phase 3
**Requirements**: DISP-01, DISP-02, DISP-03
**Success Criteria** (what must be TRUE):
1. An AI response containing markdown (headings, lists, bold, links) renders as formatted HTML in the chat area
2. Code blocks in AI responses display with syntax highlighting appropriate to the language
3. User can click a copy button on any message and the text is copied to the clipboard
**Plans**: TBD
**UI hint**: yes
### Phase 5: UI Polish
**Goal**: The app has a complete, usable layout — sidebar with conversation list, chat input area, and a responsive design that works across screen sizes
**Depends on**: Phase 4
**Requirements**: UI-01, UI-02, UI-03
**Success Criteria** (what must be TRUE):
1. App displays a sidebar on the left with the conversation list and a main chat area on the right
2. The chat area has a text input field and a send button visible at the bottom of the screen
3. The layout reflows gracefully on a narrow viewport (mobile-width browser window) without horizontal scrolling or clipped content
**Plans**: TBD
**UI hint**: yes
## Progress
**Execution Order:**
Phases execute in numeric order: 1 → 2 → 3 → 4 → 5
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Architecture Foundation | 0/TBD | Not started | - |
| 2. Conversation Storage | 0/TBD | Not started | - |
| 3. Basic AI Chat | 0/TBD | Not started | - |
| 4. Message Display | 0/TBD | Not started | - |
| 5. UI Polish | 0/TBD | Not started | - |

62
.planning/STATE.md Normal file
View File

@@ -0,0 +1,62 @@
# Project State
## Project Reference
See: .planning/PROJECT.md (updated 2026-03-27)
**Core value:** A working, well-understood AI chat interface — every line of code is intentional and explained
**Current focus:** Phase 1 — Architecture Foundation
## Current Position
Phase: 1 of 5 (Architecture Foundation)
Plan: 0 of TBD in current phase
Status: Ready to plan
Last activity: 2026-03-27 — Roadmap created; all 14 v1 requirements mapped to 5 phases
Progress: [░░░░░░░░░░] 0%
## Performance Metrics
**Velocity:**
- Total plans completed: 0
- Average duration: —
- Total execution time: 0 hours
**By Phase:**
| Phase | Plans | Total | Avg/Plan |
|-------|-------|-------|----------|
| - | - | - | - |
**Recent Trend:**
- Last 5 plans: —
- Trend: —
*Updated after each plan completion*
## Accumulated Context
### Decisions
Decisions are logged in PROJECT.md Key Decisions table.
Recent decisions affecting current work:
- [Init]: Streaming (STRM-01/02/03) deferred to v2 — user chose non-streaming for v1
- [Init]: Tutorial convention established in Phase 1 — CODE-01/02 anchor there, applied cross-phase
- [Init]: Phase order follows strict dependency chain: scaffold → storage → AI → display → UI polish
### Pending Todos
None yet.
### Blockers/Concerns
- [Research flag] Phase 4: Verify `Markdown.ColorCode` WASM compatibility before implementing (community-reported, not officially confirmed)
- [Research flag] Phase 4: Confirm Markdig `DisableHtml()` decision — accepted XSS risk for single-user tool; document explicitly in code
## Session Continuity
Last session: 2026-03-27
Stopped at: Roadmap created, STATE.md initialized — ready to plan Phase 1
Resume file: None

147
CLAUDE.md Normal file
View File

@@ -0,0 +1,147 @@
<!-- GSD:project-start source:PROJECT.md -->
## Project
**Chat Agent WebApp**
A personal AI chat web application built with Blazor WebAssembly and the OpenAI GPT API. Users send messages, receive streaming AI responses rendered as markdown, and manage multiple persistent conversations. The project doubles as an incremental learning journey — each phase introduces one concept with well-documented, explained code, making it suitable as a Blazor tutorial for a developer experienced in C# but new to the framework.
**Core Value:** A working, well-understood AI chat interface — every line of code is intentional and explained, so the builder learns Blazor patterns while shipping a real product.
### Constraints
- **Tech stack**: .NET / C# / Blazor WebAssembly — non-negotiable
- **LLM provider**: OpenAI GPT API
- **Storage**: JSON files on local disk
- **Architecture**: WASM client + backend API (API key stays server-side)
- **Code style**: Every Blazor concept introduced must have inline comments explaining what it does and why
<!-- GSD:project-end -->
<!-- GSD:stack-start source:research/STACK.md -->
## Technology Stack
## Recommended Stack
### Core Technologies
| Technology | Version | Purpose | Why Recommended |
|------------|---------|---------|-----------------|
| .NET 9 SDK | 9.x (latest patch) | Runtime, tooling, SDK | LTS-adjacent, stable, .NET 10 is in preview — stay on 9 for a tutorial project targeting a stable foundation |
| Blazor WebAssembly Standalone | .NET 9 | Client SPA running in-browser | Non-negotiable per project constraints; client-side execution with no server round-trip for UI |
| ASP.NET Core Web API | .NET 9 | Backend proxy for OpenAI calls | Required to keep the OpenAI API key server-side; WASM cannot access secrets directly |
| C# 13 | Included with .NET 9 | Application language | Included in .NET 9 SDK; no separate install needed |
### OpenAI Integration
| Library | Version | Purpose | Why Recommended |
|---------|---------|---------|-----------------|
| `OpenAI` (official) | 2.9.1 | OpenAI API client with streaming | The official OpenAI-published .NET library; supports `CompleteChatStreamingAsync()` returning `AsyncCollectionResult<StreamingChatCompletionUpdate>` via `await foreach`; stable release as of 2026-03-02 |
### Markdown Rendering
| Library | Version | Purpose | Why Recommended |
|---------|---------|---------|-----------------|
| `Markdig` | 1.1.1 | Parse markdown text to HTML | The de facto standard markdown processor for .NET; CommonMark-compliant, fast, extensible, targets .NET Standard 2.0 so works in WASM; used by Microsoft and Syncfusion as the underlying engine |
### UI Component Library
| Library | Version | Purpose | Why Recommended |
|---------|---------|---------|-----------------|
| `MudBlazor` | 9.2.0 | Material Design component library | Full .NET 9 support confirmed; pure C# with minimal JavaScript; comprehensive chat-friendly components (MudTextField, MudPaper, MudScrollToBottom, MudList); large community; no per-seat licensing |
### JSON Storage (Server-side)
| Technology | Version | Purpose | Why Recommended |
|------------|---------|---------|-----------------|
| `System.Text.Json` | Built into .NET 9 | Serialize/deserialize conversation history | Built-in, no extra dependency; `JsonSerializerOptions` with `WriteIndented = true` for human-readable files; async file I/O via `File.ReadAllTextAsync` / `File.WriteAllTextAsync` |
## Supporting Libraries
| Library | Version | Purpose | When to Use |
|---------|---------|---------|-------------|
| `Microsoft.Extensions.AI` (abstractions) | 9.x preview | Optional AI abstraction layer | Skip for v1 — adds indirection before the core chat pattern is understood. Relevant for v2 when adding multi-provider support |
| `Blazored.LocalStorage` | latest | Browser local storage | Not needed for this project — persistence is on the server via JSON files, not the browser |
| `System.Net.ServerSentEvents` | Built into .NET 9 | SSE parser for streaming | Used automatically by the `OpenAI` library on the server; no direct usage needed |
## Development Tools
| Tool | Purpose | Notes |
|------|---------|-------|
| Visual Studio 2022 (v17.12+) | IDE with Blazor hot reload | Recommended for tutorial builder; full Blazor debugging, component preview, and hot reload support |
| VS Code + C# Dev Kit | Lighter-weight alternative | Works well; use `dotnet watch` for hot reload |
| `dotnet watch run` | Hot reload during development | Run in both Client and Server project directories simultaneously |
| `dotnet-dev-certs` | HTTPS dev certificate | Required for local HTTPS; run `dotnet dev-certs https --trust` once |
## Installation
# Create solution
# Create Blazor WASM client (standalone)
# Create ASP.NET Core Web API backend
# Install OpenAI SDK in the API project
# Install Markdig in the Client project
## Alternatives Considered
| Recommended | Alternative | When to Use Alternative |
|-------------|-------------|-------------------------|
| `OpenAI` 2.9.1 (official) | `OpenAI-DotNet` 8.8.8 (unofficial) | Never — the official package is now stable and maintained by OpenAI directly |
| `OpenAI` 2.9.1 (official) | `Azure.AI.OpenAI` 2.1.0 | When targeting Azure OpenAI Service specifically (e.g., enterprise, EU data residency, private endpoints) — overkill for this project |
| `Markdig` | `CommonMark.NET` | Only if strict CommonMark compliance matters more than extensions; Markdig is a superset and the ecosystem standard |
| `MudBlazor` | Radzen Blazor | Radzen is fine; choose it if you already know it; MudBlazor has more learning resources |
| `MudBlazor` | Telerik UI for Blazor | Telerik requires a paid license; not appropriate for a personal tool |
| Standalone WASM + separate Web API | Blazor Web App template (unified) | Use the unified Blazor Web App template when you want mixed Server+WASM render modes on a single project; overkill for this project and obscures the WASM-specific patterns the tutorial aims to teach |
| JSON flat files (server-side) | SQLite via EF Core | SQLite is a better choice at scale; JSON is simpler for single-user personal tools and avoids introducing a migration workflow |
## What NOT to Use
| Avoid | Why | Use Instead |
|-------|-----|-------------|
| `OpenAI-DotNet` (unofficial) | Different API surface, not maintained by OpenAI, version numbers create confusion | Official `OpenAI` NuGet package |
| `Microsoft.SemanticKernel` | Adds significant abstraction and dependency weight for a tutorial; streaming works but is complex to explain | Direct `OpenAI` SDK calls; add SK in v2 when orchestration is needed |
| JavaScript `EventSource` API via JSInterop for streaming | Blazor WASM has `SetBrowserResponseStreamingEnabled` which avoids JS interop; adding JSInterop for streaming increases complexity significantly | `HttpCompletionOption.ResponseHeadersRead` + `SetBrowserResponseStreamingEnabled(true)` in the HTTP handler |
| `Newtonsoft.Json` | Unnecessary dependency; `System.Text.Json` is built into .NET 9 and is faster; Newtonsoft was the pre-.NET Core standard | `System.Text.Json` (built-in) |
| `Blazored.LocalStorage` for persistence | Browser storage is limited (~5MB), cleared by users, and not suitable for chat history of any meaningful length; also exposes all data client-side | Server-side JSON file storage via the Web API |
| AOT compilation during learning phase | Dramatically increases build times; not needed until production optimization is a concern; confusing to introduce in a tutorial | Default IL interpretation; add AOT opt-in note in the final phase |
## Stack Patterns by Variant
- Backend streams OpenAI tokens as `text/event-stream` (SSE) or `application/x-ndjson`
- Client uses `SetBrowserResponseStreamingEnabled(true)` on `HttpRequestMessage`
- Client reads with `HttpCompletionOption.ResponseHeadersRead` and iterates the stream
- Trigger `StateHasChanged()` in the component after each token to update the UI
- Define a `ConversationRepository` service on the API that reads/writes from a configurable base path
- Register as `Singleton` (not `Scoped`) since there is only one user and file access must be serialized
- Use `SemaphoreSlim(1,1)` to prevent concurrent write conflicts even in single-user mode
- Use `Markdig.Markdown.ToHtml(text, pipeline)` where `pipeline` is built with `MarkdownPipelineBuilder` enabling extensions (e.g., `UseAutoLinks()`, `UseEmojiAndSmiley()`)
- Render the HTML string using `@((MarkupString)html)` inside a `<div class="markdown-body">` element
- Apply CSS (GitHub Markdown CSS or custom) scoped to `.markdown-body` for code blocks and tables
## Version Compatibility
| Package | Compatible With | Notes |
|---------|-----------------|-------|
| `OpenAI` 2.9.1 | .NET Standard 2.0+ (.NET 9 confirmed) | Published 2026-03-02; requires `System.Net.ServerSentEvents` (built into .NET 9) |
| `Markdig` 1.1.1 | .NET 8.0, .NET Standard 2.0, .NET Framework 4.6.2 | .NET 9 compatible via .NET 8 TFM; published 2026-03-04 |
| `MudBlazor` 9.2.0 | .NET 8.0, .NET 9.0, .NET 10.0 | Published 2026-03-18; version 9.x = full support for .NET 9 |
| .NET 9 SDK | Blazor WASM + Web API in same solution | Both project types target `net9.0`; no cross-framework issues |
## Sources
- https://www.nuget.org/packages/OpenAI — Official OpenAI NuGet package; version 2.9.1 confirmed (2026-03-02)
- https://github.com/openai/openai-dotnet — Official OpenAI .NET SDK; streaming API verified (`CompleteChatStreamingAsync`, `await foreach`)
- https://www.nuget.org/packages/Markdig — Markdig version 1.1.1 confirmed (2026-03-04)
- https://www.nuget.org/packages/MudBlazor — MudBlazor 9.2.0 confirmed; .NET 8/9/10 full support (2026-03-18)
- https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-9.0 — Official Blazor hosting model docs; standalone WASM vs Blazor Web App distinction verified
- https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/default-http-streaming — Breaking change: WASM streaming opt-in (.NET 9) vs default (.NET 10)
- https://www.strathweb.com/2024/07/built-in-support-for-server-sent-events-in-net-9/ — SSE native support in .NET 9 via `System.Net.ServerSentEvents`; used internally by OpenAI SDK (MEDIUM confidence, single source)
- https://github.com/openai/openai-dotnet/issues/65 — Confirmed streaming issue in Blazor WASM requires `SetBrowserResponseStreamingEnabled(true)` (MEDIUM confidence, GitHub issue thread)
- https://devblogs.microsoft.com/dotnet/openai-dotnet-library/ — Official .NET Blog announcement of the OpenAI library
- https://dev.to/kazinix/blazor-web-app-webassembly-hosted-in-net8-and-net9-1k6g — Hosted template removal in .NET 8+, manual solution structure (MEDIUM confidence)
<!-- GSD:stack-end -->
<!-- GSD:conventions-start source:CONVENTIONS.md -->
## Conventions
Conventions not yet established. Will populate as patterns emerge during development.
<!-- GSD:conventions-end -->
<!-- GSD:architecture-start source:ARCHITECTURE.md -->
## Architecture
Architecture not yet mapped. Follow existing patterns found in the codebase.
<!-- GSD:architecture-end -->
<!-- GSD:workflow-start source:GSD defaults -->
## GSD Workflow Enforcement
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
- `/gsd:quick` for small fixes, doc updates, and ad-hoc tasks
- `/gsd:debug` for investigation and bug fixing
- `/gsd:execute-phase` for planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
<!-- GSD:workflow-end -->
<!-- GSD:profile-start -->
## Developer Profile
> Profile not yet configured. Run `/gsd:profile-user` to generate your developer profile.
> This section is managed by `generate-claude-profile` -- do not edit manually.
<!-- GSD:profile-end -->