@jaimevalasek/aioson 1.6.0 → 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 (252) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +729 -232
  3. package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
  4. package/docs/integrations/sdlc-genius-boundary.md +76 -0
  5. package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
  6. package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
  7. package/docs/integrations/sdlc-genius-review-samples.md +86 -0
  8. package/docs/pt/README.md +3 -0
  9. package/docs/pt/agentes.md +1 -0
  10. package/docs/pt/comandos-cli.md +888 -2
  11. package/docs/pt/design-hybrid-forge.md +255 -6
  12. package/docs/pt/devlog-pipeline.md +270 -0
  13. package/docs/pt/fluxo-artefatos.md +178 -0
  14. package/docs/pt/hooks-session-guard.md +454 -0
  15. package/docs/pt/monitor-de-contexto.md +59 -5
  16. package/docs/pt/sdd-automation-scripts.md +557 -0
  17. package/docs/pt/site-forge.md +309 -0
  18. package/docs/pt/spec-learnings-pipeline.md +265 -0
  19. package/package.json +1 -1
  20. package/src/a2a/client.js +165 -0
  21. package/src/a2a/server.js +223 -0
  22. package/src/cli.js +235 -1
  23. package/src/commands/agent-audit.js +397 -0
  24. package/src/commands/agent-export-skill.js +229 -0
  25. package/src/commands/artifact-validate.js +189 -0
  26. package/src/commands/brief-gen.js +405 -0
  27. package/src/commands/brief-validate.js +65 -0
  28. package/src/commands/classify.js +256 -0
  29. package/src/commands/context-compact.js +49 -0
  30. package/src/commands/context-health.js +175 -0
  31. package/src/commands/context-monitor.js +71 -0
  32. package/src/commands/context-trim.js +177 -0
  33. package/src/commands/detect-test-runner.js +55 -0
  34. package/src/commands/devlog-export-brains.js +27 -0
  35. package/src/commands/devlog-process.js +292 -0
  36. package/src/commands/devlog-watch.js +131 -0
  37. package/src/commands/feature-close.js +165 -0
  38. package/src/commands/gate-check.js +228 -0
  39. package/src/commands/hooks-emit.js +253 -0
  40. package/src/commands/hooks-install.js +347 -0
  41. package/src/commands/learning-auto-promote.js +195 -0
  42. package/src/commands/learning-evolve.js +18 -9
  43. package/src/commands/learning-export.js +103 -0
  44. package/src/commands/learning-rollback.js +164 -0
  45. package/src/commands/live.js +25 -1
  46. package/src/commands/pattern-detect.js +33 -0
  47. package/src/commands/preflight-context.js +30 -0
  48. package/src/commands/preflight.js +208 -0
  49. package/src/commands/pulse-update.js +130 -0
  50. package/src/commands/runner-daemon.js +274 -0
  51. package/src/commands/runner-plan.js +70 -0
  52. package/src/commands/runner-queue-from-plan.js +166 -0
  53. package/src/commands/runner-queue.js +189 -0
  54. package/src/commands/runner-run.js +129 -0
  55. package/src/commands/runtime.js +47 -1
  56. package/src/commands/self-implement-loop.js +256 -0
  57. package/src/commands/session-guard.js +218 -0
  58. package/src/commands/sizing.js +165 -0
  59. package/src/commands/skill.js +65 -0
  60. package/src/commands/spec-checkpoint.js +177 -0
  61. package/src/commands/spec-status.js +79 -0
  62. package/src/commands/spec-sync.js +190 -0
  63. package/src/commands/spec-tasks.js +288 -0
  64. package/src/commands/squad-autorun.js +1220 -0
  65. package/src/commands/squad-bus.js +217 -0
  66. package/src/commands/squad-card.js +149 -0
  67. package/src/commands/squad-daemon.js +134 -0
  68. package/src/commands/squad-dependency-graph.js +164 -0
  69. package/src/commands/squad-review.js +106 -0
  70. package/src/commands/squad-scaffold.js +55 -0
  71. package/src/commands/squad-tool-register.js +157 -0
  72. package/src/commands/state-save.js +122 -0
  73. package/src/commands/update.js +2 -0
  74. package/src/commands/verify-gate.js +572 -0
  75. package/src/commands/workflow-execute.js +241 -0
  76. package/src/constants.js +9 -0
  77. package/src/install-profile.js +2 -2
  78. package/src/install-wizard.js +3 -2
  79. package/src/installer.js +6 -0
  80. package/src/lib/health-check.js +158 -0
  81. package/src/lib/hook-protocol.js +76 -0
  82. package/src/mcp/apps/squad-dashboard/app.js +163 -0
  83. package/src/mcp/apps/squad-dashboard/index.html +261 -0
  84. package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
  85. package/src/mcp/resources/squad-state.js +130 -0
  86. package/src/preflight-engine.js +443 -0
  87. package/src/runner/cascade.js +97 -0
  88. package/src/runner/cli-launcher.js +109 -0
  89. package/src/runner/plan-importer.js +63 -0
  90. package/src/runner/queue-store.js +159 -0
  91. package/src/runtime-store.js +61 -3
  92. package/src/squad/agent-teams-adapter.js +264 -0
  93. package/src/squad/brief-validator.js +350 -0
  94. package/src/squad/bus-bridge.js +140 -0
  95. package/src/squad/context-compactor.js +265 -0
  96. package/src/squad/cross-ai-synthesizer.js +250 -0
  97. package/src/squad/hooks-generator.js +196 -0
  98. package/src/squad/inter-squad-events.js +175 -0
  99. package/src/squad/intra-bus.js +345 -0
  100. package/src/squad/learning-extractor.js +213 -0
  101. package/src/squad/pattern-detector.js +365 -0
  102. package/src/squad/preflight-context.js +296 -0
  103. package/src/squad/recovery-context.js +242 -71
  104. package/src/squad/reflection.js +365 -0
  105. package/src/squad/squad-scaffold.js +177 -0
  106. package/src/squad/state-manager.js +310 -0
  107. package/src/squad/task-decomposer.js +652 -0
  108. package/src/squad/verify-gate.js +303 -0
  109. package/src/updater.js +4 -5
  110. package/src/worker-runner.js +186 -1
  111. package/template/.aioson/agents/analyst.md +62 -1
  112. package/template/.aioson/agents/architect.md +61 -1
  113. package/template/.aioson/agents/design-hybrid-forge.md +14 -0
  114. package/template/.aioson/agents/dev.md +242 -24
  115. package/template/.aioson/agents/deyvin.md +66 -8
  116. package/template/.aioson/agents/discovery-design-doc.md +44 -0
  117. package/template/.aioson/agents/genome.md +14 -0
  118. package/template/.aioson/agents/neo.md +78 -1
  119. package/template/.aioson/agents/orache.md +50 -4
  120. package/template/.aioson/agents/orchestrator.md +197 -1
  121. package/template/.aioson/agents/pm.md +35 -0
  122. package/template/.aioson/agents/product.md +50 -5
  123. package/template/.aioson/agents/profiler-enricher.md +14 -0
  124. package/template/.aioson/agents/profiler-forge.md +14 -0
  125. package/template/.aioson/agents/profiler-researcher.md +14 -0
  126. package/template/.aioson/agents/qa.md +172 -21
  127. package/template/.aioson/agents/setup.md +79 -9
  128. package/template/.aioson/agents/sheldon.md +131 -6
  129. package/template/.aioson/agents/site-forge.md +1753 -0
  130. package/template/.aioson/agents/squad.md +162 -0
  131. package/template/.aioson/agents/tester.md +53 -0
  132. package/template/.aioson/agents/ux-ui.md +34 -1
  133. package/template/.aioson/brains/README.md +128 -0
  134. package/template/.aioson/brains/_index.json +16 -0
  135. package/template/.aioson/brains/scripts/query.js +103 -0
  136. package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
  137. package/template/.aioson/config.md +143 -13
  138. package/template/.aioson/constitution.md +33 -0
  139. package/template/.aioson/context/project-pulse.md +34 -0
  140. package/template/.aioson/docs/LAYERS.md +79 -0
  141. package/template/.aioson/docs/README.md +76 -0
  142. package/template/.aioson/docs/example-external-api-context.md +72 -0
  143. package/template/.aioson/locales/en/agents/architect.md +17 -0
  144. package/template/.aioson/locales/en/agents/dev.md +79 -13
  145. package/template/.aioson/locales/en/agents/orache.md +6 -0
  146. package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
  147. package/template/.aioson/locales/en/agents/product.md +50 -0
  148. package/template/.aioson/locales/en/agents/sheldon.md +115 -0
  149. package/template/.aioson/locales/en/agents/squad.md +14 -0
  150. package/template/.aioson/locales/en/agents/tester.md +6 -0
  151. package/template/.aioson/locales/es/agents/analyst.md +2 -0
  152. package/template/.aioson/locales/es/agents/architect.md +19 -0
  153. package/template/.aioson/locales/es/agents/dev.md +64 -4
  154. package/template/.aioson/locales/es/agents/deyvin.md +2 -0
  155. package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
  156. package/template/.aioson/locales/es/agents/genome.md +2 -0
  157. package/template/.aioson/locales/es/agents/neo.md +2 -0
  158. package/template/.aioson/locales/es/agents/orache.md +2 -0
  159. package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
  160. package/template/.aioson/locales/es/agents/pair.md +2 -0
  161. package/template/.aioson/locales/es/agents/pm.md +2 -0
  162. package/template/.aioson/locales/es/agents/product.md +52 -0
  163. package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
  164. package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
  165. package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
  166. package/template/.aioson/locales/es/agents/qa.md +2 -0
  167. package/template/.aioson/locales/es/agents/setup.md +2 -0
  168. package/template/.aioson/locales/es/agents/sheldon.md +117 -0
  169. package/template/.aioson/locales/es/agents/squad.md +16 -0
  170. package/template/.aioson/locales/es/agents/tester.md +9 -0
  171. package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
  172. package/template/.aioson/locales/fr/agents/analyst.md +2 -0
  173. package/template/.aioson/locales/fr/agents/architect.md +19 -0
  174. package/template/.aioson/locales/fr/agents/dev.md +64 -4
  175. package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
  176. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
  177. package/template/.aioson/locales/fr/agents/genome.md +2 -0
  178. package/template/.aioson/locales/fr/agents/neo.md +2 -0
  179. package/template/.aioson/locales/fr/agents/orache.md +2 -0
  180. package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
  181. package/template/.aioson/locales/fr/agents/pair.md +2 -0
  182. package/template/.aioson/locales/fr/agents/pm.md +2 -0
  183. package/template/.aioson/locales/fr/agents/product.md +52 -0
  184. package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
  185. package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
  186. package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
  187. package/template/.aioson/locales/fr/agents/qa.md +2 -0
  188. package/template/.aioson/locales/fr/agents/setup.md +2 -0
  189. package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
  190. package/template/.aioson/locales/fr/agents/squad.md +16 -0
  191. package/template/.aioson/locales/fr/agents/tester.md +9 -0
  192. package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
  193. package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
  194. package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
  195. package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
  196. package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
  197. package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
  198. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
  199. package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
  200. package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
  201. package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
  202. package/template/.aioson/locales/pt-BR/agents/setup.md +101 -18
  203. package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
  204. package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
  205. package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
  206. package/template/.aioson/rules/README.md +69 -0
  207. package/template/.aioson/rules/data-format-convention.md +136 -0
  208. package/template/.aioson/rules/example-monetary-values.md +30 -0
  209. package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
  210. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
  211. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
  212. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
  213. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
  214. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
  215. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
  216. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
  217. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +1 -0
  218. package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
  219. package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
  220. package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
  221. package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
  222. package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +35 -0
  223. package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
  224. package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
  225. package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
  226. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +4 -1
  227. package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +15 -0
  228. package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +32 -0
  229. package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +20 -0
  230. package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
  231. package/template/.aioson/skills/static/context-budget-guide.md +46 -0
  232. package/template/.aioson/skills/static/harness-sensors.md +74 -0
  233. package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
  234. package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
  235. package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
  236. package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
  237. package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
  238. package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
  239. package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
  240. package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
  241. package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
  242. package/template/.aioson/skills/static/threejs-patterns.md +929 -0
  243. package/template/.aioson/skills/static/web-research-cache.md +112 -0
  244. package/template/.aioson/tasks/implementation-plan.md +21 -1
  245. package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
  246. package/template/.claude/commands/aioson/agent/orache.md +5 -0
  247. package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
  248. package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
  249. package/template/AGENTS.md +55 -3
  250. package/template/CLAUDE.md +30 -0
  251. package/template/OPENCODE.md +4 -0
  252. package/template/researchs/.gitkeep +0 -0
@@ -0,0 +1,241 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson workflow:execute — orchestrate the full agent workflow for a feature.
5
+ *
6
+ * Uses agent:prompt, gate:check, pulse:update, feature:close as building blocks.
7
+ * Always supports --dry-run to preview the plan without executing.
8
+ *
9
+ * Usage:
10
+ * aioson workflow:execute . --feature=checkout --tool=claude --dry-run
11
+ * aioson workflow:execute . --feature=checkout --tool=claude
12
+ * aioson workflow:execute . --feature=checkout --tool=claude --start-from=dev
13
+ * aioson workflow:execute . --feature=checkout --json --dry-run
14
+ */
15
+
16
+ const path = require('node:path');
17
+ const { execSync } = require('node:child_process');
18
+ const {
19
+ detectClassification,
20
+ scanArtifacts,
21
+ readPhaseGates
22
+ } = require('../preflight-engine');
23
+
24
+ const BAR = '━'.repeat(45);
25
+
26
+ const WORKFLOW_BY_CLASSIFICATION = {
27
+ MICRO: [
28
+ { agent: 'dev', gate_before: null, gate_after: null, description: 'Direct implementation' }
29
+ ],
30
+ SMALL: [
31
+ { agent: 'product', gate_before: null, gate_after: null, description: 'Generate PRD' },
32
+ { agent: 'sheldon', gate_before: null, gate_after: null, description: 'Enrich PRD (recommended)', optional: true },
33
+ { agent: 'analyst', gate_before: null, gate_after: 'A', description: 'Map requirements + spec' },
34
+ { agent: 'dev', gate_before: 'A', gate_after: 'C', description: 'Implementation' },
35
+ { agent: 'qa', gate_before: 'C', gate_after: 'D', description: 'QA + feature closure' }
36
+ ],
37
+ MEDIUM: [
38
+ { agent: 'product', gate_before: null, gate_after: null, description: 'Generate PRD' },
39
+ { agent: 'sheldon', gate_before: null, gate_after: null, description: 'Enrich PRD (required)', optional: false },
40
+ { agent: 'analyst', gate_before: null, gate_after: 'A', description: 'Map requirements + spec' },
41
+ { agent: 'architect', gate_before: 'A', gate_after: 'B', description: 'Architecture design' },
42
+ { agent: 'ux-ui', gate_before: 'A', gate_after: 'B', description: 'UI/UX design', optional: true },
43
+ { agent: 'pm', gate_before: 'B', gate_after: null, description: 'Backlog + PM plan' },
44
+ { agent: 'dev', gate_before: 'C', gate_after: 'C', description: 'Implementation' },
45
+ { agent: 'qa', gate_before: 'C', gate_after: 'D', description: 'QA + feature closure' }
46
+ ]
47
+ };
48
+
49
+ const GATE_NAMES = { A: 'requirements', B: 'design', C: 'plan', D: 'execution' };
50
+
51
+ async function buildExecutionPlan(targetDir, slug, classification, startFrom) {
52
+ const steps = WORKFLOW_BY_CLASSIFICATION[classification] || WORKFLOW_BY_CLASSIFICATION.SMALL;
53
+ const artifacts = await scanArtifacts(targetDir, slug);
54
+ const gates = await readPhaseGates(targetDir, slug);
55
+
56
+ const plan = [];
57
+ let stepNum = 1;
58
+ let startFromReached = !startFrom;
59
+
60
+ for (const step of steps) {
61
+ if (startFrom && !startFromReached) {
62
+ if (step.agent === startFrom) startFromReached = true;
63
+ else continue;
64
+ }
65
+
66
+ // Determine if step can be skipped (artifact already exists)
67
+ let skip = false;
68
+ let skipReason = null;
69
+
70
+ if (step.agent === 'product' && artifacts.prd.exists) {
71
+ skip = true; skipReason = 'prd already exists';
72
+ } else if (step.agent === 'sheldon' && artifacts.sheldon_enrichment.exists) {
73
+ skip = true; skipReason = 'sheldon enrichment already exists';
74
+ } else if (step.agent === 'analyst' && artifacts.requirements.exists && gates.requirements === 'approved') {
75
+ skip = true; skipReason = 'requirements + Gate A already approved';
76
+ } else if (step.agent === 'architect' && artifacts.architecture.exists && gates.design === 'approved') {
77
+ skip = true; skipReason = 'architecture + Gate B already approved';
78
+ }
79
+
80
+ plan.push({
81
+ step: stepNum++,
82
+ agent: step.agent,
83
+ description: step.description,
84
+ gate_before: step.gate_before,
85
+ gate_after: step.gate_after,
86
+ optional: step.optional || false,
87
+ skip,
88
+ skip_reason: skipReason
89
+ });
90
+ }
91
+
92
+ return plan;
93
+ }
94
+
95
+ function runCommand(cmd) {
96
+ try {
97
+ execSync(cmd, { stdio: 'inherit' });
98
+ return { ok: true };
99
+ } catch (err) {
100
+ return { ok: false, error: err.message };
101
+ }
102
+ }
103
+
104
+ async function runWorkflowExecute({ args, options = {}, logger }) {
105
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
106
+ const slug = options.feature ? String(options.feature) : null;
107
+ const tool = options.tool ? String(options.tool) : 'claude';
108
+ const dryRun = Boolean(options['dry-run'] || options.dry);
109
+ const startFrom = options['start-from'] ? String(options['start-from']) : null;
110
+ const skipOptional = Boolean(options['skip-optional']);
111
+
112
+ if (!slug) {
113
+ if (options.json) return { ok: false, reason: 'missing_feature' };
114
+ logger.log('--feature=<slug> is required.');
115
+ return { ok: false };
116
+ }
117
+
118
+ let classification = await detectClassification(targetDir, slug);
119
+ if (!classification) classification = options.classification ? String(options.classification).toUpperCase() : 'SMALL';
120
+
121
+ const plan = await buildExecutionPlan(targetDir, slug, classification, startFrom);
122
+ const activePlan = plan.filter((s) => !s.skip && !(skipOptional && s.optional));
123
+ const skippedPlan = plan.filter((s) => s.skip);
124
+
125
+ if (dryRun || options.json) {
126
+ const result = {
127
+ ok: true,
128
+ feature: slug,
129
+ classification,
130
+ tool,
131
+ dry_run: true,
132
+ steps: plan,
133
+ active_steps: activePlan.length,
134
+ skipped_steps: skippedPlan.length
135
+ };
136
+
137
+ if (options.json) return result;
138
+
139
+ logger.log('');
140
+ logger.log(`Workflow Execution Plan — ${slug} (${classification})`);
141
+ logger.log(BAR);
142
+
143
+ for (const step of plan) {
144
+ const icon = step.skip ? '○ (skip)' : `Step ${step.step}:`;
145
+ const optional = step.optional ? ' (optional)' : '';
146
+ const gateInfo = step.gate_after ? ` → Gate ${step.gate_after} check` : '';
147
+ const skipInfo = step.skip ? ` — ${step.skip_reason}` : '';
148
+ logger.log(`${icon} @${step.agent}${optional} — ${step.description}${gateInfo}${skipInfo}`);
149
+ }
150
+
151
+ logger.log('');
152
+ logger.log(`Gates enforced: ${plan.filter((s) => s.gate_after && !s.skip).map((s) => s.gate_after).join(', ') || 'none'}`);
153
+ logger.log(`Active sessions: ${activePlan.length} | Skipped: ${skippedPlan.length}`);
154
+ logger.log('');
155
+ logger.log('Run without --dry-run to execute.');
156
+ logger.log('');
157
+
158
+ return result;
159
+ }
160
+
161
+ // Execute
162
+ logger.log('');
163
+ logger.log(`Workflow Execution — ${slug} (${classification})`);
164
+ logger.log(BAR);
165
+
166
+ let completed = 0;
167
+ let failed = 0;
168
+ const executionLog = [];
169
+
170
+ for (const step of plan) {
171
+ if (step.skip) {
172
+ logger.log(`[skip] @${step.agent} — ${step.skip_reason}`);
173
+ executionLog.push({ step: step.step, agent: step.agent, status: 'skipped', reason: step.skip_reason });
174
+ continue;
175
+ }
176
+
177
+ if (skipOptional && step.optional) {
178
+ logger.log(`[skip] @${step.agent} — optional, skipped`);
179
+ executionLog.push({ step: step.step, agent: step.agent, status: 'skipped', reason: 'optional' });
180
+ continue;
181
+ }
182
+
183
+ // Gate check before
184
+ if (step.gate_before) {
185
+ logger.log(`[Gate ${step.gate_before} check] pre-step ${step.step}...`);
186
+ const gateCmd = `aioson gate:check ${targetDir} --feature=${slug} --gate=${step.gate_before}`;
187
+ const gateResult = runCommand(gateCmd);
188
+ if (!gateResult.ok) {
189
+ logger.log(`[Gate ${step.gate_before}] BLOCKED — cannot proceed with @${step.agent}`);
190
+ executionLog.push({ step: step.step, agent: step.agent, status: 'blocked', gate: step.gate_before });
191
+ failed++;
192
+ break;
193
+ }
194
+ }
195
+
196
+ logger.log(`[Step ${step.step}/${activePlan.length}] @${step.agent} — ${step.description}...`);
197
+ const agentCmd = `aioson agent:prompt ${targetDir} --agent=${step.agent} --feature=${slug} --tool=${tool}`;
198
+ const agentResult = runCommand(agentCmd);
199
+
200
+ if (!agentResult.ok) {
201
+ logger.log(`[Step ${step.step}] @${step.agent} FAILED`);
202
+ executionLog.push({ step: step.step, agent: step.agent, status: 'failed' });
203
+ failed++;
204
+ break;
205
+ }
206
+
207
+ // Gate check after
208
+ if (step.gate_after) {
209
+ logger.log(`[Gate ${step.gate_after} check] post-step ${step.step}...`);
210
+ }
211
+
212
+ // Pulse update
213
+ const pulseCmd = `aioson pulse:update ${targetDir} --agent=${step.agent} --feature=${slug} --action="${step.description}" 2>/dev/null || true`;
214
+ runCommand(pulseCmd);
215
+
216
+ executionLog.push({ step: step.step, agent: step.agent, status: 'completed' });
217
+ completed++;
218
+ logger.log(`[Step ${step.step}] @${step.agent} ✓`);
219
+ }
220
+
221
+ const allDone = completed === activePlan.length;
222
+ if (allDone) {
223
+ logger.log('');
224
+ logger.log(`Workflow complete: ${slug} → done`);
225
+ logger.log(`Total sessions: ${completed}`);
226
+ } else {
227
+ logger.log('');
228
+ logger.log(`Workflow stopped: ${completed} completed, ${failed} failed.`);
229
+ }
230
+
231
+ return {
232
+ ok: allDone,
233
+ feature: slug,
234
+ classification,
235
+ completed,
236
+ failed,
237
+ execution_log: executionLog
238
+ };
239
+ }
240
+
241
+ module.exports = { runWorkflowExecute };
package/src/constants.js CHANGED
@@ -34,6 +34,7 @@ const MANAGED_FILES = [
34
34
  '.aioson/agents/orache.md',
35
35
  '.aioson/agents/genome.md',
36
36
  '.aioson/agents/design-hybrid-forge.md',
37
+ '.aioson/agents/site-forge.md',
37
38
  '.aioson/agents/profiler-researcher.md',
38
39
  '.aioson/agents/profiler-enricher.md',
39
40
  '.aioson/agents/profiler-forge.md',
@@ -358,6 +359,14 @@ const AGENT_DEFINITIONS = [
358
359
  dependsOn: ['.aioson/context/project.context.md'],
359
360
  output: '.aioson/installed-skills/{hybrid-slug}/SKILL.md + .aioson/installed-skills/{hybrid-slug}/references/ + .aioson/installed-skills/{hybrid-slug}/previews/ + .aioson/installed-skills/{hybrid-slug}/.skill-meta.json'
360
361
  },
362
+ {
363
+ id: 'site-forge',
364
+ displayName: 'Site Forge',
365
+ command: '@site-forge',
366
+ path: '.aioson/agents/site-forge.md',
367
+ dependsOn: ['.aioson/context/project.context.md'],
368
+ output: 'src/components/*.tsx + src/app/page.tsx + docs/research/{hostname}/ + public/images/{hostname}/'
369
+ },
361
370
  {
362
371
  id: 'profiler-researcher',
363
372
  displayName: 'Profiler Researcher',
@@ -20,7 +20,7 @@ const TOOL_FILES = {
20
20
 
21
21
  // Squad agent/task/skill paths (non-locale)
22
22
  const SQUAD_PATHS = [
23
- /^\.aioson\/agents\/(squad|orache|genome|profiler-researcher|profiler-enricher|profiler-forge|design-hybrid-forge)\.md$/,
23
+ /^\.aioson\/agents\/(squad|orache|genome|profiler-researcher|profiler-enricher|profiler-forge)\.md$/,
24
24
  /^\.aioson\/tasks\/squad-/,
25
25
  /^\.aioson\/skills\/squad\//,
26
26
  /^\.aioson\/templates\/squads\//,
@@ -28,7 +28,7 @@ const SQUAD_PATHS = [
28
28
  ];
29
29
 
30
30
  // Squad agents inside locale dirs — filtered by BOTH locale AND squad
31
- const SQUAD_LOCALE_AGENT_RE = /^\.aioson\/locales\/([^/]+)\/agents\/(squad|orache|genome|profiler-researcher|profiler-enricher|profiler-forge|design-hybrid-forge)\.md$/;
31
+ const SQUAD_LOCALE_AGENT_RE = /^\.aioson\/locales\/([^/]+)\/agents\/(squad|orache|genome|profiler-researcher|profiler-enricher|profiler-forge)\.md$/;
32
32
 
33
33
  // Design skill IDs disponíveis
34
34
  const DESIGN_IDS = [
@@ -118,7 +118,7 @@ function renderScreen1(cursor, selected, warn, stdout) {
118
118
  stdout.write('\n');
119
119
  }
120
120
 
121
- function renderScreen2(cursor, selected, stdout) {
121
+ function renderScreen2(cursor, selected, warn, stdout) {
122
122
  header(2, 4, stdout);
123
123
  stdout.write(' What will you do with AIOSON?\n');
124
124
  stdout.write(' (space to select, enter to continue)\n\n');
@@ -130,6 +130,7 @@ function renderScreen2(cursor, selected, stdout) {
130
130
  stdout.write(` ${pointer} [${check}] ${use.label}${lock}\n`);
131
131
  stdout.write(` ${use.desc}\n`);
132
132
  }
133
+ if (warn) stdout.write('\n ⚠ Select at least one use to continue.\n');
133
134
  stdout.write('\n');
134
135
  }
135
136
 
@@ -413,7 +414,7 @@ async function runInstallWizard(options = {}, io = {}) {
413
414
  items: USES,
414
415
  defaultSelected: defaultUses,
415
416
  lockFirst: true,
416
- render: (cursor, selected, _warn, out) => renderScreen2(cursor, selected, out),
417
+ render: (cursor, selected, warn, out) => renderScreen2(cursor, selected, warn, out),
417
418
  io
418
419
  });
419
420
  if (!uses) { finalCleanup(); return null; }
package/src/installer.js CHANGED
@@ -186,6 +186,7 @@ async function installTemplate(targetDir, options = {}) {
186
186
  backupOnOverwrite = mode === 'update',
187
187
  frameworkDetection = null,
188
188
  installProfile = null,
189
+ selectiveUpdate = false,
189
190
  onProgress = null
190
191
  } = options;
191
192
 
@@ -219,6 +220,11 @@ async function installTemplate(targetDir, options = {}) {
219
220
  continue;
220
221
  }
221
222
 
223
+ if (!destExists && selectiveUpdate) {
224
+ skipped.push({ path: rel, reason: 'not-installed' });
225
+ continue;
226
+ }
227
+
222
228
  if (destExists && !overwrite && mode !== 'update') {
223
229
  skipped.push({ path: rel, reason: 'already-exists' });
224
230
  continue;
@@ -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 };