forgecraft 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -310,6 +310,9 @@ function playSound() {
310
310
  "paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null || printf '\\x07'"
311
311
  );
312
312
  break;
313
+ case "win32":
314
+ exec('powershell -c "[System.Media.SystemSounds]::Exclamation.Play()"');
315
+ break;
313
316
  default:
314
317
  process.stdout.write("\x07");
315
318
  }
@@ -1146,7 +1149,7 @@ var Worker = class {
1146
1149
  }
1147
1150
  shortPath(p) {
1148
1151
  if (!p) return "";
1149
- const parts = p.split("/");
1152
+ const parts = p.split(/[/\\]/);
1150
1153
  return parts.length > 2 ? ".../" + parts.slice(-2).join("/") : p;
1151
1154
  }
1152
1155
  };
@@ -3034,4 +3037,4 @@ export {
3034
3037
  validateConfig,
3035
3038
  loadAndValidateConfig
3036
3039
  };
3037
- //# sourceMappingURL=chunk-P5CLBIGQ.js.map
3040
+ //# sourceMappingURL=chunk-YP5E2NQR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/adapters/nextjs.ts","../src/core/adapters/react-vite.ts","../src/core/adapters/django.ts","../src/core/adapters/generic.ts","../src/core/adapters/index.ts","../src/core/utils/sound.ts","../src/core/orchestrator/index.ts","../src/core/orchestrator/prompts.ts","../src/core/worker/index.ts","../src/core/worker/prompts/index.ts","../src/core/git/index.ts","../src/state/index.ts","../src/core/pipeline/index.ts","../src/core/pipeline/auto.ts","../src/core/github/index.ts","../src/core/utils/attachments.ts","../src/core/utils/config.ts"],"sourcesContent":["import type { FrameworkAdapter } from \"./base.js\";\n\nexport const nextjsAdapter: FrameworkAdapter = {\n id: \"nextjs\",\n name: \"Next.js\",\n language: \"typescript\",\n scaffoldCommands: [\n \"npx create-next-app@latest . --typescript --tailwind --eslint --app --src-dir --import-alias '@/*' --use-npm --no-turbopack\",\n ],\n buildCommand: \"npm run build\",\n lintCommand: \"npm run lint\",\n typecheckCommand: \"npx tsc --noEmit\",\n devCommand: \"npm run dev\",\n devPort: 3000,\n designSupport: true,\n packageManager: \"npm\",\n requiredFiles: [\"package.json\", \"tsconfig.json\", \"next.config.ts\", \"tailwind.config.ts\"],\n\n buildPromptAdditions: `\nFOR NEXT.JS:\n- Use App Router (not Pages Router)\n- Server Components by default — only use \"use client\" when genuinely needed\n- Server Actions for mutations\n- Proper metadata and SEO in layout.tsx\n- Dynamic imports for heavy components\n- Use next/image for all images with width, height, alt\n- Use next/link for all internal navigation\n- Use next/font for custom fonts (no Google Fonts CDN)\n\nASSETS & SEO (REQUIRED):\n- Create favicon.ico, icon.svg, and apple-touch-icon.png in public/\n- Create og.png (1200x630 placeholder) for Open Graph sharing\n- Add complete metadata in layout.tsx: title, description, Open Graph tags, Twitter cards\n- Create robots.txt, sitemap.xml, and manifest.json in public/\n- Ensure every page has a unique <title> and meta description\n`.trim(),\n\n designPromptAdditions: `\nNEXT.JS DESIGN:\n- Components use shadcn/ui + Tailwind CSS\n- Use CSF3 format for Storybook stories\n- Include viewport decorators for mobile (375px) and desktop (1440px)\n`.trim(),\n\n fileStructure: `\nsrc/\n├── app/\n│ ├── layout.tsx # Root layout with metadata\n│ ├── page.tsx # Home page\n│ ├── globals.css # Global styles + Tailwind\n│ └── [route]/\n│ └── page.tsx # Route pages\n├── components/\n│ ├── ui/ # shadcn/ui components\n│ └── [feature]/ # Feature-specific components\n├── lib/\n│ └── utils.ts # Shared utilities\n└── types/\n └── index.ts # TypeScript types\npublic/\n├── favicon.ico\n├── og.png\n├── robots.txt\n└── sitemap.xml\n`.trim(),\n};\n","import type { FrameworkAdapter } from \"./base.js\";\n\nexport const reactViteAdapter: FrameworkAdapter = {\n id: \"react\",\n name: \"React + Vite\",\n language: \"typescript\",\n scaffoldCommands: [\n \"npm create vite@latest . -- --template react-ts\",\n \"npm install\",\n \"npm install -D tailwindcss @tailwindcss/vite\",\n \"npm install react-router-dom\",\n ],\n buildCommand: \"npm run build\",\n lintCommand: \"npm run lint\",\n typecheckCommand: \"npx tsc --noEmit\",\n devCommand: \"npm run dev\",\n devPort: 5173,\n designSupport: true,\n packageManager: \"npm\",\n requiredFiles: [\"package.json\", \"tsconfig.json\", \"vite.config.ts\", \"index.html\"],\n\n buildPromptAdditions: `\nFOR REACT + VITE:\n- Use React Router v6 with createBrowserRouter for routing\n- Functional components only — no class components\n- Use TypeScript strict mode throughout\n- Tailwind CSS for styling (configured via @tailwindcss/vite plugin)\n- Use React.lazy() and Suspense for code splitting\n- State management: React context + useReducer for simple state, or Zustand if complex\n- No SSR — this is a client-side SPA\n- Put entry point in src/main.tsx, root component in src/App.tsx\n- Environment variables: import.meta.env.VITE_* prefix\n\nVITE CONFIG:\n- Configure in vite.config.ts\n- Add @tailwindcss/vite plugin\n- Set resolve aliases: \"@/\" -> \"./src/\"\n\nASSETS & SEO:\n- favicon.ico and icon.svg in public/\n- og.png (1200x630) in public/\n- Update index.html with proper <title>, meta description, og tags\n- robots.txt in public/\n`.trim(),\n\n designPromptAdditions: `\nREACT + VITE DESIGN:\n- Components use Tailwind CSS utility classes\n- Use CSF3 format for Storybook stories\n- No Next.js-specific features (no next/image, next/link, etc.)\n- Use standard <img>, <a> tags or react-router <Link>\n`.trim(),\n\n fileStructure: `\nsrc/\n├── main.tsx # Entry point\n├── App.tsx # Root component with router\n├── index.css # Global styles + Tailwind\n├── components/\n│ ├── ui/ # Reusable UI components\n│ └── [feature]/ # Feature-specific components\n├── pages/\n│ └── [PageName].tsx # Route pages\n├── hooks/\n│ └── use[Hook].ts # Custom hooks\n├── lib/\n│ └── utils.ts # Shared utilities\n└── types/\n └── index.ts # TypeScript types\npublic/\n├── favicon.ico\n├── og.png\n└── robots.txt\n`.trim(),\n};\n","import type { FrameworkAdapter } from \"./base.js\";\n\nexport const djangoAdapter: FrameworkAdapter = {\n id: \"django\",\n name: \"Django\",\n language: \"python\",\n scaffoldCommands: [\n \"python3 -m venv venv\",\n \"venv/bin/pip install django djangorestframework django-cors-headers python-dotenv\",\n \"venv/bin/django-admin startproject config .\",\n \"venv/bin/python manage.py startapp core\",\n ],\n buildCommand: \"venv/bin/python manage.py check --deploy\",\n lintCommand: \"venv/bin/python -m py_compile manage.py\",\n typecheckCommand: \"echo 'Type checking skipped (Python)'\",\n devCommand: \"venv/bin/python manage.py runserver\",\n devPort: 8000,\n designSupport: false,\n packageManager: \"pip\",\n requiredFiles: [\"manage.py\", \"config/settings.py\", \"config/urls.py\", \"requirements.txt\"],\n\n buildPromptAdditions: `\nFOR DJANGO:\n- Use Django 5.x with Django REST Framework for APIs\n- Class-Based Views for CRUD, function-based views for custom logic\n- Use Django models with proper field types, validators, and Meta classes\n- Migrations: always run makemigrations + migrate after model changes\n- URL patterns in config/urls.py, app-level urls in each app's urls.py\n- Use Django templates (Jinja-style) for server-rendered pages\n- Static files in static/, templates in templates/\n- Settings: use python-dotenv for environment variables\n- Always create a superuser: python manage.py createsuperuser --noinput\n (set DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_PASSWORD, DJANGO_SUPERUSER_EMAIL)\n- Register models in admin.py for Django Admin access\n- Use django-cors-headers for API CORS configuration\n\nSECURITY:\n- CSRF protection enabled by default — don't disable it\n- Use Django's built-in auth system (User model, login/logout views)\n- Set DEBUG=False in production settings\n- Configure ALLOWED_HOSTS properly\n\nAFTER WRITING CODE:\n1. Run: venv/bin/python manage.py makemigrations\n2. Run: venv/bin/python manage.py migrate\n3. Run: venv/bin/python manage.py check --deploy\n4. Fix any warnings or errors before proceeding\n\nALWAYS generate a requirements.txt with: venv/bin/pip freeze > requirements.txt\n`.trim(),\n\n designPromptAdditions: `\nDJANGO DESIGN:\n- No Storybook — Django uses server-rendered templates\n- Design phase is skipped for Django projects\n- Focus on clean, functional UI with Django templates + CSS\n`.trim(),\n\n fileStructure: `\nconfig/\n├── __init__.py\n├── settings.py # Django settings\n├── urls.py # Root URL configuration\n├── wsgi.py # WSGI entry point\n└── asgi.py # ASGI entry point\ncore/\n├── __init__.py\n├── admin.py # Admin registrations\n├── apps.py # App config\n├── models.py # Database models\n├── views.py # Views (CBV/FBV)\n├── urls.py # App URL patterns\n├── serializers.py # DRF serializers\n├── forms.py # Django forms\n├── tests.py # Tests\n├── migrations/\n│ └── __init__.py\n└── templates/\n └── core/ # App templates\nstatic/\n├── css/\n├── js/\n└── images/\ntemplates/\n└── base.html # Base template\nmanage.py # Django CLI\nrequirements.txt # Python dependencies\n.env # Environment variables\n`.trim(),\n};\n","import type { FrameworkAdapter } from \"./base.js\";\n\nexport const genericAdapter: FrameworkAdapter = {\n id: \"generic\",\n name: \"Custom Stack\",\n language: \"typescript\", // default, but prompts tell the agent to auto-detect\n scaffoldCommands: [],\n buildCommand: \"AUTO_DETECT\",\n lintCommand: \"AUTO_DETECT\",\n typecheckCommand: \"AUTO_DETECT\",\n devCommand: \"npm run dev\",\n devPort: 3000,\n designSupport: false,\n packageManager: \"npm\",\n requiredFiles: [],\n\n buildPromptAdditions: `\nCUSTOM TECH STACK — IMPORTANT:\nThis project uses a tech stack chosen by the user. You MUST auto-detect everything.\n\nSTEP 1 — DETECT THE STACK:\nBefore writing ANY code, read these files (whichever exist):\n- package.json (Node.js/JS/TS projects)\n- requirements.txt / pyproject.toml / Pipfile (Python projects)\n- go.mod (Go projects)\n- Cargo.toml (Rust projects)\n- pom.xml / build.gradle (Java/Kotlin projects)\n- pubspec.yaml (Flutter/Dart projects)\n- Gemfile (Ruby projects)\n- composer.json (PHP projects)\n- Any existing source files to understand patterns\n\nSTEP 2 — FOLLOW EXISTING CONVENTIONS:\n- If the project already has code, match its style exactly (naming, file structure, patterns)\n- If starting from scratch, use the standard project structure for the detected tech stack\n- Use the package manager the project already uses (npm, yarn, pnpm, pip, poetry, cargo, go, etc.)\n\nSTEP 3 — BUILD VERIFICATION:\n- Detect the correct build/lint/test commands from the project config\n- For Node.js: check package.json \"scripts\" for build, lint, typecheck commands\n- For Python: use pytest, flake8/ruff, mypy if configured\n- For Go: use go build, go vet, go test\n- For Rust: use cargo build, cargo clippy, cargo test\n- If no build script exists, skip the build step — do NOT fail\n- If a command does not exist or is not configured, skip it gracefully\n\nSTEP 4 — SCAFFOLDING:\n- If the project directory is empty, scaffold the project using the standard tooling for the stack\n (e.g., npm init, cargo init, go mod init, django-admin startproject, etc.)\n- Install dependencies after scaffolding\n`.trim(),\n\n designPromptAdditions: \"\",\n\n fileStructure: `\n(auto-detected — read the project's existing files to determine structure)\n`.trim(),\n};\n","// ============================================================\n// Adapter Registry — Factory for framework adapters\n// ============================================================\n\nimport type { FrameworkAdapter } from \"./base.js\";\nimport { nextjsAdapter } from \"./nextjs.js\";\nimport { reactViteAdapter } from \"./react-vite.js\";\nimport { djangoAdapter } from \"./django.js\";\nimport { genericAdapter } from \"./generic.js\";\n\nconst adapters: Record<string, FrameworkAdapter> = {\n nextjs: nextjsAdapter,\n react: reactViteAdapter,\n django: djangoAdapter,\n generic: genericAdapter,\n};\n\n/** Get the adapter for a framework. Throws if unknown. */\nexport function getAdapter(framework: string): FrameworkAdapter {\n const adapter = adapters[framework];\n if (!adapter) {\n throw new Error(\n `Unknown framework \"${framework}\". Supported: ${Object.keys(adapters).join(\", \")}`\n );\n }\n return adapter;\n}\n\n/** List all supported frameworks */\nexport function listAdapters(): FrameworkAdapter[] {\n return Object.values(adapters);\n}\n\nexport type { FrameworkAdapter } from \"./base.js\";\n","import { exec } from \"child_process\";\nimport { platform } from \"os\";\n\n/**\n * Play a system notification sound (fire-and-forget).\n * Skips silently if not a TTY.\n */\nexport function playSound(): void {\n if (!process.stdout.isTTY) return;\n\n switch (platform()) {\n case \"darwin\":\n exec(\"afplay /System/Library/Sounds/Blow.aiff\");\n break;\n case \"linux\":\n exec(\n \"paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null || printf '\\\\x07'\"\n );\n break;\n case \"win32\":\n exec(\"powershell -c \\\"[System.Media.SystemSounds]::Exclamation.Play()\\\"\");\n break;\n default:\n process.stdout.write(\"\\x07\");\n }\n}\n","import { query } from \"@anthropic-ai/claude-agent-sdk\";\nimport chalk from \"chalk\";\nimport type {\n Plan,\n Story,\n SprintState,\n ForgeConfig,\n OrchestratorDecision,\n WorkerMode,\n} from \"../../types/plan.js\";\nimport { ORCHESTRATOR_SYSTEM_PROMPT } from \"./prompts.js\";\nimport { getAdapter } from \"../adapters/index.js\";\nimport { playSound } from \"../utils/sound.js\";\n\n// ============================================================\n// Orchestrator Agent\n// The project manager. Never writes code.\n// Plans, routes, reviews, and crafts prompts for the Worker.\n// Framework-aware via adapter system.\n// ============================================================\n\nexport class Orchestrator {\n private config: ForgeConfig;\n private plan: Plan | null = null;\n\n constructor(config: ForgeConfig) {\n this.config = config;\n }\n\n // ── Plan Generation ───────────────────────────────────────\n\n async generatePlan(description: string): Promise<Plan> {\n const adapter = getAdapter(this.config.framework);\n\n const isGeneric = adapter.id === \"generic\";\n const frameworkHint = isGeneric\n ? `Tech stack: Detect from the user's description below. The user may specify their own framework, language, and tools.`\n : `Framework: ${adapter.name} (${this.config.framework})\\n Language: ${adapter.language}`;\n\n const prompt = `\n The user wants to build the following application:\n \"${description}\"\n\n ${frameworkHint}\n Design support: ${adapter.designSupport ? \"yes (Storybook)\" : \"no\"}\n\n Break this down into epics and stories. Each story should be:\n - Small enough to build in one agent session\n - Independently testable\n - Ordered by dependency (foundation first)\n\n Story types:\n - \"ui\" = has a visual component ${adapter.designSupport ? \"(needs design phase)\" : \"(no design phase for this framework)\"}\n - \"backend\" = API/database only (skip design phase)\n - \"fullstack\" = both UI and backend\n\n Return ONLY valid JSON with this structure:\n {\n \"project\": \"project name\",\n \"framework\": \"${this.config.framework}\",\n \"description\": \"brief description\",\n \"epics\": [\n {\n \"id\": \"epic-id\",\n \"title\": \"Epic Title\",\n \"stories\": [\n {\n \"id\": \"story-id\",\n \"title\": \"Story Title\",\n \"description\": \"What to build\",\n \"type\": \"ui\" | \"backend\" | \"fullstack\",\n \"priority\": 1,\n \"dependencies\": [\"other-story-id\"]\n }\n ]\n }\n ]\n }\n\n No explanation, just the JSON.\n `;\n\n const resultText = await this.runQuery(prompt, { maxTurns: 3 });\n\n let rawPlan: any;\n try {\n rawPlan = JSON.parse(this.cleanJson(resultText));\n } catch {\n throw new Error(\n \"Failed to parse plan. The AI returned invalid JSON. Try again with a clearer description.\"\n );\n }\n\n // Validate required fields\n if (!rawPlan.epics || !Array.isArray(rawPlan.epics)) {\n throw new Error(\"Invalid plan: missing epics array. Try regenerating.\");\n }\n\n // Hydrate with default status fields\n const plan: Plan = {\n project: rawPlan.project || \"Untitled\",\n framework: rawPlan.framework || this.config.framework,\n description: rawPlan.description || description,\n created: new Date().toISOString(),\n epics: rawPlan.epics.map((epic: any) => ({\n id: epic.id || `epic-${Date.now()}`,\n title: epic.title || \"Untitled Epic\",\n status: \"planned\" as const,\n stories: (epic.stories || []).map((story: any) => ({\n id: story.id || `story-${Date.now()}`,\n title: story.title || \"Untitled Story\",\n description: story.description || \"\",\n type: story.type || \"fullstack\",\n status: \"planned\" as const,\n branch: null,\n designApproved: false,\n tags: [],\n priority: story.priority || 1,\n dependencies: story.dependencies || [],\n })),\n })),\n };\n\n this.plan = plan;\n return plan;\n }\n\n // ── User Input Routing ────────────────────────────────────\n\n async routeUserInput(\n message: string,\n currentState: SprintState\n ): Promise<OrchestratorDecision> {\n const routingPrompt = `\n Current sprint state:\n - Phase: ${currentState.currentPhase}\n - Current story: ${currentState.currentStory || \"none\"}\n - Worker mode: ${currentState.workerMode || \"idle\"}\n - Framework: ${this.config.framework}\n\n The user said: \"${message}\"\n\n Classify this input and decide what to do.\n Return ONLY valid JSON with this structure:\n {\n \"action\": \"route-to-worker\" | \"add-story\" | \"reprioritize\" | \"answer\" | \"queue-change\",\n \"workerMode\": \"design\" | \"build\" | \"review\" | \"fix\" (if routing to worker),\n \"response\": \"your response to the user\" (if answering directly),\n \"prompt\": \"detailed prompt for the worker\" (if routing to worker),\n \"story\": { \"title\": \"...\", \"description\": \"...\", \"type\": \"...\" } (if adding a new story)\n }\n\n Routing rules:\n - Visual tweak (color, spacing, font) → route-to-worker, mode: fix\n - Layout/UX redesign → route-to-worker, mode: design\n - Bug fix → route-to-worker, mode: fix\n - New feature → add-story (include title, description, type)\n - Content change (text, labels) → route-to-worker, mode: fix\n - Question → answer directly\n - If worker is currently active → queue-change (apply after current task)\n `;\n\n const resultText = await this.runQuery(routingPrompt, { maxTurns: 1 });\n try {\n return JSON.parse(this.cleanJson(resultText));\n } catch {\n // Fallback: treat as a question if JSON parse fails\n return { action: \"answer\", response: resultText };\n }\n }\n\n // ── Prompt Crafting ───────────────────────────────────────\n\n craftWorkerPrompt(\n story: Story,\n mode: WorkerMode,\n context: {\n plan: Plan;\n designMeta?: any;\n existingFiles?: string[];\n }\n ): string {\n const adapter = getAdapter(this.config.framework);\n\n switch (mode) {\n case \"design\":\n return this.craftDesignPrompt(story, context, adapter);\n case \"build\":\n return this.craftBuildPrompt(story, context, adapter);\n case \"review\":\n return this.craftReviewPrompt(story, context, adapter);\n case \"fix\":\n return this.craftFixPrompt(story, context, adapter);\n }\n }\n\n private craftDesignPrompt(\n story: Story,\n context: { plan: Plan },\n adapter: any\n ): string {\n const refsDir = \".forge/designs/references\";\n\n return `\n You are designing the UI for: \"${story.title}\"\n\n Description: ${story.description}\n App: ${context.plan.project} (${adapter.name})\n Full app context: ${context.plan.description}\n\n DESIGN REFERENCES:\n Check if ${refsDir}/ exists and contains reference images.\n If so, read them and match their visual style, color palette, typography, and layout.\n\n Create a Storybook story file that renders this component/page.\n The file should be at: stories/${story.id}.stories.tsx\n\n Requirements:\n - Must be responsive (mobile-first: 375px, then 768px, then 1440px)\n - Use Tailwind CSS for styling\n - Include realistic placeholder data (not lorem ipsum)\n - Show default, loading, empty, and error states as separate stories\n - Use a distinctive, professional design (not generic AI aesthetics)\n - Choose fonts and colors that match the app's purpose\n\n DO NOT write the actual app code. Only the Storybook preview.\n `;\n }\n\n private craftBuildPrompt(\n story: Story,\n context: { plan: Plan; designMeta?: any; existingFiles?: string[] },\n adapter: any\n ): string {\n const isGeneric = adapter.id === \"generic\";\n const designRef = context.designMeta\n ? `\\nApproved design: Follow the design in stories/${story.id}.stories.tsx exactly.`\n : \"\";\n\n const existingRef = context.existingFiles?.length\n ? `\\nExisting files to reference for patterns:\\n${context.existingFiles.map((f) => ` - ${f}`).join(\"\\n\")}`\n : \"\";\n\n const verifySteps = isGeneric\n ? `\n After writing code:\n 1. Detect the project's build/lint/typecheck commands from its config files (package.json scripts, Makefile, pyproject.toml, etc.)\n 2. Run whichever commands exist — skip any that aren't configured\n 3. Fix any errors before finishing\n `\n : `\n After writing code:\n 1. Run: ${adapter.buildCommand} (fix any errors)\n 2. Run: ${adapter.lintCommand} (fix any warnings)\n 3. Run: ${adapter.typecheckCommand} (fix any type errors)\n `;\n\n const structureRef = isGeneric\n ? `\n Project structure:\n Read the existing project files to understand the structure.\n If starting from scratch, use the standard conventions for this tech stack.\n `\n : `\n Expected project structure:\n ${adapter.fileStructure}\n `;\n\n return `\n Implement: \"${story.title}\"\n\n Description: ${story.description}\n App: ${context.plan.project} (${adapter.name})\n ${designRef}\n ${existingRef}\n\n ${structureRef}\n\n Technical requirements:\n - Follow existing code patterns in the project\n - Small, focused components/functions\n - Proper error handling\n - Responsive design (mobile-first)\n\n ${verifySteps}\n\n If any command fails, read the error, fix it, and re-run.\n Do NOT leave broken code.\n `;\n }\n\n private craftReviewPrompt(\n story: Story,\n context: { plan: Plan; designMeta?: any },\n adapter: any\n ): string {\n const isGeneric = adapter.id === \"generic\";\n const runCmds = isGeneric\n ? `Run the project's build/lint/test commands (detect from config files). Skip any that aren't configured.`\n : `Run:\\n - ${adapter.buildCommand}\\n - ${adapter.lintCommand}\\n - ${adapter.typecheckCommand}`;\n\n return `\n Review the code for: \"${story.title}\"\n\n Framework: ${adapter.name}\n\n Check:\n 1. Does the implementation match the story description?\n ${context.designMeta ? \"2. Does it match the approved design?\" : \"\"}\n 3. Code quality — no shortcuts, proper types\n 4. Responsive design — works on mobile and desktop\n 5. Error handling — graceful failures, loading states\n 6. Accessibility — semantic HTML, ARIA labels\n 7. No debug logs, no commented-out code, no TODOs\n\n ${runCmds}\n\n If you find issues:\n - Minor (formatting, missing type): fix them directly\n - Major (broken logic, missing feature): list them and do NOT fix\n\n Return a summary of what you found and what you fixed.\n `;\n }\n\n private craftFixPrompt(\n story: Story,\n context: { plan: Plan },\n adapter: any\n ): string {\n const isGeneric = adapter.id === \"generic\";\n const verifyCmds = isGeneric\n ? \"After fixing, run the project's build/test commands to verify (detect from config files).\"\n : `After fixing, run ${adapter.buildCommand} and ${adapter.typecheckCommand} to verify.`;\n\n return `\n Fix an issue in: \"${story.title}\"\n Framework: ${adapter.name}\n\n Make the smallest possible change. Do not refactor.\n ${verifyCmds}\n `;\n }\n\n // ── SDK Query Helper ──────────────────────────────────────\n\n private async runQuery(\n prompt: string,\n opts: { maxTurns?: number } = {}\n ): Promise<string> {\n const maxRetries = 3;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await this.executeQuery(prompt, opts);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n\n if (this.isAuthError(msg) && attempt < maxRetries) {\n playSound();\n console.log(chalk.yellow(\"\\n Authentication expired\"));\n console.log(chalk.dim(\" Run: claude login\"));\n console.log(chalk.dim(` Retrying in 30s (attempt ${attempt}/${maxRetries})...\\n`));\n await new Promise((r) => setTimeout(r, 30_000));\n continue;\n }\n\n throw error;\n }\n }\n\n throw new Error(\"Max retries exceeded\");\n }\n\n private async executeQuery(\n prompt: string,\n opts: { maxTurns?: number } = {}\n ): Promise<string> {\n let resultText = \"\";\n\n for await (const msg of query({\n prompt,\n options: {\n model: this.config.model,\n systemPrompt: ORCHESTRATOR_SYSTEM_PROMPT,\n maxTurns: opts.maxTurns,\n allowedTools: [],\n },\n })) {\n if (msg.type === \"result\") {\n if (\"result\" in msg && typeof msg.result === \"string\") {\n resultText = msg.result;\n } else if (\"errors\" in msg && Array.isArray(msg.errors)) {\n throw new Error(`Agent error: ${msg.errors.join(\", \")}`);\n }\n }\n\n if (msg.type === \"assistant\" && msg.message?.content) {\n const textBlocks = msg.message.content\n .filter((b: any) => b.type === \"text\")\n .map((b: any) => b.text);\n if (textBlocks.length > 0) {\n resultText = textBlocks.join(\"\\n\");\n }\n }\n }\n\n if (!resultText) {\n throw new Error(\"No response from agent\");\n }\n\n return resultText;\n }\n\n private isAuthError(msg: string): boolean {\n const lower = msg.toLowerCase();\n return (\n lower.includes(\"401\") ||\n lower.includes(\"unauthorized\") ||\n lower.includes(\"auth\") ||\n lower.includes(\"token expired\") ||\n lower.includes(\"session expired\") ||\n lower.includes(\"not authenticated\")\n );\n }\n\n private cleanJson(text: string): string {\n return text\n .replace(/```json\\s*/g, \"\")\n .replace(/```\\s*/g, \"\")\n .trim();\n }\n}\n","// ============================================================\n// System Prompts for the Orchestrator Agent\n// ============================================================\n\nexport const ORCHESTRATOR_SYSTEM_PROMPT = `\nYou are the Orchestrator — a senior tech lead managing an AI development sprint for the \"Forge\" framework.\n\nYOUR ROLE:\nYou NEVER write code. You plan, delegate, and review. You are the brain of the operation.\n\nRESPONSIBILITIES:\n1. Break user requirements into epics and stories\n2. Craft detailed, specific prompts for the Worker agent\n3. Route user feedback to the correct Worker mode\n4. Review Worker output and decide next steps\n5. Maintain project context and sprint state\n\nWHEN CREATING STORIES:\n- Each story must be independently buildable\n- UI stories need design phase; backend-only stories skip it\n- Order stories by dependency (foundation/setup first, then data layer, then UI, then integration)\n- Each story should result in working, testable code\n- Story IDs should be kebab-case: \"auth-login\", \"dashboard-layout\"\n- First story should always be project setup/scaffolding\n\nWHEN CRAFTING WORKER PROMPTS:\n- Include EXACT file paths to create or modify\n- Reference approved designs when available\n- Specify the framework patterns to follow (App Router, Server Components, etc.)\n- Include acceptance criteria — what \"done\" looks like\n- Never be vague — the Worker should not have to guess anything\n- Include the full project context the Worker needs (but not more)\n\nWHEN ROUTING USER FEEDBACK:\n- Visual tweak (color, spacing, font, border) → Worker fix mode, direct code change\n- Layout/UX redesign (page structure, navigation, flow) → Worker design mode first, then build\n- Bug fix (something broken, error, crash) → Worker fix mode with debug focus\n- New feature (something that doesn't exist yet) → Create new story, full pipeline\n- Content change (text, labels, copy) → Worker fix mode, string replacement\n- Question about the project → Answer directly, don't route\n- If Worker is currently busy → Queue the change for after current task\n\nWHEN REVIEWING WORKER OUTPUT:\n- Does the output match what was requested?\n- Did the Worker run build/lint/typecheck?\n- Are there any obvious issues?\n- Minor issues: send back to Worker fix mode\n- Major issues: send back to Worker build mode with specific instructions\n\nOUTPUT FORMAT:\nAlways respond with valid JSON when asked for structured data.\nWhen answering questions, respond in plain text.\nNever include markdown code fences around JSON output.\n\nDESIGN QUALITY STANDARDS:\nWhen the Worker is in design mode, ensure designs reference real products:\n- Finance/Banking → Stripe, Mercury, Wise\n- Dashboard/Admin → Linear, Vercel, Raycast\n- E-commerce → Shopify Admin, Gumroad\n- Social/Community → Discord, Slack\n- Content/Blog → Medium, Ghost, Substack\n- SaaS/Productivity → Notion, Figma\n- Healthcare/Church/Nonprofit → warm, trustworthy, accessible\n\nNEVER accept generic AI-looking designs (purple gradients, Inter font, rounded white cards on gray).\n`.trim();\n\n// ============================================================\n// Routing Classification Prompt\n// Used when the Orchestrator needs to classify user input\n// ============================================================\n\nexport const ROUTING_CLASSIFICATION_PROMPT = `\nClassify the user's message into one of these categories:\n\n1. VISUAL_TWEAK — Small CSS/styling change\n Examples: \"make it blue\", \"bigger font\", \"add shadow\", \"more padding\"\n \n2. REDESIGN — Significant layout or UX change\n Examples: \"redesign the dashboard\", \"switch to sidebar nav\", \"make it look like Stripe\"\n \n3. BUG_FIX — Something is broken or not working\n Examples: \"button doesn't work\", \"page is blank\", \"getting an error\"\n \n4. NEW_FEATURE — Something that doesn't exist yet\n Examples: \"add dark mode\", \"add recurring donations\", \"add export to PDF\"\n \n5. CONTENT_CHANGE — Text, labels, or copy changes\n Examples: \"change 'Submit' to 'Send'\", \"update the footer text\"\n \n6. QUESTION — Asking for information\n Examples: \"what stack are we using?\", \"how many stories left?\", \"show me the schema\"\n \n7. PRIORITY_CHANGE — Wants to reorder or skip stories\n Examples: \"do reports next\", \"skip the settings page for now\"\n\nRespond with ONLY the category name and a brief routing instruction.\n`.trim();\n","import { query } from \"@anthropic-ai/claude-agent-sdk\";\nimport chalk from \"chalk\";\nimport type { WorkerMode, ForgeConfig } from \"../../types/plan.js\";\nimport {\n getDesignPrompt,\n getBuildPrompt,\n getReviewPrompt,\n getFixPrompt,\n} from \"./prompts/index.js\";\nimport { playSound } from \"../utils/sound.js\";\n\n// ============================================================\n// Worker Agent\n// Single agent, multiple modes. Does the actual work.\n// Framework-aware prompts via adapter system.\n// ============================================================\n\nconst MODE_TOOLS: Record<WorkerMode, string[]> = {\n design: [\"Read\", \"Write\", \"Glob\", \"LS\"],\n build: [\"Read\", \"Write\", \"Edit\", \"Bash\", \"Glob\", \"LS\", \"Grep\"],\n review: [\"Read\", \"Bash\", \"Glob\", \"LS\", \"Grep\"],\n fix: [\"Read\", \"Write\", \"Edit\", \"Bash\", \"Glob\", \"LS\", \"Grep\"],\n};\n\nfunction getModePrompt(mode: WorkerMode, framework?: string): string {\n switch (mode) {\n case \"design\": return getDesignPrompt(framework);\n case \"build\": return getBuildPrompt(framework);\n case \"review\": return getReviewPrompt(framework);\n case \"fix\": return getFixPrompt(framework);\n }\n}\n\nconst MODE_MAX_TURNS: Record<WorkerMode, number> = {\n design: 30,\n build: 50,\n review: 20,\n fix: 15,\n};\n\nexport interface WorkerUsage {\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n durationMs: number;\n}\n\nexport interface WorkerResult {\n success: boolean;\n filesCreated: string[];\n filesModified: string[];\n errors: string[];\n summary: string;\n usage: WorkerUsage;\n}\n\nexport interface WorkerProgressEvent {\n type: \"tool_use\" | \"tool_running\" | \"tool_done\" | \"thinking\" | \"status\";\n content: string;\n tool?: string;\n elapsed?: number;\n}\n\nexport interface WorkerProgressCallback {\n (event: WorkerProgressEvent): void;\n}\n\nexport interface WorkerSandboxOptions {\n sandbox?: boolean;\n yes?: boolean;\n workingDir?: string;\n allowedDomains?: string[];\n}\n\nconst MAX_AUTH_RETRIES = 3;\nconst AUTH_RETRY_DELAY_MS = 30_000; // 30s between retries\n\nexport class Worker {\n private config: ForgeConfig;\n private sandboxOpts: WorkerSandboxOptions;\n private mute: boolean;\n\n constructor(config: ForgeConfig, sandboxOpts: WorkerSandboxOptions = {}, mute = false) {\n this.config = config;\n this.sandboxOpts = sandboxOpts;\n this.mute = mute;\n }\n\n async run(\n mode: WorkerMode,\n prompt: string,\n options: {\n workingDir?: string;\n onProgress?: WorkerProgressCallback;\n } = {}\n ): Promise<WorkerResult> {\n // Retry loop for auth/token errors\n for (let attempt = 1; attempt <= MAX_AUTH_RETRIES; attempt++) {\n const result = await this.executeQuery(mode, prompt, options);\n\n // Check if it's a recoverable auth error\n if (!result.success && this.isAuthError(result.errors)) {\n if (attempt < MAX_AUTH_RETRIES) {\n this.notifyAuthError(attempt);\n await this.waitForReauth();\n // Clear auth errors before retrying — keep other errors\n result.errors = result.errors.filter((e) => !this.isAuthErrorMsg(e));\n continue;\n }\n // Final attempt failed — add help text\n result.errors.push(\n \"Authentication failed after retries. Run: claude login\"\n );\n }\n\n return result;\n }\n\n // Should never reach here, but TypeScript needs it\n return {\n success: false,\n filesCreated: [],\n filesModified: [],\n errors: [\"Max retries exceeded\"],\n summary: \"\",\n usage: { inputTokens: 0, outputTokens: 0, costUsd: 0, durationMs: 0 },\n };\n }\n\n private async executeQuery(\n mode: WorkerMode,\n prompt: string,\n options: {\n workingDir?: string;\n onProgress?: WorkerProgressCallback;\n } = {}\n ): Promise<WorkerResult> {\n let workingDir = options.workingDir || this.sandboxOpts.workingDir;\n if (!workingDir) {\n try {\n workingDir = process.cwd();\n } catch {\n // CWD was deleted (EPERM uv_cwd) — use the sandbox working dir or fail gracefully\n return {\n success: false,\n filesCreated: [],\n filesModified: [],\n errors: [\"Working directory no longer exists. Please cd to your project and retry.\"],\n summary: \"\",\n usage: { inputTokens: 0, outputTokens: 0, costUsd: 0, durationMs: 0 },\n };\n }\n }\n const { onProgress } = options;\n\n const result: WorkerResult = {\n success: false,\n filesCreated: [],\n filesModified: [],\n errors: [],\n summary: \"\",\n usage: { inputTokens: 0, outputTokens: 0, costUsd: 0, durationMs: 0 },\n };\n\n const sdkOptions: Record<string, any> = {\n model: this.config.model,\n systemPrompt: getModePrompt(mode, this.config.framework),\n allowedTools: MODE_TOOLS[mode],\n cwd: workingDir,\n maxTurns: MODE_MAX_TURNS[mode],\n };\n\n if (this.sandboxOpts.yes && !this.sandboxOpts.sandbox) {\n sdkOptions.permissionMode = \"bypassPermissions\";\n }\n\n if (this.sandboxOpts.sandbox) {\n sdkOptions.permissionMode = \"bypassPermissions\";\n sdkOptions.sandbox = {\n enabled: true,\n autoAllowBashIfSandboxed: true,\n filesystem: {\n allowWrite: [workingDir],\n },\n network: {\n allowedDomains: this.sandboxOpts.allowedDomains || [\n \"registry.npmjs.org\",\n \"api.anthropic.com\",\n ],\n },\n };\n }\n\n try {\n for await (const msg of query({ prompt, options: sdkOptions })) {\n\n // Assistant message — contains tool_use and text blocks\n if (msg.type === \"assistant\") {\n // Accumulate usage from individual messages as fallback\n if (msg.message?.usage) {\n result.usage.inputTokens += msg.message.usage.input_tokens || 0;\n result.usage.outputTokens += msg.message.usage.output_tokens || 0;\n }\n for (const block of msg.message?.content || []) {\n if (block.type === \"text\") {\n onProgress?.({ type: \"thinking\", content: block.text.slice(0, 120) });\n }\n if (block.type === \"tool_use\") {\n const detail = this.describeToolUse(block);\n onProgress?.({ type: \"tool_use\", content: detail, tool: block.name });\n\n if (block.name === \"Write\" && block.input?.file_path) {\n result.filesCreated.push(block.input.file_path);\n }\n if (block.name === \"Edit\" && block.input?.file_path) {\n result.filesModified.push(block.input.file_path);\n }\n }\n }\n }\n\n // Tool progress — fires while a tool is still running\n if (msg.type === \"tool_progress\") {\n onProgress?.({\n type: \"tool_running\",\n content: msg.tool_name,\n tool: msg.tool_name,\n elapsed: msg.elapsed_time_seconds,\n });\n }\n\n // Tool use summary — human-readable summary after tool completes\n if (msg.type === \"tool_use_summary\") {\n onProgress?.({ type: \"tool_done\", content: msg.summary });\n }\n\n // Result — final message with usage stats\n if (msg.type === \"result\") {\n if (\"result\" in msg && typeof msg.result === \"string\") {\n result.summary = msg.result;\n }\n if (\"errors\" in msg && Array.isArray(msg.errors) && msg.errors.length > 0) {\n result.errors.push(...msg.errors);\n }\n if (\"is_error\" in msg && msg.is_error) {\n result.errors.push(msg.subtype || \"unknown error\");\n }\n // Extract token usage — SDK result gives cumulative totals, so overwrite\n if (msg.usage) {\n result.usage.inputTokens = msg.usage.input_tokens || 0;\n result.usage.outputTokens = msg.usage.output_tokens || 0;\n }\n if (typeof msg.total_cost_usd === \"number\") {\n result.usage.costUsd = msg.total_cost_usd;\n }\n if (typeof msg.duration_ms === \"number\") {\n result.usage.durationMs = msg.duration_ms;\n }\n // Handle max turns cap gracefully\n if (\"is_error\" in msg && msg.subtype === \"error_max_turns\") {\n result.errors.push(`Hit ${MODE_MAX_TURNS[mode]}-turn safety cap — story may be incomplete`);\n }\n }\n }\n\n result.success = result.errors.length === 0;\n\n if (!result.summary) {\n result.summary = \"Completed without summary.\";\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n result.success = false;\n result.errors.push(msg);\n }\n\n return result;\n }\n\n // ── Auth Error Detection ──────────────────────────────────\n\n private isAuthErrorMsg(msg: string): boolean {\n const lower = msg.toLowerCase();\n return (\n lower.includes(\"401\") ||\n lower.includes(\"unauthorized\") ||\n lower.includes(\"auth\") ||\n lower.includes(\"token expired\") ||\n lower.includes(\"session expired\") ||\n lower.includes(\"not authenticated\") ||\n lower.includes(\"login required\") ||\n lower.includes(\"credential\")\n );\n }\n\n private isAuthError(errors: string[]): boolean {\n return errors.some((e) => this.isAuthErrorMsg(e));\n }\n\n private notifyAuthError(attempt: number): void {\n if (!this.mute) playSound();\n console.log(\"\");\n console.log(chalk.yellow(\" ⚠ Authentication expired\"));\n console.log(chalk.dim(\" Your Claude session token has expired.\"));\n console.log(chalk.dim(\" Please re-authenticate:\"));\n console.log(chalk.white(\" claude login\"));\n console.log(chalk.dim(`\\n Waiting to retry (attempt ${attempt}/${MAX_AUTH_RETRIES})...`));\n console.log(chalk.dim(\" Forge will resume automatically once auth is renewed.\\n\"));\n }\n\n private waitForReauth(): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, AUTH_RETRY_DELAY_MS));\n }\n\n /** Turn a tool_use block into a short human-readable string */\n private describeToolUse(block: any): string {\n const name = block.name;\n const input = block.input || {};\n\n switch (name) {\n case \"Write\":\n return `Write ${this.shortPath(input.file_path)}`;\n case \"Edit\":\n return `Edit ${this.shortPath(input.file_path)}`;\n case \"Read\":\n return `Read ${this.shortPath(input.file_path)}`;\n case \"Bash\":\n return `Run ${(input.command || \"\").slice(0, 60)}`;\n case \"Glob\":\n return `Search ${input.pattern || \"\"}`;\n case \"Grep\":\n return `Grep ${input.pattern || \"\"}`;\n default:\n return name;\n }\n }\n\n private shortPath(p?: string): string {\n if (!p) return \"\";\n const parts = p.split(/[/\\\\]/);\n return parts.length > 2 ? \".../\" + parts.slice(-2).join(\"/\") : p;\n }\n}\n","// ============================================================\n// Worker System Prompts — one per mode\n// Framework-specific additions are injected by the adapter.\n// ============================================================\n\nimport { getAdapter } from \"../../adapters/index.js\";\n\n/** Build the design system prompt, optionally with framework additions */\nexport function getDesignPrompt(framework?: string): string {\n const adapter = framework ? getAdapter(framework) : null;\n const additions = adapter?.designPromptAdditions || \"\";\n\n return `\nYou are a senior UI/UX designer working within the Forge development framework.\nYour job is to create beautiful, professional component previews as Storybook stories.\n\nDESIGN PRINCIPLES:\n- Mobile-first: design for 375px, then scale up to 768px and 1440px\n- Use the project's design system (shadcn/ui + Tailwind CSS)\n- Choose distinctive typography — NEVER use Inter, Arial, or Roboto\n- Commit to a cohesive color palette with a dominant color and sharp accents\n- Add micro-interactions (hover states, transitions)\n- Use realistic placeholder data (real names, real numbers, not \"Lorem ipsum\")\n- Include all states: default, loading, empty, error, success\n\nSTORYBOOK OUTPUT FORMAT:\n- Create .stories.tsx files in the stories/ directory\n- Each story file should export a default meta and named story variants\n- Use CSF3 format (Component Story Format)\n- Include args/controls for interactive props\n- Add viewport decorators for mobile/desktop\n\nQUALITY BAR:\nYour designs should look like they came from a professional design agency.\nReference real, well-designed products:\n- Finance → Stripe, Mercury, Wise\n- Dashboards → Linear, Vercel\n- E-commerce → Shopify, Gumroad\n- Social → Discord, Slack\n\nNEVER produce:\n- Purple gradient backgrounds\n- Generic rounded white cards on gray\n- Stock-photo placeholder images\n- Inconsistent spacing or alignment\n- Missing hover/focus states\n\n${additions}\n`.trim();\n}\n\n/** Build the build system prompt, optionally with framework additions */\nexport function getBuildPrompt(framework?: string): string {\n const adapter = framework ? getAdapter(framework) : null;\n const additions = adapter?.buildPromptAdditions || \"\";\n const isGeneric = adapter?.id === \"generic\";\n\n const verifyBlock = isGeneric\n ? `\nAFTER WRITING CODE:\n1. Detect the project's build/lint/typecheck/test commands from its config files\n (package.json scripts, Makefile, pyproject.toml, Cargo.toml, etc.)\n2. Run whichever commands exist — skip any that aren't configured\n3. Fix ALL errors before proceeding\n4. If no build system is configured, verify the code is syntactically valid\n`\n : `\nAFTER WRITING CODE:\n1. Run: ${adapter?.buildCommand || \"npm run build\"} — fix ALL errors before proceeding\n2. Run: ${adapter?.lintCommand || \"npm run lint\"} — fix warnings\n3. Run: ${adapter?.typecheckCommand || \"npx tsc --noEmit\"} — fix type errors\n`;\n\n return `\nYou are a senior fullstack developer working within the Forge development framework.\nYour job is to implement features based on approved designs and story requirements.\n\nCODING STANDARDS:\n- Small, focused components and functions (< 100 lines per file)\n- Proper error handling — try/catch, error boundaries, loading states\n- Responsive design — mobile-first with Tailwind breakpoints\n- Semantic HTML with accessibility (ARIA labels, keyboard navigation)\n- Clean imports, no circular dependencies\n\n${additions}\n\n${verifyBlock}\n\nIf any command fails:\n- Read the full error output\n- Identify the root cause\n- Fix it\n- Re-run the command\n- Repeat until all checks pass\n\nNEVER leave code in a broken state. Every commit must build successfully.\n\nGIT:\n- Make small, atomic changes\n- Write descriptive file names and function names\n`.trim();\n}\n\n/** Review system prompt — framework-aware build/lint/typecheck commands */\nexport function getReviewPrompt(framework?: string): string {\n const adapter = framework ? getAdapter(framework) : null;\n const isGeneric = adapter?.id === \"generic\";\n const lang = adapter?.language || \"typescript\";\n\n const langCheck = isGeneric\n ? \"3. Code quality — follows the language's best practices and idioms\"\n : lang === \"typescript\"\n ? \"3. TypeScript strict compliance (no any, no ts-ignore, no ts-expect-error)\"\n : \"3. Python code quality (no bare except, proper type hints where used)\";\n\n const runBlock = isGeneric\n ? `\nRUN THESE COMMANDS:\n- Detect build/lint/test commands from the project's config files (package.json, Makefile, pyproject.toml, Cargo.toml, etc.)\n- Run whichever exist — skip any that aren't configured\n- Run tests if a test runner is configured\n`\n : `\nRUN THESE COMMANDS:\n- ${adapter?.buildCommand || \"npm run build\"}\n- ${adapter?.lintCommand || \"npm run lint\"}\n- ${adapter?.typecheckCommand || \"npx tsc --noEmit\"}\n- npm run test (if tests exist)\n`;\n\n return `\nYou are a QA engineer reviewing code within the Forge development framework.\nYour job is to catch issues before code is merged to main.\n\nREVIEW CHECKLIST:\n1. Implementation matches the story description\n2. If design was approved — implementation matches the design\n${langCheck}\n4. Responsive design works at 375px, 768px, 1440px\n5. Error handling — what happens when things fail?\n6. Loading states — what does the user see while waiting?\n7. Empty states — what if there's no data?\n8. Accessibility — semantic HTML, focus management, screen reader support\n9. No debug logs (console.log / print() for debugging)\n10. No commented-out code\n11. No TODO/FIXME/HACK comments left behind\n12. No hardcoded values that should be configurable\n\n${runBlock}\n\nISSUE CLASSIFICATION:\n- MINOR: formatting, missing type annotation, unused import\n → Fix it directly, note what you fixed\n- MAJOR: broken logic, missing error handling, security issue, missing feature\n → List the issue with file path and line, do NOT attempt to fix\n\nOUTPUT:\nProvide a structured review summary:\n- Files reviewed\n- Issues found (with severity)\n- Issues auto-fixed\n- Commands run and their results\n- PASS or FAIL recommendation\n`.trim();\n}\n\n/** Fix system prompt — framework-aware commands */\nexport function getFixPrompt(framework?: string): string {\n const adapter = framework ? getAdapter(framework) : null;\n const isGeneric = adapter?.id === \"generic\";\n\n const verifyBlock = isGeneric\n ? `\nAFTER EVERY FIX:\n1. Detect the project's build/test commands from its config files\n2. Run whichever exist to verify nothing is broken\n3. Verify the fix works\n`\n : `\nAFTER EVERY FIX:\n1. Run: ${adapter?.buildCommand || \"npm run build\"}\n2. Run: ${adapter?.typecheckCommand || \"npx tsc --noEmit\"}\n3. Verify the fix works\n`;\n\n return `\nYou are a debugger and problem solver within the Forge development framework.\nYour job is to make targeted fixes without breaking anything else.\n\nPRINCIPLES:\n- Make the SMALLEST possible change to fix the issue\n- Do NOT refactor surrounding code — you're here to fix, not improve\n- Read the existing code carefully before changing anything\n- Understand the full context of what you're changing\n\nFOR VISUAL TWEAKS:\n- Change only the specific CSS/Tailwind classes needed\n- Verify the change doesn't break other viewports\n- Check both mobile and desktop after changing\n\nFOR BUG FIXES:\n- Read error messages and stack traces carefully\n- Trace the issue to its ROOT CAUSE\n- Fix the cause, not the symptom\n- Check if the same bug pattern exists elsewhere\n- Verify the fix by running the relevant command\n\n${verifyBlock}\n\nIf your fix introduces new errors, undo it and try a different approach.\n`.trim();\n}\n\n// ── Legacy exports for backward compatibility ────────────────\n// These are used by Worker when no framework is specified.\n\nexport const DESIGN_SYSTEM_PROMPT = getDesignPrompt();\nexport const BUILD_SYSTEM_PROMPT = getBuildPrompt();\nexport const REVIEW_SYSTEM_PROMPT = getReviewPrompt();\nexport const FIX_SYSTEM_PROMPT = getFixPrompt();\n","import simpleGit, { type SimpleGit } from \"simple-git\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\n// ============================================================\n// Git Manager\n// Handles branch strategy, tagging, and snapshots.\n// ============================================================\n\nexport class GitManager {\n private git: SimpleGit;\n private basePath: string;\n private cachedBranch: string | null = null;\n private repoVerified = false;\n\n constructor(basePath: string = process.cwd()) {\n this.basePath = basePath;\n this.git = simpleGit(basePath);\n }\n\n // ── Branch Operations ─────────────────────────────────────\n\n async createBranch(name: string): Promise<void> {\n // Always commit dirty state before switching branches\n await this.stashDirtyState();\n\n const currentBranch = await this.getCurrentBranch();\n if (currentBranch !== \"main\") {\n await this.git.checkout(\"main\");\n }\n await this.git.checkoutLocalBranch(name);\n }\n\n async checkout(branch: string): Promise<void> {\n await this.stashDirtyState();\n await this.git.checkout(branch);\n this.cachedBranch = branch;\n }\n\n async merge(branch: string): Promise<void> {\n await this.git.merge([branch, \"--no-ff\"]);\n }\n\n async deleteBranch(branch: string): Promise<void> {\n await this.git.deleteLocalBranch(branch, true);\n }\n\n async getCurrentBranch(): Promise<string> {\n if (this.cachedBranch) return this.cachedBranch;\n try {\n const status = await this.git.status();\n if (status.current) {\n this.cachedBranch = status.current;\n return this.cachedBranch;\n }\n } catch {\n // Don't cache on error — let next call retry\n }\n return \"main\";\n }\n\n async listBranches(): Promise<string[]> {\n const result = await this.git.branchLocal();\n return result.all;\n }\n\n // ── Commit Operations ─────────────────────────────────────\n\n async commitAll(message: string): Promise<void> {\n // Use git add + commit in one flow; skip status check — let commit fail silently if nothing staged\n await this.git.add(\".\");\n try {\n await this.git.commit(message);\n } catch (err: any) {\n // \"nothing to commit\" is not an error\n if (!err?.message?.includes(\"nothing to commit\")) throw err;\n }\n }\n\n async commitState(message: string): Promise<void> {\n await this.git.add(\".forge/\");\n await this.git.add(\"forge.config.json\");\n\n const status = await this.git.status();\n if (status.staged.length > 0) {\n await this.git.commit(`forge: ${message}`);\n }\n }\n\n // ── Tag Operations ────────────────────────────────────────\n\n async tag(name: string): Promise<void> {\n await this.git.addTag(name);\n }\n\n async listTags(): Promise<string[]> {\n const result = await this.git.tags();\n return result.all.filter((t) => t.startsWith(\"forge/\"));\n }\n\n async checkoutTag(tagName: string): Promise<void> {\n await this.stashDirtyState();\n await this.git.checkout(tagName);\n }\n\n // ── Diff & History ────────────────────────────────────────\n\n async getDiff(branch: string): Promise<string> {\n return this.git.diff([\"main\", branch]);\n }\n\n /** Diff between any two refs (tags, commits, branches) */\n async getDiff2(ref1: string, ref2: string): Promise<string> {\n return this.git.diff([ref1, ref2]);\n }\n\n async getLog(count: number = 10): Promise<any[]> {\n const log = await this.git.log({ maxCount: count });\n return log.all as any[];\n }\n\n /** Get the current HEAD commit hash */\n async getHead(): Promise<string> {\n const log = await this.git.log({ maxCount: 1 });\n return log.latest?.hash || \"\";\n }\n\n /** Revert a specific commit (creates a new revert commit) */\n async revertCommit(hash: string): Promise<void> {\n await this.git.raw([\"revert\", \"--no-edit\", hash]);\n }\n\n /** Get forge-related commits (feat:, fix:, forge:, docs:, ci:) */\n async getForgeLog(count: number = 20): Promise<Array<{ hash: string; date: string; message: string }>> {\n const log = await this.git.log({ maxCount: count });\n return (log.all as any[]).map((entry) => ({\n hash: entry.hash,\n date: entry.date,\n message: entry.message,\n }));\n }\n\n /** Get tags pointing at a specific commit */\n async getTagsAtCommit(hash: string): Promise<string[]> {\n try {\n const result = await this.git.raw([\"tag\", \"--points-at\", hash]);\n return result.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n }\n\n // ── Push Operations ─────────────────────────────────────\n\n /** Check if a remote named 'origin' exists */\n async hasRemote(): Promise<boolean> {\n try {\n const remotes = await this.git.getRemotes();\n return remotes.some((r) => r.name === \"origin\");\n } catch {\n return false;\n }\n }\n\n /** Push current branch to origin */\n async push(): Promise<void> {\n const branch = await this.getCurrentBranch();\n await this.git.push(\"origin\", branch, [\"--set-upstream\"]);\n }\n\n /** Push tags to origin */\n async pushTags(): Promise<void> {\n await this.git.pushTags(\"origin\");\n }\n\n // ── Status ────────────────────────────────────────────────\n\n async isClean(): Promise<boolean> {\n const status = await this.git.status();\n return status.isClean();\n }\n\n async hasUncommittedChanges(): Promise<boolean> {\n const status = await this.git.status();\n return !status.isClean();\n }\n\n // ── Init (for new projects) ───────────────────────────────\n\n async ensureRepo(): Promise<void> {\n if (this.repoVerified) return;\n\n const isRepo = await this.git.checkIsRepo();\n if (!isRepo) {\n await this.git.init();\n }\n // Ensure .gitignore has common entries\n await this.ensureGitignore();\n\n // Initial commit if repo is empty\n const log = await this.git.log().catch(() => null);\n if (!log || log.total === 0) {\n await this.git.add(\".\");\n await this.git.commit(\"Initial commit\");\n }\n\n this.repoVerified = true;\n }\n\n async ensureMainBranch(): Promise<void> {\n const current = await this.getCurrentBranch();\n if (current !== \"main\") {\n // Only check branches if we're not already on main\n const branches = await this.listBranches();\n if (!branches.includes(\"main\")) {\n await this.git.branch([\"-M\", \"main\"]);\n this.cachedBranch = \"main\";\n }\n }\n }\n\n // ── Internal ──────────────────────────────────────────────\n\n /** Commit any uncommitted changes before branch operations */\n private async stashDirtyState(): Promise<void> {\n const status = await this.git.status();\n if (status.isClean()) return;\n\n await this.git.add(\".\");\n await this.git.commit(\"forge: save state before branch switch\");\n }\n\n /** Ensure .gitignore covers build artifacts and forge internals */\n private async ensureGitignore(): Promise<void> {\n const gitignorePath = path.join(this.basePath, \".gitignore\");\n const requiredEntries = [\n \"node_modules/\",\n \".next/\",\n \".forge/snapshots/\",\n \"dist/\",\n \".env\",\n \".env.local\",\n ];\n\n let content = \"\";\n try {\n content = await fs.readFile(gitignorePath, \"utf-8\");\n } catch {\n // File doesn't exist yet\n }\n\n const missing = requiredEntries.filter((e) => !content.includes(e));\n if (missing.length > 0) {\n const addition = (content ? \"\\n\" : \"\") + missing.join(\"\\n\") + \"\\n\";\n await fs.appendFile(gitignorePath, addition);\n }\n }\n}\n","import fs from \"fs/promises\";\nimport path from \"path\";\nimport type {\n Plan,\n SprintState,\n Phase,\n ForgeConfig,\n Snapshot,\n} from \"../types/plan.js\";\n\n// ============================================================\n// State Manager\n// Reads/writes .forge/ JSON files. Source of truth for the sprint.\n// ============================================================\n\nconst FORGE_DIR = \".forge\";\nconst PLAN_FILE = \"plan.json\";\nconst STATE_FILE = \"state.json\";\nconst CONFIG_FILE = \"forge.config.json\";\nconst SNAPSHOTS_DIR = \"snapshots\";\n\nclass StateManager {\n private basePath: string;\n private cache: Map<string, { data: any; mtime: number }> = new Map();\n private dirCreated: Set<string> = new Set();\n\n constructor(basePath: string = process.cwd()) {\n this.basePath = basePath;\n }\n\n /** Clear all caches (call when basePath changes) */\n clearCache(): void {\n this.cache.clear();\n this.dirCreated.clear();\n }\n\n // ── Paths ─────────────────────────────────────────────────\n\n private forgePath(...parts: string[]): string {\n return path.join(this.basePath, FORGE_DIR, ...parts);\n }\n\n private rootPath(...parts: string[]): string {\n return path.join(this.basePath, ...parts);\n }\n\n // ── Plan ──────────────────────────────────────────────────\n\n async savePlan(plan: Plan): Promise<void> {\n await this.writeJson(this.forgePath(PLAN_FILE), plan);\n }\n\n async getPlan(): Promise<Plan | null> {\n return this.readJson<Plan>(this.forgePath(PLAN_FILE));\n }\n\n async hasPlan(): Promise<boolean> {\n return this.fileExists(this.forgePath(PLAN_FILE));\n }\n\n // ── State ─────────────────────────────────────────────────\n\n async getState(): Promise<SprintState> {\n const state = await this.readJson<SprintState>(\n this.forgePath(STATE_FILE)\n );\n return (\n state || {\n currentPhase: \"init\",\n currentStory: null,\n workerMode: null,\n queue: [],\n history: [],\n }\n );\n }\n\n async updatePhase(phase: Phase): Promise<void> {\n const state = await this.getState();\n state.currentPhase = phase;\n await this.writeJson(this.forgePath(STATE_FILE), state);\n }\n\n async updateState(updates: Partial<SprintState>): Promise<void> {\n const state = await this.getState();\n Object.assign(state, updates);\n await this.writeJson(this.forgePath(STATE_FILE), state);\n }\n\n async addHistoryEntry(entry: {\n action: string;\n storyId: string | null;\n details: string;\n snapshotId?: string;\n }): Promise<void> {\n const state = await this.getState();\n state.history.push({\n ...entry,\n timestamp: new Date().toISOString(),\n snapshotId: entry.snapshotId || null,\n });\n await this.writeJson(this.forgePath(STATE_FILE), state);\n }\n\n // ── Config ────────────────────────────────────────────────\n\n async getConfig(): Promise<ForgeConfig | null> {\n return this.readJson<ForgeConfig>(this.rootPath(CONFIG_FILE));\n }\n\n async isInitialized(): Promise<boolean> {\n return this.fileExists(this.rootPath(CONFIG_FILE));\n }\n\n // ── Snapshots ─────────────────────────────────────────────\n\n async saveSnapshot(data: {\n action: string;\n storyId: string | null;\n branch: string;\n commitBefore?: string;\n }): Promise<string> {\n const state = await this.getState();\n const id = String(state.history.length + 1).padStart(3, \"0\");\n\n const snapshot: Snapshot = {\n id,\n action: data.action,\n storyId: data.storyId,\n timestamp: new Date().toISOString(),\n files: [],\n branch: data.branch,\n commitBefore: data.commitBefore || \"\",\n };\n\n await this.writeJson(\n this.forgePath(SNAPSHOTS_DIR, `${id}-pre-${data.action}-${data.storyId || \"global\"}.json`),\n snapshot\n );\n\n await this.addHistoryEntry({\n action: data.action,\n storyId: data.storyId,\n details: `Snapshot taken before ${data.action}`,\n snapshotId: id,\n });\n\n return id;\n }\n\n async getSnapshot(id: string): Promise<Snapshot | null> {\n const dir = this.forgePath(SNAPSHOTS_DIR);\n const files = await fs.readdir(dir).catch(() => []);\n const match = files.find((f) => f.startsWith(id));\n if (!match) return null;\n return this.readJson<Snapshot>(path.join(dir, match));\n }\n\n async listSnapshots(): Promise<Snapshot[]> {\n const dir = this.forgePath(SNAPSHOTS_DIR);\n const files = await fs.readdir(dir).catch(() => []);\n const snapshots: Snapshot[] = [];\n for (const file of files.filter((f) => f.endsWith(\".json\"))) {\n const snapshot = await this.readJson<Snapshot>(path.join(dir, file));\n if (snapshot) snapshots.push(snapshot);\n }\n return snapshots.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n }\n\n // ── Design References ──────────────────────────────────────\n\n async saveDesignReferences(files: string[]): Promise<void> {\n const refDir = this.forgePath(\"designs\", \"references\");\n await fs.mkdir(refDir, { recursive: true });\n\n const manifest: Array<{ original: string; saved: string }> = [];\n for (const file of files) {\n const basename = path.basename(file);\n const dest = path.join(refDir, basename);\n await fs.copyFile(file, dest);\n manifest.push({ original: file, saved: dest });\n }\n\n await this.writeJson(this.forgePath(\"designs\", \"references.json\"), manifest);\n }\n\n async getDesignReferences(): Promise<string[]> {\n const manifest = await this.readJson<Array<{ saved: string }>>(\n this.forgePath(\"designs\", \"references.json\")\n );\n return manifest?.map((r) => r.saved) || [];\n }\n\n // ── Helpers ───────────────────────────────────────────────\n\n private async readJson<T>(filePath: string): Promise<T | null> {\n try {\n const stat = await fs.stat(filePath);\n const mtime = stat.mtimeMs;\n\n // Return cached if file hasn't changed\n const cached = this.cache.get(filePath);\n if (cached && cached.mtime === mtime) {\n return cached.data as T;\n }\n\n const content = await fs.readFile(filePath, \"utf-8\");\n const data = JSON.parse(content) as T;\n this.cache.set(filePath, { data, mtime });\n return data;\n } catch (err: any) {\n // File not found is expected — return null\n if (err?.code === \"ENOENT\") return null;\n // JSON parse error — file is corrupted, return null\n if (err instanceof SyntaxError) return null;\n // Permission or other system errors — propagate so caller knows\n throw err;\n }\n }\n\n private async writeJson(filePath: string, data: any): Promise<void> {\n const dir = path.dirname(filePath);\n // Only mkdir if we haven't already created this directory\n if (!this.dirCreated.has(dir)) {\n await fs.mkdir(dir, { recursive: true });\n this.dirCreated.add(dir);\n }\n const json = JSON.stringify(data, null, 2);\n await fs.writeFile(filePath, json);\n // Update cache immediately — avoid re-reading what we just wrote\n const stat = await fs.stat(filePath);\n this.cache.set(filePath, { data, mtime: stat.mtimeMs });\n }\n\n private async fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n }\n}\n\n// Singleton\nexport const stateManager = new StateManager();\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport inquirer from \"inquirer\";\nimport type {\n Plan,\n Story,\n ForgeConfig,\n QueuedChange,\n} from \"../../types/plan.js\";\nimport { Orchestrator } from \"../orchestrator/index.js\";\nimport { Worker, type WorkerProgressCallback } from \"../worker/index.js\";\nimport { GitManager } from \"../git/index.js\";\nimport { getAdapter } from \"../adapters/index.js\";\nimport { stateManager } from \"../../state/index.js\";\n\n// ============================================================\n// Pipeline Engine\n// Manages the phase flow: plan > design > build > review\n// with human review gates between each phase.\n// Builds on main — no feature branches. Per-story commits + tags.\n// ============================================================\n\nconst MAX_REGEN_ATTEMPTS = 5;\n\nexport class Pipeline {\n private orchestrator: Orchestrator;\n private worker: Worker;\n private git: GitManager;\n private config: ForgeConfig;\n private plan: Plan | null = null;\n private changeQueue: QueuedChange[] = [];\n\n constructor(config: ForgeConfig) {\n this.config = config;\n this.orchestrator = new Orchestrator(config);\n this.worker = new Worker(config, {});\n this.git = new GitManager();\n }\n\n // ── Full Sprint (all phases) ──────────────────────────────\n\n async runSprint(description: string): Promise<void> {\n console.log(chalk.bold(\"\\n forge\") + chalk.dim(\" sprint\\n\"));\n\n await this.git.ensureRepo();\n await this.git.ensureMainBranch();\n\n // Phase 1: Plan\n this.plan = await this.runPlanPhase(description);\n if (!this.plan) return;\n\n // Phase 2: Design (skip if framework doesn't support it)\n const adapter = getAdapter(this.config.framework);\n if (adapter.designSupport) {\n await this.runDesignPhase(this.plan);\n } else {\n console.log(chalk.dim(`\\n Design skipped (${adapter.name} — no Storybook support)\\n`));\n }\n\n // Phase 3: Build\n await this.runBuildPhase(this.plan);\n\n // Phase 4: Review\n await this.runReviewPhase(this.plan);\n\n // Done\n console.log(chalk.dim(\"\\n ─────────────────────────────────\"));\n console.log(chalk.bold(\" Sprint complete\\n\"));\n console.log(chalk.dim(\" Run your app and test it.\"));\n console.log(chalk.dim(' Use ' + chalk.white('forge fix \"description\"') + ' to make changes.'));\n console.log(chalk.dim(\" Use \" + chalk.white(\"forge undo\") + \" to revert.\\n\"));\n }\n\n // ── Phase 1: Plan ────────────────────────────────────────\n\n async runPlanPhase(description: string, attempt = 1): Promise<Plan | null> {\n if (attempt === 1) {\n console.log(chalk.bold(\" Plan\\n\"));\n }\n\n const spinner = ora({ text: \"Analyzing requirements...\", indent: 2 }).start();\n\n let plan: Plan;\n try {\n plan = await this.orchestrator.generatePlan(description);\n } catch (err) {\n spinner.fail(\"Plan generation failed\");\n console.log(chalk.red(` ${err instanceof Error ? err.message : err}`));\n return null;\n }\n spinner.succeed(\"Plan generated\");\n\n this.displayPlan(plan);\n\n // User gate\n const { action } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"action\",\n message: \"Action\",\n choices: [\n { name: \"Approve plan\", value: \"approve\" },\n { name: \"Edit (describe changes)\", value: \"edit\" },\n { name: \"Regenerate\", value: \"regen\" },\n { name: \"Cancel\", value: \"cancel\" },\n ],\n },\n ]);\n\n switch (action) {\n case \"approve\":\n await stateManager.savePlan(plan);\n await stateManager.updatePhase(\"plan\");\n await this.git.commitState(\"Sprint plan approved\");\n await this.git.tag(\"forge/v0.0-plan\");\n console.log(chalk.green(\" Plan saved\\n\"));\n return plan;\n\n case \"edit\": {\n if (attempt >= MAX_REGEN_ATTEMPTS) {\n console.log(chalk.yellow(` Max edit attempts (${MAX_REGEN_ATTEMPTS}) reached. Approving current plan.`));\n await stateManager.savePlan(plan);\n return plan;\n }\n const { changes } = await inquirer.prompt([\n { type: \"input\", name: \"changes\", message: \"Describe changes:\" },\n ]);\n console.log(chalk.dim(\" Re-planning...\"));\n return this.runPlanPhase(`${description}\\n\\nUser edits: ${changes}`, attempt + 1);\n }\n\n case \"regen\": {\n if (attempt >= MAX_REGEN_ATTEMPTS) {\n console.log(chalk.yellow(` Max regeneration attempts (${MAX_REGEN_ATTEMPTS}) reached.`));\n return null;\n }\n return this.runPlanPhase(description, attempt + 1);\n }\n\n case \"cancel\":\n console.log(chalk.dim(\" Cancelled.\"));\n return null;\n\n default:\n return null;\n }\n }\n\n // ── Phase 2: Design ──────────────────────────────────────\n\n async runDesignPhase(plan: Plan): Promise<void> {\n const uiStories = this.getStoriesByType(plan, [\"ui\", \"fullstack\"]);\n\n if (uiStories.length === 0) {\n console.log(chalk.dim(\"\\n No UI stories, skipping design.\\n\"));\n return;\n }\n\n console.log(chalk.bold(`\\n Design`) + chalk.dim(` · ${uiStories.length} stories\\n`));\n\n for (const story of uiStories) {\n const spinner = ora({ text: story.title, indent: 4 }).start();\n\n const prompt = this.orchestrator.craftWorkerPrompt(story, \"design\", { plan });\n\n const result = await this.worker.run(\"design\", prompt, {\n onProgress: (event) => {\n if (event.type === \"tool_use\") {\n spinner.text = event.content;\n }\n },\n });\n\n if (result.success) {\n spinner.succeed(story.title);\n } else {\n spinner.fail(story.title);\n console.log(chalk.red(` ${result.errors.join(\", \")}`));\n continue;\n }\n\n // User gate\n const adapter = getAdapter(this.config.framework);\n console.log(chalk.dim(` Preview: http://localhost:${adapter.devPort}\\n`));\n\n const { approval } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"approval\",\n message: `Approve \"${story.title}\"?`,\n choices: [\n { name: \"Approve\", value: \"approve\" },\n { name: \"Request changes\", value: \"change\" },\n { name: \"Skip\", value: \"skip\" },\n ],\n },\n ]);\n\n if (approval === \"approve\") {\n story.designApproved = true;\n story.status = \"design-approved\";\n console.log(chalk.green(` Approved\\n`));\n } else if (approval === \"change\") {\n const { feedback } = await inquirer.prompt([\n { type: \"input\", name: \"feedback\", message: \"Describe changes:\" },\n ]);\n // Re-run design with feedback\n const fixResult = await this.worker.run(\"fix\", `Revise design for \"${story.title}\": ${feedback}`);\n if (fixResult.success) {\n console.log(chalk.dim(\" Revised.\\n\"));\n }\n }\n }\n\n await stateManager.savePlan(plan);\n await stateManager.updatePhase(\"design\");\n await this.git.commitAll(\"forge: designs reviewed\");\n await this.git.tag(\"forge/v0.1-designs\");\n\n console.log(chalk.dim(\" Design phase complete\\n\"));\n }\n\n // ── Phase 3: Build ───────────────────────────────────────\n\n async runBuildPhase(plan: Plan): Promise<void> {\n const buildableStories = this.getAllStories(plan).filter(\n (s) => s.status === \"design-approved\" || s.status === \"planned\"\n );\n\n if (buildableStories.length === 0) {\n console.log(chalk.dim(\"\\n No stories to build.\\n\"));\n return;\n }\n\n console.log(chalk.bold(`\\n Build`) + chalk.dim(` · ${buildableStories.length} stories\\n`));\n\n for (const story of buildableStories) {\n const spinner = ora({ text: story.title, indent: 4 }).start();\n\n // Snapshot before building\n const headBefore = await this.git.getHead();\n await stateManager.saveSnapshot({\n action: \"build\",\n storyId: story.id,\n branch: \"main\",\n commitBefore: headBefore,\n });\n\n story.status = \"building\";\n await stateManager.savePlan(plan);\n\n const prompt = this.orchestrator.craftWorkerPrompt(story, \"build\", {\n plan,\n designMeta: story.designApproved ? { storyId: story.id } : undefined,\n });\n\n const result = await this.worker.run(\"build\", prompt, {\n onProgress: (event) => {\n if (event.type === \"tool_use\") {\n spinner.text = event.content;\n }\n },\n });\n\n if (result.success) {\n await this.git.commitAll(`feat: ${story.title}`);\n story.status = \"reviewing\";\n spinner.succeed(story.title + chalk.dim(` · ${result.filesCreated.length} files`));\n } else {\n story.status = \"blocked\";\n spinner.fail(story.title);\n for (const error of result.errors) {\n console.log(chalk.red(` ${error}`));\n }\n }\n\n await stateManager.savePlan(plan);\n await this.processQueue(plan);\n }\n\n await stateManager.updatePhase(\"build\");\n console.log(chalk.dim(\"\\n Build phase complete\\n\"));\n }\n\n // ── Phase 4: Review ──────────────────────────────────────\n\n async runReviewPhase(plan: Plan): Promise<void> {\n const reviewableStories = this.getAllStories(plan).filter(\n (s) => s.status === \"reviewing\"\n );\n\n if (reviewableStories.length === 0) return;\n\n console.log(chalk.bold(`\\n Review`) + chalk.dim(` · ${reviewableStories.length} stories\\n`));\n\n for (const story of reviewableStories) {\n const spinner = ora({ text: story.title, indent: 4 }).start();\n\n const prompt = this.orchestrator.craftWorkerPrompt(story, \"review\", {\n plan,\n designMeta: story.designApproved ? { storyId: story.id } : undefined,\n });\n\n let result;\n try {\n result = await this.worker.run(\"review\", prompt);\n } catch (err) {\n spinner.fail(story.title + chalk.dim(\" — review error\"));\n console.log(chalk.red(` ${err instanceof Error ? err.message : err}`));\n continue;\n }\n\n if (result.success) {\n const tagName = `forge/v0.${this.getNextTagNumber()}-${story.id}`;\n await this.git.tag(tagName);\n story.tags.push(tagName);\n story.status = \"done\";\n spinner.succeed(story.title + chalk.dim(` [${tagName}]`));\n } else {\n spinner.fail(story.title);\n console.log(chalk.dim(` ${result.summary}`));\n }\n\n await stateManager.savePlan(plan);\n }\n\n await stateManager.updatePhase(\"review\");\n console.log(chalk.dim(\"\\n Review phase complete\\n\"));\n }\n\n // ── Change Queue ─────────────────────────────────────────\n\n queueChange(change: QueuedChange): void {\n this.changeQueue.push(change);\n console.log(chalk.dim(` Queued: \"${change.message}\"`));\n }\n\n private async processQueue(plan: Plan): Promise<void> {\n if (this.changeQueue.length === 0) return;\n\n console.log(chalk.dim(`\\n Processing ${this.changeQueue.length} queued changes...\\n`));\n\n for (const change of this.changeQueue) {\n const decision = await this.orchestrator.routeUserInput(\n change.message,\n await stateManager.getState()\n );\n\n if (decision.action === \"route-to-worker\" && decision.prompt) {\n const mode = decision.workerMode || \"fix\";\n const spinner = ora({ text: change.message, indent: 4 }).start();\n const result = await this.worker.run(mode, decision.prompt);\n if (result.success) {\n await this.git.commitAll(`fix: ${change.message}`);\n spinner.succeed(change.message);\n } else {\n spinner.fail(change.message);\n }\n }\n }\n\n this.changeQueue = [];\n }\n\n // ── Helpers ──────────────────────────────────────────────\n\n private displayPlan(plan: Plan): void {\n console.log(chalk.bold(`\\n ${plan.project}`) + chalk.dim(` · ${plan.framework}`));\n console.log(chalk.dim(` ${plan.description}\\n`));\n\n for (const epic of plan.epics) {\n console.log(chalk.dim(` ${epic.title}`));\n for (const story of epic.stories) {\n const tag = story.type === \"ui\" ? \"ui\" : story.type === \"backend\" ? \"api\" : \"full\";\n console.log(` ${chalk.dim(`[${tag}]`)} ${story.id} ${chalk.dim(\"—\")} ${story.title}`);\n }\n console.log(\"\");\n }\n }\n\n private getAllStories(plan: Plan): Story[] {\n return plan.epics.flatMap((epic) => epic.stories);\n }\n\n private getStoriesByType(plan: Plan, types: string[]): Story[] {\n return this.getAllStories(plan).filter((s) => types.includes(s.type));\n }\n\n private tagCounter = 2;\n private getNextTagNumber(): number {\n return this.tagCounter++;\n }\n}\n","import chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\nimport readline from \"readline\";\nimport inquirer from \"inquirer\";\nimport type {\n Plan,\n Story,\n ForgeConfig,\n QueuedChange,\n} from \"../../types/plan.js\";\nimport { Orchestrator } from \"../orchestrator/index.js\";\nimport { Worker, type WorkerProgressCallback, type WorkerUsage } from \"../worker/index.js\";\nimport { GitManager } from \"../git/index.js\";\nimport { stateManager } from \"../../state/index.js\";\nimport { playSound } from \"../utils/sound.js\";\nimport { GitHubSync } from \"../github/index.js\";\nimport { buildAttachmentPrompt, type Attachment } from \"../utils/attachments.js\";\n\n// ============================================================\n// Autonomous Pipeline\n// Runs plan > design > build > review with no human gates\n// (except a review gate after build).\n// Shows live progress with elapsed timer.\n// Type messages anytime — queued and handled between stories.\n// Independent stories are built in parallel.\n// ============================================================\n\nexport interface AutoPipelineOptions {\n workingDir?: string;\n sandbox?: boolean;\n yes?: boolean;\n allowedDomains?: string[];\n quiet?: boolean;\n mute?: boolean;\n deploy?: boolean;\n skipDesign?: boolean;\n attachments?: Attachment[];\n}\n\nexport class AutoPipeline {\n private orchestrator: Orchestrator;\n private worker: Worker;\n private git: GitManager;\n private config: ForgeConfig;\n private plan: Plan | null = null;\n private options: AutoPipelineOptions;\n private chatQueue: QueuedChange[] = [];\n private rl: readline.Interface | null = null;\n private startTime: number = 0;\n private totalUsage: WorkerUsage = { inputTokens: 0, outputTokens: 0, costUsd: 0, durationMs: 0 };\n private shuttingDown = false;\n private activeSpinner: Ora | null = null;\n private tagCounter = 1;\n\n constructor(config: ForgeConfig, options: AutoPipelineOptions = {}) {\n this.config = config;\n this.options = options;\n this.orchestrator = new Orchestrator(config);\n this.worker = new Worker(\n config,\n {\n sandbox: options.sandbox ?? true,\n yes: options.yes ?? false,\n workingDir: options.workingDir,\n allowedDomains: options.allowedDomains,\n },\n options.mute,\n );\n this.git = new GitManager();\n this.setupGracefulShutdown();\n }\n\n // ── Graceful Shutdown ────────────────────────────────────\n\n private setupGracefulShutdown(): void {\n const handler = async () => {\n if (this.shuttingDown) return;\n this.shuttingDown = true;\n\n // Stop spinner so shutdown message is visible\n if (this.activeSpinner?.isSpinning) {\n this.activeSpinner.stop();\n }\n\n console.log(chalk.yellow(\"\\n\\n Interrupted — saving progress...\"));\n\n try {\n if (this.plan) {\n await stateManager.savePlan(this.plan);\n await this.git.commitAll(\"forge: save progress (interrupted)\");\n console.log(chalk.dim(\" Progress saved. Resume with: forge resume\\n\"));\n }\n } catch {\n console.log(chalk.dim(\" Could not save progress.\\n\"));\n }\n\n this.stopChatListener();\n process.exit(130);\n };\n\n process.on(\"SIGINT\", handler);\n process.on(\"SIGTERM\", handler);\n }\n\n // ── Resume an interrupted sprint ──────────────────────────\n\n async resume(existingPlan: Plan): Promise<{ success: boolean; plan: Plan; errors: string[] }> {\n const errors: string[] = [];\n this.startTime = Date.now();\n this.plan = existingPlan;\n\n console.log(chalk.bold(\"\\n forge\") + chalk.dim(\" resume\"));\n console.log(chalk.dim(` Continuing from last checkpoint\\n`));\n\n this.startChatListener();\n await this.git.ensureRepo();\n await this.git.ensureMainBranch();\n\n const allStories = this.getAllStories(this.plan);\n const needsDesign = allStories.some(\n (s) => s.status === \"planned\" && (s.type === \"ui\" || s.type === \"fullstack\")\n );\n const needsBuild = allStories.some(\n (s) => s.status === \"planned\" || s.status === \"design-approved\"\n );\n const needsReview = allStories.some((s) => s.status === \"reviewing\");\n\n if (!needsDesign && !needsBuild && !needsReview) {\n console.log(chalk.green(\" Nothing to resume — all stories are complete or blocked.\\n\"));\n this.stopChatListener();\n return { success: true, plan: this.plan, errors };\n }\n\n // Design (only stories not yet designed)\n if (needsDesign && !this.options.skipDesign) {\n try { await this.runDesignPhase(this.plan); }\n catch (err) {\n await this.saveProgressOnError(\"design\");\n errors.push(`Design: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n // Build (only stories not yet built)\n if (needsBuild) {\n try { await this.runBuildPhase(this.plan); }\n catch (err) {\n await this.saveProgressOnError(\"build\");\n errors.push(`Build: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n // Review (only stories awaiting review)\n if (needsReview || needsBuild) {\n const gateAction = await this.reviewGate();\n if (gateAction === \"abort\") {\n this.stopChatListener();\n this.printSummary(errors);\n return { success: false, plan: this.plan, errors: [...errors, \"Aborted\"] };\n }\n if (gateAction !== \"skip\") {\n try { await this.runReviewPhase(this.plan); }\n catch (err) {\n await this.saveProgressOnError(\"review\");\n errors.push(`Review: ${err instanceof Error ? err.message : err}`);\n }\n }\n }\n\n // Auto-push on resume too\n await this.autoPush();\n\n this.stopChatListener();\n this.printSummary(errors);\n await stateManager.updatePhase(\"done\");\n\n const failedCount = allStories.filter((s) => s.status === \"blocked\").length;\n return { success: errors.length === 0 && failedCount === 0, plan: this.plan, errors };\n }\n\n // ── Full Autonomous Sprint ─────────────────────────────────\n\n async run(description: string): Promise<{ success: boolean; plan: Plan | null; errors: string[] }> {\n const errors: string[] = [];\n this.startTime = Date.now();\n\n console.log(chalk.bold(\"\\n forge\") + chalk.dim(\" auto\"));\n const flags = [\n `sandbox ${this.options.sandbox !== false ? \"on\" : \"off\"}`,\n ...(this.options.yes ? [\"auto-approve on\"] : []),\n ].join(\" · \");\n console.log(chalk.dim(` ${flags} · type a message anytime to queue feedback\\n`));\n\n this.startChatListener();\n\n await this.git.ensureRepo();\n await this.git.ensureMainBranch();\n\n // ── Plan ───────────────────────────────────────────────\n const planSpinner = ora({ text: `${this.elapsed()} Planning...`, indent: 2 }).start();\n this.activeSpinner = planSpinner;\n try {\n const attachmentContext = buildAttachmentPrompt(this.options.attachments || []);\n this.plan = await this.orchestrator.generatePlan(description + attachmentContext);\n planSpinner.succeed(`${this.elapsed()} Plan ready`);\n this.activeSpinner = null;\n this.displayPlan(this.plan);\n await stateManager.savePlan(this.plan);\n await stateManager.updatePhase(\"plan\");\n await this.git.commitState(\"Sprint plan\");\n await this.git.tag(\"forge/v0.0-plan\");\n\n // Sync to GitHub Issues if enabled\n await this.syncToGitHub(this.plan);\n } catch (err) {\n planSpinner.fail(`${this.elapsed()} Planning failed`);\n this.activeSpinner = null;\n const msg = err instanceof Error ? err.message : String(err);\n console.log(chalk.red(`\\n ${msg}`));\n if (err instanceof Error && err.stack) {\n console.log(chalk.dim(` ${err.stack.split(\"\\n\").slice(1, 3).join(\"\\n \")}`));\n }\n this.stopChatListener();\n return { success: false, plan: null, errors: [`Plan: ${msg}`] };\n }\n\n this.showInputHint();\n\n // ── Design ─────────────────────────────────────────────\n if (this.options.skipDesign) {\n // Mark all stories as ready for build (skip design = treat as approved)\n for (const story of this.getAllStories(this.plan)) {\n if (story.status === \"planned\") {\n story.designApproved = true;\n }\n }\n console.log(chalk.dim(`\\n Design skipped (--skip-design)\\n`));\n } else {\n try { await this.runDesignPhase(this.plan); }\n catch (err) {\n await this.saveProgressOnError(\"design\");\n errors.push(`Design: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n // ── Build ──────────────────────────────────────────────\n try { await this.runBuildPhase(this.plan); }\n catch (err) {\n await this.saveProgressOnError(\"build\");\n errors.push(`Build: ${err instanceof Error ? err.message : err}`);\n }\n\n // ── README ─────────────────────────────────────────────\n try { await this.generateReadme(this.plan); }\n catch (err) { errors.push(`README: ${err instanceof Error ? err.message : err}`); }\n\n // ── Review Gate ────────────────────────────────────────\n const gateAction = await this.reviewGate();\n\n if (gateAction === \"abort\") {\n this.stopChatListener();\n this.printSummary(errors);\n await stateManager.updatePhase(\"done\");\n return { success: false, plan: this.plan, errors: [...errors, \"Aborted by user\"] };\n }\n\n // ── Review ─────────────────────────────────────────────\n if (gateAction !== \"skip\") {\n try { await this.runReviewPhase(this.plan); }\n catch (err) {\n await this.saveProgressOnError(\"review\");\n errors.push(`Review: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n // ── Deploy (optional) ──────────────────────────────────\n if (this.options.deploy) {\n try { await this.runDeployPhase(this.plan); }\n catch (err) { errors.push(`Deploy: ${err instanceof Error ? err.message : err}`); }\n }\n\n // ── Auto-push to GitHub ───────────────────────────────\n await this.autoPush();\n\n this.stopChatListener();\n this.printSummary(errors);\n await stateManager.updatePhase(\"done\");\n\n const allStories = this.getAllStories(this.plan);\n const failedCount = allStories.filter((s) => s.status === \"blocked\").length;\n return { success: errors.length === 0 && failedCount === 0, plan: this.plan, errors };\n }\n\n /** Save current progress when a phase fails — prevents data loss */\n private async saveProgressOnError(phase: string): Promise<void> {\n try {\n if (this.plan) {\n await stateManager.savePlan(this.plan);\n await stateManager.updatePhase(phase as any);\n await this.git.commitAll(`forge: save progress (${phase} interrupted)`);\n console.log(chalk.dim(` Progress saved. Resume with: forge resume\\n`));\n }\n } catch {\n // Best-effort — don't let save failure mask the original error\n }\n }\n\n // ── Elapsed Timer ─────────────────────────────────────────\n\n private elapsed(): string {\n const sec = Math.floor((Date.now() - this.startTime) / 1000);\n const minutes = Math.floor(sec / 60);\n const seconds = sec % 60;\n return chalk.dim(`[${minutes}:${seconds.toString().padStart(2, \"0\")}]`);\n }\n\n // ── Progress Helper with Timer ────────────────────────────\n\n private makeProgress(\n spinner: Ora,\n storyTitle: string\n ): { onProgress: WorkerProgressCallback; stop: () => void } {\n if (this.options.quiet) {\n return { onProgress: () => {}, stop: () => {} };\n }\n\n let lastDetail = \"\";\n\n const update = () => {\n if (!spinner.isSpinning) return;\n const prefix = this.elapsed();\n const detail = lastDetail ? \" \" + chalk.dim(lastDetail) : \"\";\n spinner.text = `${prefix} ${storyTitle}${detail}`;\n };\n\n // Tick every 5 seconds — keeps timer fresh without excessive terminal redraws\n const interval = setInterval(update, 5000);\n\n const onProgress: WorkerProgressCallback = (event) => {\n switch (event.type) {\n case \"tool_use\":\n lastDetail = event.content;\n break;\n case \"tool_running\":\n if (event.elapsed && event.elapsed > 3) {\n lastDetail = `${event.tool} (${Math.round(event.elapsed!)}s)`;\n }\n break;\n case \"tool_done\":\n lastDetail = event.content.slice(0, 80);\n break;\n }\n update();\n };\n\n return {\n onProgress,\n stop: () => clearInterval(interval),\n };\n }\n\n // ── Input Hint ────────────────────────────────────────────\n\n private showInputHint(): void {\n if (process.stdout.isTTY && !this.options.quiet) {\n // Stop spinner briefly so the hint is visible\n const wasSpinning = this.activeSpinner?.isSpinning ?? false;\n const spinnerText = this.activeSpinner?.text ?? \"\";\n if (wasSpinning) this.activeSpinner!.stop();\n\n process.stdout.write(chalk.dim(\"\\n ─ type a message and press enter ─\\n > \"));\n\n if (wasSpinning && this.activeSpinner) {\n this.activeSpinner.start(spinnerText);\n }\n }\n }\n\n // ── Dependency Grouping ───────────────────────────────────\n\n private groupByDependency(stories: Story[]): Story[][] {\n const batches: Story[][] = [];\n const completed = new Set<string>();\n const remaining = new Set(stories.map((s) => s.id));\n const storyMap = new Map(stories.map((s) => [s.id, s]));\n\n // Also treat already-done stories as completed deps\n if (this.plan) {\n for (const s of this.getAllStories(this.plan)) {\n if (s.status === \"done\" || s.status === \"reviewing\") {\n completed.add(s.id);\n }\n }\n }\n\n let iterations = 0;\n const maxIterations = stories.length + 1; // Safety: prevent infinite loop on circular deps\n\n while (remaining.size > 0 && iterations < maxIterations) {\n iterations++;\n\n const batch: Story[] = [];\n for (const id of remaining) {\n const story = storyMap.get(id)!;\n const depsReady = story.dependencies.every(\n (dep) => completed.has(dep) || !remaining.has(dep) // dep done or not in buildable set\n );\n if (depsReady) {\n batch.push(story);\n }\n }\n\n if (batch.length === 0) {\n // Circular deps — break the cycle by running remaining stories sequentially\n for (const id of remaining) {\n batches.push([storyMap.get(id)!]);\n }\n break;\n }\n\n batches.push(batch);\n for (const s of batch) {\n completed.add(s.id);\n remaining.delete(s.id);\n }\n }\n\n return batches;\n }\n\n // ── Design Phase (parallel) ───────────────────────────────\n\n private async runDesignPhase(plan: Plan): Promise<void> {\n const uiStories = this.getStoriesByType(plan, [\"ui\", \"fullstack\"]).filter(\n (s) => s.status === \"planned\"\n );\n if (uiStories.length === 0) return;\n\n console.log(chalk.bold(`\\n Design`) + chalk.dim(` · ${uiStories.length} stories\\n`));\n\n // Design stories are independent — run in parallel\n if (uiStories.length > 1) {\n await Promise.all(\n uiStories.map((story, i) =>\n this.designSingleStory(story, plan, i + 1, uiStories.length)\n )\n );\n } else {\n await this.designSingleStory(uiStories[0], plan, 1, 1);\n }\n\n await stateManager.savePlan(plan);\n await stateManager.updatePhase(\"design\");\n await this.git.commitState(\"Designs complete\");\n await this.git.tag(\"forge/v0.1-designs\");\n\n await this.processChatQueue();\n this.showInputHint();\n }\n\n private async designSingleStory(\n story: Story,\n plan: Plan,\n index: number,\n total: number\n ): Promise<void> {\n const label = `[${index}/${total}] ${story.title}`;\n const spinner = ora({ text: `${this.elapsed()} ${label}`, indent: 2 }).start();\n this.activeSpinner = spinner;\n const progress = this.makeProgress(spinner, label);\n\n try {\n story.status = \"designing\";\n\n const prompt = this.orchestrator.craftWorkerPrompt(story, \"design\", { plan });\n const result = await this.worker.run(\"design\", prompt, {\n onProgress: progress.onProgress,\n });\n\n this.addUsage(result.usage);\n const tokens = chalk.dim(\n `${this.formatTokens(result.usage.inputTokens)} in / ${this.formatTokens(result.usage.outputTokens)} out`\n );\n\n if (result.success) {\n spinner.succeed(`${this.elapsed()} ${label} ${tokens}`);\n story.designApproved = true;\n story.status = \"design-approved\";\n } else {\n spinner.warn(`${this.elapsed()} ${label}` + chalk.dim(\" skipped\") + ` ${tokens}`);\n // Still mark as design-approved so build can proceed\n story.designApproved = false;\n story.status = \"design-approved\";\n }\n } finally {\n progress.stop();\n this.activeSpinner = null;\n }\n }\n\n // ── Build Phase (parallel by dependency) ──────────────────\n\n private async runBuildPhase(plan: Plan): Promise<void> {\n const buildable = this.getAllStories(plan).filter(\n (s) => s.status === \"design-approved\" || s.status === \"planned\"\n );\n if (buildable.length === 0) return;\n\n console.log(chalk.bold(`\\n Build`) + chalk.dim(` · ${buildable.length} stories\\n`));\n\n const batches = this.groupByDependency(buildable);\n let storyIndex = 0;\n\n for (const batch of batches) {\n if (batch.length === 1) {\n storyIndex++;\n await this.buildSingleStory(batch[0], plan, storyIndex, buildable.length, false);\n } else {\n // Parallel batch — stories run concurrently\n console.log(chalk.dim(` ${this.elapsed()} parallel: ${batch.map((s) => s.title).join(\", \")}`));\n\n // Capture indices before async work\n const indexedBatch = batch.map((story) => {\n storyIndex++;\n return { story, index: storyIndex };\n });\n\n // Run in parallel but do NOT let parallel builds commit individually\n await Promise.all(\n indexedBatch.map(({ story, index }) =>\n this.buildSingleStory(story, plan, index, buildable.length, true)\n )\n );\n\n // Commit all parallel changes together\n const builtTitles = batch\n .filter((s) => s.status === \"reviewing\")\n .map((s) => s.title);\n if (builtTitles.length > 0) {\n await this.git.commitAll(`feat: ${builtTitles.join(\", \")}`);\n }\n }\n\n await stateManager.savePlan(plan);\n await this.processChatQueue();\n this.showInputHint();\n }\n\n await stateManager.updatePhase(\"build\");\n }\n\n private async buildSingleStory(\n story: Story,\n plan: Plan,\n index: number,\n total: number,\n parallel: boolean\n ): Promise<void> {\n const label = `[${index}/${total}] ${story.title}`;\n const spinner = ora({ text: `${this.elapsed()} ${label}`, indent: 2 }).start();\n this.activeSpinner = spinner;\n const progress = this.makeProgress(spinner, label);\n\n try {\n // Snapshot before building (capture current HEAD for undo)\n const headBefore = await this.git.getHead();\n await stateManager.saveSnapshot({\n action: \"build\",\n storyId: story.id,\n branch: \"main\",\n commitBefore: headBefore,\n });\n\n story.status = \"building\";\n\n const prompt = this.orchestrator.craftWorkerPrompt(story, \"build\", {\n plan,\n designMeta: story.designApproved ? { storyId: story.id } : undefined,\n });\n\n const result = await this.worker.run(\"build\", prompt, {\n onProgress: progress.onProgress,\n });\n\n this.addUsage(result.usage);\n const tokens = chalk.dim(\n `${this.formatTokens(result.usage.inputTokens)} in / ${this.formatTokens(result.usage.outputTokens)} out`\n );\n\n if (result.success) {\n if (!parallel) {\n await this.git.commitAll(`feat: ${story.title}`);\n }\n story.status = \"reviewing\";\n spinner.succeed(\n `${this.elapsed()} ${label}` +\n chalk.dim(` · ${result.filesCreated.length} files`) +\n ` ${tokens}`\n );\n } else {\n story.status = \"blocked\";\n spinner.fail(`${this.elapsed()} ${label} ${tokens}`);\n for (const error of result.errors) {\n console.log(chalk.red(` ${error}`));\n }\n // Show max-turns warning prominently\n if (result.errors.some((e) => e.includes(\"safety cap\"))) {\n console.log(chalk.yellow(` Tip: Story may be too large. Try splitting it into smaller stories.`));\n }\n }\n } finally {\n progress.stop();\n this.activeSpinner = null;\n }\n }\n\n // ── README Generation ─────────────────────────────────────\n\n private async generateReadme(plan: Plan): Promise<void> {\n const builtStories = this.getAllStories(plan).filter(\n (s) => s.status === \"reviewing\" || s.status === \"done\"\n );\n if (builtStories.length === 0) return;\n\n const label = \"README.md\";\n const spinner = ora({ text: `${this.elapsed()} Generating ${label}`, indent: 2 }).start();\n this.activeSpinner = spinner;\n const progress = this.makeProgress(spinner, label);\n\n try {\n const storyList = builtStories\n .map((s) => `- ${s.title}: ${s.description}`)\n .join(\"\\n\");\n\n const prompt = `\n Generate a README.md for this project.\n\n Project: ${plan.project}\n Description: ${plan.description}\n Framework: ${plan.framework}\n\n Features built:\n ${storyList}\n\n Read the actual codebase to understand the project structure.\n\n Include these sections:\n - Project name and description\n - Key features (from the stories above)\n - Tech stack\n - Getting started (install, dev server, build)\n - Project structure (based on actual files you can see)\n\n Write the README.md file in the project root.\n Keep it concise and professional.\n `;\n\n const result = await this.worker.run(\"build\", prompt, {\n onProgress: progress.onProgress,\n });\n this.addUsage(result.usage);\n\n if (result.success) {\n await this.git.commitAll(\"docs: generate README.md\");\n spinner.succeed(`${this.elapsed()} ${label}`);\n } else {\n spinner.warn(`${this.elapsed()} ${label}` + chalk.dim(\" skipped\"));\n }\n } finally {\n progress.stop();\n this.activeSpinner = null;\n }\n }\n\n // ── Review Gate ───────────────────────────────────────────\n\n private async reviewGate(): Promise<\"continue\" | \"skip\" | \"abort\"> {\n if (this.options.yes) return \"continue\";\n if (!process.stdout.isTTY) return \"continue\";\n\n // Notify user that build is done\n if (!this.options.mute) {\n playSound();\n }\n\n // Stop spinner and chat listener so inquirer can take over stdin cleanly\n if (this.activeSpinner?.isSpinning) {\n this.activeSpinner.stop();\n this.activeSpinner = null;\n }\n this.stopChatListener();\n\n console.log(\"\");\n\n const { action } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"action\",\n message: `${this.elapsed()} Build complete. What next?`,\n choices: [\n { name: \"Continue to review\", value: \"continue\" },\n { name: \"Skip review\", value: \"skip\" },\n { name: \"Abort\", value: \"abort\" },\n ],\n },\n ]);\n\n // Resume readline\n this.startChatListener();\n\n return action;\n }\n\n // ── Review Phase ──────────────────────────────────────────\n\n private async runReviewPhase(plan: Plan): Promise<void> {\n const reviewable = this.getAllStories(plan).filter((s) => s.status === \"reviewing\");\n if (reviewable.length === 0) return;\n\n console.log(chalk.bold(`\\n Review`) + chalk.dim(` · ${reviewable.length} stories\\n`));\n\n for (let i = 0; i < reviewable.length; i++) {\n const story = reviewable[i];\n const label = `[${i + 1}/${reviewable.length}] ${story.title}`;\n const spinner = ora({ text: `${this.elapsed()} ${label}`, indent: 2 }).start();\n this.activeSpinner = spinner;\n const progress = this.makeProgress(spinner, label);\n\n try {\n const prompt = this.orchestrator.craftWorkerPrompt(story, \"review\", {\n plan,\n designMeta: story.designApproved ? { storyId: story.id } : undefined,\n });\n\n const result = await this.worker.run(\"review\", prompt, {\n onProgress: progress.onProgress,\n });\n\n this.addUsage(result.usage);\n const tokens = chalk.dim(\n `${this.formatTokens(result.usage.inputTokens)} in / ${this.formatTokens(result.usage.outputTokens)} out`\n );\n\n if (result.success) {\n const tagName = `forge/v0.${this.tagCounter++}-${story.id}`;\n await this.git.tag(tagName);\n story.tags.push(tagName);\n story.status = \"done\";\n spinner.succeed(`${this.elapsed()} ${label}` + chalk.dim(` [${tagName}]`) + ` ${tokens}`);\n } else {\n // Auto-fix attempt\n spinner.text = `${this.elapsed()} ${label}` + chalk.dim(\" fixing issues...\");\n const fixed = await this.autoFix(story, plan, result.summary, spinner, label);\n if (fixed) {\n const tagName = `forge/v0.${this.tagCounter++}-${story.id}`;\n await this.git.tag(tagName);\n story.tags.push(tagName);\n story.status = \"done\";\n spinner.succeed(`${this.elapsed()} ${label}` + chalk.dim(` [${tagName}] fixed`));\n } else {\n story.status = \"blocked\";\n spinner.fail(`${this.elapsed()} ${label}` + chalk.dim(\" blocked\"));\n }\n }\n } finally {\n progress.stop();\n this.activeSpinner = null;\n }\n\n await stateManager.savePlan(plan);\n await this.processChatQueue();\n this.showInputHint();\n }\n\n await stateManager.updatePhase(\"review\");\n }\n\n // ── Auto-Fix ──────────────────────────────────────────────\n\n private async autoFix(\n story: Story,\n _plan: Plan,\n reviewSummary: string,\n spinner: Ora,\n label: string\n ): Promise<boolean> {\n const fixPrompt = `\n The review found these issues:\n ${reviewSummary}\n\n Fix them. Make minimal changes. Then re-run build/lint/typecheck to verify.\n `;\n\n const fixProgress = this.makeProgress(spinner, label + chalk.dim(\" fix\"));\n try {\n const result = await this.worker.run(\"fix\", fixPrompt, {\n onProgress: fixProgress.onProgress,\n });\n\n if (result.success) {\n await this.git.commitAll(`fix: review issues in ${story.title}`);\n return true;\n }\n return false;\n } finally {\n fixProgress.stop();\n }\n }\n\n // ── Deploy Phase (optional) ───────────────────────────────\n\n private async runDeployPhase(plan: Plan): Promise<void> {\n console.log(chalk.bold(`\\n Deploy`) + chalk.dim(` · GitHub Pages\\n`));\n\n const label = \"GitHub Pages\";\n const spinner = ora({ text: `${this.elapsed()} Configuring ${label}`, indent: 2 }).start();\n this.activeSpinner = spinner;\n const progress = this.makeProgress(spinner, label);\n\n try {\n const framework = plan.framework || \"Next.js\";\n const prompt = `\n Set up GitHub Pages deployment for this ${framework} project.\n\n 1. Update next.config.js or next.config.ts to add: output: \"export\"\n (merge with existing config, do not overwrite other settings)\n 2. Create .github/workflows/deploy.yml for GitHub Pages deployment\n 3. The workflow should:\n - Trigger on push to main\n - Install dependencies with npm ci\n - Build with npm run build\n - Use actions/configure-pages, actions/upload-pages-artifact, actions/deploy-pages\n\n Do NOT run any git commands. Just create/update the configuration files.\n `;\n\n const result = await this.worker.run(\"build\", prompt, {\n onProgress: progress.onProgress,\n });\n this.addUsage(result.usage);\n\n if (result.success) {\n await this.git.commitAll(\"ci: add GitHub Pages deployment\");\n spinner.succeed(`${this.elapsed()} ${label} configured`);\n } else {\n spinner.warn(`${this.elapsed()} ${label}` + chalk.dim(\" skipped\"));\n }\n } finally {\n progress.stop();\n this.activeSpinner = null;\n }\n }\n\n // ── Chat Queue ────────────────────────────────────────────\n\n private startChatListener(): void {\n if (!process.stdin.isTTY) return;\n if (this.rl) return; // Already listening\n\n this.rl = readline.createInterface({\n input: process.stdin,\n terminal: false,\n });\n\n this.rl.on(\"line\", (line) => {\n const msg = line.trim();\n if (!msg) return;\n\n this.chatQueue.push({\n type: \"content-change\",\n message: msg,\n queuedAt: new Date().toISOString(),\n });\n\n const count = this.chatQueue.length;\n\n // Pause the active spinner so our output doesn't collide\n const wasSpinning = this.activeSpinner?.isSpinning ?? false;\n const spinnerText = this.activeSpinner?.text ?? \"\";\n if (wasSpinning) this.activeSpinner!.stop();\n\n // Clear the current line and show confirmation\n if (process.stdout.isTTY) {\n process.stdout.write(`\\r\\x1b[K`);\n }\n console.log(\n chalk.green(` [queued${count > 1 ? ` #${count}` : \"\"}]`) +\n chalk.dim(` ${msg}`)\n );\n console.log(chalk.dim(\" > \"));\n\n // Resume spinner if it was running\n if (wasSpinning && this.activeSpinner) {\n this.activeSpinner.start(spinnerText);\n }\n });\n }\n\n private stopChatListener(): void {\n if (this.rl) {\n this.rl.close();\n this.rl = null;\n }\n }\n\n private async processChatQueue(): Promise<void> {\n if (this.chatQueue.length === 0) return;\n\n // Stop spinner while processing queue messages\n if (this.activeSpinner?.isSpinning) {\n this.activeSpinner.stop();\n }\n\n console.log(chalk.dim(`\\n Processing ${this.chatQueue.length} queued message${this.chatQueue.length > 1 ? \"s\" : \"\"}...\\n`));\n\n const messages = [...this.chatQueue];\n this.chatQueue = [];\n\n for (const change of messages) {\n try {\n const state = await stateManager.getState();\n const decision = await this.orchestrator.routeUserInput(change.message, state);\n\n if (decision.action === \"answer\" && decision.response) {\n console.log(chalk.white(` > ${change.message}`));\n console.log(chalk.dim(` ${decision.response}\\n`));\n } else if (decision.action === \"route-to-worker\" && decision.prompt) {\n const mode = decision.workerMode || \"fix\";\n const spinner = ora({ text: change.message, indent: 2 }).start();\n const result = await this.worker.run(mode, decision.prompt);\n if (result.success) {\n await this.git.commitAll(`fix: ${change.message}`);\n spinner.succeed(change.message);\n } else {\n spinner.fail(change.message);\n }\n } else if (decision.action === \"add-story\" && this.plan) {\n const newStory: Story = {\n id: `story-${Date.now()}`,\n title: decision.story?.title || change.message,\n description: decision.story?.description || change.message,\n type: (decision.story?.type as any) || \"fullstack\",\n status: \"planned\",\n branch: null,\n designApproved: false,\n tags: [],\n priority: 99,\n dependencies: [],\n };\n // Add to last epic\n if (this.plan.epics.length > 0) {\n this.plan.epics[this.plan.epics.length - 1].stories.push(newStory);\n console.log(chalk.dim(` + Story added: ${newStory.title}`));\n }\n }\n } catch (err) {\n console.log(chalk.dim(` Could not process: ${change.message}`));\n }\n }\n }\n\n // ── Summary ───────────────────────────────────────────────\n\n private printSummary(errors: string[]): void {\n const elapsedSec = (Date.now() - this.startTime) / 1000;\n const elapsed = elapsedSec >= 60\n ? `${Math.floor(elapsedSec / 60)}m ${Math.round(elapsedSec % 60)}s`\n : `${Math.round(elapsedSec)}s`;\n\n const allStories = this.getAllStories(this.plan!);\n const done = allStories.filter((s) => s.status === \"done\").length;\n const blocked = allStories.filter((s) => s.status === \"blocked\").length;\n const total = allStories.length;\n\n if (!this.options.mute) {\n playSound();\n }\n\n console.log(chalk.dim(\"\\n ─────────────────────────────────\"));\n console.log(chalk.bold(\" Done\") + chalk.dim(` in ${elapsed} · ${done}/${total} stories`));\n\n // Token usage\n const u = this.totalUsage;\n if (u.inputTokens > 0 || u.outputTokens > 0) {\n console.log(chalk.dim(\n ` ${this.formatTokens(u.inputTokens)} in / ${this.formatTokens(u.outputTokens)} out` +\n (u.costUsd > 0 ? ` · ${this.formatCost(u.costUsd)}` : \"\")\n ));\n }\n\n if (blocked > 0) {\n console.log(chalk.yellow(` ${blocked} blocked`) + chalk.dim(\" — \" + chalk.white(\"forge status\")));\n }\n\n for (const e of errors) {\n console.log(chalk.dim(` ! ${e}`));\n }\n\n console.log(\"\");\n }\n\n // ── Usage Tracking ────────────────────────────────────────\n\n private addUsage(usage: WorkerUsage): void {\n this.totalUsage.inputTokens += usage.inputTokens;\n this.totalUsage.outputTokens += usage.outputTokens;\n this.totalUsage.costUsd += usage.costUsd;\n this.totalUsage.durationMs += usage.durationMs;\n }\n\n private formatTokens(n: number): string {\n if (n >= 1_000_000) return (n / 1_000_000).toFixed(1) + \"M\";\n if (n >= 1_000) return (n / 1_000).toFixed(1) + \"k\";\n return String(n);\n }\n\n private formatCost(usd: number): string {\n return \"$\" + usd.toFixed(4);\n }\n\n // ── GitHub Sync ────────────────────────────────────────────\n\n private async syncToGitHub(plan: Plan): Promise<void> {\n if (!this.config.githubSync || !this.config.githubRepo) return;\n if (!GitHubSync.isAvailable()) return;\n\n try {\n const gh = new GitHubSync(this.config.githubRepo);\n await gh.ensureLabels();\n const { created, updated } = await gh.syncPlan(plan);\n if (created > 0 || updated > 0) {\n console.log(chalk.dim(` GitHub: ${created} issues created, ${updated} updated`));\n }\n } catch {\n // Silently skip — GitHub sync is best-effort\n }\n }\n\n // ── Auto-Push ───────────────────────────────────────────\n\n private async autoPush(): Promise<void> {\n const hasRemote = await this.git.hasRemote();\n if (!hasRemote) return; // No remote configured — skip silently\n\n const spinner = ora({ text: `${this.elapsed()} Pushing to GitHub...`, indent: 2 }).start();\n this.activeSpinner = spinner;\n\n try {\n await this.git.push();\n await this.git.pushTags();\n spinner.succeed(`${this.elapsed()} Pushed to GitHub`);\n } catch {\n spinner.warn(`${this.elapsed()} Push failed` + chalk.dim(\" — run forge push to retry\"));\n } finally {\n this.activeSpinner = null;\n }\n }\n\n // ── Helpers ───────────────────────────────────────────────\n\n private displayPlan(plan: Plan): void {\n console.log(chalk.bold(`\\n ${plan.project}`) + chalk.dim(` · ${plan.framework}`));\n const total = this.getAllStories(plan).length;\n console.log(chalk.dim(` ${total} stories across ${plan.epics.length} epics\\n`));\n\n for (const epic of plan.epics) {\n console.log(chalk.dim(` ${epic.title}`));\n for (const story of epic.stories) {\n const tag = story.type === \"ui\" ? \"ui\" : story.type === \"backend\" ? \"api\" : \"full\";\n console.log(` ${chalk.dim(`[${tag}]`)} ${story.title}`);\n }\n }\n console.log(\"\");\n }\n\n private getAllStories(plan: Plan): Story[] {\n return plan.epics.flatMap((e) => e.stories);\n }\n\n private getStoriesByType(plan: Plan, types: string[]): Story[] {\n return this.getAllStories(plan).filter((s) => types.includes(s.type));\n }\n}\n","import { spawnSync } from \"child_process\";\nimport type { Plan, Story } from \"../../types/plan.js\";\n\n// ============================================================\n// GitHub Sync\n// Creates and updates GitHub Issues for sprint stories.\n// Uses the `gh` CLI — no extra dependencies.\n// ============================================================\n\nexport class GitHubSync {\n private repo: string;\n\n constructor(repo: string) {\n this.repo = repo;\n }\n\n /** Check if `gh` CLI is installed and authenticated */\n static isAvailable(): boolean {\n const result = spawnSync(\"gh\", [\"auth\", \"status\"], { stdio: \"ignore\" });\n return result.status === 0;\n }\n\n /** Create GitHub labels for forge story tracking */\n async ensureLabels(): Promise<void> {\n const labels = [\n { name: \"forge\", color: \"000000\", description: \"Managed by ForgeAI\" },\n { name: \"type:ui\", color: \"7057ff\", description: \"UI component\" },\n { name: \"type:backend\", color: \"0075ca\", description: \"Backend/API\" },\n { name: \"type:fullstack\", color: \"008672\", description: \"Full stack\" },\n { name: \"status:planned\", color: \"d4c5f9\", description: \"Planned\" },\n { name: \"status:in-progress\", color: \"fbca04\", description: \"Building\" },\n { name: \"status:review\", color: \"f9d0c4\", description: \"In review\" },\n { name: \"status:done\", color: \"0e8a16\", description: \"Complete\" },\n { name: \"status:blocked\", color: \"e11d48\", description: \"Blocked\" },\n ];\n\n for (const label of labels) {\n spawnSync(\"gh\", [\n \"label\", \"create\", label.name,\n \"--repo\", this.repo,\n \"--color\", label.color,\n \"--description\", label.description,\n \"--force\",\n ], { stdio: \"ignore\" });\n }\n }\n\n /** Sync all stories in a plan to GitHub Issues */\n async syncPlan(plan: Plan): Promise<{ created: number; updated: number }> {\n let created = 0;\n let updated = 0;\n\n for (const epic of plan.epics) {\n for (const story of epic.stories) {\n const result = await this.syncStory(story, epic.title);\n if (result === \"created\") created++;\n else if (result === \"updated\") updated++;\n }\n }\n\n return { created, updated };\n }\n\n /** Sync a single story to a GitHub Issue */\n private async syncStory(\n story: Story,\n epicTitle: string\n ): Promise<\"created\" | \"updated\" | \"skipped\"> {\n const title = `[${epicTitle}] ${story.title}`;\n const labels = this.getLabels(story);\n const body = [\n `**Story ID:** \\`${story.id}\\``,\n `**Type:** ${story.type}`,\n `**Priority:** ${story.priority}`,\n `**Status:** ${story.status}`,\n \"\",\n story.description,\n \"\",\n \"---\",\n \"_Managed by [ForgeAI](https://github.com/joeljohn159/forgeai)_\",\n ].join(\"\\n\");\n\n // Search for existing issue by story ID in body\n const searchResult = spawnSync(\"gh\", [\n \"issue\", \"list\",\n \"--repo\", this.repo,\n \"--search\", story.id,\n \"--label\", \"forge\",\n \"--json\", \"number\",\n \"--jq\", \".[0].number\",\n \"--state\", \"all\",\n ], { encoding: \"utf-8\" });\n\n const existingNumber = searchResult.stdout?.trim();\n\n if (existingNumber && /^\\d+$/.test(existingNumber)) {\n // Update existing issue\n const args = [\n \"issue\", \"edit\", existingNumber,\n \"--repo\", this.repo,\n \"--title\", title,\n \"--body\", body,\n ];\n\n // Update labels\n for (const label of labels) {\n args.push(\"--add-label\", label);\n }\n\n spawnSync(\"gh\", args, { stdio: \"ignore\" });\n\n // Close if done\n if (story.status === \"done\") {\n spawnSync(\"gh\", [\n \"issue\", \"close\", existingNumber,\n \"--repo\", this.repo,\n ], { stdio: \"ignore\" });\n }\n\n return \"updated\";\n }\n\n // Create new issue\n const createArgs = [\n \"issue\", \"create\",\n \"--repo\", this.repo,\n \"--title\", title,\n \"--body\", body,\n ];\n\n for (const label of labels) {\n createArgs.push(\"--label\", label);\n }\n\n const createResult = spawnSync(\"gh\", createArgs, { stdio: \"ignore\" });\n\n if (createResult.status === 0) {\n return \"created\";\n }\n\n return \"skipped\";\n }\n\n /** Map story status to GitHub labels */\n private getLabels(story: Story): string[] {\n const labels = [\"forge\", `type:${story.type}`];\n\n switch (story.status) {\n case \"planned\":\n case \"designing\":\n case \"design-approved\":\n labels.push(\"status:planned\");\n break;\n case \"building\":\n labels.push(\"status:in-progress\");\n break;\n case \"reviewing\":\n labels.push(\"status:review\");\n break;\n case \"done\":\n labels.push(\"status:done\");\n break;\n case \"blocked\":\n labels.push(\"status:blocked\");\n break;\n }\n\n return labels;\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\n\n// ============================================================\n// Attachment Parser\n// Detects file paths in user input (drag-and-drop), classifies\n// them as images or documents, and returns clean labels.\n// ============================================================\n\nexport interface Attachment {\n /** Display label: [Image1], [Document1], etc. */\n label: string;\n /** Original absolute path */\n originalPath: string;\n /** Resolved absolute path (quotes/escapes removed) */\n resolvedPath: string;\n /** File type category */\n type: \"image\" | \"document\";\n /** File extension */\n ext: string;\n /** File name */\n fileName: string;\n}\n\nexport interface ParsedInput {\n /** The description text with file paths replaced by labels */\n description: string;\n /** Extracted attachments */\n attachments: Attachment[];\n}\n\nconst IMAGE_EXTS = new Set([\n \".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".svg\", \".bmp\", \".ico\", \".tiff\", \".avif\",\n]);\n\nconst DOCUMENT_EXTS = new Set([\n \".pdf\", \".doc\", \".docx\", \".txt\", \".md\", \".csv\", \".xls\", \".xlsx\",\n \".ppt\", \".pptx\", \".rtf\", \".html\", \".json\", \".yaml\", \".yml\",\n \".xml\", \".figma\", \".sketch\", \".xd\",\n]);\n\n// Matches file paths: absolute paths, quoted paths, or escaped-space paths\n// Examples: /Users/foo/bar.png, \"/Users/foo/bar.png\", /Users/foo/bar\\ baz.png\nconst PATH_PATTERN = /(?:\"([^\"]+\\.[\\w]+)\")|(?:'([^']+\\.[\\w]+)')|(?:((?:\\/|[A-Z]:\\\\)(?:[^\\s,;]|\\\\[ ])+\\.[\\w]+))/g;\n\n/**\n * Parse user input to extract file paths and replace them with clean labels.\n * Handles drag-and-drop paths from terminal (absolute paths, quoted, escaped spaces).\n */\nexport function parseAttachments(input: string): ParsedInput {\n const attachments: Attachment[] = [];\n let imageCount = 0;\n let docCount = 0;\n\n let cleaned = input.replace(PATH_PATTERN, (match, quoted, singleQuoted, raw) => {\n const filePath = (quoted || singleQuoted || raw || \"\").replace(/\\\\ /g, \" \").trim();\n\n if (!filePath) return match;\n\n // Resolve the path\n const resolved = path.resolve(filePath);\n\n // Check if the file actually exists\n if (!fs.existsSync(resolved)) return match;\n\n const ext = path.extname(resolved).toLowerCase();\n const fileName = path.basename(resolved);\n\n let type: \"image\" | \"document\";\n let label: string;\n\n if (IMAGE_EXTS.has(ext)) {\n imageCount++;\n type = \"image\";\n label = `[Image${imageCount}]`;\n } else if (DOCUMENT_EXTS.has(ext)) {\n docCount++;\n type = \"document\";\n label = `[Document${docCount}]`;\n } else {\n // Treat unknown file types as documents\n docCount++;\n type = \"document\";\n label = `[Document${docCount}]`;\n }\n\n attachments.push({\n label,\n originalPath: match,\n resolvedPath: resolved,\n type,\n ext,\n fileName,\n });\n\n return label;\n });\n\n // Clean up extra whitespace from removed paths\n cleaned = cleaned.replace(/\\s{2,}/g, \" \").trim();\n\n return { description: cleaned, attachments };\n}\n\n/**\n * Copy attachments to .forge/attachments/ so workers can access them.\n * Returns the list of copied paths.\n */\nexport function stageAttachments(attachments: Attachment[]): string[] {\n if (attachments.length === 0) return [];\n\n const attachDir = path.join(process.cwd(), \".forge\", \"attachments\");\n fs.mkdirSync(attachDir, { recursive: true });\n\n const stagedPaths: string[] = [];\n\n for (const att of attachments) {\n // Use label-based filename to keep it clean: image1.png, document1.pdf\n const stagedName = att.label.replace(/[\\[\\]]/g, \"\").toLowerCase() + att.ext;\n const dest = path.join(attachDir, stagedName);\n\n try {\n fs.copyFileSync(att.resolvedPath, dest);\n stagedPaths.push(dest);\n } catch {\n // If copy fails (permissions, etc.), skip silently\n }\n }\n\n return stagedPaths;\n}\n\n/**\n * Format attachments for display in the terminal.\n */\nexport function formatAttachmentList(attachments: Attachment[]): string {\n if (attachments.length === 0) return \"\";\n\n return attachments\n .map((a) => ` ${a.label} ${a.fileName}`)\n .join(\"\\n\");\n}\n\n/**\n * Build an attachment context block for the orchestrator/worker prompt.\n */\nexport function buildAttachmentPrompt(attachments: Attachment[]): string {\n if (attachments.length === 0) return \"\";\n\n const lines = attachments.map((a) => {\n const relPath = path.relative(process.cwd(), a.resolvedPath);\n if (a.type === \"image\") {\n return `- ${a.label}: Image file at ${relPath} — read this file to see the visual reference`;\n }\n return `- ${a.label}: Document at ${relPath} — read this file for requirements/specs`;\n });\n\n return `\nATTACHMENTS (provided by the user):\n${lines.join(\"\\n\")}\n\nUse these attachments as reference material. For images, match the visual style/layout.\nFor documents, extract requirements and specifications from them.\n`;\n}\n","// ============================================================\n// Config Validation\n// Validates forge.config.json before running commands.\n// ============================================================\n\nimport chalk from \"chalk\";\nimport type { ForgeConfig } from \"../../types/plan.js\";\nimport { listAdapters } from \"../adapters/index.js\";\n\nexport interface ConfigValidation {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\nexport function validateConfig(config: any): ConfigValidation {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!config || typeof config !== \"object\") {\n return { valid: false, errors: [\"Config is empty or not an object\"], warnings: [] };\n }\n\n // Framework\n const frameworks = listAdapters().map((a) => a.id);\n if (!config.framework) {\n errors.push(\"Missing 'framework' field\");\n } else if (!frameworks.includes(config.framework)) {\n errors.push(\n `Unknown framework \"${config.framework}\". Supported: ${frameworks.join(\", \")}`\n );\n }\n\n // Model\n const validModels = [\"sonnet\", \"opus\", \"haiku\"];\n if (!config.model) {\n errors.push(\"Missing 'model' field\");\n } else if (!validModels.includes(config.model)) {\n warnings.push(\n `Unknown model \"${config.model}\". Expected: ${validModels.join(\", \")}`\n );\n }\n\n // GitHub sync\n if (config.githubSync && !config.githubRepo) {\n warnings.push(\"GitHub sync enabled but no repo configured\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/** Validate config and print errors. Returns config if valid, null if not. */\nexport function loadAndValidateConfig(raw: any): ForgeConfig | null {\n const result = validateConfig(raw);\n\n if (result.warnings.length > 0) {\n for (const w of result.warnings) {\n console.log(chalk.yellow(` warning: ${w}`));\n }\n }\n\n if (!result.valid) {\n for (const e of result.errors) {\n console.log(chalk.red(` error: ${e}`));\n }\n console.log(chalk.dim(\"\\n Fix forge.config.json or run: forge init\\n\"));\n return null;\n }\n\n return raw as ForgeConfig;\n}\n"],"mappings":"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","names":["query","chalk","query","chalk","fs","path","chalk","chalk","chalk","ora","inquirer","fs","path","chalk","ora","inquirer","chalk","chalk"]}