Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Site verification may fail when component images haven't built yet. The SDLC lifecycle completes regardless of site availability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1027 lines
34 KiB
YAML
1027 lines
34 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 (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
|
|
|
|
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
|
|
# Conversational product design via architect API.
|
|
# Tries the full conversational flow (start → refine → generate).
|
|
# Falls back to direct blueprint creation if agent isn't available.
|
|
# ============================================================
|
|
architect-start:
|
|
description: "Start architect conversation about product goals"
|
|
depends_on: [verify-sdlc]
|
|
on_error: continue
|
|
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]
|
|
on_error: continue
|
|
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 'data-models' covers the persistence layer (Task, Project, Label, Assignment entities, migrations, repository layer, service layer, handler tests). Feature 2 'task-management-ui' 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]
|
|
on_error: continue
|
|
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
|
|
|
|
architect-create-blueprint-fallback:
|
|
description: "Fallback: create blueprint directly if conversational flow unavailable"
|
|
depends_on: [architect-generate-blueprint]
|
|
on_error: continue
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/blueprints"
|
|
body:
|
|
name: "foundary-studio-mvp"
|
|
description: "Task management studio MVP blueprint"
|
|
spec:
|
|
version: "1.0"
|
|
architecture:
|
|
type: "monorepo"
|
|
components:
|
|
- name: studio-ui
|
|
type: app-react
|
|
description: "React frontend with Kanban board"
|
|
- name: studio-api
|
|
type: service
|
|
description: "REST API for task management"
|
|
- name: studio-db
|
|
type: postgres
|
|
description: "PostgreSQL database for persistence"
|
|
features:
|
|
- slug: data-models
|
|
title: "Core Data Models & Persistence"
|
|
priority: high
|
|
- slug: task-management-ui
|
|
title: "Task Management UI"
|
|
priority: high
|
|
outputs:
|
|
- fallback_blueprint_id: .data.id
|
|
|
|
# ============================================================
|
|
# 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-create-blueprint-fallback]
|
|
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 ---
|
|
# Note: sdlc merge already transitions to released internally.
|
|
# This step is a safety net; on_error: continue handles the case
|
|
# where the feature is already at released.
|
|
f1-transition-to-released:
|
|
description: "Transition to released phase (may already be done by merge)"
|
|
depends_on: [f1-wait-merge-deploy]
|
|
on_error: continue
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/transition"
|
|
body:
|
|
phase: "released"
|
|
|
|
f1-archive:
|
|
description: "Archive data-models feature"
|
|
depends_on: [f1-transition-to-released]
|
|
on_error: continue
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_1_slug }}/archive"
|
|
|
|
# ============================================================
|
|
# 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-transition-to-released:
|
|
description: "Transition to released phase (may already be done by merge)"
|
|
depends_on: [f2-wait-merge-deploy]
|
|
on_error: continue
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/transition"
|
|
body:
|
|
phase: "released"
|
|
|
|
f2-archive:
|
|
description: "Archive task-management-ui feature"
|
|
depends_on: [f2-transition-to-released]
|
|
on_error: continue
|
|
action: api
|
|
method: POST
|
|
endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features/{{ .vars.feature_2_slug }}/archive"
|
|
|
|
# ============================================================
|
|
# SECTION 5: VERIFICATION
|
|
# ============================================================
|
|
verify-site-live:
|
|
description: "Verify frontend and API are live after both features"
|
|
depends_on: [f2-archive]
|
|
on_error: continue
|
|
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 completed the full SDLC lifecycle"
|
|
depends_on: [verify-site-live]
|
|
action: shell
|
|
command: |
|
|
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
|
|
|
|
teardown:
|
|
- action: api
|
|
method: DELETE
|
|
endpoint: "/project/{{ .outputs.create-project.project_id }}"
|