@jaimevalasek/aioson 1.5.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +729 -226
  3. package/docs/design-previews/aurora-command-ui-website.html +884 -0
  4. package/docs/design-previews/aurora-command-ui.html +682 -0
  5. package/docs/design-previews/bold-editorial-ui-website.html +658 -0
  6. package/docs/design-previews/bold-editorial-ui.html +717 -0
  7. package/docs/design-previews/clean-saas-ui-website.html +1202 -0
  8. package/docs/design-previews/clean-saas-ui.html +549 -0
  9. package/docs/design-previews/cognitive-core-ui-website.html +1009 -0
  10. package/docs/design-previews/cognitive-core-ui.html +463 -0
  11. package/docs/design-previews/glassmorphism-ui-website.html +572 -0
  12. package/docs/design-previews/glassmorphism-ui.html +886 -0
  13. package/docs/design-previews/index.html +699 -0
  14. package/docs/design-previews/interface-design-website.html +1187 -0
  15. package/docs/design-previews/interface-design.html +513 -0
  16. package/docs/design-previews/neo-brutalist-ui-website.html +621 -0
  17. package/docs/design-previews/neo-brutalist-ui.html +797 -0
  18. package/docs/design-previews/premium-command-center-ui-website.html +1217 -0
  19. package/docs/design-previews/premium-command-center-ui.html +552 -0
  20. package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
  21. package/docs/design-previews/warm-craft-ui-website.html +684 -0
  22. package/docs/design-previews/warm-craft-ui.html +739 -0
  23. package/docs/en/cli-reference.md +20 -9
  24. package/docs/integrations/sdlc-genius-boundary.md +76 -0
  25. package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
  26. package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
  27. package/docs/integrations/sdlc-genius-review-samples.md +86 -0
  28. package/docs/pt/README.md +10 -0
  29. package/docs/pt/agent-sharding.md +132 -0
  30. package/docs/pt/agentes.md +9 -2
  31. package/docs/pt/busca-de-contexto.md +129 -0
  32. package/docs/pt/cache-de-contexto.md +156 -0
  33. package/docs/pt/comandos-cli.md +915 -1
  34. package/docs/pt/design-hybrid-forge.md +356 -0
  35. package/docs/pt/devlog-pipeline.md +270 -0
  36. package/docs/pt/fluxo-artefatos.md +178 -0
  37. package/docs/pt/hooks-session-guard.md +454 -0
  38. package/docs/pt/inicio-rapido.md +54 -3
  39. package/docs/pt/inteligencia-adaptativa.md +324 -0
  40. package/docs/pt/monitor-de-contexto.md +158 -0
  41. package/docs/pt/recuperacao-de-sessao.md +125 -0
  42. package/docs/pt/sandbox.md +125 -0
  43. package/docs/pt/sdd-automation-scripts.md +557 -0
  44. package/docs/pt/site-forge.md +309 -0
  45. package/docs/pt/skills.md +98 -6
  46. package/docs/pt/spec-learnings-pipeline.md +265 -0
  47. package/package.json +1 -1
  48. package/src/a2a/client.js +165 -0
  49. package/src/a2a/server.js +223 -0
  50. package/src/agent-loader.js +280 -0
  51. package/src/cli.js +329 -1
  52. package/src/commands/agent-audit.js +397 -0
  53. package/src/commands/agent-export-skill.js +229 -0
  54. package/src/commands/agent-loader.js +85 -0
  55. package/src/commands/artifact-validate.js +189 -0
  56. package/src/commands/brief-gen.js +405 -0
  57. package/src/commands/brief-validate.js +65 -0
  58. package/src/commands/classify.js +256 -0
  59. package/src/commands/context-cache.js +90 -0
  60. package/src/commands/context-compact.js +49 -0
  61. package/src/commands/context-health.js +175 -0
  62. package/src/commands/context-monitor.js +163 -0
  63. package/src/commands/context-search.js +66 -0
  64. package/src/commands/context-trim.js +177 -0
  65. package/src/commands/design-hybrid-options.js +385 -0
  66. package/src/commands/detect-test-runner.js +55 -0
  67. package/src/commands/devlog-export-brains.js +27 -0
  68. package/src/commands/devlog-process.js +292 -0
  69. package/src/commands/devlog-watch.js +131 -0
  70. package/src/commands/feature-close.js +165 -0
  71. package/src/commands/gate-check.js +228 -0
  72. package/src/commands/health.js +214 -0
  73. package/src/commands/hooks-emit.js +253 -0
  74. package/src/commands/hooks-install.js +347 -0
  75. package/src/commands/init.js +54 -13
  76. package/src/commands/install.js +52 -13
  77. package/src/commands/learning-auto-promote.js +195 -0
  78. package/src/commands/learning-evolve.js +364 -0
  79. package/src/commands/learning-export.js +103 -0
  80. package/src/commands/learning-rollback.js +164 -0
  81. package/src/commands/live.js +59 -1
  82. package/src/commands/pattern-detect.js +33 -0
  83. package/src/commands/preflight-context.js +30 -0
  84. package/src/commands/preflight.js +208 -0
  85. package/src/commands/pulse-update.js +130 -0
  86. package/src/commands/recovery.js +43 -0
  87. package/src/commands/runner-daemon.js +274 -0
  88. package/src/commands/runner-plan.js +70 -0
  89. package/src/commands/runner-queue-from-plan.js +166 -0
  90. package/src/commands/runner-queue.js +189 -0
  91. package/src/commands/runner-run.js +129 -0
  92. package/src/commands/runtime.js +47 -1
  93. package/src/commands/sandbox.js +37 -0
  94. package/src/commands/self-implement-loop.js +256 -0
  95. package/src/commands/session-guard.js +218 -0
  96. package/src/commands/setup-context.js +22 -2
  97. package/src/commands/setup.js +178 -0
  98. package/src/commands/sizing.js +165 -0
  99. package/src/commands/skill.js +144 -32
  100. package/src/commands/spec-checkpoint.js +177 -0
  101. package/src/commands/spec-status.js +79 -0
  102. package/src/commands/spec-sync.js +190 -0
  103. package/src/commands/spec-tasks.js +288 -0
  104. package/src/commands/squad-autorun.js +1220 -0
  105. package/src/commands/squad-bus.js +217 -0
  106. package/src/commands/squad-card.js +149 -0
  107. package/src/commands/squad-daemon.js +134 -0
  108. package/src/commands/squad-dependency-graph.js +164 -0
  109. package/src/commands/squad-review.js +106 -0
  110. package/src/commands/squad-scaffold.js +55 -0
  111. package/src/commands/squad-tool-register.js +157 -0
  112. package/src/commands/state-save.js +122 -0
  113. package/src/commands/tool-registry-cmd.js +232 -0
  114. package/src/commands/update.js +9 -0
  115. package/src/commands/verify-gate.js +572 -0
  116. package/src/commands/workflow-execute.js +241 -0
  117. package/src/constants.js +18 -0
  118. package/src/context-cache.js +159 -0
  119. package/src/context-search.js +326 -0
  120. package/src/design-variation-catalog.js +503 -0
  121. package/src/i18n/messages/en.js +32 -2
  122. package/src/i18n/messages/es.js +30 -2
  123. package/src/i18n/messages/fr.js +30 -2
  124. package/src/i18n/messages/pt-BR.js +32 -2
  125. package/src/install-animation.js +260 -0
  126. package/src/install-profile.js +143 -0
  127. package/src/install-wizard.js +475 -0
  128. package/src/installer.js +44 -10
  129. package/src/lib/health-check.js +158 -0
  130. package/src/lib/hook-protocol.js +76 -0
  131. package/src/mcp/apps/squad-dashboard/app.js +163 -0
  132. package/src/mcp/apps/squad-dashboard/index.html +261 -0
  133. package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
  134. package/src/mcp/resources/squad-state.js +130 -0
  135. package/src/parser.js +7 -1
  136. package/src/preflight-engine.js +443 -0
  137. package/src/recovery-context-session.js +154 -0
  138. package/src/runner/cascade.js +97 -0
  139. package/src/runner/cli-launcher.js +109 -0
  140. package/src/runner/plan-importer.js +63 -0
  141. package/src/runner/queue-store.js +159 -0
  142. package/src/runtime-store.js +158 -4
  143. package/src/sandbox.js +177 -0
  144. package/src/squad/agent-teams-adapter.js +264 -0
  145. package/src/squad/brief-validator.js +350 -0
  146. package/src/squad/bus-bridge.js +140 -0
  147. package/src/squad/context-compactor.js +265 -0
  148. package/src/squad/cross-ai-synthesizer.js +250 -0
  149. package/src/squad/hooks-generator.js +196 -0
  150. package/src/squad/inter-squad-events.js +175 -0
  151. package/src/squad/intra-bus.js +345 -0
  152. package/src/squad/learning-extractor.js +213 -0
  153. package/src/squad/pattern-detector.js +365 -0
  154. package/src/squad/preflight-context.js +296 -0
  155. package/src/squad/recovery-context.js +242 -71
  156. package/src/squad/reflection.js +365 -0
  157. package/src/squad/squad-scaffold.js +177 -0
  158. package/src/squad/state-manager.js +310 -0
  159. package/src/squad/task-decomposer.js +652 -0
  160. package/src/squad/verify-gate.js +303 -0
  161. package/src/tool-executor.js +94 -0
  162. package/src/updater.js +10 -3
  163. package/src/worker-runner.js +186 -1
  164. package/template/.aioson/agents/analyst.md +119 -3
  165. package/template/.aioson/agents/architect.md +98 -0
  166. package/template/.aioson/agents/design-hybrid-forge.md +141 -0
  167. package/template/.aioson/agents/dev.md +335 -14
  168. package/template/.aioson/agents/deyvin.md +117 -2
  169. package/template/.aioson/agents/discovery-design-doc.md +44 -0
  170. package/template/.aioson/agents/genome.md +14 -0
  171. package/template/.aioson/agents/neo.md +78 -1
  172. package/template/.aioson/agents/orache.md +50 -4
  173. package/template/.aioson/agents/orchestrator.md +197 -1
  174. package/template/.aioson/agents/pm.md +93 -0
  175. package/template/.aioson/agents/product.md +77 -4
  176. package/template/.aioson/agents/profiler-enricher.md +14 -0
  177. package/template/.aioson/agents/profiler-forge.md +14 -0
  178. package/template/.aioson/agents/profiler-researcher.md +14 -0
  179. package/template/.aioson/agents/qa.md +249 -19
  180. package/template/.aioson/agents/setup.md +144 -12
  181. package/template/.aioson/agents/sheldon.md +237 -11
  182. package/template/.aioson/agents/site-forge.md +1753 -0
  183. package/template/.aioson/agents/squad.md +162 -0
  184. package/template/.aioson/agents/tester.md +209 -0
  185. package/template/.aioson/agents/ux-ui.md +34 -1
  186. package/template/.aioson/brains/README.md +128 -0
  187. package/template/.aioson/brains/_index.json +16 -0
  188. package/template/.aioson/brains/scripts/query.js +103 -0
  189. package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
  190. package/template/.aioson/config.md +158 -13
  191. package/template/.aioson/constitution.md +33 -0
  192. package/template/.aioson/context/forensics/.gitkeep +0 -0
  193. package/template/.aioson/context/project-pulse.md +34 -0
  194. package/template/.aioson/context/seeds/seed-example.md +27 -0
  195. package/template/.aioson/context/user-profile.md +42 -0
  196. package/template/.aioson/docs/LAYERS.md +79 -0
  197. package/template/.aioson/docs/README.md +76 -0
  198. package/template/.aioson/docs/example-external-api-context.md +72 -0
  199. package/template/.aioson/locales/en/agents/architect.md +17 -0
  200. package/template/.aioson/locales/en/agents/dev.md +79 -13
  201. package/template/.aioson/locales/en/agents/orache.md +6 -0
  202. package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
  203. package/template/.aioson/locales/en/agents/product.md +50 -0
  204. package/template/.aioson/locales/en/agents/setup.md +33 -1
  205. package/template/.aioson/locales/en/agents/sheldon.md +115 -0
  206. package/template/.aioson/locales/en/agents/squad.md +14 -0
  207. package/template/.aioson/locales/en/agents/tester.md +6 -0
  208. package/template/.aioson/locales/es/agents/analyst.md +2 -0
  209. package/template/.aioson/locales/es/agents/architect.md +19 -0
  210. package/template/.aioson/locales/es/agents/dev.md +64 -4
  211. package/template/.aioson/locales/es/agents/deyvin.md +2 -0
  212. package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
  213. package/template/.aioson/locales/es/agents/genome.md +2 -0
  214. package/template/.aioson/locales/es/agents/neo.md +2 -0
  215. package/template/.aioson/locales/es/agents/orache.md +2 -0
  216. package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
  217. package/template/.aioson/locales/es/agents/pair.md +2 -0
  218. package/template/.aioson/locales/es/agents/pm.md +2 -0
  219. package/template/.aioson/locales/es/agents/product.md +52 -0
  220. package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
  221. package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
  222. package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
  223. package/template/.aioson/locales/es/agents/qa.md +2 -0
  224. package/template/.aioson/locales/es/agents/setup.md +35 -1
  225. package/template/.aioson/locales/es/agents/sheldon.md +117 -0
  226. package/template/.aioson/locales/es/agents/squad.md +16 -0
  227. package/template/.aioson/locales/es/agents/tester.md +9 -0
  228. package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
  229. package/template/.aioson/locales/fr/agents/analyst.md +2 -0
  230. package/template/.aioson/locales/fr/agents/architect.md +19 -0
  231. package/template/.aioson/locales/fr/agents/dev.md +64 -4
  232. package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
  233. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
  234. package/template/.aioson/locales/fr/agents/genome.md +2 -0
  235. package/template/.aioson/locales/fr/agents/neo.md +2 -0
  236. package/template/.aioson/locales/fr/agents/orache.md +2 -0
  237. package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
  238. package/template/.aioson/locales/fr/agents/pair.md +2 -0
  239. package/template/.aioson/locales/fr/agents/pm.md +2 -0
  240. package/template/.aioson/locales/fr/agents/product.md +52 -0
  241. package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
  242. package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
  243. package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
  244. package/template/.aioson/locales/fr/agents/qa.md +2 -0
  245. package/template/.aioson/locales/fr/agents/setup.md +35 -1
  246. package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
  247. package/template/.aioson/locales/fr/agents/squad.md +16 -0
  248. package/template/.aioson/locales/fr/agents/tester.md +9 -0
  249. package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
  250. package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
  251. package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
  252. package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
  253. package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
  254. package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
  255. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
  256. package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
  257. package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
  258. package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
  259. package/template/.aioson/locales/pt-BR/agents/setup.md +134 -19
  260. package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
  261. package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
  262. package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
  263. package/template/.aioson/rules/README.md +69 -0
  264. package/template/.aioson/rules/data-format-convention.md +136 -0
  265. package/template/.aioson/rules/example-monetary-values.md +30 -0
  266. package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
  267. package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +243 -0
  268. package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -0
  269. package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -0
  270. package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -0
  271. package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -0
  272. package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -0
  273. package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +482 -0
  274. package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +387 -0
  275. package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +222 -0
  276. package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -0
  277. package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -0
  278. package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -0
  279. package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -0
  280. package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -0
  281. package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -0
  282. package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -0
  283. package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +213 -0
  284. package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -0
  285. package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -0
  286. package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -0
  287. package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -0
  288. package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -0
  289. package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -0
  290. package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -0
  291. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
  292. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
  293. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
  294. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
  295. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
  296. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
  297. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
  298. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +46 -0
  299. package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
  300. package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +109 -0
  301. package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
  302. package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +44 -0
  303. package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +37 -0
  304. package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
  305. package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
  306. package/template/.aioson/skills/process/aioson-spec-driven/references/hardening-lane.md +49 -0
  307. package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +101 -0
  308. package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
  309. package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
  310. package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
  311. package/template/.aioson/skills/process/aioson-spec-driven/references/ui-language.md +75 -0
  312. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +147 -0
  313. package/template/.aioson/skills/process/design-hybrid-forge/references/crossover-protocol.md +221 -0
  314. package/template/.aioson/skills/process/design-hybrid-forge/references/naming-registry.md +88 -0
  315. package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +306 -0
  316. package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +149 -0
  317. package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +208 -0
  318. package/template/.aioson/skills/process/design-hybrid-forge/references/variation-library.md +125 -0
  319. package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
  320. package/template/.aioson/skills/static/context-budget-guide.md +46 -0
  321. package/template/.aioson/skills/static/harness-sensors.md +74 -0
  322. package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
  323. package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
  324. package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
  325. package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
  326. package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
  327. package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
  328. package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
  329. package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
  330. package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
  331. package/template/.aioson/skills/static/threejs-patterns.md +929 -0
  332. package/template/.aioson/skills/static/web-research-cache.md +112 -0
  333. package/template/.aioson/tasks/implementation-plan.md +21 -1
  334. package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
  335. package/template/.claude/commands/aioson/agent/orache.md +5 -0
  336. package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
  337. package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
  338. package/template/AGENTS.md +75 -1
  339. package/template/CLAUDE.md +31 -0
  340. package/template/OPENCODE.md +4 -0
  341. package/template/researchs/.gitkeep +0 -0
@@ -2,20 +2,23 @@
2
2
 
3
3
  const fs = require('node:fs/promises');
4
4
  const path = require('node:path');
5
+ const stateManager = require('./state-manager');
5
6
 
6
7
  const SQUADS_DIR = path.join('.aioson', 'squads');
8
+ const MAX_HISTORY_ENTRIES = 5;
9
+ const MAX_TOKENS = 2000;
10
+ const HISTORY_TOKEN_BUDGET = 600; // tokens reserved for history section
7
11
 
8
12
  // Events that trigger an automatic refresh of the recovery context
9
13
  const REFRESH_EVENTS = new Set(['task_completed', 'decision_made', 'handoff']);
10
14
 
11
- // Approximate token count (chars / 4)
15
+ // Approximate token count (chars / 4) + 1
12
16
  function estimateTokens(str) {
13
- return Math.ceil(str.length / 4);
17
+ return Math.ceil(str.length / 4) + 1;
14
18
  }
15
19
 
16
- /**
17
- * Read squad manifest (best-effort, returns {} on failure).
18
- */
20
+ // ─── Data loaders ─────────────────────────────────────────────────────────────
21
+
19
22
  async function readManifest(projectDir, squadSlug) {
20
23
  const p = path.join(projectDir, SQUADS_DIR, squadSlug, 'squad.manifest.json');
21
24
  try {
@@ -26,27 +29,56 @@ async function readManifest(projectDir, squadSlug) {
26
29
  }
27
30
 
28
31
  /**
29
- * Read recent events from session-log.json (last N entries).
32
+ * Read recent bus events from the bus/ directory (JSONL files).
33
+ * Falls back gracefully if no sessions exist yet.
30
34
  */
31
35
  async function readRecentEvents(projectDir, squadSlug, limit = 10) {
32
- const p = path.join(projectDir, SQUADS_DIR, squadSlug, 'session-log.json');
36
+ const busDir = path.join(projectDir, SQUADS_DIR, squadSlug, 'bus');
33
37
  try {
34
- const raw = JSON.parse(await fs.readFile(p, 'utf8'));
35
- const entries = Array.isArray(raw) ? raw : (raw.entries || []);
36
- return entries.slice(-limit);
38
+ const entries = await fs.readdir(busDir, { withFileTypes: true });
39
+ const jsonlFiles = entries
40
+ .filter((e) => e.isFile() && e.name.endsWith('.jsonl'))
41
+ .map((e) => path.join(busDir, e.name));
42
+
43
+ if (jsonlFiles.length === 0) return [];
44
+
45
+ // Read the most recent file (sorted by name — sessions use UUIDs/timestamps)
46
+ const sorted = jsonlFiles.sort();
47
+ const recentFile = sorted[sorted.length - 1];
48
+ const content = await fs.readFile(recentFile, 'utf8');
49
+
50
+ const events = content
51
+ .split('\n')
52
+ .filter((line) => line.trim())
53
+ .map((line) => { try { return JSON.parse(line); } catch { return null; } })
54
+ .filter(Boolean);
55
+
56
+ return events.slice(-limit);
37
57
  } catch {
38
58
  return [];
39
59
  }
40
60
  }
41
61
 
42
62
  /**
43
- * Read recent tasks from tasks.json (last 5, enriched).
63
+ * Read recent tasks from the most recent session plan.json.
64
+ * Falls back gracefully if no sessions exist yet.
44
65
  */
45
66
  async function readRecentTasks(projectDir, squadSlug, limit = 5) {
46
- const p = path.join(projectDir, SQUADS_DIR, squadSlug, 'tasks.json');
67
+ const sessionsDir = path.join(projectDir, SQUADS_DIR, squadSlug, 'sessions');
47
68
  try {
48
- const raw = JSON.parse(await fs.readFile(p, 'utf8'));
49
- const tasks = Array.isArray(raw) ? raw : (raw.tasks || []);
69
+ const sessionEntries = await fs.readdir(sessionsDir, { withFileTypes: true });
70
+ const sessionDirs = sessionEntries
71
+ .filter((e) => e.isDirectory())
72
+ .map((e) => e.name)
73
+ .sort(); // lexicographic — UUID/timestamp sorts correctly
74
+
75
+ if (sessionDirs.length === 0) return [];
76
+
77
+ // Use most recent session
78
+ const latestSession = sessionDirs[sessionDirs.length - 1];
79
+ const planPath = path.join(sessionsDir, latestSession, 'plan.json');
80
+ const plan = JSON.parse(await fs.readFile(planPath, 'utf8'));
81
+ const tasks = Array.isArray(plan.tasks) ? plan.tasks : [];
50
82
  return tasks.slice(-limit);
51
83
  } catch {
52
84
  return [];
@@ -54,132 +86,266 @@ async function readRecentTasks(projectDir, squadSlug, limit = 5) {
54
86
  }
55
87
 
56
88
  /**
57
- * Read context-monitor.json snapshot for an agent.
89
+ * Read context snapshot from STATE.md via state-manager.
90
+ * Returns a simplified snapshot compatible with buildCurrentState().
58
91
  */
59
- async function readContextSnapshot(projectDir, squadSlug, agentSlug) {
60
- const p = path.join(projectDir, SQUADS_DIR, squadSlug, 'context-monitor.json');
92
+ async function readContextSnapshot(projectDir, squadSlug) {
61
93
  try {
62
- const data = JSON.parse(await fs.readFile(p, 'utf8'));
63
- if (agentSlug && data.agents && data.agents[agentSlug]) {
64
- return data.agents[agentSlug];
65
- }
66
- return data;
94
+ const state = await stateManager.readState(projectDir, squadSlug);
95
+ if (!state) return null;
96
+ return {
97
+ currentPhase: state.meta.current_session || '',
98
+ recentDecisions: (state.decisions || []).slice(-5),
99
+ activeBlockers: state.blockers || [],
100
+ sessionsCompleted: state.meta.sessions_completed || 0
101
+ };
67
102
  } catch {
68
103
  return null;
69
104
  }
70
105
  }
71
106
 
107
+ // ─── Incremental compaction history ──────────────────────────────────────────
108
+
72
109
  /**
73
- * Build the markdown content for recovery-context.md.
74
- * Target < 2000 tokens.
110
+ * Extract the "## Compaction History" section from an existing recovery-context.md.
111
+ * Returns an array of raw entry strings (trimmed), oldest first.
75
112
  */
76
- function buildRecoveryMarkdown(squadSlug, agentSlug, manifest, tasks, events, ctxSnapshot) {
77
- const lines = [];
113
+ function extractCompactionHistory(existingContent) {
114
+ if (!existingContent) return [];
115
+
116
+ const match = existingContent.match(/## Compaction History\n([\s\S]*?)(?=\n---|\n## [^C]|$)/);
117
+ if (!match) return [];
78
118
 
79
- lines.push(`# Recovery Context ${squadSlug} / ${agentSlug}`);
80
- lines.push(`> Generated: ${new Date().toISOString()}`);
81
- lines.push('');
119
+ // Split on "### Snapshot" entries
120
+ const raw = match[1].trim();
121
+ if (!raw) return [];
122
+
123
+ const entries = raw.split(/(?=### Snapshot)/).map((e) => e.trim()).filter(Boolean);
124
+ return entries;
125
+ }
126
+
127
+ /**
128
+ * Extract the "## Current State" section from an existing recovery-context.md.
129
+ * This becomes a history entry when a new snapshot is generated.
130
+ */
131
+ function extractCurrentState(existingContent) {
132
+ if (!existingContent) return null;
133
+
134
+ const match = existingContent.match(/## Current State\n([\s\S]*?)(?=\n## |$)/);
135
+ if (!match) return null;
136
+
137
+ const body = match[1].trim();
138
+ if (!body) return null;
139
+
140
+ // Wrap as a Snapshot history entry
141
+ const ts = existingContent.match(/> Last Updated: (.+)/)?.[1] || new Date().toISOString();
142
+ return `### Snapshot — ${ts}\n${body}`;
143
+ }
144
+
145
+ // ─── Snapshot builder ─────────────────────────────────────────────────────────
146
+
147
+ /**
148
+ * Build the "Current State" section content from live data.
149
+ * This is the fresh snapshot injected on every recovery update.
150
+ */
151
+ function buildCurrentState(squadSlug, agentSlug, manifest, tasks, events, ctxSnapshot) {
152
+ const lines = [];
82
153
 
83
154
  // Squad goal
84
155
  if (manifest.goal) {
85
- lines.push('## Squad Goal');
86
- lines.push(manifest.goal);
156
+ lines.push(`**Squad goal:** ${manifest.goal}`);
87
157
  lines.push('');
88
158
  }
89
159
 
90
- // Agent role (from executors array)
91
- const executor = (manifest.executors || []).find(e => e.slug === agentSlug);
160
+ // Agent role
161
+ const executor = (manifest.executors || []).find((e) => e.slug === agentSlug);
92
162
  if (executor) {
93
- lines.push('## Your Role');
94
- lines.push(`**${executor.title || agentSlug}**: ${executor.role || ''}`);
163
+ lines.push(`**Your role:** ${executor.title || agentSlug} — ${executor.role || ''}`);
95
164
  lines.push('');
96
165
  }
97
166
 
98
- // Recent tasks
167
+ // Recent tasks (most recent first, capped)
99
168
  if (tasks.length > 0) {
100
- lines.push('## Recent Tasks');
169
+ lines.push('**Recent tasks:**');
101
170
  for (const t of tasks) {
102
171
  const status = t.status || 'unknown';
103
172
  const title = t.title || t.slug || t.id || '(untitled)';
104
173
  lines.push(`- [${status}] ${title}`);
105
174
  if (t.output && typeof t.output === 'string') {
106
- // Truncate long outputs
107
- const out = t.output.length > 200 ? t.output.slice(0, 200) + '…' : t.output;
108
- lines.push(` Output: ${out}`);
175
+ const out = t.output.length > 150 ? t.output.slice(0, 150) + '…' : t.output;
176
+ lines.push(` → ${out}`);
109
177
  }
110
178
  }
111
179
  lines.push('');
112
180
  }
113
181
 
114
- // Recent events
182
+ // Recent events (brief)
115
183
  if (events.length > 0) {
116
- lines.push('## Recent Events');
117
- for (const ev of events) {
118
- const ts = ev.created_at || ev.timestamp || '';
184
+ lines.push('**Recent events:**');
185
+ for (const ev of events.slice(-5)) {
119
186
  const type = ev.event_type || ev.type || 'event';
120
187
  const msg = ev.message || ev.summary || '';
121
- lines.push(`- [${ts}] ${type}: ${msg}`);
188
+ lines.push(`- ${type}: ${msg}`);
122
189
  }
123
190
  lines.push('');
124
191
  }
125
192
 
126
- // Context snapshot
193
+ // State snapshot (from STATE.md via state-manager)
127
194
  if (ctxSnapshot) {
128
- lines.push('## Context Window at Last Compact');
129
- const used = ctxSnapshot.totalUsed || 0;
130
- const win = ctxSnapshot.windowSize || 0;
131
- const pct = win > 0 ? Math.round((used / win) * 100) : 0;
132
- lines.push(`Used: ${used.toLocaleString()} / ${win.toLocaleString()} tokens (${pct}%)`);
133
- lines.push('');
195
+ if (ctxSnapshot.sessionsCompleted) {
196
+ lines.push(`**Sessions completed:** ${ctxSnapshot.sessionsCompleted}`);
197
+ }
198
+ if (ctxSnapshot.recentDecisions && ctxSnapshot.recentDecisions.length > 0) {
199
+ lines.push('**Recent decisions:**');
200
+ for (const d of ctxSnapshot.recentDecisions.slice(-3)) {
201
+ const text = typeof d === 'string' ? d : (d.text || JSON.stringify(d));
202
+ lines.push(`- ${text}`);
203
+ }
204
+ lines.push('');
205
+ }
206
+ if (ctxSnapshot.activeBlockers && ctxSnapshot.activeBlockers.length > 0) {
207
+ lines.push('**Active blockers:**');
208
+ for (const b of ctxSnapshot.activeBlockers) {
209
+ const text = typeof b === 'string' ? b : (b.text || JSON.stringify(b));
210
+ lines.push(`- ${text}`);
211
+ }
212
+ lines.push('');
213
+ }
134
214
  }
135
215
 
136
- lines.push('---');
137
- lines.push('*Inject this file at the top of your next session to restore context after a compact.*');
216
+ return lines.join('\n');
217
+ }
218
+
219
+ // ─── Full incremental markdown builder ───────────────────────────────────────
220
+
221
+ /**
222
+ * Build the incremental recovery-context.md content.
223
+ *
224
+ * Strategy:
225
+ * 1. Extract current "Current State" from existing file → becomes history entry
226
+ * 2. Build fresh "Current State" from live data
227
+ * 3. Assemble: header + current state + history (oldest → newest, capped)
228
+ * 4. Enforce MAX_TOKENS budget by trimming history first
229
+ */
230
+ function buildIncrementalRecovery(
231
+ squadSlug, agentSlug,
232
+ manifest, tasks, events, ctxSnapshot,
233
+ existingContent
234
+ ) {
235
+ const now = new Date().toISOString();
236
+
237
+ // Build fresh current state
238
+ const currentState = buildCurrentState(squadSlug, agentSlug, manifest, tasks, events, ctxSnapshot);
239
+
240
+ // Gather history: existing history entries + previous current state (if any)
241
+ const prevState = extractCurrentState(existingContent);
242
+ const existingHistory = extractCompactionHistory(existingContent);
243
+
244
+ let historyEntries = [...existingHistory];
245
+ if (prevState) historyEntries.push(prevState);
246
+ // Keep only the most recent MAX_HISTORY_ENTRIES - 1 entries (we add current above)
247
+ historyEntries = historyEntries.slice(-(MAX_HISTORY_ENTRIES - 1));
248
+
249
+ // Assemble full content
250
+ const headerLines = [
251
+ `# Recovery Context — ${squadSlug} / ${agentSlug}`,
252
+ `> Last Updated: ${now}`,
253
+ '',
254
+ '## Current State',
255
+ currentState,
256
+ ''
257
+ ];
258
+
259
+ const historyLines = historyEntries.length > 0
260
+ ? ['## Compaction History', '*Previous snapshots — oldest → newest:*', '', ...historyEntries.map((e) => e + '\n'), '']
261
+ : [];
138
262
 
139
- const content = lines.join('\n');
263
+ const footerLines = [
264
+ '---',
265
+ '*Inject at top of session to restore context after compact.*'
266
+ ];
140
267
 
141
- // Enforce token limit: if over budget, trim events section
142
- if (estimateTokens(content) > 2000) {
143
- // Rebuild with fewer events
144
- return buildRecoveryMarkdown(squadSlug, agentSlug, manifest, tasks, events.slice(-3), ctxSnapshot);
268
+ const allLines = [...headerLines, ...historyLines, ...footerLines];
269
+ let content = allLines.join('\n');
270
+
271
+ // Enforce token budget: trim history entries if needed
272
+ while (estimateTokens(content) > MAX_TOKENS && historyEntries.length > 0) {
273
+ historyEntries.shift(); // remove oldest entry
274
+ const trimmedHistoryLines = historyEntries.length > 0
275
+ ? ['## Compaction History', '*Previous snapshots — oldest → newest:*', '', ...historyEntries.map((e) => e + '\n'), '']
276
+ : [];
277
+ content = [...headerLines, ...trimmedHistoryLines, ...footerLines].join('\n');
145
278
  }
146
279
 
147
280
  return content;
148
281
  }
149
282
 
283
+ // ─── Public API ───────────────────────────────────────────────────────────────
284
+
150
285
  /**
151
- * Generate and write recovery-context.md for an agent.
286
+ * Generate and write recovery-context.md for a squad agent.
287
+ * Uses incremental merging: preserves compaction history across cycles.
288
+ *
152
289
  * @param {string} projectDir
153
290
  * @param {string} squadSlug
154
291
  * @param {string} agentSlug
155
- * @returns {{ ok: boolean, path: string, tokens: number }}
292
+ * @returns {{ ok: boolean, path: string, tokens: number, incremental: boolean }}
156
293
  */
157
294
  async function generateRecovery(projectDir, squadSlug, agentSlug) {
158
- const [manifest, tasks, events, ctxSnapshot] = await Promise.all([
295
+ const outDir = path.join(projectDir, SQUADS_DIR, squadSlug);
296
+ const outPath = path.join(outDir, 'recovery-context.md');
297
+
298
+ const [manifest, tasks, events, ctxSnapshot, existingContent] = await Promise.all([
159
299
  readManifest(projectDir, squadSlug),
160
300
  readRecentTasks(projectDir, squadSlug),
161
301
  readRecentEvents(projectDir, squadSlug),
162
- readContextSnapshot(projectDir, squadSlug, agentSlug)
302
+ readContextSnapshot(projectDir, squadSlug),
303
+ fs.readFile(outPath, 'utf8').catch(() => null)
163
304
  ]);
164
305
 
165
- const content = buildRecoveryMarkdown(squadSlug, agentSlug, manifest, tasks, events, ctxSnapshot);
306
+ const content = buildIncrementalRecovery(
307
+ squadSlug, agentSlug,
308
+ manifest, tasks, events, ctxSnapshot,
309
+ existingContent
310
+ );
311
+
166
312
  const tokens = estimateTokens(content);
313
+ const incremental = Boolean(existingContent);
167
314
 
168
- const outDir = path.join(projectDir, SQUADS_DIR, squadSlug);
169
- const outPath = path.join(outDir, `recovery-context.md`);
315
+ // Build structured handoff JSON (consumed by MCP resources, Agent Teams adapter, etc.)
316
+ const completedTasks = tasks.filter((t) => t.status === 'completed').map((t) => t.title || t.id || '(untitled)');
317
+ const pendingTasks = tasks.filter((t) => t.status !== 'completed').map((t) => t.title || t.id || '(untitled)');
318
+ const handoffJson = {
319
+ agent: agentSlug,
320
+ squad: squadSlug,
321
+ session_id: null,
322
+ compacted_at: new Date().toISOString(),
323
+ summary: {
324
+ tasks_completed: completedTasks,
325
+ pending_work: pendingTasks,
326
+ key_files: [],
327
+ decisions: []
328
+ },
329
+ resume_instruction: 'Continue from this checkpoint. Do not acknowledge this summary.'
330
+ };
170
331
 
171
332
  try {
172
333
  await fs.mkdir(outDir, { recursive: true });
173
334
  await fs.writeFile(outPath, content, 'utf8');
335
+ await fs.writeFile(
336
+ path.join(outDir, 'last-handoff.json'),
337
+ JSON.stringify(handoffJson, null, 2),
338
+ 'utf8'
339
+ );
174
340
  } catch (err) {
175
- return { ok: false, error: err.message, path: outPath, tokens };
341
+ return { ok: false, error: err.message, path: outPath, tokens, incremental };
176
342
  }
177
343
 
178
- return { ok: true, path: outPath, tokens, squadSlug, agentSlug };
344
+ return { ok: true, path: outPath, tokens, squadSlug, agentSlug, incremental };
179
345
  }
180
346
 
181
347
  /**
182
- * Read the current recovery-context.md for an agent (returns null if missing).
348
+ * Read the current recovery-context.md for a squad (returns null if missing).
183
349
  */
184
350
  async function readRecovery(projectDir, squadSlug) {
185
351
  const p = path.join(projectDir, SQUADS_DIR, squadSlug, 'recovery-context.md');
@@ -192,10 +358,15 @@ async function readRecovery(projectDir, squadSlug) {
192
358
 
193
359
  /**
194
360
  * Check if a runtime event should trigger a recovery refresh.
195
- * @param {string} eventType
196
361
  */
197
362
  function shouldRefreshOnEvent(eventType) {
198
363
  return REFRESH_EVENTS.has(eventType);
199
364
  }
200
365
 
201
- module.exports = { generateRecovery, readRecovery, shouldRefreshOnEvent, REFRESH_EVENTS };
366
+ module.exports = {
367
+ generateRecovery,
368
+ readRecovery,
369
+ shouldRefreshOnEvent,
370
+ REFRESH_EVENTS,
371
+ estimateTokens
372
+ };