rdev/cookbooks/trees/foundary.yaml
jordan c68fadbccd
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix(architect): add pod_name to agent requests, rewrite foundary cookbook
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>
2026-02-11 01:24:34 -07:00

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 }}"