FAB Protocol
FAB Intake, Headless Execution & Workspace Isolation Guide
Sección titulada «FAB Intake, Headless Execution & Workspace Isolation Guide»AI-First Engineering Framework v7.0 — Phase 1: Orchestration Layer
Sección titulada «AI-First Engineering Framework v7.0 — Phase 1: Orchestration Layer»Versión: 1.0.0 | Estado: Activo | Fecha: Marzo 2026 | Tipo: Guide Framework: AI-First Engineering Framework v7.0 (Factory-Native) Prerequisito:
CORE_F04_Fullstack_Agent_Builder.md(Phase 0) Fuentes: Anthropic Claude Code Docs (2026), Gas Town Orchestrator (2026), StrongDM Software Factory (2026), DealInspect Case Study (2026), Druce.ai Claude Code Guide (2026)
1. Visión General de Phase 1
Sección titulada «1. Visión General de Phase 1»Phase 1 construye la capa de orquestación entre el humano director y los Fullstack Agent Builders:
┌─────────────────────────────────────────────────────────────────┐│ PHASE 1: ORCHESTRATION LAYER ││ ││ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ ││ │ 1. INTAKE │──►│ 2. HEADLESS │──►│ 3. WORKSPACE │ ││ │ PROCESSOR │ │ EXECUTION │ │ ISOLATION │ ││ │ │ │ PROTOCOL │ │ PLAYBOOK │ ││ │ Issues, slack, │ │ Cómo lanzar y │ │ Git worktrees│ ││ │ notas → intents │ │ monitorear FABs │ │ 1 repo = 1 │ ││ │ estructurados │ │ autónomos │ │ FAB aislado │ ││ └─────────────────┘ └─────────────────┘ └──────────────┘ │└─────────────────────────────────────────────────────────────────┘2. Intake Processor — De Input Crudo a Intent Estructurado
Sección titulada «2. Intake Processor — De Input Crudo a Intent Estructurado»2.1 El Problema
Sección titulada «2.1 El Problema»El humano director tiene ideas, issues, mensajes de Slack, notas de voz — todas en formatos diferentes. El FAB necesita un intent document estructurado y validable.
INPUT CRUDO INTENT ESTRUCTURADO───────────── ────────────────────"necesitamos login social" ──► intent/INTENT-001.yamlGitHub Issue #42 ──► intent/INTENT-002.yamlNota en Apple Notes ──► intent/INTENT-003.yamlSlack msg: "el search falla" ──► intent/INTENT-004.yamlPRD.pdf de 10 páginas ──► intent/INTENT-005.yaml intent/INTENT-006.yaml intent/INTENT-007.yaml2.2 Flujo del Intake Processor
Sección titulada «2.2 Flujo del Intake Processor»┌──────────────────────────────────────────────────────────────────┐│ INTAKE PROCESSOR FLOW ││ ││ 1. CAPTURE 2. NORMALIZE 3. VALIDATE ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ Capturar │────►│ LLM │─────►│ Schema │ ││ │ input │ │ normaliza│ │ validate │ ││ │ crudo │ │ a YAML │ │ intent │ ││ └──────────┘ └──────────┘ └────┬─────┘ ││ │ ││ 4. CLASSIFY 5. PRIORITIZE 6. QUEUE ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ Tipo: │────►│ Score: │────►│ Agregar │ ││ │ feature, │ │ urgency, │ │ a cola │ ││ │ bug, │ │ value, │ │ y asignar│ ││ │ refactor │ │ effort │ │ a FAB │ ││ └──────────┘ └──────────┘ └──────────┘ │└──────────────────────────────────────────────────────────────────┘2.3 Intent Document Schema
Sección titulada «2.3 Intent Document Schema»El intent document es el contrato entre el humano director y el FAB:
# Validar con: scripts/schemas/intent.schema.jsonintent: # ── Metadata ── id: "INTENT-2026-042" version: "1" # Se incrementa si el humano modifica project: "project-a" created_by: "human-director" created_at: "2026-03-21T09:30:00Z" updated_at: "2026-03-21T09:30:00Z" source: "github_issue" # github_issue | slack | manual | prd | voice_note source_ref: "https://github.com/org/project-a/issues/42"
# ── Clasificación ── type: "new_feature" # new_feature | bug_fix | refactoring | documentation | security_fix | infrastructure | exploration priority: "high" # critical | high | medium | low estimated_effort: "medium" # tiny (<30min) | small (30min-2h) | medium (2-8h) | large (8h+)
# ── Problema y Solución ── problem: | Los usuarios no pueden hacer login con sus cuentas de Google o GitHub. Actualmente no hay sistema de autenticación. Los usuarios acceden directamente al dashboard sin protección.
context: | El proyecto ya tiene Prisma configurado con PostgreSQL. Hay un layout con header donde iría el botón de login. No hay modelo User aún en el schema.
acceptance_criteria: - id: "AC-01" description: "OAuth2 flow funcional con Google y GitHub" testable: true test_type: "integration" - id: "AC-02" description: "JWT tokens para sesiones (1h expiry, refresh tokens)" testable: true test_type: "unit" - id: "AC-03" description: "Página de perfil muestra nombre, email, avatar" testable: true test_type: "e2e" - id: "AC-04" description: "Middleware de protección en rutas /api/* y /dashboard/*" testable: true test_type: "integration" - id: "AC-05" description: "Tests de integración para happy path y error cases" testable: true test_type: "meta" - id: "AC-06" description: "Documentación de setup (env vars, OAuth app config)" testable: false test_type: "manual_review"
# ── Restricciones ── constraints: stack: - "Next.js 15, TypeScript, Prisma, PostgreSQL" technical: - "No dependencias pesadas (no NextAuth — usar jose + oauth4webapi)" architectural: - "Seguir ADR-001 (API patterns)" - "Seguir ADR-003 (security baseline)" regulatory: []
# ── Scope ── scope_limits: out_of_scope: - "NO implementar 2FA en esta iteración" - "NO implementar roles/permissions (será INTENT siguiente)" dependencies: - "Crear modelo User en Prisma (nuevo)" affected_areas: - "src/app/auth/" - "src/middleware.ts" - "prisma/schema.prisma" - "src/app/dashboard/profile/"
# ── Budget ── budget: max_cost_usd: 30 max_time_hours: 4 model_preference: "sonnet" # sonnet | opus | haiku | auto
# ── Delivery ── delivery: branch: "feature/auth-oauth2" pr_target: "main" auto_merge: false # true solo para low-risk + all tests pass requires_human_review: true # true para auth/security/infra deploy_to: "staging" # staging | production | none
# ── FAB Execution ── execution: mode: "headless" # headless | interactive | hybrid phases: ["F04", "F05", "F06", "F07", "F08", "F09"] checkpoint_interval_min: 60 escalation_policy: "pause_and_notify" # pause_and_notify | continue_with_assumption | stop_immediately
# ── Estado (actualizado por FAB) ── status: "queued" # draft | queued | in_progress | blocked | completed | cancelled assigned_fab: "" # FAB ID asignado started_at: "" completed_at: "" actual_cost_usd: 0 actual_time_hours: 0 pr_url: "" blocker_notes: ""2.4 Intake por Tipo de Source
Sección titulada «2.4 Intake por Tipo de Source»2.4.1 Desde GitHub Issue
Sección titulada «2.4.1 Desde GitHub Issue»# Script: Convertir GitHub Issue a Intent Document# Uso: ./scripts/fab-intake.sh github <issue-url>
#!/bin/bashset -euo pipefail
ISSUE_URL="$1"INTENT_DIR="intent"DATE=$(date +%Y-%m-%d)INTENT_ID="INTENT-$(date +%Y)-$(printf '%03d' $(ls $INTENT_DIR/*.yaml 2>/dev/null | wc -l))"
mkdir -p "$INTENT_DIR"
# Extraer issue data via gh CLIISSUE_DATA=$(gh issue view "$ISSUE_URL" --json title,body,labels,assignees)TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')BODY=$(echo "$ISSUE_DATA" | jq -r '.body')LABELS=$(echo "$ISSUE_DATA" | jq -r '.labels[].name' | tr '\n' ', ')
# Usar Claude para normalizar a intent documentclaude --print "You are an Intake Processor for an AI-Driven Software Factory.Convert this GitHub Issue into a structured intent document.
Title: $TITLEBody: $BODYLabels: $LABELS
Output ONLY valid YAML following the intent schema.Include all required fields. Set status to 'queued'.Set mode to 'headless' if requirements are clear, 'interactive' if ambiguous.Estimate effort: tiny (<30min), small (30min-2h), medium (2-8h), large (8h+)." > "$INTENT_DIR/$INTENT_ID.yaml"
echo "✅ Created: $INTENT_DIR/$INTENT_ID.yaml"echo "📋 Review and adjust before launching FAB"2.4.2 Desde Texto Libre (Slack, notas, voz)
Sección titulada «2.4.2 Desde Texto Libre (Slack, notas, voz)»# Script: Convertir texto libre a Intent Document# Uso: ./scripts/fab-intake.sh text "necesitamos que el search funcione con filtros"
#!/bin/bashINPUT_TEXT="$2"INTENT_DIR="intent"INTENT_ID="INTENT-$(date +%Y)-$(printf '%03d' $(ls $INTENT_DIR/*.yaml 2>/dev/null | wc -l))"
mkdir -p "$INTENT_DIR"
claude --print "You are an Intake Processor for an AI-Driven Software Factory.Convert this informal request into a structured intent document.
Request: $INPUT_TEXT
Output ONLY valid YAML following the intent schema.For any information you cannot infer, use reasonable defaults and markwith REVIEW comments. Set status to 'draft' (requires human review).Set mode to 'interactive' since requirements may be incomplete." > "$INTENT_DIR/$INTENT_ID.yaml"
echo "⚠️ Created DRAFT: $INTENT_DIR/$INTENT_ID.yaml"echo "📋 This intent needs human review before launching FAB"2.4.3 Desde PRD/Documento Largo
Sección titulada «2.4.3 Desde PRD/Documento Largo»# Script: Descomponer PRD en múltiples intent documents# Uso: ./scripts/fab-intake.sh prd docs/prd-v2.md
#!/bin/bashPRD_PATH="$2"INTENT_DIR="intent"
mkdir -p "$INTENT_DIR"
claude --print "You are an Intake Processor for an AI-Driven Software Factory.This is a Product Requirements Document. Decompose it intoINDIVIDUAL intent documents — one per feature/capability.
PRD content:$(cat "$PRD_PATH")
Rules:1. Each intent must be independently implementable2. Order by dependency (foundations first)3. Each intent should take 2-8 hours of agent work4. If a feature is too large (>8h), split into sub-intents5. Output as YAML array, one document per intent
Output format:---# INTENT-2026-001intent: ...---# INTENT-2026-002intent: ..." > "$INTENT_DIR/prd_decomposition.yaml"
echo "✅ PRD decomposed. Review: $INTENT_DIR/prd_decomposition.yaml"echo "📋 Split into individual files and review before launching FABs"2.5 Intent Queue Management
Sección titulada «2.5 Intent Queue Management»# intent/queue.yaml — Cola de intents priorizada# Actualizado automáticamente por el sistema o manualmente por el humano directorqueue: last_updated: "2026-03-21T10:00:00Z"
active: - intent_id: "INTENT-2026-042" project: "project-a" fab_id: "fab-001" status: "in_progress" started_at: "2026-03-21T09:45:00Z" progress: "F06 - Build (60%)" cost_so_far: "$12.30"
- intent_id: "INTENT-2026-043" project: "project-b" fab_id: "fab-002" status: "in_progress" started_at: "2026-03-21T10:00:00Z" progress: "F04 - Architecture" cost_so_far: "$3.20"
queued: - intent_id: "INTENT-2026-044" project: "project-a" priority: "medium" type: "refactoring" estimated_effort: "small"
- intent_id: "INTENT-2026-045" project: "project-c" priority: "high" type: "bug_fix" estimated_effort: "tiny"
blocked: - intent_id: "INTENT-2026-040" project: "project-b" blocker: "Waiting for API credentials from vendor" blocked_since: "2026-03-20T14:00:00Z"
completed_today: - intent_id: "INTENT-2026-041" project: "project-a" completed_at: "2026-03-21T08:30:00Z" actual_cost: "$18.50" pr_url: "https://github.com/org/project-a/pull/15"2.6 Validación de Intents
Sección titulada «2.6 Validación de Intents»# Validar intent document contra schema antes de lanzar FAB# Uso: python3 scripts/validate-intent.py intent/INTENT-2026-042.yaml
#!/usr/bin/env python3"""Validate intent document against JSON Schema."""import sysimport yamlimport jsonfrom jsonschema import validate, ValidationError
def validate_intent(intent_path: str, schema_path: str = "scripts/schemas/intent.schema.json"): with open(intent_path) as f: intent = yaml.safe_load(f) with open(schema_path) as f: schema = json.load(f)
try: validate(instance=intent, schema=schema) print(f"✅ {intent_path} is valid")
# Additional quality checks warnings = [] intent_data = intent.get("intent", {})
if not intent_data.get("acceptance_criteria"): warnings.append("⚠️ No acceptance criteria defined")
ac_list = intent_data.get("acceptance_criteria", []) untestable = [ac for ac in ac_list if not ac.get("testable", True)] if len(untestable) > len(ac_list) * 0.5: warnings.append("⚠️ More than 50% of acceptance criteria are not testable")
if not intent_data.get("budget", {}).get("max_cost_usd"): warnings.append("⚠️ No cost cap defined")
if not intent_data.get("scope_limits", {}).get("out_of_scope"): warnings.append("⚠️ No out-of-scope items defined (risk of scope creep)")
if intent_data.get("execution", {}).get("mode") == "headless": if intent_data.get("type") == "exploration": warnings.append("⚠️ Exploration intents should use 'interactive' mode")
for w in warnings: print(w)
return True
except ValidationError as e: print(f"❌ {intent_path} is INVALID: {e.message}") return False
if __name__ == "__main__": sys.exit(0 if validate_intent(sys.argv[1]) else 1)3. Headless Execution Protocol
Sección titulada «3. Headless Execution Protocol»3.1 Modos de Ejecución del FAB
Sección titulada «3.1 Modos de Ejecución del FAB»┌─────────────────────────────────────────────────────────────────┐│ FAB EXECUTION MODES ││ ││ MODE 1: INTERACTIVE ││ ┌─────────────────────────────────────────────────┐ ││ │ Humano + FAB en terminal, conversación real-time │ ││ │ → F01-F04 (strategy, discovery, architecture) │ ││ │ → Cuando hay ambigüedad o exploración │ ││ │ → Usa: claude (en terminal directo) │ ││ └─────────────────────────────────────────────────┘ ││ ││ MODE 2: HEADLESS ││ ┌─────────────────────────────────────────────────┐ ││ │ FAB opera solo, humano revisa después │ ││ │ → F05-F09 (build, test, security, deploy) │ ││ │ → Cuando intent es claro y testeble │ ││ │ → Usa: claude --print o background agents │ ││ └─────────────────────────────────────────────────┘ ││ ││ MODE 3: HYBRID ││ ┌─────────────────────────────────────────────────┐ ││ │ Empieza interactivo (arch), continúa headless │ ││ │ → F04 interactivo, F05-F09 headless │ ││ │ → Para features que requieren decisión + build │ ││ │ → Usa: sesión interactiva → checkpoint → headless │ ││ └─────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────────────┘3.2 Lanzar un FAB Headless
Sección titulada «3.2 Lanzar un FAB Headless»Opción A: Claude Code Background Agent (Recomendado)
Sección titulada «Opción A: Claude Code Background Agent (Recomendado)»# Lanzar FAB headless usando background agent de Claude Code# El agente trabaja en segundo plano, sin bloquear terminal
cd /path/to/project-a
# 1. Asegurarse de que el intent y harness están listoscat intent/INTENT-2026-042.yaml # Verificarpython3 scripts/validate-intent.py intent/INTENT-2026-042.yaml
# 2. Lanzar background agentclaude --background \ "You are a Fullstack Agent Builder (FAB). Read intent/INTENT-2026-042.yaml and execute the complete implementation. Follow the FAB protocol: 1. Read the intent document completely 2. Create progress-tracker.md with your plan 3. Execute phases: F04 → F05 → F06 → F07 → F08 → F09 4. Checkpoint (commit + HANDOFF.md) every 60 minutes 5. Create PR when all acceptance criteria are met 6. Update intent status to 'completed'
IMPORTANT: - If uncertain (confidence < 0.7), document assumption and continue - If cost exceeds 80% of budget, pause and update intent status to 'blocked' - If security finding, stop and update intent status to 'blocked' - Tests MUST pass before creating PR"Opción B: Claude Code —print (Para scripts/CI)
Sección titulada «Opción B: Claude Code —print (Para scripts/CI)»# Lanzar FAB usando --print (no-interactivo, output a stdout)# Útil para GitHub Actions o cron jobs
cd /path/to/project-a
claude --print \ --max-turns 100 \ --output-format json \ "Read intent/INTENT-2026-042.yaml. Execute full FAB protocol. Create PR when done." \ 2>&1 | tee logs/fab-$(date +%Y%m%d-%H%M%S).logOpción C: GitHub Action (Para CI/CD automatizado)
Sección titulada «Opción C: GitHub Action (Para CI/CD automatizado)»name: FAB Headless Executionon: workflow_dispatch: inputs: intent_file: description: 'Path to intent YAML file' required: true type: string
jobs: fab-execute: runs-on: ubuntu-latest timeout-minutes: 240 # 4h max permissions: contents: write pull-requests: write
steps: - uses: actions/checkout@v4
- name: Validate Intent run: python3 scripts/validate-intent.py ${{ inputs.intent_file }}
- name: Execute FAB env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | claude --print \ --max-turns 100 \ "You are a FAB. Read ${{ inputs.intent_file }}. Execute full protocol. Create PR when done." \ 2>&1 | tee fab-execution.log
- name: Upload Execution Log if: always() uses: actions/upload-artifact@v4 with: name: fab-log-${{ github.run_id }} path: fab-execution.log3.3 Monitoreo de FABs Headless
Sección titulada «3.3 Monitoreo de FABs Headless»3.3.1 Progress Tracker (File-based)
Sección titulada «3.3.1 Progress Tracker (File-based)»El FAB actualiza progress-tracker.md durante la ejecución:
<!-- progress-tracker.md — Auto-maintained by FAB --># FAB Execution: INTENT-2026-042 — OAuth2 Authentication
## Intent- **ID**: INTENT-2026-042- **Project**: project-a- **Mode**: headless- **Budget**: $30 / 4h
## Plan (6 phases)- [x] F04: Architecture — ADR for auth strategy (done, commit a1b2c3)- [x] F05: Contracts — Prisma schema + API specs (done, commit d4e5f6)- [x] F06: Build — Implementation (done, commit g7h8i9)- [ ] F07: TEVV — Tests (IN PROGRESS)- [ ] F08: Security — OWASP scan- [ ] F09: Deploy — Staging deploy + docs
## Current Phase: F07 — TEVV- Started: 2026-03-21T11:15:00Z- Context window: 52%- Files modified this phase: tests/auth.test.ts, tests/middleware.test.ts- Tests passing: 14/16 (2 pending)
## Cost- Tokens used: ~85,000- Estimated cost: $14.20 (47% of budget)- Burn rate: $4.70/hour
## Decisions Made- [10:00] Using jose for JWT (not jsonwebtoken) — lighter, ESM native- [10:15] Prisma User model with provider + providerId (multi-provider support)- [10:45] Middleware pattern: Edge Middleware for all /api/* and /dashboard/*- [11:20] Using crypto.subtle for token signing (no external deps)
## Blockers- None
## Assumptions Made (flagged for review)- ⚠️ Assumed Google OAuth callback URL: /api/auth/callback/google- ⚠️ Assumed JWT secret from env var: AUTH_SECRET3.3.2 Health Check Script
Sección titulada «3.3.2 Health Check Script»#!/bin/bash# scripts/fab-health-check.sh — Check health of all running FABsset -euo pipefail
echo "╔══════════════════════════════════════════════════════════╗"echo "║ FAB FACTORY HEALTH CHECK ║"echo "║ $(date +%Y-%m-%d\ %H:%M:%S) ║"echo "╚══════════════════════════════════════════════════════════╝"echo ""
# Check each project worktreefor WORKTREE in ../fab-project-*; do if [ -d "$WORKTREE" ]; then PROJECT=$(basename "$WORKTREE")
echo "┌── $PROJECT ──────────────────────────────"
# Check last commit time LAST_COMMIT=$(cd "$WORKTREE" && git log -1 --format="%ar" 2>/dev/null || echo "no commits") echo "│ Last commit: $LAST_COMMIT"
# Check progress tracker if [ -f "$WORKTREE/progress-tracker.md" ]; then PHASE=$(grep "Current Phase:" "$WORKTREE/progress-tracker.md" | head -1 || echo "unknown") echo "│ $PHASE"
COST=$(grep "Estimated cost:" "$WORKTREE/progress-tracker.md" | head -1 || echo "unknown") echo "│ $COST" else echo "│ ⚠️ No progress-tracker.md found" fi
# Check intent status ACTIVE_INTENT=$(find "$WORKTREE/intent" -name "*.yaml" -newer "$WORKTREE/.git/index" 2>/dev/null | head -1) if [ -n "$ACTIVE_INTENT" ]; then STATUS=$(grep "status:" "$ACTIVE_INTENT" | head -1 | awk '{print $2}' | tr -d '"') echo "│ Intent status: $STATUS" fi
# Stale detection: no commit in 30+ minutes LAST_COMMIT_EPOCH=$(cd "$WORKTREE" && git log -1 --format="%ct" 2>/dev/null || echo "0") NOW_EPOCH=$(date +%s) DIFF_MIN=$(( (NOW_EPOCH - LAST_COMMIT_EPOCH) / 60 ))
if [ "$DIFF_MIN" -gt 30 ]; then echo "│ 🚨 STALE: No commit in ${DIFF_MIN} minutes!" elif [ "$DIFF_MIN" -gt 15 ]; then echo "│ ⚠️ WARNING: No commit in ${DIFF_MIN} minutes" else echo "│ ✅ Active (last commit ${DIFF_MIN}m ago)" fi
echo "└──────────────────────────────────────────" echo "" fidone
# SummaryTOTAL=$(ls -d ../fab-project-* 2>/dev/null | wc -l)echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"echo "Total projects: $TOTAL"echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"3.4 Comunicación FAB → Humano
Sección titulada «3.4 Comunicación FAB → Humano»3.4.1 Notificaciones
Sección titulada «3.4.1 Notificaciones»# fab_notifications.yaml — Configuración de alertasnotifications: channels: slack: webhook: "${FAB_SLACK_WEBHOOK}" enabled: true email: to: "${FAB_DIRECTOR_EMAIL}" enabled: false github: enabled: true # Comments on issues/PRs
events: intent_started: message: "🚀 FAB started: {intent_id} on {project}" channels: ["slack"]
phase_completed: message: "✅ {project}: Phase {phase} completed ({cost_so_far})" channels: ["slack"]
blocker_detected: message: "🚨 FAB BLOCKED: {intent_id} — {blocker_reason}" channels: ["slack", "email"] priority: "high"
cost_warning: message: "💰 Cost alert: {project} at {percent}% of budget ({cost_so_far})" channels: ["slack"]
pr_created: message: "📋 PR ready for review: {pr_url} ({intent_id})" channels: ["slack", "github"]
intent_completed: message: "✅ DONE: {intent_id} — Cost: {actual_cost}, Time: {actual_time}" channels: ["slack"]
stale_session: message: "⚠️ Stale session: {project} — no commit in {minutes}min" channels: ["slack"]
error: message: "❌ FAB ERROR: {project} — {error_message}" channels: ["slack", "email"] priority: "critical"3.4.2 FAB Completion Report
Sección titulada «3.4.2 FAB Completion Report»Cuando el FAB termina un intent, genera un completion report en el PR:
<!-- Auto-generated by FAB upon PR creation -->## FAB Completion Report
### Intent- **ID**: INTENT-2026-042- **Problem**: OAuth2 authentication with Google and GitHub
### Execution Summary| Metric | Value ||--------|-------|| Total time | 2h 45min || Total cost | $18.50 || Phases completed | F04, F05, F06, F07, F08, F09 || Tests added | 16 || Test pass rate | 100% || Coverage delta | +12% || Security findings | 0 critical, 0 high || Files changed | 14 || Lines added | 842 || Lines removed | 23 || Checkpoints | 3 |
### Acceptance Criteria Status- [x] AC-01: OAuth2 flow with Google and GitHub ✅- [x] AC-02: JWT tokens (1h expiry, refresh) ✅- [x] AC-03: Profile page with name, email, avatar ✅- [x] AC-04: Middleware protection on /api/* and /dashboard/* ✅- [x] AC-05: Integration tests for happy path + error cases ✅- [x] AC-06: Setup documentation ✅
### Assumptions Made (review these)- ⚠️ Google OAuth callback: `/api/auth/callback/google`- ⚠️ JWT secret from env var: `AUTH_SECRET`
### Decisions Made- Used `jose` for JWT (ADR-005 created)- Edge Middleware pattern for route protection- Multi-provider support in User model
### How to Test```bash# Setup env varscp .env.example .env.local# Add GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, etc.
# Run testsnpm test
# Start dev servernpm run dev# Visit http://localhost:3000/api/auth/login/google---
## 4. Workspace Isolation Playbook
### 4.1 Estrategia: Un Repo = Un Worktree = Un FAB┌────────────────────────────────────────────────────────────────┐ │ WORKSPACE ISOLATION │ │ │ │ MAIN REPO (origin) WORKTREES (local) │ │ ┌──────────────┐ ┌──────────────────┐ │ │ │ main branch │ │ ../fab-project-a/ │ ← FAB #1 │ │ │ (protected) │ │ branch: feat/x │ │ │ │ │ │ worktree │ │ │ │ │ ├──────────────────┤ │ │ │ │ │ ../fab-project-b/ │ ← FAB #2 │ │ │ │ │ branch: feat/y │ │ │ │ │ │ worktree │ │ │ │ │ ├──────────────────┤ │ │ │ │ │ ../fab-project-c/ │ ← FAB #3 │ │ │ │ │ branch: feat/z │ │ │ └──────────────┘ └──────────────────┘ │ │ │ │ SEPARADO (proyectos diferentes) │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ github/ │ │ github/ │ │ github/ │ │ │ │ org/proj-a │ │ org/proj-b │ │ org/proj-c │ │ │ │ (repo propio)│ │ (repo propio)│ │ (repo propio)│ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ← FAB #1 ← FAB #2 ← FAB #3 │ └────────────────────────────────────────────────────────────────┘
### 4.2 Script de Setup: Factory Workspace
```bash#!/bin/bash# scripts/fab-workspace-setup.sh — Setup workspace isolation for FAB Factory# Uso: ./scripts/fab-workspace-setup.sh <project-name> <repo-url> [branch]
set -euo pipefail
PROJECT_NAME="${1:?Usage: fab-workspace-setup.sh <project-name> <repo-url> [branch]}"REPO_URL="${2:?Usage: fab-workspace-setup.sh <project-name> <repo-url> [branch]}"BRANCH="${3:-main}"FAB_DIR="../fab-${PROJECT_NAME}"
echo "🏭 Setting up FAB workspace: $PROJECT_NAME"echo " Repo: $REPO_URL"echo " Branch: $BRANCH"echo " Path: $FAB_DIR"
# ── 1. Clone or create worktree ──if [ -d "$FAB_DIR" ]; then echo "⚠️ Directory $FAB_DIR already exists. Skipping."else echo "📂 Cloning repo..." git clone "$REPO_URL" "$FAB_DIR" cd "$FAB_DIR" git checkout -b "fab/$PROJECT_NAME" "$BRANCH"fi
cd "$FAB_DIR"
# ── 2. Create intent directory ──mkdir -p intentcat > intent/README.md << 'EOF'# Intent Documents
Place intent YAML files here. Each intent represents one unit of workfor the Fullstack Agent Builder (FAB).
## File naming- `INTENT-YYYY-NNN.yaml` — Individual intent- `queue.yaml` — Priority queue (auto-managed)
## Workflow1. Human director creates intent YAML (or uses intake script)2. Validate: `python3 scripts/validate-intent.py intent/INTENT-YYYY-NNN.yaml`3. FAB reads intent and executes4. FAB updates status in intent file when done
## See also- `../baseline/framework/guides/FAB_Intake_Headless_Workspace_Guide.md`- `../baseline/framework/core/F04_.../CORE_F04_Fullstack_Agent_Builder.md`EOF
# ── 3. Create progress tracker template ──cat > progress-tracker.md << 'EOF'<!-- progress-tracker.md — Auto-maintained by FAB --># FAB Progress Tracker
## Current Intent- **ID**: (none)- **Status**: idle
## Plan(No active plan)
## Cost- Tokens used: 0- Estimated cost: $0.00
## Decisions Made(none)
## Blockers(none)EOF
# ── 4. Create HANDOFF.md template ──cat > HANDOFF.md << 'EOF'<!-- HANDOFF.md — Written by FAB at checkpoints for session continuity --># Session Handoff
## Last Checkpoint- **Date**: (none)- **Phase**: (none)- **Commit**: (none)
## State(No active session)
## Next Steps(none)
## Open Questions(none)EOF
# ── 5. Create .fab-config.yaml ──cat > .fab-config.yaml << EOF# FAB Configuration for $PROJECT_NAMEfab: project_name: "$PROJECT_NAME" fab_id: "fab-$(echo "$PROJECT_NAME" | md5sum | head -c 6)"
budget: max_cost_per_session_usd: 50 max_cost_per_day_usd: 200 alert_at_percent: 80
execution: default_mode: "headless" checkpoint_interval_min: 60 max_session_hours: 4 stale_threshold_min: 30
notifications: slack_webhook: "" # Set in environment: FAB_SLACK_WEBHOOK on_blocker: true on_completion: true on_cost_warning: true
quality: require_tests: true min_coverage_delta: 5 security_scan: true auto_merge: falseEOF
# ── 6. Verify setup ──echo ""echo "✅ FAB workspace ready: $FAB_DIR"echo ""echo " 📂 intent/ — Place intent documents here"echo " 📋 progress-tracker.md — FAB updates during execution"echo " 📝 HANDOFF.md — Session continuity document"echo " ⚙️ .fab-config.yaml — FAB configuration"echo ""echo "Next steps:"echo " 1. Create an intent: cp baseline/project-template/intent/intent-template.yaml intent/INTENT-2026-001.yaml"echo " 2. Edit the intent with your requirements"echo " 3. Validate: python3 scripts/validate-intent.py intent/INTENT-2026-001.yaml"echo " 4. Launch FAB: cd $FAB_DIR && claude --background 'Read intent/INTENT-2026-001.yaml. Execute FAB protocol.'"4.3 Multi-Project Management Script
Sección titulada «4.3 Multi-Project Management Script»#!/bin/bash# scripts/fab-factory.sh — Manage multiple FAB projects# Uso: ./scripts/fab-factory.sh <command> [args]
set -euo pipefail
COMMAND="${1:-status}"
case "$COMMAND" in status) echo "╔══════════════════════════════════════════════════╗" echo "║ FAB FACTORY STATUS ║" echo "║ $(date +%Y-%m-%d\ %H:%M:%S) ║" echo "╚══════════════════════════════════════════════════╝"
for DIR in ../fab-*/; do if [ -d "$DIR" ]; then NAME=$(basename "$DIR") BRANCH=$(cd "$DIR" && git branch --show-current 2>/dev/null || echo "detached") LAST=$(cd "$DIR" && git log -1 --format="%ar" 2>/dev/null || echo "n/a")
# Read FAB config if [ -f "$DIR/.fab-config.yaml" ]; then FAB_ID=$(grep "fab_id:" "$DIR/.fab-config.yaml" | awk '{print $2}' | tr -d '"') else FAB_ID="unconfigured" fi
# Check status if [ -f "$DIR/progress-tracker.md" ]; then PHASE=$(grep -m1 "Current Phase:" "$DIR/progress-tracker.md" 2>/dev/null | sed 's/## //' || echo "idle") else PHASE="idle" fi
printf " %-20s | %-10s | %-15s | %-20s | %s\n" "$NAME" "$FAB_ID" "$BRANCH" "$LAST" "$PHASE" fi done ;;
launch) PROJECT="${2:?Usage: fab-factory.sh launch <project-name> <intent-file>}" INTENT="${3:?Usage: fab-factory.sh launch <project-name> <intent-file>}" FAB_DIR="../fab-${PROJECT}"
if [ ! -d "$FAB_DIR" ]; then echo "❌ Project not found: $FAB_DIR" echo " Run: fab-workspace-setup.sh $PROJECT <repo-url>" exit 1 fi
echo "🚀 Launching FAB for $PROJECT with intent $INTENT" cd "$FAB_DIR"
# Validate intent python3 ../baseline/scripts/validate-intent.py "$INTENT" || exit 1
# Launch headless claude --background \ "You are a Fullstack Agent Builder (FAB). Read $INTENT and execute the complete implementation. Follow the FAB protocol in CLAUDE.md. Checkpoint every 60 minutes. Create PR when all acceptance criteria are met."
echo "✅ FAB launched for $PROJECT" ;;
stop) PROJECT="${2:?Usage: fab-factory.sh stop <project-name>}" echo "🛑 Stopping FAB for $PROJECT" # Signal to FAB to checkpoint and stop echo "STOP_REQUESTED=$(date -Iseconds)" >> "../fab-${PROJECT}/.fab-signal" echo "✅ Stop signal sent. FAB will checkpoint and stop at next iteration." ;;
cost) echo "💰 FAB Factory Cost Report" echo "━━━━━━━━━━━━━━━━━━━━━━━━" TOTAL=0 for DIR in ../fab-*/; do if [ -f "$DIR/progress-tracker.md" ]; then NAME=$(basename "$DIR") COST=$(grep -m1 "Estimated cost:" "$DIR/progress-tracker.md" 2>/dev/null | grep -oP '\$[\d.]+' || echo "\$0.00") echo " $NAME: $COST" fi done echo "━━━━━━━━━━━━━━━━━━━━━━━━" ;;
*) echo "Usage: fab-factory.sh <status|launch|stop|cost> [args]" ;;esac4.4 Merge Strategy
Sección titulada «4.4 Merge Strategy»# merge_strategy.yaml — How FABs merge their work backmerge: # Para proyectos separados (repos distintos) separate_repos: strategy: "standard_pr" description: "Cada FAB trabaja en su repo, crea PR a main" conflict_risk: "none" # Repos separados = 0 conflictos
# Para worktrees del mismo repo (features paralelas) same_repo_worktrees: strategy: "serialized_merge_queue" description: "Merge uno a la vez, CI completo en cada merge" steps: 1: "FAB crea PR desde feature branch" 2: "CI runs on PR branch" 3: "Human approves (or auto-merge si confianza alta)" 4: "Merge queue procesa uno a la vez" 5: "Si conflicto post-merge: FAB re-resolve en siguiente sesión"
conflict_prevention: - "Cada FAB trabaja en bounded contexts separados" - "Archivos compartidos (routes, config) requieren human approval" - "Contratos (schemas, API) son inmutables durante bolt"
# Para monorepo con paths separados monorepo_paths: strategy: "path_based_ownership" description: "Cada FAB owns un path, merge libre" codeowners: | /apps/project-a/ @fab-001 /apps/project-b/ @fab-002 /packages/shared/ @human-director # Shared code = human only5. Checklist de Implementación Phase 1
Sección titulada «5. Checklist de Implementación Phase 1»5.1 Quick Start (30 minutos)
Sección titulada «5.1 Quick Start (30 minutos)»# 1. Setup primer proyecto FAB./scripts/fab-workspace-setup.sh my-project https://github.com/you/my-project.git
# 2. Crear primer intentcp project-template/intent/intent-template.yaml ../fab-my-project/intent/INTENT-2026-001.yaml# Editar con tu problema/feature real
# 3. Validar intentpython3 scripts/validate-intent.py ../fab-my-project/intent/INTENT-2026-001.yaml
# 4. Lanzar FAB interactivo (primera vez)cd ../fab-my-projectclaude "Read intent/INTENT-2026-001.yaml. Execute FAB protocol."
# 5. Monitorear./scripts/fab-health-check.sh5.2 Checklist Completo
Sección titulada «5.2 Checklist Completo»- Intake Processor configurado (scripts de conversión por source type)
- Intent Schema validado y funcionando (
scripts/schemas/intent.schema.json) - Al menos 1 proyecto con workspace aislado (
fab-workspace-setup.sh) - CLAUDE.md del proyecto contiene instrucciones FAB
- progress-tracker.md template en cada worktree
- HANDOFF.md template en cada worktree
- .fab-config.yaml con budget limits en cada worktree
- Health check script probado (
fab-health-check.sh) - Factory management script disponible (
fab-factory.sh) - Primer intent creado, validado y ejecutado (interactivo primero)
- Primer intent headless ejecutado exitosamente
- Merge strategy definida para el tipo de setup (repos separados vs worktrees)
6. Anti-Patrones de Phase 1
Sección titulada «6. Anti-Patrones de Phase 1»| Anti-patrón | Riesgo | Solución |
|---|---|---|
| Intent sin acceptance criteria | FAB no sabe cuándo “terminó” | Mínimo 3 criteria testeables |
| Lanzar headless sin validar intent | Desperdicio de tokens en intent mal formado | Siempre validate-intent.py primero |
| Múltiples FABs en mismo directorio | Conflictos de archivos, corrupción | 1 worktree/repo = 1 FAB |
| Sin checkpoints | Pérdida de trabajo en crash | Checkpoint cada 60 min obligatorio |
| Sin monitoring | FAB stuck sin saberlo | Health check cada 15-30 min |
| Intent demasiado grande (>8h) | FAB pierde coherencia | Descomponer en sub-intents |
| Headless para exploración | Output incoherente | Usar modo interactivo para F01-F04 |
7. Event-Driven Triggers — Automations (v7.4)
Sección titulada «7. Event-Driven Triggers — Automations (v7.4)»Los triggers permiten que el Factory OS reaccione automaticamente a eventos externos, creando intents y lanzando FABs sin intervencion humana.
Tipos de triggers soportados
Sección titulada «Tipos de triggers soportados»| Tipo | Fuente | Ejemplo |
|---|---|---|
github_event | GitHub (issues, PRs, CI) | Issue con label fab-auto → crear intent |
slack_message | Slack (mensajes en canal) | Mensaje con patron @fab fix ... → intent bug_fix |
cron_schedule | Timer (expresion cron) | Cada dia a las 09:00 → health check |
ci_result | CI/CD (GitHub Actions, etc.) | CI falla en main → intent de fix automatico |
webhook | HTTP POST externo | Evento de monitoring → intent de investigacion |
file_change | Filesystem (watch) | Cambio en *.yaml → validar artefactos |
Configuracion
Sección titulada «Configuracion»Archivo: project/F09_operations/fab_triggers.yaml
triggers: - id: "auto-fix-ci" name: "Fix CI failures automatically" type: ci_result conditions: status_filter: "failure" branch_pattern: "main" action: type: create_intent intent_template: "intent/templates/bug_fix.yaml" intent_overrides: priority: "high" cooldown_minutes: 30Ejecucion
Sección titulada «Ejecucion»# Listar triggers configuradospython3 baseline/scripts/fab-trigger-dispatcher.py list --project-dir .
# Simular sin ejecutarpython3 baseline/scripts/fab-trigger-dispatcher.py dry-run --project-dir . --event event.json
# Modo escucha continuopython3 baseline/scripts/fab-trigger-dispatcher.py listen --project-dir .Seguridad
Sección titulada «Seguridad»- Solo triggers configurados explicitamente en
fab_triggers.yamlse ejecutan - Cooldown obligatorio entre ejecuciones del mismo trigger
- No se ejecuta codigo arbitrario — solo crear intents, despachar FABs, o correr scripts listados
- Los intents generados pasan por el mismo pipeline de validacion que los manuales
8. Operacion Autonoma Multi-Dia (v7.4)
Sección titulada «8. Operacion Autonoma Multi-Dia (v7.4)»Para intents que requieren mas de un dia de trabajo continuo.
Configuracion
Sección titulada «Configuracion»En .fab-config.yaml:
long_running: enabled: true max_session_hours: 72 checkpoint_strategy: "adaptive" adaptive_rules: min_interval_min: 30 max_interval_min: 480 increase_on_green_streak: true heartbeat_interval_min: 15 recovery: auto_resume: true max_retries: 3 state_persistence: "git"Estrategias de checkpoint
Sección titulada «Estrategias de checkpoint»| Estrategia | Intervalo | Cuando usar |
|---|---|---|
time_based | Fijo (cada N minutos) | Default, sesiones < 8h |
phase_based | Al completar cada fase | Intents multi-fase claros |
adaptive | Dinamico segun salud | Sesiones > 8h, exploratorias |
Adaptive: logica de ajuste
Sección titulada «Adaptive: logica de ajuste»- Inicia con
min_interval_min(30 min) - 3 checkpoints verdes consecutivos → intervalo sube 50%
- Error o test falla → intervalo baja a minimo
- Nunca supera
max_interval_min(8h)
Monitoring de FABs long-running
Sección titulada «Monitoring de FABs long-running»- Heartbeat cada 15 min: commit ligero con progress-tracker.md
- Si no hay heartbeat en 2x intervalo → FAB considerado muerto
- Dashboard via:
python3 baseline/scripts/fab-health-check.sh - Notificaciones via messaging bridge (Telegram/Discord/Slack)
Recovery tras crash
Sección titulada «Recovery tras crash»- Leer
HANDOFF.md→ estado al ultimo checkpoint - Leer
progress-tracker.md→ fase y paso actual - Verificar tests → confirmar integridad del ultimo checkpoint
- Retomar desde siguiente accion pendiente
- Si
max_retriesalcanzado → marcar intent comoblocked, notificar
Cost guardrails multi-dia
Sección titulada «Cost guardrails multi-dia»fab-cost-guard.pyusa rolling window diario- Si gasto del dia > 80% del budget diario → checkpoint + pausa
- Budget total del intent se divide en budget_diario = total / dias_estimados
- Metrica: costo acumulado vs costo proyectado (linear projection)
Ejemplo de intent con long_running
Sección titulada «Ejemplo de intent con long_running»execution: mode: headless long_running: true estimated_hours: 48 checkpoint_strategy: adaptive budget: max_usd: 150.0 daily_limit_usd: 60.09. Kill Switch Drill (v7.7)
Sección titulada «9. Kill Switch Drill (v7.7)»El script fab-kill-switch-drill.sh permite ejecutar simulacros del mecanismo de parada de emergencia sin afectar FABs en produccion. Es una practica recomendada para validar que el kill switch responde correctamente antes de depender de el en una emergencia real.
9.1 Ejecucion
Sección titulada «9.1 Ejecucion»# Drill basico con output JSONbash scripts/fab-kill-switch-drill.sh --json
# Drill con output detalladobash scripts/fab-kill-switch-drill.sh --verbose9.2 Que Valida el Drill
Sección titulada «9.2 Que Valida el Drill»| Verificacion | Descripcion |
|---|---|
| Senal de parada | El kill switch envia la senal correctamente |
| Checkpoint automatico | Se genera checkpoint antes del shutdown |
| Shutdown graceful | Los procesos terminan de forma ordenada |
| Tiempo de respuesta | El kill switch responde dentro del SLA definido |
9.3 Frecuencia Recomendada
Sección titulada «9.3 Frecuencia Recomendada»| Track | Frecuencia |
|---|---|
| Solo | Mensual |
| Lean | Semanal |
| Full | Semanal + antes de cada deploy a produccion |
10. Relación con Otros Documentos
Sección titulada «10. Relación con Otros Documentos»| Documento | Relación |
|---|---|
CORE_F04_Fullstack_Agent_Builder.md | Perfil del FAB que este guide operacionaliza |
Multi_Agent_Orchestration_Guide.md §7 | Long-running sessions, checkpoints |
Swarming_Strategy_Merge_Wall_Guide.md | Merge strategies para parallelism |
Context_Engineering_Guide.md | Context management para FABs |
Brownfield_Adoption_Guide.md | Bootstrap del framework en proyectos existentes |
REF_CROSS_FAB_Runtime_Comparison.yaml | Comparación de runtimes para FABs |
Documento creado como parte de AI Software Factory OS v7.7 (Factory-Native) — Phase 1: Intake & Orchestration. Fuentes: Anthropic Claude Code Docs (2026), Gas Town Orchestrator (2026), StrongDM Software Factory (2026), DealInspect Case Study (2026), Druce.ai Claude Code Guide (2026). Kill switch drill agregado en v7.7.