@jaimevalasek/aioson 1.5.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +729 -226
  3. package/docs/design-previews/aurora-command-ui-website.html +884 -0
  4. package/docs/design-previews/aurora-command-ui.html +682 -0
  5. package/docs/design-previews/bold-editorial-ui-website.html +658 -0
  6. package/docs/design-previews/bold-editorial-ui.html +717 -0
  7. package/docs/design-previews/clean-saas-ui-website.html +1202 -0
  8. package/docs/design-previews/clean-saas-ui.html +549 -0
  9. package/docs/design-previews/cognitive-core-ui-website.html +1009 -0
  10. package/docs/design-previews/cognitive-core-ui.html +463 -0
  11. package/docs/design-previews/glassmorphism-ui-website.html +572 -0
  12. package/docs/design-previews/glassmorphism-ui.html +886 -0
  13. package/docs/design-previews/index.html +699 -0
  14. package/docs/design-previews/interface-design-website.html +1187 -0
  15. package/docs/design-previews/interface-design.html +513 -0
  16. package/docs/design-previews/neo-brutalist-ui-website.html +621 -0
  17. package/docs/design-previews/neo-brutalist-ui.html +797 -0
  18. package/docs/design-previews/premium-command-center-ui-website.html +1217 -0
  19. package/docs/design-previews/premium-command-center-ui.html +552 -0
  20. package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
  21. package/docs/design-previews/warm-craft-ui-website.html +684 -0
  22. package/docs/design-previews/warm-craft-ui.html +739 -0
  23. package/docs/en/cli-reference.md +20 -9
  24. package/docs/integrations/sdlc-genius-boundary.md +76 -0
  25. package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
  26. package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
  27. package/docs/integrations/sdlc-genius-review-samples.md +86 -0
  28. package/docs/pt/README.md +10 -0
  29. package/docs/pt/agent-sharding.md +132 -0
  30. package/docs/pt/agentes.md +9 -2
  31. package/docs/pt/busca-de-contexto.md +129 -0
  32. package/docs/pt/cache-de-contexto.md +156 -0
  33. package/docs/pt/comandos-cli.md +915 -1
  34. package/docs/pt/design-hybrid-forge.md +356 -0
  35. package/docs/pt/devlog-pipeline.md +270 -0
  36. package/docs/pt/fluxo-artefatos.md +178 -0
  37. package/docs/pt/hooks-session-guard.md +454 -0
  38. package/docs/pt/inicio-rapido.md +54 -3
  39. package/docs/pt/inteligencia-adaptativa.md +324 -0
  40. package/docs/pt/monitor-de-contexto.md +158 -0
  41. package/docs/pt/recuperacao-de-sessao.md +125 -0
  42. package/docs/pt/sandbox.md +125 -0
  43. package/docs/pt/sdd-automation-scripts.md +557 -0
  44. package/docs/pt/site-forge.md +309 -0
  45. package/docs/pt/skills.md +98 -6
  46. package/docs/pt/spec-learnings-pipeline.md +265 -0
  47. package/package.json +1 -1
  48. package/src/a2a/client.js +165 -0
  49. package/src/a2a/server.js +223 -0
  50. package/src/agent-loader.js +280 -0
  51. package/src/cli.js +329 -1
  52. package/src/commands/agent-audit.js +397 -0
  53. package/src/commands/agent-export-skill.js +229 -0
  54. package/src/commands/agent-loader.js +85 -0
  55. package/src/commands/artifact-validate.js +189 -0
  56. package/src/commands/brief-gen.js +405 -0
  57. package/src/commands/brief-validate.js +65 -0
  58. package/src/commands/classify.js +256 -0
  59. package/src/commands/context-cache.js +90 -0
  60. package/src/commands/context-compact.js +49 -0
  61. package/src/commands/context-health.js +175 -0
  62. package/src/commands/context-monitor.js +163 -0
  63. package/src/commands/context-search.js +66 -0
  64. package/src/commands/context-trim.js +177 -0
  65. package/src/commands/design-hybrid-options.js +385 -0
  66. package/src/commands/detect-test-runner.js +55 -0
  67. package/src/commands/devlog-export-brains.js +27 -0
  68. package/src/commands/devlog-process.js +292 -0
  69. package/src/commands/devlog-watch.js +131 -0
  70. package/src/commands/feature-close.js +165 -0
  71. package/src/commands/gate-check.js +228 -0
  72. package/src/commands/health.js +214 -0
  73. package/src/commands/hooks-emit.js +253 -0
  74. package/src/commands/hooks-install.js +347 -0
  75. package/src/commands/init.js +54 -13
  76. package/src/commands/install.js +52 -13
  77. package/src/commands/learning-auto-promote.js +195 -0
  78. package/src/commands/learning-evolve.js +364 -0
  79. package/src/commands/learning-export.js +103 -0
  80. package/src/commands/learning-rollback.js +164 -0
  81. package/src/commands/live.js +59 -1
  82. package/src/commands/pattern-detect.js +33 -0
  83. package/src/commands/preflight-context.js +30 -0
  84. package/src/commands/preflight.js +208 -0
  85. package/src/commands/pulse-update.js +130 -0
  86. package/src/commands/recovery.js +43 -0
  87. package/src/commands/runner-daemon.js +274 -0
  88. package/src/commands/runner-plan.js +70 -0
  89. package/src/commands/runner-queue-from-plan.js +166 -0
  90. package/src/commands/runner-queue.js +189 -0
  91. package/src/commands/runner-run.js +129 -0
  92. package/src/commands/runtime.js +47 -1
  93. package/src/commands/sandbox.js +37 -0
  94. package/src/commands/self-implement-loop.js +256 -0
  95. package/src/commands/session-guard.js +218 -0
  96. package/src/commands/setup-context.js +22 -2
  97. package/src/commands/setup.js +178 -0
  98. package/src/commands/sizing.js +165 -0
  99. package/src/commands/skill.js +144 -32
  100. package/src/commands/spec-checkpoint.js +177 -0
  101. package/src/commands/spec-status.js +79 -0
  102. package/src/commands/spec-sync.js +190 -0
  103. package/src/commands/spec-tasks.js +288 -0
  104. package/src/commands/squad-autorun.js +1220 -0
  105. package/src/commands/squad-bus.js +217 -0
  106. package/src/commands/squad-card.js +149 -0
  107. package/src/commands/squad-daemon.js +134 -0
  108. package/src/commands/squad-dependency-graph.js +164 -0
  109. package/src/commands/squad-review.js +106 -0
  110. package/src/commands/squad-scaffold.js +55 -0
  111. package/src/commands/squad-tool-register.js +157 -0
  112. package/src/commands/state-save.js +122 -0
  113. package/src/commands/tool-registry-cmd.js +232 -0
  114. package/src/commands/update.js +9 -0
  115. package/src/commands/verify-gate.js +572 -0
  116. package/src/commands/workflow-execute.js +241 -0
  117. package/src/constants.js +18 -0
  118. package/src/context-cache.js +159 -0
  119. package/src/context-search.js +326 -0
  120. package/src/design-variation-catalog.js +503 -0
  121. package/src/i18n/messages/en.js +32 -2
  122. package/src/i18n/messages/es.js +30 -2
  123. package/src/i18n/messages/fr.js +30 -2
  124. package/src/i18n/messages/pt-BR.js +32 -2
  125. package/src/install-animation.js +260 -0
  126. package/src/install-profile.js +143 -0
  127. package/src/install-wizard.js +475 -0
  128. package/src/installer.js +44 -10
  129. package/src/lib/health-check.js +158 -0
  130. package/src/lib/hook-protocol.js +76 -0
  131. package/src/mcp/apps/squad-dashboard/app.js +163 -0
  132. package/src/mcp/apps/squad-dashboard/index.html +261 -0
  133. package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
  134. package/src/mcp/resources/squad-state.js +130 -0
  135. package/src/parser.js +7 -1
  136. package/src/preflight-engine.js +443 -0
  137. package/src/recovery-context-session.js +154 -0
  138. package/src/runner/cascade.js +97 -0
  139. package/src/runner/cli-launcher.js +109 -0
  140. package/src/runner/plan-importer.js +63 -0
  141. package/src/runner/queue-store.js +159 -0
  142. package/src/runtime-store.js +158 -4
  143. package/src/sandbox.js +177 -0
  144. package/src/squad/agent-teams-adapter.js +264 -0
  145. package/src/squad/brief-validator.js +350 -0
  146. package/src/squad/bus-bridge.js +140 -0
  147. package/src/squad/context-compactor.js +265 -0
  148. package/src/squad/cross-ai-synthesizer.js +250 -0
  149. package/src/squad/hooks-generator.js +196 -0
  150. package/src/squad/inter-squad-events.js +175 -0
  151. package/src/squad/intra-bus.js +345 -0
  152. package/src/squad/learning-extractor.js +213 -0
  153. package/src/squad/pattern-detector.js +365 -0
  154. package/src/squad/preflight-context.js +296 -0
  155. package/src/squad/recovery-context.js +242 -71
  156. package/src/squad/reflection.js +365 -0
  157. package/src/squad/squad-scaffold.js +177 -0
  158. package/src/squad/state-manager.js +310 -0
  159. package/src/squad/task-decomposer.js +652 -0
  160. package/src/squad/verify-gate.js +303 -0
  161. package/src/tool-executor.js +94 -0
  162. package/src/updater.js +10 -3
  163. package/src/worker-runner.js +186 -1
  164. package/template/.aioson/agents/analyst.md +119 -3
  165. package/template/.aioson/agents/architect.md +98 -0
  166. package/template/.aioson/agents/design-hybrid-forge.md +141 -0
  167. package/template/.aioson/agents/dev.md +335 -14
  168. package/template/.aioson/agents/deyvin.md +117 -2
  169. package/template/.aioson/agents/discovery-design-doc.md +44 -0
  170. package/template/.aioson/agents/genome.md +14 -0
  171. package/template/.aioson/agents/neo.md +78 -1
  172. package/template/.aioson/agents/orache.md +50 -4
  173. package/template/.aioson/agents/orchestrator.md +197 -1
  174. package/template/.aioson/agents/pm.md +93 -0
  175. package/template/.aioson/agents/product.md +77 -4
  176. package/template/.aioson/agents/profiler-enricher.md +14 -0
  177. package/template/.aioson/agents/profiler-forge.md +14 -0
  178. package/template/.aioson/agents/profiler-researcher.md +14 -0
  179. package/template/.aioson/agents/qa.md +249 -19
  180. package/template/.aioson/agents/setup.md +144 -12
  181. package/template/.aioson/agents/sheldon.md +237 -11
  182. package/template/.aioson/agents/site-forge.md +1753 -0
  183. package/template/.aioson/agents/squad.md +162 -0
  184. package/template/.aioson/agents/tester.md +209 -0
  185. package/template/.aioson/agents/ux-ui.md +34 -1
  186. package/template/.aioson/brains/README.md +128 -0
  187. package/template/.aioson/brains/_index.json +16 -0
  188. package/template/.aioson/brains/scripts/query.js +103 -0
  189. package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
  190. package/template/.aioson/config.md +158 -13
  191. package/template/.aioson/constitution.md +33 -0
  192. package/template/.aioson/context/forensics/.gitkeep +0 -0
  193. package/template/.aioson/context/project-pulse.md +34 -0
  194. package/template/.aioson/context/seeds/seed-example.md +27 -0
  195. package/template/.aioson/context/user-profile.md +42 -0
  196. package/template/.aioson/docs/LAYERS.md +79 -0
  197. package/template/.aioson/docs/README.md +76 -0
  198. package/template/.aioson/docs/example-external-api-context.md +72 -0
  199. package/template/.aioson/locales/en/agents/architect.md +17 -0
  200. package/template/.aioson/locales/en/agents/dev.md +79 -13
  201. package/template/.aioson/locales/en/agents/orache.md +6 -0
  202. package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
  203. package/template/.aioson/locales/en/agents/product.md +50 -0
  204. package/template/.aioson/locales/en/agents/setup.md +33 -1
  205. package/template/.aioson/locales/en/agents/sheldon.md +115 -0
  206. package/template/.aioson/locales/en/agents/squad.md +14 -0
  207. package/template/.aioson/locales/en/agents/tester.md +6 -0
  208. package/template/.aioson/locales/es/agents/analyst.md +2 -0
  209. package/template/.aioson/locales/es/agents/architect.md +19 -0
  210. package/template/.aioson/locales/es/agents/dev.md +64 -4
  211. package/template/.aioson/locales/es/agents/deyvin.md +2 -0
  212. package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
  213. package/template/.aioson/locales/es/agents/genome.md +2 -0
  214. package/template/.aioson/locales/es/agents/neo.md +2 -0
  215. package/template/.aioson/locales/es/agents/orache.md +2 -0
  216. package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
  217. package/template/.aioson/locales/es/agents/pair.md +2 -0
  218. package/template/.aioson/locales/es/agents/pm.md +2 -0
  219. package/template/.aioson/locales/es/agents/product.md +52 -0
  220. package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
  221. package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
  222. package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
  223. package/template/.aioson/locales/es/agents/qa.md +2 -0
  224. package/template/.aioson/locales/es/agents/setup.md +35 -1
  225. package/template/.aioson/locales/es/agents/sheldon.md +117 -0
  226. package/template/.aioson/locales/es/agents/squad.md +16 -0
  227. package/template/.aioson/locales/es/agents/tester.md +9 -0
  228. package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
  229. package/template/.aioson/locales/fr/agents/analyst.md +2 -0
  230. package/template/.aioson/locales/fr/agents/architect.md +19 -0
  231. package/template/.aioson/locales/fr/agents/dev.md +64 -4
  232. package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
  233. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
  234. package/template/.aioson/locales/fr/agents/genome.md +2 -0
  235. package/template/.aioson/locales/fr/agents/neo.md +2 -0
  236. package/template/.aioson/locales/fr/agents/orache.md +2 -0
  237. package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
  238. package/template/.aioson/locales/fr/agents/pair.md +2 -0
  239. package/template/.aioson/locales/fr/agents/pm.md +2 -0
  240. package/template/.aioson/locales/fr/agents/product.md +52 -0
  241. package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
  242. package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
  243. package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
  244. package/template/.aioson/locales/fr/agents/qa.md +2 -0
  245. package/template/.aioson/locales/fr/agents/setup.md +35 -1
  246. package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
  247. package/template/.aioson/locales/fr/agents/squad.md +16 -0
  248. package/template/.aioson/locales/fr/agents/tester.md +9 -0
  249. package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
  250. package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
  251. package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
  252. package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
  253. package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
  254. package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
  255. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
  256. package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
  257. package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
  258. package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
  259. package/template/.aioson/locales/pt-BR/agents/setup.md +134 -19
  260. package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
  261. package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
  262. package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
  263. package/template/.aioson/rules/README.md +69 -0
  264. package/template/.aioson/rules/data-format-convention.md +136 -0
  265. package/template/.aioson/rules/example-monetary-values.md +30 -0
  266. package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
  267. package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +243 -0
  268. package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -0
  269. package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -0
  270. package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -0
  271. package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -0
  272. package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -0
  273. package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +482 -0
  274. package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +387 -0
  275. package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +222 -0
  276. package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -0
  277. package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -0
  278. package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -0
  279. package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -0
  280. package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -0
  281. package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -0
  282. package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -0
  283. package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +213 -0
  284. package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -0
  285. package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -0
  286. package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -0
  287. package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -0
  288. package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -0
  289. package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -0
  290. package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -0
  291. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
  292. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
  293. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
  294. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
  295. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
  296. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
  297. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
  298. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +46 -0
  299. package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
  300. package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +109 -0
  301. package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
  302. package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +44 -0
  303. package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +37 -0
  304. package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
  305. package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
  306. package/template/.aioson/skills/process/aioson-spec-driven/references/hardening-lane.md +49 -0
  307. package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +101 -0
  308. package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
  309. package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
  310. package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
  311. package/template/.aioson/skills/process/aioson-spec-driven/references/ui-language.md +75 -0
  312. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +147 -0
  313. package/template/.aioson/skills/process/design-hybrid-forge/references/crossover-protocol.md +221 -0
  314. package/template/.aioson/skills/process/design-hybrid-forge/references/naming-registry.md +88 -0
  315. package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +306 -0
  316. package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +149 -0
  317. package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +208 -0
  318. package/template/.aioson/skills/process/design-hybrid-forge/references/variation-library.md +125 -0
  319. package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
  320. package/template/.aioson/skills/static/context-budget-guide.md +46 -0
  321. package/template/.aioson/skills/static/harness-sensors.md +74 -0
  322. package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
  323. package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
  324. package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
  325. package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
  326. package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
  327. package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
  328. package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
  329. package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
  330. package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
  331. package/template/.aioson/skills/static/threejs-patterns.md +929 -0
  332. package/template/.aioson/skills/static/web-research-cache.md +112 -0
  333. package/template/.aioson/tasks/implementation-plan.md +21 -1
  334. package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
  335. package/template/.claude/commands/aioson/agent/orache.md +5 -0
  336. package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
  337. package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
  338. package/template/AGENTS.md +75 -1
  339. package/template/CLAUDE.md +31 -0
  340. package/template/OPENCODE.md +4 -0
  341. package/template/researchs/.gitkeep +0 -0
@@ -0,0 +1,158 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Ambient Intelligence Health Check — Phase 5.3
5
+ *
6
+ * Aggregates state from multiple SQLite tables and file-system checks
7
+ * to produce a list of items awaiting attention.
8
+ *
9
+ * Used by:
10
+ * - live:start → shows alert at session start
11
+ * - daemon:start → triggers automatic actions in the background loop
12
+ */
13
+
14
+ const fs = require('node:fs/promises');
15
+ const path = require('node:path');
16
+ const { openRuntimeDb } = require('../runtime-store');
17
+
18
+ const MIN_LEARNINGS_FOR_EVOLVE = 5;
19
+ const MIN_LEARNING_FREQUENCY = 2;
20
+ const SQUAD_INACTIVE_DAYS = 30;
21
+ const TOOL_UNUSED_DAYS = 60;
22
+ const EVENT_STALE_HOURS = 24;
23
+
24
+ /**
25
+ * Run all health checks and return a list of items.
26
+ *
27
+ * @param {string} projectDir
28
+ * @returns {Promise<{ items: HealthItem[], ok: boolean }>}
29
+ */
30
+ async function runHealthCheck(projectDir) {
31
+ const handle = await openRuntimeDb(projectDir, { mustExist: true });
32
+ if (!handle) return { items: [], ok: true };
33
+ const { db } = handle;
34
+
35
+ const items = [];
36
+
37
+ try {
38
+ // ── Check 1: Learnings ready for evolve ────────────────────────────────
39
+ try {
40
+ const learnings = db.prepare(`
41
+ SELECT squad_slug, COUNT(*) as count
42
+ FROM squad_learnings
43
+ WHERE status = 'active' AND frequency >= ?
44
+ GROUP BY squad_slug
45
+ HAVING count >= ?
46
+ `).all(MIN_LEARNING_FREQUENCY, MIN_LEARNINGS_FOR_EVOLVE);
47
+
48
+ for (const row of learnings) {
49
+ items.push({
50
+ type: 'learnings_ready',
51
+ priority: 'high',
52
+ squad: row.squad_slug,
53
+ count: row.count,
54
+ message: `${row.count} learnings prontos para evoluir (squad: ${row.squad_slug})`,
55
+ action: `aioson learning:evolve . --squad=${row.squad_slug} --auto-apply`
56
+ });
57
+ }
58
+ } catch { /* table might not exist yet */ }
59
+
60
+ // ── Check 2: Inactive squads ───────────────────────────────────────────
61
+ try {
62
+ const inactive = db.prepare(`
63
+ SELECT squad_slug, updated_at
64
+ FROM squads
65
+ WHERE status = 'active'
66
+ AND updated_at < datetime('now', '-${SQUAD_INACTIVE_DAYS} days')
67
+ `).all();
68
+
69
+ for (const row of inactive) {
70
+ const daysSince = Math.round((Date.now() - new Date(row.updated_at).getTime()) / 86400000);
71
+ items.push({
72
+ type: 'squad_inactive',
73
+ priority: 'low',
74
+ squad: row.squad_slug,
75
+ days: daysSince,
76
+ message: `Squad "${row.squad_slug}" inativo há ${daysSince} dias`,
77
+ action: null
78
+ });
79
+ }
80
+ } catch { /* ok */ }
81
+
82
+ // ── Check 3: Stale inter-squad events ─────────────────────────────────
83
+ try {
84
+ const stale = db.prepare(`
85
+ SELECT id, from_squad, event, created_at
86
+ FROM inter_squad_events
87
+ WHERE datetime(created_at, '+${EVENT_STALE_HOURS} hours') < datetime('now')
88
+ AND consumed_by = '[]'
89
+ `).all();
90
+
91
+ if (stale.length > 0) {
92
+ items.push({
93
+ type: 'stale_events',
94
+ priority: 'medium',
95
+ count: stale.length,
96
+ message: `${stale.length} evento(s) inter-squad pendentes há mais de ${EVENT_STALE_HOURS}h sem consumidor`,
97
+ action: null
98
+ });
99
+ }
100
+ } catch { /* ok */ }
101
+
102
+ // ── Check 4: Dynamic tools unused for a long time ─────────────────────
103
+ try {
104
+ const unusedTools = db.prepare(`
105
+ SELECT t.name, t.squad_slug, t.registered_at
106
+ FROM dynamic_squad_tools t
107
+ WHERE t.registered_at < datetime('now', '-${TOOL_UNUSED_DAYS} days')
108
+ `).all();
109
+
110
+ if (unusedTools.length > 0) {
111
+ items.push({
112
+ type: 'unused_tools',
113
+ priority: 'low',
114
+ count: unusedTools.length,
115
+ message: `${unusedTools.length} tool(s) dinâmico(s) sem uso há mais de ${TOOL_UNUSED_DAYS} dias`,
116
+ action: `aioson squad:tool:register . --list --squad=<slug>`
117
+ });
118
+ }
119
+ } catch { /* ok */ }
120
+ } finally {
121
+ db.close();
122
+ }
123
+
124
+ return { items, ok: true };
125
+ }
126
+
127
+ /**
128
+ * Format health items for display in terminal (live:start alert).
129
+ *
130
+ * @param {HealthItem[]} items
131
+ * @returns {string|null} Formatted alert string, or null if nothing to report
132
+ */
133
+ function formatHealthAlert(items) {
134
+ if (items.length === 0) return null;
135
+
136
+ const high = items.filter((i) => i.priority === 'high');
137
+ const medium = items.filter((i) => i.priority === 'medium');
138
+ const low = items.filter((i) => i.priority === 'low');
139
+
140
+ const lines = [
141
+ `AIOSON — ${items.length} item(s) aguardam atenção:`
142
+ ];
143
+
144
+ for (const item of high) {
145
+ lines.push(` ● ${item.message}`);
146
+ if (item.action) lines.push(` → ${item.action}`);
147
+ }
148
+ for (const item of medium) {
149
+ lines.push(` ◐ ${item.message}`);
150
+ }
151
+ for (const item of low) {
152
+ lines.push(` ○ ${item.message}`);
153
+ }
154
+
155
+ return lines.join('\n');
156
+ }
157
+
158
+ module.exports = { runHealthCheck, formatHealthAlert };
@@ -0,0 +1,76 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Hook Exit Code Protocol
5
+ *
6
+ * Standardized exit codes for AIOSON hook scripts:
7
+ * HOOK_ALLOW (0): Allow the operation — continue normally
8
+ * HOOK_DENY (2): Deny the operation — abort with error message from stderr
9
+ * Any other: Warn — log stderr, continue (non-fatal)
10
+ *
11
+ * Used by squad:autorun to run `hooks.pre_run` scripts declared in squad manifests.
12
+ * Allows squads to gate their own execution based on inter-squad state.
13
+ *
14
+ * Example manifest:
15
+ * "hooks": {
16
+ * "pre_run": "sh .aioson/squads/distribution-team/hooks/check-content-ready.sh"
17
+ * }
18
+ *
19
+ * Example hook script (exits 2 to deny):
20
+ * #!/bin/sh
21
+ * STATUS=$(aioson squad:status . --squad=content-team --json | jq -r '.status')
22
+ * [ "$STATUS" = "active" ] && exit 0
23
+ * echo "content-team not ready (status: $STATUS)" >&2
24
+ * exit 2
25
+ */
26
+
27
+ const { spawnSync } = require('node:child_process');
28
+
29
+ const HOOK_ALLOW = 0;
30
+ const HOOK_DENY = 2;
31
+
32
+ /**
33
+ * Run a hook script and interpret its exit code.
34
+ *
35
+ * @param {string} script Shell command to execute (via `sh -c`)
36
+ * @param {object} context Key-value pairs passed as uppercase env vars to the script
37
+ * @param {object} opts Options: { timeoutMs }
38
+ *
39
+ * @returns {{ allowed: boolean, denied: boolean, exitCode: number, stdout: string, stderr: string, warn?: boolean }}
40
+ */
41
+ function runHook(script, context = {}, opts = {}) {
42
+ const timeoutMs = opts.timeoutMs || 10_000;
43
+
44
+ const env = {
45
+ ...process.env,
46
+ ...Object.fromEntries(
47
+ Object.entries(context).map(([k, v]) => [
48
+ 'AIOSON_' + k.toUpperCase().replace(/[^A-Z0-9]/g, '_'),
49
+ String(v)
50
+ ])
51
+ )
52
+ };
53
+
54
+ const result = spawnSync('sh', ['-c', script], {
55
+ env,
56
+ timeout: timeoutMs,
57
+ encoding: 'utf8',
58
+ stdio: 'pipe'
59
+ });
60
+
61
+ const exitCode = result.status ?? 1;
62
+ const stdout = (result.stdout || '').trim();
63
+ const stderr = (result.stderr || '').trim();
64
+
65
+ if (exitCode === HOOK_DENY) {
66
+ return { allowed: false, denied: true, exitCode, stdout, stderr };
67
+ }
68
+
69
+ if (exitCode !== HOOK_ALLOW) {
70
+ return { allowed: true, denied: false, exitCode, stdout, stderr, warn: true };
71
+ }
72
+
73
+ return { allowed: true, denied: false, exitCode, stdout, stderr };
74
+ }
75
+
76
+ module.exports = { HOOK_ALLOW, HOOK_DENY, runHook };
@@ -0,0 +1,163 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Squad Dashboard App Logic — Plan 81, Phase 4.1
5
+ *
6
+ * Provides data fetching and rendering logic for the MCP App dashboard.
7
+ * Can run standalone (via HTTP API) or embedded in MCP App context.
8
+ */
9
+
10
+ const fs = require('node:fs/promises');
11
+ const path = require('node:path');
12
+
13
+ const SQUADS_DIR = path.join('.aioson', 'squads');
14
+
15
+ // ─── State readers ───────────────────────────────────────────────────────────
16
+
17
+ async function readSquadState(projectDir, squadSlug) {
18
+ const statePath = path.join(projectDir, SQUADS_DIR, squadSlug, 'STATE.md');
19
+ try {
20
+ const content = await fs.readFile(statePath, 'utf8');
21
+ // Parse frontmatter
22
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
23
+ if (!match) return { raw: content };
24
+
25
+ const meta = {};
26
+ for (const line of match[1].split('\n')) {
27
+ const kv = line.match(/^(\w[\w_]*):\s*(.+)$/);
28
+ if (kv) {
29
+ const val = kv[2].trim();
30
+ if (/^\d+(\.\d+)?$/.test(val)) meta[kv[1]] = Number(val);
31
+ else meta[kv[1]] = val.replace(/^["']|["']$/g, '');
32
+ }
33
+ }
34
+
35
+ return { ...meta, raw: content };
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+
41
+ async function readBusState(projectDir, squadSlug) {
42
+ // Find the most recent session
43
+ const sessionsDir = path.join(projectDir, SQUADS_DIR, squadSlug, 'sessions');
44
+ try {
45
+ const entries = await fs.readdir(sessionsDir, { withFileTypes: true });
46
+ const sessions = entries.filter((e) => e.isDirectory()).map((e) => e.name).sort().reverse();
47
+
48
+ if (sessions.length === 0) return { messages: [], total: 0 };
49
+
50
+ const latestSession = sessions[0];
51
+ const busPath = path.join(sessionsDir, latestSession, 'bus.jsonl');
52
+ const raw = await fs.readFile(busPath, 'utf8');
53
+ const messages = raw.split('\n')
54
+ .filter(Boolean)
55
+ .map((line) => { try { return JSON.parse(line); } catch { return null; } })
56
+ .filter(Boolean);
57
+
58
+ // Classify
59
+ const blocks = messages.filter((m) => m.type === 'block');
60
+ const results = messages.filter((m) => m.type === 'result');
61
+ const byType = {};
62
+ const byExecutor = {};
63
+ for (const m of messages) {
64
+ byType[m.type] = (byType[m.type] || 0) + 1;
65
+ byExecutor[m.from] = (byExecutor[m.from] || 0) + 1;
66
+ }
67
+
68
+ return {
69
+ sessionId: latestSession,
70
+ total: messages.length,
71
+ blocks: blocks.length,
72
+ results: results.length,
73
+ byType,
74
+ byExecutor,
75
+ lastMessages: messages.slice(-20)
76
+ };
77
+ } catch {
78
+ return { messages: [], total: 0 };
79
+ }
80
+ }
81
+
82
+ async function readBudgetState(projectDir, squadSlug) {
83
+ const manifestPath = path.join(projectDir, SQUADS_DIR, squadSlug, 'squad.manifest.json');
84
+ try {
85
+ const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
86
+ return manifest.budget || { max_tokens_per_session: null, max_tokens_per_task: null };
87
+ } catch {
88
+ return {};
89
+ }
90
+ }
91
+
92
+ async function readWavesState(projectDir, squadSlug) {
93
+ const sessionsDir = path.join(projectDir, SQUADS_DIR, squadSlug, 'sessions');
94
+ try {
95
+ const entries = await fs.readdir(sessionsDir, { withFileTypes: true });
96
+ const sessions = entries.filter((e) => e.isDirectory()).map((e) => e.name).sort().reverse();
97
+
98
+ if (sessions.length === 0) return { waves: [] };
99
+
100
+ const planPath = path.join(sessionsDir, sessions[0], 'plan.json');
101
+ const plan = JSON.parse(await fs.readFile(planPath, 'utf8'));
102
+
103
+ const waves = [];
104
+ const groups = plan.parallel_groups || {};
105
+
106
+ for (const [groupNum, taskIds] of Object.entries(groups)) {
107
+ const waveTasks = taskIds.map((id) => {
108
+ const task = plan.tasks.find((t) => t.id === id);
109
+ return task ? {
110
+ id: task.id,
111
+ title: task.title,
112
+ executor: task.executor,
113
+ status: task.status || 'pending'
114
+ } : { id, status: 'unknown' };
115
+ });
116
+
117
+ const allDone = waveTasks.every((t) => t.status === 'completed');
118
+ const anyRunning = waveTasks.some((t) => t.status === 'in_progress');
119
+ const anyBlocked = waveTasks.some((t) => t.status === 'escalated' || t.status === 'failed');
120
+
121
+ waves.push({
122
+ wave: Number(groupNum),
123
+ status: allDone ? 'DONE' : anyRunning ? 'RUNNING' : anyBlocked ? 'BLOCKED' : 'PENDING',
124
+ tasks: waveTasks
125
+ });
126
+ }
127
+
128
+ return { sessionId: sessions[0], waves, goal: plan.goal };
129
+ } catch {
130
+ return { waves: [] };
131
+ }
132
+ }
133
+
134
+ // ─── Composite dashboard data ────────────────────────────────────────────────
135
+
136
+ /**
137
+ * Get complete dashboard data for a squad.
138
+ */
139
+ async function getDashboardData(projectDir, squadSlug) {
140
+ const [state, busState, budget, wavesState] = await Promise.all([
141
+ readSquadState(projectDir, squadSlug),
142
+ readBusState(projectDir, squadSlug),
143
+ readBudgetState(projectDir, squadSlug),
144
+ readWavesState(projectDir, squadSlug)
145
+ ]);
146
+
147
+ return {
148
+ squad: squadSlug,
149
+ timestamp: new Date().toISOString(),
150
+ state,
151
+ bus: busState,
152
+ budget,
153
+ waves: wavesState
154
+ };
155
+ }
156
+
157
+ module.exports = {
158
+ getDashboardData,
159
+ readSquadState,
160
+ readBusState,
161
+ readBudgetState,
162
+ readWavesState
163
+ };
@@ -0,0 +1,261 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Squad Dashboard — AIOSON</title>
7
+ <style>
8
+ :root {
9
+ --bg: #1a1a2e;
10
+ --surface: #16213e;
11
+ --border: #0f3460;
12
+ --text: #e0e0e0;
13
+ --muted: #888;
14
+ --green: #4ade80;
15
+ --yellow: #fbbf24;
16
+ --red: #f87171;
17
+ --blue: #60a5fa;
18
+ }
19
+ * { margin: 0; padding: 0; box-sizing: border-box; }
20
+ body {
21
+ font-family: 'SF Mono', 'Fira Code', monospace;
22
+ background: var(--bg);
23
+ color: var(--text);
24
+ font-size: 13px;
25
+ padding: 12px;
26
+ }
27
+ .header {
28
+ display: flex;
29
+ justify-content: space-between;
30
+ align-items: center;
31
+ padding: 8px 12px;
32
+ background: var(--surface);
33
+ border: 1px solid var(--border);
34
+ border-radius: 6px;
35
+ margin-bottom: 12px;
36
+ }
37
+ .header .squad-name { font-size: 15px; font-weight: 600; }
38
+ .header .session { color: var(--muted); font-size: 11px; }
39
+ .status-dot {
40
+ display: inline-block;
41
+ width: 8px; height: 8px;
42
+ border-radius: 50%;
43
+ margin-right: 6px;
44
+ }
45
+ .status-dot.active { background: var(--green); }
46
+ .status-dot.warning { background: var(--yellow); }
47
+ .status-dot.error { background: var(--red); }
48
+ .waves-container {
49
+ display: flex;
50
+ gap: 8px;
51
+ margin-bottom: 12px;
52
+ overflow-x: auto;
53
+ }
54
+ .wave {
55
+ flex: 1;
56
+ min-width: 120px;
57
+ background: var(--surface);
58
+ border: 1px solid var(--border);
59
+ border-radius: 6px;
60
+ padding: 8px;
61
+ }
62
+ .wave-header {
63
+ font-size: 11px;
64
+ text-transform: uppercase;
65
+ letter-spacing: 0.5px;
66
+ margin-bottom: 6px;
67
+ padding-bottom: 4px;
68
+ border-bottom: 1px solid var(--border);
69
+ }
70
+ .wave-header.done { color: var(--green); }
71
+ .wave-header.running { color: var(--blue); }
72
+ .wave-header.blocked { color: var(--red); }
73
+ .wave-header.pending { color: var(--muted); }
74
+ .task {
75
+ font-size: 12px;
76
+ padding: 2px 0;
77
+ display: flex;
78
+ align-items: center;
79
+ gap: 4px;
80
+ }
81
+ .task-icon { font-size: 10px; }
82
+ .task-icon.completed { color: var(--green); }
83
+ .task-icon.in_progress { color: var(--blue); }
84
+ .task-icon.failed { color: var(--red); }
85
+ .task-icon.pending { color: var(--muted); }
86
+ .stats-bar {
87
+ display: flex;
88
+ gap: 8px;
89
+ background: var(--surface);
90
+ border: 1px solid var(--border);
91
+ border-radius: 6px;
92
+ padding: 8px 12px;
93
+ margin-bottom: 12px;
94
+ }
95
+ .stat {
96
+ display: flex;
97
+ align-items: center;
98
+ gap: 4px;
99
+ }
100
+ .stat-label { color: var(--muted); font-size: 11px; }
101
+ .stat-value { font-weight: 600; }
102
+ .stat-divider {
103
+ width: 1px;
104
+ background: var(--border);
105
+ align-self: stretch;
106
+ }
107
+ .bus-feed {
108
+ background: var(--surface);
109
+ border: 1px solid var(--border);
110
+ border-radius: 6px;
111
+ padding: 8px;
112
+ max-height: 120px;
113
+ overflow-y: auto;
114
+ }
115
+ .bus-msg {
116
+ font-size: 11px;
117
+ padding: 2px 0;
118
+ border-bottom: 1px solid rgba(255,255,255,0.05);
119
+ }
120
+ .bus-msg .from { color: var(--blue); }
121
+ .bus-msg .type { color: var(--muted); }
122
+ .bus-msg .type.block { color: var(--red); }
123
+ .bus-msg .type.result { color: var(--green); }
124
+ #loading { text-align: center; padding: 40px; color: var(--muted); }
125
+ </style>
126
+ </head>
127
+ <body>
128
+ <div id="loading">Loading dashboard data...</div>
129
+ <div id="dashboard" style="display:none">
130
+ <div class="header">
131
+ <div>
132
+ <span class="status-dot active" id="status-dot"></span>
133
+ <span class="squad-name" id="squad-name">—</span>
134
+ </div>
135
+ <div class="session" id="session-info">—</div>
136
+ </div>
137
+
138
+ <div class="waves-container" id="waves"></div>
139
+
140
+ <div class="stats-bar">
141
+ <div class="stat">
142
+ <span class="stat-label">Bus:</span>
143
+ <span class="stat-value" id="bus-total">0</span>
144
+ <span class="stat-label">msgs</span>
145
+ </div>
146
+ <div class="stat-divider"></div>
147
+ <div class="stat">
148
+ <span class="stat-label">Blocks:</span>
149
+ <span class="stat-value" id="bus-blocks">0</span>
150
+ </div>
151
+ <div class="stat-divider"></div>
152
+ <div class="stat">
153
+ <span class="stat-label">Budget:</span>
154
+ <span class="stat-value" id="budget-info">—</span>
155
+ </div>
156
+ <div class="stat-divider"></div>
157
+ <div class="stat">
158
+ <span class="stat-label">Sessions:</span>
159
+ <span class="stat-value" id="sessions-count">0</span>
160
+ </div>
161
+ </div>
162
+
163
+ <div class="bus-feed" id="bus-feed"></div>
164
+ </div>
165
+
166
+ <script>
167
+ const TASK_ICONS = {
168
+ completed: '\u2713',
169
+ in_progress: '\u25B6',
170
+ failed: '\u2717',
171
+ escalated: '\u26A0',
172
+ pending: '\u25CB',
173
+ skipped: '\u2013'
174
+ };
175
+
176
+ function renderWaves(wavesData) {
177
+ const container = document.getElementById('waves');
178
+ container.innerHTML = '';
179
+
180
+ for (const wave of (wavesData.waves || [])) {
181
+ const el = document.createElement('div');
182
+ el.className = 'wave';
183
+ const statusClass = wave.status.toLowerCase();
184
+
185
+ el.innerHTML = `
186
+ <div class="wave-header ${statusClass}">Wave ${wave.wave} [${wave.status}]</div>
187
+ ${wave.tasks.map(t => `
188
+ <div class="task">
189
+ <span class="task-icon ${t.status}">${TASK_ICONS[t.status] || '?'}</span>
190
+ <span>${t.executor || t.title || t.id}</span>
191
+ </div>
192
+ `).join('')}
193
+ `;
194
+ container.appendChild(el);
195
+ }
196
+ }
197
+
198
+ function renderBusFeed(busData) {
199
+ const feed = document.getElementById('bus-feed');
200
+ const messages = busData.lastMessages || [];
201
+ feed.innerHTML = messages.slice(-10).reverse().map(m => `
202
+ <div class="bus-msg">
203
+ <span class="from">${m.from}</span>
204
+ <span class="type ${m.type}">[${m.type}]</span>
205
+ ${m.content ? m.content.slice(0, 80) : ''}
206
+ </div>
207
+ `).join('');
208
+ }
209
+
210
+ function renderDashboard(data) {
211
+ document.getElementById('loading').style.display = 'none';
212
+ document.getElementById('dashboard').style.display = 'block';
213
+
214
+ document.getElementById('squad-name').textContent = `Squad: ${data.squad}`;
215
+ document.getElementById('session-info').textContent =
216
+ data.waves.sessionId ? `Session: ${data.waves.sessionId.slice(0, 8)}` : '';
217
+
218
+ if (data.state) {
219
+ document.getElementById('sessions-count').textContent =
220
+ data.state.sessions_completed || 0;
221
+ }
222
+
223
+ document.getElementById('bus-total').textContent = data.bus.total || 0;
224
+ document.getElementById('bus-blocks').textContent = data.bus.blocks || 0;
225
+
226
+ if (data.budget && data.budget.max_tokens_per_session) {
227
+ document.getElementById('budget-info').textContent =
228
+ `${(data.budget.max_tokens_per_session / 1000).toFixed(0)}k`;
229
+ }
230
+
231
+ const dot = document.getElementById('status-dot');
232
+ if (data.bus.blocks > 0) {
233
+ dot.className = 'status-dot warning';
234
+ } else {
235
+ dot.className = 'status-dot active';
236
+ }
237
+
238
+ renderWaves(data.waves);
239
+ renderBusFeed(data.bus);
240
+ }
241
+
242
+ // MCP App data injection point
243
+ if (window.__MCP_DATA__) {
244
+ renderDashboard(window.__MCP_DATA__);
245
+ }
246
+
247
+ // Polling fallback for standalone mode
248
+ if (window.__DASHBOARD_API__) {
249
+ async function poll() {
250
+ try {
251
+ const res = await fetch(window.__DASHBOARD_API__);
252
+ const data = await res.json();
253
+ renderDashboard(data);
254
+ } catch { /* retry */ }
255
+ setTimeout(poll, 3000);
256
+ }
257
+ poll();
258
+ }
259
+ </script>
260
+ </body>
261
+ </html>
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "aioson-squad-dashboard",
3
+ "version": "1.0.0",
4
+ "description": "Real-time squad execution dashboard for AIOSON",
5
+ "type": "mcp-app",
6
+ "display": {
7
+ "title": "Squad Dashboard",
8
+ "icon": "grid",
9
+ "width": 600,
10
+ "height": 400
11
+ },
12
+ "entry": "index.html",
13
+ "resources": [
14
+ "aioson://squad/{slug}/state",
15
+ "aioson://squad/{slug}/bus",
16
+ "aioson://squad/{slug}/budget",
17
+ "aioson://squad/{slug}/waves"
18
+ ],
19
+ "permissions": [
20
+ "read:squad-state",
21
+ "read:squad-bus"
22
+ ]
23
+ }