Two distinct fixes: 1. Database terminology: Make it crystal clear that generated projects use CockroachDB in production and PostgreSQL for local dev, while the rdev platform itself uses PostgreSQL. Updated 15 files across skeleton agents, component templates, cookbook trees, and platform docs. 2. Video storage: VideoHandler was ignoring vid.Data bytes (already downloaded by the Gemini adapter with auth) and re-downloading from the provider URL with a plain GET — which fails because Gemini URLs require API key auth. Now uses vid.Data first, falls back to downloadURL only for public URLs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
396 lines
15 KiB
YAML
396 lines
15 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 CockroachDB 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
|
|
|
|
setup-hooks:
|
|
description: "Configure git hooks in project workspace"
|
|
depends_on: [wait-bootstrap]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
|
|
body:
|
|
prompt: "Run ./scripts/setup-hooks.sh to configure git hooks. Then verify with: git config core.hooksPath"
|
|
auto_commit: false
|
|
auto_push: false
|
|
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
|
|
outputs:
|
|
- build_id: .data.task_id
|
|
|
|
wait-setup-hooks:
|
|
description: "Wait for git hooks setup to complete"
|
|
depends_on: [setup-hooks]
|
|
action: wait_build
|
|
build_id: "{{ .outputs.setup-hooks.build_id }}"
|
|
max_attempts: 120
|
|
poll_interval: 5
|
|
|
|
add-components:
|
|
description: "Add React frontend, API service, and CockroachDB database"
|
|
depends_on: [wait-setup-hooks]
|
|
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: 120
|
|
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 CockroachDB 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 CockroachDB 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
|
|
|
|
# --- Commit QA artifacts and validate pre-merge hooks ---
|
|
commit-after-qa:
|
|
description: "Commit any remaining changes after QA"
|
|
depends_on: [wait-deploy-polish]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
|
|
body:
|
|
prompt: '/commit-all "chore: commit QA artifacts and fixes"'
|
|
auto_commit: false
|
|
auto_push: false
|
|
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
|
|
outputs:
|
|
- build_id: .data.task_id
|
|
|
|
wait-commit-after-qa:
|
|
description: "Wait for QA commit to complete"
|
|
depends_on: [commit-after-qa]
|
|
action: wait_build
|
|
build_id: "{{ .outputs.commit-after-qa.build_id }}"
|
|
max_attempts: 120
|
|
poll_interval: 5
|
|
|
|
pre-merge-validate:
|
|
description: "Run pre-commit hooks and fix any failures"
|
|
depends_on: [wait-commit-after-qa]
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
|
|
body:
|
|
prompt: |
|
|
Run ./.githooks/pre-commit to check code quality.
|
|
If it fails, run /fix-all to fix all issues, then re-run
|
|
./.githooks/pre-commit. Repeat until it passes.
|
|
auto_commit: true
|
|
auto_push: true
|
|
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
|
|
outputs:
|
|
- build_id: .data.task_id
|
|
|
|
wait-pre-merge-validate:
|
|
description: "Wait for pre-merge validation to complete"
|
|
depends_on: [pre-merge-validate]
|
|
action: wait_build
|
|
build_id: "{{ .outputs.pre-merge-validate.build_id }}"
|
|
max_attempts: 720
|
|
poll_interval: 5
|
|
|
|
wait-deploy-final:
|
|
description: "Wait for final deployment pipeline after validation fixes"
|
|
depends_on: [wait-pre-merge-validate]
|
|
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-final]
|
|
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 }}"
|