@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.
- package/CHANGELOG.md +42 -0
- package/README.md +7 -5
- package/docs/en/5-reference/cli-reference.md +40 -10
- package/docs/pt/4-agentes/briefing.md +2 -0
- package/docs/pt/4-agentes/copywriter.md +2 -0
- package/docs/pt/4-agentes/genome.md +1 -0
- package/docs/pt/4-agentes/pm.md +1 -1
- package/docs/pt/4-agentes/profiler-enricher.md +2 -0
- package/docs/pt/4-agentes/profiler-forge.md +2 -0
- package/docs/pt/4-agentes/sheldon.md +2 -0
- package/docs/pt/4-agentes/squad.md +12 -10
- package/docs/pt/5-referencia/autopilot-handoff.md +4 -4
- package/docs/pt/5-referencia/comandos-cli.md +7 -3
- package/docs/pt/5-referencia/fluxo-artefatos.md +1 -1
- package/docs/pt/5-referencia/memoria-e-contexto.md +62 -2
- package/docs/pt/_arquivo/monitor-de-contexto.md +2 -2
- package/package.json +4 -2
- package/src/cli.js +72 -24
- package/src/commands/ac-test-audit.js +45 -0
- package/src/commands/artifact-validate.js +62 -50
- package/src/commands/classify.js +73 -2
- package/src/commands/context-brief.js +59 -0
- package/src/commands/context-guard.js +88 -0
- package/src/commands/context-monitor.js +1 -1
- package/src/commands/context-search.js +101 -52
- package/src/commands/context-select.js +11 -2
- package/src/commands/feature-archive.js +21 -12
- package/src/commands/feature-current.js +82 -0
- package/src/commands/gate-check.js +32 -15
- package/src/commands/harness-check.js +17 -1
- package/src/commands/hooks-install.js +169 -26
- package/src/commands/hygiene-scan.js +423 -0
- package/src/commands/rules-lint.js +124 -0
- package/src/commands/sdd-benchmark.js +134 -0
- package/src/commands/spec-analyze.js +6 -4
- package/src/commands/store-system.js +329 -49
- package/src/constants.js +8 -3
- package/src/context-brief.js +585 -0
- package/src/context-guard.js +209 -0
- package/src/context-search.js +796 -96
- package/src/context-selector.js +802 -420
- package/src/handoff-contract.js +14 -6
- package/src/harness/contract-schema.js +1 -1
- package/src/i18n/messages/en.js +12 -5
- package/src/i18n/messages/es.js +11 -4
- package/src/i18n/messages/fr.js +11 -4
- package/src/i18n/messages/pt-BR.js +12 -5
- package/src/lib/ac-test-audit.js +194 -0
- package/src/preflight-engine.js +10 -6
- package/src/squad/state-manager.js +1 -1
- package/template/.aioson/agents/analyst.md +93 -53
- package/template/.aioson/agents/architect.md +41 -32
- package/template/.aioson/agents/briefing-refiner.md +15 -2
- package/template/.aioson/agents/briefing.md +105 -86
- package/template/.aioson/agents/committer.md +1 -1
- package/template/.aioson/agents/copywriter.md +53 -10
- package/template/.aioson/agents/design-hybrid-forge.md +9 -5
- package/template/.aioson/agents/dev.md +22 -25
- package/template/.aioson/agents/deyvin.md +126 -124
- package/template/.aioson/agents/discover.md +8 -9
- package/template/.aioson/agents/discovery-design-doc.md +52 -36
- package/template/.aioson/agents/forge-run.md +3 -0
- package/template/.aioson/agents/genome.md +12 -6
- package/template/.aioson/agents/neo.md +30 -24
- package/template/.aioson/agents/orache.md +16 -21
- package/template/.aioson/agents/orchestrator.md +40 -31
- package/template/.aioson/agents/pentester.md +22 -12
- package/template/.aioson/agents/pm.md +11 -2
- package/template/.aioson/agents/product.md +162 -183
- package/template/.aioson/agents/profiler-enricher.md +29 -6
- package/template/.aioson/agents/profiler-forge.md +16 -6
- package/template/.aioson/agents/profiler-researcher.md +10 -6
- package/template/.aioson/agents/qa.md +29 -19
- package/template/.aioson/agents/scope-check.md +14 -2
- package/template/.aioson/agents/sheldon.md +51 -21
- package/template/.aioson/agents/site-forge.md +4 -6
- package/template/.aioson/agents/squad.md +7 -12
- package/template/.aioson/agents/tester.md +40 -30
- package/template/.aioson/agents/ux-ui.md +56 -41
- package/template/.aioson/agents/validator.md +2 -2
- package/template/.aioson/config.md +4 -3
- package/template/.aioson/design-docs/agent-loading-contract.md +3 -3
- package/template/.aioson/docs/LAYERS.md +2 -0
- package/template/.aioson/docs/autonomy-protocol.md +7 -5
- package/template/.aioson/docs/autopilot-handoff.md +5 -3
- package/template/.aioson/docs/dev/execution-discipline.md +3 -0
- package/template/.aioson/docs/dev/simple-plan-lane.md +126 -77
- package/template/.aioson/docs/dev/stack-conventions.md +4 -1
- package/template/.aioson/docs/deyvin/continuity-recovery.md +21 -18
- package/template/.aioson/docs/deyvin/debugging-escalation.md +3 -0
- package/template/.aioson/docs/deyvin/pair-execution.md +3 -0
- package/template/.aioson/docs/deyvin/runtime-handoffs.md +6 -3
- package/template/.aioson/docs/dossier/agent-templates.md +3 -0
- package/template/.aioson/docs/dossier/schema.md +3 -0
- package/template/.aioson/docs/example-external-api-context.md +2 -0
- package/template/.aioson/docs/feature-expansion-taxonomy.md +53 -0
- package/template/.aioson/docs/handoff-persistence.md +95 -91
- package/template/.aioson/docs/pentester/app-playbooks.md +3 -0
- package/template/.aioson/docs/pentester/browser-dast-playbook.md +401 -398
- package/template/.aioson/docs/pentester/llm-supplychain.md +3 -0
- package/template/.aioson/docs/product/conversation-playbook.md +1 -1
- package/template/.aioson/docs/quality/code-health-analysis.md +2 -0
- package/template/.aioson/docs/sheldon/enrichment-paths.md +47 -1
- package/template/.aioson/docs/sheldon/harness-contract.md +26 -21
- package/template/.aioson/docs/sheldon/quality-lens.md +3 -0
- package/template/.aioson/docs/sheldon/research-loop.md +3 -0
- package/template/.aioson/docs/sheldon/web-intelligence.md +3 -0
- package/template/.aioson/docs/site-forge-build.md +4 -2
- package/template/.aioson/docs/site-forge-extraction.md +2 -0
- package/template/.aioson/docs/site-forge-qa.md +2 -0
- package/template/.aioson/docs/site-forge-recon.md +7 -5
- package/template/.aioson/docs/site-forge-transform.md +2 -0
- package/template/.aioson/docs/squad/content-output.md +3 -0
- package/template/.aioson/docs/squad/creation-flow.md +22 -1
- package/template/.aioson/docs/squad/domain-breadth.md +3 -0
- package/template/.aioson/docs/squad/domain-classification.md +3 -0
- package/template/.aioson/docs/squad/eval-gate.md +3 -0
- package/template/.aioson/docs/squad/genome-bindings.md +14 -0
- package/template/.aioson/docs/squad/package-contract.md +5 -0
- package/template/.aioson/docs/squad/persona-grounding.md +65 -62
- package/template/.aioson/docs/squad/quality-lens.md +3 -0
- package/template/.aioson/docs/squad/research-loop.md +3 -0
- package/template/.aioson/docs/squad/session-operations.md +3 -0
- package/template/.aioson/docs/squad/workflow-quality.md +3 -0
- package/template/.aioson/docs/tester/coverage-quality.md +4 -1
- package/template/.aioson/docs/ux-ui/design-execution.md +9 -7
- package/template/.aioson/rules/README.md +48 -2
- package/template/.aioson/rules/agent-language-policy.md +26 -21
- package/template/.aioson/rules/agent-structural-contract.md +168 -158
- package/template/.aioson/rules/aioson-context-boundary.md +7 -1
- package/template/.aioson/rules/canonical-path-contract.md +16 -10
- package/template/.aioson/rules/data-format-convention.md +17 -11
- package/template/.aioson/rules/disk-first-artifacts.md +12 -8
- package/template/.aioson/rules/example-monetary-values.md +4 -0
- package/template/.aioson/rules/implementation-structure-and-data-access.md +50 -0
- package/template/.aioson/rules/output-brevity.md +2 -0
- package/template/.aioson/rules/prd-section-ownership.md +17 -12
- package/template/.aioson/rules/security-baseline.md +8 -3
- package/template/.aioson/rules/simple-plan-lane.md +22 -5
- package/template/.aioson/rules/source-code-language-convention.md +34 -0
- package/template/.aioson/rules/spec-level-ownership.md +10 -5
- package/template/.aioson/rules/squad-driver-pattern.md +5 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +24 -23
- package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +4 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +2 -2
- package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +1 -1
- package/template/.aioson/skills/process/briefing-expansion-scout/SKILL.md +72 -0
- package/template/.aioson/skills/process/product-scope-expansion/SKILL.md +74 -0
- package/template/.aioson/skills/process/sheldon-expansion-audit/SKILL.md +67 -0
- package/template/.aioson/skills/static/context-budget-guide.md +1 -1
- package/template/.aioson/skills/static/multi-agent-patterns.md +5 -4
- package/template/.aioson/tasks/squad-create.md +11 -0
- package/template/.aioson/tasks/squad-design.md +3 -3
- package/template/AGENTS.md +36 -19
- package/template/CLAUDE.md +9 -5
package/src/handoff-contract.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
147
|
+
errors.push({ field: 'contract_mode', reason: 'must be one of: balanced, safe, builder, autopilot' });
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
package/src/i18n/messages/en.js
CHANGED
|
@@ -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
|
-
|
|
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=
|
|
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:
|
package/src/i18n/messages/es.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
package/src/i18n/messages/fr.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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=
|
|
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
|
+
};
|
package/src/preflight-engine.js
CHANGED
|
@@ -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
|
-
|
|
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
|