@jaimevalasek/aioson 1.4.0 → 1.6.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 (301) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/LICENSE +661 -21
  3. package/README.md +9 -1
  4. package/docs/design-previews/aurora-command-ui-website.html +884 -0
  5. package/docs/design-previews/aurora-command-ui.html +682 -0
  6. package/docs/design-previews/bold-editorial-ui-website.html +658 -0
  7. package/docs/design-previews/bold-editorial-ui.html +717 -0
  8. package/docs/design-previews/clean-saas-ui-website.html +1202 -0
  9. package/docs/design-previews/clean-saas-ui.html +549 -0
  10. package/docs/design-previews/cognitive-core-ui-website.html +1009 -0
  11. package/docs/design-previews/cognitive-core-ui.html +463 -0
  12. package/docs/design-previews/glassmorphism-ui-website.html +572 -0
  13. package/docs/design-previews/glassmorphism-ui.html +886 -0
  14. package/docs/design-previews/index.html +699 -0
  15. package/docs/design-previews/interface-design-website.html +1187 -0
  16. package/docs/design-previews/interface-design.html +513 -0
  17. package/docs/design-previews/neo-brutalist-ui-website.html +621 -0
  18. package/docs/design-previews/neo-brutalist-ui.html +797 -0
  19. package/docs/design-previews/premium-command-center-ui-website.html +1217 -0
  20. package/docs/design-previews/premium-command-center-ui.html +552 -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/en/squad-dashboard.md +372 -0
  25. package/docs/openclaw-bridge.md +308 -0
  26. package/docs/pt/README.md +7 -0
  27. package/docs/pt/agent-sharding.md +132 -0
  28. package/docs/pt/agentes.md +131 -11
  29. package/docs/pt/busca-de-contexto.md +129 -0
  30. package/docs/pt/cache-de-contexto.md +156 -0
  31. package/docs/pt/cenarios.md +46 -2
  32. package/docs/pt/comandos-cli.md +88 -1
  33. package/docs/pt/design-hybrid-forge.md +107 -0
  34. package/docs/pt/inicio-rapido.md +72 -5
  35. package/docs/pt/inteligencia-adaptativa.md +324 -0
  36. package/docs/pt/monitor-de-contexto.md +104 -0
  37. package/docs/pt/recuperacao-de-sessao.md +125 -0
  38. package/docs/pt/sandbox.md +125 -0
  39. package/docs/pt/skills.md +98 -6
  40. package/docs/pt/squad-dashboard.md +373 -0
  41. package/docs/testing/genome-2.0-matrix.md +5 -5
  42. package/docs/testing/genome-2.0-rollout.md +9 -9
  43. package/package.json +2 -2
  44. package/src/agent-loader.js +280 -0
  45. package/src/backup-local.js +74 -0
  46. package/src/cli.js +192 -0
  47. package/src/commands/agent-loader.js +85 -0
  48. package/src/commands/backup-local-cmd.js +25 -0
  49. package/src/commands/context-cache.js +90 -0
  50. package/src/commands/context-monitor.js +92 -0
  51. package/src/commands/context-search.js +66 -0
  52. package/src/commands/design-hybrid-options.js +385 -0
  53. package/src/commands/health.js +214 -0
  54. package/src/commands/init.js +54 -13
  55. package/src/commands/install.js +52 -13
  56. package/src/commands/learning-evolve.js +355 -0
  57. package/src/commands/live.js +34 -0
  58. package/src/commands/recovery.js +43 -0
  59. package/src/commands/runtime.js +242 -0
  60. package/src/commands/sandbox.js +37 -0
  61. package/src/commands/setup-context.js +29 -4
  62. package/src/commands/setup.js +178 -0
  63. package/src/commands/skill.js +79 -32
  64. package/src/commands/squad-daemon.js +209 -0
  65. package/src/commands/squad-dashboard.js +39 -0
  66. package/src/commands/squad-deploy.js +64 -0
  67. package/src/commands/squad-doctor.js +52 -0
  68. package/src/commands/squad-mcp.js +270 -0
  69. package/src/commands/squad-processes.js +56 -0
  70. package/src/commands/squad-recovery.js +42 -0
  71. package/src/commands/squad-roi.js +291 -0
  72. package/src/commands/squad-score.js +250 -0
  73. package/src/commands/squad-status.js +37 -1
  74. package/src/commands/squad-validate.js +62 -1
  75. package/src/commands/squad-webhook.js +160 -0
  76. package/src/commands/squad-worker.js +191 -0
  77. package/src/commands/squad-worktrees.js +75 -0
  78. package/src/commands/tool-registry-cmd.js +232 -0
  79. package/src/commands/update.js +7 -0
  80. package/src/commands/web-map.js +70 -0
  81. package/src/commands/web-scrape.js +71 -0
  82. package/src/constants.js +17 -0
  83. package/src/context-cache.js +159 -0
  84. package/src/context-search.js +326 -0
  85. package/src/context-writer.js +45 -1
  86. package/src/design-variation-catalog.js +503 -0
  87. package/src/i18n/messages/en.js +159 -3
  88. package/src/i18n/messages/es.js +147 -2
  89. package/src/i18n/messages/fr.js +147 -2
  90. package/src/i18n/messages/pt-BR.js +158 -3
  91. package/src/install-animation.js +260 -0
  92. package/src/install-profile.js +143 -0
  93. package/src/install-wizard.js +474 -0
  94. package/src/installer.js +38 -10
  95. package/src/lib/webhook-server.js +328 -0
  96. package/src/mcp-connectors/registry.js +602 -0
  97. package/src/parser.js +7 -1
  98. package/src/recovery-context-session.js +154 -0
  99. package/src/runtime-store.js +355 -2
  100. package/src/sandbox.js +177 -0
  101. package/src/squad/external-session.js +180 -0
  102. package/src/squad/inter-squad.js +74 -0
  103. package/src/squad/recovery-context.js +201 -0
  104. package/src/squad/worktree-manager.js +114 -0
  105. package/src/squad-daemon.js +490 -0
  106. package/src/squad-dashboard/api.js +223 -0
  107. package/src/squad-dashboard/attachment-handler.js +93 -0
  108. package/src/squad-dashboard/context-monitor.js +157 -0
  109. package/src/squad-dashboard/execution-logs.js +115 -0
  110. package/src/squad-dashboard/hunk-review.js +209 -0
  111. package/src/squad-dashboard/metrics.js +133 -0
  112. package/src/squad-dashboard/process-monitor.js +125 -0
  113. package/src/squad-dashboard/renderer.js +858 -0
  114. package/src/squad-dashboard/server.js +232 -0
  115. package/src/squad-dashboard/styles.js +525 -0
  116. package/src/squad-dashboard/token-tracker.js +99 -0
  117. package/src/tool-executor.js +94 -0
  118. package/src/updater.js +11 -3
  119. package/src/web.js +284 -0
  120. package/src/worker-runner.js +339 -0
  121. package/template/.aioson/agents/analyst.md +62 -3
  122. package/template/.aioson/agents/architect.md +42 -0
  123. package/template/.aioson/agents/design-hybrid-forge.md +127 -0
  124. package/template/.aioson/agents/dev.md +223 -11
  125. package/template/.aioson/agents/deyvin.md +65 -0
  126. package/template/.aioson/agents/neo.md +152 -0
  127. package/template/.aioson/agents/orache.md +17 -0
  128. package/template/.aioson/agents/orchestrator.md +26 -0
  129. package/template/.aioson/agents/pm.md +58 -0
  130. package/template/.aioson/agents/product.md +88 -12
  131. package/template/.aioson/agents/qa.md +80 -0
  132. package/template/.aioson/agents/setup.md +128 -22
  133. package/template/.aioson/agents/sheldon.md +704 -0
  134. package/template/.aioson/agents/squad.md +191 -0
  135. package/template/.aioson/agents/tester.md +410 -0
  136. package/template/.aioson/agents/ux-ui.md +12 -0
  137. package/template/.aioson/config.md +21 -0
  138. package/template/.aioson/context/forensics/.gitkeep +0 -0
  139. package/template/.aioson/context/seeds/seed-example.md +27 -0
  140. package/template/.aioson/context/user-profile.md +42 -0
  141. package/template/.aioson/locales/en/agents/analyst.md +8 -0
  142. package/template/.aioson/locales/en/agents/architect.md +8 -0
  143. package/template/.aioson/locales/en/agents/dev.md +66 -7
  144. package/template/.aioson/locales/en/agents/deyvin.md +8 -0
  145. package/template/.aioson/locales/en/agents/neo.md +8 -0
  146. package/template/.aioson/locales/en/agents/orchestrator.md +26 -0
  147. package/template/.aioson/locales/en/agents/qa.md +49 -0
  148. package/template/.aioson/locales/en/agents/setup.md +35 -2
  149. package/template/.aioson/locales/en/agents/sheldon.md +340 -0
  150. package/template/.aioson/locales/en/agents/ux-ui.md +8 -0
  151. package/template/.aioson/locales/es/agents/analyst.md +8 -0
  152. package/template/.aioson/locales/es/agents/architect.md +8 -0
  153. package/template/.aioson/locales/es/agents/dev.md +66 -7
  154. package/template/.aioson/locales/es/agents/deyvin.md +8 -0
  155. package/template/.aioson/locales/es/agents/neo.md +48 -0
  156. package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
  157. package/template/.aioson/locales/es/agents/qa.md +26 -0
  158. package/template/.aioson/locales/es/agents/setup.md +35 -2
  159. package/template/.aioson/locales/es/agents/sheldon.md +192 -0
  160. package/template/.aioson/locales/es/agents/squad.md +63 -0
  161. package/template/.aioson/locales/es/agents/ux-ui.md +8 -0
  162. package/template/.aioson/locales/fr/agents/analyst.md +8 -0
  163. package/template/.aioson/locales/fr/agents/architect.md +8 -0
  164. package/template/.aioson/locales/fr/agents/dev.md +66 -7
  165. package/template/.aioson/locales/fr/agents/deyvin.md +8 -0
  166. package/template/.aioson/locales/fr/agents/neo.md +48 -0
  167. package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
  168. package/template/.aioson/locales/fr/agents/qa.md +26 -0
  169. package/template/.aioson/locales/fr/agents/setup.md +35 -2
  170. package/template/.aioson/locales/fr/agents/sheldon.md +192 -0
  171. package/template/.aioson/locales/fr/agents/squad.md +63 -0
  172. package/template/.aioson/locales/fr/agents/ux-ui.md +8 -0
  173. package/template/.aioson/locales/pt-BR/agents/analyst.md +19 -0
  174. package/template/.aioson/locales/pt-BR/agents/architect.md +19 -0
  175. package/template/.aioson/locales/pt-BR/agents/dev.md +75 -12
  176. package/template/.aioson/locales/pt-BR/agents/deyvin.md +8 -0
  177. package/template/.aioson/locales/pt-BR/agents/neo.md +147 -0
  178. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +26 -0
  179. package/template/.aioson/locales/pt-BR/agents/product.md +8 -3
  180. package/template/.aioson/locales/pt-BR/agents/qa.md +60 -0
  181. package/template/.aioson/locales/pt-BR/agents/setup.md +35 -2
  182. package/template/.aioson/locales/pt-BR/agents/sheldon.md +192 -0
  183. package/template/.aioson/locales/pt-BR/agents/squad.md +105 -0
  184. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +8 -0
  185. package/template/.aioson/schemas/squad-blueprint.schema.json +21 -0
  186. package/template/.aioson/schemas/squad-manifest.schema.json +178 -1
  187. package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +243 -0
  188. package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -0
  189. package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -0
  190. package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -0
  191. package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -0
  192. package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -0
  193. package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +482 -0
  194. package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +387 -0
  195. package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +205 -0
  196. package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -0
  197. package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -0
  198. package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -0
  199. package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -0
  200. package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -0
  201. package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -0
  202. package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -0
  203. package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +210 -0
  204. package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -0
  205. package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -0
  206. package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -0
  207. package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -0
  208. package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -0
  209. package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -0
  210. package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -0
  211. package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +55 -9
  212. package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -0
  213. package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +1 -1
  214. package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +100 -0
  215. package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +43 -9
  216. package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +40 -0
  217. package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +1 -1
  218. package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +99 -12
  219. package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +222 -0
  220. package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -0
  221. package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -0
  222. package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -0
  223. package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -0
  224. package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -0
  225. package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -0
  226. package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -0
  227. package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +213 -0
  228. package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -0
  229. package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -0
  230. package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -0
  231. package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -0
  232. package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -0
  233. package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -0
  234. package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -0
  235. package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +209 -0
  236. package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -0
  237. package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -0
  238. package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -0
  239. package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -0
  240. package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -0
  241. package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -0
  242. package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -0
  243. package/template/.aioson/skills/premium-visual-design/SKILL.md +83 -0
  244. package/template/.aioson/skills/premium-visual-design/components/agent-badge.md +92 -0
  245. package/template/.aioson/skills/premium-visual-design/components/dependency-node.md +102 -0
  246. package/template/.aioson/skills/premium-visual-design/components/mention-autocomplete.md +136 -0
  247. package/template/.aioson/skills/premium-visual-design/components/notification-center.md +136 -0
  248. package/template/.aioson/skills/premium-visual-design/components/review-action-bar.md +188 -0
  249. package/template/.aioson/skills/premium-visual-design/components/team-switcher.md +131 -0
  250. package/template/.aioson/skills/premium-visual-design/patterns/agent-message-thread.md +198 -0
  251. package/template/.aioson/skills/premium-visual-design/patterns/notification-panel.md +275 -0
  252. package/template/.aioson/skills/premium-visual-design/patterns/review-workflow-ui.md +234 -0
  253. package/template/.aioson/skills/premium-visual-design/patterns/task-dependency-graph.md +147 -0
  254. package/template/.aioson/skills/premium-visual-design/tokens/status-extended.md +142 -0
  255. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +45 -0
  256. package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +109 -0
  257. package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +44 -0
  258. package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +37 -0
  259. package/template/.aioson/skills/process/aioson-spec-driven/references/hardening-lane.md +49 -0
  260. package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +66 -0
  261. package/template/.aioson/skills/process/aioson-spec-driven/references/ui-language.md +75 -0
  262. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +144 -0
  263. package/template/.aioson/skills/process/design-hybrid-forge/references/crossover-protocol.md +221 -0
  264. package/template/.aioson/skills/process/design-hybrid-forge/references/naming-registry.md +88 -0
  265. package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +291 -0
  266. package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +117 -0
  267. package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +188 -0
  268. package/template/.aioson/skills/process/design-hybrid-forge/references/variation-library.md +125 -0
  269. package/template/.aioson/skills/squad/formats/catalog.json +15 -0
  270. package/template/.aioson/skills/squad/formats/content/blog-post.md +47 -0
  271. package/template/.aioson/skills/squad/formats/content/newsletter.md +47 -0
  272. package/template/.aioson/skills/squad/formats/creative/podcast-script.md +43 -0
  273. package/template/.aioson/skills/squad/formats/creative/video-script.md +41 -0
  274. package/template/.aioson/skills/squad/formats/social/instagram-feed.md +42 -0
  275. package/template/.aioson/skills/squad/formats/social/linkedin-post.md +42 -0
  276. package/template/.aioson/skills/squad/formats/social/tiktok.md +39 -0
  277. package/template/.aioson/skills/squad/formats/social/twitter-thread.md +39 -0
  278. package/template/.aioson/skills/squad/formats/social/youtube-long.md +47 -0
  279. package/template/.aioson/skills/squad/formats/social/youtube-shorts.md +39 -0
  280. package/template/.aioson/skills/squad/patterns/multi-platform-pattern.md +108 -0
  281. package/template/.aioson/skills/squad/patterns/persona-based-pattern.md +98 -0
  282. package/template/.aioson/skills/squad/patterns/pipeline-pattern.md +106 -0
  283. package/template/.aioson/skills/squad/patterns/review-loop-pattern.md +81 -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 +19 -0
  290. package/template/.aioson/tasks/squad-design.md +28 -0
  291. package/template/.aioson/tasks/squad-profile.md +48 -0
  292. package/template/.aioson/tasks/squad-review.md +61 -0
  293. package/template/.aioson/tasks/squad-task-decompose.md +66 -0
  294. package/template/.claude/commands/aioson/agent/neo.md +5 -0
  295. package/template/.claude/commands/aioson/agent/tester.md +5 -0
  296. package/template/.gemini/GEMINI.md +1 -0
  297. package/template/.gemini/commands/aios-neo.toml +4 -0
  298. package/template/.gemini/commands/aios-tester.toml +6 -0
  299. package/template/AGENTS.md +26 -1
  300. package/template/CLAUDE.md +6 -2
  301. package/template/OPENCODE.md +2 -0
@@ -5,6 +5,17 @@ const path = require('node:path');
5
5
  const { installTemplate } = require('../installer');
6
6
  const { applyAgentLocale } = require('../locales');
7
7
  const { resolvePromptTool } = require('../prompt-tool');
8
+ const { runInstallWizard } = require('../install-wizard');
9
+ const { renderRevealAnimation, renderInstallSummary, renderProgress } = require('../install-animation');
10
+ const { getCliVersion } = require('../version');
11
+
12
+ // Complete profile used when --all is passed (skip wizard, install everything)
13
+ const ALL_PROFILE = {
14
+ tools: ['claude', 'codex', 'gemini', 'opencode'],
15
+ uses: ['development', 'squads'],
16
+ design: 'all',
17
+ locale: 'en'
18
+ };
8
19
 
9
20
  async function directoryIsEmpty(dirPath) {
10
21
  try {
@@ -25,6 +36,8 @@ async function runInit({ args, options, logger, t }) {
25
36
  const targetDir = path.resolve(process.cwd(), projectName);
26
37
  const force = Boolean(options.force);
27
38
  const dryRun = Boolean(options['dry-run']);
39
+ const noInteractive = Boolean(options['no-interactive']);
40
+ const installAll = Boolean(options.all);
28
41
  const requestedLanguage = options.lang || options.language;
29
42
  const promptTool = resolvePromptTool(options.tool);
30
43
 
@@ -34,15 +47,33 @@ async function runInit({ args, options, logger, t }) {
34
47
  throw new Error(t('init.non_empty_dir', { targetDir }));
35
48
  }
36
49
 
50
+ // Run wizard for new projects (TTY only) — unless --all skips it
51
+ const isTTY = process.stdin.isTTY && process.stdout.isTTY;
52
+ let installProfile = null;
53
+
54
+ if (installAll) {
55
+ // --all: skip wizard, install complete
56
+ installProfile = ALL_PROFILE;
57
+ if (isTTY && !dryRun) {
58
+ logger.log(t('init_all.installing_full', { projectName }));
59
+ }
60
+ } else if (!noInteractive && !dryRun && isTTY) {
61
+ installProfile = await runInstallWizard({ noInteractive, t });
62
+ // null = user cancelled → fall back to full install
63
+ }
64
+
37
65
  const result = await installTemplate(targetDir, {
38
66
  overwrite: true,
39
67
  dryRun,
40
- mode: 'init'
68
+ mode: 'init',
69
+ installProfile,
70
+ onProgress: isTTY && !dryRun ? renderProgress : null
41
71
  });
42
72
 
73
+ const effectiveLocale = requestedLanguage || (installProfile && installProfile.locale) || null;
43
74
  let localeApply = null;
44
- if (requestedLanguage) {
45
- localeApply = await applyAgentLocale(targetDir, requestedLanguage, { dryRun });
75
+ if (effectiveLocale) {
76
+ localeApply = await applyAgentLocale(targetDir, effectiveLocale, { dryRun });
46
77
  if (dryRun) {
47
78
  logger.log(t('locale_apply.dry_run_applied', { locale: localeApply.locale }));
48
79
  } else {
@@ -50,22 +81,32 @@ async function runInit({ args, options, logger, t }) {
50
81
  }
51
82
  }
52
83
 
53
- logger.log(t('init.created_at', { targetDir }));
54
- logger.log(t('init.files_copied', { count: result.copied.length }));
55
- if (result.skipped.length > 0) {
56
- logger.log(t('init.files_skipped', { count: result.skipped.length }));
84
+ // Reveal animation + summary (TTY only, not dry-run)
85
+ if (isTTY && !dryRun) {
86
+ const version = await getCliVersion();
87
+ await renderRevealAnimation(version);
88
+ renderInstallSummary({ result, installProfile });
89
+ logger.log('');
90
+ logger.log(t('init.step_cd', { projectName }));
91
+ } else {
92
+ logger.log(t('init.created_at', { targetDir }));
93
+ logger.log(t('init.files_copied', { count: result.copied.length }));
94
+ if (result.skipped.length > 0) {
95
+ logger.log(t('init.files_skipped', { count: result.skipped.length }));
96
+ }
97
+ logger.log(t('init.next_steps'));
98
+ logger.log(t('init.step_cd', { projectName }));
99
+ logger.log(t('init.step_setup'));
100
+ logger.log(t('init.step_agents'));
101
+ logger.log(t('init.step_agent_prompt', { tool: promptTool }));
57
102
  }
58
- logger.log(t('init.next_steps'));
59
- logger.log(t('init.step_cd', { projectName }));
60
- logger.log(t('init.step_setup'));
61
- logger.log(t('init.step_agents'));
62
- logger.log(t('init.step_agent_prompt', { tool: promptTool }));
63
103
 
64
104
  return {
65
105
  ok: true,
66
106
  targetDir,
67
107
  ...result,
68
- localeApply
108
+ localeApply,
109
+ installProfile
69
110
  };
70
111
  }
71
112
 
@@ -2,14 +2,19 @@
2
2
 
3
3
  const path = require('node:path');
4
4
  const { detectFramework } = require('../detector');
5
- const { installTemplate } = require('../installer');
5
+ const { installTemplate, readInstallProfile } = require('../installer');
6
6
  const { applyAgentLocale } = require('../locales');
7
7
  const { resolvePromptTool } = require('../prompt-tool');
8
+ const { runInstallWizard } = require('../install-wizard');
9
+ const { renderRevealAnimation, renderInstallSummary, renderProgress } = require('../install-animation');
10
+ const { getCliVersion } = require('../version');
8
11
 
9
12
  async function runInstall({ args, options, logger, t }) {
10
13
  const targetDir = path.resolve(process.cwd(), args[0] || '.');
11
14
  const force = Boolean(options.force);
12
15
  const dryRun = Boolean(options['dry-run']);
16
+ const noInteractive = Boolean(options['no-interactive']);
17
+ const reconfigure = Boolean(options.reconfigure);
13
18
  const requestedLanguage = options.lang || options.language;
14
19
  const promptTool = resolvePromptTool(options.tool);
15
20
 
@@ -23,16 +28,42 @@ async function runInstall({ args, options, logger, t }) {
23
28
  logger.log(t('install.framework_not_detected'));
24
29
  }
25
30
 
31
+ // Decide install profile
32
+ let installProfile = null;
33
+ const isTTY = process.stdin.isTTY && process.stdout.isTTY;
34
+
35
+ if (!noInteractive && isTTY && !dryRun) {
36
+ const existingProfile = await readInstallProfile(targetDir);
37
+ if (!existingProfile || reconfigure) {
38
+ installProfile = await runInstallWizard({
39
+ noInteractive,
40
+ existingProfile: reconfigure ? existingProfile : null,
41
+ t
42
+ });
43
+ // null = user cancelled → fall back to full install
44
+ } else {
45
+ installProfile = existingProfile;
46
+ logger.log(t('install.using_saved_profile'));
47
+ }
48
+ }
49
+
50
+ // When reconfigure, we need overwrite=true so changed profile is reflected
51
+ const overwrite = force || reconfigure;
52
+
26
53
  const result = await installTemplate(targetDir, {
27
- overwrite: force,
54
+ overwrite,
28
55
  dryRun,
29
56
  mode: 'install',
30
- frameworkDetection: detection.framework
57
+ frameworkDetection: detection.framework,
58
+ installProfile,
59
+ onProgress: isTTY && !dryRun ? renderProgress : null
31
60
  });
32
61
 
62
+ // Locale: explicit --lang flag wins over profile, profile wins over nothing
63
+ const effectiveLocale = requestedLanguage || (installProfile && installProfile.locale) || null;
33
64
  let localeApply = null;
34
- if (requestedLanguage) {
35
- localeApply = await applyAgentLocale(targetDir, requestedLanguage, { dryRun });
65
+ if (effectiveLocale) {
66
+ localeApply = await applyAgentLocale(targetDir, effectiveLocale, { dryRun });
36
67
  if (dryRun) {
37
68
  logger.log(t('locale_apply.dry_run_applied', { locale: localeApply.locale }));
38
69
  } else {
@@ -40,13 +71,20 @@ async function runInstall({ args, options, logger, t }) {
40
71
  }
41
72
  }
42
73
 
43
- logger.log(t('install.done_at', { targetDir }));
44
- logger.log(t('install.files_copied', { count: result.copied.length }));
45
- logger.log(t('install.files_skipped', { count: result.skipped.length }));
46
- logger.log(t('install.next_steps'));
47
- logger.log(t('install.step_setup_context'));
48
- logger.log(t('install.step_agents'));
49
- logger.log(t('install.step_agent_prompt', { tool: promptTool }));
74
+ // Reveal animation + summary (TTY only, not dry-run)
75
+ if (isTTY && !dryRun) {
76
+ const version = await getCliVersion();
77
+ await renderRevealAnimation(version);
78
+ renderInstallSummary({ result, installProfile });
79
+ } else {
80
+ logger.log(t('install.done_at', { targetDir }));
81
+ logger.log(t('install.files_copied', { count: result.copied.length }));
82
+ logger.log(t('install.files_skipped', { count: result.skipped.length }));
83
+ logger.log(t('install.next_steps'));
84
+ logger.log(t('install.step_setup_context'));
85
+ logger.log(t('install.step_agents'));
86
+ logger.log(t('install.step_agent_prompt', { tool: promptTool }));
87
+ }
50
88
 
51
89
  if (result.isExistingProject) {
52
90
  logger.log('');
@@ -59,7 +97,8 @@ async function runInstall({ args, options, logger, t }) {
59
97
  targetDir,
60
98
  detection,
61
99
  ...result,
62
- localeApply
100
+ localeApply,
101
+ installProfile
63
102
  };
64
103
  }
65
104
 
@@ -0,0 +1,355 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const { openRuntimeDb, listSquadLearnings, listProjectLearnings, promoteSquadLearning, promoteProjectLearning } = require('../runtime-store');
6
+
7
+ const AGENTS_DIR = path.join('.aioson', 'agents');
8
+ const EVOLUTION_DIR = path.join('.aioson', 'evolution');
9
+ const CONTEXT_FILE = path.join('.aioson', 'context', 'project.context.md');
10
+ const MAX_FILE_LINES = 300;
11
+ const MIN_FREQUENCY = 2;
12
+
13
+ /**
14
+ * Mapeia tipo de learning para seção e arquivo alvo.
15
+ */
16
+ function resolveDeltaTarget(type, squadSlug) {
17
+ const rulesDir = path.join('.aioson', 'rules');
18
+ if (type === 'preference') {
19
+ return { file: CONTEXT_FILE, section: '## Preferências dos Agentes' };
20
+ }
21
+ if (type === 'process') {
22
+ const filename = squadSlug ? `${squadSlug}-process.md` : 'project-process.md';
23
+ return { file: path.join(rulesDir, filename), section: null };
24
+ }
25
+ if (type === 'domain') {
26
+ return { file: CONTEXT_FILE, section: '## Conhecimento de Domínio' };
27
+ }
28
+ if (type === 'quality') {
29
+ return { file: CONTEXT_FILE, section: '## Padrões de Qualidade' };
30
+ }
31
+ return { file: CONTEXT_FILE, section: '## Observações' };
32
+ }
33
+
34
+ /**
35
+ * Gate 1: arquivo não pode estar dentro de .aioson/agents/
36
+ */
37
+ function passesConstitutionGate(filePath, projectDir) {
38
+ const absolute = path.isAbsolute(filePath) ? filePath : path.resolve(projectDir, filePath);
39
+ const agentsAbsolute = path.resolve(projectDir, AGENTS_DIR);
40
+ return !absolute.startsWith(agentsAbsolute + path.sep) && absolute !== agentsAbsolute;
41
+ }
42
+
43
+ /**
44
+ * Gate 2: arquivo alvo não pode ultrapassar MAX_FILE_LINES após append.
45
+ */
46
+ async function passesSizeGate(filePath, projectDir, newContent) {
47
+ const absolute = path.isAbsolute(filePath) ? filePath : path.resolve(projectDir, filePath);
48
+ let existingLines = 0;
49
+ try {
50
+ const content = await fs.readFile(absolute, 'utf8');
51
+ existingLines = content.split('\n').length;
52
+ } catch {
53
+ existingLines = 0;
54
+ }
55
+ const newLines = String(newContent || '').split('\n').length;
56
+ return (existingLines + newLines) <= MAX_FILE_LINES;
57
+ }
58
+
59
+ /**
60
+ * Gera o conteúdo textual de um delta a partir de um grupo de learnings.
61
+ */
62
+ function buildDeltaContent(learnings, section) {
63
+ const lines = [];
64
+ if (section) {
65
+ lines.push('');
66
+ }
67
+ for (const l of learnings) {
68
+ const confidence = l.confidence === 'high' ? '(alta confiança)' : l.confidence === 'low' ? '(baixa confiança)' : '';
69
+ lines.push(`- ${l.title} ${confidence}`.trim());
70
+ if (l.evidence) {
71
+ lines.push(` > ${l.evidence}`);
72
+ }
73
+ }
74
+ return lines.join('\n');
75
+ }
76
+
77
+ /**
78
+ * Aplica um delta aprovado no sistema de arquivos.
79
+ */
80
+ async function applyDelta(delta, projectDir) {
81
+ const absolute = path.isAbsolute(delta.file) ? delta.file : path.resolve(projectDir, delta.file);
82
+
83
+ await fs.mkdir(path.dirname(absolute), { recursive: true });
84
+
85
+ let existing = '';
86
+ try {
87
+ existing = await fs.readFile(absolute, 'utf8');
88
+ } catch {
89
+ existing = '';
90
+ }
91
+
92
+ if (delta.section && existing) {
93
+ if (existing.includes(delta.section)) {
94
+ // Insere após o cabeçalho da seção
95
+ const updated = existing.replace(delta.section, `${delta.section}\n${delta.content}`);
96
+ await fs.writeFile(absolute, updated, 'utf8');
97
+ } else {
98
+ // Adiciona a seção no final
99
+ await fs.writeFile(absolute, `${existing}\n${delta.section}\n${delta.content}\n`, 'utf8');
100
+ }
101
+ } else {
102
+ // Append simples
103
+ await fs.writeFile(absolute, `${existing}\n${delta.content}\n`, 'utf8');
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Ponto de entrada principal.
109
+ */
110
+ async function runLearningEvolve({ args = [], options = {}, logger = console, t = (k) => k } = {}) {
111
+ const projectDir = path.resolve(process.cwd(), args[0] || '.');
112
+ const squadSlug = options.squad || null;
113
+ const dryRun = Boolean(options['dry-run'] || options.dry);
114
+ const autoApply = Boolean(options['auto-apply'] || options.auto);
115
+ const quiet = Boolean(options.quiet);
116
+
117
+ const handle = await openRuntimeDb(projectDir, { mustExist: true });
118
+ if (!handle) {
119
+ logger.error('Runtime store não encontrado. Execute aioson runtime:init primeiro.');
120
+ return { ok: false, error: 'no_runtime' };
121
+ }
122
+ const { db } = handle;
123
+
124
+ let learnings;
125
+ try {
126
+ if (squadSlug) {
127
+ learnings = listSquadLearnings(db, squadSlug, 'active');
128
+ } else {
129
+ const squad = listSquadLearnings(db, null, 'active');
130
+ const project = listProjectLearnings(db, 'active');
131
+ learnings = [...squad, ...project];
132
+ }
133
+ } finally {
134
+ db.close();
135
+ }
136
+
137
+ // Filtra por frequência mínima
138
+ const eligible = learnings.filter((l) => Number(l.frequency || 1) >= MIN_FREQUENCY);
139
+
140
+ if (eligible.length === 0) {
141
+ if (!quiet) logger.log('Nenhum learning com frequência suficiente para evoluir (mínimo: 2 ocorrências).');
142
+ return { ok: true, evolved: 0, skipped: 0, proposed: [] };
143
+ }
144
+
145
+ if (!quiet) logger.log(`Analisando ${eligible.length} learnings elegíveis...`);
146
+
147
+ // Agrupa por tipo
148
+ const grouped = {};
149
+ for (const l of eligible) {
150
+ const key = l.type;
151
+ if (!grouped[key]) grouped[key] = [];
152
+ grouped[key].push(l);
153
+ }
154
+
155
+ // Gera deltas
156
+ const proposed = [];
157
+ const rejected = [];
158
+
159
+ for (const [type, group] of Object.entries(grouped)) {
160
+ const { file, section } = resolveDeltaTarget(type, group[0].squad_slug || null);
161
+ const content = buildDeltaContent(group, section);
162
+
163
+ // Gate 1: Constitution
164
+ if (!passesConstitutionGate(file, projectDir)) {
165
+ rejected.push({ type, reason: 'constitution_gate', file, count: group.length });
166
+ continue;
167
+ }
168
+
169
+ // Gate 2: Size
170
+ const sizeOk = await passesSizeGate(file, projectDir, content);
171
+ if (!sizeOk) {
172
+ rejected.push({ type, reason: 'size_gate', file, count: group.length });
173
+ continue;
174
+ }
175
+
176
+ proposed.push({
177
+ type,
178
+ file,
179
+ section,
180
+ content,
181
+ sourceIds: group.map((l) => l.learning_id),
182
+ count: group.length
183
+ });
184
+ }
185
+
186
+ // Exibe resultados
187
+ if (!quiet) {
188
+ logger.log('');
189
+ logger.log(`Deltas propostos: ${proposed.length} aprovados, ${rejected.length} rejeitados`);
190
+ logger.log('');
191
+
192
+ for (let i = 0; i < proposed.length; i++) {
193
+ const d = proposed[i];
194
+ logger.log(` [${i + 1}] APPEND → ${d.file}`);
195
+ if (d.section) logger.log(` Seção: ${d.section}`);
196
+ logger.log(` Learnings: ${d.count} (${d.type})`);
197
+ logger.log(d.content.split('\n').map((l) => ` ${l}`).join('\n'));
198
+ logger.log('');
199
+ }
200
+
201
+ for (const r of rejected) {
202
+ const reason = r.reason === 'constitution_gate' ? 'gate constitucional (arquivo imutável)' : `gate de tamanho (>${MAX_FILE_LINES} linhas)`;
203
+ logger.log(` ✗ Rejeitado [${r.type}] → ${r.file}: ${reason}`);
204
+ }
205
+ }
206
+
207
+ if (proposed.length === 0) {
208
+ return { ok: true, evolved: 0, skipped: rejected.length, proposed: [] };
209
+ }
210
+
211
+ // Dry-run: só exibe, não aplica
212
+ if (dryRun) {
213
+ logger.log('Modo dry-run: nenhuma alteração foi feita.');
214
+ return { ok: true, evolved: 0, skipped: rejected.length, proposed };
215
+ }
216
+
217
+ // Auto-apply: aplica diretamente
218
+ if (autoApply) {
219
+ return applyProposed(proposed, projectDir, db, logger, quiet, squadSlug);
220
+ }
221
+
222
+ // Modo padrão: salva arquivo pendente
223
+ const evolutionDir = path.resolve(projectDir, EVOLUTION_DIR);
224
+ await fs.mkdir(evolutionDir, { recursive: true });
225
+
226
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
227
+ const pendingFile = path.join(evolutionDir, `pending-${timestamp}.json`);
228
+ await fs.writeFile(pendingFile, JSON.stringify({ createdAt: new Date().toISOString(), projectDir, proposed, rejected }, null, 2), 'utf8');
229
+
230
+ if (!quiet) {
231
+ logger.log(`Proposta salva em: ${pendingFile}`);
232
+ logger.log('Para aplicar: aioson learning:apply . --file=' + path.relative(projectDir, pendingFile));
233
+ logger.log('Para aplicar automaticamente: aioson learning:evolve . --auto-apply');
234
+ }
235
+
236
+ return { ok: true, evolved: 0, skipped: rejected.length, proposed, pendingFile };
237
+ }
238
+
239
+ async function applyProposed(proposed, projectDir, db, logger, quiet, squadSlug) {
240
+ const handle = await openRuntimeDb(projectDir, { mustExist: true });
241
+ if (!handle) return { ok: false, error: 'no_runtime' };
242
+ const applyDb = handle.db;
243
+
244
+ let evolved = 0;
245
+ try {
246
+ for (const delta of proposed) {
247
+ await applyDelta(delta, projectDir);
248
+
249
+ // Promove learnings no DB
250
+ for (const id of delta.sourceIds) {
251
+ try {
252
+ if (id.startsWith('sl-') || id.startsWith('pl-')) {
253
+ if (id.startsWith('sl-')) {
254
+ promoteSquadLearning(applyDb, id, delta.file);
255
+ } else {
256
+ promoteProjectLearning(applyDb, id, delta.file);
257
+ }
258
+ } else {
259
+ promoteSquadLearning(applyDb, id, delta.file);
260
+ }
261
+ } catch { /* learning pode já ter sido promovido */ }
262
+ }
263
+
264
+ evolved++;
265
+ if (!quiet) logger.log(` ✓ Aplicado: ${delta.file} (+${delta.count} learnings)`);
266
+ }
267
+
268
+ // Registra no log de evolução
269
+ const evolutionDir = path.resolve(projectDir, EVOLUTION_DIR);
270
+ await fs.mkdir(evolutionDir, { recursive: true });
271
+ const logFile = path.join(evolutionDir, 'log.jsonl');
272
+ const logEntry = JSON.stringify({
273
+ appliedAt: new Date().toISOString(),
274
+ deltasCount: evolved,
275
+ squad: squadSlug || null,
276
+ files: proposed.map((d) => d.file)
277
+ });
278
+ await fs.appendFile(logFile, `${logEntry}\n`, 'utf8');
279
+
280
+ if (!quiet) logger.log(`\n${evolved} delta(s) aplicado(s) com sucesso.`);
281
+ } finally {
282
+ applyDb.close();
283
+ }
284
+
285
+ return { ok: true, evolved, skipped: 0, proposed };
286
+ }
287
+
288
+ /**
289
+ * Subcomando: apply — aplica um arquivo de deltas pendentes.
290
+ */
291
+ async function runLearningApply({ args = [], options = {}, logger = console } = {}) {
292
+ const projectDir = path.resolve(process.cwd(), args[0] || '.');
293
+ const filePath = options.file ? String(options.file) : null;
294
+
295
+ if (!filePath) {
296
+ logger.error('--file é obrigatório. Exemplo: aioson learning:apply . --file=.aioson/evolution/pending-XXX.json');
297
+ return { ok: false, error: 'file_required' };
298
+ }
299
+
300
+ const absolute = path.isAbsolute(filePath) ? filePath : path.resolve(projectDir, filePath);
301
+
302
+ let pendingData;
303
+ try {
304
+ pendingData = JSON.parse(await fs.readFile(absolute, 'utf8'));
305
+ } catch (err) {
306
+ logger.error(`Não foi possível ler o arquivo: ${absolute}\n${err.message}`);
307
+ return { ok: false, error: 'file_not_readable' };
308
+ }
309
+
310
+ const { proposed = [], rejected = [] } = pendingData;
311
+
312
+ if (proposed.length === 0) {
313
+ logger.log('Nenhum delta para aplicar neste arquivo.');
314
+ return { ok: true, evolved: 0 };
315
+ }
316
+
317
+ logger.log(`Aplicando ${proposed.length} delta(s)...`);
318
+
319
+ const handle = await openRuntimeDb(projectDir, { mustExist: true });
320
+ const db = handle ? handle.db : null;
321
+
322
+ let evolved = 0;
323
+ for (const delta of proposed) {
324
+ try {
325
+ await applyDelta(delta, projectDir);
326
+ if (db) {
327
+ for (const id of (delta.sourceIds || [])) {
328
+ try {
329
+ if (id.startsWith('pl-')) {
330
+ promoteProjectLearning(db, id, delta.file);
331
+ } else {
332
+ promoteSquadLearning(db, id, delta.file);
333
+ }
334
+ } catch { /* ok */ }
335
+ }
336
+ }
337
+ evolved++;
338
+ logger.log(` ✓ ${delta.file}`);
339
+ } catch (err) {
340
+ logger.error(` ✗ Falha em ${delta.file}: ${err.message}`);
341
+ }
342
+ }
343
+
344
+ if (db) db.close();
345
+
346
+ // Remove o arquivo pendente após aplicar
347
+ try { await fs.unlink(absolute); } catch { /* ok */ }
348
+
349
+ logger.log(`\n${evolved}/${proposed.length} delta(s) aplicado(s).`);
350
+ if (rejected.length > 0) logger.log(`${rejected.length} rejeitado(s) previamente pelos gates.`);
351
+
352
+ return { ok: true, evolved };
353
+ }
354
+
355
+ module.exports = { runLearningEvolve, runLearningApply };
@@ -1062,6 +1062,23 @@ async function runLiveStart({ args, options = {}, logger, t }) {
1062
1062
  logger.log(t('live.session_started', { agent: agentName, tool, session: sessionKey, dbPath }));
1063
1063
  }
1064
1064
 
1065
+ // Ambient Intelligence: exibe digest de saúde ao iniciar sessão
1066
+ if (!options.json && !options['no-health']) {
1067
+ try {
1068
+ const { getHealthDigest } = require('./health');
1069
+ const items = await getHealthDigest(targetDir);
1070
+ if (items && items.length > 0) {
1071
+ logger.log('');
1072
+ logger.log('AIOSON Health — itens pendentes:');
1073
+ for (const item of items) {
1074
+ logger.log(` ● ${item}`);
1075
+ }
1076
+ logger.log(' → aioson health . para detalhes');
1077
+ logger.log('');
1078
+ }
1079
+ } catch { /* não bloqueia o start */ }
1080
+ }
1081
+
1065
1082
  if (child) {
1066
1083
  childResult = await waitForChild(child);
1067
1084
  }
@@ -1508,6 +1525,23 @@ async function runLiveClose({ args, options = {}, logger, t }) {
1508
1525
  logger.log(t('live.session_closed', { agent: context.agentName, session: context.sessionKey, dbPath }));
1509
1526
  }
1510
1527
 
1528
+ // Ambient Intelligence: sugere evolução se há learnings acumulados
1529
+ if (!options.json && !options['no-health']) {
1530
+ try {
1531
+ const { getHealthDigest } = require('./health');
1532
+ const items = await getHealthDigest(targetDir);
1533
+ if (items && items.length > 0) {
1534
+ logger.log('');
1535
+ logger.log('AIOSON Health — itens após sessão:');
1536
+ for (const item of items) {
1537
+ logger.log(` ● ${item}`);
1538
+ }
1539
+ logger.log(' → aioson health . para detalhes e ações');
1540
+ logger.log('');
1541
+ }
1542
+ } catch { /* não bloqueia o close */ }
1543
+ }
1544
+
1511
1545
  return {
1512
1546
  ok: true,
1513
1547
  targetDir,
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+ const { generateSessionRecovery, readSessionRecovery } = require('../recovery-context-session');
5
+
6
+ async function runRecoveryGenerate({ args, options, logger }) {
7
+ const cwd = path.resolve(process.cwd(), args[0] || '.');
8
+ const sessionState = {
9
+ goal: options.goal || undefined,
10
+ agent: options.agent || undefined,
11
+ tasks: [],
12
+ notes: []
13
+ };
14
+
15
+ const result = await generateSessionRecovery(cwd, sessionState);
16
+
17
+ if (!result.ok) {
18
+ logger.error(`recovery:generate failed: ${result.error}`);
19
+ return result;
20
+ }
21
+
22
+ logger.log(`Recovery context generated: ${result.path} (${result.tokens} tokens)`);
23
+ return result;
24
+ }
25
+
26
+ async function runRecoveryShow({ args, options, logger }) {
27
+ const cwd = path.resolve(process.cwd(), args[0] || '.');
28
+ const content = await readSessionRecovery(cwd);
29
+
30
+ if (!content) {
31
+ logger.log('No recovery context found. Run: aioson recovery:generate');
32
+ return { ok: false, error: 'not_found' };
33
+ }
34
+
35
+ if (options.json) {
36
+ return { ok: true, content };
37
+ }
38
+
39
+ logger.log(content);
40
+ return { ok: true, content };
41
+ }
42
+
43
+ module.exports = { runRecoveryGenerate, runRecoveryShow };