diff --git a/bootstrap-vdp-agentic.sh b/bootstrap-vdp-agentic.sh deleted file mode 100755 index ad55c54..0000000 --- a/bootstrap-vdp-agentic.sh +++ /dev/null @@ -1,1415 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -PROJECT_RAW="${1:-}" - -if [[ -z "$PROJECT_RAW" ]]; then - echo "Usage: $0 [--no-install]" - echo "Example: $0 surveyable" - exit 1 -fi - -NO_INSTALL=false -for arg in "$@"; do - case "$arg" in - --no-install) NO_INSTALL=true ;; - esac -done - -require_cmd() { - if ! command -v "$1" >/dev/null 2>&1; then - echo "Missing required command: $1" - exit 1 - fi -} - -require_cmd dotnet -require_cmd npm - -# Fix old npm config warning: -# npm warn Unknown builtin config "globalignorefile" -if npm config get globalignorefile >/dev/null 2>&1; then - npm config delete globalignorefile >/dev/null 2>&1 || true -fi - -to_pascal_case() { - echo "$1" \ - | tr '[:upper:]' '[:lower:]' \ - | sed -E 's/[^a-z0-9]+/ /g' \ - | awk '{ - out=""; - for (i=1; i<=NF; i++) { - word=$i; - out = out toupper(substr(word,1,1)) substr(word,2); - } - print out; - }' -} - -PROJECT_DIR="$PROJECT_RAW" -PASCAL="$(to_pascal_case "$PROJECT_RAW")" - -if [[ -z "$PASCAL" ]]; then - echo "Project name must contain at least one letter or number." - exit 1 -fi - -API_NAME="${PASCAL}.Api" -TEST_NAME="${PASCAL}.Tests" -SLNX_NAME="${PASCAL}.slnx" - -BACKEND_PORT=5080 -FRONTEND_PORT=5173 -COMPOSE_PORT=8080 - -echo "Project directory: $PROJECT_DIR" -echo ".NET solution: $SLNX_NAME" -echo "API project: $API_NAME" -echo "Test project: $TEST_NAME" -echo "Backend dev URL: http://0.0.0.0:$BACKEND_PORT" -echo "Frontend dev URL: http://0.0.0.0:$FRONTEND_PORT" -echo - -mkdir -p "$PROJECT_DIR" -cd "$PROJECT_DIR" - -mkdir -p backend/src backend/tests docs deploy/caddy shared/openapi scripts - -######################################## -# Backend: .NET 10 API + Tests + .slnx -######################################## -cd backend - -dotnet new sln -n "$PASCAL" - -if [[ ! -f "$SLNX_NAME" ]]; then - echo "Expected $SLNX_NAME, but dotnet did not create it." - echo "Detected SDK:" - dotnet --version - exit 1 -fi - -dotnet new webapi -n "$API_NAME" -o "src/$API_NAME" --framework net10.0 -dotnet new xunit -n "$TEST_NAME" -o "tests/$TEST_NAME" --framework net10.0 - -dotnet sln "$SLNX_NAME" add "src/$API_NAME/$API_NAME.csproj" -dotnet sln "$SLNX_NAME" add "tests/$TEST_NAME/$TEST_NAME.csproj" - -dotnet add "tests/$TEST_NAME/$TEST_NAME.csproj" reference "src/$API_NAME/$API_NAME.csproj" - -API_DIR="src/$API_NAME" -rm -f "$API_DIR/WeatherForecast.cs" || true - -mkdir -p "$API_DIR/Endpoints/Health" -mkdir -p "$API_DIR/Contracts/Health" -mkdir -p "$API_DIR/Domain" -mkdir -p "$API_DIR/Infrastructure" -mkdir -p "$API_DIR/Properties" - -cat > "$API_DIR/Properties/launchSettings.json" < "$API_DIR/Contracts/Health/HealthResponse.cs" < "$API_DIR/Contracts/Health/HelloResponse.cs" < "$API_DIR/Endpoints/Health/HealthEndpoints.cs" < - Results.Ok(new HealthResponse("ok", DateTimeOffset.UtcNow))) - .WithName("GetHealth") - .WithOpenApi(); - - group.MapGet("/hello", () => - Results.Ok(new HelloResponse("Hello from the .NET API"))) - .WithName("GetHello") - .WithOpenApi(); - - return group; - } -} -EOF - -cat > "$API_DIR/Program.cs" <(options => -{ - options.SerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase; -}); - -const string DevCorsPolicy = "DevCors"; - -builder.Services.AddCors(options => -{ - options.AddPolicy(DevCorsPolicy, policy => - { - policy - .AllowAnyHeader() - .AllowAnyMethod() - .AllowCredentials() - .SetIsOriginAllowed(origin => - { - if (string.IsNullOrWhiteSpace(origin)) return false; - - var uri = new Uri(origin); - - return uri.Host is "localhost" or "127.0.0.1" - || uri.Host.StartsWith("192.168.") - || uri.Host.StartsWith("10.") - || uri.Host.StartsWith("172."); - }); - }); -}); - -var app = builder.Build(); - -if (app.Environment.IsDevelopment()) -{ - app.MapOpenApi(); - app.UseCors(DevCorsPolicy); -} - -app.MapHealthEndpoints(); - -app.Run(); -EOF - -cat > "$API_DIR/Dockerfile" < src/app/main.ts <<'EOF' -import { createApp } from 'vue' -import App from '../App.vue' - -createApp(App).mount('#app') -EOF - -sed -i 's|/src/main.ts|/src/app/main.ts|g' index.html - -cat > src/App.vue <<'EOF' - - - -EOF - -cat > src/pages/HomePage.vue <<'EOF' - - - - - -EOF - -cat > src/features/health/types.ts <<'EOF' -export type HealthStatus = { - status: string - serverTimeUtc: string -} -EOF - -cat > src/features/health/api.ts < src/features/health/components/HealthPanel.vue <<'EOF' - - - - - -EOF - -cat > src/api/client.ts <({ - baseUrl: import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:$BACKEND_PORT', -}) -EOF - -cat > src/api/schema.d.ts <<'EOF' -export interface paths { - '/api/health': { - get: { - responses: { - 200: { - content: { - 'application/json': { - status: string - serverTimeUtc: string - } - } - } - } - } - } -} -EOF - -cat > scripts/fetch-openapi.mjs < vite.config.ts < Dockerfile < scripts/dev-backend.sh < scripts/dev-frontend.sh < scripts/update-openapi.sh < docker-compose.yml < deploy/caddy/Caddyfile <<'EOF' -:80 { - root * /srv - encode gzip zstd - - handle /api/* { - reverse_proxy api:8080 - } - - handle { - try_files {path} /index.html - file_server - } -} -EOF - -######################################## -# Docs + Agentic workflow -######################################## -mkdir -p docs/FEATURES docs/TASKS docs/PROMPTS docs/DECISIONS - -cat > README.md <:$FRONTEND_PORT -\`\`\` - -Backend: - -\`\`\`txt -http://localhost:$BACKEND_PORT -http://:$BACKEND_PORT -\`\`\` - -## Update frontend API types from backend - -The backend must be running first. - -\`\`\`bash -./scripts/update-openapi.sh -\`\`\` - -This writes: - -\`\`\`txt -shared/openapi/openapi.json -frontend/src/api/schema.d.ts -\`\`\` - -## Docker Compose - -\`\`\`bash -docker compose up --build -\`\`\` - -Then open: - -\`\`\`txt -http://localhost:$COMPOSE_PORT -http://:$COMPOSE_PORT -\`\`\` - -## Solution - -\`\`\`bash -dotnet build backend/$SLNX_NAME -dotnet test backend/$SLNX_NAME -\`\`\` - -## Agentic workflow - -Start here: - -\`\`\`txt -docs/AGENTIC_WORKFLOW.md -\`\`\` - -Use feature specs, task files, and prompt templates instead of asking agents to work from vague chat history. -EOF - -cat > docs/ARCHITECTURE.md < OpenAPI -> frontend TypeScript types -\`\`\` -EOF - -cat > docs/DEVELOPMENT_WORKFLOW.md < docs/AGENTIC_WORKFLOW.md <<'EOF' -# Agentic Workflow - -This repository is designed to be worked on by humans and coding agents. - -The goal is to avoid the common failure mode where the first AI prompt creates a lot of code and every later prompt degrades because the agent loses architectural context. - -## Core rule - -Agents do not work from vague chat history. - -Agents work from repository files: - -1. `AGENTS.md` -2. `docs/ARCHITECTURE.md` -3. `docs/DEVELOPMENT_WORKFLOW.md` -4. `docs/FEATURES/.md` -5. `docs/TASKS//.md` -6. `docs/PROMPTS/.md` - -## Workflow loop - -For every meaningful change: - -1. Define or update a feature spec in `docs/FEATURES/` -2. Create a small task in `docs/TASKS//` -3. Use the correct prompt template from `docs/PROMPTS/` -4. Ask the agent to implement only that task -5. Review the diff -6. Run tests/builds -7. Update OpenAPI when backend contracts change -8. Commit the task separately - -## Unit of work - -A task should usually be small enough to finish in one agent session. - -Good task examples: - -- Add `POST /api/auth/login` -- Add `LoginPage.vue` -- Add typed API wrapper for auth -- Add validation for registration email -- Add integration test for health endpoint - -Bad task examples: - -- Build auth -- Make the whole SaaS -- Redesign the app -- Add billing and dashboard and admin - -## Backend task pattern - -Backend changes should generally touch: - -```txt -backend/src/.Api/Endpoints// -backend/src/.Api/Contracts// -backend/tests/.Tests/ -``` - -Do not create new backend projects unless there is a clear architectural reason. - -## Frontend task pattern - -Frontend changes should generally touch: - -```txt -frontend/src/features// -frontend/src/pages/ -frontend/src/api/ -``` - -Prefer feature folders over global folders. - -## Contract workflow - -When backend endpoints or contracts change: - -```bash -./scripts/dev-backend.sh -./scripts/update-openapi.sh -``` - -Then check frontend TypeScript errors and fix affected frontend code. - -## Agent guardrails - -Agents must not: - -- invent architecture -- perform broad unrelated refactors -- manually duplicate generated API types -- ignore existing docs -- change deployment defaults without updating docs -- silently replace the chosen backend/frontend structure - -Agents should: - -- make small changes -- update feature specs when behavior changes -- update task files if implementation scope changes -- run or list validation commands -EOF - -cat > docs/FEATURE_TEMPLATE.md <<'EOF' -# Feature: - -## Status - -Draft | In Progress | Complete - -## Goal - -Describe the user-facing outcome. - -## User stories - -- As a , I want , so that . - -## Backend - -### Endpoints - -- `GET /api/...` -- `POST /api/...` - -### Contracts - -- `` -- `` - -### Domain rules - -- Rule 1 -- Rule 2 - -## Frontend - -### Pages - -- `` - -### Components - -- `` - -### State - -- Local component state -- Store state, if needed - -## API contract - -Describe what needs to appear in OpenAPI. - -## Done when - -- [ ] Backend endpoint implemented -- [ ] Backend tests added -- [ ] OpenAPI updated -- [ ] Frontend calls generated API types/client -- [ ] Frontend UI implemented -- [ ] Build/test passes - -## Notes - -Architectural notes, edge cases, and decisions. -EOF - -cat > docs/TASK_TEMPLATE.md <<'EOF' -# Task: - -## Feature - -`docs/FEATURES/.md` - -## Goal - -One concrete change. - -## Context - -What the agent needs to know before coding. - -## Files likely to change - -- `backend/src/...` -- `frontend/src/...` - -## Constraints - -- Follow existing architecture. -- Do not refactor unrelated files. -- Do not manually duplicate generated API types. -- Keep the diff focused. - -## Implementation steps - -1. Step one -2. Step two -3. Step three - -## Done when - -- [ ] Code implemented -- [ ] Tests/build pass -- [ ] OpenAPI regenerated if backend contracts changed -- [ ] Docs updated if behavior changed - -## Validation commands - -```bash -dotnet test backend/*.slnx -cd frontend && npm run build -``` -EOF - -cat > docs/PROMPT_TEMPLATE.md <<'EOF' -# General Agent Prompt Template - -You are working in this repository. - -## Read first - -- `AGENTS.md` -- `README.md` -- `docs/ARCHITECTURE.md` -- `docs/DEVELOPMENT_WORKFLOW.md` -- `docs/AGENTIC_WORKFLOW.md` -- `` -- `` - -## Task - -Implement: - -`` - -## Rules - -- Implement only this task. -- Do not refactor unrelated code. -- Follow existing backend/frontend structure. -- Backend feature code goes under `Endpoints/` and `Contracts/`. -- Frontend feature code goes under `frontend/src/features/`. -- If backend contracts change, update OpenAPI using `./scripts/update-openapi.sh`. -- Do not manually duplicate generated API types. - -## Output expected - -- Code changes -- Tests where appropriate -- Minimal docs update if behavior changed -- Summary of what changed -- Validation commands run -EOF - -cat > docs/PROMPTS/backend-task.md <<'EOF' -# Backend Task Prompt - -You are implementing a backend task in this repository. - -## Read first - -- `AGENTS.md` -- `docs/ARCHITECTURE.md` -- `docs/DEVELOPMENT_WORKFLOW.md` -- `docs/AGENTIC_WORKFLOW.md` -- Relevant feature spec in `docs/FEATURES/` -- Relevant task file in `docs/TASKS/` - -## Instructions - -- Implement only the requested backend task. -- Use the existing one-project backend structure. -- Put endpoints under `Endpoints//`. -- Put request/response contracts under `Contracts//`. -- Add or update tests under `backend/tests/`. -- Do not introduce repository/service layers unless the task explicitly requires it. -- Do not split the backend into multiple projects. - -## After coding - -Run or recommend: - -```bash -dotnet build backend/*.slnx -dotnet test backend/*.slnx -./scripts/update-openapi.sh -``` -EOF - -cat > docs/PROMPTS/frontend-task.md <<'EOF' -# Frontend Task Prompt - -You are implementing a frontend task in this repository. - -## Read first - -- `AGENTS.md` -- `docs/ARCHITECTURE.md` -- `docs/DEVELOPMENT_WORKFLOW.md` -- `docs/AGENTIC_WORKFLOW.md` -- Relevant feature spec in `docs/FEATURES/` -- Relevant task file in `docs/TASKS/` - -## Instructions - -- Implement only the requested frontend task. -- Put feature code under `frontend/src/features//`. -- Put route-level pages under `frontend/src/pages/`. -- Use generated API types from `frontend/src/api/schema.d.ts`. -- Do not manually recreate backend DTOs. -- Do not create global services unless the feature truly needs shared behavior. - -## After coding - -Run or recommend: - -```bash -cd frontend -npm run build -``` -EOF - -cat > docs/PROMPTS/debug.md <<'EOF' -# Debug Prompt - -You are debugging a specific failure in this repository. - -## Read first - -- `AGENTS.md` -- `docs/ARCHITECTURE.md` -- `docs/DEVELOPMENT_WORKFLOW.md` - -## Error - -Paste the full error here. - -## Instructions - -- Identify the most likely root cause. -- Make the smallest safe fix. -- Do not refactor unrelated code. -- Explain how to verify the fix. - -## Validation - -List the exact command(s) to run after the fix. -EOF - -cat > docs/PROMPTS/refactor.md <<'EOF' -# Refactor Prompt - -You are refactoring part of this repository. - -## Read first - -- `AGENTS.md` -- `docs/ARCHITECTURE.md` -- `docs/AGENTIC_WORKFLOW.md` -- Relevant feature spec - -## Scope - -Describe the exact refactor boundary. - -## Rules - -- Preserve behavior. -- Do not add features. -- Keep the diff focused. -- Update docs if structure or workflow changes. -- Run tests/builds after. - -## Validation - -```bash -dotnet test backend/*.slnx -cd frontend && npm run build -``` -EOF - -cat > docs/FEATURES/health.md <<'EOF' -# Feature: Health - -## Status - -Complete - -## Goal - -Verify that the frontend can call the backend through the generated OpenAPI TypeScript contract. - -## Backend - -### Endpoints - -- `GET /api/health` -- `GET /api/hello` - -### Contracts - -- `HealthResponse` -- `HelloResponse` - -## Frontend - -### Components - -- `HealthPanel.vue` - -### API - -- `features/health/api.ts` - -## Done when - -- [x] Backend exposes health endpoint -- [x] Frontend calls health endpoint -- [x] OpenAPI can generate frontend types -EOF - -mkdir -p docs/TASKS/health - -cat > docs/TASKS/health/001-verify-health-slice.md <<'EOF' -# Task: Verify health vertical slice - -## Feature - -`docs/FEATURES/health.md` - -## Goal - -Verify the generated project works end-to-end. - -## Steps - -1. Run the backend. -2. Run the frontend. -3. Open the frontend from localhost and optionally from another LAN machine. -4. Regenerate OpenAPI types. -5. Build/test. - -## Validation commands - -```bash -./scripts/dev-backend.sh -./scripts/dev-frontend.sh -./scripts/update-openapi.sh -dotnet test backend/*.slnx -cd frontend && npm run build -``` - -## Done when - -- [ ] Health panel shows backend status -- [ ] OpenAPI types regenerate successfully -- [ ] Backend tests pass -- [ ] Frontend build passes -EOF - -cat > docs/DECISIONS/0001-use-simple-dotnet-vue-monorepo.md < AGENTS.md <\` and \`Contracts/\`. -- Frontend feature code goes under \`frontend/src/features/\`. -- Frontend API types are generated from backend OpenAPI. -- Do not manually duplicate backend DTOs into frontend code. -- If backend DTOs or endpoints change, run \`./scripts/update-openapi.sh\`. -- Dev servers must use HTTP and bind to \`0.0.0.0\` for LAN access. -- Avoid broad refactors unless the task explicitly asks for one. - -## Task discipline - -Agents should work from task files in \`docs/TASKS/\`. - -A good task: - -- has a clear goal -- names the relevant feature -- has a small scope -- lists validation commands - -If no task exists, create one before implementing a meaningful feature. - -## Validation - -For backend changes: - -\`\`\`bash -dotnet build backend/$SLNX_NAME -dotnet test backend/$SLNX_NAME -\`\`\` - -For frontend changes: - -\`\`\`bash -cd frontend -npm run build -\`\`\` - -For contract changes: - -\`\`\`bash -./scripts/update-openapi.sh -\`\`\` -EOF - -cat > .gitignore <<'EOF' -# .NET -bin/ -obj/ -TestResults/ -*.user -*.suo - -# Node -node_modules/ -dist/ -.vite/ - -# Env -.env -.env.* - -# IDE -.vscode/ -.idea/ - -# OS -.DS_Store -Thumbs.db -EOF - -echo -echo "Bootstrap complete." -echo -echo "Next:" -echo " cd $PROJECT_DIR" -echo " ./scripts/dev-backend.sh" -echo " ./scripts/dev-frontend.sh" -echo -echo "After backend is running:" -echo " ./scripts/update-openapi.sh" -echo -echo "Agentic workflow:" -echo " docs/AGENTIC_WORKFLOW.md"