rdev/cookbooks/trees/foundary.yaml
jordan a69eb7e587 feat(foundary): implement complete backend for conversational project design
Implements all 5 phases of Foundary Studio backend:

Phase 1: Chat Persistence (8 API endpoints)
- Conversations and messages with proper cascading deletes
- PostgreSQL schema with auto-update triggers
- Full CRUD operations with structured logging

Phase 2: Blueprint Entity (5 API endpoints)
- JSONB spec storage with GIN indexes
- Flexible structured data for project specifications
- Version-controlled blueprint management

Phase 3: Architect Service (3 API endpoints)
- Conversational AI orchestration with Claude
- Multi-turn dialogue with context building
- Blueprint spec extraction from conversations

Phase 4: Work Queue Integration
- Verified existing endpoint compatibility

Phase 5: Structured Questions (6 API endpoints)
- Four question types: text, choice, multichoice, yesno
- Answer validation with proper constraints
- Conversation-linked Q&A flow

Architecture:
- Textbook hexagonal architecture (domain → port → adapter → service → handler)
- Zero external dependencies in domain layer
- Consistent error handling with proper wrapping
- Auth scopes on all routes (projects:read, projects:execute)
- Structured logging with operation context and duration tracking
- NULL-safe DTO converters throughout

Database:
- 3 new migrations (019, 020, 021)
- UUIDs for all primary keys
- Proper foreign key constraints with ON DELETE CASCADE
- Optimized indexes including partial index for unanswered questions
- Auto-update triggers for timestamps

OpenAPI Documentation:
- Complete API documentation under 'Foundary' tag
- 22 new endpoints documented with examples
- Request/response schemas for all operations

Logging Improvements:
- Added operation field to all service logs
- Added duration_ms tracking for performance monitoring
- Log response_length instead of full response content
- Consistent use of logging field constants
- Execute-then-log pattern for delete operations

Files: 32 changed, 2800+ lines added
- 7 domain models
- 3 database migrations
- 3 port interfaces
- 3 postgres adapters
- 4 services (conversation, blueprint, question, architect)
- 4 handlers with DTOs
- OpenAPI documentation
- Integration in main.go

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-09 00:50:46 -07:00

999 lines
33 KiB
YAML

name: foundary
description: "Foundary Studio: Conversational product development lifecycle. Bootstraps a React+API+DB project, specs two features via SDLC, implements with build agents, reviews, merges, and releases."
version: 1
vars:
project_name: ""
feature_1_slug: "data-models"
feature_1_title: "Core Data Models & Persistence"
feature_2_slug: "task-management-ui"
feature_2_title: "Task Management UI"
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: Conversational product development"
template: "default"
prompt: "Set up the monorepo workspace. Ensure the root README describes a product studio for conversational product development."
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 after component scaffolding"
depends_on: [wait-components]
action: wait_site
domain: "{{ .outputs.create-project.domain }}"
max_attempts: 60
verify-sdlc:
description: "Verify SDLC state is initialized"
depends_on: [verify-site]
action: api
method: GET
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/state"
outputs:
- sdlc_initialized: .data.initialized
# ============================================================
# SECTION 2: ARCHITECT (Shell Stubs for Future Chat/Blueprint APIs)
# Documents the conversational architect flow that will use
# POST /projects/{id}/chat and GET /projects/{id}/blueprints
# ============================================================
architect-session:
description: "Simulate architect conversation (stub for future chat API)"
depends_on: [verify-sdlc]
action: shell
command: |
cat <<'ARCHITECT'
============================================================
FOUNDARY ARCHITECT SESSION (Future: POST /projects/{id}/chat)
============================================================
The architect conversation would:
1. Discuss product goals for a task management studio
2. Identify core entities: projects, tasks, labels, assignments
3. Propose two features for MVP:
- Feature 1: data-models (Core Data Models & Persistence)
- Feature 2: task-management-ui (Task Management UI)
4. Generate blueprint (Future: GET /projects/{id}/blueprints)
Feature definitions for downstream SDLC:
{
"features": [
{
"slug": "data-models",
"title": "Core Data Models & Persistence",
"requirements": "Define Task, Project, Label, and Assignment entities with full CRUD. Postgres storage via studio-db. REST endpoints on studio-api. Include migrations, repository layer, service layer, and handler tests."
},
{
"slug": "task-management-ui",
"title": "Task Management UI",
"requirements": "React UI in studio-ui for managing tasks. Kanban board view with drag-and-drop columns (To Do, In Progress, Done). Task creation/edit modal. Filter by label and assignee. Connects to studio-api REST endpoints."
}
]
}
ARCHITECT
echo "Architect session complete — feature definitions ready"
# ============================================================
# SECTION 3: FEATURE 1 — Core Data Models (draft → released)
# Full 10-phase SDLC lifecycle
# ============================================================
# --- Phase 1: Draft ---
f1-create-feature:
description: "Create data-models feature in draft phase"
depends_on: [architect-session]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features"
body:
slug: "{{ .vars.feature_1_slug }}"
title: "{{ .vars.feature_1_title }}"
outputs:
- feature_phase: .data.phase
f1-verify-draft:
description: "Verify feature 1 is in draft phase"
depends_on: [f1-create-feature]
action: shell
command: |
PHASE="{{ .outputs.f1-create-feature.feature_phase }}"
if [ "$PHASE" == "draft" ]; then
echo "Feature 1 created in draft phase"
exit 0
else
echo "Expected draft, got $PHASE"
exit 1
fi
# --- Phase 2: Draft → Specified ---
f1-write-spec:
description: "Agent writes spec for data models"
depends_on: [f1-verify-draft]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/spec-feature {{ .vars.feature_1_slug }} --requirements 'Define Task, Project, Label, and Assignment entities with full CRUD. Postgres storage via studio-db. REST endpoints on studio-api. Include migrations, repository layer, service layer, and handler tests.'"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-spec:
depends_on: [f1-write-spec]
action: wait_build
build_id: "{{ .outputs.f1-write-spec.build_id }}"
max_attempts: 720
poll_interval: 5
f1-approve-spec:
description: "Approve spec artifact"
depends_on: [f1-wait-spec]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/artifacts/spec/approve"
body:
comment: "Spec approved by foundary automation"
f1-transition-to-specified:
description: "Transition from draft to specified"
depends_on: [f1-approve-spec]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "specified"
outputs:
- new_phase: .data.phase
# --- Phase 3: Specified → Planned ---
f1-write-design:
description: "Agent writes design for data models"
depends_on: [f1-transition-to-specified]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/design-feature {{ .vars.feature_1_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-design:
depends_on: [f1-write-design]
action: wait_build
build_id: "{{ .outputs.f1-write-design.build_id }}"
max_attempts: 720
poll_interval: 5
f1-approve-design:
description: "Approve design artifact"
depends_on: [f1-wait-design]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/artifacts/design/approve"
body:
comment: "Design approved by foundary automation"
f1-write-tasks:
description: "Agent breaks down into tasks"
depends_on: [f1-approve-design]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/breakdown-feature {{ .vars.feature_1_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-tasks:
depends_on: [f1-write-tasks]
action: wait_build
build_id: "{{ .outputs.f1-write-tasks.build_id }}"
max_attempts: 720
poll_interval: 5
f1-approve-tasks:
description: "Approve tasks artifact"
depends_on: [f1-wait-tasks]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/artifacts/tasks/approve"
body:
comment: "Tasks approved by foundary automation"
f1-write-qa-plan:
description: "Agent writes QA plan"
depends_on: [f1-approve-tasks]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/create-qa-plan {{ .vars.feature_1_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-qa-plan:
depends_on: [f1-write-qa-plan]
action: wait_build
build_id: "{{ .outputs.f1-write-qa-plan.build_id }}"
max_attempts: 720
poll_interval: 5
f1-approve-qa-plan:
description: "Approve QA plan artifact"
depends_on: [f1-wait-qa-plan]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/artifacts/qa_plan/approve"
body:
comment: "QA plan approved by foundary automation"
f1-transition-to-planned:
description: "Transition from specified to planned"
depends_on: [f1-approve-qa-plan]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "planned"
outputs:
- new_phase: .data.phase
# --- Phase 4: Planned → Ready ---
f1-create-branch:
description: "Create feature branch for data-models"
depends_on: [f1-transition-to-planned]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/branches"
outputs:
- branch_name: .data.name
f1-transition-to-ready:
description: "Transition from planned to ready"
depends_on: [f1-create-branch]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "ready"
outputs:
- new_phase: .data.phase
# --- Phase 5: Ready → Implementation ---
f1-implement:
description: "Agent implements data models feature"
depends_on: [f1-transition-to-ready]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/implement-feature {{ .vars.feature_1_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-implement:
depends_on: [f1-implement]
action: wait_build
build_id: "{{ .outputs.f1-implement.build_id }}"
max_attempts: 720
poll_interval: 5
f1-wait-deploy-impl:
description: "Wait for implementation to deploy"
depends_on: [f1-wait-implement]
action: wait_pipeline
project_id: "{{ .outputs.create-project.project_id }}"
max_attempts: 720
f1-transition-to-implementation:
description: "Transition to implementation phase"
depends_on: [f1-wait-deploy-impl]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "implementation"
outputs:
- new_phase: .data.phase
# --- Phase 6: Implementation → Review ---
f1-write-review:
description: "Agent writes code review"
depends_on: [f1-transition-to-implementation]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/review-feature {{ .vars.feature_1_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-review:
depends_on: [f1-write-review]
action: wait_build
build_id: "{{ .outputs.f1-write-review.build_id }}"
max_attempts: 720
poll_interval: 5
f1-pass-review:
description: "Mark review as passed"
depends_on: [f1-wait-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/artifacts/review/pass"
f1-transition-to-review:
description: "Transition to review phase"
depends_on: [f1-pass-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "review"
outputs:
- new_phase: .data.phase
# --- Phase 7: Review → Audit ---
f1-write-audit:
description: "Agent writes security audit"
depends_on: [f1-transition-to-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/audit-feature {{ .vars.feature_1_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-audit:
depends_on: [f1-write-audit]
action: wait_build
build_id: "{{ .outputs.f1-write-audit.build_id }}"
max_attempts: 720
poll_interval: 5
f1-pass-audit:
description: "Mark audit as passed"
depends_on: [f1-wait-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/artifacts/audit/pass"
f1-transition-to-audit:
description: "Transition to audit phase"
depends_on: [f1-pass-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "audit"
outputs:
- new_phase: .data.phase
# --- Phase 8: Audit → QA ---
f1-run-qa:
description: "Agent runs QA plan"
depends_on: [f1-transition-to-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/run-qa {{ .vars.feature_1_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f1-wait-qa:
depends_on: [f1-run-qa]
action: wait_build
build_id: "{{ .outputs.f1-run-qa.build_id }}"
max_attempts: 720
poll_interval: 5
f1-pass-qa:
description: "Mark QA as passed"
depends_on: [f1-wait-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/artifacts/qa_results/pass"
f1-transition-to-qa:
description: "Transition to QA phase"
depends_on: [f1-pass-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "qa"
outputs:
- new_phase: .data.phase
# --- Phase 9: QA → Merge ---
f1-transition-to-merge:
description: "Transition to merge phase"
depends_on: [f1-transition-to-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "merge"
outputs:
- new_phase: .data.phase
f1-merge:
description: "Merge data-models feature branch to main"
depends_on: [f1-transition-to-merge]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/merge"
body:
strategy: "squash"
outputs:
- merge_commit: .data.commit_sha
f1-wait-merge-deploy:
description: "Wait for merged code to deploy"
depends_on: [f1-merge]
action: wait_pipeline
project_id: "{{ .outputs.create-project.project_id }}"
max_attempts: 720
# --- Phase 10: Merge → Released ---
f1-archive:
description: "Archive data-models feature"
depends_on: [f1-wait-merge-deploy]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/archive"
f1-transition-to-released:
description: "Transition to released phase"
depends_on: [f1-archive]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
body:
phase: "released"
outputs:
- final_phase: .data.phase
# ============================================================
# SECTION 4: FEATURE 2 — Task Management UI (draft → released)
# Spec starts after Feature 1 spec (independent)
# Design depends on Feature 1 reaching planned (schema defined)
# Implementation depends on Feature 1 released (schema in main)
# ============================================================
# --- Phase 1: Draft ---
# Feature 2 creation can start after Feature 1 spec is approved (parallel speccing)
f2-create-feature:
description: "Create task-management-ui feature in draft phase"
depends_on: [f1-approve-spec]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features"
body:
slug: "{{ .vars.feature_2_slug }}"
title: "{{ .vars.feature_2_title }}"
outputs:
- feature_phase: .data.phase
f2-verify-draft:
description: "Verify feature 2 is in draft phase"
depends_on: [f2-create-feature]
action: shell
command: |
PHASE="{{ .outputs.f2-create-feature.feature_phase }}"
if [ "$PHASE" == "draft" ]; then
echo "Feature 2 created in draft phase"
exit 0
else
echo "Expected draft, got $PHASE"
exit 1
fi
# --- Phase 2: Draft → Specified ---
f2-write-spec:
description: "Agent writes spec for task management UI"
depends_on: [f2-verify-draft]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/spec-feature {{ .vars.feature_2_slug }} --requirements 'React UI in studio-ui for managing tasks. Kanban board view with drag-and-drop columns (To Do, In Progress, Done). Task creation/edit modal with title, description, label, assignee fields. Filter by label and assignee. Connects to studio-api REST endpoints for Task CRUD.'"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-spec:
depends_on: [f2-write-spec]
action: wait_build
build_id: "{{ .outputs.f2-write-spec.build_id }}"
max_attempts: 720
poll_interval: 5
f2-approve-spec:
description: "Approve spec artifact"
depends_on: [f2-wait-spec]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/artifacts/spec/approve"
body:
comment: "Spec approved by foundary automation"
f2-transition-to-specified:
description: "Transition from draft to specified"
depends_on: [f2-approve-spec]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "specified"
outputs:
- new_phase: .data.phase
# --- Phase 3: Specified → Planned ---
# Design depends on Feature 1 reaching planned (schema must be defined first)
f2-write-design:
description: "Agent writes design for task management UI (after F1 schema planned)"
depends_on: [f2-transition-to-specified, f1-transition-to-planned]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/design-feature {{ .vars.feature_2_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-design:
depends_on: [f2-write-design]
action: wait_build
build_id: "{{ .outputs.f2-write-design.build_id }}"
max_attempts: 720
poll_interval: 5
f2-approve-design:
description: "Approve design artifact"
depends_on: [f2-wait-design]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/artifacts/design/approve"
body:
comment: "Design approved by foundary automation"
f2-write-tasks:
description: "Agent breaks down into tasks"
depends_on: [f2-approve-design]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/breakdown-feature {{ .vars.feature_2_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-tasks:
depends_on: [f2-write-tasks]
action: wait_build
build_id: "{{ .outputs.f2-write-tasks.build_id }}"
max_attempts: 720
poll_interval: 5
f2-approve-tasks:
description: "Approve tasks artifact"
depends_on: [f2-wait-tasks]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/artifacts/tasks/approve"
body:
comment: "Tasks approved by foundary automation"
f2-write-qa-plan:
description: "Agent writes QA plan"
depends_on: [f2-approve-tasks]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/create-qa-plan {{ .vars.feature_2_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-qa-plan:
depends_on: [f2-write-qa-plan]
action: wait_build
build_id: "{{ .outputs.f2-write-qa-plan.build_id }}"
max_attempts: 720
poll_interval: 5
f2-approve-qa-plan:
description: "Approve QA plan artifact"
depends_on: [f2-wait-qa-plan]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/artifacts/qa_plan/approve"
body:
comment: "QA plan approved by foundary automation"
f2-transition-to-planned:
description: "Transition from specified to planned"
depends_on: [f2-approve-qa-plan]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "planned"
outputs:
- new_phase: .data.phase
# --- Phase 4: Planned → Ready ---
f2-create-branch:
description: "Create feature branch for task-management-ui"
depends_on: [f2-transition-to-planned]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/branches"
outputs:
- branch_name: .data.name
f2-transition-to-ready:
description: "Transition from planned to ready"
depends_on: [f2-create-branch]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "ready"
outputs:
- new_phase: .data.phase
# --- Phase 5: Ready → Implementation ---
# Implementation depends on Feature 1 being released (schema in main)
f2-implement:
description: "Agent implements task management UI (after F1 released to main)"
depends_on: [f2-transition-to-ready, f1-transition-to-released]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/implement-feature {{ .vars.feature_2_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-implement:
depends_on: [f2-implement]
action: wait_build
build_id: "{{ .outputs.f2-implement.build_id }}"
max_attempts: 720
poll_interval: 5
f2-wait-deploy-impl:
description: "Wait for implementation to deploy"
depends_on: [f2-wait-implement]
action: wait_pipeline
project_id: "{{ .outputs.create-project.project_id }}"
max_attempts: 720
f2-transition-to-implementation:
description: "Transition to implementation phase"
depends_on: [f2-wait-deploy-impl]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "implementation"
outputs:
- new_phase: .data.phase
# --- Phase 6: Implementation → Review ---
f2-write-review:
description: "Agent writes code review"
depends_on: [f2-transition-to-implementation]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/review-feature {{ .vars.feature_2_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-review:
depends_on: [f2-write-review]
action: wait_build
build_id: "{{ .outputs.f2-write-review.build_id }}"
max_attempts: 720
poll_interval: 5
f2-pass-review:
description: "Mark review as passed"
depends_on: [f2-wait-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/artifacts/review/pass"
f2-transition-to-review:
description: "Transition to review phase"
depends_on: [f2-pass-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "review"
outputs:
- new_phase: .data.phase
# --- Phase 7: Review → Audit ---
f2-write-audit:
description: "Agent writes security audit"
depends_on: [f2-transition-to-review]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/audit-feature {{ .vars.feature_2_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-audit:
depends_on: [f2-write-audit]
action: wait_build
build_id: "{{ .outputs.f2-write-audit.build_id }}"
max_attempts: 720
poll_interval: 5
f2-pass-audit:
description: "Mark audit as passed"
depends_on: [f2-wait-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/artifacts/audit/pass"
f2-transition-to-audit:
description: "Transition to audit phase"
depends_on: [f2-pass-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "audit"
outputs:
- new_phase: .data.phase
# --- Phase 8: Audit → QA ---
f2-run-qa:
description: "Agent runs QA plan"
depends_on: [f2-transition-to-audit]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds"
body:
prompt: "/run-qa {{ .vars.feature_2_slug }}"
auto_commit: true
auto_push: true
git_clone_url: "{{ .outputs.create-project.git_clone_http }}"
outputs:
- build_id: .data.task_id
f2-wait-qa:
depends_on: [f2-run-qa]
action: wait_build
build_id: "{{ .outputs.f2-run-qa.build_id }}"
max_attempts: 720
poll_interval: 5
f2-pass-qa:
description: "Mark QA as passed"
depends_on: [f2-wait-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/artifacts/qa_results/pass"
f2-transition-to-qa:
description: "Transition to QA phase"
depends_on: [f2-pass-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "qa"
outputs:
- new_phase: .data.phase
# --- Phase 9: QA → Merge ---
f2-transition-to-merge:
description: "Transition to merge phase"
depends_on: [f2-transition-to-qa]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "merge"
outputs:
- new_phase: .data.phase
f2-merge:
description: "Merge task-management-ui feature branch to main"
depends_on: [f2-transition-to-merge]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/merge"
body:
strategy: "squash"
outputs:
- merge_commit: .data.commit_sha
f2-wait-merge-deploy:
description: "Wait for merged code to deploy"
depends_on: [f2-merge]
action: wait_pipeline
project_id: "{{ .outputs.create-project.project_id }}"
max_attempts: 720
# --- Phase 10: Merge → Released ---
f2-archive:
description: "Archive task-management-ui feature"
depends_on: [f2-wait-merge-deploy]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/archive"
f2-transition-to-released:
description: "Transition to released phase"
depends_on: [f2-archive]
action: api
method: POST
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
body:
phase: "released"
outputs:
- final_phase: .data.phase
# ============================================================
# SECTION 5: VERIFICATION
# ============================================================
verify-site-live:
description: "Verify frontend and API are live after both features"
depends_on: [f2-transition-to-released]
action: shell
command: |
DOMAIN="{{ .outputs.create-project.domain }}"
# Check frontend
UI_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://$DOMAIN")
echo "Frontend status: $UI_STATUS"
# Check API health
API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://$DOMAIN/api/studio-api/health")
echo "API status: $API_STATUS"
if [ "$UI_STATUS" -ge 200 ] && [ "$UI_STATUS" -lt 400 ] && [ "$API_STATUS" -ge 200 ] && [ "$API_STATUS" -lt 400 ]; then
echo "Site is live: frontend and API responding"
exit 0
else
echo "Site check failed"
exit 1
fi
verify-sdlc-complete:
description: "Verify both features reached released phase"
depends_on: [verify-site-live]
action: shell
command: |
F1_PHASE="{{ .outputs.f1-transition-to-released.final_phase }}"
F2_PHASE="{{ .outputs.f2-transition-to-released.final_phase }}"
echo "Feature 1 (data-models): $F1_PHASE"
echo "Feature 2 (task-management-ui): $F2_PHASE"
if [ "$F1_PHASE" == "released" ] && [ "$F2_PHASE" == "released" ]; then
echo ""
echo "============================================================"
echo "SUCCESS: Foundary Studio lifecycle complete"
echo "============================================================"
echo "Both features traversed all 10 SDLC phases:"
echo " draft → specified → planned → ready → implementation →"
echo " review → audit → qa → merge → released"
echo ""
echo "Infrastructure: React + API + Postgres (batch provisioned)"
echo "Feature 1: Core Data Models & Persistence"
echo "Feature 2: Task Management UI (dependent on F1 schema)"
echo "============================================================"
exit 0
else
echo "FAIL: Expected both features at released"
exit 1
fi
teardown:
- action: api
method: DELETE
endpoint: "/project/{{ .outputs.create-project.project_id }}"