singularity-forge/gsd-orchestrator/workflows/build-from-spec.md
ace-pm b29c12d5e5 refactor(native): rename gsd_parser.rs to forge_parser.rs
Final rebrand: rename remaining Rust source file to complete the gsd → forge
transition. All parser references already use forge_parser after earlier commits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:58:21 +02:00

4.3 KiB

Build From Spec

End-to-end workflow: take a product idea or specification, produce working software.

Prerequisites

  • sf CLI installed (npm install -g sf-run)
  • A directory for the project (can be empty)
  • Git initialized in the directory

Process

Step 1: Prepare the project directory

PROJECT_DIR="/tmp/my-project-name"
mkdir -p "$PROJECT_DIR"
cd "$PROJECT_DIR"
git init 2>/dev/null  # SF needs a git repo

Step 2: Write the spec file

Write a spec file that describes what to build. More detail = better results.

cat > spec.md << 'SPEC'
# Product Name

## What
[Concrete description of what to build]

## Requirements
- [Specific, testable requirement 1]
- [Specific, testable requirement 2]
- [Specific, testable requirement 3]

## Technical Constraints
- [Language, framework, or platform requirements]
- [External services or APIs involved]
- [Performance or security requirements]

## Out of Scope
- [Things explicitly NOT included]
SPEC

Spec quality matters. Vague specs produce vague results. Include:

  • What the user can DO when it's done (not what code to write)
  • Technical constraints (language, framework, Node version)
  • What's out of scope (prevents scope creep)

Step 3: Launch the build

Fire-and-forget (simplest — SF does everything):

cd "$PROJECT_DIR"
RESULT=$(sf headless --output-format json --timeout 0 --context spec.md new-milestone --auto 2>/dev/null)
EXIT=$?

--timeout 0 disables the timeout for long builds. --auto chains milestone creation into execution.

With budget limit:

# Use step-by-step mode with budget checks instead of auto
# See workflows/step-by-step.md

For CI or ecosystem runs (no user config):

RESULT=$(sf headless --bare --output-format json --timeout 0 --context spec.md new-milestone --auto 2>/dev/null)
EXIT=$?

Step 4: Handle the result

case $EXIT in
  0)
    # Success — verify deliverables
    STATUS=$(echo "$RESULT" | jq -r '.status')
    COST=$(echo "$RESULT" | jq -r '.cost.total')
    COMMITS=$(echo "$RESULT" | jq -r '.commits | length')
    echo "Build complete: $STATUS, cost: \$$COST, commits: $COMMITS"

    # Inspect what was built
    sf headless query | jq '.state.progress'

    # Check the actual files
    ls -la "$PROJECT_DIR"
    ;;
  1)
    # Error — inspect and decide
    echo "Build failed"
    echo "$RESULT" | jq '{status: .status, phase: .phase}'

    # Check state for details
    sf headless query | jq '.state'
    ;;
  10)
    # Blocked — needs intervention
    echo "Build blocked — needs human input"
    sf headless query | jq '{phase: .state.phase, blockers: .state.blockers}'

    # Options: steer, supply answers, or escalate
    # See workflows/monitor-and-poll.md for blocker handling
    ;;
  11)
    echo "Build was cancelled"
    ;;
esac

Step 5: Verify deliverables

After a successful build, verify the output:

cd "$PROJECT_DIR"

# Check project state
sf headless query | jq '{
  phase: .state.phase,
  progress: .state.progress,
  cost: .cost.total
}'

# Check git log for what was built
git log --oneline

# Run the project's own tests if they exist
[ -f package.json ] && npm test 2>/dev/null
[ -f Makefile ] && make test 2>/dev/null

Complete Example

# 1. Setup
mkdir -p /tmp/todo-api && cd /tmp/todo-api && git init

# 2. Write spec
cat > spec.md << 'SPEC'
# Todo API

Build a REST API for managing todo items using Node.js and Express.

## Requirements
- GET /todos — list all todos
- POST /todos — create a todo (title, completed)
- PUT /todos/:id — update a todo
- DELETE /todos/:id — delete a todo
- Todos stored in-memory (no database)
- Input validation with descriptive error messages
- Health check endpoint at GET /health

## Technical Constraints
- Node.js with ESM modules
- Express framework
- No external database — in-memory array
- Port configurable via PORT env var (default 3000)

## Out of Scope
- Authentication
- Persistent storage
- Frontend
SPEC

# 3. Launch
RESULT=$(sf headless --output-format json --timeout 0 --context spec.md new-milestone --auto 2>/dev/null)
EXIT=$?

# 4. Report
if [ $EXIT -eq 0 ]; then
  COST=$(echo "$RESULT" | jq -r '.cost.total')
  echo "Build complete (\$$COST)"
  echo "Files created:"
  find . -not -path './.sf/*' -not -path './.git/*' -type f
else
  echo "Build failed (exit $EXIT)"
  echo "$RESULT" | jq .
fi