@jaimevalasek/aioson 1.5.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +729 -226
  3. package/docs/design-previews/aurora-command-ui-website.html +884 -0
  4. package/docs/design-previews/aurora-command-ui.html +682 -0
  5. package/docs/design-previews/bold-editorial-ui-website.html +658 -0
  6. package/docs/design-previews/bold-editorial-ui.html +717 -0
  7. package/docs/design-previews/clean-saas-ui-website.html +1202 -0
  8. package/docs/design-previews/clean-saas-ui.html +549 -0
  9. package/docs/design-previews/cognitive-core-ui-website.html +1009 -0
  10. package/docs/design-previews/cognitive-core-ui.html +463 -0
  11. package/docs/design-previews/glassmorphism-ui-website.html +572 -0
  12. package/docs/design-previews/glassmorphism-ui.html +886 -0
  13. package/docs/design-previews/index.html +699 -0
  14. package/docs/design-previews/interface-design-website.html +1187 -0
  15. package/docs/design-previews/interface-design.html +513 -0
  16. package/docs/design-previews/neo-brutalist-ui-website.html +621 -0
  17. package/docs/design-previews/neo-brutalist-ui.html +797 -0
  18. package/docs/design-previews/premium-command-center-ui-website.html +1217 -0
  19. package/docs/design-previews/premium-command-center-ui.html +552 -0
  20. package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
  21. package/docs/design-previews/warm-craft-ui-website.html +684 -0
  22. package/docs/design-previews/warm-craft-ui.html +739 -0
  23. package/docs/en/cli-reference.md +20 -9
  24. package/docs/integrations/sdlc-genius-boundary.md +76 -0
  25. package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
  26. package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
  27. package/docs/integrations/sdlc-genius-review-samples.md +86 -0
  28. package/docs/pt/README.md +10 -0
  29. package/docs/pt/agent-sharding.md +132 -0
  30. package/docs/pt/agentes.md +9 -2
  31. package/docs/pt/busca-de-contexto.md +129 -0
  32. package/docs/pt/cache-de-contexto.md +156 -0
  33. package/docs/pt/comandos-cli.md +915 -1
  34. package/docs/pt/design-hybrid-forge.md +356 -0
  35. package/docs/pt/devlog-pipeline.md +270 -0
  36. package/docs/pt/fluxo-artefatos.md +178 -0
  37. package/docs/pt/hooks-session-guard.md +454 -0
  38. package/docs/pt/inicio-rapido.md +54 -3
  39. package/docs/pt/inteligencia-adaptativa.md +324 -0
  40. package/docs/pt/monitor-de-contexto.md +158 -0
  41. package/docs/pt/recuperacao-de-sessao.md +125 -0
  42. package/docs/pt/sandbox.md +125 -0
  43. package/docs/pt/sdd-automation-scripts.md +557 -0
  44. package/docs/pt/site-forge.md +309 -0
  45. package/docs/pt/skills.md +98 -6
  46. package/docs/pt/spec-learnings-pipeline.md +265 -0
  47. package/package.json +1 -1
  48. package/src/a2a/client.js +165 -0
  49. package/src/a2a/server.js +223 -0
  50. package/src/agent-loader.js +280 -0
  51. package/src/cli.js +329 -1
  52. package/src/commands/agent-audit.js +397 -0
  53. package/src/commands/agent-export-skill.js +229 -0
  54. package/src/commands/agent-loader.js +85 -0
  55. package/src/commands/artifact-validate.js +189 -0
  56. package/src/commands/brief-gen.js +405 -0
  57. package/src/commands/brief-validate.js +65 -0
  58. package/src/commands/classify.js +256 -0
  59. package/src/commands/context-cache.js +90 -0
  60. package/src/commands/context-compact.js +49 -0
  61. package/src/commands/context-health.js +175 -0
  62. package/src/commands/context-monitor.js +163 -0
  63. package/src/commands/context-search.js +66 -0
  64. package/src/commands/context-trim.js +177 -0
  65. package/src/commands/design-hybrid-options.js +385 -0
  66. package/src/commands/detect-test-runner.js +55 -0
  67. package/src/commands/devlog-export-brains.js +27 -0
  68. package/src/commands/devlog-process.js +292 -0
  69. package/src/commands/devlog-watch.js +131 -0
  70. package/src/commands/feature-close.js +165 -0
  71. package/src/commands/gate-check.js +228 -0
  72. package/src/commands/health.js +214 -0
  73. package/src/commands/hooks-emit.js +253 -0
  74. package/src/commands/hooks-install.js +347 -0
  75. package/src/commands/init.js +54 -13
  76. package/src/commands/install.js +52 -13
  77. package/src/commands/learning-auto-promote.js +195 -0
  78. package/src/commands/learning-evolve.js +364 -0
  79. package/src/commands/learning-export.js +103 -0
  80. package/src/commands/learning-rollback.js +164 -0
  81. package/src/commands/live.js +59 -1
  82. package/src/commands/pattern-detect.js +33 -0
  83. package/src/commands/preflight-context.js +30 -0
  84. package/src/commands/preflight.js +208 -0
  85. package/src/commands/pulse-update.js +130 -0
  86. package/src/commands/recovery.js +43 -0
  87. package/src/commands/runner-daemon.js +274 -0
  88. package/src/commands/runner-plan.js +70 -0
  89. package/src/commands/runner-queue-from-plan.js +166 -0
  90. package/src/commands/runner-queue.js +189 -0
  91. package/src/commands/runner-run.js +129 -0
  92. package/src/commands/runtime.js +47 -1
  93. package/src/commands/sandbox.js +37 -0
  94. package/src/commands/self-implement-loop.js +256 -0
  95. package/src/commands/session-guard.js +218 -0
  96. package/src/commands/setup-context.js +22 -2
  97. package/src/commands/setup.js +178 -0
  98. package/src/commands/sizing.js +165 -0
  99. package/src/commands/skill.js +144 -32
  100. package/src/commands/spec-checkpoint.js +177 -0
  101. package/src/commands/spec-status.js +79 -0
  102. package/src/commands/spec-sync.js +190 -0
  103. package/src/commands/spec-tasks.js +288 -0
  104. package/src/commands/squad-autorun.js +1220 -0
  105. package/src/commands/squad-bus.js +217 -0
  106. package/src/commands/squad-card.js +149 -0
  107. package/src/commands/squad-daemon.js +134 -0
  108. package/src/commands/squad-dependency-graph.js +164 -0
  109. package/src/commands/squad-review.js +106 -0
  110. package/src/commands/squad-scaffold.js +55 -0
  111. package/src/commands/squad-tool-register.js +157 -0
  112. package/src/commands/state-save.js +122 -0
  113. package/src/commands/tool-registry-cmd.js +232 -0
  114. package/src/commands/update.js +9 -0
  115. package/src/commands/verify-gate.js +572 -0
  116. package/src/commands/workflow-execute.js +241 -0
  117. package/src/constants.js +18 -0
  118. package/src/context-cache.js +159 -0
  119. package/src/context-search.js +326 -0
  120. package/src/design-variation-catalog.js +503 -0
  121. package/src/i18n/messages/en.js +32 -2
  122. package/src/i18n/messages/es.js +30 -2
  123. package/src/i18n/messages/fr.js +30 -2
  124. package/src/i18n/messages/pt-BR.js +32 -2
  125. package/src/install-animation.js +260 -0
  126. package/src/install-profile.js +143 -0
  127. package/src/install-wizard.js +475 -0
  128. package/src/installer.js +44 -10
  129. package/src/lib/health-check.js +158 -0
  130. package/src/lib/hook-protocol.js +76 -0
  131. package/src/mcp/apps/squad-dashboard/app.js +163 -0
  132. package/src/mcp/apps/squad-dashboard/index.html +261 -0
  133. package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
  134. package/src/mcp/resources/squad-state.js +130 -0
  135. package/src/parser.js +7 -1
  136. package/src/preflight-engine.js +443 -0
  137. package/src/recovery-context-session.js +154 -0
  138. package/src/runner/cascade.js +97 -0
  139. package/src/runner/cli-launcher.js +109 -0
  140. package/src/runner/plan-importer.js +63 -0
  141. package/src/runner/queue-store.js +159 -0
  142. package/src/runtime-store.js +158 -4
  143. package/src/sandbox.js +177 -0
  144. package/src/squad/agent-teams-adapter.js +264 -0
  145. package/src/squad/brief-validator.js +350 -0
  146. package/src/squad/bus-bridge.js +140 -0
  147. package/src/squad/context-compactor.js +265 -0
  148. package/src/squad/cross-ai-synthesizer.js +250 -0
  149. package/src/squad/hooks-generator.js +196 -0
  150. package/src/squad/inter-squad-events.js +175 -0
  151. package/src/squad/intra-bus.js +345 -0
  152. package/src/squad/learning-extractor.js +213 -0
  153. package/src/squad/pattern-detector.js +365 -0
  154. package/src/squad/preflight-context.js +296 -0
  155. package/src/squad/recovery-context.js +242 -71
  156. package/src/squad/reflection.js +365 -0
  157. package/src/squad/squad-scaffold.js +177 -0
  158. package/src/squad/state-manager.js +310 -0
  159. package/src/squad/task-decomposer.js +652 -0
  160. package/src/squad/verify-gate.js +303 -0
  161. package/src/tool-executor.js +94 -0
  162. package/src/updater.js +10 -3
  163. package/src/worker-runner.js +186 -1
  164. package/template/.aioson/agents/analyst.md +119 -3
  165. package/template/.aioson/agents/architect.md +98 -0
  166. package/template/.aioson/agents/design-hybrid-forge.md +141 -0
  167. package/template/.aioson/agents/dev.md +335 -14
  168. package/template/.aioson/agents/deyvin.md +117 -2
  169. package/template/.aioson/agents/discovery-design-doc.md +44 -0
  170. package/template/.aioson/agents/genome.md +14 -0
  171. package/template/.aioson/agents/neo.md +78 -1
  172. package/template/.aioson/agents/orache.md +50 -4
  173. package/template/.aioson/agents/orchestrator.md +197 -1
  174. package/template/.aioson/agents/pm.md +93 -0
  175. package/template/.aioson/agents/product.md +77 -4
  176. package/template/.aioson/agents/profiler-enricher.md +14 -0
  177. package/template/.aioson/agents/profiler-forge.md +14 -0
  178. package/template/.aioson/agents/profiler-researcher.md +14 -0
  179. package/template/.aioson/agents/qa.md +249 -19
  180. package/template/.aioson/agents/setup.md +144 -12
  181. package/template/.aioson/agents/sheldon.md +237 -11
  182. package/template/.aioson/agents/site-forge.md +1753 -0
  183. package/template/.aioson/agents/squad.md +162 -0
  184. package/template/.aioson/agents/tester.md +209 -0
  185. package/template/.aioson/agents/ux-ui.md +34 -1
  186. package/template/.aioson/brains/README.md +128 -0
  187. package/template/.aioson/brains/_index.json +16 -0
  188. package/template/.aioson/brains/scripts/query.js +103 -0
  189. package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
  190. package/template/.aioson/config.md +158 -13
  191. package/template/.aioson/constitution.md +33 -0
  192. package/template/.aioson/context/forensics/.gitkeep +0 -0
  193. package/template/.aioson/context/project-pulse.md +34 -0
  194. package/template/.aioson/context/seeds/seed-example.md +27 -0
  195. package/template/.aioson/context/user-profile.md +42 -0
  196. package/template/.aioson/docs/LAYERS.md +79 -0
  197. package/template/.aioson/docs/README.md +76 -0
  198. package/template/.aioson/docs/example-external-api-context.md +72 -0
  199. package/template/.aioson/locales/en/agents/architect.md +17 -0
  200. package/template/.aioson/locales/en/agents/dev.md +79 -13
  201. package/template/.aioson/locales/en/agents/orache.md +6 -0
  202. package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
  203. package/template/.aioson/locales/en/agents/product.md +50 -0
  204. package/template/.aioson/locales/en/agents/setup.md +33 -1
  205. package/template/.aioson/locales/en/agents/sheldon.md +115 -0
  206. package/template/.aioson/locales/en/agents/squad.md +14 -0
  207. package/template/.aioson/locales/en/agents/tester.md +6 -0
  208. package/template/.aioson/locales/es/agents/analyst.md +2 -0
  209. package/template/.aioson/locales/es/agents/architect.md +19 -0
  210. package/template/.aioson/locales/es/agents/dev.md +64 -4
  211. package/template/.aioson/locales/es/agents/deyvin.md +2 -0
  212. package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
  213. package/template/.aioson/locales/es/agents/genome.md +2 -0
  214. package/template/.aioson/locales/es/agents/neo.md +2 -0
  215. package/template/.aioson/locales/es/agents/orache.md +2 -0
  216. package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
  217. package/template/.aioson/locales/es/agents/pair.md +2 -0
  218. package/template/.aioson/locales/es/agents/pm.md +2 -0
  219. package/template/.aioson/locales/es/agents/product.md +52 -0
  220. package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
  221. package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
  222. package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
  223. package/template/.aioson/locales/es/agents/qa.md +2 -0
  224. package/template/.aioson/locales/es/agents/setup.md +35 -1
  225. package/template/.aioson/locales/es/agents/sheldon.md +117 -0
  226. package/template/.aioson/locales/es/agents/squad.md +16 -0
  227. package/template/.aioson/locales/es/agents/tester.md +9 -0
  228. package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
  229. package/template/.aioson/locales/fr/agents/analyst.md +2 -0
  230. package/template/.aioson/locales/fr/agents/architect.md +19 -0
  231. package/template/.aioson/locales/fr/agents/dev.md +64 -4
  232. package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
  233. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
  234. package/template/.aioson/locales/fr/agents/genome.md +2 -0
  235. package/template/.aioson/locales/fr/agents/neo.md +2 -0
  236. package/template/.aioson/locales/fr/agents/orache.md +2 -0
  237. package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
  238. package/template/.aioson/locales/fr/agents/pair.md +2 -0
  239. package/template/.aioson/locales/fr/agents/pm.md +2 -0
  240. package/template/.aioson/locales/fr/agents/product.md +52 -0
  241. package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
  242. package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
  243. package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
  244. package/template/.aioson/locales/fr/agents/qa.md +2 -0
  245. package/template/.aioson/locales/fr/agents/setup.md +35 -1
  246. package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
  247. package/template/.aioson/locales/fr/agents/squad.md +16 -0
  248. package/template/.aioson/locales/fr/agents/tester.md +9 -0
  249. package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
  250. package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
  251. package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
  252. package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
  253. package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
  254. package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
  255. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
  256. package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
  257. package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
  258. package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
  259. package/template/.aioson/locales/pt-BR/agents/setup.md +134 -19
  260. package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
  261. package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
  262. package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
  263. package/template/.aioson/rules/README.md +69 -0
  264. package/template/.aioson/rules/data-format-convention.md +136 -0
  265. package/template/.aioson/rules/example-monetary-values.md +30 -0
  266. package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
  267. package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +243 -0
  268. package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -0
  269. package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -0
  270. package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -0
  271. package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -0
  272. package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -0
  273. package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +482 -0
  274. package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +387 -0
  275. package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +222 -0
  276. package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -0
  277. package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -0
  278. package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -0
  279. package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -0
  280. package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -0
  281. package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -0
  282. package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -0
  283. package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +213 -0
  284. package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -0
  285. package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -0
  286. package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -0
  287. package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -0
  288. package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -0
  289. package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -0
  290. package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -0
  291. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
  292. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
  293. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
  294. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
  295. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
  296. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
  297. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
  298. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +46 -0
  299. package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
  300. package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +109 -0
  301. package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
  302. package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +44 -0
  303. package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +37 -0
  304. package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
  305. package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
  306. package/template/.aioson/skills/process/aioson-spec-driven/references/hardening-lane.md +49 -0
  307. package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +101 -0
  308. package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
  309. package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
  310. package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
  311. package/template/.aioson/skills/process/aioson-spec-driven/references/ui-language.md +75 -0
  312. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +147 -0
  313. package/template/.aioson/skills/process/design-hybrid-forge/references/crossover-protocol.md +221 -0
  314. package/template/.aioson/skills/process/design-hybrid-forge/references/naming-registry.md +88 -0
  315. package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +306 -0
  316. package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +149 -0
  317. package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +208 -0
  318. package/template/.aioson/skills/process/design-hybrid-forge/references/variation-library.md +125 -0
  319. package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
  320. package/template/.aioson/skills/static/context-budget-guide.md +46 -0
  321. package/template/.aioson/skills/static/harness-sensors.md +74 -0
  322. package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
  323. package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
  324. package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
  325. package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
  326. package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
  327. package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
  328. package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
  329. package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
  330. package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
  331. package/template/.aioson/skills/static/threejs-patterns.md +929 -0
  332. package/template/.aioson/skills/static/web-research-cache.md +112 -0
  333. package/template/.aioson/tasks/implementation-plan.md +21 -1
  334. package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
  335. package/template/.claude/commands/aioson/agent/orache.md +5 -0
  336. package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
  337. package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
  338. package/template/AGENTS.md +75 -1
  339. package/template/CLAUDE.md +31 -0
  340. package/template/OPENCODE.md +4 -0
  341. package/template/researchs/.gitkeep +0 -0
@@ -0,0 +1,85 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const { AgentLoader } = require('../agent-loader');
5
+
6
+ async function runAgentLoad({ args, options, logger }) {
7
+ const agentId = args[0] || options.agent || '';
8
+ const goal = options.goal || '';
9
+ const cwd = path.resolve(process.cwd(), options.cwd || '.');
10
+ const agentsDir = path.join(cwd, options['agents-dir'] || '.aioson/agents');
11
+ const maxShards = Number(options['max-shards']) || 3;
12
+ const maxTokens = Number(options['max-tokens']) || 2000;
13
+
14
+ if (!agentId) {
15
+ logger.error('Usage: aioson agent:load <agent-id> --goal="..." [--cwd=.]');
16
+ return { ok: false, error: 'missing_agent' };
17
+ }
18
+
19
+ const loader = new AgentLoader();
20
+ await loader.open();
21
+
22
+ try {
23
+ // Index agents dir if needed
24
+ await loader.indexAgentsDir(agentsDir, { force: Boolean(options.force) });
25
+
26
+ // Load relevant shards
27
+ const result = await loader.loadRelevantShards(agentId, goal, { maxShards, maxTokens });
28
+
29
+ if (result.shards.length === 0) {
30
+ logger.log(`No shards found for agent: ${agentId}`);
31
+ logger.log(`Make sure the agents directory exists: ${agentsDir}`);
32
+ return { ok: true, agentId, shards: [], tokens: 0 };
33
+ }
34
+
35
+ if (options.json) {
36
+ return { ok: true, ...result };
37
+ }
38
+
39
+ logger.log(`\n Agent: ${agentId} (${result.shards.length}/${result.totalShards} shards, ${result.tokens} tokens)\n`);
40
+ for (const shard of result.shards) {
41
+ logger.log(` ## ${shard.heading} (${shard.tokens} tokens)`);
42
+ }
43
+ logger.log('');
44
+
45
+ if (options.print) {
46
+ logger.log('\n---\n');
47
+ logger.log(AgentLoader.buildContext(result.shards));
48
+ }
49
+
50
+ return { ok: true, ...result };
51
+ } finally {
52
+ loader.close();
53
+ }
54
+ }
55
+
56
+ async function runAgentShardIndex({ args, options, logger }) {
57
+ const cwd = path.resolve(process.cwd(), args[0] || '.');
58
+ const agentsDir = path.join(cwd, options['agents-dir'] || '.aioson/agents');
59
+ const force = Boolean(options.force);
60
+
61
+ logger.log(`Indexing agent shards from: ${agentsDir}`);
62
+
63
+ const loader = new AgentLoader();
64
+ await loader.open();
65
+
66
+ try {
67
+ const result = await loader.indexAgentsDir(agentsDir, { force });
68
+ const stats = loader.stats();
69
+
70
+ if (options.json) {
71
+ return { ok: true, ...result, stats };
72
+ }
73
+
74
+ logger.log(` Agents indexed: ${result.agents}`);
75
+ logger.log(` Total shards: ${result.totalShards}`);
76
+ logger.log(` Index total docs: ${stats.totalDocs}`);
77
+ logger.log('');
78
+
79
+ return { ok: true, ...result, stats };
80
+ } finally {
81
+ loader.close();
82
+ }
83
+ }
84
+
85
+ module.exports = { runAgentLoad, runAgentShardIndex };
@@ -0,0 +1,189 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson artifact:validate — validate the complete artifact chain for a feature.
5
+ *
6
+ * Checks all expected artifacts (prd → sheldon → requirements → spec →
7
+ * architecture → implementation-plan → conformance) and reports chain integrity.
8
+ *
9
+ * Usage:
10
+ * aioson artifact:validate . --feature=checkout
11
+ * aioson artifact:validate . --feature=checkout --json
12
+ */
13
+
14
+ const path = require('node:path');
15
+ const {
16
+ scanArtifacts,
17
+ detectClassification,
18
+ parseGatesFromSpec,
19
+ parseFrontmatter,
20
+ contextDir
21
+ } = require('../preflight-engine');
22
+
23
+ const BAR = '━'.repeat(45);
24
+
25
+ function gateDisplay(gates) {
26
+ const letters = { requirements: 'A', design: 'B', plan: 'C', execution: 'D' };
27
+ return Object.entries(letters).map(([name, letter]) => {
28
+ const status = gates[name];
29
+ return status === 'approved' ? `${letter}✓` : `${letter}○`;
30
+ }).join(' ');
31
+ }
32
+
33
+ async function runArtifactValidate({ args, options = {}, logger }) {
34
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
35
+ const slug = options.feature ? String(options.feature) : null;
36
+
37
+ if (!slug) {
38
+ if (options.json) return { ok: false, reason: 'missing_feature' };
39
+ logger.log('--feature=<slug> is required.');
40
+ return { ok: false };
41
+ }
42
+
43
+ const artifacts = await scanArtifacts(targetDir, slug);
44
+ const classification = await detectClassification(targetDir, slug);
45
+
46
+ // Gates from spec
47
+ const specGates = artifacts.spec.exists ? parseGatesFromSpec(artifacts.spec.content) : {};
48
+
49
+ // Spec details
50
+ const specFm = artifacts.spec.exists ? parseFrontmatter(artifacts.spec.content) : {};
51
+ const specVersion = specFm.version || null;
52
+ const specGateDisplay = artifacts.spec.exists ? gateDisplay(specGates) : null;
53
+
54
+ // Sheldon readiness
55
+ const sheldonReady = artifacts.sheldon_enrichment.exists
56
+ ? (artifacts.sheldon_enrichment.frontmatter.readiness === 'ready_for_downstream' ? 'ready_for_downstream' : 'present')
57
+ : null;
58
+
59
+ // Implementation plan status
60
+ const planStatus = artifacts.implementation_plan.exists
61
+ ? (artifacts.implementation_plan.frontmatter.status || 'present')
62
+ : null;
63
+
64
+ // Requirement count
65
+ let reqCount = null;
66
+ if (artifacts.requirements.exists && artifacts.requirements.content) {
67
+ const reqs = artifacts.requirements.content.match(/\bREQ[-\s]?\d+\b/g) || [];
68
+ const acs = artifacts.requirements.content.match(/\bAC[-\s]?\d+\b/g) || [];
69
+ reqCount = `${reqs.length} REQs, ${acs.length} ACs`;
70
+ }
71
+
72
+ // Conformance required?
73
+ const conformanceRequired = classification === 'MEDIUM';
74
+
75
+ // Build chain items
76
+ const chain = [
77
+ {
78
+ name: 'project.context.md',
79
+ exists: artifacts.project_context.exists,
80
+ detail: artifacts.project_context.exists ? `${artifacts.project_context.size}B` : null,
81
+ required: true,
82
+ indent: 0
83
+ },
84
+ {
85
+ name: `prd-${slug}.md`,
86
+ exists: artifacts.prd.exists,
87
+ detail: artifacts.prd.exists ? `${artifacts.prd.size}B` : null,
88
+ required: true,
89
+ indent: 0
90
+ },
91
+ {
92
+ name: `sheldon-enrichment-${slug}.md`,
93
+ exists: artifacts.sheldon_enrichment.exists,
94
+ detail: sheldonReady ? `readiness: ${sheldonReady}` : null,
95
+ required: false,
96
+ indent: 1
97
+ },
98
+ {
99
+ name: `requirements-${slug}.md`,
100
+ exists: artifacts.requirements.exists,
101
+ detail: reqCount,
102
+ required: true,
103
+ indent: 1
104
+ },
105
+ {
106
+ name: `spec-${slug}.md`,
107
+ exists: artifacts.spec.exists,
108
+ detail: artifacts.spec.exists ? `version: ${specVersion || '?'}, gates: ${specGateDisplay || '?'}` : null,
109
+ required: true,
110
+ indent: 1
111
+ },
112
+ {
113
+ name: 'architecture.md',
114
+ exists: artifacts.architecture.exists,
115
+ detail: null,
116
+ required: true,
117
+ indent: 1
118
+ },
119
+ {
120
+ name: `implementation-plan-${slug}.md`,
121
+ exists: artifacts.implementation_plan.exists,
122
+ detail: planStatus ? `status: ${planStatus}` : null,
123
+ required: true,
124
+ indent: 1
125
+ },
126
+ {
127
+ name: `conformance-${slug}.yaml`,
128
+ exists: artifacts.conformance.exists,
129
+ detail: !conformanceRequired ? `required for MEDIUM — NOT required for ${classification || 'SMALL'}` : null,
130
+ required: conformanceRequired,
131
+ indent: 1
132
+ }
133
+ ];
134
+
135
+ // Validate chain integrity
136
+ const missing = chain.filter((c) => c.required && !c.exists);
137
+ const missingOptional = chain.filter((c) => !c.required && !c.exists);
138
+
139
+ const valid = missing.length === 0;
140
+
141
+ const result = {
142
+ ok: valid,
143
+ feature: slug,
144
+ classification: classification || 'unknown',
145
+ chain: chain.map((c) => ({
146
+ name: c.name,
147
+ exists: c.exists,
148
+ required: c.required,
149
+ detail: c.detail
150
+ })),
151
+ missing_required: missing.map((c) => c.name),
152
+ missing_optional: missingOptional.map((c) => c.name),
153
+ integrity: valid ? 'VALID' : 'INVALID'
154
+ };
155
+
156
+ if (options.json) return result;
157
+
158
+ logger.log('');
159
+ logger.log(`Artifact Chain — ${slug}`);
160
+ logger.log(BAR);
161
+
162
+ for (const item of chain) {
163
+ const icon = item.exists ? '✓' : '✗';
164
+ const indent = ' '.repeat(item.indent) + (item.indent > 0 ? '→ ' : '');
165
+ const detail = item.detail ? ` (${item.detail})` : '';
166
+ logger.log(`${indent}${icon} ${item.name}${detail}`);
167
+ }
168
+
169
+ logger.log('');
170
+ logger.log(`Chain integrity: ${valid ? 'VALID' : 'INVALID'}`);
171
+
172
+ if (missing.length > 0) {
173
+ logger.log(`Missing required: ${missing.map((c) => c.name).join(', ')}`);
174
+ }
175
+
176
+ if (missingOptional.length > 0 && !valid) {
177
+ logger.log(`Missing optional: ${missingOptional.map((c) => c.name).join(', ')}`);
178
+ }
179
+
180
+ if (valid && missingOptional.length > 0) {
181
+ logger.log(`Missing optional: ${missingOptional.map((c) => c.name).join(', ')} (${classification || 'SMALL'} — acceptable)`);
182
+ }
183
+
184
+ logger.log('');
185
+
186
+ return result;
187
+ }
188
+
189
+ module.exports = { runArtifactValidate };
@@ -0,0 +1,405 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson brief:gen — Generate a 100% self-contained worker brief
5
+ *
6
+ * Reads the current implementation plan phase (or a named phase), combines
7
+ * it with the project architecture, spec, and any existing context files,
8
+ * and writes a fully self-contained brief that a worker can execute with
9
+ * zero additional lookups.
10
+ *
11
+ * Brief completeness checklist (from orchestrator.md):
12
+ * ✓ Phase name and goal
13
+ * ✓ Files to read before starting
14
+ * ✓ Files to create or modify
15
+ * ✓ Hard constraints (must not touch)
16
+ * ✓ Out-of-scope (what NOT to do)
17
+ * ✓ Done criteria (verifiable)
18
+ * ✓ Relevant excerpts from architecture / spec
19
+ *
20
+ * Usage:
21
+ * aioson brief:gen .
22
+ * aioson brief:gen . --phase=2 Target a specific plan phase
23
+ * aioson brief:gen . --plan=my-plan.md Use a specific plan file
24
+ * aioson brief:gen . --out=briefs/phase-2.md Override output path
25
+ * aioson brief:gen . --squad=content-team Target squad directory instead of .aioson/context
26
+ * aioson brief:gen . --executor=writer Target executor inside squad
27
+ * aioson brief:gen . --json JSON output
28
+ */
29
+
30
+ const fs = require('node:fs/promises');
31
+ const path = require('node:path');
32
+
33
+ // ─── File discovery helpers ───────────────────────────────────────────────────
34
+
35
+ async function tryRead(filePath) {
36
+ try {
37
+ return await fs.readFile(filePath, 'utf8');
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ async function findFile(candidates) {
44
+ for (const p of candidates) {
45
+ const content = await tryRead(p);
46
+ if (content !== null) return { path: p, content };
47
+ }
48
+ return null;
49
+ }
50
+
51
+ // ─── Plan parser ──────────────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * Parse phases from an implementation plan markdown.
55
+ * Phases are identified by ## or ### headings containing "Phase" or "Sprint" or
56
+ * "Step" followed by a number.
57
+ */
58
+ function parsePlanPhases(content) {
59
+ const lines = content.split(/\r?\n/);
60
+ const phases = [];
61
+ const phaseHeadingRe = /^#{1,4}\s+(?:Phase|Sprint|Step|Fase|Etapa)\s*(\d+)\b(.*)$/i;
62
+
63
+ let current = null;
64
+ let currentLines = [];
65
+
66
+ function flush() {
67
+ if (current !== null) {
68
+ phases.push({
69
+ number: current.number,
70
+ title: current.title,
71
+ content: currentLines.join('\n').trim()
72
+ });
73
+ }
74
+ }
75
+
76
+ for (const line of lines) {
77
+ const match = line.match(phaseHeadingRe);
78
+ if (match) {
79
+ flush();
80
+ current = {
81
+ number: parseInt(match[1], 10),
82
+ title: line.trim()
83
+ };
84
+ currentLines = [line];
85
+ } else if (current !== null) {
86
+ currentLines.push(line);
87
+ }
88
+ }
89
+ flush();
90
+
91
+ return phases;
92
+ }
93
+
94
+ /**
95
+ * Extract a named section (## heading) from markdown content.
96
+ * Returns the section body (without the heading line).
97
+ */
98
+ function extractSection(content, sectionPattern) {
99
+ const lines = content.split(/\r?\n/);
100
+ const re = new RegExp(`^#{1,4}\\s+.*${sectionPattern}.*$`, 'i');
101
+ let inSection = false;
102
+ let sectionLevel = 0;
103
+ const result = [];
104
+
105
+ for (const line of lines) {
106
+ const headingMatch = line.match(/^(#{1,4})\s+/);
107
+
108
+ if (!inSection) {
109
+ if (re.test(line)) {
110
+ inSection = true;
111
+ sectionLevel = headingMatch ? headingMatch[1].length : 2;
112
+ }
113
+ continue;
114
+ }
115
+
116
+ // Stop if we hit a heading of equal or higher level
117
+ if (headingMatch && headingMatch[1].length <= sectionLevel) {
118
+ break;
119
+ }
120
+ result.push(line);
121
+ }
122
+
123
+ return result.join('\n').trim();
124
+ }
125
+
126
+ // ─── Architecture excerpt extractor ──────────────────────────────────────────
127
+
128
+ const ARCH_SECTIONS = [
129
+ 'tech stack', 'stack', 'architecture', 'folder structure', 'directory',
130
+ 'conventions', 'database', 'api', 'services', 'modules', 'layers'
131
+ ];
132
+
133
+ function extractArchitectureExcerpts(archContent, maxChars = 3000) {
134
+ if (!archContent) return null;
135
+
136
+ // Try to pull relevant sections
137
+ const excerpts = [];
138
+ for (const keyword of ARCH_SECTIONS) {
139
+ const section = extractSection(archContent, keyword);
140
+ if (section.length > 50) {
141
+ excerpts.push(section);
142
+ }
143
+ if (excerpts.reduce((s, e) => s + e.length, 0) >= maxChars) break;
144
+ }
145
+
146
+ if (excerpts.length === 0) {
147
+ // Fall back to the first maxChars characters
148
+ return archContent.slice(0, maxChars) + (archContent.length > maxChars ? '\n\n[...truncated — read full file for details]' : '');
149
+ }
150
+
151
+ return excerpts.join('\n\n---\n\n');
152
+ }
153
+
154
+ // ─── Brief builder ────────────────────────────────────────────────────────────
155
+
156
+ function buildBrief({
157
+ phase,
158
+ planPath,
159
+ architectureExcerpt,
160
+ specExcerpt,
161
+ contextNote,
162
+ squadSlug,
163
+ executorSlug,
164
+ projectDir
165
+ }) {
166
+ const now = new Date().toISOString();
167
+ const relPlan = path.relative(projectDir, planPath);
168
+ const squadLine = squadSlug ? `Squad : ${squadSlug}` : null;
169
+ const executorLine = executorSlug ? `Executor : ${executorSlug}` : null;
170
+
171
+ const lines = [
172
+ '---',
173
+ `generated_at : ${now}`,
174
+ `plan_file : ${relPlan}`,
175
+ `phase : ${phase.number}`,
176
+ ...(squadLine ? [squadLine] : []),
177
+ ...(executorLine ? [executorLine] : []),
178
+ '---',
179
+ '',
180
+ `# Worker Brief — ${phase.title}`,
181
+ '',
182
+ '> This brief is 100% self-contained. Do not look up additional context.',
183
+ '> Read only the files listed in "Files to read". Write only the files listed in "Files to write".',
184
+ ''
185
+ ];
186
+
187
+ // Phase task block
188
+ lines.push('## Phase goal and tasks');
189
+ lines.push('');
190
+ lines.push(phase.content);
191
+ lines.push('');
192
+
193
+ // Architecture
194
+ if (architectureExcerpt) {
195
+ lines.push('## Architecture reference (excerpts)');
196
+ lines.push('');
197
+ lines.push(architectureExcerpt);
198
+ lines.push('');
199
+ }
200
+
201
+ // Spec
202
+ if (specExcerpt) {
203
+ lines.push('## Spec reference (excerpts)');
204
+ lines.push('');
205
+ lines.push(specExcerpt);
206
+ lines.push('');
207
+ }
208
+
209
+ // Context note
210
+ if (contextNote) {
211
+ lines.push('## Project context');
212
+ lines.push('');
213
+ lines.push(contextNote);
214
+ lines.push('');
215
+ }
216
+
217
+ // Done criteria placeholder (agent should fill in based on phase content)
218
+ lines.push('## Done criteria');
219
+ lines.push('');
220
+ lines.push('> Fill in the specific, verifiable done criteria for this phase before handing off.');
221
+ lines.push('> Example format:');
222
+ lines.push('> - [ ] `path/to/file.ts` exists and exports `FunctionName`');
223
+ lines.push('> - [ ] All existing tests pass (`npm test`)');
224
+ lines.push('> - [ ] No TypeScript errors (`tsc --noEmit`)');
225
+ lines.push('');
226
+
227
+ // Hard constraints placeholder
228
+ lines.push('## Hard constraints');
229
+ lines.push('');
230
+ lines.push('> Fill in what the worker MUST NOT touch or change.');
231
+ lines.push('> Example:');
232
+ lines.push('> - Do NOT modify `src/db/schema.ts` (owned by another phase)');
233
+ lines.push('> - Do NOT add new npm dependencies without coordinator approval');
234
+ lines.push('');
235
+
236
+ // Out of scope
237
+ lines.push('## Out of scope');
238
+ lines.push('');
239
+ lines.push('> Fill in what explicitly falls outside this phase.');
240
+ lines.push('> Example:');
241
+ lines.push('> - UI styling (handled in Phase 3)');
242
+ lines.push('> - Authentication (handled in Phase 4)');
243
+ lines.push('');
244
+
245
+ return lines.join('\n');
246
+ }
247
+
248
+ // ─── Main command ─────────────────────────────────────────────────────────────
249
+
250
+ async function runBriefGen({ args, options = {}, logger }) {
251
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
252
+ const phaseNumber = options.phase != null ? Number(options.phase) : null;
253
+ const squadSlug = String(options.squad || '').trim() || null;
254
+ const executorSlug = String(options.executor || '').trim() || null;
255
+
256
+ const contextDir = squadSlug
257
+ ? path.join(targetDir, '.aioson', 'squads', squadSlug)
258
+ : path.join(targetDir, '.aioson', 'context');
259
+
260
+ // ── Locate plan file ─────────────────────────────────────────────────────
261
+ let planFile;
262
+ if (options.plan) {
263
+ const explicit = path.resolve(targetDir, options.plan);
264
+ const content = await tryRead(explicit);
265
+ if (!content) {
266
+ logger.error(`Plan file not found: ${options.plan}`);
267
+ return { ok: false, error: 'plan_not_found' };
268
+ }
269
+ planFile = { path: explicit, content };
270
+ } else {
271
+ planFile = await findFile([
272
+ path.join(contextDir, 'implementation-plan.md'),
273
+ path.join(targetDir, '.aioson', 'context', 'implementation-plan.md'),
274
+ path.join(targetDir, 'plans', 'implementation-plan.md'),
275
+ path.join(targetDir, 'implementation-plan.md')
276
+ ]);
277
+ }
278
+
279
+ if (!planFile) {
280
+ logger.error('No implementation plan found. Run `aioson plan:show` or provide --plan=<path>.');
281
+ return { ok: false, error: 'no_plan' };
282
+ }
283
+
284
+ // ── Parse phases ─────────────────────────────────────────────────────────
285
+ const phases = parsePlanPhases(planFile.content);
286
+
287
+ if (phases.length === 0) {
288
+ logger.error(`No phases found in plan: ${path.relative(targetDir, planFile.path)}`);
289
+ logger.error('Phases must use headings like "## Phase 1 — description" or "## Sprint 2".');
290
+ return { ok: false, error: 'no_phases' };
291
+ }
292
+
293
+ // Pick target phase
294
+ let phase;
295
+ if (phaseNumber != null) {
296
+ phase = phases.find((p) => p.number === phaseNumber);
297
+ if (!phase) {
298
+ logger.error(`Phase ${phaseNumber} not found. Available: ${phases.map((p) => p.number).join(', ')}`);
299
+ return { ok: false, error: 'phase_not_found' };
300
+ }
301
+ } else {
302
+ // Default: first incomplete phase (or first phase)
303
+ phase = phases[0];
304
+ }
305
+
306
+ // ── Locate supporting files ───────────────────────────────────────────────
307
+ const [archFile, specFile, ctxFile] = await Promise.all([
308
+ findFile([
309
+ path.join(contextDir, 'architecture.md'),
310
+ path.join(targetDir, '.aioson', 'context', 'architecture.md'),
311
+ path.join(targetDir, 'docs', 'architecture.md'),
312
+ path.join(targetDir, 'ARCHITECTURE.md')
313
+ ]),
314
+ findFile([
315
+ path.join(contextDir, 'spec.md'),
316
+ path.join(targetDir, '.aioson', 'context', 'spec.md'),
317
+ path.join(targetDir, 'docs', 'spec.md'),
318
+ path.join(targetDir, 'SPEC.md')
319
+ ]),
320
+ findFile([
321
+ path.join(contextDir, 'project.context.md'),
322
+ path.join(targetDir, '.aioson', 'context', 'project.context.md')
323
+ ])
324
+ ]);
325
+
326
+ const architectureExcerpt = archFile
327
+ ? extractArchitectureExcerpts(archFile.content)
328
+ : null;
329
+
330
+ const specExcerpt = specFile
331
+ ? (specFile.content.length > 4000
332
+ ? specFile.content.slice(0, 4000) + '\n\n[...truncated — read full file for details]'
333
+ : specFile.content)
334
+ : null;
335
+
336
+ // Context: pull a short summary from project.context.md
337
+ const contextNote = ctxFile
338
+ ? extractSection(ctxFile.content, 'summary|overview|objetivo|goal') ||
339
+ ctxFile.content.slice(0, 800)
340
+ : null;
341
+
342
+ // ── Build brief ───────────────────────────────────────────────────────────
343
+ const briefContent = buildBrief({
344
+ phase,
345
+ planPath: planFile.path,
346
+ architectureExcerpt,
347
+ specExcerpt,
348
+ contextNote,
349
+ squadSlug,
350
+ executorSlug,
351
+ projectDir: targetDir
352
+ });
353
+
354
+ // ── Determine output path ─────────────────────────────────────────────────
355
+ let outPath;
356
+ if (options.out) {
357
+ outPath = path.resolve(targetDir, options.out);
358
+ } else {
359
+ const outDir = squadSlug
360
+ ? path.join(targetDir, '.aioson', 'squads', squadSlug, 'briefs')
361
+ : path.join(targetDir, '.aioson', 'context', 'briefs');
362
+ const executorSuffix = executorSlug ? `-${executorSlug}` : '';
363
+ outPath = path.join(outDir, `phase-${phase.number}${executorSuffix}.md`);
364
+ }
365
+
366
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
367
+ await fs.writeFile(outPath, briefContent, 'utf8');
368
+
369
+ const relOut = path.relative(targetDir, outPath);
370
+
371
+ if (options.json) {
372
+ return {
373
+ ok: true,
374
+ brief_path: relOut,
375
+ phase: phase.number,
376
+ phase_title: phase.title,
377
+ plan_file: path.relative(targetDir, planFile.path),
378
+ has_architecture: Boolean(architectureExcerpt),
379
+ has_spec: Boolean(specExcerpt),
380
+ has_context: Boolean(contextNote),
381
+ chars: briefContent.length,
382
+ tokens: Math.ceil(briefContent.length / 4)
383
+ };
384
+ }
385
+
386
+ logger.log('Brief generated');
387
+ logger.log('─'.repeat(60));
388
+ logger.log(`Phase : ${phase.number} — ${phase.title}`);
389
+ logger.log(`Plan : ${path.relative(targetDir, planFile.path)}`);
390
+ logger.log(`Architecture : ${archFile ? path.relative(targetDir, archFile.path) : '(not found)'}`);
391
+ logger.log(`Spec : ${specFile ? path.relative(targetDir, specFile.path) : '(not found)'}`);
392
+ logger.log(`Output : ${relOut}`);
393
+ logger.log(`Size : ${briefContent.length} chars (~${Math.ceil(briefContent.length / 4)} tokens)`);
394
+ logger.log('');
395
+ logger.log('Review the "Done criteria", "Hard constraints", and "Out of scope" sections');
396
+ logger.log('before handing the brief to a worker. These are left as placeholders intentionally.');
397
+
398
+ return {
399
+ ok: true,
400
+ brief_path: relOut,
401
+ phase: phase.number
402
+ };
403
+ }
404
+
405
+ module.exports = { runBriefGen };