@jaimevalasek/aioson 1.21.3 → 1.21.4
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 +1 -1
- package/package.json +1 -1
- package/src/agents.js +23 -22
- package/src/cli.js +43 -20
- package/src/commands/agent-audit.js +189 -119
- package/src/commands/artifact-validate.js +31 -14
- package/src/commands/context-health.js +170 -34
- package/src/commands/devlog-process.js +35 -13
- package/src/commands/learning.js +98 -19
- package/src/commands/live.js +48 -22
- package/src/commands/preflight.js +16 -7
- package/src/commands/quality-audit.js +119 -0
- package/src/commands/skill-audit.js +200 -0
- package/src/commands/squad-playbook.js +100 -0
- package/src/commands/squad-role-scan.js +188 -0
- package/src/commands/state-save.js +9 -7
- package/src/commands/workflow-execute.js +172 -32
- package/src/commands/workflow-next.js +148 -40
- package/src/commands/workflow-status.js +54 -22
- package/src/handoff-contract.js +11 -6
- package/src/i18n/messages/en.js +13 -7
- package/src/i18n/messages/es.js +7 -5
- package/src/i18n/messages/fr.js +7 -5
- package/src/i18n/messages/pt-BR.js +13 -7
- package/src/learning-import-claude.js +218 -0
- package/src/learning-loop-engine.js +268 -254
- package/src/learning-loop-migration.js +177 -163
- package/src/learning-materialize.js +192 -0
- package/src/lib/quality/provider.js +132 -0
- package/src/lib/quality/report.js +82 -0
- package/src/lib/quality/result.js +185 -0
- package/src/parser.js +5 -4
- package/src/preflight-engine.js +49 -22
- package/src/runtime-store.js +2 -1
- package/template/.aioson/agents/analyst.md +18 -6
- package/template/.aioson/agents/committer.md +5 -5
- package/template/.aioson/agents/copywriter.md +27 -27
- package/template/.aioson/agents/dev.md +58 -39
- package/template/.aioson/agents/deyvin.md +43 -32
- package/template/.aioson/agents/discovery-design-doc.md +27 -13
- package/template/.aioson/agents/genome.md +81 -82
- package/template/.aioson/agents/manifests/dev.manifest.json +5 -4
- package/template/.aioson/agents/manifests/deyvin.manifest.json +4 -3
- package/template/.aioson/agents/neo.md +1 -1
- package/template/.aioson/agents/orchestrator.md +1 -1
- package/template/.aioson/agents/pentester.md +2 -2
- package/template/.aioson/agents/product.md +27 -19
- package/template/.aioson/agents/qa.md +4 -4
- package/template/.aioson/agents/setup.md +1 -1
- package/template/.aioson/agents/site-forge.md +17 -19
- package/template/.aioson/agents/squad.md +4 -0
- package/template/.aioson/agents/tester.md +178 -153
- package/template/.aioson/agents/ux-ui.md +1 -1
- package/template/.aioson/config.md +12 -12
- package/template/.aioson/context/design-doc.md +136 -136
- package/template/.aioson/context/project-map.md +7 -5
- package/template/.aioson/context/seeds/seed-example.md +27 -27
- package/template/.aioson/context/user-profile.md +42 -42
- package/template/.aioson/design-docs/agent-loading-contract.md +117 -138
- package/template/.aioson/docs/dev/simple-plan-lane.md +92 -0
- package/template/.aioson/docs/product/conversation-playbook.md +15 -17
- package/template/.aioson/docs/site-forge-build.md +2 -2
- package/template/.aioson/docs/site-forge-recon.md +5 -5
- package/template/.aioson/docs/squad/creation-flow.md +55 -0
- package/template/.aioson/docs/squad/eval-gate.md +79 -0
- package/template/.aioson/docs/squad/package-contract.md +39 -6
- package/template/.aioson/docs/squad/persona-grounding.md +62 -0
- package/template/.aioson/docs/squad/quality-lens.md +12 -1
- package/template/.aioson/genomes/INDEX.md +37 -37
- package/template/.aioson/genomes/copywriting/references/application-notes.md +2 -2
- package/template/.aioson/genomes/copywriting/references/frameworks/pms-research.md +1 -1
- package/template/.aioson/genomes/copywriting-brunson/references/application-notes.md +2 -2
- package/template/.aioson/learnings/gotchas/.gitkeep +1 -0
- package/template/.aioson/learnings/recipes/.gitkeep +1 -0
- package/template/.aioson/rules/agent-language-policy.md +21 -21
- package/template/.aioson/rules/agent-structural-contract.md +2 -2
- package/template/.aioson/rules/aioson-context-boundary.md +8 -6
- package/template/.aioson/rules/canonical-path-contract.md +10 -5
- package/template/.aioson/rules/data-format-convention.md +11 -11
- package/template/.aioson/rules/disk-first-artifacts.md +5 -4
- package/template/.aioson/rules/prd-section-ownership.md +12 -12
- package/template/.aioson/rules/simple-plan-lane.md +48 -0
- package/template/.aioson/rules/spec-level-ownership.md +5 -4
- package/template/.aioson/schemas/squad-blueprint.schema.json +32 -11
- package/template/.aioson/schemas/squad-manifest.schema.json +29 -8
- package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +4 -4
- package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +30 -30
- package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +4 -4
- package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +2 -2
- package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +1 -1
- package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +1 -1
- package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +5 -5
- package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +2 -2
- package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +4 -4
- package/template/.aioson/skills/design-system/dashboards/SKILL.md +5 -5
- package/template/.aioson/skills/design-system/patterns/SKILL.md +1 -1
- package/template/.aioson/skills/marketing/references/cta-matrix.md +43 -43
- package/template/.aioson/skills/marketing/references/headline-matrix.md +33 -33
- package/template/.aioson/skills/marketing/references/market-intelligence.md +2 -2
- package/template/.aioson/skills/marketing/references/platform-constraints.md +2 -2
- package/template/.aioson/skills/marketing/references/pms-research.md +3 -3
- package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +7 -7
- package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +13 -11
- package/template/.aioson/skills/process/aioson-spec-driven/references/ui-language.md +85 -75
- package/template/.aioson/skills/process/decision-presentation/SKILL.md +11 -11
- package/template/.aioson/skills/process/decision-presentation/references/jargon-map.pt-BR.yaml +4 -4
- package/template/.aioson/skills/squad/references/executor-archetypes.md +77 -2
- package/template/.aioson/skills/static/harness-validate/SKILL.md +55 -46
- package/template/.aioson/skills/static/react-motion-patterns.md +1 -1
- package/template/.aioson/skills/static/static-html-patterns.md +2 -2
- package/template/.aioson/skills/static/threejs-patterns.md +2 -2
- package/template/.aioson/tasks/implementation-plan.md +325 -327
- package/template/.aioson/tasks/squad-analyze.md +93 -83
- package/template/.aioson/tasks/squad-create.md +156 -148
- package/template/.aioson/tasks/squad-design.md +223 -206
- package/template/.aioson/tasks/squad-eval.md +72 -0
- package/template/.aioson/tasks/squad-execution-plan.md +279 -279
- package/template/.aioson/tasks/squad-export.md +20 -20
- package/template/.aioson/tasks/squad-extend.md +73 -68
- package/template/.aioson/tasks/squad-investigate.md +57 -57
- package/template/.aioson/tasks/squad-pipeline.md +122 -122
- package/template/.aioson/tasks/squad-profile.md +48 -48
- package/template/.aioson/tasks/squad-refresh.md +242 -236
- package/template/.aioson/tasks/squad-repair.md +85 -85
- package/template/.aioson/tasks/squad-review.md +61 -61
- package/template/.aioson/tasks/squad-task-decompose.md +66 -66
- package/template/.aioson/tasks/squad-validate.md +65 -58
- package/template/.aioson/templates/squads/content-basic/template.json +1 -1
- package/template/.aioson/templates/squads/media-channel/template.json +1 -1
- package/template/.aioson/templates/squads/research-analysis/template.json +1 -1
- package/template/AGENTS.md +10 -6
- package/template/CLAUDE.md +10 -6
- package/template/OPENCODE.md +9 -5
- package/template/agents/_shared/learning-capture-directive.md +88 -0
package/CHANGELOG.md
CHANGED
|
@@ -29,7 +29,7 @@ All notable changes to this project will be documented in this file.
|
|
|
29
29
|
### Fixed
|
|
30
30
|
- **`memory:reflect-commit --dry-run` is now non-destructive.** The command never read the `--dry-run` flag, so a "dry run" silently performed the full destructive commit — it wrote the bootstrap files **and** unlinked the single-use manifest, leaving the flow unrecoverable (`missing_manifest`) on the next call. `--dry-run` now runs validation + path containment exactly like a real commit, then returns `{ ok: true, dryRun: true, would_write: [...] }` without writing any file or consuming the manifest, so a real commit can still follow. Regression coverage in `tests/memory-reflect-commit-dry-run.test.js`. Note: the reflect manifest remains single-use — a successful real commit consumes it (re-run by re-running `memory:reflect-prepare`).
|
|
31
31
|
|
|
32
|
-
## [1.21.0] - 2026-
|
|
32
|
+
## [1.21.0] - 2026-05-28
|
|
33
33
|
|
|
34
34
|
### Added
|
|
35
35
|
- **Gemini CLI deprecation warning (gemini-phaseout Phase 1).** Google announced (2026-05-20) that the Gemini CLI free/personal tier ends 2026-06-18.
|
package/package.json
CHANGED
package/src/agents.js
CHANGED
|
@@ -29,14 +29,15 @@ function buildAgentPrompt(agent, tool, options = {}) {
|
|
|
29
29
|
const safeTool = String(tool || 'codex').toLowerCase();
|
|
30
30
|
const instructionPath = options.instructionPath || agent.path;
|
|
31
31
|
const targetDir = options.targetDir ? String(options.targetDir) : '.';
|
|
32
|
-
const interactionLanguage = String(options.interactionLanguage || 'en');
|
|
33
|
-
const autonomyMode = String(options.autonomyMode || '').trim();
|
|
34
|
-
const capabilitySummary = String(options.capabilitySummary || '').trim();
|
|
35
|
-
const activationContext = String(options.activationContext || '').trim();
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
const interactionLanguage = String(options.interactionLanguage || 'en');
|
|
33
|
+
const autonomyMode = String(options.autonomyMode || '').trim();
|
|
34
|
+
const capabilitySummary = String(options.capabilitySummary || '').trim();
|
|
35
|
+
const activationContext = String(options.activationContext || '').trim();
|
|
36
|
+
const dependsOn = Array.isArray(options.dependsOn) ? options.dependsOn : agent.dependsOn;
|
|
37
|
+
const dependencyText =
|
|
38
|
+
dependsOn.length > 0
|
|
39
|
+
? `Check required context files first: ${dependsOn.join(', ')}.`
|
|
40
|
+
: 'No prerequisite context files are required.';
|
|
40
41
|
const activationBlock = activationContext
|
|
41
42
|
? [
|
|
42
43
|
'',
|
|
@@ -68,20 +69,20 @@ function buildAgentPrompt(agent, tool, options = {}) {
|
|
|
68
69
|
`**Scope boundary:** You operate exclusively as ${agent.command}. Do not perform work that belongs to another agent. When your work is complete, output only the handoff — which agent is next and why. Do not continue into that agent\'s territory.`,
|
|
69
70
|
].join('\n');
|
|
70
71
|
|
|
71
|
-
if (safeTool === 'claude') {
|
|
72
|
-
return `Read ${instructionPath} and execute ${agent.command}. ${dependencyText}${activationBlock}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (safeTool === 'gemini') {
|
|
76
|
-
return `Run the Gemini command mapped to ${instructionPath} and execute ${agent.command}. ${dependencyText}${activationBlock}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (safeTool === 'opencode') {
|
|
80
|
-
return `Use agent "${agent.id}" from ${instructionPath}. ${dependencyText}${activationBlock}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return `Read AGENTS.md and execute ${agent.command} using ${instructionPath}. ${dependencyText}${activationBlock}
|
|
84
|
-
}
|
|
72
|
+
if (safeTool === 'claude') {
|
|
73
|
+
return `Read ${instructionPath} and execute ${agent.command}. ${dependencyText}${activationBlock}\n\nWrite output to ${agent.output}.${autonomyBlock}${lifecycleBlock}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (safeTool === 'gemini') {
|
|
77
|
+
return `Run the Gemini command mapped to ${instructionPath} and execute ${agent.command}. ${dependencyText}${activationBlock}\n\nSave result to ${agent.output}.${autonomyBlock}${lifecycleBlock}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (safeTool === 'opencode') {
|
|
81
|
+
return `Use agent "${agent.id}" from ${instructionPath}. ${dependencyText}${activationBlock}\n\nSave output to ${agent.output}.${autonomyBlock}${lifecycleBlock}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return `Read AGENTS.md and execute ${agent.command} using ${instructionPath}. ${dependencyText}${activationBlock}\n\nSave output to ${agent.output}.${autonomyBlock}${lifecycleBlock}`;
|
|
85
|
+
}
|
|
85
86
|
|
|
86
87
|
module.exports = {
|
|
87
88
|
normalizeAgentName,
|
package/src/cli.js
CHANGED
|
@@ -58,6 +58,8 @@ const { runSquadStatus } = require('./commands/squad-status');
|
|
|
58
58
|
const { runSquadDoctor } = require('./commands/squad-doctor');
|
|
59
59
|
const { runSquadRepairGenomes } = require('./commands/squad-repair-genomes');
|
|
60
60
|
const { runSquadValidate } = require('./commands/squad-validate');
|
|
61
|
+
const { runSquadRoleScan } = require('./commands/squad-role-scan');
|
|
62
|
+
const { runSquadPlaybook } = require('./commands/squad-playbook');
|
|
61
63
|
const { runSquadExport } = require('./commands/squad-export');
|
|
62
64
|
const { runSquadPipeline } = require('./commands/squad-pipeline');
|
|
63
65
|
const { runSquadAgentCreate } = require('./commands/squad-agent-create');
|
|
@@ -80,10 +82,12 @@ const { runSquadWebhook } = require('./commands/squad-webhook');
|
|
|
80
82
|
const { runSquadBus } = require('./commands/squad-bus');
|
|
81
83
|
const { runSquadAutorun } = require('./commands/squad-autorun');
|
|
82
84
|
const { runSquadDependencyGraph } = require('./commands/squad-dependency-graph');
|
|
83
|
-
const { runSquadToolRegister } = require('./commands/squad-tool-register');
|
|
84
|
-
const { runSquadReview } = require('./commands/squad-review');
|
|
85
|
-
const { runAgentAudit } = require('./commands/agent-audit');
|
|
86
|
-
const {
|
|
85
|
+
const { runSquadToolRegister } = require('./commands/squad-tool-register');
|
|
86
|
+
const { runSquadReview } = require('./commands/squad-review');
|
|
87
|
+
const { runAgentAudit } = require('./commands/agent-audit');
|
|
88
|
+
const { runSkillAudit } = require('./commands/skill-audit');
|
|
89
|
+
const { runQualityAudit } = require('./commands/quality-audit');
|
|
90
|
+
const { runBriefGen } = require('./commands/brief-gen');
|
|
87
91
|
const { runHarnessInit, runHarnessValidate, runHarnessApplyValidation } = require('./commands/harness');
|
|
88
92
|
const { runVerifyGate } = require('./commands/verify-gate');
|
|
89
93
|
const {
|
|
@@ -325,6 +329,10 @@ const JSON_SUPPORTED_COMMANDS = new Set([
|
|
|
325
329
|
'squad-repair-genomes',
|
|
326
330
|
'squad:validate',
|
|
327
331
|
'squad-validate',
|
|
332
|
+
'squad:role-scan',
|
|
333
|
+
'squad-role-scan',
|
|
334
|
+
'squad:playbook',
|
|
335
|
+
'squad-playbook',
|
|
328
336
|
'squad:export',
|
|
329
337
|
'squad-export',
|
|
330
338
|
'squad:pipeline',
|
|
@@ -376,9 +384,13 @@ const JSON_SUPPORTED_COMMANDS = new Set([
|
|
|
376
384
|
'squad-tool-register',
|
|
377
385
|
'squad:review',
|
|
378
386
|
'squad-review',
|
|
379
|
-
'agent:audit',
|
|
380
|
-
'agent-audit',
|
|
381
|
-
'
|
|
387
|
+
'agent:audit',
|
|
388
|
+
'agent-audit',
|
|
389
|
+
'skill:audit',
|
|
390
|
+
'skill-audit',
|
|
391
|
+
'quality:audit',
|
|
392
|
+
'quality-audit',
|
|
393
|
+
'brief:gen',
|
|
382
394
|
'harness:init',
|
|
383
395
|
'harness-init',
|
|
384
396
|
'harness:validate',
|
|
@@ -812,9 +824,11 @@ function printHelp(t, logger) {
|
|
|
812
824
|
logHelpLine(t, logger, 'cli.help_squad_daemon');
|
|
813
825
|
logHelpLine(t, logger, 'cli.help_squad_mcp');
|
|
814
826
|
logHelpLine(t, logger, 'cli.help_squad_roi');
|
|
815
|
-
logHelpLine(t, logger, 'cli.help_squad_score');
|
|
816
|
-
logHelpLine(t, logger, 'cli.help_squad_learning');
|
|
817
|
-
logHelpLine(t, logger, 'cli.
|
|
827
|
+
logHelpLine(t, logger, 'cli.help_squad_score');
|
|
828
|
+
logHelpLine(t, logger, 'cli.help_squad_learning');
|
|
829
|
+
logHelpLine(t, logger, 'cli.help_agent_audit');
|
|
830
|
+
logHelpLine(t, logger, 'cli.help_quality_audit');
|
|
831
|
+
logHelpLine(t, logger, 'cli.help_learning');
|
|
818
832
|
logHelpLine(t, logger, 'cli.help_runtime_init');
|
|
819
833
|
logHelpLine(t, logger, 'cli.help_runtime_ingest');
|
|
820
834
|
logHelpLine(t, logger, 'cli.help_runtime_task_start');
|
|
@@ -837,9 +851,10 @@ function printHelp(t, logger) {
|
|
|
837
851
|
logHelpLine(t, logger, 'cli.help_scaffold_complete');
|
|
838
852
|
logHelpLine(t, logger, 'cli.help_runtime_backup');
|
|
839
853
|
logHelpLine(t, logger, 'cli.help_runtime_restore');
|
|
840
|
-
logHelpLine(t, logger, 'cli.help_skill_install');
|
|
841
|
-
logHelpLine(t, logger, 'cli.help_skill_list');
|
|
842
|
-
logHelpLine(t, logger, 'cli.help_skill_remove');
|
|
854
|
+
logHelpLine(t, logger, 'cli.help_skill_install');
|
|
855
|
+
logHelpLine(t, logger, 'cli.help_skill_list');
|
|
856
|
+
logHelpLine(t, logger, 'cli.help_skill_remove');
|
|
857
|
+
logHelpLine(t, logger, 'cli.help_skill_audit');
|
|
843
858
|
logHelpLine(t, logger, 'cli.help_design_hybrid_options');
|
|
844
859
|
logHelpLine(t, logger, 'cli.help_cloud_import_squad');
|
|
845
860
|
logHelpLine(t, logger, 'cli.help_cloud_import_genome');
|
|
@@ -1164,6 +1179,10 @@ async function main() {
|
|
|
1164
1179
|
result = await runSquadRepairGenomes({ args, options, logger: commandLogger, t });
|
|
1165
1180
|
} else if (command === 'squad:validate' || command === 'squad-validate') {
|
|
1166
1181
|
result = await runSquadValidate({ args, options, logger: commandLogger, t });
|
|
1182
|
+
} else if (command === 'squad:role-scan' || command === 'squad-role-scan') {
|
|
1183
|
+
result = await runSquadRoleScan({ args, options, logger: commandLogger });
|
|
1184
|
+
} else if (command === 'squad:playbook' || command === 'squad-playbook') {
|
|
1185
|
+
result = await runSquadPlaybook({ args, options, logger: commandLogger });
|
|
1167
1186
|
} else if (command === 'squad:export' || command === 'squad-export') {
|
|
1168
1187
|
result = await runSquadExport({ args, options, logger: commandLogger, t });
|
|
1169
1188
|
} else if (command === 'squad:pipeline' || command === 'squad-pipeline') {
|
|
@@ -1216,10 +1235,14 @@ async function main() {
|
|
|
1216
1235
|
result = await runSquadToolRegister({ args, options, logger: commandLogger });
|
|
1217
1236
|
} else if (command === 'squad:review' || command === 'squad-review') {
|
|
1218
1237
|
result = await runSquadReview({ args, options, logger: commandLogger });
|
|
1219
|
-
} else if (command === 'agent:audit' || command === 'agent-audit') {
|
|
1220
|
-
result = await runAgentAudit({ args, options, logger: commandLogger });
|
|
1221
|
-
} else if (command === '
|
|
1222
|
-
result = await
|
|
1238
|
+
} else if (command === 'agent:audit' || command === 'agent-audit') {
|
|
1239
|
+
result = await runAgentAudit({ args, options, logger: commandLogger });
|
|
1240
|
+
} else if (command === 'skill:audit' || command === 'skill-audit') {
|
|
1241
|
+
result = await runSkillAudit({ args, options, logger: commandLogger });
|
|
1242
|
+
} else if (command === 'quality:audit' || command === 'quality-audit') {
|
|
1243
|
+
result = await runQualityAudit({ args, options, logger: commandLogger });
|
|
1244
|
+
} else if (command === 'brief:gen' || command === 'brief-gen') {
|
|
1245
|
+
result = await runBriefGen({ args, options, logger: commandLogger, t });
|
|
1223
1246
|
} else if (command === 'harness:init' || command === 'harness-init') {
|
|
1224
1247
|
result = await runHarnessInit({ args, options, logger: commandLogger, t });
|
|
1225
1248
|
} else if (command === 'harness:validate' || command === 'harness-validate') {
|
|
@@ -1268,9 +1291,9 @@ async function main() {
|
|
|
1268
1291
|
result = await runSpecCheckpoint({ args, options, logger: commandLogger });
|
|
1269
1292
|
} else if (command === 'spec:tasks' || command === 'spec-tasks') {
|
|
1270
1293
|
result = await runSpecTasks({ args, options, logger: commandLogger });
|
|
1271
|
-
} else if (command.startsWith('learning:') || command === 'learning') {
|
|
1272
|
-
const sub = command === 'learning' ? (args[1] || 'list') : command.split(':')[1];
|
|
1273
|
-
result = await runLearning({ args, options: { ...options, sub }, logger: commandLogger, t });
|
|
1294
|
+
} else if (command.startsWith('learning:') || command === 'learning') {
|
|
1295
|
+
const sub = command === 'learning' ? (options.sub || args[1] || 'list') : command.split(':')[1];
|
|
1296
|
+
result = await runLearning({ args, options: { ...options, sub }, logger: commandLogger, t });
|
|
1274
1297
|
} else if (command.startsWith('plan:') || command === 'plan') {
|
|
1275
1298
|
const sub = command === 'plan' ? (args[1] || 'show') : command.split(':')[1];
|
|
1276
1299
|
result = await runImplementationPlan({ args, options: { ...options, sub }, logger: commandLogger, t });
|
|
@@ -19,8 +19,11 @@
|
|
|
19
19
|
*
|
|
20
20
|
* Usage:
|
|
21
21
|
* aioson agent:audit .
|
|
22
|
-
* aioson agent:audit . --verbose Show per-section breakdown
|
|
23
|
-
* aioson agent:audit . --locales Include locale variant files
|
|
22
|
+
* aioson agent:audit . --verbose Show per-section breakdown
|
|
23
|
+
* aioson agent:audit . --locales Include locale variant files
|
|
24
|
+
* aioson agent:audit . --runtime-only Scan project/runtime surfaces only
|
|
25
|
+
* aioson agent:audit . --template-only Scan template surfaces only
|
|
26
|
+
* aioson agent:audit . --inception Scan project and template surfaces
|
|
24
27
|
* aioson agent:audit . --fix Write savings report to .aioson/docs/agent-audit.md
|
|
25
28
|
* aioson agent:audit . --json
|
|
26
29
|
*/
|
|
@@ -117,7 +120,7 @@ function parseSections(content) {
|
|
|
117
120
|
|
|
118
121
|
// ─── File scanner ─────────────────────────────────────────────────────────────
|
|
119
122
|
|
|
120
|
-
async function scanAgentFile(filePath, relativePath) {
|
|
123
|
+
async function scanAgentFile(filePath, relativePath, category = 'workspace_agent') {
|
|
121
124
|
let content;
|
|
122
125
|
try {
|
|
123
126
|
content = await fs.readFile(filePath, 'utf8');
|
|
@@ -140,10 +143,11 @@ async function scanAgentFile(filePath, relativePath) {
|
|
|
140
143
|
? 'over_target'
|
|
141
144
|
: 'ok';
|
|
142
145
|
|
|
143
|
-
return {
|
|
144
|
-
file: relativePath,
|
|
145
|
-
slug,
|
|
146
|
-
|
|
146
|
+
return {
|
|
147
|
+
file: relativePath,
|
|
148
|
+
slug,
|
|
149
|
+
category,
|
|
150
|
+
agent_type: typeDef.type,
|
|
147
151
|
chars,
|
|
148
152
|
tokens: estimateTokens(chars),
|
|
149
153
|
target_chars: typeDef.target,
|
|
@@ -156,7 +160,7 @@ async function scanAgentFile(filePath, relativePath) {
|
|
|
156
160
|
};
|
|
157
161
|
}
|
|
158
162
|
|
|
159
|
-
async function scanDir(dirPath, projectDir, results) {
|
|
163
|
+
async function scanDir(dirPath, projectDir, results, category = 'workspace_agent') {
|
|
160
164
|
let entries;
|
|
161
165
|
try {
|
|
162
166
|
entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
@@ -166,12 +170,70 @@ async function scanDir(dirPath, projectDir, results) {
|
|
|
166
170
|
|
|
167
171
|
for (const entry of entries) {
|
|
168
172
|
if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
|
|
169
|
-
const filePath = path.join(dirPath, entry.name);
|
|
170
|
-
const rel = path.relative(projectDir, filePath).split(path.sep).join('/');
|
|
171
|
-
const result = await scanAgentFile(filePath, rel);
|
|
172
|
-
if (result) results.push(result);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
173
|
+
const filePath = path.join(dirPath, entry.name);
|
|
174
|
+
const rel = path.relative(projectDir, filePath).split(path.sep).join('/');
|
|
175
|
+
const result = await scanAgentFile(filePath, rel, category);
|
|
176
|
+
if (result) results.push(result);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function normalizeRel(projectDir, filePath) {
|
|
181
|
+
return path.relative(projectDir, filePath).split(path.sep).join('/');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function getAuditMode(options) {
|
|
185
|
+
const selected = [
|
|
186
|
+
options['runtime-only'] ? 'runtime' : null,
|
|
187
|
+
options['template-only'] ? 'template' : null,
|
|
188
|
+
options.inception ? 'inception' : null
|
|
189
|
+
].filter(Boolean);
|
|
190
|
+
|
|
191
|
+
if (selected.length > 1) {
|
|
192
|
+
return { error: 'conflicting_modes', selected };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return { mode: selected[0] || 'inception' };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function buildAgentRoots(targetDir, mode) {
|
|
199
|
+
const roots = [];
|
|
200
|
+
|
|
201
|
+
if (mode === 'runtime' || mode === 'inception') {
|
|
202
|
+
roots.push({
|
|
203
|
+
type: 'dir',
|
|
204
|
+
path: path.join(targetDir, '.aioson', 'agents'),
|
|
205
|
+
rel: '.aioson/agents',
|
|
206
|
+
category: 'workspace_agent'
|
|
207
|
+
});
|
|
208
|
+
for (const name of ['CLAUDE.md', 'AGENTS.md']) {
|
|
209
|
+
roots.push({
|
|
210
|
+
type: 'file',
|
|
211
|
+
path: path.join(targetDir, name),
|
|
212
|
+
rel: name,
|
|
213
|
+
category: 'auto_loaded'
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (mode === 'template' || mode === 'inception') {
|
|
219
|
+
roots.push({
|
|
220
|
+
type: 'dir',
|
|
221
|
+
path: path.join(targetDir, 'template', '.aioson', 'agents'),
|
|
222
|
+
rel: 'template/.aioson/agents',
|
|
223
|
+
category: 'template_agent'
|
|
224
|
+
});
|
|
225
|
+
for (const name of ['CLAUDE.md', 'AGENTS.md']) {
|
|
226
|
+
roots.push({
|
|
227
|
+
type: 'file',
|
|
228
|
+
path: path.join(targetDir, 'template', name),
|
|
229
|
+
rel: `template/${name}`,
|
|
230
|
+
category: 'auto_loaded'
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return roots;
|
|
236
|
+
}
|
|
175
237
|
|
|
176
238
|
// ─── Report writer ────────────────────────────────────────────────────────────
|
|
177
239
|
|
|
@@ -238,104 +300,98 @@ function buildMarkdownReport(files, projectDir) {
|
|
|
238
300
|
|
|
239
301
|
// ─── Main command ─────────────────────────────────────────────────────────────
|
|
240
302
|
|
|
241
|
-
async function runAgentAudit({ args, options = {}, logger }) {
|
|
242
|
-
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
243
|
-
const verbose = Boolean(options.verbose || options.v);
|
|
244
|
-
const includeLocales = Boolean(options.locales);
|
|
245
|
-
const writeFix = Boolean(options.fix);
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
if (
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
files.
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
logger.log('
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
logger.log(
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
'
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
for (const s of topSections) {
|
|
334
|
-
const flag = s.onDemandCandidate ? ' [on-demand candidate]' : '';
|
|
335
|
-
logger.log(` ${'§ ' + s.title.slice(0, 40)} ${formatKb(s.chars)}${flag}`);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
303
|
+
async function runAgentAudit({ args, options = {}, logger }) {
|
|
304
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
305
|
+
const verbose = Boolean(options.verbose || options.v);
|
|
306
|
+
const includeLocales = Boolean(options.locales);
|
|
307
|
+
const writeFix = Boolean(options.fix);
|
|
308
|
+
const modeResult = getAuditMode(options);
|
|
309
|
+
|
|
310
|
+
if (modeResult.error) {
|
|
311
|
+
if (!options.json) logger.error('Choose only one audit mode: --runtime-only, --template-only, or --inception.');
|
|
312
|
+
return { ok: false, reason: modeResult.error, selected: modeResult.selected };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const mode = modeResult.mode;
|
|
316
|
+
const scanRoots = buildAgentRoots(targetDir, mode);
|
|
317
|
+
|
|
318
|
+
const files = [];
|
|
319
|
+
|
|
320
|
+
for (const root of scanRoots) {
|
|
321
|
+
if (root.type === 'dir') {
|
|
322
|
+
if (await dirExists(root.path)) await scanDir(root.path, targetDir, files, root.category);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const r = await scanAgentFile(root.path, normalizeRel(targetDir, root.path), root.category);
|
|
327
|
+
if (r) files.push(r);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Optionally include locales
|
|
331
|
+
if (includeLocales && (mode === 'runtime' || mode === 'inception')) {
|
|
332
|
+
await scanLocaleAgents(path.join(targetDir, '.aioson', 'locales'), targetDir, files, 'workspace_agent');
|
|
333
|
+
}
|
|
334
|
+
if (includeLocales && (mode === 'template' || mode === 'inception')) {
|
|
335
|
+
await scanLocaleAgents(path.join(targetDir, 'template', '.aioson', 'locales'), targetDir, files, 'template_agent');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const roots = scanRoots.map((r) => r.rel);
|
|
339
|
+
|
|
340
|
+
if (files.length === 0) {
|
|
341
|
+
if (!options.json) logger.log('No agent files found. Run from the aioson project root or a project with .aioson/agents/.');
|
|
342
|
+
return { ok: false, reason: 'no_files', mode, roots };
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Sort by size descending
|
|
346
|
+
files.sort((a, b) => b.chars - a.chars);
|
|
347
|
+
|
|
348
|
+
if (options.json) return { ok: true, mode, roots, files };
|
|
349
|
+
|
|
350
|
+
// ── Console report ─────────────────────────────────────────────────────────
|
|
351
|
+
const overHard = files.filter((f) => f.status === 'over_hard');
|
|
352
|
+
const overTarget = files.filter((f) => f.status === 'over_target');
|
|
353
|
+
const totalTokens = files.reduce((s, f) => s + f.tokens, 0);
|
|
354
|
+
const totalSavings = files.reduce((s, f) => s + f.savings_tokens, 0);
|
|
355
|
+
|
|
356
|
+
logger.log('Agent Audit');
|
|
357
|
+
logger.log('─'.repeat(70));
|
|
358
|
+
logger.log(`Mode : ${mode}`);
|
|
359
|
+
logger.log(`Roots : ${roots.join(', ')}`);
|
|
360
|
+
logger.log(`Files scanned : ${files.length}`);
|
|
361
|
+
logger.log(`Total tokens : ~${totalTokens.toLocaleString()} per session`);
|
|
362
|
+
logger.log(`Over hard limit: ${overHard.length} Over target: ${overTarget.length}`);
|
|
363
|
+
logger.log(`Potential save : ~${totalSavings.toLocaleString()} tokens/session (on-demand split)`);
|
|
364
|
+
logger.log('');
|
|
365
|
+
|
|
366
|
+
// File table
|
|
367
|
+
const COL = { file: 45, type: 14, size: 9, tokens: 12, status: 8 };
|
|
368
|
+
logger.log(
|
|
369
|
+
'File'.padEnd(COL.file) +
|
|
370
|
+
'Type'.padEnd(COL.type) +
|
|
371
|
+
'Size'.padEnd(COL.size) +
|
|
372
|
+
'Tokens'.padEnd(COL.tokens) +
|
|
373
|
+
'Status'
|
|
374
|
+
);
|
|
375
|
+
logger.log('─'.repeat(70));
|
|
376
|
+
|
|
377
|
+
for (const f of files) {
|
|
378
|
+
const statusLabel = { ok: '✓ ok', over_target: '⚠ target', over_hard: '✗ hard' }[f.status];
|
|
379
|
+
logger.log(
|
|
380
|
+
f.file.slice(0, COL.file - 1).padEnd(COL.file) +
|
|
381
|
+
f.agent_type.padEnd(COL.type) +
|
|
382
|
+
formatKb(f.chars).padEnd(COL.size) +
|
|
383
|
+
formatTokens(f.chars).padEnd(COL.tokens) +
|
|
384
|
+
statusLabel
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
if (verbose && f.sections.length > 0) {
|
|
388
|
+
const topSections = [...f.sections].sort((a, b) => b.chars - a.chars).slice(0, 5);
|
|
389
|
+
for (const s of topSections) {
|
|
390
|
+
const flag = s.onDemandCandidate ? ' [on-demand candidate]' : '';
|
|
391
|
+
logger.log(` ${'§ ' + s.title.slice(0, 40)} ${formatKb(s.chars)}${flag}`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
339
395
|
|
|
340
396
|
logger.log('');
|
|
341
397
|
|
|
@@ -375,15 +431,29 @@ async function runAgentAudit({ args, options = {}, logger }) {
|
|
|
375
431
|
logger.log(' Run with --verbose to see per-section breakdown.');
|
|
376
432
|
}
|
|
377
433
|
|
|
378
|
-
return {
|
|
379
|
-
ok: true,
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
434
|
+
return {
|
|
435
|
+
ok: true,
|
|
436
|
+
mode,
|
|
437
|
+
roots,
|
|
438
|
+
files: files.length,
|
|
439
|
+
over_hard: overHard.length,
|
|
440
|
+
over_target: overTarget.length,
|
|
441
|
+
total_tokens: totalTokens,
|
|
384
442
|
potential_savings_tokens: totalSavings
|
|
385
443
|
};
|
|
386
|
-
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async function scanLocaleAgents(localesBase, targetDir, files, category) {
|
|
447
|
+
try {
|
|
448
|
+
const langs = await fs.readdir(localesBase, { withFileTypes: true });
|
|
449
|
+
for (const lang of langs) {
|
|
450
|
+
if (!lang.isDirectory()) continue;
|
|
451
|
+
await scanDir(path.join(localesBase, lang.name, 'agents'), targetDir, files, category);
|
|
452
|
+
}
|
|
453
|
+
} catch {
|
|
454
|
+
// locales dir optional
|
|
455
|
+
}
|
|
456
|
+
}
|
|
387
457
|
|
|
388
458
|
async function dirExists(dirPath) {
|
|
389
459
|
try {
|
|
@@ -70,8 +70,9 @@ async function runArtifactValidate({ args, options = {}, logger }) {
|
|
|
70
70
|
reqCount = `${new Set(reqs).size} REQs, ${new Set(acs).size} ACs`;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
// Conformance required?
|
|
74
|
-
const conformanceRequired = classification === 'MEDIUM';
|
|
73
|
+
// Conformance required?
|
|
74
|
+
const conformanceRequired = classification === 'MEDIUM';
|
|
75
|
+
const designDocRequired = classification === 'SMALL' || classification === 'MEDIUM';
|
|
75
76
|
|
|
76
77
|
// Build chain items
|
|
77
78
|
const chain = [
|
|
@@ -110,15 +111,29 @@ async function runArtifactValidate({ args, options = {}, logger }) {
|
|
|
110
111
|
required: true,
|
|
111
112
|
indent: 1
|
|
112
113
|
},
|
|
113
|
-
{
|
|
114
|
-
name: 'architecture.md',
|
|
115
|
-
exists: artifacts.architecture.exists,
|
|
116
|
-
detail: null,
|
|
117
|
-
required: true,
|
|
118
|
-
indent: 1
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
name:
|
|
114
|
+
{
|
|
115
|
+
name: 'architecture.md',
|
|
116
|
+
exists: artifacts.architecture.exists,
|
|
117
|
+
detail: null,
|
|
118
|
+
required: true,
|
|
119
|
+
indent: 1
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'design-doc.md',
|
|
123
|
+
exists: artifacts.design_doc.exists,
|
|
124
|
+
detail: designDocRequired ? 'pre-dev design governance contract' : `SMALL/MEDIUM only — NOT required for ${classification || 'MICRO'}`,
|
|
125
|
+
required: designDocRequired,
|
|
126
|
+
indent: 1
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'readiness.md',
|
|
130
|
+
exists: artifacts.readiness.exists,
|
|
131
|
+
detail: designDocRequired ? 'pre-dev readiness contract' : `SMALL/MEDIUM only — NOT required for ${classification || 'MICRO'}`,
|
|
132
|
+
required: designDocRequired,
|
|
133
|
+
indent: 1
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: `implementation-plan-${slug}.md`,
|
|
122
137
|
exists: artifacts.implementation_plan.exists,
|
|
123
138
|
detail: planStatus ? `status: ${planStatus}` : null,
|
|
124
139
|
required: true,
|
|
@@ -143,9 +158,11 @@ async function runArtifactValidate({ args, options = {}, logger }) {
|
|
|
143
158
|
const ARTIFACT_OWNER_MAP = {
|
|
144
159
|
'project.context.md': { agent: '@setup', reason: 'setup not complete' },
|
|
145
160
|
[`prd-${slug}.md`]: { agent: '@product', reason: 'PRD not produced yet' },
|
|
146
|
-
[`requirements-${slug}.md`]: { agent: '@analyst', reason: 'requirements not produced yet (Gate A)' },
|
|
147
|
-
'architecture.md': { agent: '@architect', reason: 'architecture not produced yet (Gate B)' },
|
|
148
|
-
|
|
161
|
+
[`requirements-${slug}.md`]: { agent: '@analyst', reason: 'requirements not produced yet (Gate A)' },
|
|
162
|
+
'architecture.md': { agent: '@architect', reason: 'architecture not produced yet (Gate B)' },
|
|
163
|
+
'design-doc.md': { agent: '@discovery-design-doc', reason: 'design governance contract not produced yet' },
|
|
164
|
+
'readiness.md': { agent: '@discovery-design-doc', reason: 'readiness contract not produced yet' },
|
|
165
|
+
[`implementation-plan-${slug}.md`]: { agent: '@pm', reason: 'implementation plan not produced yet (Gate C)' },
|
|
149
166
|
[`spec-${slug}.md`]: { agent: '@analyst', reason: 'spec not produced yet — @analyst seeds the feature memory' },
|
|
150
167
|
[`conformance-${slug}.yaml`]: { agent: '@analyst', reason: 'conformance contract missing — @analyst creates it for MEDIUM features' }
|
|
151
168
|
};
|