All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
The architect service was missing pod_name/namespace in AgentRequest metadata, causing Claude Code adapter to reject all requests. Added ArchitectServiceConfig with pod resolution (project PodName → default claudebox-0). Removed silent JSON fallback in extractSpecFromMessages that masked errors. Rewrote foundary cookbook from 90-step SDLC flow to focused 25-step cookbook using natural language build prompts instead of /slash-commands that claudebox cannot execute. Added "no fallbacks" rule to CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
319 lines
12 KiB
YAML
319 lines
12 KiB
YAML
name: foundary
|
|
description: "Foundary Studio: Bootstrap a React+API+DB project, design via architect conversation, build with natural language prompts, and verify the live site."
|
|
version: 2
|
|
|
|
vars:
|
|
project_name: ""
|
|
|
|
steps:
|
|
# ============================================================
|
|
# SECTION 1: INFRASTRUCTURE
|
|
# Create project with React app, API service, and database
|
|
# ============================================================
|
|
create-project:
|
|
description: "Create project with bootstrap build"
|
|
action: api
|
|
method: POST
|
|
endpoint: /project/create-and-build
|
|
body:
|
|
name: "{{ .vars.project_name }}"
|
|
description: "Foundary Studio: Task management with Kanban board"
|
|
template: "skeleton"
|
|
prompt: "Set up the monorepo workspace. Ensure the root README describes a task management studio with Kanban board, REST API, and Postgres persistence."
|
|
auto_commit: true
|
|
auto_push: true
|
|
outputs:
|
|
- project_id: .data.project_id
|
|
- domain: .data.domain
|
|
- git_clone_http: .data.git.clone_http
|
|
- bootstrap_task_id: .data.task_id
|
|
|
|
wait-bootstrap:
|
|
description: "Wait for bootstrap build to complete"
|
|
depends_on: [create-project]
|
|
action: wait_build
|
|
build_id: "{{ .outputs.create-project.bootstrap_task_id }}"
|
|
max_attempts: 720
|
|
poll_interval: 5
|
|
|
|
add-components:
|
|
description: "Add React frontend, API service, and Postgres database"
|
|
depends_on: [wait-bootstrap]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/components/batch"
|
|
body:
|
|
components:
|
|
- type: app-react
|
|
name: studio-ui
|
|
- type: service
|
|
name: studio-api
|
|
- type: postgres
|
|
name: studio-db
|
|
|
|
wait-components:
|
|
description: "Wait for component scaffolding pipeline"
|
|
depends_on: [add-components]
|
|
action: wait_pipeline
|
|
project_id: "{{ .outputs.create-project.project_id }}"
|
|
max_attempts: 720
|
|
on_error: continue
|
|
|
|
verify-site:
|
|
description: "Verify site is live (may 503 until first build pushes component images)"
|
|
depends_on: [wait-components]
|
|
action: wait_site
|
|
domain: "{{ .outputs.create-project.domain }}"
|
|
max_attempts: 60
|
|
on_error: continue
|
|
|
|
# ============================================================
|
|
# SECTION 2: DESIGN & BUILD
|
|
# Architect conversation flow, then 3 iterative builds with
|
|
# natural language prompts (no slash commands).
|
|
# ============================================================
|
|
architect-start:
|
|
description: "Start architect conversation about product goals"
|
|
depends_on: [verify-site]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/architect/start"
|
|
body:
|
|
prompt: "I want to build a task management studio. The product needs: 1) Core data models for Task, Project, Label, and Assignment entities with full CRUD stored in Postgres via studio-db, exposed as REST endpoints on studio-api. 2) A React frontend in studio-ui with a Kanban board (drag-and-drop columns: To Do, In Progress, Done), task creation/edit modals, and filtering by label and assignee. Propose the architecture and identify the two MVP features we should build."
|
|
outputs:
|
|
- conversation_id: .data.id
|
|
|
|
architect-refine:
|
|
description: "Refine architecture with component details"
|
|
depends_on: [architect-start]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/architect/continue/{{ .outputs.architect-start.conversation_id }}"
|
|
body:
|
|
message: "Good. Let's define exactly two features for the MVP: Feature 1 covers the persistence layer (Task, Project, Label, Assignment entities, migrations, repository layer, service layer, handler tests). Feature 2 covers the React frontend (Kanban board, task CRUD modals, label/assignee filters). Feature 2 depends on Feature 1 being complete since it consumes the API. Please confirm this breakdown and note any architectural considerations."
|
|
|
|
architect-generate-blueprint:
|
|
description: "Generate structured blueprint from conversation"
|
|
depends_on: [architect-refine]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/architect/generate-blueprint/{{ .outputs.architect-start.conversation_id }}"
|
|
body:
|
|
name: "foundary-studio-mvp"
|
|
outputs:
|
|
- blueprint_id: .data.blueprint.id
|
|
|
|
# --- Build 1: Data models, migrations, repository, handlers on studio-api ---
|
|
build-api:
|
|
description: "Build studio-api: data models, migrations, repository, handlers"
|
|
depends_on: [architect-generate-blueprint]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
|
|
body:
|
|
prompt: |
|
|
Build the studio-api service with these requirements:
|
|
|
|
1. Data models: Define Task, Project, Label, and Assignment entities.
|
|
- Task: id, title, description, status (todo/in_progress/done), project_id, assignee_id, created_at, updated_at
|
|
- Project: id, name, description, created_at
|
|
- Label: id, name, color, project_id
|
|
- Assignment: id, task_id, label_id (many-to-many join)
|
|
|
|
2. Database: Create SQL migrations for all tables with foreign keys and indexes.
|
|
Use the studio-db Postgres connection (DATABASE_URL env var).
|
|
|
|
3. Repository layer: Implement CRUD operations for each entity using sqlx.
|
|
|
|
4. Service layer: Business logic for task lifecycle (create, update status, assign labels).
|
|
|
|
5. HTTP handlers: RESTful endpoints mounted at /api/:
|
|
- GET/POST /api/projects, GET/PUT/DELETE /api/projects/:id
|
|
- GET/POST /api/tasks, GET/PUT/DELETE /api/tasks/:id
|
|
- GET/POST /api/labels, GET/PUT/DELETE /api/labels/:id
|
|
- POST/DELETE /api/tasks/:id/labels/:label_id
|
|
|
|
6. Tests: Add handler tests for the task CRUD endpoints.
|
|
|
|
Work in the components/studio-api/ directory.
|
|
auto_commit: true
|
|
auto_push: true
|
|
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
|
|
outputs:
|
|
- build_id: .data.task_id
|
|
|
|
wait-build-api:
|
|
description: "Wait for API build to complete"
|
|
depends_on: [build-api]
|
|
action: wait_build
|
|
build_id: "{{ .outputs.build-api.build_id }}"
|
|
max_attempts: 720
|
|
poll_interval: 5
|
|
|
|
wait-deploy-api:
|
|
description: "Wait for API deployment pipeline"
|
|
depends_on: [wait-build-api]
|
|
action: wait_pipeline
|
|
project_id: "{{ .outputs.create-project.project_id }}"
|
|
max_attempts: 720
|
|
|
|
# --- Build 2: React Kanban UI, API client, task CRUD modals on studio-ui ---
|
|
build-ui:
|
|
description: "Build studio-ui: Kanban board, API client, task modals"
|
|
depends_on: [wait-deploy-api]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
|
|
body:
|
|
prompt: |
|
|
Build the studio-ui React frontend with these requirements:
|
|
|
|
1. API client: Create a typed fetch wrapper that calls the studio-api endpoints.
|
|
Base URL should be configurable via VITE_API_URL env var, defaulting to /api.
|
|
|
|
2. Kanban board: Three columns (To Do, In Progress, Done).
|
|
- Display tasks as cards with title, description preview, and labels.
|
|
- Implement drag-and-drop between columns using @dnd-kit/core.
|
|
- Moving a card between columns calls PUT /api/tasks/:id to update status.
|
|
|
|
3. Task modals: Create/Edit modal with fields for title, description, and label selection.
|
|
- Create: POST /api/tasks
|
|
- Edit: PUT /api/tasks/:id
|
|
- Delete: confirmation dialog, then DELETE /api/tasks/:id
|
|
|
|
4. Project selector: Dropdown to switch between projects (GET /api/projects).
|
|
|
|
5. Label/assignee filters: Filter bar above the Kanban board.
|
|
|
|
6. Layout: Clean dashboard layout with header, project selector, filter bar, and board.
|
|
|
|
Work in the components/studio-ui/ directory. Use Tailwind CSS for styling.
|
|
auto_commit: true
|
|
auto_push: true
|
|
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
|
|
outputs:
|
|
- build_id: .data.task_id
|
|
|
|
wait-build-ui:
|
|
description: "Wait for UI build to complete"
|
|
depends_on: [build-ui]
|
|
action: wait_build
|
|
build_id: "{{ .outputs.build-ui.build_id }}"
|
|
max_attempts: 720
|
|
poll_interval: 5
|
|
|
|
wait-deploy-ui:
|
|
description: "Wait for UI deployment pipeline"
|
|
depends_on: [wait-build-ui]
|
|
action: wait_pipeline
|
|
project_id: "{{ .outputs.create-project.project_id }}"
|
|
max_attempts: 720
|
|
|
|
# --- Build 3: Polish — CORS, error handling, health check, README ---
|
|
build-polish:
|
|
description: "Polish: CORS, error handling, health check, README"
|
|
depends_on: [wait-deploy-ui]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
|
|
body:
|
|
prompt: |
|
|
Polish the Foundary Studio application:
|
|
|
|
1. CORS: Ensure studio-api allows requests from the studio-ui origin.
|
|
Add CORS middleware that allows GET, POST, PUT, DELETE, OPTIONS with credentials.
|
|
|
|
2. Error handling: Add proper error responses (400, 404, 500) with JSON error bodies
|
|
from studio-api handlers. Add error toast notifications in studio-ui.
|
|
|
|
3. Health check: Add GET /api/health endpoint on studio-api that checks database
|
|
connectivity and returns {"status": "ok", "service": "studio-api"}.
|
|
|
|
4. README: Update the root README.md with:
|
|
- Project description (task management studio)
|
|
- Architecture overview (monorepo with studio-ui, studio-api, studio-db)
|
|
- API endpoint reference
|
|
- Local development instructions
|
|
auto_commit: true
|
|
auto_push: true
|
|
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
|
|
outputs:
|
|
- build_id: .data.task_id
|
|
|
|
wait-build-polish:
|
|
description: "Wait for polish build to complete"
|
|
depends_on: [build-polish]
|
|
action: wait_build
|
|
build_id: "{{ .outputs.build-polish.build_id }}"
|
|
max_attempts: 720
|
|
poll_interval: 5
|
|
|
|
wait-deploy-polish:
|
|
description: "Wait for polish deployment pipeline"
|
|
depends_on: [wait-build-polish]
|
|
action: wait_pipeline
|
|
project_id: "{{ .outputs.create-project.project_id }}"
|
|
max_attempts: 720
|
|
|
|
# ============================================================
|
|
# SECTION 3: VERIFY
|
|
# Confirm site is live and API responds
|
|
# ============================================================
|
|
verify-site-live:
|
|
description: "Verify site is live after all builds"
|
|
depends_on: [wait-deploy-polish]
|
|
action: wait_site
|
|
domain: "{{ .outputs.create-project.domain }}"
|
|
max_attempts: 120
|
|
|
|
verify-api-health:
|
|
description: "Verify API health endpoint responds"
|
|
depends_on: [verify-site-live]
|
|
on_error: continue
|
|
action: shell
|
|
command: |
|
|
DOMAIN="{{ .outputs.create-project.domain }}"
|
|
|
|
# Check API health
|
|
HEALTH=$(curl -sf "https://$DOMAIN/api/studio-api/health" 2>/dev/null || echo '{}')
|
|
echo "API health response: $HEALTH"
|
|
|
|
STATUS=$(echo "$HEALTH" | grep -o '"status":"ok"' || true)
|
|
if [ -n "$STATUS" ]; then
|
|
echo "API health check passed"
|
|
exit 0
|
|
else
|
|
echo "API health check failed (may not have health endpoint yet)"
|
|
exit 1
|
|
fi
|
|
|
|
verify-complete:
|
|
description: "Print success summary"
|
|
depends_on: [verify-api-health]
|
|
action: shell
|
|
command: |
|
|
echo ""
|
|
echo "============================================================"
|
|
echo "SUCCESS: Foundary Studio build complete"
|
|
echo "============================================================"
|
|
echo ""
|
|
echo "Domain: {{ .outputs.create-project.domain }}"
|
|
echo "Project ID: {{ .outputs.create-project.project_id }}"
|
|
echo ""
|
|
echo "Architecture:"
|
|
echo " studio-ui — React Kanban board frontend"
|
|
echo " studio-api — REST API with Task/Project/Label CRUD"
|
|
echo " studio-db — PostgreSQL persistence"
|
|
echo ""
|
|
echo "Builds completed:"
|
|
echo " 1. API: data models, migrations, repository, handlers"
|
|
echo " 2. UI: Kanban board, drag-and-drop, task modals"
|
|
echo " 3. Polish: CORS, error handling, health check, README"
|
|
echo "============================================================"
|
|
exit 0
|
|
|
|
teardown:
|
|
- action: api
|
|
method: DELETE
|
|
endpoint: "/project/{{ .outputs.create-project.project_id }}"
|