@jaimevalasek/aioson 1.28.1 → 1.30.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 (155) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +7 -5
  3. package/docs/en/5-reference/cli-reference.md +40 -10
  4. package/docs/pt/4-agentes/briefing.md +2 -0
  5. package/docs/pt/4-agentes/copywriter.md +2 -0
  6. package/docs/pt/4-agentes/genome.md +1 -0
  7. package/docs/pt/4-agentes/pm.md +1 -1
  8. package/docs/pt/4-agentes/profiler-enricher.md +2 -0
  9. package/docs/pt/4-agentes/profiler-forge.md +2 -0
  10. package/docs/pt/4-agentes/sheldon.md +2 -0
  11. package/docs/pt/4-agentes/squad.md +12 -10
  12. package/docs/pt/5-referencia/autopilot-handoff.md +4 -4
  13. package/docs/pt/5-referencia/comandos-cli.md +7 -3
  14. package/docs/pt/5-referencia/fluxo-artefatos.md +1 -1
  15. package/docs/pt/5-referencia/memoria-e-contexto.md +62 -2
  16. package/docs/pt/_arquivo/monitor-de-contexto.md +2 -2
  17. package/package.json +4 -2
  18. package/src/cli.js +72 -24
  19. package/src/commands/ac-test-audit.js +45 -0
  20. package/src/commands/artifact-validate.js +62 -50
  21. package/src/commands/classify.js +73 -2
  22. package/src/commands/context-brief.js +59 -0
  23. package/src/commands/context-guard.js +88 -0
  24. package/src/commands/context-monitor.js +1 -1
  25. package/src/commands/context-search.js +101 -52
  26. package/src/commands/context-select.js +11 -2
  27. package/src/commands/feature-archive.js +21 -12
  28. package/src/commands/feature-current.js +82 -0
  29. package/src/commands/gate-check.js +32 -15
  30. package/src/commands/harness-check.js +17 -1
  31. package/src/commands/hooks-install.js +169 -26
  32. package/src/commands/hygiene-scan.js +423 -0
  33. package/src/commands/rules-lint.js +124 -0
  34. package/src/commands/sdd-benchmark.js +134 -0
  35. package/src/commands/spec-analyze.js +6 -4
  36. package/src/commands/store-system.js +329 -49
  37. package/src/constants.js +8 -3
  38. package/src/context-brief.js +585 -0
  39. package/src/context-guard.js +209 -0
  40. package/src/context-search.js +796 -96
  41. package/src/context-selector.js +802 -420
  42. package/src/handoff-contract.js +14 -6
  43. package/src/harness/contract-schema.js +1 -1
  44. package/src/i18n/messages/en.js +12 -5
  45. package/src/i18n/messages/es.js +11 -4
  46. package/src/i18n/messages/fr.js +11 -4
  47. package/src/i18n/messages/pt-BR.js +12 -5
  48. package/src/lib/ac-test-audit.js +194 -0
  49. package/src/preflight-engine.js +10 -6
  50. package/src/squad/state-manager.js +1 -1
  51. package/template/.aioson/agents/analyst.md +93 -53
  52. package/template/.aioson/agents/architect.md +41 -32
  53. package/template/.aioson/agents/briefing-refiner.md +15 -2
  54. package/template/.aioson/agents/briefing.md +105 -86
  55. package/template/.aioson/agents/committer.md +1 -1
  56. package/template/.aioson/agents/copywriter.md +53 -10
  57. package/template/.aioson/agents/design-hybrid-forge.md +9 -5
  58. package/template/.aioson/agents/dev.md +22 -25
  59. package/template/.aioson/agents/deyvin.md +126 -124
  60. package/template/.aioson/agents/discover.md +8 -9
  61. package/template/.aioson/agents/discovery-design-doc.md +52 -36
  62. package/template/.aioson/agents/forge-run.md +3 -0
  63. package/template/.aioson/agents/genome.md +12 -6
  64. package/template/.aioson/agents/neo.md +30 -24
  65. package/template/.aioson/agents/orache.md +16 -21
  66. package/template/.aioson/agents/orchestrator.md +40 -31
  67. package/template/.aioson/agents/pentester.md +22 -12
  68. package/template/.aioson/agents/pm.md +11 -2
  69. package/template/.aioson/agents/product.md +162 -183
  70. package/template/.aioson/agents/profiler-enricher.md +29 -6
  71. package/template/.aioson/agents/profiler-forge.md +16 -6
  72. package/template/.aioson/agents/profiler-researcher.md +10 -6
  73. package/template/.aioson/agents/qa.md +29 -19
  74. package/template/.aioson/agents/scope-check.md +14 -2
  75. package/template/.aioson/agents/sheldon.md +51 -21
  76. package/template/.aioson/agents/site-forge.md +4 -6
  77. package/template/.aioson/agents/squad.md +7 -12
  78. package/template/.aioson/agents/tester.md +40 -30
  79. package/template/.aioson/agents/ux-ui.md +56 -41
  80. package/template/.aioson/agents/validator.md +2 -2
  81. package/template/.aioson/config.md +4 -3
  82. package/template/.aioson/design-docs/agent-loading-contract.md +3 -3
  83. package/template/.aioson/docs/LAYERS.md +2 -0
  84. package/template/.aioson/docs/autonomy-protocol.md +7 -5
  85. package/template/.aioson/docs/autopilot-handoff.md +5 -3
  86. package/template/.aioson/docs/dev/execution-discipline.md +3 -0
  87. package/template/.aioson/docs/dev/simple-plan-lane.md +126 -77
  88. package/template/.aioson/docs/dev/stack-conventions.md +4 -1
  89. package/template/.aioson/docs/deyvin/continuity-recovery.md +21 -18
  90. package/template/.aioson/docs/deyvin/debugging-escalation.md +3 -0
  91. package/template/.aioson/docs/deyvin/pair-execution.md +3 -0
  92. package/template/.aioson/docs/deyvin/runtime-handoffs.md +6 -3
  93. package/template/.aioson/docs/dossier/agent-templates.md +3 -0
  94. package/template/.aioson/docs/dossier/schema.md +3 -0
  95. package/template/.aioson/docs/example-external-api-context.md +2 -0
  96. package/template/.aioson/docs/feature-expansion-taxonomy.md +53 -0
  97. package/template/.aioson/docs/handoff-persistence.md +95 -91
  98. package/template/.aioson/docs/pentester/app-playbooks.md +3 -0
  99. package/template/.aioson/docs/pentester/browser-dast-playbook.md +401 -398
  100. package/template/.aioson/docs/pentester/llm-supplychain.md +3 -0
  101. package/template/.aioson/docs/product/conversation-playbook.md +1 -1
  102. package/template/.aioson/docs/quality/code-health-analysis.md +2 -0
  103. package/template/.aioson/docs/sheldon/enrichment-paths.md +47 -1
  104. package/template/.aioson/docs/sheldon/harness-contract.md +26 -21
  105. package/template/.aioson/docs/sheldon/quality-lens.md +3 -0
  106. package/template/.aioson/docs/sheldon/research-loop.md +3 -0
  107. package/template/.aioson/docs/sheldon/web-intelligence.md +3 -0
  108. package/template/.aioson/docs/site-forge-build.md +4 -2
  109. package/template/.aioson/docs/site-forge-extraction.md +2 -0
  110. package/template/.aioson/docs/site-forge-qa.md +2 -0
  111. package/template/.aioson/docs/site-forge-recon.md +7 -5
  112. package/template/.aioson/docs/site-forge-transform.md +2 -0
  113. package/template/.aioson/docs/squad/content-output.md +3 -0
  114. package/template/.aioson/docs/squad/creation-flow.md +22 -1
  115. package/template/.aioson/docs/squad/domain-breadth.md +3 -0
  116. package/template/.aioson/docs/squad/domain-classification.md +3 -0
  117. package/template/.aioson/docs/squad/eval-gate.md +3 -0
  118. package/template/.aioson/docs/squad/genome-bindings.md +14 -0
  119. package/template/.aioson/docs/squad/package-contract.md +5 -0
  120. package/template/.aioson/docs/squad/persona-grounding.md +65 -62
  121. package/template/.aioson/docs/squad/quality-lens.md +3 -0
  122. package/template/.aioson/docs/squad/research-loop.md +3 -0
  123. package/template/.aioson/docs/squad/session-operations.md +3 -0
  124. package/template/.aioson/docs/squad/workflow-quality.md +3 -0
  125. package/template/.aioson/docs/tester/coverage-quality.md +4 -1
  126. package/template/.aioson/docs/ux-ui/design-execution.md +9 -7
  127. package/template/.aioson/rules/README.md +48 -2
  128. package/template/.aioson/rules/agent-language-policy.md +26 -21
  129. package/template/.aioson/rules/agent-structural-contract.md +168 -158
  130. package/template/.aioson/rules/aioson-context-boundary.md +7 -1
  131. package/template/.aioson/rules/canonical-path-contract.md +16 -10
  132. package/template/.aioson/rules/data-format-convention.md +17 -11
  133. package/template/.aioson/rules/disk-first-artifacts.md +12 -8
  134. package/template/.aioson/rules/example-monetary-values.md +4 -0
  135. package/template/.aioson/rules/implementation-structure-and-data-access.md +50 -0
  136. package/template/.aioson/rules/output-brevity.md +2 -0
  137. package/template/.aioson/rules/prd-section-ownership.md +17 -12
  138. package/template/.aioson/rules/security-baseline.md +8 -3
  139. package/template/.aioson/rules/simple-plan-lane.md +22 -5
  140. package/template/.aioson/rules/source-code-language-convention.md +34 -0
  141. package/template/.aioson/rules/spec-level-ownership.md +10 -5
  142. package/template/.aioson/rules/squad-driver-pattern.md +5 -0
  143. package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +24 -23
  144. package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +4 -0
  145. package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +2 -2
  146. package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +1 -1
  147. package/template/.aioson/skills/process/briefing-expansion-scout/SKILL.md +72 -0
  148. package/template/.aioson/skills/process/product-scope-expansion/SKILL.md +74 -0
  149. package/template/.aioson/skills/process/sheldon-expansion-audit/SKILL.md +67 -0
  150. package/template/.aioson/skills/static/context-budget-guide.md +1 -1
  151. package/template/.aioson/skills/static/multi-agent-patterns.md +5 -4
  152. package/template/.aioson/tasks/squad-create.md +11 -0
  153. package/template/.aioson/tasks/squad-design.md +3 -3
  154. package/template/AGENTS.md +36 -19
  155. package/template/CLAUDE.md +9 -5
@@ -8,8 +8,9 @@
8
8
  * sessions early instead of discovering missing artifacts later.
9
9
  */
10
10
 
11
- const path = require('node:path');
12
- const { readFileSafe, fileExists } = require('./preflight-engine');
11
+ const path = require('node:path');
12
+ const { readFileSafe, fileExists } = require('./preflight-engine');
13
+ const { auditAcceptanceCriteriaTests } = require('./lib/ac-test-audit');
13
14
 
14
15
  // Contract definitions per agent stage
15
16
  const CONTRACTS = {
@@ -373,7 +374,7 @@ async function validateHandoffContract(targetDir, state, stageName) {
373
374
  }
374
375
 
375
376
  // 2. Gates
376
- for (const gateLetter of contract.gates) {
377
+ for (const gateLetter of contract.gates) {
377
378
  const gateCheck = await checkGateApproval(
378
379
  targetDir,
379
380
  gateLetter,
@@ -384,9 +385,16 @@ async function validateHandoffContract(targetDir, state, stageName) {
384
385
  if (!gateCheck.ok) {
385
386
  missing.push(`gate ${gateLetter} not approved (${gateCheck.reason})`);
386
387
  }
387
- }
388
-
389
- // 3. Context updates (soft check just warn if completely missing)
388
+ }
389
+
390
+ if (stageName === 'qa' && state.featureSlug) {
391
+ const acAudit = await auditAcceptanceCriteriaTests(targetDir, state.featureSlug);
392
+ if (!acAudit.ok) {
393
+ missing.push(`AC test audit failed: missing tests for ${acAudit.missing.join(', ')}`);
394
+ }
395
+ }
396
+
397
+ // 3. Context updates (soft check — just warn if completely missing)
390
398
  for (const p of contract.contextUpdates) {
391
399
  const abs = path.join(targetDir, p);
392
400
  if (!(await fileExists(abs))) {
@@ -144,7 +144,7 @@ function validateContract(contract) {
144
144
 
145
145
  if (contract.contract_mode !== undefined) {
146
146
  if (typeof contract.contract_mode !== 'string' || !VALID_MODES.has(contract.contract_mode.toLowerCase())) {
147
- errors.push({ field: 'contract_mode', reason: 'must be one of: BALANCED, safe, builder, autopilot' });
147
+ errors.push({ field: 'contract_mode', reason: 'must be one of: balanced, safe, builder, autopilot' });
148
148
  }
149
149
  }
150
150
 
@@ -13,9 +13,10 @@ module.exports = {
13
13
  help_setup:
14
14
  'aioson setup [path] [--defaults] [--framework=<name>] [--lang=<bcp47-tag>] [--project-name=<name>] [--force] [--dry-run] [--tool=codex|claude|opencode] [--locale=en]',
15
15
  help_update: 'aioson update [path] [--dry-run] [--lang=<bcp47-tag>] [--locale=en]',
16
- help_info: 'aioson info [path] [--json] [--locale=en]',
17
- help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=en]',
18
- help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=en]',
16
+ help_info: 'aioson info [path] [--json] [--locale=en]',
17
+ help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=en]',
18
+ help_hygiene_scan: 'aioson hygiene:scan [path] [--json] [--locale=en]',
19
+ help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=en]',
19
20
  help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=en]',
20
21
  help_agent_prompt:
21
22
  'aioson agent:prompt <agent> [path] [--tool=codex|claude|opencode] [--lang=<bcp47-tag>] [--locale=en]',
@@ -28,8 +29,14 @@ module.exports = {
28
29
  help_context_validate: 'aioson context:validate [path] [--json] [--locale=en]',
29
30
  help_context_pack:
30
31
  'aioson context:pack [path] [--agent=<agent>] [--goal=<text>] [--module=<module-or-folder>] [--max-files=8] [--json] [--locale=en]',
32
+ help_context_search:
33
+ 'aioson context:search [path] --query=<text> [--agent=<agent>] [--mode=planning|executing] [--task=<text>] [--paths=<path[,path2]>] [--intent=memory|feature|rules] [--limit=10] [--json] [--locale=en]',
31
34
  help_context_select:
32
- 'aioson context:select [path] [--agent=<agent>] [--mode=planning|executing] [--task=<text>] [--paths=<path[,path2]>] [--feature=<slug>] [--json] [--locale=en]',
35
+ 'aioson context:select [path] [--agent=<agent>] [--mode=planning|executing] [--task=<text>] [--paths=<path[,path2]>] [--feature=<slug>] [--no-semantic] [--json] [--locale=en]',
36
+ help_context_brief:
37
+ 'aioson context:brief [path] [--agent=<agent>] [--mode=planning|executing] [--task=<text>] [--paths=<path[,path2]>] [--feature=<slug>] [--no-semantic] [--no-recall] [--json] [--locale=en]',
38
+ help_context_guard:
39
+ 'aioson context:guard [path] [--tool=claude] [--agent=<agent>] [--event=<json>] [--event-file=<path>] [--json] [--locale=en]',
33
40
  help_context_load:
34
41
  'aioson context:load [path] --target=<rule|brain>:<slug> --agent=<name> [--batch="slug1,slug2"] [--feature=<slug>] [--classification=<MICRO|SMALL|MEDIUM>] [--verbose] [--json] [--locale=en]',
35
42
  help_chain_audit:
@@ -153,7 +160,7 @@ module.exports = {
153
160
  help_qa_report:
154
161
  'aioson qa:report [path] [--html] [--json] [--locale=en]',
155
162
  help_harness_init:
156
- 'aioson harness:init [path] --slug=<slug> [--mode=BALANCED|URGENT|ECONOMICAL] [--locale=en]',
163
+ 'aioson harness:init [path] --slug=<slug> [--mode=balanced|safe|builder|autopilot] [--locale=en]',
157
164
  help_harness_validate:
158
165
  'aioson harness:validate [path] --slug=<slug> [--base=<ref>] [--no-diff] [--max-diff-bytes=<n>] [--artifact=<path>] [--locale=en]',
159
166
  help_harness_check:
@@ -14,9 +14,10 @@ module.exports = {
14
14
  'aioson setup [path] [--defaults] [--framework=<nombre>] [--lang=<bcp47-tag>] [--project-name=<nombre>] [--force] [--dry-run] [--tool=codex|claude|opencode] [--locale=es]',
15
15
  help_update:
16
16
  'aioson update [path] [--dry-run] [--lang=<bcp47-tag>] [--locale=es]',
17
- help_info: 'aioson info [path] [--json] [--locale=es]',
18
- help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=es]',
19
- help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=es]',
17
+ help_info: 'aioson info [path] [--json] [--locale=es]',
18
+ help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=es]',
19
+ help_hygiene_scan: 'aioson hygiene:scan [path] [--json] [--locale=es]',
20
+ help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=es]',
20
21
  help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=es]',
21
22
  help_agent_prompt:
22
23
  'aioson agent:prompt <agent> [path] [--tool=codex|claude|opencode] [--lang=<bcp47-tag>] [--locale=es]',
@@ -29,8 +30,14 @@ module.exports = {
29
30
  help_context_validate: 'aioson context:validate [path] [--json] [--locale=es]',
30
31
  help_context_pack:
31
32
  'aioson context:pack [path] [--agent=<agente>] [--goal=<texto>] [--module=<modulo-o-carpeta>] [--max-files=8] [--json] [--locale=es]',
33
+ help_context_search:
34
+ 'aioson context:search [path] --query=<texto> [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<ruta[,ruta2]>] [--intent=memory|feature|rules] [--limit=10] [--json] [--locale=es]',
32
35
  help_context_select:
33
- 'aioson context:select [path] [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<ruta[,ruta2]>] [--feature=<slug>] [--json] [--locale=es]',
36
+ 'aioson context:select [path] [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<ruta[,ruta2]>] [--feature=<slug>] [--no-semantic] [--json] [--locale=es]',
37
+ help_context_brief:
38
+ 'aioson context:brief [path] [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<ruta[,ruta2]>] [--feature=<slug>] [--no-semantic] [--no-recall] [--json] [--locale=es]',
39
+ help_context_guard:
40
+ 'aioson context:guard [path] [--tool=claude] [--agent=<agente>] [--event=<json>] [--event-file=<ruta>] [--json] [--locale=es]',
34
41
  help_context_load:
35
42
  'aioson context:load [path] --target=<rule|brain>:<slug> --agent=<nombre> [--batch="slug1,slug2"] [--feature=<slug>] [--classification=<MICRO|SMALL|MEDIUM>] [--verbose] [--json] [--locale=es]',
36
43
  help_chain_audit:
@@ -14,9 +14,10 @@ module.exports = {
14
14
  'aioson setup [path] [--defaults] [--framework=<nom>] [--lang=<bcp47-tag>] [--project-name=<nom>] [--force] [--dry-run] [--tool=codex|claude|opencode] [--locale=fr]',
15
15
  help_update:
16
16
  'aioson update [path] [--dry-run] [--lang=<bcp47-tag>] [--locale=fr]',
17
- help_info: 'aioson info [path] [--json] [--locale=fr]',
18
- help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=fr]',
19
- help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=fr]',
17
+ help_info: 'aioson info [path] [--json] [--locale=fr]',
18
+ help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=fr]',
19
+ help_hygiene_scan: 'aioson hygiene:scan [path] [--json] [--locale=fr]',
20
+ help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=fr]',
20
21
  help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=fr]',
21
22
  help_agent_prompt:
22
23
  'aioson agent:prompt <agent> [path] [--tool=codex|claude|opencode] [--lang=<bcp47-tag>] [--locale=fr]',
@@ -29,8 +30,14 @@ module.exports = {
29
30
  help_context_validate: 'aioson context:validate [path] [--json] [--locale=fr]',
30
31
  help_context_pack:
31
32
  'aioson context:pack [path] [--agent=<agent>] [--goal=<texte>] [--module=<module-ou-dossier>] [--max-files=8] [--json] [--locale=fr]',
33
+ help_context_search:
34
+ 'aioson context:search [path] --query=<texte> [--agent=<agent>] [--mode=planning|executing] [--task=<texte>] [--paths=<chemin[,chemin2]>] [--intent=memory|feature|rules] [--limit=10] [--json] [--locale=fr]',
32
35
  help_context_select:
33
- 'aioson context:select [path] [--agent=<agent>] [--mode=planning|executing] [--task=<texte>] [--paths=<chemin[,chemin2]>] [--feature=<slug>] [--json] [--locale=fr]',
36
+ 'aioson context:select [path] [--agent=<agent>] [--mode=planning|executing] [--task=<texte>] [--paths=<chemin[,chemin2]>] [--feature=<slug>] [--no-semantic] [--json] [--locale=fr]',
37
+ help_context_brief:
38
+ 'aioson context:brief [path] [--agent=<agent>] [--mode=planning|executing] [--task=<texte>] [--paths=<chemin[,chemin2]>] [--feature=<slug>] [--no-semantic] [--no-recall] [--json] [--locale=fr]',
39
+ help_context_guard:
40
+ 'aioson context:guard [path] [--tool=claude] [--agent=<agent>] [--event=<json>] [--event-file=<chemin>] [--json] [--locale=fr]',
34
41
  help_context_load:
35
42
  'aioson context:load [path] --target=<rule|brain>:<slug> --agent=<nom> [--batch="slug1,slug2"] [--feature=<slug>] [--classification=<MICRO|SMALL|MEDIUM>] [--verbose] [--json] [--locale=fr]',
36
43
  help_chain_audit:
@@ -14,9 +14,10 @@ module.exports = {
14
14
  'aioson setup [path] [--defaults] [--framework=<nome>] [--lang=<bcp47-tag>] [--project-name=<nome>] [--force] [--dry-run] [--tool=codex|claude|opencode] [--locale=pt-BR]',
15
15
  help_update:
16
16
  'aioson update [path] [--dry-run] [--lang=<bcp47-tag>] [--locale=pt-BR]',
17
- help_info: 'aioson info [path] [--json] [--locale=pt-BR]',
18
- help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=pt-BR]',
19
- help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=pt-BR]',
17
+ help_info: 'aioson info [path] [--json] [--locale=pt-BR]',
18
+ help_doctor: 'aioson doctor [path] [--fix] [--dry-run] [--json] [--locale=pt-BR]',
19
+ help_hygiene_scan: 'aioson hygiene:scan [path] [--json] [--locale=pt-BR]',
20
+ help_i18n_add: 'aioson i18n:add <locale> [--force] [--dry-run] [--locale=pt-BR]',
20
21
  help_agents: 'aioson agents [path] [--lang=<bcp47-tag>] [--locale=pt-BR]',
21
22
  help_agent_prompt:
22
23
  'aioson agent:prompt <agent> [path] [--tool=codex|claude|opencode] [--lang=<bcp47-tag>] [--locale=pt-BR]',
@@ -29,8 +30,14 @@ module.exports = {
29
30
  help_context_validate: 'aioson context:validate [path] [--json] [--locale=pt-BR]',
30
31
  help_context_pack:
31
32
  'aioson context:pack [path] [--agent=<agente>] [--goal=<texto>] [--module=<modulo-ou-pasta>] [--max-files=8] [--json] [--locale=pt-BR]',
33
+ help_context_search:
34
+ 'aioson context:search [path] --query=<texto> [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<caminho[,caminho2]>] [--intent=memory|feature|rules] [--limit=10] [--json] [--locale=pt-BR]',
32
35
  help_context_select:
33
- 'aioson context:select [path] [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<caminho[,caminho2]>] [--feature=<slug>] [--json] [--locale=pt-BR]',
36
+ 'aioson context:select [path] [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<caminho[,caminho2]>] [--feature=<slug>] [--no-semantic] [--json] [--locale=pt-BR]',
37
+ help_context_brief:
38
+ 'aioson context:brief [path] [--agent=<agente>] [--mode=planning|executing] [--task=<texto>] [--paths=<caminho[,caminho2]>] [--feature=<slug>] [--no-semantic] [--no-recall] [--json] [--locale=pt-BR]',
39
+ help_context_guard:
40
+ 'aioson context:guard [path] [--tool=claude] [--agent=<agente>] [--event=<json>] [--event-file=<caminho>] [--json] [--locale=pt-BR]',
34
41
  help_context_load:
35
42
  'aioson context:load [path] --target=<rule|brain>:<slug> --agent=<nome> [--batch="slug1,slug2"] [--feature=<slug>] [--classification=<MICRO|SMALL|MEDIUM>] [--verbose] [--json] [--locale=pt-BR]',
36
43
  help_chain_audit:
@@ -155,7 +162,7 @@ module.exports = {
155
162
  help_qa_report:
156
163
  'aioson qa:report [path] [--html] [--json] [--locale=pt-BR]',
157
164
  help_harness_init:
158
- 'aioson harness:init [path] --slug=<slug> [--mode=BALANCED|URGENT|ECONOMICAL] [--locale=pt-BR]',
165
+ 'aioson harness:init [path] --slug=<slug> [--mode=balanced|safe|builder|autopilot] [--locale=pt-BR]',
159
166
  help_harness_validate:
160
167
  'aioson harness:validate [path] --slug=<slug> [--base=<ref>] [--no-diff] [--max-diff-bytes=<n>] [--artifact=<path>] [--locale=pt-BR]',
161
168
  help_harness_check:
@@ -0,0 +1,194 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * ac-test-audit — deterministic AC→test evidence audit (no LLM).
5
+ *
6
+ * `AC_ID_RE` is the single canonical AC identifier pattern; spec-analyze and
7
+ * artifact-validate import it so all three surfaces extract the same IDs
8
+ * (case-insensitive segments cover slugged ids like AC-checkout-01).
9
+ *
10
+ * Matching contract & known limitations (kept honest on purpose):
11
+ * - Evidence is a token-boundary mention of the AC id in a test file or in an
12
+ * executable harness criterion. `mentionsAcId` matches whole hyphen-delimited
13
+ * tokens so AC-1 does NOT match inside AC-10 (substring collision).
14
+ * - It cannot judge assertion strength: any token-boundary mention counts, so a
15
+ * weak/empty test or a comment that names the AC reads as covered. The
16
+ * harness `verification` path is the stronger evidence.
17
+ * - A test that exercises an AC's behaviour without naming the id reads as
18
+ * missing — the audit enforces the "cite the AC in its test" convention.
19
+ */
20
+
21
+ const fs = require('node:fs/promises');
22
+ const path = require('node:path');
23
+
24
+ const AC_ID_RE = /\bAC(?:-[A-Za-z0-9]+)+\b/g;
25
+ const TEST_FILE_RE = /(?:^|[\\/])(?:tests?|__tests__)[\\/].+\.(?:test|spec)\.(?:js|cjs|mjs|ts|tsx|jsx)$|(?:^|[\\/])[^\\/]+\.(?:test|spec)\.(?:js|cjs|mjs|ts|tsx|jsx)$/i;
26
+
27
+ function extractAcIds(content) {
28
+ return [...new Set(String(content || '').match(AC_ID_RE) || [])].sort();
29
+ }
30
+
31
+ function escapeRegExp(value) {
32
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
33
+ }
34
+
35
+ // Whole-token match: the id must not be flanked by word chars or hyphens, so
36
+ // AC-1 will not match inside AC-10 / AC-100 and AC-SDLC-1 not inside AC-SDLC-10.
37
+ function mentionsAcId(text, acId) {
38
+ return new RegExp(`(?<![\\w-])${escapeRegExp(acId)}(?![\\w-])`).test(String(text || ''));
39
+ }
40
+
41
+ async function readText(filePath) {
42
+ try {
43
+ return await fs.readFile(filePath, 'utf8');
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ function toRel(targetDir, filePath) {
50
+ return path.relative(targetDir, filePath).split(path.sep).join('/');
51
+ }
52
+
53
+ function shouldSkipDir(targetDir, dirPath) {
54
+ const rel = toRel(targetDir, dirPath);
55
+ return rel.split('/').some((part, idx, parts) => {
56
+ if (part === 'node_modules' || part === '.git' || part === 'dist' || part === 'build' || part === 'coverage') return true;
57
+ return idx > 0 && parts[idx - 1] === '.aioson' && part === 'backups';
58
+ });
59
+ }
60
+
61
+ async function listTestFiles(targetDir, dirPath = targetDir, out = []) {
62
+ let entries;
63
+ try {
64
+ entries = await fs.readdir(dirPath, { withFileTypes: true });
65
+ } catch {
66
+ return out;
67
+ }
68
+
69
+ for (const entry of entries) {
70
+ const full = path.join(dirPath, entry.name);
71
+ if (entry.isDirectory()) {
72
+ if (!shouldSkipDir(targetDir, full)) await listTestFiles(targetDir, full, out);
73
+ continue;
74
+ }
75
+ if (!entry.isFile()) continue;
76
+ const rel = toRel(targetDir, full);
77
+ if (TEST_FILE_RE.test(rel)) out.push(full);
78
+ }
79
+ return out;
80
+ }
81
+
82
+ function testEvidenceFor(acId, testContents) {
83
+ return testContents
84
+ .filter((item) => mentionsAcId(item.content, acId))
85
+ .map((item) => ({
86
+ file: item.file,
87
+ evidence: `test file references ${acId}`
88
+ }));
89
+ }
90
+
91
+ function harnessEvidenceFor(acId, contract) {
92
+ if (!contract || !Array.isArray(contract.criteria)) return [];
93
+ return contract.criteria
94
+ .filter((criterion) => {
95
+ if (!criterion || typeof criterion !== 'object') return false;
96
+ const text = JSON.stringify(criterion);
97
+ return mentionsAcId(text, acId) && typeof criterion.verification === 'string' && criterion.verification.trim();
98
+ })
99
+ .map((criterion) => ({
100
+ file: '.aioson/plans/{slug}/harness-contract.json',
101
+ criterion: criterion.id,
102
+ evidence: `executable harness criterion references ${acId}`
103
+ }));
104
+ }
105
+
106
+ async function readHarnessContract(targetDir, slug) {
107
+ const contractPath = path.join(targetDir, '.aioson', 'plans', slug, 'harness-contract.json');
108
+ const raw = await readText(contractPath);
109
+ if (!raw) return null;
110
+ try {
111
+ return JSON.parse(raw);
112
+ } catch {
113
+ return null;
114
+ }
115
+ }
116
+
117
+ async function collectAcceptanceCriteria(targetDir, slug) {
118
+ const contextDir = path.join(targetDir, '.aioson', 'context');
119
+ const sources = [
120
+ { kind: 'requirements', path: path.join(contextDir, `requirements-${slug}.md`) },
121
+ { kind: 'prd', path: path.join(contextDir, `prd-${slug}.md`) },
122
+ { kind: 'conformance', path: path.join(contextDir, `conformance-${slug}.yaml`) }
123
+ ];
124
+
125
+ const byId = new Map();
126
+ for (const source of sources) {
127
+ const content = await readText(source.path);
128
+ if (!content) continue;
129
+ for (const id of extractAcIds(content)) {
130
+ if (!byId.has(id)) {
131
+ byId.set(id, { id, sources: [] });
132
+ }
133
+ byId.get(id).sources.push({
134
+ kind: source.kind,
135
+ file: toRel(targetDir, source.path)
136
+ });
137
+ }
138
+ }
139
+
140
+ return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
141
+ }
142
+
143
+ async function auditAcceptanceCriteriaTests(targetDir, slug) {
144
+ const criteria = await collectAcceptanceCriteria(targetDir, slug);
145
+ const testFiles = await listTestFiles(targetDir);
146
+ const testContents = [];
147
+ for (const filePath of testFiles) {
148
+ const content = await readText(filePath);
149
+ if (content !== null) {
150
+ testContents.push({ file: toRel(targetDir, filePath), content });
151
+ }
152
+ }
153
+
154
+ const contract = await readHarnessContract(targetDir, slug);
155
+ const items = criteria.map((criterion) => {
156
+ const testEvidence = testEvidenceFor(criterion.id, testContents);
157
+ const harnessEvidence = harnessEvidenceFor(criterion.id, contract).map((e) => ({
158
+ ...e,
159
+ file: e.file.replace('{slug}', slug)
160
+ }));
161
+ const evidence = [...testEvidence, ...harnessEvidence];
162
+ return {
163
+ ac: criterion.id,
164
+ status: evidence.length > 0 ? 'covered' : 'missing',
165
+ sources: criterion.sources,
166
+ evidence
167
+ };
168
+ });
169
+
170
+ const missing = items.filter((item) => item.status === 'missing');
171
+ const summary = {
172
+ acs_total: items.length,
173
+ covered: items.filter((item) => item.status === 'covered').length,
174
+ missing: missing.length,
175
+ test_files_scanned: testContents.length
176
+ };
177
+
178
+ return {
179
+ ok: missing.length === 0,
180
+ feature: slug,
181
+ audited_at: new Date().toISOString(),
182
+ summary,
183
+ items,
184
+ missing: missing.map((item) => item.ac)
185
+ };
186
+ }
187
+
188
+ module.exports = {
189
+ AC_ID_RE,
190
+ extractAcIds,
191
+ mentionsAcId,
192
+ collectAcceptanceCriteria,
193
+ auditAcceptanceCriteriaTests
194
+ };
@@ -257,10 +257,11 @@ async function scanArtifacts(targetDir, slug) {
257
257
  : [path.join(dir, 'readiness.md')];
258
258
 
259
259
  const results = {
260
- project_context: await check('project.context', path.join(dir, 'project.context.md')),
261
- prd: slug ? await check('prd', path.join(dir, `prd-${slug}.md`)) : { exists: false },
262
- sheldon_enrichment: slug ? await check('sheldon', path.join(dir, `sheldon-enrichment-${slug}.md`)) : { exists: false },
263
- requirements: slug ? await check('requirements', path.join(dir, `requirements-${slug}.md`)) : { exists: false },
260
+ project_context: await check('project.context', path.join(dir, 'project.context.md')),
261
+ prd: slug ? await check('prd', path.join(dir, `prd-${slug}.md`)) : { exists: false },
262
+ sheldon_enrichment: slug ? await check('sheldon', path.join(dir, `sheldon-enrichment-${slug}.md`)) : { exists: false },
263
+ sheldon_validation: slug ? await check('sheldon-validation', path.join(dir, `sheldon-validation-${slug}.md`)) : { exists: false },
264
+ requirements: slug ? await check('requirements', path.join(dir, `requirements-${slug}.md`)) : { exists: false },
264
265
  spec: slug ? await check('spec', path.join(dir, `spec-${slug}.md`)) : await check('spec', path.join(dir, 'spec.md')),
265
266
  architecture: await check('architecture', path.join(dir, 'architecture.md')),
266
267
  design_doc: await checkFirst('design-doc', designDocCandidates),
@@ -479,8 +480,11 @@ function buildContextPackage(agent, slug, classification, artifacts, devState, m
479
480
  const downstreamAgents = ['discovery-design-doc', 'pm', 'orchestrator', 'dev', 'deyvin', 'qa'];
480
481
  const shouldCarryFullFeatureContext = downstreamAgents.includes(agent);
481
482
 
482
- if (shouldCarryFullFeatureContext && artifacts.prd.exists) pkg.push(artifacts.prd.path);
483
- if (shouldCarryFullFeatureContext && artifacts.sheldon_enrichment.exists) pkg.push(artifacts.sheldon_enrichment.path);
483
+ if (shouldCarryFullFeatureContext && artifacts.prd.exists) pkg.push(artifacts.prd.path);
484
+ if (shouldCarryFullFeatureContext && artifacts.sheldon_enrichment.exists) pkg.push(artifacts.sheldon_enrichment.path);
485
+ if (shouldCarryFullFeatureContext && artifacts.sheldon_validation && artifacts.sheldon_validation.exists) {
486
+ pkg.push(artifacts.sheldon_validation.path);
487
+ }
484
488
  if ((shouldCarryFullFeatureContext || ['analyst', 'architect'].includes(agent)) && artifacts.requirements.exists) {
485
489
  pkg.push(artifacts.requirements.path);
486
490
  }
@@ -6,7 +6,7 @@
6
6
  * Maintains a cross-session memory file per squad at:
7
7
  * .aioson/squads/{slug}/STATE.md
8
8
  *
9
- * The STATE.md survives /clear and gives the next session instant context on:
9
+ * The STATE.md survives /compact or /clear and gives the next session instant context on:
10
10
  * - Current position in the squad's lifecycle
11
11
  * - Velocity metrics
12
12
  * - Active blockers