@mir-code/specs-platform 1.0.1
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.
- package/LICENSE +21 -0
- package/README.md +460 -0
- package/assets/specs-usage-statusline.sh +77 -0
- package/assets/template/.agents/README.md +123 -0
- package/assets/template/.agents/RUNTIME.md +64 -0
- package/assets/template/.agents/agents/discovery-agent.md +15 -0
- package/assets/template/.agents/agents/drawing-agent.md +15 -0
- package/assets/template/.agents/agents/feature-runner.md +15 -0
- package/assets/template/.agents/agents/refinement-runner.md +15 -0
- package/assets/template/.agents/agents/refinement.md +15 -0
- package/assets/template/.agents/project.md +158 -0
- package/assets/template/.agents/scripts/check-commit.mjs +70 -0
- package/assets/template/.agents/scripts/validate-spec.mjs +345 -0
- package/assets/template/.agents/skills/discovery-agent/SKILL.md +80 -0
- package/assets/template/.agents/skills/discovery-writing/SKILL.md +76 -0
- package/assets/template/.agents/skills/drawing-agent/SKILL.md +85 -0
- package/assets/template/.agents/skills/drawing-writing/SKILL.md +100 -0
- package/assets/template/.agents/skills/execution-protocol/SKILL.md +110 -0
- package/assets/template/.agents/skills/execution-protocol/references/git.md +104 -0
- package/assets/template/.agents/skills/execution-protocol/references/relatorio-halt.md +103 -0
- package/assets/template/.agents/skills/feature-runner/SKILL.md +81 -0
- package/assets/template/.agents/skills/feature-runner/references/divergencias.md +38 -0
- package/assets/template/.agents/skills/feature-runner/references/implementar.md +80 -0
- package/assets/template/.agents/skills/feature-runner/references/localizar.md +46 -0
- package/assets/template/.agents/skills/mermaid-diagramming/SKILL.md +198 -0
- package/assets/template/.agents/skills/prototype-check/SKILL.md +90 -0
- package/assets/template/.agents/skills/refinement/SKILL.md +136 -0
- package/assets/template/.agents/skills/refinement/references/estrutura.md +27 -0
- package/assets/template/.agents/skills/refinement/references/mapear-terreno.md +46 -0
- package/assets/template/.agents/skills/refinement/references/validar-renderizacao.md +29 -0
- package/assets/template/.agents/skills/refinement-runner/SKILL.md +145 -0
- package/assets/template/.agents/skills/requirements-closure/SKILL.md +236 -0
- package/assets/template/.agents/skills/spec-writing/SKILL.md +258 -0
- package/assets/template/.agents/skills/test-strategy/SKILL.md +176 -0
- package/assets/template/.agents/skills/verification/SKILL.md +143 -0
- package/assets/template/.specs/config.json +39 -0
- package/assets/template/.specs/discoveries/meta.json +4 -0
- package/assets/template/.specs/drawings/meta.json +4 -0
- package/assets/template/.specs/specs/_templates/task-backend.md +75 -0
- package/assets/template/.specs/specs/_templates/task-frontend.md +89 -0
- package/assets/template/.specs/specs/_templates/task-integracao.md +72 -0
- package/assets/template/.specs/specs/exemplo/feat-exemplo-primeira-task.md +82 -0
- package/assets/template/.specs/specs/exemplo/meta.json +8 -0
- package/assets/template/.specs/specs/exemplo/overview.md +45 -0
- package/assets/template/.specs/specs/meta.json +4 -0
- package/assets/template/SPECS.md +213 -0
- package/dist/chunk-SOOETS3N.js +3490 -0
- package/dist/chunk-SOOETS3N.js.map +1 -0
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/assets/abnfDiagram-VCTEODGH-DYXtkHNq.js +2 -0
- package/dist/ui/assets/abnfDiagram-VCTEODGH-DYXtkHNq.js.map +1 -0
- package/dist/ui/assets/arc-CJs0gz4E.js +2 -0
- package/dist/ui/assets/arc-CJs0gz4E.js.map +1 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-Br7ZNRfe.js +37 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-Br7ZNRfe.js.map +1 -0
- package/dist/ui/assets/blockDiagram-I7D4REHJ-172V7R5o.js +130 -0
- package/dist/ui/assets/blockDiagram-I7D4REHJ-172V7R5o.js.map +1 -0
- package/dist/ui/assets/c4Diagram-7LVT6UL2-B4AYFhRs.js +39 -0
- package/dist/ui/assets/c4Diagram-7LVT6UL2-B4AYFhRs.js.map +1 -0
- package/dist/ui/assets/channel-BfWO3B41.js +2 -0
- package/dist/ui/assets/channel-BfWO3B41.js.map +1 -0
- package/dist/ui/assets/chunk-2Q5K7J3B-B-u7gtZN.js +2 -0
- package/dist/ui/assets/chunk-2Q5K7J3B-B-u7gtZN.js.map +1 -0
- package/dist/ui/assets/chunk-5VM5RSS4-CjFDq_cq.js +16 -0
- package/dist/ui/assets/chunk-5VM5RSS4-CjFDq_cq.js.map +1 -0
- package/dist/ui/assets/chunk-F27PBJKO-BDYeB7B8.js +2 -0
- package/dist/ui/assets/chunk-F27PBJKO-BDYeB7B8.js.map +1 -0
- package/dist/ui/assets/chunk-IMKFNOWR-y2kXPnac.js +232 -0
- package/dist/ui/assets/chunk-IMKFNOWR-y2kXPnac.js.map +1 -0
- package/dist/ui/assets/chunk-JWPE2WC7-DyCryvDN.js +2 -0
- package/dist/ui/assets/chunk-JWPE2WC7-DyCryvDN.js.map +1 -0
- package/dist/ui/assets/chunk-POPQ4Y6H-DeaxKHvR.js +2 -0
- package/dist/ui/assets/chunk-POPQ4Y6H-DeaxKHvR.js.map +1 -0
- package/dist/ui/assets/chunk-SVP7TREG-CmcZEncL.js +89 -0
- package/dist/ui/assets/chunk-SVP7TREG-CmcZEncL.js.map +1 -0
- package/dist/ui/assets/chunk-TICWLB2K-Df1RRXWR.js +207 -0
- package/dist/ui/assets/chunk-TICWLB2K-Df1RRXWR.js.map +1 -0
- package/dist/ui/assets/chunk-XXDRQBXY-ClTat8Q0.js +2 -0
- package/dist/ui/assets/chunk-XXDRQBXY-ClTat8Q0.js.map +1 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-YTUiu8rF.js +2 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-YTUiu8rF.js.map +1 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-YTUiu8rF.js +2 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-YTUiu8rF.js.map +1 -0
- package/dist/ui/assets/cose-bilkent-JH36ORCC-QvqQLoy5.js +2 -0
- package/dist/ui/assets/cose-bilkent-JH36ORCC-QvqQLoy5.js.map +1 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-BY6w3pAQ.js +179 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-BY6w3pAQ.js.map +1 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-luPP4ha1.js +63 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-luPP4ha1.js.map +1 -0
- package/dist/ui/assets/cytoscape.esm-Ix0LnXOy.js +332 -0
- package/dist/ui/assets/cytoscape.esm-Ix0LnXOy.js.map +1 -0
- package/dist/ui/assets/dagre-GXQ25YYZ-DhpPwKqq.js +5 -0
- package/dist/ui/assets/dagre-GXQ25YYZ-DhpPwKqq.js.map +1 -0
- package/dist/ui/assets/defaultLocale-DX6XiGOO.js +2 -0
- package/dist/ui/assets/defaultLocale-DX6XiGOO.js.map +1 -0
- package/dist/ui/assets/diagram-S7CK7UJ4-B9wvQM0w.js +31 -0
- package/dist/ui/assets/diagram-S7CK7UJ4-B9wvQM0w.js.map +1 -0
- package/dist/ui/assets/diagram-UQ7AKVKN-gm1M_iZS.js +42 -0
- package/dist/ui/assets/diagram-UQ7AKVKN-gm1M_iZS.js.map +1 -0
- package/dist/ui/assets/diagram-VSXAHHWV-DkEB6nEx.js +4 -0
- package/dist/ui/assets/diagram-VSXAHHWV-DkEB6nEx.js.map +1 -0
- package/dist/ui/assets/diagram-VX7I27RA-Ce2F1bHi.js +25 -0
- package/dist/ui/assets/diagram-VX7I27RA-Ce2F1bHi.js.map +1 -0
- package/dist/ui/assets/diagram-Z3DM3KII-B5ArCh-E.js +25 -0
- package/dist/ui/assets/diagram-Z3DM3KII-B5ArCh-E.js.map +1 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-DgBM80MD.js +2 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-DgBM80MD.js.map +1 -0
- package/dist/ui/assets/erDiagram-RLTQ6QDP-C161af8G.js +100 -0
- package/dist/ui/assets/erDiagram-RLTQ6QDP-C161af8G.js.map +1 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-B8N_WyW5.js +169 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-B8N_WyW5.js.map +1 -0
- package/dist/ui/assets/ganttDiagram-EL5Y4UJY-CD2RJpTb.js +293 -0
- package/dist/ui/assets/ganttDiagram-EL5Y4UJY-CD2RJpTb.js.map +1 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BrDAzeFT.js +107 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BrDAzeFT.js.map +1 -0
- package/dist/ui/assets/index-CVWRdirI.css +32 -0
- package/dist/ui/assets/index-DoR97Zqf.js +408 -0
- package/dist/ui/assets/index-DoR97Zqf.js.map +1 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-HYGaMzrA.js +3 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-HYGaMzrA.js.map +1 -0
- package/dist/ui/assets/init-Gi6I4Gst.js +2 -0
- package/dist/ui/assets/init-Gi6I4Gst.js.map +1 -0
- package/dist/ui/assets/ishikawaDiagram-5VMMS53U-DXTLlBiw.js +71 -0
- package/dist/ui/assets/ishikawaDiagram-5VMMS53U-DXTLlBiw.js.map +1 -0
- package/dist/ui/assets/journeyDiagram-3NMN7TZE-DSJ8QN1S.js +140 -0
- package/dist/ui/assets/journeyDiagram-3NMN7TZE-DSJ8QN1S.js.map +1 -0
- package/dist/ui/assets/kanban-definition-UXKFOSKX-Bm5iz0k3.js +90 -0
- package/dist/ui/assets/kanban-definition-UXKFOSKX-Bm5iz0k3.js.map +1 -0
- package/dist/ui/assets/katex-C5jXJg4s.js +258 -0
- package/dist/ui/assets/katex-C5jXJg4s.js.map +1 -0
- package/dist/ui/assets/layout-DfJgW6eG.js +2 -0
- package/dist/ui/assets/layout-DfJgW6eG.js.map +1 -0
- package/dist/ui/assets/linear-B_kyVotV.js +2 -0
- package/dist/ui/assets/linear-B_kyVotV.js.map +1 -0
- package/dist/ui/assets/mermaid-block-CUJSBQFx.js +2 -0
- package/dist/ui/assets/mermaid-block-CUJSBQFx.js.map +1 -0
- package/dist/ui/assets/mermaid.core-ExHG1WnM.js +313 -0
- package/dist/ui/assets/mermaid.core-ExHG1WnM.js.map +1 -0
- package/dist/ui/assets/mindmap-definition-YA3MSWOX-B1Hh9dQz.js +97 -0
- package/dist/ui/assets/mindmap-definition-YA3MSWOX-B1Hh9dQz.js.map +1 -0
- package/dist/ui/assets/ordinal-Cboi1Yqb.js +2 -0
- package/dist/ui/assets/ordinal-Cboi1Yqb.js.map +1 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-x242yOd7.js +2 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-x242yOd7.js.map +1 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-Dl-YP7Xs.js +40 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-Dl-YP7Xs.js.map +1 -0
- package/dist/ui/assets/quadrantDiagram-AXDQQJYC-CMJ920V9.js +8 -0
- package/dist/ui/assets/quadrantDiagram-AXDQQJYC-CMJ920V9.js.map +1 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-1kV83y5t.js +2 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-1kV83y5t.js.map +1 -0
- package/dist/ui/assets/requirementDiagram-BXWQKSXE-BFd8ZZD3.js +85 -0
- package/dist/ui/assets/requirementDiagram-BXWQKSXE-BFd8ZZD3.js.map +1 -0
- package/dist/ui/assets/sankeyDiagram-P5KCCOFB-C0LZevnf.js +41 -0
- package/dist/ui/assets/sankeyDiagram-P5KCCOFB-C0LZevnf.js.map +1 -0
- package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-BasIXLJ0.js +163 -0
- package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-BasIXLJ0.js.map +1 -0
- package/dist/ui/assets/sizeCapture-INFHLROL-qAtnqB7N.js +2 -0
- package/dist/ui/assets/sizeCapture-INFHLROL-qAtnqB7N.js.map +1 -0
- package/dist/ui/assets/stateDiagram-D77RDMKH-CllWDWZP.js +2 -0
- package/dist/ui/assets/stateDiagram-D77RDMKH-CllWDWZP.js.map +1 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-Dwntf8Tk.js +2 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-Dwntf8Tk.js.map +1 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-Bgt0KslH.js +2 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-Bgt0KslH.js.map +1 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-C9abicdw.js +9 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-C9abicdw.js.map +1 -0
- package/dist/ui/assets/timeline-definition-24CTP7MA-BYO2h9Qr.js +121 -0
- package/dist/ui/assets/timeline-definition-24CTP7MA-BYO2h9Qr.js.map +1 -0
- package/dist/ui/assets/vennDiagram-4TSXK5OY-ZzyiwIUi.js +35 -0
- package/dist/ui/assets/vennDiagram-4TSXK5OY-ZzyiwIUi.js.map +1 -0
- package/dist/ui/assets/wardleyDiagram-VM6X3IG4-DfjKCK0N.js +79 -0
- package/dist/ui/assets/wardleyDiagram-VM6X3IG4-DfjKCK0N.js.map +1 -0
- package/dist/ui/assets/xychartDiagram-S5SC5T6Z-Z7daOfmM.js +8 -0
- package/dist/ui/assets/xychartDiagram-S5SC5T6Z-Z7daOfmM.js.map +1 -0
- package/dist/ui/favicon.svg +6 -0
- package/dist/ui/index.html +21 -0
- package/package.json +70 -0
- package/scripts/copy-ui.mjs +21 -0
- package/scripts/fix-node-pty-perms.cjs +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../internal/toolkit-core/src/log.ts","../../../internal/toolkit-core/src/tool.ts","../../../internal/toolkit-core/src/fs.ts","../../../internal/toolkit-core/src/package-root.ts","../src/commands/install.ts","../src/paths.ts","../src/commands/start.ts","../../../internal/specs-server/src/start-server.ts","../../../internal/specs-server/src/config-defaults.ts","../../../internal/specs-server/src/claude-usage.ts","../../../internal/specs-server/src/specs-watcher.ts","../../../internal/specs-server/src/fs-utils.ts","../../../internal/specs-server/src/tree-builder.ts","../../../internal/specs-server/src/frontmatter.ts","../../../internal/specs-server/src/headings.ts","../../../internal/specs-server/src/run-agent.ts","../../../internal/specs-server/src/review.ts","../../../internal/specs-server/src/prototype.ts","../../../internal/specs-server/src/job-manager.ts","../../../internal/specs-server/src/job-store.ts","../../../internal/specs-server/src/job-routes.ts","../../../internal/specs-server/src/types.ts","../src/tool.ts"],"sourcesContent":["import pc from 'picocolors'\n\nexport const log = {\n title: (msg: string) => console.log(pc.bold(pc.cyan(msg))),\n step: (msg: string) => console.log(`${pc.cyan('→')} ${msg}`),\n added: (msg: string) => console.log(pc.green(` + ${msg}`)),\n kept: (msg: string) => console.log(pc.dim(` · ${msg}`)),\n removed: (msg: string) => console.log(pc.yellow(` - ${msg}`)),\n warn: (msg: string) => console.log(pc.yellow(` ! ${msg}`)),\n success: (msg: string) => console.log(pc.bold(pc.green(`✓ ${msg}`))),\n error: (msg: string) => console.error(pc.red(`✗ ${msg}`)),\n blank: () => console.log(''),\n}\n","import type { Command } from 'commander'\n\n/** Uma entrada do menu interativo do `mircode-ai` para uma tool. */\nexport type ToolAction = {\n id: string\n label: string\n hint?: string\n run: (ctx: ToolActionContext) => Promise<void>\n}\n\nexport type ToolActionContext = {\n /** Diretório onde o usuário rodou o CLI. */\n cwd: string\n}\n\n/**\n * Contrato que todo pacote instalável (@mir-code/*) exporta. O `mircode-ai`\n * monta o menu interativo com `actions` e os subcomandos com `register`;\n * o bin próprio do pacote (ex.: `specs`) usa o mesmo `register`.\n */\nexport type ToolDefinition = {\n /** Slug usado na linha de comando: `mircode-ai <id> ...`. */\n id: string\n packageName: string\n title: string\n description: string\n version: string\n /** Registra os subcomandos da tool no `Command` recebido. */\n register: (cmd: Command) => void\n actions: ToolAction[]\n}\n\nexport function defineTool(tool: ToolDefinition): ToolDefinition {\n return tool\n}\n","import { constants } from 'node:fs'\nimport {\n access,\n cp,\n lstat,\n mkdir,\n readFile,\n readlink,\n rm,\n symlink,\n writeFile,\n} from 'node:fs/promises'\nimport path from 'node:path'\n\nexport async function exists(p: string): Promise<boolean> {\n try {\n await access(p, constants.F_OK)\n return true\n } catch {\n return false\n }\n}\n\n/** Copia arquivo ou diretório, substituindo o destino por inteiro. */\nexport async function copyReplacing(src: string, dest: string): Promise<void> {\n await mkdir(path.dirname(dest), { recursive: true })\n await rm(dest, { recursive: true, force: true })\n await cp(src, dest, { recursive: true })\n}\n\n/**\n * Copia só se o destino não existir (ou com `force`). Retorna `true` quando escreveu.\n * Usado para arquivos que o projeto consumidor customiza.\n */\nexport async function copyIfAbsent(src: string, dest: string, force = false): Promise<boolean> {\n if (!force && (await exists(dest))) return false\n await copyReplacing(src, dest)\n return true\n}\n\nexport type SymlinkResult = 'created' | 'unchanged' | 'backed-up'\n\n/**\n * Garante `linkPath → target` (target relativo). Se já houver um diretório/arquivo\n * real no lugar, move para `<linkPath>.bak-<timestamp>` antes de criar o link.\n */\nexport async function ensureSymlink(target: string, linkPath: string): Promise<SymlinkResult> {\n await mkdir(path.dirname(linkPath), { recursive: true })\n let result: SymlinkResult = 'created'\n try {\n const stat = await lstat(linkPath)\n if (stat.isSymbolicLink()) {\n if ((await readlink(linkPath)) === target) return 'unchanged'\n await rm(linkPath)\n } else {\n const stamp = new Date().toISOString().replace(/\\D/g, '').slice(0, 14)\n await cp(linkPath, `${linkPath}.bak-${stamp}`, { recursive: true })\n await rm(linkPath, { recursive: true, force: true })\n result = 'backed-up'\n }\n } catch {\n // não existe — cria\n }\n await symlink(target, linkPath)\n return result\n}\n\n/**\n * Garante que cada entrada esteja no `.gitignore` do projeto. Entradas ausentes\n * são adicionadas num bloco com `header`. Retorna as entradas adicionadas.\n */\nexport async function ensureGitignore(\n projectRoot: string,\n header: string,\n entries: string[],\n): Promise<string[]> {\n const file = path.join(projectRoot, '.gitignore')\n const current = (await exists(file)) ? await readFile(file, 'utf8') : ''\n const lines = new Set(current.split(/\\r?\\n/).map((l) => l.trim().replace(/\\/$/, '')))\n const missing = entries.filter((e) => !lines.has(e.replace(/\\/$/, '')))\n if (missing.length === 0) return []\n const prefix =\n current === '' || current.endsWith('\\n\\n') ? '' : current.endsWith('\\n') ? '\\n' : '\\n\\n'\n await writeFile(file, `${current}${prefix}# ${header}\\n${missing.join('\\n')}\\n`, 'utf8')\n return missing\n}\n","import { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Sobe a partir do arquivo que chamou até achar o `package.json` do pacote.\n * Funciona tanto no bundle (`dist/cli.js`) quanto rodando o source.\n */\nexport function findPackageRoot(importMetaUrl: string): string {\n let dir = path.dirname(fileURLToPath(importMetaUrl))\n for (;;) {\n if (existsSync(path.join(dir, 'package.json'))) return dir\n const parent = path.dirname(dir)\n if (parent === dir) throw new Error(`package.json não encontrado a partir de ${importMetaUrl}`)\n dir = parent\n }\n}\n","import { spawn } from 'node:child_process'\nimport { readFile, readdir, rm, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport {\n copyIfAbsent,\n copyReplacing,\n ensureGitignore,\n ensureSymlink,\n exists,\n log,\n} from '@mir-code/toolkit-core'\nimport { templateDir } from '../paths.js'\n\nexport type InstallOptions = {\n /** Raiz do projeto consumidor. */\n projectRoot: string\n /** Sobrescreve também os arquivos customizáveis (config, project.md, SPECS.md, scaffolds). */\n force?: boolean\n /** Remove o `.specs/app/` de instalações antigas (runtime copiado pelo install-here.sh). */\n cleanLegacy?: boolean\n}\n\nexport type InstallResult = {\n fresh: boolean\n legacyAppDir: boolean\n}\n\ntype TerminalKind = 'osascript' | 'gnome-terminal' | 'kitty' | 'wezterm' | 'none'\n\n/**\n * Instala ou atualiza a Specs Platform num projeto. Idempotente:\n *\n * - `.agents/{agents,skills,scripts}`, `.agents/README.md` e `.agents/RUNTIME.md` são\n * gerenciados pelo pacote e SEMPRE regravados (item a item — skills que o projeto\n * adicionou por conta própria sobrevivem).\n * - `.agents/project.md`, `.specs/config.json`, os `meta.json`, `_templates/` e `SPECS.md`\n * são do projeto: só criados se ausentes (ou com `force`).\n * - `.claude/` e `.cursor/` recebem symlinks para `.agents/`.\n */\nexport async function runInstall(opts: InstallOptions): Promise<InstallResult> {\n const { projectRoot, force = false } = opts\n const src = (...p: string[]) => path.join(templateDir, ...p)\n const dest = (...p: string[]) => path.join(projectRoot, ...p)\n const fresh = !(await exists(dest('.specs', 'specs', 'meta.json')))\n\n log.title(`specs install — ${projectRoot}`)\n log.kept(\n fresh\n ? 'modo: instalação'\n : force\n ? 'modo: força (sobrescreve customizações)'\n : 'modo: atualização',\n )\n log.blank()\n\n // --- 1) .agents/ gerenciado pelo pacote ---\n log.step('Agentes e skills (.agents/)')\n for (const kind of ['agents', 'skills', 'scripts']) {\n for (const entry of await readdir(src('.agents', kind))) {\n await copyReplacing(src('.agents', kind, entry), dest('.agents', kind, entry))\n log.added(`.agents/${kind}/${entry}`)\n }\n }\n for (const file of ['README.md', 'RUNTIME.md']) {\n await copyReplacing(src('.agents', file), dest('.agents', file))\n log.added(`.agents/${file}`)\n }\n await installCustomizable(\n src('.agents', 'project.md'),\n dest('.agents', 'project.md'),\n '.agents/project.md',\n force,\n )\n\n for (const legacy of [\n dest('.agents', 'agents', 'specs-runner.md'),\n dest('.claude', 'agents', 'specs-runner.md'),\n ]) {\n if (await exists(legacy)) {\n await rm(legacy)\n log.removed(`${path.relative(projectRoot, legacy)} (descontinuado)`)\n }\n }\n\n // --- 2) Symlinks para Claude Code e Cursor ---\n for (const consumer of ['.claude', '.cursor']) {\n for (const kind of ['agents', 'skills']) {\n const result = await ensureSymlink(`../.agents/${kind}`, dest(consumer, kind))\n const label = `${consumer}/${kind} → .agents/${kind}`\n if (result === 'backed-up') log.warn(`${label} (diretório real movido para ${kind}.bak-*)`)\n else if (result === 'created') log.added(label)\n else log.kept(label)\n }\n }\n\n // --- 3) Scaffold .specs/ (do projeto) ---\n log.blank()\n log.step('Scaffold (.specs/)')\n const configPath = dest('.specs', 'config.json')\n if (await copyIfAbsent(src('.specs', 'config.json'), configPath, force)) {\n const terminal = await detectDefaultTerminal()\n await setOpenTerminal(configPath, terminal)\n log.added(`.specs/config.json (openTerminal: ${terminal})`)\n } else {\n log.kept('.specs/config.json (preservado)')\n }\n\n for (const dir of ['specs', 'discoveries', 'drawings']) {\n await installCustomizable(\n src('.specs', dir, 'meta.json'),\n dest('.specs', dir, 'meta.json'),\n `.specs/${dir}/meta.json`,\n force,\n )\n }\n for (const tpl of await readdir(src('.specs', 'specs', '_templates'))) {\n await installCustomizable(\n src('.specs', 'specs', '_templates', tpl),\n dest('.specs', 'specs', '_templates', tpl),\n `.specs/specs/_templates/${tpl}`,\n force,\n )\n }\n // A feature exemplo só entra junto com o meta.json que a referencia.\n if (fresh || force) {\n await copyReplacing(src('.specs', 'specs', 'exemplo'), dest('.specs', 'specs', 'exemplo'))\n log.added('.specs/specs/exemplo/ (feature exemplo)')\n }\n\n await installCustomizable(src('SPECS.md'), dest('SPECS.md'), 'SPECS.md', force)\n if (!force && (await readFile(dest('SPECS.md'), 'utf8')).includes('install-here.sh')) {\n log.warn(\n 'SPECS.md é da versão antiga (fala de .specs/app/ e specs:run). Apague-o e rode de novo para regenerar.',\n )\n }\n\n // --- 4) .gitignore ---\n log.blank()\n log.step('.gitignore')\n const added = await ensureGitignore(\n projectRoot,\n 'Specs Platform — estado local da máquina, não do projeto',\n ['.specs/.jobs.json', '.specs/.run/'],\n )\n if (added.length > 0) log.added(`.gitignore (${added.join(', ')})`)\n else log.kept('.gitignore já cobre o estado local')\n\n // --- 5) Legado: .specs/app/ ---\n const legacyAppDir = await exists(dest('.specs', 'app'))\n if (legacyAppDir) {\n log.blank()\n if (opts.cleanLegacy) {\n await rm(dest('.specs', 'app'), { recursive: true, force: true })\n log.removed('.specs/app/ (runtime antigo — agora a plataforma roda do pacote npm)')\n } else {\n log.warn(\n '.specs/app/ é de uma instalação antiga e não é mais usado. Remova com `specs install --clean-legacy`.',\n )\n }\n }\n\n log.blank()\n log.success(`Specs Platform ${fresh ? 'instalada' : 'atualizada'} em ${projectRoot}`)\n console.log(' Próximo passo: preencha .agents/project.md e rode `specs start`.')\n return { fresh, legacyAppDir }\n}\n\nasync function installCustomizable(src: string, dest: string, label: string, force: boolean) {\n if (await copyIfAbsent(src, dest, force)) log.added(label)\n else log.kept(`${label} (preservado)`)\n}\n\nasync function setOpenTerminal(configPath: string, terminal: TerminalKind) {\n const config = JSON.parse(await readFile(configPath, 'utf8')) as {\n agent?: Record<string, unknown>\n }\n if (config.agent && typeof config.agent === 'object') config.agent.openTerminal = terminal\n await writeFile(configPath, `${JSON.stringify(config, null, 2)}\\n`, 'utf8')\n}\n\nasync function detectDefaultTerminal(): Promise<TerminalKind> {\n if (process.platform === 'darwin') return 'osascript'\n if (process.platform !== 'linux') return 'none'\n const which = (bin: string) =>\n new Promise<boolean>((resolve) => {\n const child = spawn('which', [bin], { stdio: 'ignore' })\n child.on('exit', (code) => resolve(code === 0))\n child.on('error', () => resolve(false))\n })\n if (process.env.KITTY_WINDOW_ID || (await which('kitty'))) return 'kitty'\n if (process.env.WEZTERM_PANE || (await which('wezterm'))) return 'wezterm'\n if (await which('gnome-terminal')) return 'gnome-terminal'\n return 'none'\n}\n","import path from 'node:path'\nimport { findPackageRoot } from '@mir-code/toolkit-core'\n\nexport const packageRoot = findPackageRoot(import.meta.url)\n\n/** Arquivos copiados para o projeto consumidor por `specs install`. */\nexport const templateDir = path.join(packageRoot, 'assets', 'template')\n\n/** Build estático da UI, servido pelo Fastify. */\nexport const uiDir = path.join(packageRoot, 'dist', 'ui')\n\nexport const cliEntry = path.join(packageRoot, 'dist', 'cli.js')\n\nexport const statuslineScript = path.join(packageRoot, 'assets', 'specs-usage-statusline.sh')\n\n/** Estado de runtime local (pid/log do `specs start` em background). */\nexport function runDir(projectRoot: string): string {\n return path.join(projectRoot, '.specs', '.run')\n}\n","import { spawn } from 'node:child_process'\nimport { openSync } from 'node:fs'\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport net from 'node:net'\nimport path from 'node:path'\nimport { type SpecsConfig, startServer } from '@mir-code/specs-server'\nimport { exists, log } from '@mir-code/toolkit-core'\nimport open from 'open'\nimport pc from 'picocolors'\nimport { cliEntry, runDir, uiDir } from '../paths.js'\n\nexport type StartOptions = {\n projectRoot: string\n port?: number\n openBrowser: boolean\n foreground: boolean\n /** Só a API — para desenvolver a UI com o Vite (`pnpm --filter @mir-code/specs-ui dev`). */\n apiOnly?: boolean\n}\n\ntype RunState = { pid: number; url: string; startedAt: string }\n\nconst stateFile = (projectRoot: string) => path.join(runDir(projectRoot), 'specs.json')\nexport const logFile = (projectRoot: string) => path.join(runDir(projectRoot), 'specs.log')\n\nexport async function runStart(opts: StartOptions): Promise<void> {\n const config = await readConfig(opts.projectRoot)\n const port = opts.port ?? config.port ?? 4321\n const url = `http://localhost:${port}`\n\n if (opts.foreground) {\n await startForeground(opts, { ...config, port }, url)\n return\n }\n\n const running = await readRunningState(opts.projectRoot)\n if (running) {\n log.success(`specs já está rodando (pid ${running.pid})`)\n printUrls(running.url, opts.projectRoot)\n return\n }\n\n // Sem esta checagem, o waitForPort abaixo \"acharia\" o servidor de outro processo.\n if (await isPortInUse(port)) {\n throw new Error(\n `a porta ${port} já está em uso (outra instância? veja \\`lsof -i :${port}\\`). Use \\`specs start -p <porta>\\`.`,\n )\n }\n\n await mkdir(runDir(opts.projectRoot), { recursive: true })\n const out = openSync(logFile(opts.projectRoot), 'w')\n const args = [cliEntry, 'start', '--foreground', '--no-open', '--port', String(port)]\n if (opts.apiOnly) args.push('--api-only')\n const child = spawn(process.execPath, args, {\n cwd: opts.projectRoot,\n detached: true,\n stdio: ['ignore', out, out],\n })\n child.unref()\n if (!child.pid) throw new Error('não foi possível iniciar o processo em background.')\n\n const state: RunState = { pid: child.pid, url, startedAt: new Date().toISOString() }\n await writeFile(stateFile(opts.projectRoot), `${JSON.stringify(state, null, 2)}\\n`, 'utf8')\n\n const ready = await waitForPort(port, 15_000, () => isAlive(state.pid))\n if (!ready) {\n await rm(stateFile(opts.projectRoot), { force: true })\n const tail = (await readFile(logFile(opts.projectRoot), 'utf8'))\n .split('\\n')\n .slice(-30)\n .join('\\n')\n throw new Error(`o servidor não subiu. Últimas linhas do log:\\n${tail}`)\n }\n\n log.success(`specs iniciado em background (pid ${state.pid})`)\n printUrls(url, opts.projectRoot)\n if (opts.openBrowser && !opts.apiOnly) await open(url).catch(() => {})\n}\n\nexport async function runStop(projectRoot: string): Promise<void> {\n const state = await readState(projectRoot)\n if (!state) {\n log.kept('specs não está rodando em background neste projeto.')\n return\n }\n if (isAlive(state.pid)) {\n process.kill(state.pid, 'SIGTERM')\n for (let i = 0; i < 50 && isAlive(state.pid); i++) await sleep(100)\n if (isAlive(state.pid)) process.kill(state.pid, 'SIGKILL')\n }\n await rm(stateFile(projectRoot), { force: true })\n log.success(`specs parado (pid ${state.pid})`)\n}\n\nexport async function runStatus(projectRoot: string): Promise<void> {\n const running = await readRunningState(projectRoot)\n if (!running) {\n log.kept('specs não está rodando em background neste projeto.')\n return\n }\n log.success(`specs rodando (pid ${running.pid}, desde ${running.startedAt})`)\n printUrls(running.url, projectRoot)\n}\n\nasync function startForeground(opts: StartOptions, config: SpecsConfig, url: string) {\n const server = await startServer(config, {\n projectRoot: opts.projectRoot,\n uiDir: opts.apiOnly ? undefined : uiDir,\n })\n log.title(`specs — ${opts.projectRoot}`)\n console.log(\n `${pc.green('✓')} ${opts.apiOnly ? 'API' : 'UI + API'}: ${pc.bold(pc.cyan(server.url))}`,\n )\n console.log(pc.dim('Pressione Ctrl+C para encerrar.'))\n if (opts.openBrowser && !opts.apiOnly) await open(url).catch(() => {})\n\n let closing = false\n const shutdown = async () => {\n if (closing) return\n closing = true\n await server.close().catch(() => {})\n process.exit(0)\n }\n for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as const) {\n process.on(signal, () => void shutdown())\n }\n}\n\nasync function readConfig(projectRoot: string): Promise<SpecsConfig> {\n const configPath = path.join(projectRoot, '.specs', 'config.json')\n if (!(await exists(configPath))) {\n throw new Error(\n '.specs/config.json não encontrado. Rode `specs install` na raiz do projeto antes.',\n )\n }\n return JSON.parse(await readFile(configPath, 'utf8')) as SpecsConfig\n}\n\nasync function readState(projectRoot: string): Promise<RunState | null> {\n try {\n return JSON.parse(await readFile(stateFile(projectRoot), 'utf8')) as RunState\n } catch {\n return null\n }\n}\n\n/** Estado do background só se o processo ainda existe; limpa o arquivo órfão. */\nasync function readRunningState(projectRoot: string): Promise<RunState | null> {\n const state = await readState(projectRoot)\n if (!state) return null\n if (isAlive(state.pid)) return state\n await rm(stateFile(projectRoot), { force: true })\n return null\n}\n\nfunction printUrls(url: string, projectRoot: string) {\n console.log(` UI: ${pc.cyan(url)}`)\n console.log(\n ` logs: ${path.relative(process.cwd(), logFile(projectRoot)) || logFile(projectRoot)}`,\n )\n console.log(' stop: specs stop')\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nfunction tryConnect(host: string, port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = net.createConnection({ host, port })\n const finish = (ok: boolean) => {\n socket.destroy()\n resolve(ok)\n }\n socket.once('connect', () => finish(true))\n socket.once('error', () => finish(false))\n socket.setTimeout(1_000, () => finish(false))\n })\n}\n\n/** Espera a porta aceitar conexão (IPv4 ou IPv6); desiste cedo se o processo morrer. */\nasync function waitForPort(\n port: number,\n timeoutMs: number,\n alive: () => boolean,\n): Promise<boolean> {\n const start = Date.now()\n while (Date.now() - start < timeoutMs && alive()) {\n if (await isPortInUse(port)) return true\n await sleep(250)\n }\n return false\n}\n\nasync function isPortInUse(port: number): Promise<boolean> {\n const [v4, v6] = await Promise.all([tryConnect('127.0.0.1', port), tryConnect('::1', port)])\n return v4 || v6\n}\n","import path from 'node:path'\nimport { readFile, rm, unlink } from 'node:fs/promises'\nimport Fastify, { type FastifyInstance } from 'fastify'\nimport fastifyCors from '@fastify/cors'\nimport fastifyStatic from '@fastify/static'\nimport { z } from 'zod'\nimport type { SpecsConfig, StartServerOptions, StartedServer, TaskNode } from './types.js'\nimport { applyDefaults } from './config-defaults.js'\nimport {\n cliCachePath,\n desktopHistoryPath,\n readClaudeUsage,\n statuslineSnapshotPath,\n} from './claude-usage.js'\nimport { createSpecsWatcher } from './specs-watcher.js'\nimport {\n SLUG_REGEX,\n assertInsideProject,\n atomicWrite,\n dirExists,\n fileExists,\n isValidSlug,\n readText,\n} from './fs-utils.js'\nimport { aggregateStatus, buildTree } from './tree-builder.js'\nimport {\n extractDiscoveryFrontmatterFields,\n extractDrawingFrontmatterFields,\n extractFrontmatterFields,\n parseFrontmatter,\n patchStatusInFrontmatter,\n} from './frontmatter.js'\nimport { extractHeadings } from './headings.js'\nimport { runAgent, runDiscoveryAgent, runDrawingAgent, runRefinement } from './run-agent.js'\nimport { collectChanges, fileDiff, openInEditor } from './review.js'\nimport { openPrototype, resolvePrototype, snapshotAbsolutePath } from './prototype.js'\nimport { createJobManager } from './job-manager.js'\nimport { registerJobRoutes } from './job-routes.js'\n\nconst statusSchema = z.enum(['pending', 'in-progress', 'completed', 'blocked'])\nconst slugSchema = z.string().regex(SLUG_REGEX)\n\nconst contentQuerySchema = z.object({\n feature: slugSchema,\n task: slugSchema,\n})\n\nconst reviewDiffQuerySchema = z.object({\n path: z.string().min(1).max(1024),\n commit: z\n .string()\n .regex(/^[0-9a-f]{7,40}$/i)\n .optional(),\n})\n\nconst openEditorBodySchema = z.object({\n path: z.string().min(1).max(1024),\n line: z.number().int().positive().optional(),\n})\n\nconst statusBodySchema = z.object({\n feature: slugSchema,\n task: slugSchema,\n status: statusSchema,\n})\n\nconst reorderFeaturesBodySchema = z.object({\n pages: z.array(slugSchema),\n})\n\nconst reorderTasksBodySchema = z.object({\n feature: slugSchema,\n pages: z.array(slugSchema),\n})\n\nconst runAgentBodySchema = z.object({\n scope: z.enum(['feature', 'featureNoPause', 'task']),\n feature: slugSchema,\n task: slugSchema.optional(),\n})\n\nconst deleteTaskQuerySchema = z.object({\n feature: slugSchema,\n task: slugSchema,\n})\n\nconst deleteFeatureQuerySchema = z.object({\n feature: slugSchema,\n})\n\nconst updateContentBodySchema = z.object({\n feature: slugSchema,\n task: slugSchema,\n body: z.string().max(1_000_000), // 1MB — bem mais que o necessário para um .md de task\n})\n\nconst runRefinementBodySchema = z.object({\n prompt: z.string().min(1).max(10_000),\n})\n\nconst discoveryContentQuerySchema = z.object({\n slug: slugSchema,\n})\n\nconst updateDiscoveryContentBodySchema = z.object({\n slug: slugSchema,\n body: z.string().max(1_000_000),\n})\n\nconst deleteDiscoveryQuerySchema = z.object({\n slug: slugSchema,\n})\n\nconst reorderDiscoveriesBodySchema = z.object({\n pages: z.array(slugSchema),\n})\n\nconst prototypeQuerySchema = z.object({\n feature: slugSchema.optional(),\n})\n\nconst runDiscoveryAgentBodySchema = z.object({\n prompt: z.string().min(1).max(10_000),\n})\n\nconst drawingContentQuerySchema = z.object({\n slug: slugSchema,\n})\n\nconst updateDrawingContentBodySchema = z.object({\n slug: slugSchema,\n body: z.string().max(1_000_000),\n})\n\nconst deleteDrawingQuerySchema = z.object({\n slug: slugSchema,\n})\n\nconst reorderDrawingsBodySchema = z.object({\n pages: z.array(slugSchema),\n})\n\nconst runDrawingAgentBodySchema = z.object({\n prompt: z.string().min(1).max(10_000),\n})\n\nfunction logLine(method: string, url: string, startMs: number, status: number) {\n const dur = Date.now() - startMs\n const stamp = new Date().toISOString()\n console.log(`[${stamp}] ${method} ${url} ${dur}ms -> ${status}`)\n}\n\nasync function readConfigFile(projectRoot: string): Promise<SpecsConfig> {\n const configPath = path.join(projectRoot, '.specs', 'config.json')\n if (!(await fileExists(configPath))) {\n return applyDefaults({})\n }\n try {\n const raw = await readFile(configPath, 'utf8')\n const parsed = JSON.parse(raw) as Partial<SpecsConfig>\n return applyDefaults(parsed)\n } catch (err) {\n throw new Error(`invalid_config: ${(err as Error).message}`)\n }\n}\n\nfunction setTaskPath(projectRoot: string, featuresDir: string, feature: string, task: string) {\n const taskPath = path.resolve(projectRoot, featuresDir, feature, `${task}.md`)\n assertInsideProject(taskPath, projectRoot)\n return taskPath\n}\n\nfunction setMetaPath(projectRoot: string, featuresDir: string, feature?: string) {\n const p = feature\n ? path.resolve(projectRoot, featuresDir, feature, 'meta.json')\n : path.resolve(projectRoot, featuresDir, 'meta.json')\n assertInsideProject(p, projectRoot)\n return p\n}\n\nfunction setDiscoveryPath(projectRoot: string, discoveriesDir: string, slug: string) {\n const p = path.resolve(projectRoot, discoveriesDir, `${slug}.md`)\n assertInsideProject(p, projectRoot)\n return p\n}\n\nfunction setDiscoveryMetaPath(projectRoot: string, discoveriesDir: string) {\n const p = path.resolve(projectRoot, discoveriesDir, 'meta.json')\n assertInsideProject(p, projectRoot)\n return p\n}\n\nfunction setDrawingPath(projectRoot: string, drawingsDir: string, slug: string) {\n const p = path.resolve(projectRoot, drawingsDir, `${slug}.md`)\n assertInsideProject(p, projectRoot)\n return p\n}\n\nfunction setDrawingMetaPath(projectRoot: string, drawingsDir: string) {\n const p = path.resolve(projectRoot, drawingsDir, 'meta.json')\n assertInsideProject(p, projectRoot)\n return p\n}\n\nexport async function startServer(\n userConfig: SpecsConfig,\n opts: StartServerOptions,\n): Promise<StartedServer> {\n const { projectRoot } = opts\n const config = applyDefaults(userConfig)\n const featuresDir = config.featuresDir\n const discoveriesDir = config.discoveriesDir\n const drawingsDir = config.drawingsDir\n\n const rootMetaPath = path.join(projectRoot, featuresDir, 'meta.json')\n if (!(await fileExists(rootMetaPath))) {\n throw new Error(\n `${featuresDir}/meta.json não encontrado em ${projectRoot}. Rode 'specs install' antes de 'specs start'.`,\n )\n }\n\n const fastify: FastifyInstance = Fastify({ logger: false })\n\n await fastify.register(fastifyCors, {\n origin: (origin, cb) => {\n if (!origin) return cb(null, true)\n try {\n const url = new URL(origin)\n if (url.hostname === 'localhost' || url.hostname === '127.0.0.1') {\n return cb(null, true)\n }\n } catch {}\n return cb(new Error('cors_blocked'), false)\n },\n })\n\n // Static files (built UI) — o `@mir-code/specs-platform` empacota o dist da UI e\n // passa o caminho em `uiDir`. Em dev (sem `uiDir`) o Vite serve o renderer em\n // outra porta e faz proxy de `/api` para cá.\n if (opts.uiDir && (await dirExists(opts.uiDir))) {\n await fastify.register(fastifyStatic, {\n root: opts.uiDir,\n prefix: '/',\n })\n // SPA fallback: rotas do react-router (ex.: /feature/x) devolvem o index.html.\n fastify.setNotFoundHandler((req, reply) => {\n if (req.method !== 'GET' || req.url.startsWith('/api')) {\n return reply.code(404).send({ error: 'not_found' })\n }\n return reply.sendFile('index.html')\n })\n }\n\n // Timing + logging hook\n fastify.addHook('onRequest', async (req) => {\n ;(req as unknown as { _startMs: number })._startMs = Date.now()\n })\n fastify.addHook('onResponse', async (req, reply) => {\n const startMs = (req as unknown as { _startMs: number })._startMs ?? Date.now()\n logLine(req.method, req.url, startMs, reply.statusCode)\n })\n\n // Job manager — estado in-memory de execuções inline (PTY).\n const jobManager = createJobManager({ projectRoot })\n registerJobRoutes(\n fastify,\n jobManager,\n () => readConfigFile(projectRoot).catch(() => config),\n projectRoot,\n )\n\n // Watcher de `.specs/` — empurra invalidações para a UI em vez de deixá-la\n // pollando. Também observa os arquivos de uso do Claude, que mudam sozinhos.\n const watcher = createSpecsWatcher({\n projectRoot,\n featuresDir,\n discoveriesDir,\n drawingsDir,\n extraFiles: [\n { file: desktopHistoryPath(), event: { type: 'usage' } },\n { file: cliCachePath(), event: { type: 'usage' } },\n { file: statuslineSnapshotPath(), event: { type: 'usage' } },\n ],\n })\n\n // GET /api/tree\n fastify.get('/api/tree', async (_req, reply) => {\n try {\n const tree = await buildTree(projectRoot, featuresDir, discoveriesDir, drawingsDir)\n return tree\n } catch (err) {\n const msg = (err as Error).message\n if (msg === 'no_features_dir') {\n return reply.code(500).send({ error: 'no_features_dir' })\n }\n return reply.code(500).send({ error: 'internal', detail: msg })\n }\n })\n\n // GET /api/content\n fastify.get('/api/content', async (req, reply) => {\n const parsed = contentQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const { feature, task } = parsed.data\n let taskPath: string\n try {\n taskPath = setTaskPath(projectRoot, featuresDir, feature, task)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (!(await fileExists(taskPath))) {\n return reply.code(404).send({ error: 'task_not_found' })\n }\n const raw = await readText(taskPath)\n const { data, body } = parseFrontmatter(raw)\n const frontmatter = {\n ...data,\n ...extractFrontmatterFields(data),\n }\n const headings = extractHeadings(body)\n return { frontmatter, body, headings, raw }\n })\n\n // GET /api/review/changes — working tree vs HEAD, com o diff de cada arquivo\n fastify.get('/api/review/changes', async (_req, reply) => {\n try {\n return await collectChanges(projectRoot)\n } catch (err) {\n return reply.code(500).send({ error: 'git_failed', detail: (err as Error).message })\n }\n })\n\n // GET /api/review/diff — diff de um arquivo, sob demanda\n fastify.get('/api/review/diff', async (req, reply) => {\n const parsed = reviewDiffQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n try {\n return await fileDiff(projectRoot, parsed.data.path, parsed.data.commit)\n } catch (err) {\n const message = (err as Error).message\n const status = message === 'invalid_path' ? 400 : 500\n return reply.code(status).send({ error: message })\n }\n })\n\n // POST /api/review/open — abre o arquivo no editor configurado\n fastify.post('/api/review/open', async (req, reply) => {\n const parsed = openEditorBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body' })\n }\n const current = await readConfigFile(projectRoot).catch(() => config)\n const result = await openInEditor(\n projectRoot,\n current.review.openCommand,\n parsed.data.path,\n parsed.data.line,\n )\n if (!result.ok) {\n const status = result.error === 'invalid_path' ? 400 : 500\n return reply.code(status).send(result)\n }\n return result\n })\n\n // POST /api/status\n fastify.post('/api/status', async (req, reply) => {\n const parsed = statusBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const { feature, task, status } = parsed.data\n let taskPath: string\n try {\n taskPath = setTaskPath(projectRoot, featuresDir, feature, task)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (!(await fileExists(taskPath))) {\n return reply.code(404).send({ error: 'task_not_found' })\n }\n const raw = await readText(taskPath)\n const next = patchStatusInFrontmatter(raw, status)\n if (next !== raw) {\n await atomicWrite(taskPath, next)\n }\n return { ok: true, status }\n })\n\n // POST /api/reorder-features\n fastify.post('/api/reorder-features', async (req, reply) => {\n const parsed = reorderFeaturesBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body' })\n }\n const { pages } = parsed.data\n const metaPath = setMetaPath(projectRoot, featuresDir)\n const raw = await readText(metaPath)\n let meta: { pages?: unknown } & Record<string, unknown>\n try {\n meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n } catch {\n return reply.code(500).send({ error: 'invalid_meta' })\n }\n const currentSet = new Set(Array.isArray(meta.pages) ? (meta.pages as string[]) : [])\n const newSet = new Set(pages)\n if (currentSet.size !== newSet.size || [...currentSet].some((s) => !newSet.has(s))) {\n return reply.code(400).send({ error: 'invalid_pages' })\n }\n meta.pages = pages\n await atomicWrite(metaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n return { ok: true }\n })\n\n // POST /api/reorder-tasks\n fastify.post('/api/reorder-tasks', async (req, reply) => {\n const parsed = reorderTasksBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body' })\n }\n const { feature, pages } = parsed.data\n const metaPath = setMetaPath(projectRoot, featuresDir, feature)\n if (!(await fileExists(metaPath))) {\n return reply.code(404).send({ error: 'feature_not_found' })\n }\n const raw = await readText(metaPath)\n let meta: { pages?: unknown } & Record<string, unknown>\n try {\n meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n } catch {\n return reply.code(500).send({ error: 'invalid_meta' })\n }\n const currentSet = new Set(Array.isArray(meta.pages) ? (meta.pages as string[]) : [])\n const newSet = new Set(pages)\n if (currentSet.size !== newSet.size || [...currentSet].some((s) => !newSet.has(s))) {\n return reply.code(400).send({ error: 'invalid_pages' })\n }\n meta.pages = pages\n await atomicWrite(metaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n return { ok: true }\n })\n\n // POST /api/run-agent\n fastify.post('/api/run-agent', async (req, reply) => {\n const parsed = runAgentBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body' })\n }\n const fresh = await readConfigFile(projectRoot).catch(() => config)\n const result = await runAgent(parsed.data, fresh, projectRoot)\n if (result.ok) return { ok: true }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n })\n\n // POST /api/run-refinement — dispara o agent `refinement` em terminal externo\n // com texto livre fornecido pelo usuário.\n fastify.post('/api/run-refinement', async (req, reply) => {\n const parsed = runRefinementBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const fresh = await readConfigFile(projectRoot).catch(() => config)\n const result = runRefinement(parsed.data.prompt, fresh, projectRoot)\n if (result.ok) return { ok: true }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n })\n\n // POST /api/run-discovery-agent — dispara o agent `discovery-agent` em terminal\n // externo com texto livre fornecido pelo usuário.\n fastify.post('/api/run-discovery-agent', async (req, reply) => {\n const parsed = runDiscoveryAgentBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const fresh = await readConfigFile(projectRoot).catch(() => config)\n const result = runDiscoveryAgent(parsed.data.prompt, fresh, projectRoot)\n if (result.ok) return { ok: true }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n })\n\n // POST /api/run-drawing-agent — dispara o agent `drawing-agent` em terminal\n // externo com texto livre fornecido pelo usuário.\n fastify.post('/api/run-drawing-agent', async (req, reply) => {\n const parsed = runDrawingAgentBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const fresh = await readConfigFile(projectRoot).catch(() => config)\n const result = runDrawingAgent(parsed.data.prompt, fresh, projectRoot)\n if (result.ok) return { ok: true }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n })\n\n // PUT /api/content — reescreve o arquivo .md de uma task (inclui frontmatter).\n fastify.put('/api/content', async (req, reply) => {\n const parsed = updateContentBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const { feature, task, body } = parsed.data\n let taskPath: string\n try {\n taskPath = setTaskPath(projectRoot, featuresDir, feature, task)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (!(await fileExists(taskPath))) {\n return reply.code(404).send({ error: 'task_not_found' })\n }\n await atomicWrite(taskPath, body)\n return { ok: true }\n })\n\n // DELETE /api/task — remove .md + remove slug do pages no meta.json da feature.\n fastify.delete('/api/task', async (req, reply) => {\n const parsed = deleteTaskQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const { feature, task } = parsed.data\n let taskPath: string\n let featureMetaPath: string\n try {\n taskPath = setTaskPath(projectRoot, featuresDir, feature, task)\n featureMetaPath = setMetaPath(projectRoot, featuresDir, feature)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n // Remove o arquivo .md (se existir — idempotente)\n if (await fileExists(taskPath)) {\n await unlink(taskPath)\n }\n // Remove o slug do pages no meta.json (se existir)\n if (await fileExists(featureMetaPath)) {\n const raw = await readText(featureMetaPath)\n try {\n const meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n if (Array.isArray(meta.pages)) {\n const filtered = (meta.pages as unknown[]).filter((p) => p !== task)\n if (filtered.length !== (meta.pages as unknown[]).length) {\n meta.pages = filtered\n await atomicWrite(featureMetaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n }\n }\n } catch {\n // meta.json inválido — ignora a parte do meta mas já deletamos o .md\n }\n }\n return { ok: true }\n })\n\n // DELETE /api/feature — remove a pasta inteira da feature + remove slug do\n // pages no meta.json raiz.\n fastify.delete('/api/feature', async (req, reply) => {\n const parsed = deleteFeatureQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const { feature } = parsed.data\n const featureDir = path.resolve(projectRoot, featuresDir, feature)\n try {\n assertInsideProject(featureDir, projectRoot)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n // Remove o diretório da feature recursivamente (se existir)\n if (await dirExists(featureDir)) {\n await rm(featureDir, { recursive: true, force: true })\n }\n // Remove do pages no meta.json raiz\n const rootMetaPath = setMetaPath(projectRoot, featuresDir)\n if (await fileExists(rootMetaPath)) {\n const raw = await readText(rootMetaPath)\n try {\n const meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n if (Array.isArray(meta.pages)) {\n const filtered = (meta.pages as unknown[]).filter((p) => p !== feature)\n if (filtered.length !== (meta.pages as unknown[]).length) {\n meta.pages = filtered\n await atomicWrite(rootMetaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n }\n }\n } catch {\n // meta.json inválido — ignora mas já deletamos a pasta\n }\n }\n return { ok: true }\n })\n\n // GET /api/discovery/content?slug=X\n fastify.get('/api/discovery/content', async (req, reply) => {\n const parsed = discoveryContentQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const { slug } = parsed.data\n let discoveryPath: string\n try {\n discoveryPath = setDiscoveryPath(projectRoot, discoveriesDir, slug)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (!(await fileExists(discoveryPath))) {\n return reply.code(404).send({ error: 'discovery_not_found' })\n }\n const raw = await readText(discoveryPath)\n const { data, body } = parseFrontmatter(raw)\n const frontmatter = {\n ...data,\n ...extractDiscoveryFrontmatterFields(data),\n }\n const headings = extractHeadings(body)\n return { frontmatter, body, headings, raw }\n })\n\n // PUT /api/discovery/content — reescreve o arquivo .md de uma discovery (inclui frontmatter).\n fastify.put('/api/discovery/content', async (req, reply) => {\n const parsed = updateDiscoveryContentBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const { slug, body } = parsed.data\n let discoveryPath: string\n try {\n discoveryPath = setDiscoveryPath(projectRoot, discoveriesDir, slug)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (!(await fileExists(discoveryPath))) {\n return reply.code(404).send({ error: 'discovery_not_found' })\n }\n await atomicWrite(discoveryPath, body)\n return { ok: true }\n })\n\n // DELETE /api/discovery — remove .md + remove slug do pages no meta.json.\n fastify.delete('/api/discovery', async (req, reply) => {\n const parsed = deleteDiscoveryQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const { slug } = parsed.data\n let discoveryPath: string\n let discoveryMetaPath: string\n try {\n discoveryPath = setDiscoveryPath(projectRoot, discoveriesDir, slug)\n discoveryMetaPath = setDiscoveryMetaPath(projectRoot, discoveriesDir)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (await fileExists(discoveryPath)) {\n await unlink(discoveryPath)\n }\n if (await fileExists(discoveryMetaPath)) {\n const raw = await readText(discoveryMetaPath)\n try {\n const meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n if (Array.isArray(meta.pages)) {\n const filtered = (meta.pages as unknown[]).filter((p) => p !== slug)\n if (filtered.length !== (meta.pages as unknown[]).length) {\n meta.pages = filtered\n await atomicWrite(discoveryMetaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n }\n }\n } catch {\n // meta inválido — ignora\n }\n }\n return { ok: true }\n })\n\n // POST /api/reorder-discoveries\n fastify.post('/api/reorder-discoveries', async (req, reply) => {\n const parsed = reorderDiscoveriesBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body' })\n }\n const { pages } = parsed.data\n const metaPath = setDiscoveryMetaPath(projectRoot, discoveriesDir)\n if (!(await fileExists(metaPath))) {\n return reply.code(404).send({ error: 'discoveries_meta_not_found' })\n }\n const raw = await readText(metaPath)\n let meta: { pages?: unknown } & Record<string, unknown>\n try {\n meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n } catch {\n return reply.code(500).send({ error: 'invalid_meta' })\n }\n const currentSet = new Set(Array.isArray(meta.pages) ? (meta.pages as string[]) : [])\n const newSet = new Set(pages)\n if (currentSet.size !== newSet.size || [...currentSet].some((s) => !newSet.has(s))) {\n return reply.code(400).send({ error: 'invalid_pages' })\n }\n meta.pages = pages\n await atomicWrite(metaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n return { ok: true }\n })\n\n // GET /api/drawing/content?slug=X\n fastify.get('/api/drawing/content', async (req, reply) => {\n const parsed = drawingContentQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n let drawingPath: string\n try {\n drawingPath = setDrawingPath(projectRoot, drawingsDir, parsed.data.slug)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (!(await fileExists(drawingPath))) {\n return reply.code(404).send({ error: 'drawing_not_found' })\n }\n const raw = await readText(drawingPath)\n const { data, body } = parseFrontmatter(raw)\n const frontmatter = {\n ...data,\n ...extractDrawingFrontmatterFields(data),\n }\n const headings = extractHeadings(body)\n return { frontmatter, body, headings, raw }\n })\n\n // PUT /api/drawing/content — reescreve o arquivo .md de um desenho (inclui frontmatter).\n fastify.put('/api/drawing/content', async (req, reply) => {\n const parsed = updateDrawingContentBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const { slug, body } = parsed.data\n let drawingPath: string\n try {\n drawingPath = setDrawingPath(projectRoot, drawingsDir, slug)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (!(await fileExists(drawingPath))) {\n return reply.code(404).send({ error: 'drawing_not_found' })\n }\n await atomicWrite(drawingPath, body)\n return { ok: true }\n })\n\n // DELETE /api/drawing — remove .md + remove slug do pages no meta.json.\n fastify.delete('/api/drawing', async (req, reply) => {\n const parsed = deleteDrawingQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const { slug } = parsed.data\n let drawingPath: string\n let drawingMetaPath: string\n try {\n drawingPath = setDrawingPath(projectRoot, drawingsDir, slug)\n drawingMetaPath = setDrawingMetaPath(projectRoot, drawingsDir)\n } catch {\n return reply.code(400).send({ error: 'invalid_path' })\n }\n if (await fileExists(drawingPath)) {\n await unlink(drawingPath)\n }\n if (await fileExists(drawingMetaPath)) {\n const raw = await readText(drawingMetaPath)\n try {\n const meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n if (Array.isArray(meta.pages)) {\n const filtered = (meta.pages as unknown[]).filter((p) => p !== slug)\n if (filtered.length !== (meta.pages as unknown[]).length) {\n meta.pages = filtered\n await atomicWrite(drawingMetaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n }\n }\n } catch {\n // meta inválido — ignora\n }\n }\n return { ok: true }\n })\n\n // POST /api/reorder-drawings\n fastify.post('/api/reorder-drawings', async (req, reply) => {\n const parsed = reorderDrawingsBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body' })\n }\n const { pages } = parsed.data\n const metaPath = setDrawingMetaPath(projectRoot, drawingsDir)\n if (!(await fileExists(metaPath))) {\n return reply.code(404).send({ error: 'drawings_meta_not_found' })\n }\n const raw = await readText(metaPath)\n let meta: { pages?: unknown } & Record<string, unknown>\n try {\n meta = JSON.parse(raw) as { pages?: unknown } & Record<string, unknown>\n } catch {\n return reply.code(500).send({ error: 'invalid_meta' })\n }\n const currentSet = new Set(Array.isArray(meta.pages) ? (meta.pages as string[]) : [])\n const newSet = new Set(pages)\n if (currentSet.size !== newSet.size || [...currentSet].some((s) => !newSet.has(s))) {\n return reply.code(400).send({ error: 'invalid_pages' })\n }\n meta.pages = pages\n await atomicWrite(metaPath, `${JSON.stringify(meta, null, 2)}\\n`)\n return { ok: true }\n })\n\n // GET /api/prototype — protótipo em vigor (config do projeto + override da feature)\n fastify.get('/api/prototype', async (req, reply) => {\n const parsed = prototypeQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const fresh = await readConfigFile(projectRoot).catch(() => config)\n const prototype = await resolvePrototype(projectRoot, fresh, parsed.data.feature)\n return { prototype }\n })\n\n // GET /api/prototype/frame — snapshot local do protótipo, servido na mesma\n // origem da UI para poder ir num iframe (o canvas remoto manda\n // `frame-ancestors 'self'` e recusa embed cross-origin).\n fastify.get('/api/prototype/frame', async (req, reply) => {\n const parsed = prototypeQuerySchema.safeParse(req.query)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_query' })\n }\n const fresh = await readConfigFile(projectRoot).catch(() => config)\n const prototype = await resolvePrototype(projectRoot, fresh, parsed.data.feature)\n if (!prototype) return reply.code(404).send({ error: 'no_prototype' })\n const abs = snapshotAbsolutePath(projectRoot, prototype)\n if (!abs) return reply.code(404).send({ error: 'no_snapshot' })\n const html = await readText(abs)\n return reply.type('text/html; charset=utf-8').header('cache-control', 'no-store').send(html)\n })\n\n // POST /api/prototype/open — abre o protótipo no app local (Pencil)\n fastify.post('/api/prototype/open', async (req, reply) => {\n const parsed = prototypeQuerySchema.safeParse(req.body ?? {})\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body' })\n }\n const fresh = await readConfigFile(projectRoot).catch(() => config)\n const prototype = await resolvePrototype(projectRoot, fresh, parsed.data.feature)\n if (!prototype) return reply.code(404).send({ error: 'no_prototype' })\n const result = openPrototype(projectRoot, prototype)\n if (result.ok) return result\n return reply.code(result.status).send(result)\n })\n\n // GET /api/config\n // Uso de tokens do Claude Code (mesmo dado do `/usage`). É informativo: quando\n // não há cache — outra CLI, ou Claude Code nunca rodou aqui — devolve null e a\n // UI simplesmente não mostra o medidor.\n // SSE de mudanças no disco. A UI abre uma conexão só e invalida as queries\n // conforme os eventos chegam. `watching: false` avisa que o SO não suporta\n // watch recursivo, e aí a UI volta a pollar.\n fastify.get('/api/events', async (req, reply) => {\n reply.raw.setHeader('content-type', 'text/event-stream')\n reply.raw.setHeader('cache-control', 'no-cache, no-transform')\n reply.raw.setHeader('connection', 'keep-alive')\n reply.raw.setHeader('x-accel-buffering', 'no')\n reply.raw.flushHeaders?.()\n\n reply.raw.write(`data: ${JSON.stringify({ type: 'hello', watching: watcher.watching })}\\n\\n`)\n\n const keepAlive = setInterval(() => {\n reply.raw.write(': ping\\n\\n')\n }, 15_000)\n\n const unsubscribe = watcher.subscribe((events) => {\n reply.raw.write(`data: ${JSON.stringify({ type: 'change', events })}\\n\\n`)\n })\n\n req.raw.on('close', () => {\n clearInterval(keepAlive)\n unsubscribe()\n })\n\n return reply\n })\n\n fastify.get('/api/usage', async (_req, reply) => {\n return reply.send({ usage: await readClaudeUsage() })\n })\n\n fastify.get('/api/config', async (_req, reply) => {\n try {\n const fresh = await readConfigFile(projectRoot)\n return { config: fresh, projectRoot }\n } catch (err) {\n return reply.code(500).send({ error: 'invalid_config', detail: (err as Error).message })\n }\n })\n\n // Health\n fastify.get('/health', async () => ({ ok: true }))\n\n const host = '127.0.0.1'\n const port = config.port\n await fastify.listen({ host, port })\n\n return {\n url: `http://localhost:${port}`,\n port,\n close: async () => {\n watcher.close()\n await jobManager.shutdownAll()\n await fastify.close()\n },\n }\n}\n\n// helper reexports not used externally but available\nexport { aggregateStatus }\nexport type { TaskNode }\n","import type { PrototypeConfig, SpecsConfig } from './types.js'\n\nexport const DEFAULT_INPUT_PROMPT_PATTERNS: string[] = [\n '\\\\?\\\\s*$',\n '\\\\((?:y\\\\/n|Y\\\\/n|y\\\\/N|Y\\\\/N)\\\\)',\n 'press\\\\s+(?:enter|any key)',\n 'Do you want to',\n 'Would you like to',\n 'waiting for input',\n '❯\\\\s*$',\n]\n\nexport const DEFAULT_REVIEW_OPEN_COMMAND = 'cursor --goto {path}:{line}'\n\nexport const DEFAULT_CLAUDE_COMMAND = 'claude {model} {effort} --agent feature-runner \"{prompt}\"'\nexport const DEFAULT_CURSOR_COMMAND =\n 'cursor-agent {model} \"Use the feature-runner subagent. {prompt}\"'\n\n/** Comando para listar modelos dinamicamente, por CLI. */\nexport const DEFAULT_MODELS_COMMAND: Record<string, string> = {\n cursor: 'cursor-agent --list-models',\n}\n\n/**\n * Lista estática de modelos por CLI. O Claude Code não expõe listagem via CLI,\n * então usamos os aliases oficiais (`--model <alias>`). Pode ser sobrescrita ou\n * estendida no `.specs/config.json`.\n */\nexport const DEFAULT_STATIC_MODELS: Record<string, string[]> = {\n claude: ['opus', 'sonnet', 'haiku', 'fable'],\n}\n\n/** Comando de abertura local do protótipo, por ferramenta. `{file}` e `{url}` são expandidos. */\nexport const DEFAULT_PROTOTYPE_OPEN_COMMAND: Record<string, string> = {\n pencil: 'open -a Pencil {file}',\n 'claude-design': 'open {url}',\n}\n\n/**\n * Normaliza o bloco `prototype`. Descarta declarações sem `tool` conhecida ou\n * sem o alvo que a ferramenta exige (`url` no Claude Design, `file` no Pencil) —\n * um protótipo meio declarado só geraria botão quebrado na UI.\n */\nexport function normalizePrototype(raw: unknown): PrototypeConfig | null {\n if (!raw || typeof raw !== 'object') return null\n const p = raw as Partial<PrototypeConfig>\n if (p.tool !== 'claude-design' && p.tool !== 'pencil') return null\n if (p.tool === 'claude-design' && !p.url) return null\n if (p.tool === 'pencil' && !p.file) return null\n return {\n tool: p.tool,\n ...(p.title ? { title: p.title } : {}),\n ...(p.url ? { url: p.url } : {}),\n ...(p.file ? { file: p.file } : {}),\n ...(p.designDir ? { designDir: p.designDir } : {}),\n ...(Array.isArray(p.artboards) ? { artboards: p.artboards.map(String) } : {}),\n ...(Array.isArray(p.nodeIds) ? { nodeIds: p.nodeIds.map(String) } : {}),\n ...(p.openCommand ? { openCommand: p.openCommand } : {}),\n ...(p.snapshot ? { snapshot: p.snapshot } : {}),\n }\n}\n\nexport function applyDefaults(partial: Partial<SpecsConfig>): SpecsConfig {\n const agent = partial.agent ?? ({} as Partial<SpecsConfig['agent']>)\n const scopes = agent.scopes ?? ({} as Partial<SpecsConfig['agent']['scopes']>)\n\n // `commands` define um template por CLI. Para retrocompat, se o usuário só tem\n // o legado `agent.command`, ele vira o template do `claude`. Os defaults de\n // claude/cursor sempre existem (a menos que o usuário sobrescreva).\n const userCommands = agent.commands ?? {}\n const commands: Record<string, string> = {\n claude: userCommands.claude ?? agent.command ?? DEFAULT_CLAUDE_COMMAND,\n cursor: userCommands.cursor ?? DEFAULT_CURSOR_COMMAND,\n ...userCommands,\n }\n const cli = agent.cli && commands[agent.cli] ? agent.cli : 'claude'\n\n const modelsCommand: Record<string, string> = {\n ...DEFAULT_MODELS_COMMAND,\n ...(agent.modelsCommand ?? {}),\n }\n const models: Record<string, string[]> = {\n ...DEFAULT_STATIC_MODELS,\n ...(agent.models ?? {}),\n }\n\n return {\n agent: {\n cli,\n commands,\n modelsCommand,\n models,\n command: agent.command ?? commands[cli] ?? DEFAULT_CLAUDE_COMMAND,\n openTerminal: agent.openTerminal ?? (process.platform === 'darwin' ? 'osascript' : 'none'),\n cwd: agent.cwd ?? '.',\n scopes: {\n feature:\n scopes.feature ??\n 'Execute a feature \"{featureTitle}\" ({featurePath}). Se houver task em progresso, continue de onde parou; senão, escolha a próxima task em pages[] do meta.json.',\n featureNoPause:\n scopes.featureNoPause ??\n 'Execute a feature \"{featureTitle}\" ({featurePath}) por inteiro, sem pausar entre tasks. Continue executando cada próxima task pendente do meta.json automaticamente até completar todas. Os testes E2E e a solicitação de code review devem ser feitos apenas ao final de todas as tasks.',\n task:\n scopes.task ??\n 'Execute a task {featurePath}{task}.md. Se já houver trabalho em progresso nela, continue de onde parou.',\n },\n defaultExecutionMode: agent.defaultExecutionMode ?? 'inline',\n sound: agent.sound ?? true,\n inputPromptPatterns:\n agent.inputPromptPatterns && agent.inputPromptPatterns.length > 0\n ? agent.inputPromptPatterns\n : DEFAULT_INPUT_PROMPT_PATTERNS,\n bufferBytesCap: agent.bufferBytesCap ?? 2_000_000,\n },\n prototype: normalizePrototype(partial.prototype),\n review: {\n openCommand: partial.review?.openCommand ?? DEFAULT_REVIEW_OPEN_COMMAND,\n },\n theme: 'dark',\n warnBelowWidth: partial.warnBelowWidth ?? 1024,\n featuresDir: partial.featuresDir ?? '.specs/specs',\n discoveriesDir: partial.discoveriesDir ?? '.specs/discoveries',\n drawingsDir: partial.drawingsDir ?? '.specs/drawings',\n port: partial.port ?? 4321,\n }\n}\n","import { readFile, stat } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\n\nconst HOUR_MS = 3_600_000\nconst FIVE_HOURS_MS = 5 * HOUR_MS\nconst SEVEN_DAYS_MS = 7 * 24 * HOUR_MS\n\n/** Janela de rate limit do plano. `resetsAt` é epoch em **segundos**. */\nexport type UsageWindow = {\n usedPercentage: number\n resetsAt: number | null\n /** true quando o horário de reset foi deduzido do histórico, não lido direto. */\n resetEstimated: boolean\n}\n\nexport type UsageSource = 'desktop-history' | 'cli-cache' | 'statusline'\n\nexport type ClaudeUsage = {\n fiveHour: UsageWindow | null\n sevenDay: UsageWindow | null\n /** Quando o dado foi medido (epoch ms) — não é o mtime do arquivo. */\n measuredAt: number\n source: UsageSource\n}\n\n/**\n * Histórico de uso do plano que o app desktop do Claude grava a cada ~15–25 min\n * enquanto está aberto. Cada amostra tem `t` (epoch ms) e `u.fh` / `u.sd`, as\n * porcentagens das janelas de 5 horas e de 7 dias.\n */\nexport function desktopHistoryPath(home: string = os.homedir()): string {\n return path.join(home, 'Library', 'Application Support', 'Claude', 'plan-usage-history.json')\n}\n\n/**\n * Cache de rate limits do CLI. Em versões recentes do Claude Code ele parou de\n * ser reescrito, então serve só de fallback — e só quando for mais novo que o\n * histórico do desktop.\n */\nexport function cliCachePath(home: string = os.homedir()): string {\n return path.join(home, '.claude', 'rate-limits-cache.json')\n}\n\n/**\n * Snapshot gravado pelo statusLine do Claude Code.\n *\n * É a **única fonte que não depende do app desktop**: o Claude Code entrega\n * `rate_limits.five_hour` e `.seven_day` (percentual e reset) no JSON que manda\n * para o comando de statusLine — mas só para assinantes Pro/Max e só depois da\n * primeira resposta da API na sessão. Não há endpoint da API para consultar isso:\n * a Usage & Cost Admin API exige chave de organização do Console e reporta\n * tokens/custo da API, não a janela do plano.\n *\n * Quem grava o arquivo é `scripts/specs-usage-statusline.sh`, plugado no\n * `statusLine` do usuário. Sem ele, esta fonte simplesmente não existe.\n */\nexport function statuslineSnapshotPath(home: string = os.homedir()): string {\n return path.join(home, '.claude', 'specs-usage.json')\n}\n\nexport type UsageSample = { t: number; fh: number; sd: number }\n\nfunction parseSamples(raw: unknown): UsageSample[] {\n if (typeof raw !== 'object' || raw === null) return []\n const list = (raw as { samples?: unknown }).samples\n if (!Array.isArray(list)) return []\n const out: UsageSample[] = []\n for (const item of list) {\n if (typeof item !== 'object' || item === null) continue\n const { t, u } = item as { t?: unknown; u?: unknown }\n if (typeof t !== 'number' || !Number.isFinite(t)) continue\n if (typeof u !== 'object' || u === null) continue\n const { fh, sd } = u as { fh?: unknown; sd?: unknown }\n if (typeof fh !== 'number' || typeof sd !== 'number') continue\n out.push({ t, fh, sd })\n }\n return out.sort((a, b) => a.t - b.t)\n}\n\n/**\n * Intervalos em que uma queda de porcentagem foi observada. Cada queda significa\n * \"o reset aconteceu em algum ponto de `(from, to]`\" — e não no instante `to`,\n * já que o app desktop só amostra enquanto está aberto e pode ter ficado dias\n * fechado por cima de um reset.\n */\nexport function dropIntervals(\n samples: UsageSample[],\n key: 'fh' | 'sd',\n): Array<{ from: number; to: number }> {\n const out: Array<{ from: number; to: number }> = []\n for (let i = 1; i < samples.length; i += 1) {\n const prev = samples[i - 1]\n const cur = samples[i]\n if (!prev || !cur) continue\n if (cur[key] < prev[key]) out.push({ from: prev.t, to: cur.t })\n }\n return out\n}\n\n/** Horas cheias contidas em `(from, to]`. */\nfunction hourBoundariesIn(from: number, to: number): number[] {\n const out: number[] = []\n let h = Math.floor(from / HOUR_MS) * HOUR_MS + HOUR_MS\n while (h <= to) {\n out.push(h)\n h += HOUR_MS\n }\n return out\n}\n\n/**\n * Reset da janela de sessão (5h). Ela **não** tem fase fixa: cada janela começa\n * na primeira mensagem depois de um período ocioso. Então só dá para estimar a\n * partir da última queda observada — e só quando o intervalo dessa queda contém\n * exatamente uma hora cheia, que é onde a Anthropic ancora o início da janela.\n *\n * Devolve null quando a queda é ambígua ou velha demais (o reset calculado já\n * passou ⇒ perdemos janelas no meio e qualquer palpite seria chute).\n */\nexport function inferSessionReset(samples: UsageSample[], now: number): number | null {\n const drops = dropIntervals(samples, 'fh')\n const last = drops[drops.length - 1]\n if (!last) return null\n if (last.to - last.from > HOUR_MS) return null\n\n const boundaries = hourBoundariesIn(last.from, last.to)\n const anchor = boundaries.length === 1 ? boundaries[0] : undefined\n if (anchor === undefined) return null\n\n const reset = anchor + FIVE_HOURS_MS\n return reset > now ? reset : null\n}\n\n/**\n * Reset da janela semanal (7d). Essa **é** periódica — cai sempre no mesmo dia e\n * hora — então dá para achar a fase mesmo com o histórico cheio de buracos:\n * testamos cada hora cheia dentro do período e ficamos com a que melhor explica\n * as quedas observadas.\n *\n * Cada queda vale conforme a **estreiteza** do seu intervalo: uma queda flagrada\n * numa janela de 1h praticamente crava a hora do reset, enquanto uma flagrada\n * depois de dias com o app fechado quase não informa nada. Sem esse peso, um\n * punhado de intervalos largos empataria com a evidência boa.\n */\nexport function inferPeriodicReset(\n samples: UsageSample[],\n key: 'fh' | 'sd',\n periodMs: number,\n now: number,\n): number | null {\n const drops = dropIntervals(samples, key)\n const lastDrop = drops[drops.length - 1]\n if (!lastDrop) return null\n\n const base = Math.floor(lastDrop.to / HOUR_MS) * HOUR_MS\n const slots = Math.round(periodMs / HOUR_MS)\n let best: number | null = null\n let bestScore = -1\n\n for (let h = 0; h < slots; h += 1) {\n const candidate = base - h * HOUR_MS\n let score = 0\n for (const drop of drops) {\n // Última ocorrência da fase candidata que não passa de `drop.to`.\n const k = Math.floor((drop.to - candidate) / periodMs)\n const instant = candidate + k * periodMs\n if (instant > drop.from && instant <= drop.to) {\n score += HOUR_MS / Math.max(drop.to - drop.from, HOUR_MS)\n }\n }\n if (score > bestScore) {\n bestScore = score\n best = candidate\n }\n }\n if (best === null || bestScore <= 0) return null\n\n let reset = best\n while (reset <= now) reset += periodMs\n return reset\n}\n\nfunction windowFrom(percentage: number, resetMs: number | null, estimated: boolean): UsageWindow {\n return {\n usedPercentage: Math.max(0, Math.min(100, percentage)),\n resetsAt: resetMs === null ? null : Math.round(resetMs / 1000),\n resetEstimated: estimated,\n }\n}\n\nasync function readDesktopHistory(home: string, now: number): Promise<ClaudeUsage | null> {\n try {\n const samples = parseSamples(JSON.parse(await readFile(desktopHistoryPath(home), 'utf8')))\n const latest = samples[samples.length - 1]\n if (!latest) return null\n return {\n fiveHour: windowFrom(latest.fh, inferSessionReset(samples, now), true),\n sevenDay: windowFrom(latest.sd, inferPeriodicReset(samples, 'sd', SEVEN_DAYS_MS, now), true),\n measuredAt: latest.t,\n source: 'desktop-history',\n }\n } catch {\n return null\n }\n}\n\nfunction parseCliWindow(raw: unknown): UsageWindow | null {\n if (typeof raw !== 'object' || raw === null) return null\n const { used_percentage: used, resets_at: resets } = raw as Record<string, unknown>\n if (typeof used !== 'number' || !Number.isFinite(used)) return null\n const resetsAt = typeof resets === 'number' && Number.isFinite(resets) ? resets * 1000 : null\n return windowFrom(used, resetsAt, false)\n}\n\n/**\n * Lê o snapshot do statusLine. `measuredAt` vem do próprio arquivo (o instante\n * em que o Claude Code entregou o dado), não do mtime — o script pode reescrever\n * o arquivo sem que os números tenham mudado.\n */\nasync function readStatuslineSnapshot(home: string): Promise<ClaudeUsage | null> {\n try {\n const parsed: unknown = JSON.parse(await readFile(statuslineSnapshotPath(home), 'utf8'))\n if (typeof parsed !== 'object' || parsed === null) return null\n const record = parsed as Record<string, unknown>\n const fiveHour = parseCliWindow(record.five_hour)\n const sevenDay = parseCliWindow(record.seven_day)\n if (!fiveHour && !sevenDay) return null\n const measuredAt =\n typeof record.measuredAt === 'number' && Number.isFinite(record.measuredAt)\n ? record.measuredAt\n : 0\n if (measuredAt <= 0) return null\n return { fiveHour, sevenDay, measuredAt, source: 'statusline' }\n } catch {\n return null\n }\n}\n\nasync function readCliCache(home: string): Promise<ClaudeUsage | null> {\n const file = cliCachePath(home)\n try {\n const [raw, info] = await Promise.all([readFile(file, 'utf8'), stat(file)])\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed !== 'object' || parsed === null) return null\n const record = parsed as Record<string, unknown>\n const fiveHour = parseCliWindow(record.five_hour)\n const sevenDay = parseCliWindow(record.seven_day)\n if (!fiveHour && !sevenDay) return null\n return { fiveHour, sevenDay, measuredAt: info.mtimeMs, source: 'cli-cache' }\n } catch {\n return null\n }\n}\n\n/**\n * Uso do plano do Claude. Lê as três fontes locais possíveis e devolve a **mais\n * recente**, sem preferir nenhuma por natureza: o snapshot do statusLine ganha\n * quando você está usando o Claude Code, o histórico do desktop ganha quando o\n * app está aberto, e o cache do CLI é um fóssil que quase nunca vence.\n *\n * Devolve `null` quando nenhuma existe; é um dado informativo, então nunca lança.\n */\nexport async function readClaudeUsage(\n home: string = os.homedir(),\n now: number = Date.now(),\n): Promise<ClaudeUsage | null> {\n const candidates = await Promise.all([\n readDesktopHistory(home, now),\n readCliCache(home),\n readStatuslineSnapshot(home),\n ])\n let best: ClaudeUsage | null = null\n for (const candidate of candidates) {\n if (!candidate) continue\n if (!best || candidate.measuredAt > best.measuredAt) best = candidate\n }\n return best\n}\n","import { watch, type FSWatcher } from 'node:fs'\nimport path from 'node:path'\n\n/**\n * Mudança observada no disco, já traduzida para \"o que a UI precisa reinvalidar\".\n * O watcher não sabe nada de react-query — só descreve o que mudou.\n */\nexport type SpecsChangeEvent =\n | { type: 'tree' }\n | { type: 'content'; feature: string; task: string }\n | { type: 'discovery'; slug: string }\n | { type: 'drawing'; slug: string }\n | { type: 'config' }\n | { type: 'usage' }\n\nexport type ClassifyDirs = {\n /** Relativo ao projectRoot, ex.: `.specs/specs`. */\n featuresDir: string\n /** Relativo ao projectRoot, ex.: `.specs/discoveries`. */\n discoveriesDir: string\n /** Relativo ao projectRoot, ex.: `.specs/drawings`. */\n drawingsDir: string\n}\n\nfunction segments(relPath: string): string[] {\n return relPath.split(path.sep).filter((s) => s.length > 0 && s !== '.')\n}\n\nfunction isUnder(relPath: string, dir: string): string | null {\n const base = segments(dir)\n const parts = segments(relPath)\n if (parts.length <= base.length) return null\n for (let i = 0; i < base.length; i += 1) {\n if (parts[i] !== base[i]) return null\n }\n return parts.slice(base.length).join('/')\n}\n\n/**\n * Traduz um caminho (relativo ao projectRoot) nos eventos que ele implica.\n *\n * Um `.md` de task gera **dois** eventos: o conteúdo em si e a árvore — porque o\n * frontmatter carrega título e status, que aparecem na sidebar. Arquivos que não\n * interessam (`.DS_Store`, temporários de editor, qualquer coisa fora de\n * `.specs/`) devolvem lista vazia.\n */\nexport function classifyPath(relPath: string, dirs: ClassifyDirs): SpecsChangeEvent[] {\n const normalized = relPath.split(path.sep).join('/')\n const name = normalized.split('/').pop() ?? ''\n if (name.startsWith('.') || name.endsWith('~')) return []\n\n if (normalized === '.specs/config.json') return [{ type: 'config' }]\n\n const inFeatures = isUnder(relPath, dirs.featuresDir)\n if (inFeatures !== null) {\n const parts = inFeatures.split('/')\n if (parts.length === 1 && parts[0] === 'meta.json') return [{ type: 'tree' }]\n const [feature, file] = parts\n if (!feature || !file || parts.length !== 2) return [{ type: 'tree' }]\n if (file === 'meta.json') return [{ type: 'tree' }]\n if (file.endsWith('.md')) {\n const task = file.slice(0, -3)\n return [{ type: 'content', feature, task }, { type: 'tree' }]\n }\n return []\n }\n\n const inDiscoveries = isUnder(relPath, dirs.discoveriesDir)\n if (inDiscoveries !== null) {\n const parts = inDiscoveries.split('/')\n if (parts.length !== 1) return []\n const file = parts[0] ?? ''\n if (file === 'meta.json') return [{ type: 'tree' }]\n if (file.endsWith('.md')) {\n return [{ type: 'discovery', slug: file.slice(0, -3) }, { type: 'tree' }]\n }\n return []\n }\n\n const inDrawings = isUnder(relPath, dirs.drawingsDir)\n if (inDrawings !== null) {\n const parts = inDrawings.split('/')\n if (parts.length !== 1) return []\n const file = parts[0] ?? ''\n if (file === 'meta.json') return [{ type: 'tree' }]\n if (file.endsWith('.md')) {\n return [{ type: 'drawing', slug: file.slice(0, -3) }, { type: 'tree' }]\n }\n return []\n }\n\n return []\n}\n\n/** Chave estável de um evento, para deduplicar dentro da janela de debounce. */\nexport function eventKey(event: SpecsChangeEvent): string {\n switch (event.type) {\n case 'content':\n return `content:${event.feature}/${event.task}`\n case 'discovery':\n return `discovery:${event.slug}`\n case 'drawing':\n return `drawing:${event.slug}`\n default:\n return event.type\n }\n}\n\nexport type SpecsWatcher = {\n subscribe: (listener: (events: SpecsChangeEvent[]) => void) => () => void\n /** false quando o SO não suporta watch recursivo — a UI cai para polling. */\n readonly watching: boolean\n close: () => void\n}\n\nexport type WatcherOptions = ClassifyDirs & {\n projectRoot: string\n /** Arquivos avulsos fora do projeto (ex.: histórico de uso do Claude). */\n extraFiles?: Array<{ file: string; event: SpecsChangeEvent }>\n debounceMs?: number\n}\n\n/** Intervalo entre tentativas de (re)armar o watch de um arquivo avulso. */\nconst REARM_RETRY_MS = 5_000\n\n/**\n * Observa um arquivo único de forma resiliente a saves atômicos.\n *\n * `fs.watch` prende o inode do arquivo. Quando o processo dono grava num `.tmp`\n * e renomeia por cima — o padrão de save atômico — o inode muda: o evento do\n * rename ainda chega, mas todas as escritas seguintes passam despercebidas. Por\n * isso re-armamos o watch depois de cada evento. Se o arquivo não existir (ainda\n * ou durante a janela do rename), tentamos de novo periodicamente.\n *\n * Devolve a função que encerra o watch.\n */\nexport function watchFileRearming(file: string, onChange: () => void): () => void {\n let current: FSWatcher | null = null\n let retry: NodeJS.Timeout | null = null\n let stopped = false\n\n function scheduleRetry() {\n if (stopped || retry) return\n retry = setTimeout(() => {\n retry = null\n arm()\n }, REARM_RETRY_MS)\n retry.unref?.()\n }\n\n function arm() {\n if (stopped) return\n try {\n current = watch(file, { persistent: false }, () => {\n onChange()\n // Re-arma no *caminho*: se foi um rename, o watch atual está morto.\n try {\n current?.close()\n } catch {}\n current = null\n arm()\n })\n } catch {\n current = null\n scheduleRetry()\n }\n }\n\n arm()\n\n return () => {\n stopped = true\n if (retry) clearTimeout(retry)\n try {\n current?.close()\n } catch {}\n current = null\n }\n}\n\n/**\n * Observa `.specs/` (e arquivos avulsos) e emite lotes de eventos com debounce.\n *\n * Um agent editando um `.md` dispara vários eventos de `fs.watch` em sequência\n * (write, rename do arquivo temporário, chmod); o debounce junta tudo num lote\n * só, deduplicado, para a UI invalidar cada query uma única vez.\n */\nexport function createSpecsWatcher(opts: WatcherOptions): SpecsWatcher {\n const {\n projectRoot,\n featuresDir,\n discoveriesDir,\n drawingsDir,\n extraFiles = [],\n debounceMs = 150,\n } = opts\n const listeners = new Set<(events: SpecsChangeEvent[]) => void>()\n const watchers: FSWatcher[] = []\n const fileWatchers: Array<() => void> = []\n const pending = new Map<string, SpecsChangeEvent>()\n let timer: NodeJS.Timeout | null = null\n let watching = false\n\n function flush() {\n timer = null\n if (pending.size === 0) return\n const batch = [...pending.values()]\n pending.clear()\n for (const listener of listeners) listener(batch)\n }\n\n function queue(events: SpecsChangeEvent[]) {\n if (events.length === 0) return\n for (const event of events) pending.set(eventKey(event), event)\n if (timer) clearTimeout(timer)\n timer = setTimeout(flush, debounceMs)\n }\n\n const specsRoot = path.join(projectRoot, '.specs')\n try {\n // `recursive` cobre macOS e Windows nativamente e Linux a partir do Node 20.\n // Se o SO não suportar, o catch abaixo deixa `watching` em false e a UI faz\n // polling — nunca fica sem atualizar.\n watchers.push(\n watch(specsRoot, { recursive: true, persistent: false }, (_event, filename) => {\n if (!filename) return\n const rel = path.join('.specs', filename.toString())\n queue(classifyPath(rel, { featuresDir, discoveriesDir, drawingsDir }))\n }),\n )\n watching = true\n } catch {\n watching = false\n }\n\n // Arquivos avulsos precisam de um watch que se re-arma. `fs.watch` prende o\n // inode, e um save atômico (grava num .tmp e renomeia por cima) troca o inode:\n // o evento do rename chega, mas todas as escritas seguintes ficam invisíveis.\n // O arquivo também pode ainda não existir quando o servidor sobe.\n for (const { file, event } of extraFiles) {\n fileWatchers.push(watchFileRearming(file, () => queue([event])))\n }\n\n return {\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n get watching() {\n return watching\n },\n close() {\n if (timer) clearTimeout(timer)\n for (const w of watchers) {\n try {\n w.close()\n } catch {}\n }\n for (const stop of fileWatchers) stop()\n listeners.clear()\n },\n }\n}\n","import { constants } from 'node:fs'\nimport { access, readFile, rename, stat, writeFile, mkdir } from 'node:fs/promises'\nimport path from 'node:path'\n\nexport const SLUG_REGEX = /^[a-z0-9][a-z0-9-]*$/\n\nexport function isValidSlug(slug: unknown): slug is string {\n return typeof slug === 'string' && SLUG_REGEX.test(slug)\n}\n\nexport function assertInsideProject(absPath: string, projectRoot: string): void {\n const rel = path.relative(projectRoot, absPath)\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw new Error(`Path ${absPath} fora do projectRoot ${projectRoot}.`)\n }\n}\n\nexport async function fileExists(p: string): Promise<boolean> {\n try {\n await access(p, constants.F_OK)\n const s = await stat(p)\n return s.isFile()\n } catch {\n return false\n }\n}\n\nexport async function dirExists(p: string): Promise<boolean> {\n try {\n const s = await stat(p)\n return s.isDirectory()\n } catch {\n return false\n }\n}\n\nexport async function readText(p: string): Promise<string> {\n return readFile(p, 'utf8')\n}\n\nexport function detectEOL(content: string): '\\n' | '\\r\\n' {\n // Amostra até 4KB para detecção\n const sample = content.length > 4096 ? content.slice(0, 4096) : content\n return sample.includes('\\r\\n') ? '\\r\\n' : '\\n'\n}\n\n/**\n * Escreve `finalPath` de forma atômica: grava em arquivo temporário na mesma\n * pasta e faz rename.\n */\nexport async function atomicWrite(finalPath: string, content: string): Promise<void> {\n const dir = path.dirname(finalPath)\n await mkdir(dir, { recursive: true })\n const tmp = `${finalPath}.tmp-${process.pid}-${Date.now()}`\n await writeFile(tmp, content, 'utf8')\n await rename(tmp, finalPath)\n}\n","import path from 'node:path'\nimport { readFile } from 'node:fs/promises'\nimport type {\n DiscoveryNode,\n DrawingNode,\n FeatureNode,\n Status,\n TaskNode,\n TreeResponse,\n} from './types.js'\nimport { dirExists, fileExists, readText } from './fs-utils.js'\nimport {\n extractDiscoveryFrontmatterFields,\n extractDrawingFrontmatterFields,\n extractFrontmatterFields,\n parseFrontmatter,\n} from './frontmatter.js'\n\ntype FeatureMetaRaw = {\n title?: unknown\n description?: unknown\n icon?: unknown\n pages?: unknown\n}\n\ntype RootMetaRaw = {\n title?: unknown\n pages?: unknown\n}\n\nfunction aggregateStatus(children: Status[]): Status {\n if (children.length === 0) return 'pending'\n if (children.some((s) => s === 'blocked')) return 'blocked'\n if (children.every((s) => s === 'completed')) return 'completed'\n if (children.some((s) => s === 'in-progress' || s === 'completed')) return 'in-progress'\n return 'pending'\n}\n\nexport async function buildTree(\n projectRoot: string,\n featuresDir: string,\n discoveriesDir: string,\n drawingsDir: string,\n): Promise<TreeResponse> {\n const featuresAbs = path.join(projectRoot, featuresDir)\n const rootMetaPath = path.join(featuresAbs, 'meta.json')\n if (!(await fileExists(rootMetaPath))) {\n throw new Error('no_features_dir')\n }\n\n const rootRaw = await readFile(rootMetaPath, 'utf8')\n const rootMeta = JSON.parse(rootRaw) as RootMetaRaw\n const rootPages = Array.isArray(rootMeta.pages) ? (rootMeta.pages as unknown[]) : []\n\n const features: FeatureNode[] = []\n\n for (const slugUnknown of rootPages) {\n if (typeof slugUnknown !== 'string') continue\n const slug = slugUnknown\n const featureDir = path.join(featuresAbs, slug)\n const featureMetaPath = path.join(featureDir, 'meta.json')\n\n if (!(await dirExists(featureDir)) || !(await fileExists(featureMetaPath))) {\n console.warn(\n `[tree] feature \"${slug}\" listada em ${featuresDir}/meta.json mas sem pasta/meta — ignorando conteúdo.`,\n )\n features.push({\n slug,\n title: slug,\n status: 'pending',\n tasks: [],\n })\n continue\n }\n\n let featureMeta: FeatureMetaRaw\n try {\n featureMeta = JSON.parse(await readText(featureMetaPath)) as FeatureMetaRaw\n } catch (err) {\n console.warn(`[tree] meta.json inválido em ${featureMetaPath}: ${(err as Error).message}`)\n featureMeta = {}\n }\n\n const title = typeof featureMeta.title === 'string' ? featureMeta.title : slug\n const description =\n typeof featureMeta.description === 'string' ? featureMeta.description : undefined\n const icon = typeof featureMeta.icon === 'string' ? featureMeta.icon : undefined\n const pages = Array.isArray(featureMeta.pages) ? (featureMeta.pages as unknown[]) : []\n\n const tasks: TaskNode[] = []\n for (const pageUnknown of pages) {\n if (typeof pageUnknown !== 'string') continue\n const pageSlug = pageUnknown\n const taskFile = path.join(featureDir, `${pageSlug}.md`)\n if (!(await fileExists(taskFile))) {\n console.warn(\n `[tree] task \"${pageSlug}\" listada em ${slug}/meta.json mas sem arquivo — omitindo.`,\n )\n continue\n }\n let raw: string\n try {\n raw = await readText(taskFile)\n } catch {\n continue\n }\n const parsed = parseFrontmatter(raw)\n const {\n title: taskTitle,\n description: taskDescription,\n status,\n } = extractFrontmatterFields(parsed.data)\n tasks.push({\n slug: pageSlug,\n title: taskTitle ?? pageSlug,\n description: taskDescription,\n status,\n file: path.relative(projectRoot, taskFile),\n })\n }\n\n features.push({\n slug,\n title,\n description,\n icon,\n status: aggregateStatus(tasks.map((t) => t.status)),\n tasks,\n })\n }\n\n const discoveries = await buildDiscoveries(projectRoot, discoveriesDir)\n const drawings = await buildDrawings(projectRoot, drawingsDir)\n\n return { features, discoveries, drawings }\n}\n\n/**\n * Lê uma seção \"plana\" — uma pasta de `.md` sem subpastas, ordenada pelo `pages`\n * do `meta.json`. Discoveries e desenhos têm exatamente essa forma; só mudam os\n * campos que cada um extrai do frontmatter.\n */\nasync function buildFlatSection<T>(\n projectRoot: string,\n dir: string,\n kind: string,\n toNode: (slug: string, data: Record<string, unknown>, file: string) => T,\n): Promise<T[]> {\n const abs = path.join(projectRoot, dir)\n const metaPath = path.join(abs, 'meta.json')\n if (!(await dirExists(abs)) || !(await fileExists(metaPath))) {\n return []\n }\n\n let meta: RootMetaRaw\n try {\n meta = JSON.parse(await readText(metaPath)) as RootMetaRaw\n } catch (err) {\n console.warn(`[tree] meta.json inválido em ${metaPath}: ${(err as Error).message}`)\n return []\n }\n\n const pages = Array.isArray(meta.pages) ? (meta.pages as unknown[]) : []\n const nodes: T[] = []\n for (const pageUnknown of pages) {\n if (typeof pageUnknown !== 'string') continue\n const pageSlug = pageUnknown\n const file = path.join(abs, `${pageSlug}.md`)\n if (!(await fileExists(file))) {\n console.warn(\n `[tree] ${kind} \"${pageSlug}\" listada em ${dir}/meta.json mas sem arquivo — omitindo.`,\n )\n continue\n }\n let raw: string\n try {\n raw = await readText(file)\n } catch {\n continue\n }\n const parsed = parseFrontmatter(raw)\n nodes.push(toNode(pageSlug, parsed.data, path.relative(projectRoot, file)))\n }\n return nodes\n}\n\nexport async function buildDiscoveries(\n projectRoot: string,\n discoveriesDir: string,\n): Promise<DiscoveryNode[]> {\n return buildFlatSection(projectRoot, discoveriesDir, 'discovery', (slug, data, file) => {\n const { title, type, date } = extractDiscoveryFrontmatterFields(data)\n return { slug, title: title ?? slug, type, date, file }\n })\n}\n\nexport async function buildDrawings(\n projectRoot: string,\n drawingsDir: string,\n): Promise<DrawingNode[]> {\n return buildFlatSection(projectRoot, drawingsDir, 'desenho', (slug, data, file) => {\n const { title, type, date } = extractDrawingFrontmatterFields(data)\n return { slug, title: title ?? slug, type, date, file }\n })\n}\n\nexport { aggregateStatus }\n","import matter from 'gray-matter'\nimport type { DiscoveryType, DrawingType, Status } from './types.js'\nimport { detectEOL } from './fs-utils.js'\n\nconst VALID_STATUS: readonly Status[] = ['pending', 'in-progress', 'completed', 'blocked']\n\nexport function isValidStatus(s: unknown): s is Status {\n return typeof s === 'string' && (VALID_STATUS as readonly string[]).includes(s)\n}\n\nconst VALID_DISCOVERY_TYPE: readonly DiscoveryType[] = ['rfc', 'spike', 'adr', 'note']\n\nexport function isValidDiscoveryType(s: unknown): s is DiscoveryType {\n return typeof s === 'string' && (VALID_DISCOVERY_TYPE as readonly string[]).includes(s)\n}\n\nconst VALID_DRAWING_TYPE: readonly DrawingType[] = [\n 'architecture',\n 'flow',\n 'sequence',\n 'data',\n 'state',\n]\n\nexport function isValidDrawingType(s: unknown): s is DrawingType {\n return typeof s === 'string' && (VALID_DRAWING_TYPE as readonly string[]).includes(s)\n}\n\n/**\n * Normaliza a data do frontmatter. YAML sem aspas (`date: 2026-09-01`) chega\n * aqui como `Date`, não como string — sem esta conversão o campo some da\n * resposta e o badge de data nunca aparece.\n */\nexport function toIsoDate(value: unknown): string | undefined {\n if (typeof value === 'string') return value\n if (value instanceof Date && !Number.isNaN(value.getTime())) {\n return value.toISOString().slice(0, 10)\n }\n return undefined\n}\n\nexport type ParsedFrontmatter = {\n data: Record<string, unknown>\n body: string\n}\n\nexport function parseFrontmatter(raw: string): ParsedFrontmatter {\n const parsed = matter(raw)\n return { data: parsed.data as Record<string, unknown>, body: parsed.content }\n}\n\n/**\n * Reescreve apenas a linha `status:` dentro do bloco frontmatter YAML, preservando\n * todo o resto byte a byte (ordem de chaves, comentários, aspas, EOL).\n *\n * Regras:\n * - Se o arquivo não tem frontmatter (`---\\n...\\n---`), retorna o conteúdo inalterado.\n * - Se o bloco YAML tem linha `status: xxx`, substitui pelo novo valor.\n * - Se não tem, insere `status: <value>` antes do `---` de fechamento.\n * - EOL original é preservado (LF ou CRLF).\n */\nexport function patchStatusInFrontmatter(raw: string, newStatus: Status): string {\n const eol = detectEOL(raw)\n const leading = raw.slice(0, 4)\n if (!leading.startsWith('---')) return raw\n\n // encontra o bloco frontmatter\n // separator: --- + EOL no início; --- + EOL no final do bloco\n const startIdx = raw.indexOf(`---${eol}`)\n if (startIdx !== 0) return raw\n\n const afterStart = raw.slice(3 + eol.length)\n const endIdx = afterStart.indexOf(`${eol}---`)\n if (endIdx < 0) return raw\n\n const yamlBlock = afterStart.slice(0, endIdx)\n const rest = afterStart.slice(endIdx) // inclui EOL + '---'\n\n const statusLineRegex = /^status:[ \\t]*.*$/m\n let newYaml: string\n if (statusLineRegex.test(yamlBlock)) {\n newYaml = yamlBlock.replace(statusLineRegex, `status: ${newStatus}`)\n } else {\n // insere ao final do bloco YAML (antes do EOL de fechamento)\n const trimmedEnd = yamlBlock.endsWith(eol) ? yamlBlock : `${yamlBlock}${eol}`\n newYaml = `${trimmedEnd}status: ${newStatus}`\n }\n\n return `---${eol}${newYaml}${rest}`\n}\n\nexport function extractFrontmatterFields(data: Record<string, unknown>): {\n title?: string\n description?: string\n status: Status\n} {\n const title = typeof data.title === 'string' ? data.title : undefined\n const description = typeof data.description === 'string' ? data.description : undefined\n const rawStatus = data.status\n const status: Status = isValidStatus(rawStatus) ? rawStatus : 'pending'\n return { title, description, status }\n}\n\nexport function extractDiscoveryFrontmatterFields(data: Record<string, unknown>): {\n title?: string\n type: DiscoveryType\n date?: string\n} {\n const title = typeof data.title === 'string' ? data.title : undefined\n const rawType = data.type\n const type: DiscoveryType = isValidDiscoveryType(rawType) ? rawType : 'note'\n const date = toIsoDate(data.date)\n return { title, type, date }\n}\n\nexport function extractDrawingFrontmatterFields(data: Record<string, unknown>): {\n title?: string\n type: DrawingType\n date?: string\n} {\n const title = typeof data.title === 'string' ? data.title : undefined\n const rawType = data.type\n // Sem `type` válido cai em `architecture`: é o desenho mais comum e um badge\n // errado é menos ruim do que um desenho invisível na lista.\n const type: DrawingType = isValidDrawingType(rawType) ? rawType : 'architecture'\n const date = toIsoDate(data.date)\n return { title, type, date }\n}\n","import GithubSlugger from 'github-slugger'\nimport type { Heading } from './types.js'\n\n/**\n * Extrai headings markdown do body. Usa regex por linha para respeitar code fences\n * (linhas dentro de ``` ... ``` são ignoradas).\n */\nexport function extractHeadings(body: string): Heading[] {\n const slugger = new GithubSlugger()\n const lines = body.split(/\\r?\\n/)\n const out: Heading[] = []\n let inFence = false\n for (const line of lines) {\n const trimmed = line.trimStart()\n if (trimmed.startsWith('```') || trimmed.startsWith('~~~')) {\n inFence = !inFence\n continue\n }\n if (inFence) continue\n const match = /^(#{1,6})\\s+(.+)$/.exec(line)\n if (!match) continue\n const level = match[1]!.length\n // remove trailing hashes (ATX closing) e espaços\n const text = match[2]!.replace(/\\s+#+\\s*$/, '').trim()\n const id = slugger.slug(text)\n out.push({ id, text, level })\n }\n return out\n}\n","import { spawn } from 'node:child_process'\nimport path from 'node:path'\nimport { readFile } from 'node:fs/promises'\nimport type {\n AgentCli,\n AgentEffort,\n AgentModel,\n AgentScopeKey,\n SpecsConfig,\n TerminalKind,\n} from './types.js'\n\ntype RunAgentInput = {\n scope: AgentScopeKey\n feature: string\n task?: string\n cli?: AgentCli\n model?: string\n effort?: AgentEffort\n}\n\n/**\n * Resolve o template de comando para a CLI escolhida. Cai no `commands[cli]`,\n * depois no comando padrão da config, garantindo retrocompat com configs antigas\n * que só tinham `agent.command`.\n */\nexport function resolveCommand(config: SpecsConfig, cli?: AgentCli): string {\n const key = cli && config.agent.commands?.[cli] ? cli : config.agent.cli\n return config.agent.commands?.[key] ?? config.agent.command\n}\n\n/**\n * Injeta a flag de modelo no template. Se houver `{model}`, substitui (por\n * `--model <id>` ou vazio). Sem placeholder, insere a flag logo após o binário.\n * `quote` controla o escaping (identidade p/ argv inline, shellQuote p/ shell).\n */\nexport function injectModel(\n template: string,\n model: string | undefined,\n quote: (s: string) => string,\n): string {\n const flag = model ? `--model ${quote(model)}` : ''\n if (template.includes('{model}')) return template.replaceAll('{model}', flag)\n if (!flag) return template\n return template.replace(/^(\\s*\\S+)/, `$1 ${flag}`)\n}\n\n/**\n * Como cada CLI recebe o nível de esforço. O Claude Code tem a flag `--effort`;\n * o cursor-agent expõe o esforço como parâmetro entre colchetes do próprio\n * modelo (`claude-opus-4-8[effort=high]`), então lá ele só se aplica quando há\n * um modelo escolhido.\n */\nconst EFFORT_MODE: Record<string, 'flag' | 'model-param'> = {\n claude: 'flag',\n cursor: 'model-param',\n}\n\nfunction effortMode(cli: string | undefined): 'flag' | 'model-param' {\n return EFFORT_MODE[cli ?? 'claude'] ?? 'flag'\n}\n\n/**\n * Acrescenta `[effort=<nível>]` ao id do modelo (sintaxe do cursor-agent),\n * preservando os parâmetros que já estiverem entre colchetes.\n */\nexport function withEffortParam(model: string, effort: AgentEffort): string {\n if (/\\[.*effort=/.test(model)) return model\n const match = /^([^[]+)\\[(.+)\\]$/.exec(model)\n if (match) return `${match[1]}[${match[2]},effort=${effort}]`\n return `${model}[effort=${effort}]`\n}\n\n/**\n * Injeta o nível de esforço no template. Com `{effort}`, substitui; sem o\n * placeholder, insere a flag logo após o binário — mesmo contrato do modelo,\n * para não quebrar configs antigas.\n */\nexport function injectEffort(\n template: string,\n effort: AgentEffort | undefined,\n quote: (s: string) => string,\n): string {\n const flag = effort ? `--effort ${quote(effort)}` : ''\n // Sem esforço, o placeholder leva junto o espaço que o precede — senão o\n // comando fica com espaço sobrando no meio.\n if (template.includes('{effort}')) {\n return flag ? template.replaceAll('{effort}', flag) : template.replace(/ ?\\{effort\\}/g, '')\n }\n if (!flag) return template\n return template.replace(/^(\\s*\\S+)/, `$1 ${flag}`)\n}\n\n/**\n * Resolve modelo + esforço para a CLI escolhida e devolve o comando pronto.\n */\nexport function buildCommand(\n config: SpecsConfig,\n cli: AgentCli | undefined,\n model: string | undefined,\n effort: AgentEffort | undefined,\n quote: (s: string) => string,\n): string {\n const mode = effortMode(cli)\n const effectiveModel =\n mode === 'model-param' && model && effort ? withEffortParam(model, effort) : model\n const withModel = injectModel(resolveCommand(config, cli), effectiveModel, quote)\n return mode === 'flag' ? injectEffort(withModel, effort, quote) : withModel\n}\n\nexport type RunAgentResult =\n | { ok: true }\n | { ok: false; status: 501; error: 'terminal_disabled'; hint: string }\n | { ok: false; status: 500; error: 'spawn_failed'; detail: string }\n\nexport type InlineCommand = {\n file: string\n args: string[]\n cwd: string\n label: string\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`\n}\n\nexport async function readFeatureTitle(metaPath: string, fallback: string): Promise<string> {\n try {\n const raw = await readFile(metaPath, 'utf8')\n const parsed = JSON.parse(raw) as { title?: unknown }\n if (typeof parsed.title === 'string' && parsed.title.trim().length > 0) {\n return parsed.title.trim()\n }\n } catch {}\n return fallback\n}\n\nexport function resolvePrompt(\n template: string,\n ctx: { feature: string; task?: string; featureTitle: string; featurePath: string },\n): string {\n return template\n .replaceAll('{feature}', ctx.feature)\n .replaceAll('{task}', ctx.task ?? '')\n .replaceAll('{featureTitle}', ctx.featureTitle)\n .replaceAll('{featurePath}', ctx.featurePath)\n}\n\nfunction buildTerminalCommand(\n terminal: TerminalKind,\n cwd: string,\n shellCommand: string,\n): { file: string; args: string[] } | null {\n switch (terminal) {\n case 'osascript': {\n const quotedCwd = shellQuote(cwd)\n const fullShell = `cd ${quotedCwd} && ${shellCommand}`\n const appleScript = [\n 'tell application \"Terminal\"',\n ' activate',\n ` do script ${JSON.stringify(fullShell)}`,\n 'end tell',\n ].join('\\n')\n return { file: 'osascript', args: ['-e', appleScript] }\n }\n case 'gnome-terminal':\n return {\n file: 'gnome-terminal',\n args: ['--', 'bash', '-c', `cd ${shellQuote(cwd)} && ${shellCommand}; exec bash`],\n }\n case 'kitty':\n return {\n file: 'kitty',\n args: ['--hold', 'bash', '-c', `cd ${shellQuote(cwd)} && ${shellCommand}`],\n }\n case 'wezterm':\n return {\n file: 'wezterm',\n args: ['start', '--cwd', cwd, '--', 'bash', '-c', shellCommand],\n }\n case 'none':\n return null\n }\n}\n\nfunction spawnInTerminal(\n config: SpecsConfig,\n projectRoot: string,\n shellCommand: string,\n): RunAgentResult {\n const terminal = config.agent.openTerminal\n if (terminal === 'none') {\n return {\n ok: false,\n status: 501,\n error: 'terminal_disabled',\n hint: 'Ajuste agent.openTerminal no .specs/config.json',\n }\n }\n\n const cwd = path.resolve(projectRoot, config.agent.cwd ?? '.')\n const termCmd = buildTerminalCommand(terminal, cwd, shellCommand)\n if (!termCmd) {\n return {\n ok: false,\n status: 501,\n error: 'terminal_disabled',\n hint: 'openTerminal não reconhecido.',\n }\n }\n\n try {\n const child = spawn(termCmd.file, termCmd.args, {\n detached: true,\n stdio: 'ignore',\n })\n child.on('error', (err) => {\n console.error(`[run-agent] spawn error: ${err.message}`)\n })\n child.unref()\n return { ok: true }\n } catch (err) {\n return {\n ok: false,\n status: 500,\n error: 'spawn_failed',\n detail: (err as Error).message,\n }\n }\n}\n\n/**\n * Extrai comando + args puros para execução inline (PTY).\n * Parseia o `agent.command` configurado substituindo \"feature-runner\" pelo agentName,\n * e injetando o prompt resolvido como último arg. Retorna null se o template\n * não puder ser parseado para o modo inline.\n */\nfunction parseInlineCommand(\n baseCommand: string,\n agentName: string,\n prompt: string,\n): { file: string; args: string[] } | null {\n // Template esperado: `claude --agent feature-runner \"{prompt}\"` (ou similar)\n // Estratégia: dividir nos tokens, trocar \"feature-runner\" por agentName, e\n // substituir a ocorrência de \"{prompt}\" (ou `\"{prompt}\"`) por prompt cru.\n const tokens = baseCommand.match(/\"[^\"]*\"|'[^']*'|\\S+/g)\n if (!tokens || tokens.length === 0) return null\n const cleaned = tokens.map((t) => {\n const unquoted =\n (t.startsWith('\"') && t.endsWith('\"')) || (t.startsWith(\"'\") && t.endsWith(\"'\"))\n ? t.slice(1, -1)\n : t\n // Troca o agent alvo. Funciona tanto quando `feature-runner` é um token\n // isolado (`claude --agent feature-runner ...`) quanto quando está embutido\n // numa frase dentro de aspas (`cursor-agent \"Use the feature-runner ...\"`).\n return unquoted.includes('feature-runner')\n ? unquoted.replaceAll('feature-runner', agentName)\n : unquoted\n })\n const promptIdx = cleaned.findIndex((t) => t.includes('{prompt}'))\n if (promptIdx === -1) {\n // Fallback: acrescenta o prompt como último argumento\n cleaned.push(prompt)\n } else {\n cleaned[promptIdx] = (cleaned[promptIdx] ?? '').replaceAll('{prompt}', prompt)\n }\n const [file, ...args] = cleaned\n if (!file) return null\n return { file, args }\n}\n\n/**\n * Monta o comando inline (para PTY) e o label humano de um agent de feature/task.\n */\nexport async function buildAgentInlineCommand(\n input: RunAgentInput,\n config: SpecsConfig,\n projectRoot: string,\n): Promise<InlineCommand | null> {\n const { scope, feature, task, cli, model, effort } = input\n const featuresDir = config.featuresDir ?? 'features'\n const featureMetaPath = path.join(projectRoot, featuresDir, feature, 'meta.json')\n const featureTitle = await readFeatureTitle(featureMetaPath, feature)\n const promptTemplate = config.agent.scopes[scope] ?? ''\n const prompt = resolvePrompt(promptTemplate, {\n feature,\n task,\n featureTitle,\n featurePath: `${featuresDir}/${feature}/`,\n })\n const command = buildCommand(config, cli, model, effort, (s) => s)\n const parsed = parseInlineCommand(command, 'feature-runner', prompt)\n if (!parsed) return null\n const cwd = path.resolve(projectRoot, config.agent.cwd ?? '.')\n const label =\n scope === 'task' && task ? `${featureTitle} — ${task}` : `${featureTitle} (${scope})`\n return { file: parsed.file, args: parsed.args, cwd, label }\n}\n\nexport function buildNamedAgentInlineCommand(\n agentName: string,\n userPrompt: string,\n config: SpecsConfig,\n projectRoot: string,\n label: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): InlineCommand | null {\n const command = buildCommand(config, cli, model, effort, (s) => s)\n const parsed = parseInlineCommand(command, agentName, userPrompt)\n if (!parsed) return null\n const cwd = path.resolve(projectRoot, config.agent.cwd ?? '.')\n return { file: parsed.file, args: parsed.args, cwd, label }\n}\n\n/**\n * Remove a seleção de subagent do template. Jobs de design não rodam sob o\n * `feature-runner`: no Claude Code o pedido é o slash command `/design`, e\n * `--agent` fixaria um subagent que não tem esse comando.\n */\nexport function stripAgentFlag(template: string): string {\n return template\n .replace(/\\s--agent(?:=|\\s+)[^\\s\"']+/g, '')\n .replace(/Use the feature-runner subagent\\.\\s*/g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/** Monta o comando inline (PTY) de um job de design. */\nexport function buildDesignInlineCommand(\n prompt: string,\n config: SpecsConfig,\n projectRoot: string,\n label: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): InlineCommand | null {\n const command = stripAgentFlag(buildCommand(config, cli, model, effort, (s) => s))\n const parsed = parseInlineCommand(command, 'design', prompt)\n if (!parsed) return null\n const cwd = path.resolve(projectRoot, config.agent.cwd ?? '.')\n return { file: parsed.file, args: parsed.args, cwd, label }\n}\n\n/** Dispara um job de design em terminal externo. */\nexport function runDesign(\n prompt: string,\n config: SpecsConfig,\n projectRoot: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): RunAgentResult {\n const command = stripAgentFlag(buildCommand(config, cli, model, effort, shellQuote))\n const shellCommand = command.replaceAll('{prompt}', shellQuote(prompt))\n return spawnInTerminal(config, projectRoot, shellCommand)\n}\n\nexport async function runAgent(\n input: RunAgentInput,\n config: SpecsConfig,\n projectRoot: string,\n): Promise<RunAgentResult> {\n const { scope, feature, task, cli, model, effort } = input\n\n const featuresDir = config.featuresDir ?? 'features'\n const featureMetaPath = path.join(projectRoot, featuresDir, feature, 'meta.json')\n const featureTitle = await readFeatureTitle(featureMetaPath, feature)\n\n const scopeKey: AgentScopeKey = scope\n const promptTemplate = config.agent.scopes[scopeKey] ?? ''\n const prompt = resolvePrompt(promptTemplate, {\n feature,\n task,\n featureTitle,\n featurePath: `${featuresDir}/${feature}/`,\n })\n\n const commandTemplate = buildCommand(config, cli, model, effort, shellQuote)\n const shellCommand = commandTemplate.replaceAll('{prompt}', shellQuote(prompt))\n\n return spawnInTerminal(config, projectRoot, shellCommand)\n}\n\nexport function runRefinement(\n userPrompt: string,\n config: SpecsConfig,\n projectRoot: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): RunAgentResult {\n return runNamedAgent('refinement', userPrompt, config, projectRoot, cli, model, effort)\n}\n\nexport function runDrawingAgent(\n userPrompt: string,\n config: SpecsConfig,\n projectRoot: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): RunAgentResult {\n return runNamedAgent('drawing-agent', userPrompt, config, projectRoot, cli, model, effort)\n}\n\nexport function runRefinementRunner(\n userPrompt: string,\n config: SpecsConfig,\n projectRoot: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): RunAgentResult {\n return runNamedAgent('refinement-runner', userPrompt, config, projectRoot, cli, model, effort)\n}\n\nexport function runDiscoveryAgent(\n userPrompt: string,\n config: SpecsConfig,\n projectRoot: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): RunAgentResult {\n return runNamedAgent('discovery-agent', userPrompt, config, projectRoot, cli, model, effort)\n}\n\nfunction runNamedAgent(\n agentName: string,\n userPrompt: string,\n config: SpecsConfig,\n projectRoot: string,\n cli?: AgentCli,\n model?: string,\n effort?: AgentEffort,\n): RunAgentResult {\n const baseCommand = buildCommand(config, cli, model, effort, shellQuote)\n const command = baseCommand.includes('feature-runner')\n ? baseCommand.replaceAll('feature-runner', agentName)\n : `claude --agent ${agentName} \"{prompt}\"`\n const shellCommand = command.replaceAll('{prompt}', shellQuote(userPrompt))\n return spawnInTerminal(config, projectRoot, shellCommand)\n}\n\nconst ANSI_RE = /\\x1b\\[[0-9;]*m/g\nconst MODEL_LINE_RE = /^([A-Za-z0-9][A-Za-z0-9._\\-/:]*)\\s+-\\s+(.+)$/\nconst MODEL_BARE_RE = /^[A-Za-z0-9][A-Za-z0-9._\\-/:]*$/\n\n/**\n * Parseia a saída de um comando de listagem de modelos. Aceita linhas no\n * formato `id - Nome de Exibição` (cursor-agent --list-models) ou só o id.\n * Linhas de cabeçalho/ruído (com espaços e sem ` - `) são ignoradas.\n */\nexport function parseModelsOutput(output: string): AgentModel[] {\n const seen = new Set<string>()\n const models: AgentModel[] = []\n for (const raw of output.replace(ANSI_RE, '').split('\\n')) {\n const line = raw.trim().replace(/^[-*•]\\s+/, '')\n if (!line) continue\n const matched = line.match(MODEL_LINE_RE)\n let id: string | undefined\n let label: string | undefined\n if (matched) {\n id = matched[1]\n label = (matched[2] ?? '').trim()\n } else if (MODEL_BARE_RE.test(line)) {\n id = line\n label = line\n }\n if (!id || seen.has(id)) continue\n seen.add(id)\n models.push({ id, label: label ?? id })\n if (models.length >= 200) break\n }\n return models\n}\n\nfunction runForStdout(\n file: string,\n args: string[],\n cwd: string,\n timeoutMs: number,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n let stdout = ''\n let stderr = ''\n const child = spawn(file, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] })\n const timer = setTimeout(() => {\n child.kill('SIGKILL')\n reject(new Error('timeout'))\n }, timeoutMs)\n child.stdout.on('data', (d) => {\n stdout += d.toString()\n })\n child.stderr.on('data', (d) => {\n stderr += d.toString()\n })\n child.on('error', (err) => {\n clearTimeout(timer)\n reject(err)\n })\n child.on('close', (code) => {\n clearTimeout(timer)\n if (code === 0) resolve(stdout)\n else reject(new Error(stderr.trim() || `exit ${code}`))\n })\n })\n}\n\nexport type ListModelsResult = {\n models: AgentModel[]\n source: 'dynamic' | 'static' | 'none'\n error?: string\n}\n\n/**\n * Lista os modelos disponíveis de uma CLI. Tenta o comando dinâmico em\n * `agent.modelsCommand[cli]`; em falha (ou ausência), cai na lista estática\n * `agent.models[cli]`. Retorna a fonte usada para a UI sinalizar.\n */\nexport async function listAgentModels(\n config: SpecsConfig,\n projectRoot: string,\n cli: AgentCli,\n): Promise<ListModelsResult> {\n const cwd = path.resolve(projectRoot, config.agent.cwd ?? '.')\n const staticList = (config.agent.models?.[cli] ?? []).map((id) => ({ id, label: id }))\n const command = config.agent.modelsCommand?.[cli]\n\n if (command) {\n const tokens = command.match(/\"[^\"]*\"|'[^']*'|\\S+/g) ?? []\n const cleaned = tokens.map((t) =>\n (t.startsWith('\"') && t.endsWith('\"')) || (t.startsWith(\"'\") && t.endsWith(\"'\"))\n ? t.slice(1, -1)\n : t,\n )\n const [file, ...args] = cleaned\n if (file) {\n try {\n const out = await runForStdout(file, args, cwd, 20_000)\n const models = parseModelsOutput(out)\n if (models.length > 0) return { models, source: 'dynamic' }\n } catch (err) {\n if (staticList.length > 0) {\n return { models: staticList, source: 'static', error: (err as Error).message }\n }\n return { models: [], source: 'none', error: (err as Error).message }\n }\n }\n }\n\n if (staticList.length > 0) return { models: staticList, source: 'static' }\n return { models: [], source: 'none' }\n}\n","import { execFile } from 'node:child_process'\nimport path from 'node:path'\nimport { promisify } from 'node:util'\n\nconst run = promisify(execFile)\n\nconst MAX_DIFF_LINES = 1500\n\nexport type ChangeStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'untracked'\n\nexport type ChangedFile = {\n path: string\n previousPath?: string\n status: ChangeStatus\n additions: number\n deletions: number\n /** Arquivo gerado/mecânico (lock, snapshot, migration SQL) — agrupado à parte na UI. */\n generated: boolean\n binary: boolean\n}\n\nexport type FileDiff = {\n path: string\n binary: boolean\n truncated: boolean\n diff: string\n}\n\nexport type LocalCommit = {\n hash: string\n shortHash: string\n subject: string\n date: string\n files: ChangedFile[]\n additions: number\n deletions: number\n}\n\nexport type ReviewChanges = {\n branch: string\n upstream: string | null\n /** Commits locais ainda não enviados — no modo feature, um por task. */\n commits: LocalCommit[]\n files: ChangedFile[]\n totals: { files: number; additions: number; deletions: number }\n}\n\nconst GENERATED_PATTERNS = [\n /(^|\\/)pnpm-lock\\.yaml$/,\n /(^|\\/)package-lock\\.json$/,\n /(^|\\/)yarn\\.lock$/,\n /\\.snap$/,\n /(^|\\/)dist\\//,\n /(^|\\/)node_modules\\//,\n /(^|\\/)migrations?\\/.+\\.sql$/,\n]\n\nfunction isGenerated(file: string): boolean {\n return GENERATED_PATTERNS.some((re) => re.test(file))\n}\n\nfunction statusFromCode(code: string): ChangeStatus {\n if (code === '??') return 'untracked'\n const flags = code.replace(/\\s/g, '')\n if (flags.includes('R')) return 'renamed'\n if (flags.includes('D')) return 'deleted'\n if (flags.includes('A')) return 'added'\n return 'modified'\n}\n\nasync function git(cwd: string, args: string[]): Promise<string> {\n try {\n const { stdout } = await run('git', args, { cwd, maxBuffer: 64 * 1024 * 1024 })\n return stdout\n } catch (err) {\n // `git diff --no-index` sai com 1 quando há diferença: a saída ainda é válida.\n const withStdout = err as { stdout?: string; code?: number }\n if (typeof withStdout.stdout === 'string' && withStdout.stdout.length > 0) {\n return withStdout.stdout\n }\n throw err\n }\n}\n\n/** Entradas de `git status --porcelain=v1 -z`, já resolvendo os pares de rename. */\nfunction parseStatus(raw: string): Array<{ code: string; file: string; previous?: string }> {\n const parts = raw.split('\\0').filter((p) => p.length > 0)\n const out: Array<{ code: string; file: string; previous?: string }> = []\n for (let i = 0; i < parts.length; i += 1) {\n const entry = parts[i] as string\n const code = entry.slice(0, 2)\n const file = entry.slice(3)\n if (code.includes('R') || code.includes('C')) {\n const previous = parts[i + 1]\n i += 1\n out.push({ code, file, previous })\n continue\n }\n out.push({ code, file })\n }\n return out\n}\n\n/** `git diff --numstat -z`: \"add\\tdel\\0path\\0\" (renames trazem dois paths). */\nfunction parseNumstat(raw: string): Map<string, { additions: number; deletions: number }> {\n const out = new Map<string, { additions: number; deletions: number }>()\n const parts = raw.split('\\0').filter((p) => p.length > 0)\n for (let i = 0; i < parts.length; i += 1) {\n const entry = parts[i] as string\n const match = /^(\\d+|-)\\t(\\d+|-)\\t?(.*)$/.exec(entry)\n if (!match) continue\n const additions = match[1] === '-' ? 0 : Number(match[1])\n const deletions = match[2] === '-' ? 0 : Number(match[2])\n let file = match[3] ?? ''\n if (!file) {\n // rename: os dois paths vêm nas entradas seguintes (origem, destino)\n i += 1\n file = parts[i + 1] ?? parts[i] ?? ''\n i += 1\n }\n if (file) out.set(file, { additions, deletions })\n }\n return out\n}\n\nasync function countUntracked(projectRoot: string, file: string): Promise<number> {\n try {\n const { readFile } = await import('node:fs/promises')\n const content = await readFile(path.resolve(projectRoot, file), 'utf8')\n if (content === '') return 0\n return content.split('\\n').length\n } catch {\n return 0\n }\n}\n\nfunction truncate(diff: string): { diff: string; truncated: boolean } {\n const lines = diff.split('\\n')\n if (lines.length <= MAX_DIFF_LINES) return { diff, truncated: false }\n return { diff: lines.slice(0, MAX_DIFF_LINES).join('\\n'), truncated: true }\n}\n\nasync function resolveUpstream(projectRoot: string, branch: string): Promise<string | null> {\n const tracked = await git(projectRoot, [\n 'rev-parse',\n '--abbrev-ref',\n '--symbolic-full-name',\n '@{u}',\n ])\n .then((out) => out.trim())\n .catch(() => '')\n if (tracked) return tracked\n const fallback = `origin/${branch}`\n const exists = await git(projectRoot, ['rev-parse', '--verify', '--quiet', fallback])\n .then((out) => out.trim().length > 0)\n .catch(() => false)\n return exists ? fallback : null\n}\n\n/** `git show --numstat`: uma linha \"add\\tdel\\tpath\" por arquivo do commit. */\nfunction parseShowNumstat(raw: string): ChangedFile[] {\n const files: ChangedFile[] = []\n for (const line of raw.split('\\n')) {\n const match = /^(\\d+|-)\\t(\\d+|-)\\t(.+)$/.exec(line.trim())\n if (!match) continue\n const file = match[3] as string\n files.push({\n path: file,\n status: 'modified',\n additions: match[1] === '-' ? 0 : Number(match[1]),\n deletions: match[2] === '-' ? 0 : Number(match[2]),\n generated: isGenerated(file),\n binary: match[1] === '-' && match[2] === '-',\n })\n }\n return files\n}\n\nasync function collectLocalCommits(\n projectRoot: string,\n upstream: string | null,\n): Promise<LocalCommit[]> {\n if (!upstream) return []\n const log = await git(projectRoot, [\n 'log',\n '--reverse',\n '--format=%H%x1f%h%x1f%s%x1f%aI',\n `${upstream}..HEAD`,\n ]).catch(() => '')\n\n const commits: LocalCommit[] = []\n for (const line of log.split('\\n')) {\n if (!line.trim()) continue\n const [hash, shortHash, subject, date] = line.split('\\x1f')\n if (!hash) continue\n const files = parseShowNumstat(\n await git(projectRoot, ['show', '--numstat', '--format=', hash]).catch(() => ''),\n )\n commits.push({\n hash,\n shortHash: shortHash ?? hash.slice(0, 7),\n subject: subject ?? '',\n date: date ?? '',\n files,\n additions: files.reduce((sum, f) => sum + f.additions, 0),\n deletions: files.reduce((sum, f) => sum + f.deletions, 0),\n })\n }\n return commits\n}\n\nasync function diffForFile(\n projectRoot: string,\n file: string,\n status: ChangeStatus,\n): Promise<string> {\n if (status === 'untracked') {\n return git(projectRoot, ['diff', '--no-index', '--unified=3', '--', '/dev/null', file])\n }\n return git(projectRoot, ['diff', 'HEAD', '--unified=3', '--', file])\n}\n\n/**\n * Alterações do working tree (staged + não staged + untracked) contra o HEAD.\n * Só metadados e contagem — o diff de cada arquivo vem sob demanda em `fileDiff`,\n * para a lista continuar barata quando a feature inteira está em revisão.\n */\nexport async function collectChanges(projectRoot: string): Promise<ReviewChanges> {\n const branch = (await git(projectRoot, ['rev-parse', '--abbrev-ref', 'HEAD'])).trim()\n const upstream = await resolveUpstream(projectRoot, branch)\n const commits = await collectLocalCommits(projectRoot, upstream)\n const status = parseStatus(\n await git(projectRoot, ['status', '--porcelain=v1', '--untracked-files=all', '-z']),\n )\n const numstat = parseNumstat(await git(projectRoot, ['diff', '--numstat', '-z', 'HEAD']))\n\n const files: ChangedFile[] = []\n for (const entry of status) {\n const fileStatus = statusFromCode(entry.code)\n const counted = numstat.get(entry.file)\n const additions =\n counted?.additions ??\n (fileStatus === 'untracked' ? await countUntracked(projectRoot, entry.file) : 0)\n files.push({\n path: entry.file,\n previousPath: entry.previous,\n status: fileStatus,\n additions,\n deletions: counted?.deletions ?? 0,\n generated: isGenerated(entry.file),\n binary: false,\n })\n }\n\n files.sort((a, b) => {\n if (a.generated !== b.generated) return a.generated ? 1 : -1\n return a.path.localeCompare(b.path)\n })\n\n return {\n branch,\n upstream,\n commits,\n files,\n totals: {\n files: files.length,\n additions: files.reduce((sum, f) => sum + f.additions, 0),\n deletions: files.reduce((sum, f) => sum + f.deletions, 0),\n },\n }\n}\n\n/**\n * Diff de um arquivo — do working tree contra o HEAD, ou de dentro de um commit\n * local quando `commit` é informado. Carregado quando o revisor abre o card.\n */\nexport async function fileDiff(\n projectRoot: string,\n file: string,\n commit?: string,\n): Promise<FileDiff> {\n const absolute = path.resolve(projectRoot, file)\n const relative = path.relative(projectRoot, absolute)\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('invalid_path')\n }\n if (commit) {\n if (!/^[0-9a-f]{7,40}$/i.test(commit)) throw new Error('invalid_commit')\n const raw = await git(projectRoot, [\n 'show',\n '--format=',\n '--unified=3',\n commit,\n '--',\n file,\n ]).catch(() => '')\n const { diff, truncated } = truncate(raw)\n return { path: file, binary: raw.includes('Binary files'), truncated, diff }\n }\n const tracked = await git(projectRoot, ['ls-files', '--error-unmatch', '--', file])\n .then(() => true)\n .catch(() => false)\n const raw = await diffForFile(projectRoot, file, tracked ? 'modified' : 'untracked').catch(\n () => '',\n )\n const { diff, truncated } = truncate(raw)\n return { path: file, binary: raw.includes('Binary files'), truncated, diff }\n}\n\nexport type OpenEditorResult =\n | { ok: true; command: string }\n | { ok: false; error: 'invalid_path' | 'spawn_failed'; detail?: string }\n\n/**\n * Abre o arquivo no editor configurado (`review.openCommand`, default Cursor),\n * posicionando o cursor na linha quando informada.\n */\nexport async function openInEditor(\n projectRoot: string,\n template: string,\n file: string,\n line?: number,\n): Promise<OpenEditorResult> {\n const absolute = path.resolve(projectRoot, file)\n const relative = path.relative(projectRoot, absolute)\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n return { ok: false, error: 'invalid_path' }\n }\n\n const filled = template\n .replaceAll('{path}', absolute)\n .replaceAll('{line}', String(line ?? 1))\n .trim()\n const [bin, ...args] = filled.split(/\\s+/)\n if (!bin) return { ok: false, error: 'spawn_failed', detail: 'comando vazio' }\n\n try {\n await run(bin, args, { cwd: projectRoot })\n return { ok: true, command: filled }\n } catch (err) {\n return { ok: false, error: 'spawn_failed', detail: (err as Error).message }\n }\n}\n","import path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport { readFile } from 'node:fs/promises'\nimport { assertInsideProject, fileExists } from './fs-utils.js'\nimport { DEFAULT_PROTOTYPE_OPEN_COMMAND, normalizePrototype } from './config-defaults.js'\nimport type { PrototypeResolved, SpecsConfig } from './types.js'\n\n/**\n * Resolve o protótipo válido para um contexto: o bloco `prototype` do\n * `.specs/config.json` vale como default do projeto, e o `meta.json` da feature\n * pode sobrescrevê-lo por completo (uma feature pode ter protótipo em outra\n * ferramenta que o resto do projeto).\n */\nexport async function resolvePrototype(\n projectRoot: string,\n config: SpecsConfig,\n feature?: string,\n): Promise<PrototypeResolved | null> {\n let resolved: PrototypeResolved | null = config.prototype\n ? { ...config.prototype, source: 'config' }\n : null\n\n if (feature) {\n const metaPath = path.resolve(projectRoot, config.featuresDir, feature, 'meta.json')\n try {\n assertInsideProject(metaPath, projectRoot)\n if (await fileExists(metaPath)) {\n const meta = JSON.parse(await readFile(metaPath, 'utf8')) as { prototype?: unknown }\n const override = normalizePrototype(meta.prototype)\n if (override) resolved = { ...override, source: 'feature', feature }\n }\n } catch {\n // meta.json ausente ou inválido — fica com o default do projeto\n }\n }\n\n if (!resolved) return null\n\n resolved = await withSnapshot(projectRoot, resolved)\n\n if (resolved.tool === 'pencil' && resolved.file) {\n const filePath = path.resolve(projectRoot, resolved.file)\n try {\n assertInsideProject(filePath, projectRoot)\n return { ...resolved, filePath, fileExists: await fileExists(filePath) }\n } catch {\n return { ...resolved, fileExists: false }\n }\n }\n\n return resolved\n}\n\n/**\n * Resolve o snapshot local do protótipo — o HTML que a plataforma serve para\n * embutir o canvas em iframe. Usa `snapshot` quando declarado; senão tenta o\n * default `<designDir>/canvas.html`.\n */\nasync function withSnapshot(\n projectRoot: string,\n prototype: PrototypeResolved,\n): Promise<PrototypeResolved> {\n const candidate =\n prototype.snapshot ??\n (prototype.designDir ? `${prototype.designDir.replace(/\\/$/, '')}/canvas.html` : undefined)\n if (!candidate) return prototype\n try {\n const abs = path.resolve(projectRoot, candidate)\n assertInsideProject(abs, projectRoot)\n return { ...prototype, snapshotPath: candidate, snapshotExists: await fileExists(abs) }\n } catch {\n return { ...prototype, snapshotPath: candidate, snapshotExists: false }\n }\n}\n\n/** Caminho absoluto do snapshot, validado — `null` quando não há um utilizável. */\nexport function snapshotAbsolutePath(\n projectRoot: string,\n prototype: PrototypeResolved,\n): string | null {\n if (!prototype.snapshotPath || !prototype.snapshotExists) return null\n try {\n const abs = path.resolve(projectRoot, prototype.snapshotPath)\n assertInsideProject(abs, projectRoot)\n return abs\n } catch {\n return null\n }\n}\n\n/**\n * Prompt do job que (re)gera o snapshot local — o HTML que a plataforma embute\n * no iframe, já que o canvas remoto recusa embed.\n */\nexport function buildSnapshotPrompt(prototype: PrototypeResolved): string {\n const target = prototype.snapshotPath ?? 'design/prototipo/canvas.html'\n if (prototype.tool === 'claude-design') {\n return `Atualize o snapshot local do protótipo: leia o canvas ${prototype.url} com a tool Artifact (action \"read\") e grave o HTML completo devolvido em ${target} (crie o diretório se não existir, e sobrescreva o arquivo se já houver um). Não altere o canvas nem outros arquivos do repositório; ao terminar, diga o tamanho do arquivo gravado.`\n }\n return `Atualize o snapshot local do protótipo Pencil ${prototype.file}: exporte a visão atual do arquivo e grave-a em ${target}. Se o Pencil MCP não permitir exportar, diga isso em vez de improvisar, e informe qual export manual o usuário precisa fazer.`\n}\n\nexport type DesignPromptContext = {\n feature?: string\n task?: string\n featureTitle?: string\n specPath?: string\n}\n\n/**\n * Monta o prompt do job de design. No Claude Design a alteração é pedida pelo\n * slash command `/design` do próprio Claude Code; no Pencil, por instrução de\n * usar o Pencil MCP sobre o `.pen` (que é encriptado e só se lê por lá).\n */\nexport function buildDesignPrompt(\n prototype: PrototypeResolved,\n request: string,\n ctx: DesignPromptContext = {},\n intent: 'change' | 'snapshot' = 'change',\n): string {\n if (intent === 'snapshot') return buildSnapshotPrompt(prototype)\n\n const context: string[] = []\n if (ctx.featureTitle || ctx.feature) {\n context.push(`Feature: ${ctx.featureTitle ?? ctx.feature}`)\n }\n if (ctx.task) context.push(`Task: ${ctx.task}`)\n if (ctx.specPath) context.push(`Spec: ${ctx.specPath}`)\n const suffix = context.length > 0 ? `\\n\\nContexto — ${context.join(' · ')}.` : ''\n\n if (prototype.tool === 'claude-design') {\n const target = [\n prototype.title ? `\"${prototype.title}\"` : null,\n prototype.url ? `(${prototype.url})` : null,\n ]\n .filter(Boolean)\n .join(' ')\n const dir = prototype.designDir\n ? ` As notas do protótipo estão em ${prototype.designDir}/README.md — atualize-as se a mudança alterar as decisões descritas lá.`\n : ''\n return `/design Atualize o protótipo ${target} do canvas existente: ${request}. Mantenha os artboards já publicados e o sistema de tokens atual; re-seed apenas o que a mudança exigir.${dir}${suffix}`\n }\n\n const file = prototype.file ?? '(arquivo .pen não declarado)'\n return `Altere o protótipo Pencil ${file}: ${request}. Use as tools do Pencil MCP (o .pen é encriptado — nunca leia com Read/Grep): confirme o estado do editor, localize os nós alvo, aplique a mudança e devolva os node IDs afetados com o antes/depois de cada um.${suffix}`\n}\n\nexport type OpenPrototypeResult =\n | { ok: true; command: string }\n | { ok: false; status: 400 | 404 | 500; error: string; detail?: string }\n\n/**\n * Abre o protótipo no app local. Só faz sentido para ferramentas de arquivo\n * (Pencil) — no Claude Design a UI abre a URL direto no browser, sem passar\n * pelo servidor.\n */\nexport function openPrototype(\n projectRoot: string,\n prototype: PrototypeResolved,\n): OpenPrototypeResult {\n if (prototype.tool !== 'pencil' || !prototype.filePath) {\n return { ok: false, status: 400, error: 'not_openable' }\n }\n if (prototype.fileExists === false) {\n return { ok: false, status: 404, error: 'prototype_file_not_found', detail: prototype.file }\n }\n const template = prototype.openCommand ?? DEFAULT_PROTOTYPE_OPEN_COMMAND[prototype.tool] ?? ''\n const command = template\n .replaceAll('{file}', prototype.filePath)\n .replaceAll('{url}', prototype.url ?? '')\n const tokens = command.match(/\"[^\"]*\"|'[^']*'|\\S+/g) ?? []\n const cleaned = tokens.map((t) =>\n (t.startsWith('\"') && t.endsWith('\"')) || (t.startsWith(\"'\") && t.endsWith(\"'\"))\n ? t.slice(1, -1)\n : t,\n )\n const [file, ...args] = cleaned\n if (!file) return { ok: false, status: 400, error: 'invalid_open_command' }\n try {\n const child = spawn(file, args, { cwd: projectRoot, detached: true, stdio: 'ignore' })\n child.on('error', (err) => {\n console.error(`[prototype] open error: ${err.message}`)\n })\n child.unref()\n return { ok: true, command }\n } catch (err) {\n return { ok: false, status: 500, error: 'spawn_failed', detail: (err as Error).message }\n }\n}\n","import { EventEmitter } from 'node:events'\nimport * as pty from 'node-pty'\nimport { nanoid } from 'nanoid'\nimport type { JobKind, JobStatus, JobSummary, JobWithBuffer } from './types.js'\nimport { loadJobHistory, saveJobHistory, type StorableJob } from './job-store.js'\n\n/**\n * Sequências de escape que um TUI escreve no PTY. Não basta o CSI (`ESC [ … letra`):\n * o Claude Code também emite **OSC** — título da janela (`ESC ] 0 ; texto BEL`) e\n * hyperlinks (`ESC ] 8 ; id=… ; url ST`). Sem removê-los, o `needsInputHint` sai\n * com `]0;` e `]8;id=…https://…` colados no texto e vaza isso para a UI.\n */\nconst OSC_REGEX = /\\x1b\\][^\\x07\\x1b]*(?:\\x07|\\x1b\\\\|$)/g\nconst CSI_REGEX = /\\x1b\\[[0-9;?]*[ -\\/]*[@-~]/g\n/** `ESC` seguido de um único byte final: `ESC ( B`, `ESC =`, `ESC >`, `ESC M`… */\nconst SIMPLE_ESC_REGEX = /\\x1b[()#][0-9A-Za-z]|\\x1b[0-9A-Za-z=><]/g\n/** Controles que sobram depois disso (BEL, backspace, VT, SO/SI…), menos \\t \\n \\r. */\nconst CONTROL_REGEX = /[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/g\n/** Um hint é uma linha de terminal — mais que isso é buffer vazando para a UI. */\nconst HINT_MAX_CHARS = 160\nconst DEFAULT_COLS = 120\nconst DEFAULT_ROWS = 30\nconst INACTIVITY_MS = 2500\nconst DEBOUNCE_MS = 200\nconst STOP_SIGTERM_DELAY_MS = 2000\nconst STOP_SIGKILL_DELAY_MS = 2000\nconst INPUT_GRACE_MS = 3000\n/** Janela de agrupamento das gravações do histórico em disco. */\nconst PERSIST_DEBOUNCE_MS = 800\n\n/**\n * Remove todo escape de terminal de um texto do PTY. Exportada porque é a\n * fronteira entre o buffer cru e o que a UI mostra — e é onde os OSC vazavam.\n */\nexport function stripAnsi(s: string): string {\n // OSC primeiro: o corpo dele pode conter algo que o CSI casaria por engano.\n return s\n .replace(OSC_REGEX, '')\n .replace(CSI_REGEX, '')\n .replace(SIMPLE_ESC_REGEX, '')\n .replace(CONTROL_REGEX, '')\n}\n\n/** Encurta o hint para caber numa linha da sidebar, sem cortar no meio de uma palavra. */\nexport function trimHint(text: string): string {\n const clean = text.replace(/\\s+/g, ' ').trim()\n if (clean.length <= HINT_MAX_CHARS) return clean\n const cut = clean.slice(0, HINT_MAX_CHARS)\n const space = cut.lastIndexOf(' ')\n return `${(space > 40 ? cut.slice(0, space) : cut).trimEnd()}…`\n}\n\n/** Última linha com conteúdo de um trecho de buffer, já sem escapes. */\nexport function lastNonEmptyLine(text: string, limitLines = 8): string {\n const plain = stripAnsi(text)\n const lines = plain.split(/\\r?\\n/).slice(-limitLines)\n for (let i = lines.length - 1; i >= 0; i--) {\n const t = lines[i]?.trim() ?? ''\n if (t.length > 0) return t\n }\n return ''\n}\n\nexport type JobEvent =\n | { type: 'chunk'; payload: string }\n | { type: 'status'; payload: { status: JobStatus; exitCode?: number; needsInputHint?: string } }\n\ntype Job = {\n id: string\n kind: JobKind\n label: string\n feature?: string\n task?: string\n status: JobStatus\n pid: number\n startedAt: number\n endedAt?: number\n exitCode?: number\n buffer: string\n bufferBytes: number\n needsInputHint?: string\n /**\n * Ausente nos jobs restaurados do disco: o processo era filho do servidor\n * anterior e morreu com ele. Sem pty, o job é só histórico legível.\n */\n pty?: pty.IPty\n /** true quando o job veio do histórico, não desta sessão do servidor. */\n restored?: boolean\n emitter: EventEmitter\n inactivityTimer?: NodeJS.Timeout\n debounceTimer?: NodeJS.Timeout\n stopTimers?: NodeJS.Timeout[]\n lastChunkAt: number\n promptPatterns: RegExp[]\n bufferBytesCap: number\n // Timestamp até o qual o detector de needs-input fica suspenso após o usuário\n // enviar input (evita re-flagar a mesma pergunta enquanto o Claude Code processa).\n graceUntil?: number\n}\n\nexport type StartJobInput = {\n kind: JobKind\n label: string\n file: string\n args: string[]\n cwd: string\n feature?: string\n task?: string\n cols?: number\n rows?: number\n env?: NodeJS.ProcessEnv\n promptPatterns: RegExp[]\n bufferBytesCap: number\n}\n\nconst jobs = new Map<string, Job>()\n\nexport type JobManagerOptions = {\n /**\n * Raiz do projeto onde o histórico é gravado. Sem ela o manager funciona\n * igual, só não sobrevive a um restart — é o modo usado nos testes.\n */\n projectRoot?: string\n}\n\nexport function createJobManager(options: JobManagerOptions = {}) {\n const { projectRoot } = options\n let persistTimer: NodeJS.Timeout | null = null\n\n function toStorable(job: Job): StorableJob {\n return { ...summarize(job), buffer: job.buffer, lastSeenAt: job.lastChunkAt }\n }\n\n /** Grava agora. Usado no shutdown, onde não dá para esperar o debounce. */\n function persistNow(): void {\n if (!projectRoot) return\n if (persistTimer) {\n clearTimeout(persistTimer)\n persistTimer = null\n }\n saveJobHistory(projectRoot, Array.from(jobs.values()).map(toStorable))\n }\n\n /**\n * Agenda a gravação. O buffer muda a cada chunk do PTY; gravar em cada um\n * transformaria o histórico num gargalo de I/O.\n */\n function schedulePersist(): void {\n if (!projectRoot || persistTimer) return\n persistTimer = setTimeout(() => {\n persistTimer = null\n persistNow()\n }, PERSIST_DEBOUNCE_MS)\n persistTimer.unref?.()\n }\n\n // Repõe o que a sessão anterior deixou. Os processos não voltam — os registros\n // sim, já marcados como interrompidos por `reviveJob`.\n if (projectRoot) {\n for (const persisted of loadJobHistory(projectRoot)) {\n if (jobs.has(persisted.id)) continue\n const emitter = new EventEmitter()\n emitter.setMaxListeners(32)\n jobs.set(persisted.id, {\n ...persisted,\n buffer: persisted.buffer,\n bufferBytes: persisted.buffer.length,\n emitter,\n lastChunkAt: persisted.endedAt ?? persisted.startedAt,\n promptPatterns: [],\n bufferBytesCap: Math.max(persisted.buffer.length, 1),\n restored: true,\n })\n }\n }\n\n function summarize(job: Job): JobSummary {\n return {\n id: job.id,\n kind: job.kind,\n label: job.label,\n feature: job.feature,\n task: job.task,\n status: job.status,\n pid: job.pid,\n startedAt: job.startedAt,\n endedAt: job.endedAt,\n exitCode: job.exitCode,\n bufferBytes: job.bufferBytes,\n needsInputHint: job.needsInputHint,\n restored: job.restored,\n }\n }\n\n function setStatus(job: Job, next: JobStatus, extra?: { exitCode?: number }) {\n if (job.status === next && extra?.exitCode === undefined) return\n job.status = next\n if (extra?.exitCode !== undefined) job.exitCode = extra.exitCode\n job.emitter.emit('event', {\n type: 'status',\n payload: {\n status: next,\n exitCode: job.exitCode,\n needsInputHint: job.needsInputHint,\n },\n } satisfies JobEvent)\n schedulePersist()\n }\n\n function matchPrompt(job: Job): string | null {\n const tail = job.buffer.slice(-8000)\n const last = lastNonEmptyLine(tail)\n if (!last) return null\n for (const re of job.promptPatterns) {\n if (re.test(last)) return last\n }\n return null\n }\n\n function evaluateNeedsInput(job: Job, trigger: 'chunk' | 'inactivity') {\n if (job.status === 'done' || job.status === 'failed' || job.status === 'cancelled') return\n // Sticky: uma vez marcado como needs-input, só sai quando o usuário envia input\n // (ver writeInput) ou o processo termina. O TUI do Claude Code costuma redesenhar\n // spinners/indicadores sobre a linha do prompt, fazendo matchPrompt oscilar —\n // se tratássemos cada flap como transição, dispararíamos notificação repetida.\n if (job.status === 'needs-input') return\n // Grace period após writeInput: o Claude Code ainda pode estar ecoando a resposta\n // e/ou re-renderizando a pergunta antiga por alguns ms. Não re-flagar enquanto isso.\n if (job.graceUntil && Date.now() < job.graceUntil) return\n const match = matchPrompt(job)\n const quietLongEnough = Date.now() - job.lastChunkAt >= INACTIVITY_MS\n const shouldFlag = Boolean(match) || (trigger === 'inactivity' && quietLongEnough)\n if (shouldFlag) {\n job.needsInputHint = trimHint(match ?? lastNonEmptyLine(job.buffer.slice(-2000)))\n setStatus(job, 'needs-input')\n }\n }\n\n function scheduleInactivity(job: Job) {\n if (job.inactivityTimer) clearTimeout(job.inactivityTimer)\n job.inactivityTimer = setTimeout(() => {\n evaluateNeedsInput(job, 'inactivity')\n }, INACTIVITY_MS + 100)\n }\n\n function appendToBuffer(job: Job, chunk: string) {\n job.buffer += chunk\n if (job.buffer.length > job.bufferBytesCap) {\n job.buffer = job.buffer.slice(job.buffer.length - job.bufferBytesCap)\n }\n job.bufferBytes = job.buffer.length\n job.lastChunkAt = Date.now()\n schedulePersist()\n }\n\n function startJob(input: StartJobInput): JobSummary {\n const id = nanoid(10)\n const cols = input.cols ?? DEFAULT_COLS\n const rows = input.rows ?? DEFAULT_ROWS\n const env = {\n ...process.env,\n ...input.env,\n TERM: 'xterm-256color',\n COLORTERM: 'truecolor',\n FORCE_COLOR: '1',\n }\n const ptyProc = pty.spawn(input.file, input.args, {\n name: 'xterm-256color',\n cwd: input.cwd,\n cols,\n rows,\n env,\n })\n\n const emitter = new EventEmitter()\n emitter.setMaxListeners(32)\n const job: Job = {\n id,\n kind: input.kind,\n label: input.label,\n feature: input.feature,\n task: input.task,\n status: 'running',\n pid: ptyProc.pid,\n startedAt: Date.now(),\n buffer: '',\n bufferBytes: 0,\n pty: ptyProc,\n emitter,\n lastChunkAt: Date.now(),\n promptPatterns: input.promptPatterns,\n bufferBytesCap: input.bufferBytesCap,\n }\n jobs.set(id, job)\n\n ptyProc.onData((chunk) => {\n appendToBuffer(job, chunk)\n emitter.emit('event', { type: 'chunk', payload: chunk } satisfies JobEvent)\n if (job.debounceTimer) clearTimeout(job.debounceTimer)\n job.debounceTimer = setTimeout(() => {\n evaluateNeedsInput(job, 'chunk')\n }, DEBOUNCE_MS)\n scheduleInactivity(job)\n })\n\n ptyProc.onExit(({ exitCode, signal }) => {\n if (job.inactivityTimer) clearTimeout(job.inactivityTimer)\n if (job.debounceTimer) clearTimeout(job.debounceTimer)\n job.endedAt = Date.now()\n if (signal !== undefined && signal !== 0 && job.status === 'cancelled') {\n setStatus(job, 'cancelled', { exitCode })\n } else if (exitCode === 0) {\n setStatus(job, 'done', { exitCode })\n } else {\n setStatus(job, 'failed', { exitCode })\n }\n })\n\n scheduleInactivity(job)\n schedulePersist()\n return summarize(job)\n }\n\n function writeInput(jobId: string, data: string): boolean {\n const job = jobs.get(jobId)\n if (!job || !job.pty) return false\n if (job.status === 'done' || job.status === 'failed' || job.status === 'cancelled') {\n return false\n }\n job.pty.write(data)\n // O usuário respondeu: volta pra running e entra em grace period — o detector\n // fica suspenso por INPUT_GRACE_MS para não re-flagar a mesma pergunta enquanto\n // o Claude Code processa a resposta.\n job.graceUntil = Date.now() + INPUT_GRACE_MS\n if (job.status === 'needs-input') {\n job.needsInputHint = undefined\n setStatus(job, 'running')\n }\n return true\n }\n\n function resize(jobId: string, cols: number, rows: number): boolean {\n const job = jobs.get(jobId)\n if (!job || !job.pty) return false\n if (job.status === 'done' || job.status === 'failed' || job.status === 'cancelled') {\n return false\n }\n try {\n job.pty.resize(Math.max(1, cols | 0), Math.max(1, rows | 0))\n return true\n } catch {\n return false\n }\n }\n\n function stopJob(jobId: string): boolean {\n const job = jobs.get(jobId)\n if (!job) return false\n if (job.status === 'done' || job.status === 'failed' || job.status === 'cancelled') {\n return true\n }\n // Job restaurado nunca está ativo (reviveJob já o marcou como cancelado),\n // mas se estivesse não haveria processo para sinalizar.\n if (!job.pty) return true\n try {\n job.pty.kill('SIGINT')\n } catch {}\n // Marca otimisticamente como cancelled; o onExit confirmará.\n setStatus(job, 'cancelled')\n const pty1 = job.pty\n const t1 = setTimeout(() => {\n if (job.status === 'cancelled' && job.endedAt === undefined) {\n try {\n pty1.kill('SIGTERM')\n } catch {}\n }\n }, STOP_SIGTERM_DELAY_MS)\n const t2 = setTimeout(() => {\n if (job.status === 'cancelled' && job.endedAt === undefined) {\n try {\n pty1.kill('SIGKILL')\n } catch {}\n }\n }, STOP_SIGTERM_DELAY_MS + STOP_SIGKILL_DELAY_MS)\n job.stopTimers = [t1, t2]\n return true\n }\n\n function deleteJob(jobId: string): boolean {\n const job = jobs.get(jobId)\n if (!job) return false\n if (job.status === 'running' || job.status === 'needs-input') return false\n if (job.stopTimers) job.stopTimers.forEach(clearTimeout)\n if (job.inactivityTimer) clearTimeout(job.inactivityTimer)\n if (job.debounceTimer) clearTimeout(job.debounceTimer)\n job.emitter.removeAllListeners()\n jobs.delete(jobId)\n schedulePersist()\n return true\n }\n\n function listJobs(): JobSummary[] {\n return Array.from(jobs.values())\n .sort((a, b) => b.startedAt - a.startedAt)\n .map(summarize)\n }\n\n function getJob(jobId: string): JobWithBuffer | null {\n const job = jobs.get(jobId)\n if (!job) return null\n return { ...summarize(job), buffer: job.buffer }\n }\n\n function subscribe(jobId: string, handler: (event: JobEvent) => void): () => void {\n const job = jobs.get(jobId)\n if (!job) return () => {}\n job.emitter.on('event', handler)\n return () => {\n job.emitter.off('event', handler)\n }\n }\n\n async function shutdownAll(): Promise<void> {\n // Grava antes de matar: é este arquivo que a próxima sessão vai reler para\n // repor a lista de Execuções.\n persistNow()\n for (const job of jobs.values()) {\n if (job.inactivityTimer) clearTimeout(job.inactivityTimer)\n if (job.debounceTimer) clearTimeout(job.debounceTimer)\n if (job.stopTimers) job.stopTimers.forEach(clearTimeout)\n try {\n if (job.pty && (job.status === 'running' || job.status === 'needs-input')) {\n job.pty.kill('SIGKILL')\n }\n } catch {}\n job.emitter.removeAllListeners()\n }\n jobs.clear()\n }\n\n return {\n startJob,\n writeInput,\n resize,\n stopJob,\n deleteJob,\n listJobs,\n getJob,\n subscribe,\n shutdownAll,\n }\n}\n\nexport type JobManager = ReturnType<typeof createJobManager>\n\nexport function compilePromptPatterns(patterns: string[]): RegExp[] {\n const compiled: RegExp[] = []\n for (const p of patterns) {\n try {\n compiled.push(new RegExp(p, 'i'))\n } catch (err) {\n console.error(`[job-manager] invalid prompt pattern \"${p}\": ${(err as Error).message}`)\n }\n }\n return compiled\n}\n","import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport path from 'node:path'\nimport type { JobKind, JobStatus, JobSummary } from './types.js'\n\n/**\n * Histórico de execuções gravado em disco.\n *\n * Os jobs vivem em memória porque são processos PTY filhos do servidor — quando\n * o servidor morre, eles morrem junto e não há como reconectar num pty destruído.\n * Mas perder a *lista* junto com os processos é gratuito: quem reinicia a\n * plataforma fica sem saber o que rodou, o que perguntou e o que ficou pela\n * metade. Este módulo persiste o registro (label, tempos, status e o fim do\n * buffer) para a sidebar de Execuções sobreviver ao restart.\n */\n\n/** Quantos jobs o arquivo guarda, dos mais recentes para trás. */\nexport const MAX_PERSISTED_JOBS = 30\n\n/**\n * Quanto do buffer de cada job vai para o disco. O buffer em memória chega a\n * 2 MB; guardar tudo de 30 jobs faria um arquivo de 60 MB para reler a cada\n * boot. O fim do terminal é o que interessa — é lá que está a última pergunta\n * ou o erro.\n */\nexport const MAX_PERSISTED_BUFFER = 64 * 1024\n\nexport type PersistedJob = JobSummary & {\n buffer: string\n /** true quando o registro veio de uma sessão anterior do servidor. */\n restored: true\n}\n\ntype FileShape = { version: 1; jobs: unknown[] }\n\n/** Onde o histórico mora. Fica ao lado da config, e é runtime — não versione. */\nexport function jobStorePath(projectRoot: string): string {\n return path.join(projectRoot, '.specs', '.jobs.json')\n}\n\nfunction isJobStatus(v: unknown): v is JobStatus {\n return (\n v === 'running' || v === 'needs-input' || v === 'done' || v === 'failed' || v === 'cancelled'\n )\n}\n\nfunction isJobKind(v: unknown): v is JobKind {\n return (\n v === 'agent' ||\n v === 'refinement' ||\n v === 'discovery-agent' ||\n v === 'drawing-agent' ||\n v === 'design'\n )\n}\n\n/**\n * Converte um registro cru do arquivo em job restaurado.\n *\n * Status ativo vira `cancelled`: o processo era filho do servidor anterior e\n * morreu com ele. Deixá-lo como `running` faria a sidebar mostrar um spinner\n * eterno para um pty que não existe mais.\n */\nexport function reviveJob(raw: unknown): PersistedJob | null {\n if (typeof raw !== 'object' || raw === null) return null\n const r = raw as Record<string, unknown>\n if (typeof r.id !== 'string' || r.id.length === 0) return null\n if (typeof r.label !== 'string') return null\n if (!isJobKind(r.kind)) return null\n if (typeof r.startedAt !== 'number' || !Number.isFinite(r.startedAt)) return null\n\n const status = isJobStatus(r.status) ? r.status : 'cancelled'\n const wasActive = status === 'running' || status === 'needs-input'\n const buffer = typeof r.buffer === 'string' ? r.buffer.slice(-MAX_PERSISTED_BUFFER) : ''\n\n return {\n id: r.id,\n kind: r.kind,\n label: r.label,\n feature: typeof r.feature === 'string' ? r.feature : undefined,\n task: typeof r.task === 'string' ? r.task : undefined,\n status: wasActive ? 'cancelled' : status,\n pid: typeof r.pid === 'number' ? r.pid : 0,\n startedAt: r.startedAt,\n // Um job que estava vivo não tem fim registrado — o servidor caiu antes.\n // Sem `endedAt`, a duração exibida cresceria para sempre.\n endedAt:\n typeof r.endedAt === 'number'\n ? r.endedAt\n : wasActive\n ? (typeof r.lastSeenAt === 'number' ? r.lastSeenAt : r.startedAt)\n : undefined,\n exitCode: typeof r.exitCode === 'number' ? r.exitCode : undefined,\n bufferBytes: buffer.length,\n needsInputHint: typeof r.needsInputHint === 'string' ? r.needsInputHint : undefined,\n buffer,\n restored: true,\n }\n}\n\n/**\n * Lê o histórico. Nunca lança: um arquivo corrompido ou de uma versão futura\n * custa o histórico, não o boot do servidor.\n */\nexport function loadJobHistory(projectRoot: string): PersistedJob[] {\n let parsed: unknown\n try {\n parsed = JSON.parse(readFileSync(jobStorePath(projectRoot), 'utf8'))\n } catch {\n return []\n }\n if (typeof parsed !== 'object' || parsed === null) return []\n const file = parsed as Partial<FileShape>\n if (file.version !== 1 || !Array.isArray(file.jobs)) return []\n\n const out: PersistedJob[] = []\n for (const raw of file.jobs) {\n const job = reviveJob(raw)\n if (job) out.push(job)\n }\n return out.sort((a, b) => b.startedAt - a.startedAt).slice(0, MAX_PERSISTED_JOBS)\n}\n\nexport type StorableJob = JobSummary & { buffer: string; lastSeenAt: number }\n\n/**\n * Grava o histórico. Síncrono e atômico de propósito: o momento mais importante\n * para gravar é o shutdown, onde não há para quem esperar uma Promise.\n */\nexport function saveJobHistory(projectRoot: string, jobs: StorableJob[]): void {\n const trimmed = jobs\n .slice()\n .sort((a, b) => b.startedAt - a.startedAt)\n .slice(0, MAX_PERSISTED_JOBS)\n .map((job) => ({ ...job, buffer: job.buffer.slice(-MAX_PERSISTED_BUFFER) }))\n\n const finalPath = jobStorePath(projectRoot)\n const tmpPath = `${finalPath}.tmp`\n const payload: FileShape = { version: 1, jobs: trimmed }\n try {\n mkdirSync(path.dirname(finalPath), { recursive: true })\n writeFileSync(tmpPath, `${JSON.stringify(payload)}\\n`, 'utf8')\n renameSync(tmpPath, finalPath)\n } catch (err) {\n console.error(`[job-store] falha ao gravar histórico: ${(err as Error).message}`)\n }\n}\n","import path from 'node:path'\nimport type { FastifyInstance } from 'fastify'\nimport { z } from 'zod'\nimport { SLUG_REGEX } from './fs-utils.js'\nimport { compilePromptPatterns, type JobEvent, type JobManager } from './job-manager.js'\nimport {\n buildAgentInlineCommand,\n buildDesignInlineCommand,\n buildNamedAgentInlineCommand,\n listAgentModels,\n runAgent,\n runDesign,\n runDiscoveryAgent,\n runDrawingAgent,\n runRefinement,\n runRefinementRunner,\n} from './run-agent.js'\nimport { buildDesignPrompt, resolvePrototype } from './prototype.js'\nimport { AGENT_EFFORTS, type SpecsConfig } from './types.js'\n\nconst slugSchema = z.string().regex(SLUG_REGEX)\n\nconst cliSchema = z\n .string()\n .min(1)\n .max(40)\n .regex(/^[a-z0-9-]+$/)\n .optional()\n\nconst modelSchema = z\n .string()\n .min(1)\n .max(80)\n .regex(/^[A-Za-z0-9][A-Za-z0-9._\\-/:]*$/)\n .optional()\n\nconst effortSchema = z.enum(AGENT_EFFORTS).optional()\n\nconst createJobBodySchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('agent'),\n mode: z.enum(['inline', 'external']).default('inline'),\n cli: cliSchema,\n model: modelSchema,\n effort: effortSchema,\n scope: z.enum(['feature', 'featureNoPause', 'task']),\n feature: slugSchema,\n task: slugSchema.optional(),\n cols: z.number().int().min(20).max(400).optional(),\n rows: z.number().int().min(5).max(200).optional(),\n }),\n z.object({\n kind: z.literal('refinement'),\n mode: z.enum(['inline', 'external']).default('inline'),\n cli: cliSchema,\n model: modelSchema,\n effort: effortSchema,\n prompt: z.string().min(1).max(10_000),\n cols: z.number().int().min(20).max(400).optional(),\n rows: z.number().int().min(5).max(200).optional(),\n }),\n z.object({\n kind: z.literal('refinement-runner'),\n mode: z.enum(['inline', 'external']).default('inline'),\n cli: cliSchema,\n model: modelSchema,\n effort: effortSchema,\n prompt: z.string().min(1).max(10_000),\n cols: z.number().int().min(20).max(400).optional(),\n rows: z.number().int().min(5).max(200).optional(),\n }),\n z.object({\n kind: z.literal('design'),\n mode: z.enum(['inline', 'external']).default('inline'),\n cli: cliSchema,\n model: modelSchema,\n effort: effortSchema,\n /** Pedido de alteração escrito pelo usuário no painel de protótipo. */\n prompt: z.string().min(1).max(10_000),\n /** `snapshot` regrava a cópia local usada no iframe; `change` (default) altera o design. */\n intent: z.enum(['change', 'snapshot']).default('change'),\n feature: slugSchema.optional(),\n task: slugSchema.optional(),\n cols: z.number().int().min(20).max(400).optional(),\n rows: z.number().int().min(5).max(200).optional(),\n }),\n z.object({\n kind: z.literal('discovery-agent'),\n mode: z.enum(['inline', 'external']).default('inline'),\n cli: cliSchema,\n model: modelSchema,\n effort: effortSchema,\n prompt: z.string().min(1).max(10_000),\n cols: z.number().int().min(20).max(400).optional(),\n rows: z.number().int().min(5).max(200).optional(),\n }),\n z.object({\n kind: z.literal('drawing-agent'),\n mode: z.enum(['inline', 'external']).default('inline'),\n cli: cliSchema,\n model: modelSchema,\n effort: effortSchema,\n prompt: z.string().min(1).max(10_000),\n cols: z.number().int().min(20).max(400).optional(),\n rows: z.number().int().min(5).max(200).optional(),\n }),\n])\n\nconst jobIdParamSchema = z.object({ id: z.string().min(1).max(64) })\n\nconst inputBodySchema = z.object({ data: z.string().max(10_000) })\n\nconst resizeBodySchema = z.object({\n cols: z.number().int().min(20).max(400),\n rows: z.number().int().min(5).max(200),\n})\n\nfunction sseEvent(ev: JobEvent): string {\n return `event: ${ev.type}\\ndata: ${JSON.stringify(ev.payload)}\\n\\n`\n}\n\nexport function registerJobRoutes(\n fastify: FastifyInstance,\n jobs: JobManager,\n getConfig: () => Promise<SpecsConfig>,\n projectRoot: string,\n): void {\n fastify.post('/api/jobs', async (req, reply) => {\n const parsed = createJobBodySchema.safeParse(req.body)\n if (!parsed.success) {\n return reply.code(400).send({ error: 'invalid_body', detail: parsed.error.message })\n }\n const config = await getConfig()\n const body = parsed.data\n\n // Jobs de design dependem do protótipo declarado (config do projeto ou\n // override da feature) — é ele que decide a ferramenta e o formato do prompt.\n let designPrompt: string | null = null\n let designLabel = ''\n if (body.kind === 'design') {\n const prototype = await resolvePrototype(projectRoot, config, body.feature)\n if (!prototype) {\n return reply.code(400).send({\n error: 'no_prototype',\n detail: 'Nenhum protótipo declarado em .specs/config.json nem no meta.json da feature.',\n })\n }\n designPrompt = buildDesignPrompt(\n prototype,\n body.prompt,\n {\n feature: body.feature,\n task: body.task,\n specPath:\n body.feature && body.task\n ? `${config.featuresDir}/${body.feature}/${body.task}.md`\n : body.feature\n ? `${config.featuresDir}/${body.feature}/`\n : undefined,\n },\n body.intent,\n )\n designLabel =\n body.intent === 'snapshot'\n ? 'Design: sincronizar snapshot'\n : `Design: ${body.prompt.slice(0, 60)}${body.prompt.length > 60 ? '…' : ''}`\n }\n\n if (body.mode === 'external') {\n if (body.kind === 'agent') {\n const result = await runAgent(\n {\n scope: body.scope,\n feature: body.feature,\n task: body.task,\n cli: body.cli,\n model: body.model,\n effort: body.effort,\n },\n config,\n projectRoot,\n )\n if (result.ok) return { ok: true, mode: 'external' as const }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n }\n if (body.kind === 'refinement') {\n const result = runRefinement(\n body.prompt,\n config,\n projectRoot,\n body.cli,\n body.model,\n body.effort,\n )\n if (result.ok) return { ok: true, mode: 'external' as const }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n }\n if (body.kind === 'refinement-runner') {\n const result = runRefinementRunner(\n body.prompt,\n config,\n projectRoot,\n body.cli,\n body.model,\n body.effort,\n )\n if (result.ok) return { ok: true, mode: 'external' as const }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n }\n if (body.kind === 'design') {\n const result = runDesign(\n designPrompt as string,\n config,\n projectRoot,\n body.cli,\n body.model,\n body.effort,\n )\n if (result.ok) return { ok: true, mode: 'external' as const }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n }\n if (body.kind === 'drawing-agent') {\n const result = runDrawingAgent(\n body.prompt,\n config,\n projectRoot,\n body.cli,\n body.model,\n body.effort,\n )\n if (result.ok) return { ok: true, mode: 'external' as const }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n }\n // discovery-agent\n const result = runDiscoveryAgent(\n body.prompt,\n config,\n projectRoot,\n body.cli,\n body.model,\n body.effort,\n )\n if (result.ok) return { ok: true, mode: 'external' as const }\n return reply.code(result.status).send({\n error: result.error,\n ...('detail' in result ? { detail: result.detail } : {}),\n ...('hint' in result ? { hint: result.hint } : {}),\n })\n }\n\n // mode === 'inline'\n const patterns = compilePromptPatterns(config.agent.inputPromptPatterns)\n const cwd = path.resolve(projectRoot, config.agent.cwd ?? '.')\n\n let inline: { file: string; args: string[]; cwd: string; label: string } | null = null\n\n if (body.kind === 'agent') {\n inline = await buildAgentInlineCommand(\n {\n scope: body.scope,\n feature: body.feature,\n task: body.task,\n cli: body.cli,\n model: body.model,\n effort: body.effort,\n },\n config,\n projectRoot,\n )\n } else if (body.kind === 'refinement') {\n inline = buildNamedAgentInlineCommand(\n 'refinement',\n body.prompt,\n config,\n projectRoot,\n `Refinement: ${body.prompt.slice(0, 60)}${body.prompt.length > 60 ? '…' : ''}`,\n body.cli,\n body.model,\n body.effort,\n )\n } else if (body.kind === 'refinement-runner') {\n inline = buildNamedAgentInlineCommand(\n 'refinement-runner',\n body.prompt,\n config,\n projectRoot,\n `Refinar + executar: ${body.prompt.slice(0, 60)}${body.prompt.length > 60 ? '…' : ''}`,\n body.cli,\n body.model,\n body.effort,\n )\n } else if (body.kind === 'design') {\n inline = buildDesignInlineCommand(\n designPrompt as string,\n config,\n projectRoot,\n designLabel,\n body.cli,\n body.model,\n body.effort,\n )\n } else if (body.kind === 'drawing-agent') {\n inline = buildNamedAgentInlineCommand(\n 'drawing-agent',\n body.prompt,\n config,\n projectRoot,\n `Desenho: ${body.prompt.slice(0, 60)}${body.prompt.length > 60 ? '…' : ''}`,\n body.cli,\n body.model,\n body.effort,\n )\n } else {\n inline = buildNamedAgentInlineCommand(\n 'discovery-agent',\n body.prompt,\n config,\n projectRoot,\n `Discovery: ${body.prompt.slice(0, 60)}${body.prompt.length > 60 ? '…' : ''}`,\n body.cli,\n body.model,\n body.effort,\n )\n }\n\n if (!inline) {\n return reply.code(500).send({\n error: 'inline_build_failed',\n detail: 'Não foi possível montar o comando para execução inline.',\n })\n }\n\n try {\n const summary = jobs.startJob({\n kind: body.kind,\n label: inline.label,\n file: inline.file,\n args: inline.args,\n cwd: inline.cwd ?? cwd,\n feature: body.kind === 'agent' || body.kind === 'design' ? body.feature : undefined,\n task: body.kind === 'agent' || body.kind === 'design' ? body.task : undefined,\n cols: body.cols,\n rows: body.rows,\n promptPatterns: patterns,\n bufferBytesCap: config.agent.bufferBytesCap,\n })\n return { ok: true, mode: 'inline' as const, jobId: summary.id, job: summary }\n } catch (err) {\n return reply.code(500).send({\n error: 'spawn_failed',\n detail: (err as Error).message,\n })\n }\n })\n\n fastify.get('/api/jobs', async () => ({ jobs: jobs.listJobs() }))\n\n const modelsQuerySchema = z.object({\n cli: z\n .string()\n .min(1)\n .max(40)\n .regex(/^[a-z0-9-]+$/),\n })\n\n fastify.get('/api/agent-models', async (req, reply) => {\n const parsed = modelsQuerySchema.safeParse(req.query)\n if (!parsed.success) return reply.code(400).send({ error: 'invalid_query' })\n const config = await getConfig()\n const result = await listAgentModels(config, projectRoot, parsed.data.cli)\n return result\n })\n\n fastify.get('/api/jobs/:id', async (req, reply) => {\n const parsed = jobIdParamSchema.safeParse(req.params)\n if (!parsed.success) return reply.code(400).send({ error: 'invalid_id' })\n const job = jobs.getJob(parsed.data.id)\n if (!job) return reply.code(404).send({ error: 'job_not_found' })\n return job\n })\n\n fastify.post('/api/jobs/:id/input', async (req, reply) => {\n const idParsed = jobIdParamSchema.safeParse(req.params)\n if (!idParsed.success) return reply.code(400).send({ error: 'invalid_id' })\n const bodyParsed = inputBodySchema.safeParse(req.body)\n if (!bodyParsed.success) return reply.code(400).send({ error: 'invalid_body' })\n const ok = jobs.writeInput(idParsed.data.id, bodyParsed.data.data)\n if (!ok) return reply.code(404).send({ error: 'job_not_found_or_terminated' })\n return { ok: true }\n })\n\n fastify.post('/api/jobs/:id/resize', async (req, reply) => {\n const idParsed = jobIdParamSchema.safeParse(req.params)\n if (!idParsed.success) return reply.code(400).send({ error: 'invalid_id' })\n const bodyParsed = resizeBodySchema.safeParse(req.body)\n if (!bodyParsed.success) return reply.code(400).send({ error: 'invalid_body' })\n const ok = jobs.resize(idParsed.data.id, bodyParsed.data.cols, bodyParsed.data.rows)\n if (!ok) return reply.code(404).send({ error: 'job_not_found_or_terminated' })\n return { ok: true }\n })\n\n fastify.post('/api/jobs/:id/stop', async (req, reply) => {\n const parsed = jobIdParamSchema.safeParse(req.params)\n if (!parsed.success) return reply.code(400).send({ error: 'invalid_id' })\n const ok = jobs.stopJob(parsed.data.id)\n if (!ok) return reply.code(404).send({ error: 'job_not_found' })\n return { ok: true }\n })\n\n fastify.delete('/api/jobs/:id', async (req, reply) => {\n const parsed = jobIdParamSchema.safeParse(req.params)\n if (!parsed.success) return reply.code(400).send({ error: 'invalid_id' })\n const ok = jobs.deleteJob(parsed.data.id)\n if (!ok) return reply.code(409).send({ error: 'job_still_running_or_not_found' })\n return { ok: true }\n })\n\n fastify.get('/api/jobs/:id/stream', async (req, reply) => {\n const parsed = jobIdParamSchema.safeParse(req.params)\n if (!parsed.success) return reply.code(400).send({ error: 'invalid_id' })\n const jobId = parsed.data.id\n const snapshot = jobs.getJob(jobId)\n if (!snapshot) return reply.code(404).send({ error: 'job_not_found' })\n\n reply.raw.setHeader('content-type', 'text/event-stream')\n reply.raw.setHeader('cache-control', 'no-cache, no-transform')\n reply.raw.setHeader('connection', 'keep-alive')\n reply.raw.setHeader('x-accel-buffering', 'no')\n reply.raw.flushHeaders?.()\n\n // Envia snapshot inicial (buffer atual + status)\n if (snapshot.buffer.length > 0) {\n reply.raw.write(sseEvent({ type: 'chunk', payload: snapshot.buffer }))\n }\n reply.raw.write(\n sseEvent({\n type: 'status',\n payload: {\n status: snapshot.status,\n exitCode: snapshot.exitCode,\n needsInputHint: snapshot.needsInputHint,\n },\n }),\n )\n\n const keepAlive = setInterval(() => {\n reply.raw.write(': ping\\n\\n')\n }, 15_000)\n\n const unsubscribe = jobs.subscribe(jobId, (event) => {\n reply.raw.write(sseEvent(event))\n })\n\n req.raw.on('close', () => {\n clearInterval(keepAlive)\n unsubscribe()\n })\n\n // Mantém o handler aberto — Fastify não encerra enquanto reply.raw não terminar.\n return reply\n })\n}\n","export type Status = 'pending' | 'in-progress' | 'completed' | 'blocked'\n\nexport type TerminalKind = 'osascript' | 'gnome-terminal' | 'kitty' | 'wezterm' | 'none'\n\nexport type AgentScopeKey = 'feature' | 'featureNoPause' | 'task'\n\nexport type DiscoveryType = 'rfc' | 'spike' | 'adr' | 'note'\n\n/**\n * Natureza do desenho. Não é o tipo de diagrama Mermaid (um `architecture` pode\n * ser um `flowchart`): é a **pergunta** que o desenho responde, que é o que\n * importa para achar o desenho certo na lista.\n */\nexport type DrawingType = 'architecture' | 'flow' | 'sequence' | 'data' | 'state'\n\nexport type ExecutionMode = 'inline' | 'external'\n\n/**\n * Chave da CLI de agente usada para disparar os jobs. `claude` (Claude Code) e\n * `cursor` (cursor-agent) são reconhecidas nativamente; chaves extras podem ser\n * adicionadas em `agent.commands` do `.specs/config.json`.\n */\nexport type AgentCli = string\n\n/** Modelo de uma CLI: `id` é o valor passado para `--model`; `label` é o nome amigável. */\nexport type AgentModel = { id: string; label: string }\n\n/** Níveis de esforço de raciocínio aceitos pelas CLIs (do mais barato ao mais caro). */\nexport const AGENT_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'] as const\nexport type AgentEffort = (typeof AGENT_EFFORTS)[number]\n\nexport type JobKind =\n | 'agent'\n | 'refinement'\n | 'refinement-runner'\n | 'discovery-agent'\n | 'drawing-agent'\n | 'design'\n\n/** Ferramenta de prototipação usada pelo projeto. */\nexport type PrototypeTool = 'claude-design' | 'pencil'\n\n/**\n * Protótipo do projeto (ou de uma feature). Declarado em `.specs/config.json`\n * como default do projeto e sobrescrevível no `meta.json` de cada feature.\n */\nexport type PrototypeConfig = {\n tool: PrototypeTool\n /** Título humano exibido no painel da Specs Platform. */\n title?: string\n /** Claude Design: URL do canvas/artifact publicado. */\n url?: string\n /** Pencil: caminho do arquivo `.pen`, relativo à raiz do projeto. */\n file?: string\n /** Pasta com o README/notas do protótipo (ex.: `design/finance-redesign`). */\n designDir?: string\n /** Artboards/telas do protótipo, listados no painel. */\n artboards?: string[]\n /** Node IDs relevantes (Pencil), quando o projeto quiser fixá-los. */\n nodeIds?: string[]\n /** Sobrescreve o comando de abertura local (Pencil). `{file}` é expandido. */\n openCommand?: string\n /**\n * HTML do protótipo salvo no repositório, servido pela plataforma para embutir\n * o protótipo em iframe. O canvas do Claude Design manda `frame-ancestors\n * 'self'` e não embute pela URL — o snapshot local resolve isso. Default:\n * `<designDir>/canvas.html`, quando existir.\n */\n snapshot?: string\n}\n\n/** Protótipo já resolvido (config global + override da feature). */\nexport type PrototypeResolved = PrototypeConfig & {\n /** De onde veio a declaração usada. */\n source: 'config' | 'feature'\n /** Feature cujo override foi aplicado, quando `source === 'feature'`. */\n feature?: string\n /** Pencil: caminho absoluto do `.pen`, quando ele existe no disco. */\n filePath?: string\n /** Pencil: `false` quando `file` está declarado mas não existe no disco. */\n fileExists?: boolean\n /** Caminho relativo do snapshot em uso (declarado ou o default do `designDir`). */\n snapshotPath?: string\n /** `true` quando há snapshot no disco — é o que habilita o iframe. */\n snapshotExists?: boolean\n}\n\nexport type JobStatus = 'running' | 'needs-input' | 'done' | 'failed' | 'cancelled'\n\nexport type JobSummary = {\n id: string\n kind: JobKind\n label: string\n feature?: string\n task?: string\n status: JobStatus\n pid: number\n startedAt: number\n endedAt?: number\n exitCode?: number\n bufferBytes: number\n needsInputHint?: string\n /**\n * true quando o registro veio do histórico em disco, de uma sessão anterior\n * do servidor. O processo não existe mais: dá para ler o terminal, não para\n * responder nele.\n */\n restored?: boolean\n}\n\nexport type JobWithBuffer = JobSummary & { buffer: string }\n\nexport type SpecsConfig = {\n agent: {\n /**\n * CLI padrão usada ao abrir os modais de execução. Deve ser uma chave de\n * `commands`. Persistida por sessão no browser via `localStorage`.\n */\n cli: AgentCli\n /**\n * Template de comando por CLI. A chave é o identificador da CLI (`claude`,\n * `cursor`, ...) e o valor o comando a ser disparado, com `{prompt}`, o\n * placeholder opcional `{model}` (expandido para `--model <id>` ou vazio) e o\n * token `feature-runner` (trocado pelo agent correspondente).\n */\n commands: Record<string, string>\n /**\n * Comando que lista os modelos de uma CLI dinamicamente (ex.: `cursor-agent\n * --list-models`). A saída é parseada linha a linha. Chave = id da CLI.\n */\n modelsCommand: Record<string, string>\n /**\n * Lista estática de modelos por CLI, usada como fallback (ou única fonte\n * quando a CLI não expõe listagem, ex.: Claude Code). Chave = id da CLI.\n */\n models: Record<string, string[]>\n /** Comando legado / fallback (= commands[cli]). Mantido para retrocompat. */\n command: string\n openTerminal: TerminalKind\n cwd: string\n scopes: Record<AgentScopeKey, string>\n defaultExecutionMode: ExecutionMode\n sound: boolean\n inputPromptPatterns: string[]\n bufferBytesCap: number\n }\n /**\n * Protótipo default do projeto. `null` quando o projeto não tem protótipo —\n * nesse caso a Specs Platform esconde o painel e os agents pulam a fase visual.\n */\n prototype: PrototypeConfig | null\n review: {\n /**\n * Comando que abre um arquivo no editor a partir da tela de review.\n * Placeholders: `{path}` (absoluto) e `{line}`. Default: Cursor.\n */\n openCommand: string\n }\n theme: 'dark'\n warnBelowWidth: number\n featuresDir: string\n discoveriesDir: string\n drawingsDir: string\n port: number\n}\n\nexport type StartServerOptions = {\n projectRoot: string\n /** Diretório com o build estático da UI. Ausente → só a API (UI via Vite em dev). */\n uiDir?: string\n}\n\nexport type StartedServer = {\n url: string\n port: number\n close: () => Promise<void>\n}\n\nexport type TaskNode = {\n slug: string\n title: string\n description?: string\n status: Status\n file: string\n}\n\nexport type FeatureNode = {\n slug: string\n title: string\n description?: string\n icon?: string\n status: Status\n tasks: TaskNode[]\n}\n\nexport type DiscoveryNode = {\n slug: string\n title: string\n type: DiscoveryType\n date?: string\n file: string\n}\n\nexport type DrawingNode = {\n slug: string\n title: string\n type: DrawingType\n date?: string\n file: string\n}\n\nexport type TreeResponse = {\n features: FeatureNode[]\n discoveries: DiscoveryNode[]\n drawings: DrawingNode[]\n}\n\nexport type Heading = { id: string; text: string; level: number }\n\nexport type ContentResponse = {\n frontmatter: {\n title?: string\n description?: string\n status: Status\n [key: string]: unknown\n }\n body: string\n headings: Heading[]\n raw: string\n}\n\nexport type DiscoveryContentResponse = {\n frontmatter: {\n title?: string\n type: DiscoveryType\n date?: string\n [key: string]: unknown\n }\n body: string\n headings: Heading[]\n raw: string\n}\n\nexport type DrawingContentResponse = {\n frontmatter: {\n title?: string\n type: DrawingType\n date?: string\n [key: string]: unknown\n }\n body: string\n headings: Heading[]\n raw: string\n}\n","import { readFileSync } from 'node:fs'\nimport path from 'node:path'\nimport * as p from '@clack/prompts'\nimport { defineTool, exists } from '@mir-code/toolkit-core'\nimport type { Command } from 'commander'\nimport { runInstall } from './commands/install.js'\nimport { runStart, runStatus, runStop } from './commands/start.js'\nimport { packageRoot, statuslineScript } from './paths.js'\n\nconst pkg = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf8')) as {\n name: string\n version: string\n description: string\n}\n\nfunction register(cmd: Command): void {\n cmd\n .command('install')\n .alias('update')\n .description(\n 'Instala ou atualiza a Specs Platform no projeto (.agents/, .specs/, symlinks, SPECS.md).',\n )\n .argument('[dir]', 'Raiz do projeto.', '.')\n .option('-f, --force', 'Sobrescreve também config, project.md, SPECS.md e scaffolds.', false)\n .option('--clean-legacy', 'Remove o .specs/app/ de instalações antigas.', false)\n .action(async (dir: string, opts: { force: boolean; cleanLegacy: boolean }) => {\n await runInstall({\n projectRoot: path.resolve(dir),\n force: opts.force,\n cleanLegacy: opts.cleanLegacy,\n })\n })\n\n cmd\n .command('start')\n .description('Sobe a UI + API (background por default) e abre o browser.')\n .option('-f, --foreground', 'Roda em foreground (Ctrl+C para parar).', false)\n .option('-p, --port <port>', 'Porta (default: `port` do .specs/config.json).')\n .option('--no-open', 'Não abre o browser.')\n .option('--api-only', 'Só a API, sem a UI (para desenvolver a UI com o Vite).', false)\n .action(\n async (opts: { foreground: boolean; port?: string; open: boolean; apiOnly: boolean }) => {\n await runStart({\n projectRoot: process.cwd(),\n foreground: opts.foreground,\n port: opts.port ? Number.parseInt(opts.port, 10) : undefined,\n openBrowser: opts.open,\n apiOnly: opts.apiOnly,\n })\n },\n )\n\n cmd\n .command('stop')\n .description('Para a instância em background deste projeto.')\n .action(() => runStop(process.cwd()))\n\n cmd\n .command('status')\n .description('Mostra se a instância em background deste projeto está rodando.')\n .action(() => runStatus(process.cwd()))\n\n cmd\n .command('statusline')\n .description('Mostra como plugar o medidor de uso do plano no statusLine do Claude Code.')\n .action(() => printStatusline())\n}\n\nfunction printStatusline() {\n console.log(\n 'Adicione em ~/.claude/settings.json (troque o argumento pelo seu statusLine atual, ou remova):\\n',\n )\n console.log(\n JSON.stringify(\n {\n statusLine: {\n type: 'command',\n command: `bash ${statuslineScript} ~/.claude/statusline-command.sh`,\n },\n },\n null,\n 2,\n ),\n )\n}\n\nasync function interactiveInstall(cwd: string) {\n const dir = await p.text({ message: 'Diretório do projeto', initialValue: cwd })\n if (p.isCancel(dir)) return\n const projectRoot = path.resolve(dir)\n\n let force = false\n if (await exists(path.join(projectRoot, '.specs', 'config.json'))) {\n const mode = await p.select({\n message: 'A Specs Platform já está instalada aqui. O que fazer?',\n options: [\n {\n value: 'update',\n label: 'Atualizar',\n hint: 'regrava agents/skills, preserva suas customizações',\n },\n {\n value: 'force',\n label: 'Reinstalar do zero',\n hint: 'sobrescreve config, project.md e SPECS.md',\n },\n ],\n })\n if (p.isCancel(mode)) return\n force = mode === 'force'\n }\n\n let cleanLegacy = false\n if (await exists(path.join(projectRoot, '.specs', 'app'))) {\n const answer = await p.confirm({\n message: 'Encontrei .specs/app/ de uma instalação antiga (não é mais usado). Remover?',\n })\n if (p.isCancel(answer)) return\n cleanLegacy = answer\n }\n\n await runInstall({ projectRoot, force, cleanLegacy })\n}\n\nexport const specsPlatformTool = defineTool({\n id: 'specs-platform',\n packageName: pkg.name,\n title: 'Specs Platform',\n description: pkg.description,\n version: pkg.version,\n register,\n actions: [\n {\n id: 'install',\n label: 'Instalar / atualizar no projeto',\n run: ({ cwd }) => interactiveInstall(cwd),\n },\n {\n id: 'start',\n label: 'Subir a UI',\n hint: 'background',\n run: ({ cwd }) => runStart({ projectRoot: cwd, foreground: false, openBrowser: true }),\n },\n { id: 'stop', label: 'Parar a UI', run: ({ cwd }) => runStop(cwd) },\n {\n id: 'statusline',\n label: 'Configurar medidor de uso do Claude',\n run: async () => printStatusline(),\n },\n ],\n})\n"],"mappings":"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","names":["p","stat","path","readFile","rm","writeFile","path","path","path","p","path","rm","readFile","writeFile","spawn","mkdir","readFile","rm","writeFile","path","path","readFile","rm","z","p","readFile","path","path","constants","access","readFile","stat","writeFile","mkdir","path","path","p","access","constants","stat","readFile","mkdir","writeFile","path","readFile","path","readFile","text","spawn","path","readFile","path","p","readFile","exists","log","raw","diff","truncated","path","spawn","readFile","path","readFile","spawn","path","jobs","text","p","path","jobs","result","path","z","slugSchema","path","readFile","p","rm","rootMetaPath","pc","path","mkdir","spawn","writeFile","rm","readFile","pc","readFileSync","path","readFileSync","path"]}
|