@jaimevalasek/aioson 1.3.0 → 1.5.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.
Files changed (330) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/LICENSE +661 -21
  3. package/README.md +22 -3
  4. package/docs/en/squad-dashboard.md +372 -0
  5. package/docs/openclaw-bridge.md +308 -0
  6. package/docs/pt/README.md +62 -2
  7. package/docs/pt/advisor-spec.md +5 -5
  8. package/docs/pt/agentes-customizados.md +670 -0
  9. package/docs/pt/agentes.md +235 -23
  10. package/docs/pt/automacao-squads.md +407 -0
  11. package/docs/pt/cenarios.md +49 -5
  12. package/docs/pt/clientes-ai.md +62 -0
  13. package/docs/pt/comandos-cli.md +226 -17
  14. package/docs/pt/deyvin.md +115 -0
  15. package/docs/pt/genome-3.0-spec.md +11 -11
  16. package/docs/pt/inicio-rapido.md +63 -2
  17. package/docs/pt/memoria-contexto.md +255 -0
  18. package/docs/pt/output-strategy-delivery.md +655 -0
  19. package/docs/pt/profiler-system.md +17 -17
  20. package/docs/pt/runtime-observability.md +5 -1
  21. package/docs/pt/skills.md +175 -0
  22. package/docs/pt/squad-dashboard.md +373 -0
  23. package/docs/pt/{squad-genoma.md → squad-genome.md} +81 -75
  24. package/docs/testing/genome-2.0-matrix.md +5 -5
  25. package/docs/testing/genome-2.0-rollout.md +10 -10
  26. package/package.json +4 -4
  27. package/src/agents.js +21 -5
  28. package/src/backup-local.js +74 -0
  29. package/src/backup-provider.js +303 -0
  30. package/src/cli.js +276 -2
  31. package/src/commands/agents.js +22 -4
  32. package/src/commands/backup-local-cmd.js +25 -0
  33. package/src/commands/backup.js +533 -0
  34. package/src/commands/cloud.js +17 -17
  35. package/src/commands/context-pack.js +45 -0
  36. package/src/commands/implementation-plan.js +340 -0
  37. package/src/commands/learning.js +134 -0
  38. package/src/commands/live.js +1583 -0
  39. package/src/commands/runtime.js +1075 -2
  40. package/src/commands/scan-project.js +288 -24
  41. package/src/commands/setup-context.js +30 -2
  42. package/src/commands/skill.js +558 -0
  43. package/src/commands/squad-agent-create.js +788 -0
  44. package/src/commands/squad-daemon.js +209 -0
  45. package/src/commands/squad-dashboard.js +39 -0
  46. package/src/commands/squad-deploy.js +64 -0
  47. package/src/commands/squad-doctor.js +103 -1
  48. package/src/commands/squad-investigate.js +261 -0
  49. package/src/commands/squad-learning.js +209 -0
  50. package/src/commands/squad-mcp.js +270 -0
  51. package/src/commands/squad-pipeline.js +247 -1
  52. package/src/commands/squad-plan.js +329 -0
  53. package/src/commands/squad-processes.js +56 -0
  54. package/src/commands/squad-recovery.js +42 -0
  55. package/src/commands/squad-roi.js +291 -0
  56. package/src/commands/squad-score.js +250 -0
  57. package/src/commands/squad-status.js +38 -2
  58. package/src/commands/squad-validate.js +118 -1
  59. package/src/commands/squad-webhook.js +160 -0
  60. package/src/commands/squad-worker.js +191 -0
  61. package/src/commands/squad-worktrees.js +75 -0
  62. package/src/commands/test-agents.js +6 -1
  63. package/src/commands/web-map.js +70 -0
  64. package/src/commands/web-scrape.js +71 -0
  65. package/src/commands/workflow-next.js +8 -1
  66. package/src/commands/workflow-status.js +250 -0
  67. package/src/constants.js +88 -16
  68. package/src/context-memory.js +837 -0
  69. package/src/context-writer.js +47 -1
  70. package/src/delivery-runner.js +319 -0
  71. package/src/genome-files.js +1 -1
  72. package/src/genome-format.js +1 -1
  73. package/src/i18n/messages/en.js +333 -8
  74. package/src/i18n/messages/es.js +240 -6
  75. package/src/i18n/messages/fr.js +239 -5
  76. package/src/i18n/messages/pt-BR.js +330 -12
  77. package/src/installer.js +30 -2
  78. package/src/lib/genomes/compat.js +1 -1
  79. package/src/lib/webhook-server.js +328 -0
  80. package/src/mcp-connectors/registry.js +602 -0
  81. package/src/runtime-store.js +1037 -42
  82. package/src/session-handoff.js +77 -0
  83. package/src/squad/external-session.js +180 -0
  84. package/src/squad/inter-squad.js +74 -0
  85. package/src/squad/recovery-context.js +201 -0
  86. package/src/squad/worktree-manager.js +114 -0
  87. package/src/squad-daemon.js +490 -0
  88. package/src/squad-dashboard/api.js +223 -0
  89. package/src/squad-dashboard/attachment-handler.js +93 -0
  90. package/src/squad-dashboard/context-monitor.js +157 -0
  91. package/src/squad-dashboard/execution-logs.js +115 -0
  92. package/src/squad-dashboard/hunk-review.js +209 -0
  93. package/src/squad-dashboard/metrics.js +133 -0
  94. package/src/squad-dashboard/process-monitor.js +125 -0
  95. package/src/squad-dashboard/renderer.js +858 -0
  96. package/src/squad-dashboard/server.js +232 -0
  97. package/src/squad-dashboard/styles.js +525 -0
  98. package/src/squad-dashboard/token-tracker.js +99 -0
  99. package/src/web.js +284 -0
  100. package/src/worker-runner.js +339 -0
  101. package/template/.aioson/agents/analyst.md +40 -9
  102. package/template/.aioson/agents/architect.md +24 -5
  103. package/template/.aioson/agents/dev.md +254 -25
  104. package/template/.aioson/agents/deyvin.md +174 -0
  105. package/template/.aioson/agents/discovery-design-doc.md +25 -1
  106. package/template/.aioson/agents/{genoma.md → genome.md} +20 -20
  107. package/template/.aioson/agents/neo.md +152 -0
  108. package/template/.aioson/agents/orache.md +388 -0
  109. package/template/.aioson/agents/orchestrator.md +63 -2
  110. package/template/.aioson/agents/pair.md +5 -0
  111. package/template/.aioson/agents/pm.md +17 -5
  112. package/template/.aioson/agents/product.md +113 -29
  113. package/template/.aioson/agents/profiler-enricher.md +1 -1
  114. package/template/.aioson/agents/profiler-forge.md +9 -9
  115. package/template/.aioson/agents/profiler-researcher.md +1 -1
  116. package/template/.aioson/agents/qa.md +18 -5
  117. package/template/.aioson/agents/setup.md +138 -18
  118. package/template/.aioson/agents/sheldon.md +603 -0
  119. package/template/.aioson/agents/squad.md +866 -28
  120. package/template/.aioson/agents/tester.md +254 -0
  121. package/template/.aioson/agents/ux-ui.md +289 -34
  122. package/template/.aioson/config.md +181 -0
  123. package/template/.aioson/context/spec.md.template +17 -0
  124. package/template/.aioson/genomes/.gitkeep +0 -0
  125. package/template/.aioson/installed-skills/.gitkeep +0 -0
  126. package/template/.aioson/locales/en/agents/analyst.md +34 -4
  127. package/template/.aioson/locales/en/agents/architect.md +18 -0
  128. package/template/.aioson/locales/en/agents/dev.md +155 -11
  129. package/template/.aioson/locales/en/agents/deyvin.md +137 -0
  130. package/template/.aioson/locales/en/agents/{genoma.md → genome.md} +14 -14
  131. package/template/.aioson/locales/en/agents/neo.md +8 -0
  132. package/template/.aioson/locales/en/agents/orchestrator.md +62 -2
  133. package/template/.aioson/locales/en/agents/pair.md +5 -0
  134. package/template/.aioson/locales/en/agents/pm.md +7 -0
  135. package/template/.aioson/locales/en/agents/product.md +35 -17
  136. package/template/.aioson/locales/en/agents/qa.md +56 -0
  137. package/template/.aioson/locales/en/agents/setup.md +53 -6
  138. package/template/.aioson/locales/en/agents/sheldon.md +340 -0
  139. package/template/.aioson/locales/en/agents/squad.md +203 -15
  140. package/template/.aioson/locales/en/agents/ux-ui.md +383 -35
  141. package/template/.aioson/locales/es/agents/analyst.md +24 -4
  142. package/template/.aioson/locales/es/agents/architect.md +18 -0
  143. package/template/.aioson/locales/es/agents/dev.md +136 -9
  144. package/template/.aioson/locales/es/agents/deyvin.md +97 -0
  145. package/template/.aioson/locales/es/agents/{genoma.md → genome.md} +13 -13
  146. package/template/.aioson/locales/es/agents/neo.md +48 -0
  147. package/template/.aioson/locales/es/agents/orache.md +103 -0
  148. package/template/.aioson/locales/es/agents/orchestrator.md +62 -2
  149. package/template/.aioson/locales/es/agents/pair.md +5 -0
  150. package/template/.aioson/locales/es/agents/pm.md +7 -0
  151. package/template/.aioson/locales/es/agents/product.md +13 -3
  152. package/template/.aioson/locales/es/agents/qa.md +33 -0
  153. package/template/.aioson/locales/es/agents/setup.md +30 -6
  154. package/template/.aioson/locales/es/agents/sheldon.md +192 -0
  155. package/template/.aioson/locales/es/agents/squad.md +284 -15
  156. package/template/.aioson/locales/es/agents/ux-ui.md +34 -25
  157. package/template/.aioson/locales/fr/agents/analyst.md +24 -4
  158. package/template/.aioson/locales/fr/agents/architect.md +18 -0
  159. package/template/.aioson/locales/fr/agents/dev.md +136 -9
  160. package/template/.aioson/locales/fr/agents/deyvin.md +97 -0
  161. package/template/.aioson/locales/fr/agents/{genoma.md → genome.md} +7 -7
  162. package/template/.aioson/locales/fr/agents/neo.md +48 -0
  163. package/template/.aioson/locales/fr/agents/orache.md +104 -0
  164. package/template/.aioson/locales/fr/agents/orchestrator.md +62 -2
  165. package/template/.aioson/locales/fr/agents/pair.md +5 -0
  166. package/template/.aioson/locales/fr/agents/pm.md +7 -0
  167. package/template/.aioson/locales/fr/agents/product.md +13 -3
  168. package/template/.aioson/locales/fr/agents/qa.md +33 -0
  169. package/template/.aioson/locales/fr/agents/setup.md +30 -6
  170. package/template/.aioson/locales/fr/agents/sheldon.md +192 -0
  171. package/template/.aioson/locales/fr/agents/squad.md +279 -10
  172. package/template/.aioson/locales/fr/agents/ux-ui.md +34 -25
  173. package/template/.aioson/locales/pt-BR/agents/analyst.md +45 -4
  174. package/template/.aioson/locales/pt-BR/agents/architect.md +29 -0
  175. package/template/.aioson/locales/pt-BR/agents/dev.md +167 -15
  176. package/template/.aioson/locales/pt-BR/agents/deyvin.md +137 -0
  177. package/template/.aioson/locales/pt-BR/agents/{genoma.md → genome.md} +49 -49
  178. package/template/.aioson/locales/pt-BR/agents/neo.md +147 -0
  179. package/template/.aioson/locales/pt-BR/agents/orache.md +137 -0
  180. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +62 -2
  181. package/template/.aioson/locales/pt-BR/agents/pair.md +5 -0
  182. package/template/.aioson/locales/pt-BR/agents/pm.md +7 -0
  183. package/template/.aioson/locales/pt-BR/agents/product.md +43 -20
  184. package/template/.aioson/locales/pt-BR/agents/qa.md +67 -0
  185. package/template/.aioson/locales/pt-BR/agents/setup.md +53 -6
  186. package/template/.aioson/locales/pt-BR/agents/sheldon.md +192 -0
  187. package/template/.aioson/locales/pt-BR/agents/squad.md +591 -47
  188. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +369 -22
  189. package/template/.aioson/my-agents/.gitkeep +0 -0
  190. package/template/.aioson/rules/.gitkeep +0 -0
  191. package/template/.aioson/rules/squad/.gitkeep +0 -0
  192. package/template/.aioson/rules/squad/README.md +50 -0
  193. package/template/.aioson/schemas/genome-meta.schema.json +1 -1
  194. package/template/.aioson/schemas/genome.schema.json +1 -1
  195. package/template/.aioson/schemas/squad-blueprint.schema.json +32 -0
  196. package/template/.aioson/schemas/squad-manifest.schema.json +434 -1
  197. package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +205 -0
  198. package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -0
  199. package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -0
  200. package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -0
  201. package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -0
  202. package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -0
  203. package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -0
  204. package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -0
  205. package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +210 -0
  206. package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -0
  207. package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -0
  208. package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -0
  209. package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -0
  210. package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -0
  211. package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -0
  212. package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -0
  213. package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +203 -0
  214. package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -0
  215. package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +407 -0
  216. package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +272 -0
  217. package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +524 -0
  218. package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +277 -0
  219. package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +289 -0
  220. package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +437 -0
  221. package/template/.aioson/skills/design/interface-design/SKILL.md +47 -0
  222. package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -0
  223. package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -0
  224. package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +71 -0
  225. package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -0
  226. package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -0
  227. package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +62 -0
  228. package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -0
  229. package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -0
  230. package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -0
  231. package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -0
  232. package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +209 -0
  233. package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -0
  234. package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -0
  235. package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -0
  236. package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -0
  237. package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -0
  238. package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -0
  239. package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -0
  240. package/template/.aioson/skills/design-system/SKILL.md +92 -0
  241. package/template/.aioson/skills/design-system/cognitive-core-ui.skill +0 -0
  242. package/template/.aioson/skills/design-system/components/SKILL.md +274 -0
  243. package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
  244. package/template/.aioson/skills/design-system/dashboards/SKILL.md +184 -0
  245. package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
  246. package/template/.aioson/skills/design-system/foundations/SKILL.md +250 -0
  247. package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
  248. package/template/.aioson/skills/design-system/motion/SKILL.md +197 -0
  249. package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
  250. package/template/.aioson/skills/design-system/patterns/SKILL.md +231 -0
  251. package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
  252. package/template/.aioson/skills/premium-visual-design/SKILL.md +83 -0
  253. package/template/.aioson/skills/premium-visual-design/components/agent-badge.md +92 -0
  254. package/template/.aioson/skills/premium-visual-design/components/dependency-node.md +102 -0
  255. package/template/.aioson/skills/premium-visual-design/components/mention-autocomplete.md +136 -0
  256. package/template/.aioson/skills/premium-visual-design/components/notification-center.md +136 -0
  257. package/template/.aioson/skills/premium-visual-design/components/review-action-bar.md +188 -0
  258. package/template/.aioson/skills/premium-visual-design/components/team-switcher.md +131 -0
  259. package/template/.aioson/skills/premium-visual-design/patterns/agent-message-thread.md +198 -0
  260. package/template/.aioson/skills/premium-visual-design/patterns/notification-panel.md +275 -0
  261. package/template/.aioson/skills/premium-visual-design/patterns/review-workflow-ui.md +234 -0
  262. package/template/.aioson/skills/premium-visual-design/patterns/task-dependency-graph.md +147 -0
  263. package/template/.aioson/skills/premium-visual-design/tokens/status-extended.md +142 -0
  264. package/template/.aioson/skills/squad/SKILL.md +58 -0
  265. package/template/.aioson/skills/squad/domains/.gitkeep +0 -0
  266. package/template/.aioson/skills/squad/formats/.gitkeep +0 -0
  267. package/template/.aioson/skills/squad/formats/catalog.json +15 -0
  268. package/template/.aioson/skills/squad/formats/content/blog-post.md +47 -0
  269. package/template/.aioson/skills/squad/formats/content/newsletter.md +47 -0
  270. package/template/.aioson/skills/squad/formats/creative/podcast-script.md +43 -0
  271. package/template/.aioson/skills/squad/formats/creative/video-script.md +41 -0
  272. package/template/.aioson/skills/squad/formats/social/instagram-feed.md +42 -0
  273. package/template/.aioson/skills/squad/formats/social/linkedin-post.md +42 -0
  274. package/template/.aioson/skills/squad/formats/social/tiktok.md +39 -0
  275. package/template/.aioson/skills/squad/formats/social/twitter-thread.md +39 -0
  276. package/template/.aioson/skills/squad/formats/social/youtube-long.md +47 -0
  277. package/template/.aioson/skills/squad/formats/social/youtube-shorts.md +39 -0
  278. package/template/.aioson/skills/squad/patterns/.gitkeep +0 -0
  279. package/template/.aioson/skills/squad/patterns/multi-platform-pattern.md +108 -0
  280. package/template/.aioson/skills/squad/patterns/persona-based-pattern.md +98 -0
  281. package/template/.aioson/skills/squad/patterns/pipeline-pattern.md +106 -0
  282. package/template/.aioson/skills/squad/patterns/review-loop-pattern.md +81 -0
  283. package/template/.aioson/skills/squad/references/.gitkeep +0 -0
  284. package/template/.aioson/skills/squad/references/checklist-templates.md +122 -0
  285. package/template/.aioson/skills/squad/references/executor-archetypes.md +123 -0
  286. package/template/.aioson/skills/squad/references/workflow-templates.md +169 -0
  287. package/template/.aioson/skills/static/debugging-protocol.md +42 -0
  288. package/template/.aioson/skills/static/git-worktrees.md +36 -0
  289. package/template/.aioson/tasks/implementation-plan.md +307 -0
  290. package/template/.aioson/tasks/squad-create.md +1 -1
  291. package/template/.aioson/tasks/squad-design.md +28 -0
  292. package/template/.aioson/tasks/squad-execution-plan.md +279 -0
  293. package/template/.aioson/tasks/squad-export.md +1 -1
  294. package/template/.aioson/tasks/squad-investigate.md +44 -0
  295. package/template/.aioson/tasks/squad-learning-review.md +44 -0
  296. package/template/.aioson/tasks/squad-output-config.md +177 -0
  297. package/template/.aioson/tasks/squad-profile.md +48 -0
  298. package/template/.aioson/tasks/squad-review.md +61 -0
  299. package/template/.aioson/tasks/squad-task-decompose.md +66 -0
  300. package/template/.aioson/tasks/squad-validate.md +1 -1
  301. package/template/.claude/commands/aioson/agent/deyvin.md +5 -0
  302. package/template/.claude/commands/aioson/agent/discovery-design-doc.md +5 -0
  303. package/template/.claude/commands/aioson/agent/genome.md +5 -0
  304. package/template/.claude/commands/aioson/agent/neo.md +5 -0
  305. package/template/.claude/commands/aioson/agent/product.md +5 -0
  306. package/template/.claude/commands/aioson/agent/profiler-enricher.md +5 -0
  307. package/template/.claude/commands/aioson/agent/profiler-forge.md +5 -0
  308. package/template/.claude/commands/aioson/agent/profiler-researcher.md +5 -0
  309. package/template/.claude/commands/aioson/agent/squad.md +5 -0
  310. package/template/.claude/commands/aioson/agent/tester.md +5 -0
  311. package/template/.gemini/GEMINI.md +3 -0
  312. package/template/.gemini/commands/aios-deyvin.toml +6 -0
  313. package/template/.gemini/commands/aios-neo.toml +4 -0
  314. package/template/.gemini/commands/aios-pair.toml +6 -0
  315. package/template/.gemini/commands/aios-tester.toml +6 -0
  316. package/template/AGENTS.md +37 -6
  317. package/template/CLAUDE.md +34 -4
  318. package/template/OPENCODE.md +8 -2
  319. package/template/squad-searches/.gitkeep +0 -0
  320. package/template/.aioson/skills/static/interface-design.md +0 -372
  321. package/template/.aioson/skills/static/premium-command-center-ui.md +0 -190
  322. /package/template/.aioson/{genomas → docs}/.gitkeep +0 -0
  323. /package/template/.claude/commands/aioson/{analyst.md → agent/analyst.md} +0 -0
  324. /package/template/.claude/commands/aioson/{architect.md → agent/architect.md} +0 -0
  325. /package/template/.claude/commands/aioson/{dev.md → agent/dev.md} +0 -0
  326. /package/template/.claude/commands/aioson/{orchestrator.md → agent/orchestrator.md} +0 -0
  327. /package/template/.claude/commands/aioson/{pm.md → agent/pm.md} +0 -0
  328. /package/template/.claude/commands/aioson/{qa.md → agent/qa.md} +0 -0
  329. /package/template/.claude/commands/aioson/{setup.md → agent/setup.md} +0 -0
  330. /package/template/.claude/commands/aioson/{ux-ui.md → agent/ux-ui.md} +0 -0
@@ -64,6 +64,18 @@ async function validateStructure(projectDir, slug, manifest) {
64
64
  }
65
65
  }
66
66
 
67
+ // Check api_endpoints workers
68
+ const apiEndpoints = Array.isArray(manifest.api_endpoints) ? manifest.api_endpoints : [];
69
+ for (const ep of apiEndpoints) {
70
+ if (ep.worker) {
71
+ const workerDir = path.join(squadDir, 'workers', ep.worker);
72
+ if (!(await pathExists(workerDir))) {
73
+ const rel = path.relative(projectDir, workerDir).replace(/\\/g, '/');
74
+ errors.push(`api_endpoints: worker "${ep.worker}" not found at ${rel}`);
75
+ }
76
+ }
77
+ }
78
+
67
79
  // Check output dir (warning only)
68
80
  const outputDir = path.join(projectDir, 'output', slug);
69
81
  if (!(await pathExists(outputDir))) {
@@ -142,7 +154,111 @@ async function validateSemanticDeep(projectDir, slug, manifest) {
142
154
  }
143
155
  } catch { warnings.push('AGENTS.md not found'); }
144
156
 
145
- // 5. Readiness não contradiz blockers
157
+ // 5. Output strategy validation
158
+ const outputStrategy = manifest.outputStrategy && typeof manifest.outputStrategy === 'object'
159
+ ? manifest.outputStrategy
160
+ : null;
161
+
162
+ if (outputStrategy) {
163
+ const validModes = ['files', 'sqlite', 'hybrid'];
164
+ if (outputStrategy.mode && !validModes.includes(outputStrategy.mode)) {
165
+ errors.push(`Invalid outputStrategy.mode: "${outputStrategy.mode}" (expected: ${validModes.join(', ')})`);
166
+ }
167
+
168
+ const delivery = outputStrategy.delivery && typeof outputStrategy.delivery === 'object'
169
+ ? outputStrategy.delivery
170
+ : null;
171
+
172
+ if (delivery) {
173
+ const webhooks = Array.isArray(delivery.webhooks) ? delivery.webhooks : [];
174
+ for (const wh of webhooks) {
175
+ if (!wh.slug) {
176
+ errors.push('Webhook missing required "slug" field');
177
+ }
178
+ if (!wh.trigger) {
179
+ errors.push(`Webhook "${wh.slug || '?'}" missing required "trigger" field`);
180
+ }
181
+ const validTriggers = ['on-publish', 'on-create', 'manual'];
182
+ if (wh.trigger && !validTriggers.includes(wh.trigger)) {
183
+ warnings.push(`Webhook "${wh.slug}" has unknown trigger: "${wh.trigger}"`);
184
+ }
185
+ if (wh.url && wh.url.includes('{{ENV:')) {
186
+ const envMatch = wh.url.match(/\{\{ENV:(\w+)\}\}/);
187
+ if (envMatch && !process.env[envMatch[1]]) {
188
+ warnings.push(`Webhook "${wh.slug}" references unset env var: ${envMatch[1]}`);
189
+ }
190
+ }
191
+ if (wh.worker) {
192
+ const workerPath = path.join(projectDir, wh.worker);
193
+ if (!(await pathExists(workerPath))) {
194
+ warnings.push(`Webhook "${wh.slug}" worker not found: ${wh.worker}`);
195
+ }
196
+ }
197
+ }
198
+
199
+ if (delivery.autoPublish && webhooks.length === 0 && !delivery.cloudPublish) {
200
+ warnings.push('autoPublish is enabled but no webhooks or cloudPublish configured');
201
+ }
202
+ }
203
+
204
+ if (outputStrategy.mode === 'files' && outputStrategy.dataOutput && outputStrategy.dataOutput.enabled) {
205
+ warnings.push('outputStrategy.mode is "files" but dataOutput.enabled is true — consider "hybrid"');
206
+ }
207
+ if (outputStrategy.mode === 'sqlite' && outputStrategy.fileOutput && outputStrategy.fileOutput.enabled) {
208
+ warnings.push('outputStrategy.mode is "sqlite" but fileOutput.enabled is true — consider "hybrid"');
209
+ }
210
+ }
211
+
212
+ // 6. Task decomposition validation
213
+ for (const exec of executors) {
214
+ const tasks = Array.isArray(exec.tasks) ? exec.tasks : [];
215
+ if (tasks.length > 0) {
216
+ const orders = tasks.map(t => t.order).sort((a, b) => a - b);
217
+ for (let i = 0; i < orders.length; i++) {
218
+ if (orders[i] !== i + 1) {
219
+ warnings.push(`Executor "${exec.slug}": task order is not sequential (expected ${i + 1}, got ${orders[i]})`);
220
+ break;
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+ // 6b. Model tiering validation
227
+ for (const exec of executors) {
228
+ if (exec.usesLLM === false && exec.modelTier && exec.modelTier !== 'none') {
229
+ warnings.push(`Executor "${exec.slug}": usesLLM is false but modelTier is "${exec.modelTier}" (expected "none")`);
230
+ }
231
+ if (exec.type === 'worker' && exec.modelTier && exec.modelTier !== 'none') {
232
+ warnings.push(`Executor "${exec.slug}": type is "worker" but modelTier is "${exec.modelTier}" (expected "none")`);
233
+ }
234
+ }
235
+
236
+ // 7. Review loop validation
237
+ const workflows = Array.isArray(manifest.workflows) ? manifest.workflows : [];
238
+ const executorSlugs = executors.map(e => e.slug);
239
+ for (const wf of workflows) {
240
+ const phases = Array.isArray(wf.phases) ? wf.phases : [];
241
+ const phaseIds = phases.map(p => p.id);
242
+ for (const phase of phases) {
243
+ if (phase.review) {
244
+ const rv = phase.review;
245
+ if (rv.reviewer && !executorSlugs.includes(rv.reviewer)) {
246
+ errors.push(`Workflow "${wf.slug}" phase "${phase.id}": reviewer "${rv.reviewer}" is not a declared executor`);
247
+ }
248
+ if (rv.onReject && !phaseIds.includes(rv.onReject)) {
249
+ errors.push(`Workflow "${wf.slug}" phase "${phase.id}": onReject target "${rv.onReject}" is not a valid phase ID`);
250
+ }
251
+ if (rv.reviewer && rv.reviewer === phase.executor) {
252
+ warnings.push(`Workflow "${wf.slug}" phase "${phase.id}": reviewer should not be the same as the creator executor`);
253
+ }
254
+ }
255
+ if (phase.review && (!phase.vetoConditions || phase.vetoConditions.length === 0)) {
256
+ warnings.push(`Workflow "${wf.slug}" phase "${phase.id}": has review but no vetoConditions — consider adding veto guards`);
257
+ }
258
+ }
259
+ }
260
+
261
+ // 7. Readiness não contradiz blockers
146
262
  if (manifest.readiness) {
147
263
  for (const [dim, val] of Object.entries(manifest.readiness)) {
148
264
  if (val && val.status === 'ready' && val.blocker) {
@@ -207,6 +323,7 @@ async function runSquadValidate({ args = [], options = {}, logger = console } =
207
323
  logger.log(` Structure: ${structure.errors.length === 0 ? '\u2705 PASS' : '\u274c FAIL'}`);
208
324
  logger.log(` Semantics: ${semantics.errors.length === 0 ? (semantics.warnings.length > 0 ? '\u26a0\ufe0f WARNINGS' : '\u2705 PASS') : '\u274c FAIL'}`);
209
325
  logger.log(` Semantic deep: ${semanticDeep.errors.length === 0 ? (semanticDeep.warnings.length > 0 ? '\u26a0\ufe0f WARNINGS' : '\u2705 PASS') : '\u274c FAIL'}`);
326
+ logger.log(` Output strategy: ${manifest.outputStrategy ? `${manifest.outputStrategy.mode || 'unknown'} mode` : 'not configured'}`);
210
327
 
211
328
  if (allErrors.length > 0) {
212
329
  logger.log('');
@@ -0,0 +1,160 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const fs = require('node:fs/promises');
5
+ const { WebhookServer } = require('../lib/webhook-server');
6
+ const { getCliVersionSync } = require('../version');
7
+ const { listWorkers, runWorker } = require('../worker-runner');
8
+ const {
9
+ loadSession,
10
+ appendTurn,
11
+ buildContextualInput,
12
+ cleanExpiredSessions
13
+ } = require('../squad/external-session');
14
+
15
+ const SQUADS_DIR = path.join('.aioson', 'squads');
16
+
17
+ async function discoverSquads(projectDir) {
18
+ const squadsDir = path.join(projectDir, SQUADS_DIR);
19
+ let entries;
20
+ try {
21
+ entries = await fs.readdir(squadsDir, { withFileTypes: true });
22
+ } catch {
23
+ return [];
24
+ }
25
+ return entries.filter(e => e.isDirectory()).map(e => e.name);
26
+ }
27
+
28
+ async function executeSquad(projectDir, squadSlug, contextualInput) {
29
+ const workers = await listWorkers(projectDir, squadSlug);
30
+ if (workers.length === 0) {
31
+ throw new Error(`No workers found in squad "${squadSlug}"`);
32
+ }
33
+
34
+ // Run the first eligible worker as the squad entry point
35
+ for (const worker of workers) {
36
+ const result = await runWorker(
37
+ projectDir,
38
+ squadSlug,
39
+ worker.slug,
40
+ { input: contextualInput },
41
+ { triggerType: 'webhook' }
42
+ );
43
+ if (result.ok) {
44
+ const out = result.output;
45
+ return typeof out === 'string' ? out : JSON.stringify(out);
46
+ }
47
+ }
48
+
49
+ throw new Error(`All workers in squad "${squadSlug}" failed`);
50
+ }
51
+
52
+ async function handleStart(projectDir, options, { logger }) {
53
+ const port = parseInt(options.port || process.env.AIOSON_WEBHOOK_PORT || '3210', 10);
54
+ const token = options.token || process.env.AIOSON_WEBHOOK_TOKEN || '';
55
+ const ttlHours = parseInt(options.sessionTtl || process.env.AIOSON_SESSION_TTL_HOURS || '24', 10);
56
+ const version = getCliVersionSync();
57
+
58
+ if (!token) {
59
+ logger.error('Warning: AIOSON_WEBHOOK_TOKEN not set — server running without authentication.');
60
+ }
61
+
62
+ // Clean up expired sessions on startup
63
+ const cleaned = await cleanExpiredSessions(projectDir, ttlHours);
64
+ if (cleaned > 0) logger.log(`Cleaned ${cleaned} expired session(s).`);
65
+
66
+ const slugs = await discoverSquads(projectDir);
67
+ const squads = slugs.map(name => ({ name, timeout_ms: 120000 }));
68
+
69
+ const server = new WebhookServer({
70
+ port,
71
+ token,
72
+ squads,
73
+ version,
74
+ onTrigger: async ({ squad, input, session_id, metadata }) => {
75
+ // Load prior session context (if any)
76
+ const session = session_id
77
+ ? await loadSession(projectDir, session_id, ttlHours)
78
+ : null;
79
+
80
+ const contextualInput = buildContextualInput(session, input);
81
+
82
+ // Save user turn before execution
83
+ if (session_id) {
84
+ await appendTurn(projectDir, session_id, 'user', input, metadata || {}, ttlHours);
85
+ }
86
+
87
+ const response = await executeSquad(projectDir, squad, contextualInput);
88
+
89
+ // Save assistant turn after execution
90
+ if (session_id) {
91
+ await appendTurn(projectDir, session_id, 'assistant', response, {}, ttlHours);
92
+ }
93
+
94
+ return { response };
95
+ },
96
+ onQuery: async ({ squad, query, max_results }) => {
97
+ const raw = await executeSquad(projectDir, squad, query);
98
+ // Best-effort: if the output is JSON, parse and slice; otherwise wrap as single result
99
+ let results;
100
+ try {
101
+ const parsed = JSON.parse(raw);
102
+ results = Array.isArray(parsed) ? parsed.slice(0, max_results) : [parsed];
103
+ } catch {
104
+ results = [{ text: raw }];
105
+ }
106
+ return { results };
107
+ }
108
+ });
109
+
110
+ await server.start();
111
+
112
+ logger.log(`AIOSON squad webhook server started on port ${port}`);
113
+ if (squads.length > 0) {
114
+ logger.log(`Available squads: ${squads.map(s => s.name).join(', ')}`);
115
+ } else {
116
+ logger.log('No squads discovered in .aioson/squads/');
117
+ }
118
+ logger.log('Endpoints: POST /trigger GET /status/:run_id GET /health');
119
+ logger.log('Press Ctrl+C to stop.');
120
+
121
+ process.on('SIGINT', async () => {
122
+ await server.stop();
123
+ process.exit(0);
124
+ });
125
+ process.on('SIGTERM', async () => {
126
+ await server.stop();
127
+ process.exit(0);
128
+ });
129
+
130
+ // Keep the process alive until signal
131
+ await new Promise(() => {});
132
+ }
133
+
134
+ function handleConfig(options, { logger }) {
135
+ const channel = options.channel || 'whatsapp';
136
+ const squad = options.squad || 'atendimento';
137
+ const port = options.port || '3210';
138
+
139
+ logger.log(`OpenClaw configuration for squad "${squad}" via ${channel}:\n`);
140
+ logger.log(`hooks:\n ${channel}:\n auto_reply:\n - pattern: ".*"\n action: webhook\n url: "http://SEU_SERVIDOR:${port}/trigger"\n headers:\n Authorization: "Bearer \${AIOSON_WEBHOOK_TOKEN}"\n body_template: |\n {\n "squad": "${squad}",\n "input": "{{message.text}}",\n "session_id": "${channel}:{{message.from}}",\n "callback_url": "{{openclaw.callback_url}}",\n "metadata": {\n "channel": "${channel}",\n "phone": "{{message.from}}",\n "user_name": "{{message.contact_name}}"\n }\n }`);
141
+
142
+ return { ok: true };
143
+ }
144
+
145
+ async function runSquadWebhook({ args, options, logger }) {
146
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
147
+ const sub = options.sub || 'start';
148
+
149
+ switch (sub) {
150
+ case 'start':
151
+ return handleStart(targetDir, options, { logger });
152
+ case 'config':
153
+ return handleConfig(options, { logger });
154
+ default:
155
+ logger.error(`Unknown subcommand: "${sub}". Use: start, config`);
156
+ return { ok: false };
157
+ }
158
+ }
159
+
160
+ module.exports = { runSquadWebhook };
@@ -0,0 +1,191 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const {
5
+ loadWorkerConfig,
6
+ listWorkers,
7
+ runWorker,
8
+ scaffoldWorker
9
+ } = require('../worker-runner');
10
+ const {
11
+ openRuntimeDb,
12
+ insertWorkerRun,
13
+ listWorkerRuns
14
+ } = require('../runtime-store');
15
+
16
+ async function handleList(projectDir, squadSlug, { logger, t }) {
17
+ if (!squadSlug) {
18
+ logger.error(t('squad_worker.squad_required'));
19
+ return { ok: false };
20
+ }
21
+ const workers = await listWorkers(projectDir, squadSlug);
22
+ if (workers.length === 0) {
23
+ logger.log(t('squad_worker.no_workers'));
24
+ return { ok: true, workers: [] };
25
+ }
26
+ logger.log(`Workers for squad "${squadSlug}" (${workers.length}):`);
27
+ for (const w of workers) {
28
+ logger.log(` ${w.slug} [${w.type || 'manual'}] - ${w.name || w.slug}`);
29
+ }
30
+ return { ok: true, workers };
31
+ }
32
+
33
+ async function handleRun(projectDir, squadSlug, workerSlug, inputStr, { logger, t }) {
34
+ if (!squadSlug || !workerSlug) {
35
+ logger.error(t('squad_worker.run_usage'));
36
+ return { ok: false };
37
+ }
38
+
39
+ let inputPayload = {};
40
+ if (inputStr) {
41
+ try {
42
+ inputPayload = JSON.parse(inputStr);
43
+ } catch {
44
+ logger.error(t('squad_worker.invalid_input'));
45
+ return { ok: false, error: 'Invalid JSON input' };
46
+ }
47
+ }
48
+
49
+ logger.log(`Running worker "${workerSlug}" on squad "${squadSlug}"...`);
50
+ const result = await runWorker(projectDir, squadSlug, workerSlug, inputPayload, { triggerType: 'manual' });
51
+
52
+ // Log to runtime store
53
+ const handle = await openRuntimeDb(projectDir, { mustExist: false });
54
+ if (handle) {
55
+ const { db } = handle;
56
+ try {
57
+ insertWorkerRun(db, {
58
+ squadSlug,
59
+ workerSlug,
60
+ triggerType: 'manual',
61
+ inputJson: JSON.stringify(inputPayload),
62
+ outputJson: result.ok ? JSON.stringify(result.output) : null,
63
+ status: result.ok ? 'completed' : 'failed',
64
+ errorMessage: result.ok ? null : result.error,
65
+ durationMs: result.durationMs || 0,
66
+ attempt: result.attempt || 1
67
+ });
68
+ } finally {
69
+ db.close();
70
+ }
71
+ }
72
+
73
+ if (result.ok) {
74
+ logger.log(t('squad_worker.run_success', { worker: workerSlug }));
75
+ logger.log(JSON.stringify(result.output, null, 2));
76
+ } else {
77
+ logger.error(t('squad_worker.run_failed', { worker: workerSlug, error: result.error }));
78
+ }
79
+ return result;
80
+ }
81
+
82
+ async function handleTest(projectDir, squadSlug, workerSlug, { logger, t }) {
83
+ if (!squadSlug || !workerSlug) {
84
+ logger.error(t('squad_worker.test_usage'));
85
+ return { ok: false };
86
+ }
87
+
88
+ const config = await loadWorkerConfig(projectDir, squadSlug, workerSlug);
89
+ if (!config) {
90
+ logger.error(t('squad_worker.not_found', { worker: workerSlug }));
91
+ return { ok: false };
92
+ }
93
+
94
+ // Build mock input from schema
95
+ const mockInput = {};
96
+ for (const [key, spec] of Object.entries(config.inputs || {})) {
97
+ if (spec.type === 'string') mockInput[key] = `test-${key}`;
98
+ else if (spec.type === 'number') mockInput[key] = 0;
99
+ else mockInput[key] = `test-${key}`;
100
+ }
101
+
102
+ logger.log(`Testing worker "${workerSlug}" with mock input:`);
103
+ logger.log(JSON.stringify(mockInput, null, 2));
104
+
105
+ const result = await runWorker(projectDir, squadSlug, workerSlug, mockInput, {
106
+ triggerType: 'manual',
107
+ noRetry: true
108
+ });
109
+
110
+ if (result.ok) {
111
+ logger.log(t('squad_worker.test_passed', { worker: workerSlug }));
112
+ logger.log(JSON.stringify(result.output, null, 2));
113
+ } else {
114
+ logger.error(t('squad_worker.test_failed', { worker: workerSlug, error: result.error }));
115
+ }
116
+ return result;
117
+ }
118
+
119
+ async function handleLogs(projectDir, squadSlug, { logger, t }) {
120
+ if (!squadSlug) {
121
+ logger.error(t('squad_worker.squad_required'));
122
+ return { ok: false };
123
+ }
124
+
125
+ const handle = await openRuntimeDb(projectDir, { mustExist: true });
126
+ if (!handle) {
127
+ logger.error(t('squad_worker.no_runtime'));
128
+ return { ok: false };
129
+ }
130
+ const { db } = handle;
131
+ try {
132
+ const runs = listWorkerRuns(db, squadSlug);
133
+ if (runs.length === 0) {
134
+ logger.log(t('squad_worker.no_logs'));
135
+ return { ok: true, runs: [] };
136
+ }
137
+ logger.log(`Worker runs for squad "${squadSlug}" (${runs.length}):`);
138
+ for (const run of runs) {
139
+ const icon = run.status === 'completed' ? '[ok]' : run.status === 'failed' ? '[!!]' : '[..]';
140
+ const duration = run.duration_ms ? `${run.duration_ms}ms` : '-';
141
+ logger.log(` ${icon} ${run.worker_slug} (${run.trigger_type}) ${duration} - ${run.created_at}`);
142
+ if (run.error_message) logger.log(` Error: ${run.error_message}`);
143
+ }
144
+ return { ok: true, runs };
145
+ } finally {
146
+ db.close();
147
+ }
148
+ }
149
+
150
+ async function handleScaffold(projectDir, squadSlug, workerSlug, options, { logger, t }) {
151
+ if (!squadSlug || !workerSlug) {
152
+ logger.error(t('squad_worker.scaffold_usage'));
153
+ return { ok: false };
154
+ }
155
+
156
+ const result = await scaffoldWorker(projectDir, squadSlug, workerSlug, {
157
+ name: options.name || workerSlug,
158
+ triggerType: options.trigger || 'manual',
159
+ inputs: options.inputs ? options.inputs.split(',') : [],
160
+ outputs: options.outputs ? options.outputs.split(',') : [],
161
+ env: options.env ? options.env.split(',') : []
162
+ });
163
+
164
+ logger.log(t('squad_worker.scaffold_created', { worker: workerSlug, path: result.workerDir }));
165
+ return { ok: true, ...result };
166
+ }
167
+
168
+ async function runSquadWorker({ args, options, logger, t }) {
169
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
170
+ const sub = options.sub || 'list';
171
+ const squadSlug = options.squad;
172
+ const workerSlug = options.worker;
173
+
174
+ switch (sub) {
175
+ case 'list':
176
+ return handleList(targetDir, squadSlug, { logger, t });
177
+ case 'run':
178
+ return handleRun(targetDir, squadSlug, workerSlug, options.input, { logger, t });
179
+ case 'test':
180
+ return handleTest(targetDir, squadSlug, workerSlug, { logger, t });
181
+ case 'logs':
182
+ return handleLogs(targetDir, squadSlug, { logger, t });
183
+ case 'scaffold':
184
+ return handleScaffold(targetDir, squadSlug, workerSlug, options, { logger, t });
185
+ default:
186
+ logger.error(t('squad_worker.unknown_sub', { sub }));
187
+ return { ok: false };
188
+ }
189
+ }
190
+
191
+ module.exports = { runSquadWorker };
@@ -0,0 +1,75 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const { createWorktree, mergeWorktree, cleanupWorktree, listWorktrees } = require('../squad/worktree-manager');
5
+
6
+ async function runSquadWorktrees({ args, options, logger }) {
7
+ const projectDir = path.resolve(process.cwd(), args[0] || '.');
8
+ const squadSlug = options.squad || args[1];
9
+
10
+ if (!squadSlug) {
11
+ logger.error('Squad slug required. Use --squad <slug>');
12
+ return { ok: false };
13
+ }
14
+
15
+ // --cleanup [agent]
16
+ if (options.cleanup !== undefined) {
17
+ const agentSlug = typeof options.cleanup === 'string' ? options.cleanup : null;
18
+ if (agentSlug) {
19
+ const result = cleanupWorktree(projectDir, squadSlug, agentSlug, true);
20
+ logger.log(result.ok ? `Worktree for "${agentSlug}" removed.` : `Failed to remove worktree for "${agentSlug}".`);
21
+ return result;
22
+ }
23
+ // cleanup all for squad
24
+ const worktrees = listWorktrees(projectDir, squadSlug);
25
+ if (worktrees.length === 0) {
26
+ logger.log(`No worktrees found for squad "${squadSlug}".`);
27
+ return { ok: true };
28
+ }
29
+ for (const wt of worktrees) {
30
+ const result = cleanupWorktree(projectDir, squadSlug, wt.agentSlug, false);
31
+ logger.log(result.ok ? ` Removed: ${wt.agentSlug}` : ` Failed: ${wt.agentSlug}`);
32
+ }
33
+ return { ok: true };
34
+ }
35
+
36
+ // List
37
+ const worktrees = listWorktrees(projectDir, squadSlug);
38
+ if (worktrees.length === 0) {
39
+ logger.log(`No worktrees found for squad "${squadSlug}".`);
40
+ return { ok: true, worktrees: [] };
41
+ }
42
+
43
+ logger.log(`Worktrees for "${squadSlug}" (${worktrees.length}):`);
44
+ for (const wt of worktrees) {
45
+ logger.log(` ${wt.agentSlug} branch:${wt.branch} path:${wt.path}`);
46
+ }
47
+ return { ok: true, worktrees };
48
+ }
49
+
50
+ async function runSquadMerge({ args, options, logger }) {
51
+ const projectDir = path.resolve(process.cwd(), args[0] || '.');
52
+ const squadSlug = options.squad || args[1];
53
+ const agentSlug = options.agent || args[2];
54
+
55
+ if (!squadSlug || !agentSlug) {
56
+ logger.error('Usage: aioson squad:merge <project> --squad <squad> --agent <agent>');
57
+ return { ok: false };
58
+ }
59
+
60
+ const autoMerge = options['no-auto'] !== true;
61
+ const result = mergeWorktree(projectDir, squadSlug, agentSlug, autoMerge);
62
+
63
+ if (result.ok) {
64
+ logger.log(`Merged branch ${result.branch} successfully.`);
65
+ } else if (result.reason === 'merge_conflict') {
66
+ logger.error(`Merge conflict on ${result.branch}. Resolve manually.`);
67
+ if (result.detail) logger.error(result.detail);
68
+ } else if (result.reason === 'auto_merge_disabled') {
69
+ logger.log(`Auto-merge disabled. Branch ready: ${result.branch}`);
70
+ }
71
+
72
+ return result;
73
+ }
74
+
75
+ module.exports = { runSquadWorktrees, runSquadMerge };
@@ -14,7 +14,7 @@ const AGENTS = [
14
14
  'qa',
15
15
  'orchestrator',
16
16
  'squad',
17
- 'genoma',
17
+ 'genome',
18
18
  'profiler-researcher',
19
19
  'profiler-enricher',
20
20
  'profiler-forge'
@@ -167,6 +167,11 @@ async function runTestAgents({ options, logger }) {
167
167
  addCheck(`skill: ${skill}`, content !== null && content.length > 100);
168
168
  }
169
169
 
170
+ const packagedDesignSkill = await readFile(
171
+ path.join(TEMPLATE_DIR, '.aioson', 'skills', 'design', 'cognitive-ui', 'SKILL.md')
172
+ );
173
+ addCheck('skill package: cognitive-ui', packagedDesignSkill !== null && packagedDesignSkill.length > 100);
174
+
170
175
  // ── Summary ──────────────────────────────────────────────────────────────
171
176
  log('');
172
177
  const total = passed + failed;
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const { mapWebsite } = require('../web');
5
+
6
+ function normalizeBoolean(value, fallback = false) {
7
+ if (typeof value === 'boolean') return value;
8
+ if (value === undefined || value === null) return fallback;
9
+ const text = String(value).trim().toLowerCase();
10
+ if (['1', 'true', 'yes', 'y', 'on'].includes(text)) return true;
11
+ if (['0', 'false', 'no', 'n', 'off'].includes(text)) return false;
12
+ return fallback;
13
+ }
14
+
15
+ function parseInteger(value, fallback) {
16
+ const parsed = Number.parseInt(String(value ?? ''), 10);
17
+ return Number.isFinite(parsed) ? parsed : fallback;
18
+ }
19
+
20
+ async function runWebMap({ args, options = {}, logger, t }) {
21
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
22
+ const url = String(options.url || '').trim();
23
+ if (!url) {
24
+ logger.error(t('web_map.url_missing'));
25
+ process.exitCode = 1;
26
+ return { ok: false, error: 'url_missing' };
27
+ }
28
+
29
+ const maxDepth = Math.max(0, parseInteger(options.depth, 2));
30
+ const maxPages = Math.max(1, parseInteger(options['max-pages'], 25));
31
+ const sameOriginOnly = !normalizeBoolean(options['include-external'], false);
32
+
33
+ try {
34
+ logger.log(t('web_map.starting', { url }));
35
+ const result = await mapWebsite(url, { maxDepth, maxPages, sameOriginOnly });
36
+ const output = {
37
+ ok: true,
38
+ targetDir,
39
+ url: result.startUrl,
40
+ maxDepth,
41
+ maxPages,
42
+ sameOriginOnly,
43
+ pageCount: result.pageCount,
44
+ urls: result.urls,
45
+ pages: result.pages
46
+ };
47
+
48
+ if (options.json) return output;
49
+
50
+ logger.log(t('web_map.pages_found', { count: result.pageCount }));
51
+ for (const page of result.pages) {
52
+ logger.log(t('web_map.page_line', {
53
+ url: page.url,
54
+ depth: page.depth,
55
+ status: page.statusCode,
56
+ links: page.linkCount
57
+ }));
58
+ }
59
+ logger.log(t('web_map.done'));
60
+ return output;
61
+ } catch (error) {
62
+ logger.error(t('web_map.failed', { error: error.message }));
63
+ process.exitCode = 1;
64
+ return { ok: false, error: 'map_failed', detail: error.message };
65
+ }
66
+ }
67
+
68
+ module.exports = {
69
+ runWebMap
70
+ };