19 KiB
19 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-architecture-foundation | 02 | execute | 2 |
|
|
false |
|
|
Purpose: Prove the WASM-to-API communication path works end-to-end with CORS, establishing the pattern all future API calls will follow. This is Phase 1's single concept: "solution structure and project boundaries" (CODE-02). Output: A running app where the WASM client calls the API health endpoint and displays the response.
<execution_context> @/home/ys/family-repo/AgenticCode/.claude/get-shit-done/workflows/execute-plan.md @/home/ys/family-repo/AgenticCode/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-architecture-foundation/01-CONTEXT.md @.planning/phases/01-architecture-foundation/01-RESEARCH.md @.planning/phases/01-architecture-foundation/01-01-SUMMARY.mdProjects created by Plan 01:
- src/ChatAgent.Client/ (Blazor WASM, port 5200)
- src/ChatAgent.Api/ (ASP.NET Core Web API, port 7100)
- src/ChatAgent.Shared/ (class library, referenced by both)
Client config (src/ChatAgent.Client/wwwroot/appsettings.json):
{
"ApiBaseUrl": "https://localhost:7100"
}
All projects target net9.0. Solution file at repo root: ChatAgent.sln
Task 1: Implement shared DTO, API health endpoint with CORS, and client services src/ChatAgent.Shared/Models/HealthResponse.cs, src/ChatAgent.Api/Program.cs, src/ChatAgent.Api/Controllers/HealthController.cs, src/ChatAgent.Client/Program.cs, src/ChatAgent.Client/Services/ChatApiClient.cs, src/ChatAgent.Client/Pages/Home.razor, src/ChatAgent.Client/Layout/MainLayout.razor, src/ChatAgent.Client/_Imports.razor, src/ChatAgent.Client/wwwroot/css/app.css src/ChatAgent.Shared/ChatAgent.Shared.csproj, src/ChatAgent.Api/Program.cs, src/ChatAgent.Api/ChatAgent.Api.csproj, src/ChatAgent.Client/Program.cs, src/ChatAgent.Client/ChatAgent.Client.csproj, src/ChatAgent.Client/_Imports.razor, src/ChatAgent.Client/Layout/MainLayout.razor, src/ChatAgent.Client/Pages/Home.razor, src/ChatAgent.Client/wwwroot/css/app.css, .planning/phases/01-architecture-foundation/01-RESEARCH.md, .planning/phases/01-architecture-foundation/01-CONTEXT.md Create/modify the following files. Per D-07/D-08/D-09 (CODE-01), EVERY file must have tutorial-style inline comments explaining WHAT each Blazor/ASP.NET Core concept is and WHY it is used. Comments go inline as XML doc comments and `//` comments right next to the code.**A. Shared DTO** -- Create `src/ChatAgent.Shared/Models/HealthResponse.cs`:
Create the `Models/` directory under `src/ChatAgent.Shared/`. Write the HealthResponse class in namespace `ChatAgent.Shared.Models` with two properties:
- `public string Status { get; set; } = string.Empty;` -- server health status (e.g., "healthy")
- `public DateTime Timestamp { get; set; }` -- server timestamp proving live response
Include XML doc comments on the class explaining it is a shared DTO (Data Transfer Object) that lives in the Shared project so both Client and Api use the same type without duplication. When the API returns this object, the Client deserializes it into the same class.
**B. API Program.cs** -- Rewrite `src/ChatAgent.Api/Program.cs`:
The file must contain, in order:
1. Top comment block explaining this is the ASP.NET Core Web API entry point, that it will eventually proxy OpenAI calls and manage JSON storage, but in Phase 1 only serves a health check
2. `builder.Services.AddControllers();` with comment: "We use Controllers (not Minimal API) for explicit structure (D-05)"
3. CORS configuration using `builder.Services.AddCors()` with a named policy `"AllowBlazorClient"` that allows origin `"https://localhost:5200"`, `AllowAnyHeader()`, `AllowAnyMethod()`. Include comments explaining: CORS is required because the WASM client runs on a different origin (different port), browsers block cross-origin requests by default for security
4. `var app = builder.Build();`
5. Middleware in correct order with comment "Middleware order matters in ASP.NET Core -- CORS must be applied before routing and authorization":
- `app.UseCors("AllowBlazorClient");`
- `app.UseAuthorization();`
- `app.MapControllers();` with comment explaining it discovers all [ApiController] classes
6. `app.Run();`
Do NOT include Swagger/OpenAPI middleware. Do NOT include `app.UseHttpsRedirection()` (it causes issues with local dev).
**C. Health Controller** -- Create `src/ChatAgent.Api/Controllers/HealthController.cs`:
Create the `Controllers/` directory if it does not exist (template may have one already). Write:
- Namespace: `ChatAgent.Api.Controllers`
- Class: `HealthController : ControllerBase`
- Attributes: `[ApiController]` and `[Route("api/[controller]")]`
- Method: `[HttpGet] public IActionResult Get()` returning `Ok(new HealthResponse { Status = "healthy", Timestamp = DateTime.UtcNow })`
- Using: `ChatAgent.Shared.Models`
- Comments explaining: [ApiController] enables automatic model validation, [Route] maps the class to a URL path, [HttpGet] maps this method to GET requests. This endpoint proves CORS works between WASM and API.
**D. Client Program.cs** -- Rewrite `src/ChatAgent.Client/Program.cs`:
The file must contain:
1. Top comment block explaining this is the Blazor WASM application entry point, that WebAssemblyHostBuilder configures root components, services (DI), and configuration
2. Using statements: `Microsoft.AspNetCore.Components.Web`, `Microsoft.AspNetCore.Components.WebAssembly.Hosting`, `ChatAgent.Client`, `ChatAgent.Client.Services`
3. `var builder = WebAssemblyHostBuilder.CreateDefault(args);`
4. `builder.RootComponents.Add<App>("#app");` with comment explaining it renders the App component inside the `<div id="app">` element in index.html
5. `builder.RootComponents.Add<HeadOutlet>("head::after");` with comment explaining HeadOutlet manages head elements from Razor components
6. Read API base URL from config: `var apiBaseUrl = builder.Configuration["ApiBaseUrl"] ?? "https://localhost:7100";` with comment explaining wwwroot/appsettings.json is PUBLIC, never put secrets there
7. Register typed HttpClient: `builder.Services.AddHttpClient<ChatApiClient>(client => { client.BaseAddress = new Uri(apiBaseUrl); });` with comments explaining AddHttpClient uses IHttpClientFactory internally for proper socket management, per-client configuration, and constructor DI
8. `await builder.Build().RunAsync();`
**E. Typed HttpClient** -- Create `src/ChatAgent.Client/Services/ChatApiClient.cs`:
Create the `Services/` directory under `src/ChatAgent.Client/`. Write:
- Namespace: `ChatAgent.Client.Services`
- Class: `ChatApiClient` with constructor injection of `HttpClient`
- Method: `public async Task<HealthResponse?> GetHealthAsync()` calling `_httpClient.GetFromJsonAsync<HealthResponse>("api/health")`
- Using: `ChatAgent.Shared.Models`, `System.Net.Http.Json`
- Comments explaining: In Blazor WASM, HttpClient is backed by the browser's Fetch API. We wrap it in a typed client so components don't depend on HttpClient directly (D-04). This makes testing easier and centralizes API URL management.
**F. Home Page** -- Rewrite `src/ChatAgent.Client/Pages/Home.razor`:
The file must contain:
1. `@page "/"` directive with comment explaining this maps the component to the root URL
2. `@using ChatAgent.Client.Services`
3. `@using ChatAgent.Shared.Models`
4. `@inject ChatApiClient ApiClient` with comment explaining @inject requests a service from the DI container
5. `<PageTitle>Chat Agent</PageTitle>`
6. An `<h1>Chat Agent</h1>` heading
7. A section that displays health check results:
- If `_healthResponse` is null and `_error` is null, show "Checking API connection..." text with class="loading"
- If `_healthResponse` is not null, show "API Status: {Status}" and "Server Time: {Timestamp}" in a div with class="health-status"
- If `_error` is not null, show the error message in a div with class="error-message"
8. An `@code` block with:
- `private HealthResponse? _healthResponse;`
- `private string? _error;`
- `protected override async Task OnInitializedAsync()` that calls `ApiClient.GetHealthAsync()` in a try/catch, setting `_error` on failure
- Comment explaining `OnInitializedAsync` is a Blazor lifecycle method called once when the component is first rendered, and that `StateHasChanged()` is called automatically after it completes
Use plain HTML/CSS per D-10 (no MudBlazor). Light theme per D-11.
**G. MainLayout** -- Update `src/ChatAgent.Client/Layout/MainLayout.razor`:
Simplify to a clean layout with:
- `@inherits LayoutComponentBase` with comment explaining LayoutComponentBase is the base class for layout components
- A `<main>` element wrapping `@Body` with comment explaining @Body is where the routed page content renders
- Remove any template navigation or sidebar (not needed in Phase 1)
- Basic styling: centered content with padding
**H. _Imports.razor** -- Update `src/ChatAgent.Client/_Imports.razor`:
Ensure these using directives are present (keep existing ones, add missing):
- `@using System.Net.Http`
- `@using System.Net.Http.Json`
- `@using Microsoft.AspNetCore.Components.Forms`
- `@using Microsoft.AspNetCore.Components.Routing`
- `@using Microsoft.AspNetCore.Components.Web`
- `@using Microsoft.AspNetCore.Components.Web.Virtualization`
- `@using Microsoft.AspNetCore.Components.WebAssembly.Http`
- `@using Microsoft.JSInterop`
- `@using ChatAgent.Client`
- `@using ChatAgent.Client.Layout`
- `@using ChatAgent.Client.Services`
- `@using ChatAgent.Shared.Models`
Add a comment at the top explaining _Imports.razor provides global using directives for all .razor files in the project.
**I. App CSS** -- Update `src/ChatAgent.Client/wwwroot/css/app.css`:
Replace with minimal clean CSS for Phase 1 (D-10 plain HTML/CSS, D-11 light theme):
```css
html, body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 0;
background-color: #ffffff;
color: #333333;
}
main {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
h1 {
color: #1a1a1a;
margin-bottom: 1.5rem;
}
.health-status {
padding: 1rem;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: #f9f9f9;
}
.health-status p {
margin: 0.5rem 0;
}
.error-message {
color: #d32f2f;
padding: 1rem;
border: 1px solid #d32f2f;
border-radius: 8px;
background-color: #fce4ec;
}
.loading {
color: #666666;
font-style: italic;
}
```
After all files are created, run:
1. `dotnet build ChatAgent.sln` -- must succeed
2. `dotnet publish src/ChatAgent.Client/ChatAgent.Client.csproj -c Release --nologo 2>&1 | grep -i "warning IL"` -- must produce no output (no IL trimmer warnings)
cd /home/ys/family-repo/AgenticCode && dotnet build ChatAgent.sln --nologo 2>&1 | tail -5 && echo "---PUBLISH---" && dotnet publish src/ChatAgent.Client/ChatAgent.Client.csproj -c Release --nologo 2>&1 | grep -ci "warning IL" || echo "0 IL warnings"
- `src/ChatAgent.Shared/Models/HealthResponse.cs` contains `public class HealthResponse`
- `src/ChatAgent.Shared/Models/HealthResponse.cs` contains `public string Status`
- `src/ChatAgent.Shared/Models/HealthResponse.cs` contains `public DateTime Timestamp`
- `src/ChatAgent.Api/Program.cs` contains `AddCors`
- `src/ChatAgent.Api/Program.cs` contains `AllowBlazorClient`
- `src/ChatAgent.Api/Program.cs` contains `WithOrigins("https://localhost:5200")`
- `src/ChatAgent.Api/Program.cs` contains `UseCors` BEFORE `MapControllers` (line number of UseCors < line number of MapControllers)
- `src/ChatAgent.Api/Program.cs` contains `AddControllers`
- `src/ChatAgent.Api/Program.cs` does NOT contain `swagger` or `Swagger` or `UseHttpsRedirection`
- `src/ChatAgent.Api/Controllers/HealthController.cs` contains `[ApiController]`
- `src/ChatAgent.Api/Controllers/HealthController.cs` contains `[HttpGet]`
- `src/ChatAgent.Api/Controllers/HealthController.cs` contains `HealthResponse`
- `src/ChatAgent.Client/Program.cs` contains `AddHttpClient`
- `src/ChatAgent.Client/Program.cs` contains `ApiBaseUrl`
- `src/ChatAgent.Client/Services/ChatApiClient.cs` contains `GetHealthAsync`
- `src/ChatAgent.Client/Services/ChatApiClient.cs` contains `api/health`
- `src/ChatAgent.Client/Pages/Home.razor` contains `@inject ChatApiClient`
- `src/ChatAgent.Client/Pages/Home.razor` contains `OnInitializedAsync`
- `src/ChatAgent.Client/_Imports.razor` contains `ChatAgent.Shared.Models`
- `dotnet build ChatAgent.sln` exits with code 0
- `dotnet publish` produces 0 IL trimmer warnings
- Every `.cs` file created contains at least 3 comment lines (`//` or `///`)
- `src/ChatAgent.Api/Program.cs` contains at least 5 comment lines
- `src/ChatAgent.Client/Program.cs` contains at least 5 comment lines
All source files created with full tutorial comments. Solution builds. WASM publishes with no IL trim warnings. Health check round-trip code is in place.
Task 2: Verify CORS health check works end-to-end
src/ChatAgent.Client/Pages/Home.razor,
src/ChatAgent.Api/Controllers/HealthController.cs
Start both projects and verify the WASM client successfully calls the API health endpoint across origins.
1. In terminal 1: `cd /home/ys/family-repo/AgenticCode && dotnet run --project src/ChatAgent.Api`
2. In terminal 2: `cd /home/ys/family-repo/AgenticCode && dotnet run --project src/ChatAgent.Client`
3. Open browser to https://localhost:5200
4. Verify the page shows "Chat Agent" heading with "API Status: healthy" and a server timestamp
5. Check browser console (F12) for absence of CORS errors
6. Optionally test API directly: `curl -k https://localhost:7100/api/health`
cd /home/ys/family-repo/AgenticCode && dotnet build ChatAgent.sln --nologo 2>&1 | tail -3
User confirms health check displays correctly in browser with no CORS errors.
Phase 1 success criteria from ROADMAP.md:
1. `dotnet run` on both projects starts without errors -- verified in checkpoint
2. WASM client reaches API server and gets response (CORS working) -- verified in checkpoint
3. Shared models library referenced by both projects -- verified by build success + ProjectReference in .csproj
4. `dotnet publish` on WASM completes with no IL trim warnings -- verified in Task 1 automated check
5. Every file contains inline comments explaining the Blazor concept -- verified by acceptance criteria comment line counts
<success_criteria>
- Health check response visible in browser at https://localhost:5200 showing "healthy" status and timestamp
- No CORS errors in browser console
- All .cs and .razor files have tutorial-style inline comments (CODE-01)
- Phase introduces exactly one concept: solution structure and project boundaries (CODE-02)
- Build and publish both succeed cleanly </success_criteria>