@jaimevalasek/aioson 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/README.md +729 -232
- package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
- package/docs/integrations/sdlc-genius-boundary.md +76 -0
- package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
- package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
- package/docs/integrations/sdlc-genius-review-samples.md +86 -0
- package/docs/pt/README.md +3 -0
- package/docs/pt/agentes.md +1 -0
- package/docs/pt/comandos-cli.md +888 -2
- package/docs/pt/design-hybrid-forge.md +255 -6
- package/docs/pt/devlog-pipeline.md +270 -0
- package/docs/pt/fluxo-artefatos.md +178 -0
- package/docs/pt/hooks-session-guard.md +454 -0
- package/docs/pt/monitor-de-contexto.md +59 -5
- package/docs/pt/sdd-automation-scripts.md +557 -0
- package/docs/pt/site-forge.md +309 -0
- package/docs/pt/spec-learnings-pipeline.md +265 -0
- package/package.json +1 -1
- package/src/a2a/client.js +165 -0
- package/src/a2a/server.js +223 -0
- package/src/cli.js +235 -1
- package/src/commands/agent-audit.js +397 -0
- package/src/commands/agent-export-skill.js +229 -0
- package/src/commands/artifact-validate.js +189 -0
- package/src/commands/brief-gen.js +405 -0
- package/src/commands/brief-validate.js +65 -0
- package/src/commands/classify.js +256 -0
- package/src/commands/context-compact.js +49 -0
- package/src/commands/context-health.js +175 -0
- package/src/commands/context-monitor.js +71 -0
- package/src/commands/context-trim.js +177 -0
- package/src/commands/detect-test-runner.js +55 -0
- package/src/commands/devlog-export-brains.js +27 -0
- package/src/commands/devlog-process.js +292 -0
- package/src/commands/devlog-watch.js +131 -0
- package/src/commands/feature-close.js +165 -0
- package/src/commands/gate-check.js +228 -0
- package/src/commands/hooks-emit.js +253 -0
- package/src/commands/hooks-install.js +347 -0
- package/src/commands/learning-auto-promote.js +195 -0
- package/src/commands/learning-evolve.js +18 -9
- package/src/commands/learning-export.js +103 -0
- package/src/commands/learning-rollback.js +164 -0
- package/src/commands/live.js +25 -1
- package/src/commands/pattern-detect.js +33 -0
- package/src/commands/preflight-context.js +30 -0
- package/src/commands/preflight.js +208 -0
- package/src/commands/pulse-update.js +130 -0
- package/src/commands/runner-daemon.js +274 -0
- package/src/commands/runner-plan.js +70 -0
- package/src/commands/runner-queue-from-plan.js +166 -0
- package/src/commands/runner-queue.js +189 -0
- package/src/commands/runner-run.js +129 -0
- package/src/commands/runtime.js +47 -1
- package/src/commands/self-implement-loop.js +256 -0
- package/src/commands/session-guard.js +218 -0
- package/src/commands/sizing.js +165 -0
- package/src/commands/skill.js +65 -0
- package/src/commands/spec-checkpoint.js +177 -0
- package/src/commands/spec-status.js +79 -0
- package/src/commands/spec-sync.js +190 -0
- package/src/commands/spec-tasks.js +288 -0
- package/src/commands/squad-autorun.js +1220 -0
- package/src/commands/squad-bus.js +217 -0
- package/src/commands/squad-card.js +149 -0
- package/src/commands/squad-daemon.js +134 -0
- package/src/commands/squad-dependency-graph.js +164 -0
- package/src/commands/squad-review.js +106 -0
- package/src/commands/squad-scaffold.js +55 -0
- package/src/commands/squad-tool-register.js +157 -0
- package/src/commands/state-save.js +122 -0
- package/src/commands/update.js +2 -0
- package/src/commands/verify-gate.js +572 -0
- package/src/commands/workflow-execute.js +241 -0
- package/src/constants.js +9 -0
- package/src/install-profile.js +2 -2
- package/src/install-wizard.js +3 -2
- package/src/installer.js +6 -0
- package/src/lib/health-check.js +158 -0
- package/src/lib/hook-protocol.js +76 -0
- package/src/mcp/apps/squad-dashboard/app.js +163 -0
- package/src/mcp/apps/squad-dashboard/index.html +261 -0
- package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
- package/src/mcp/resources/squad-state.js +130 -0
- package/src/preflight-engine.js +443 -0
- package/src/runner/cascade.js +97 -0
- package/src/runner/cli-launcher.js +109 -0
- package/src/runner/plan-importer.js +63 -0
- package/src/runner/queue-store.js +159 -0
- package/src/runtime-store.js +61 -3
- package/src/squad/agent-teams-adapter.js +264 -0
- package/src/squad/brief-validator.js +350 -0
- package/src/squad/bus-bridge.js +140 -0
- package/src/squad/context-compactor.js +265 -0
- package/src/squad/cross-ai-synthesizer.js +250 -0
- package/src/squad/hooks-generator.js +196 -0
- package/src/squad/inter-squad-events.js +175 -0
- package/src/squad/intra-bus.js +345 -0
- package/src/squad/learning-extractor.js +213 -0
- package/src/squad/pattern-detector.js +365 -0
- package/src/squad/preflight-context.js +296 -0
- package/src/squad/recovery-context.js +242 -71
- package/src/squad/reflection.js +365 -0
- package/src/squad/squad-scaffold.js +177 -0
- package/src/squad/state-manager.js +310 -0
- package/src/squad/task-decomposer.js +652 -0
- package/src/squad/verify-gate.js +303 -0
- package/src/updater.js +4 -5
- package/src/worker-runner.js +186 -1
- package/template/.aioson/agents/analyst.md +62 -1
- package/template/.aioson/agents/architect.md +61 -1
- package/template/.aioson/agents/design-hybrid-forge.md +14 -0
- package/template/.aioson/agents/dev.md +242 -24
- package/template/.aioson/agents/deyvin.md +66 -8
- package/template/.aioson/agents/discovery-design-doc.md +44 -0
- package/template/.aioson/agents/genome.md +14 -0
- package/template/.aioson/agents/neo.md +78 -1
- package/template/.aioson/agents/orache.md +50 -4
- package/template/.aioson/agents/orchestrator.md +197 -1
- package/template/.aioson/agents/pm.md +35 -0
- package/template/.aioson/agents/product.md +50 -5
- package/template/.aioson/agents/profiler-enricher.md +14 -0
- package/template/.aioson/agents/profiler-forge.md +14 -0
- package/template/.aioson/agents/profiler-researcher.md +14 -0
- package/template/.aioson/agents/qa.md +172 -21
- package/template/.aioson/agents/setup.md +79 -9
- package/template/.aioson/agents/sheldon.md +131 -6
- package/template/.aioson/agents/site-forge.md +1753 -0
- package/template/.aioson/agents/squad.md +162 -0
- package/template/.aioson/agents/tester.md +53 -0
- package/template/.aioson/agents/ux-ui.md +34 -1
- package/template/.aioson/brains/README.md +128 -0
- package/template/.aioson/brains/_index.json +16 -0
- package/template/.aioson/brains/scripts/query.js +103 -0
- package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
- package/template/.aioson/config.md +143 -13
- package/template/.aioson/constitution.md +33 -0
- package/template/.aioson/context/project-pulse.md +34 -0
- package/template/.aioson/docs/LAYERS.md +79 -0
- package/template/.aioson/docs/README.md +76 -0
- package/template/.aioson/docs/example-external-api-context.md +72 -0
- package/template/.aioson/locales/en/agents/architect.md +17 -0
- package/template/.aioson/locales/en/agents/dev.md +79 -13
- package/template/.aioson/locales/en/agents/orache.md +6 -0
- package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
- package/template/.aioson/locales/en/agents/product.md +50 -0
- package/template/.aioson/locales/en/agents/sheldon.md +115 -0
- package/template/.aioson/locales/en/agents/squad.md +14 -0
- package/template/.aioson/locales/en/agents/tester.md +6 -0
- package/template/.aioson/locales/es/agents/analyst.md +2 -0
- package/template/.aioson/locales/es/agents/architect.md +19 -0
- package/template/.aioson/locales/es/agents/dev.md +64 -4
- package/template/.aioson/locales/es/agents/deyvin.md +2 -0
- package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
- package/template/.aioson/locales/es/agents/genome.md +2 -0
- package/template/.aioson/locales/es/agents/neo.md +2 -0
- package/template/.aioson/locales/es/agents/orache.md +2 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
- package/template/.aioson/locales/es/agents/pair.md +2 -0
- package/template/.aioson/locales/es/agents/pm.md +2 -0
- package/template/.aioson/locales/es/agents/product.md +52 -0
- package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
- package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
- package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
- package/template/.aioson/locales/es/agents/qa.md +2 -0
- package/template/.aioson/locales/es/agents/setup.md +2 -0
- package/template/.aioson/locales/es/agents/sheldon.md +117 -0
- package/template/.aioson/locales/es/agents/squad.md +16 -0
- package/template/.aioson/locales/es/agents/tester.md +9 -0
- package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
- package/template/.aioson/locales/fr/agents/analyst.md +2 -0
- package/template/.aioson/locales/fr/agents/architect.md +19 -0
- package/template/.aioson/locales/fr/agents/dev.md +64 -4
- package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
- package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
- package/template/.aioson/locales/fr/agents/genome.md +2 -0
- package/template/.aioson/locales/fr/agents/neo.md +2 -0
- package/template/.aioson/locales/fr/agents/orache.md +2 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
- package/template/.aioson/locales/fr/agents/pair.md +2 -0
- package/template/.aioson/locales/fr/agents/pm.md +2 -0
- package/template/.aioson/locales/fr/agents/product.md +52 -0
- package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
- package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
- package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
- package/template/.aioson/locales/fr/agents/qa.md +2 -0
- package/template/.aioson/locales/fr/agents/setup.md +2 -0
- package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
- package/template/.aioson/locales/fr/agents/squad.md +16 -0
- package/template/.aioson/locales/fr/agents/tester.md +9 -0
- package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
- package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
- package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
- package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
- package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
- package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
- package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
- package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +101 -18
- package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
- package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
- package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
- package/template/.aioson/rules/README.md +69 -0
- package/template/.aioson/rules/data-format-convention.md +136 -0
- package/template/.aioson/rules/example-monetary-values.md +30 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
- package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
- package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
- package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +1 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +35 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
- package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +4 -1
- package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +15 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +32 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +20 -0
- package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
- package/template/.aioson/skills/static/context-budget-guide.md +46 -0
- package/template/.aioson/skills/static/harness-sensors.md +74 -0
- package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
- package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
- package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
- package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
- package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
- package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
- package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
- package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
- package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
- package/template/.aioson/skills/static/threejs-patterns.md +929 -0
- package/template/.aioson/skills/static/web-research-cache.md +112 -0
- package/template/.aioson/tasks/implementation-plan.md +21 -1
- package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
- package/template/.claude/commands/aioson/agent/orache.md +5 -0
- package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
- package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
- package/template/AGENTS.md +55 -3
- package/template/CLAUDE.md +30 -0
- package/template/OPENCODE.md +4 -0
- package/template/researchs/.gitkeep +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* aioson squad:review [projectDir] --squad=<slug> --output=<file>
|
|
5
|
+
* [--criteria=<text,...>] [--synthesize-to=<path>]
|
|
6
|
+
* [--include-current] [--timeout=<seconds>]
|
|
7
|
+
*
|
|
8
|
+
* Cross-AI adversarial review of a squad output.
|
|
9
|
+
*
|
|
10
|
+
* Detects available AI CLIs (excluding the current runtime), sends the same
|
|
11
|
+
* review prompt to each, and synthesizes results into REVIEWS.md.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* aioson squad:review . --squad=content-team --output=outputs/ep3.md
|
|
15
|
+
* aioson squad:review . --squad=content-team --output=outputs/ep3.md \
|
|
16
|
+
* --criteria="Check factual accuracy,Check tone consistency"
|
|
17
|
+
* aioson squad:review . --squad=content-team --output=outputs/ep3.md \
|
|
18
|
+
* --synthesize-to=outputs/ep3-reviews.md
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const path = require('node:path');
|
|
22
|
+
const { runCrossAIReview, detectAvailableCLIs } = require('../squad/cross-ai-synthesizer');
|
|
23
|
+
|
|
24
|
+
async function runSquadReview({ args, options = {}, logger }) {
|
|
25
|
+
const projectDir = path.resolve(process.cwd(), args[0] || '.');
|
|
26
|
+
const squadSlug = String(options.squad || '').trim();
|
|
27
|
+
const outputFile = String(options.output || '').trim();
|
|
28
|
+
|
|
29
|
+
if (!squadSlug) {
|
|
30
|
+
logger.error('Error: --squad is required');
|
|
31
|
+
return { ok: false, error: 'missing_squad' };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!outputFile) {
|
|
35
|
+
logger.error('Error: --output <file-to-review> is required');
|
|
36
|
+
return { ok: false, error: 'missing_output' };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const outputPath = path.isAbsolute(outputFile)
|
|
40
|
+
? outputFile
|
|
41
|
+
: path.join(projectDir, outputFile);
|
|
42
|
+
|
|
43
|
+
// Parse criteria
|
|
44
|
+
const rawCriteria = String(options.criteria || '').trim();
|
|
45
|
+
const reviewCriteria = rawCriteria
|
|
46
|
+
? rawCriteria.split(',').map((c) => c.trim()).filter(Boolean)
|
|
47
|
+
: [];
|
|
48
|
+
|
|
49
|
+
const excludeCurrent = options['include-current'] !== true && options['include-current'] !== 'true';
|
|
50
|
+
const timeoutMs = (Number(options.timeout || 60)) * 1000;
|
|
51
|
+
|
|
52
|
+
const synthesizeTo = options['synthesize-to']
|
|
53
|
+
? path.resolve(projectDir, String(options['synthesize-to']))
|
|
54
|
+
: null;
|
|
55
|
+
|
|
56
|
+
// Show what CLIs will be queried
|
|
57
|
+
const clis = detectAvailableCLIs({ excludeCurrent });
|
|
58
|
+
if (clis.length === 0) {
|
|
59
|
+
logger.error('No AI CLIs detected. Install claude, gemini, or codex in PATH.');
|
|
60
|
+
logger.log('You can override with --include-current to include the current runtime.');
|
|
61
|
+
return { ok: false, error: 'no_clis_detected' };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
logger.log(`Squad Review — ${squadSlug}`);
|
|
65
|
+
logger.log(`Output file: ${path.relative(projectDir, outputPath)}`);
|
|
66
|
+
logger.log(`Reviewers: ${clis.join(', ')}`);
|
|
67
|
+
if (reviewCriteria.length > 0) {
|
|
68
|
+
logger.log(`Criteria: ${reviewCriteria.join('; ')}`);
|
|
69
|
+
}
|
|
70
|
+
logger.log('');
|
|
71
|
+
logger.log('Querying reviewers...');
|
|
72
|
+
|
|
73
|
+
const result = await runCrossAIReview({
|
|
74
|
+
projectDir,
|
|
75
|
+
outputFile: outputPath,
|
|
76
|
+
reviewCriteria,
|
|
77
|
+
squadSlug,
|
|
78
|
+
excludeCurrent,
|
|
79
|
+
synthesizeTo,
|
|
80
|
+
timeoutMs
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (!result.ok) {
|
|
84
|
+
logger.error(`✗ Review failed: ${result.error}`);
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
logger.log('');
|
|
89
|
+
logger.log(`✓ Reviews complete`);
|
|
90
|
+
logger.log(` Reviewers: ${result.reviewers.join(', ')}`);
|
|
91
|
+
logger.log(` Successful: ${result.successCount}/${result.reviewers.length}`);
|
|
92
|
+
logger.log(` Written to: ${path.relative(projectDir, result.reviewsPath)}`);
|
|
93
|
+
|
|
94
|
+
if (result.failCount > 0) {
|
|
95
|
+
const failed = result.reviews.filter((r) => !r.ok);
|
|
96
|
+
logger.log('');
|
|
97
|
+
logger.log(` ⚠ Failed reviewers:`);
|
|
98
|
+
for (const f of failed) {
|
|
99
|
+
logger.log(` ${f.cli}: ${f.error}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { runSquadReview };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* aioson squad:scaffold — Deterministic squad directory generator
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* aioson squad:scaffold . --slug=content-team --name="Content Team" --mode=content
|
|
8
|
+
* aioson squad:scaffold . --slug=dev-core --name="Dev Core" --mode=code
|
|
9
|
+
* aioson squad:scaffold . --slug=research --name="Research Hub" --mode=hybrid
|
|
10
|
+
* aioson squad:scaffold . --slug=test --json
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const path = require('node:path');
|
|
14
|
+
const { scaffoldSquad } = require('../squad/squad-scaffold');
|
|
15
|
+
|
|
16
|
+
async function runSquadScaffold({ args, options = {}, logger }) {
|
|
17
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
18
|
+
const slug = String(options.slug || '').trim();
|
|
19
|
+
const name = String(options.name || slug || '').trim();
|
|
20
|
+
const mode = String(options.mode || 'hybrid').trim();
|
|
21
|
+
|
|
22
|
+
if (!slug) {
|
|
23
|
+
logger.error('Error: --slug is required');
|
|
24
|
+
return { ok: false, error: 'missing_slug' };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const result = await scaffoldSquad(targetDir, { slug, name, mode });
|
|
28
|
+
|
|
29
|
+
if (!result.ok) {
|
|
30
|
+
logger.error(`Error: ${result.error}`);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (options.json) return result;
|
|
35
|
+
|
|
36
|
+
logger.log(`Squad "${result.name}" scaffolded (mode: ${result.mode})`);
|
|
37
|
+
logger.log('');
|
|
38
|
+
logger.log('Files created:');
|
|
39
|
+
for (const f of result.files) {
|
|
40
|
+
logger.log(` ✓ ${f}`);
|
|
41
|
+
}
|
|
42
|
+
if (result.directories.length > 0) {
|
|
43
|
+
logger.log('');
|
|
44
|
+
logger.log('Directories created:');
|
|
45
|
+
for (const d of result.directories) {
|
|
46
|
+
logger.log(` ✓ ${d}/`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
logger.log('');
|
|
50
|
+
logger.log(`Total: ${result.total} items`);
|
|
51
|
+
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { runSquadScaffold };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* aioson squad:tool:register [projectDir] --squad=<slug> --name=<tool-name>
|
|
5
|
+
* --description=<desc> --handler=<shell-command>
|
|
6
|
+
* [--handler-type=shell|script] [--handler-path=<path>]
|
|
7
|
+
* [--input-schema=<json>] [--registered-by=<executor-slug>]
|
|
8
|
+
*
|
|
9
|
+
* Register a dynamic tool for a squad at runtime.
|
|
10
|
+
* Tools registered here are available to executors in subsequent squad:autorun sessions.
|
|
11
|
+
*
|
|
12
|
+
* Security: handler only receives AIOSON_TOOL_INPUT env var — no API keys, no PATH injection.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* aioson squad:tool:register . --squad=content-team --name=fetch-rss \
|
|
16
|
+
* --description="Fetch RSS feed and return items" \
|
|
17
|
+
* --handler='curl -s "$AIOSON_TOOL_INPUT" | python3 -c "import sys,xml.etree.ElementTree as ET; ..."'
|
|
18
|
+
*
|
|
19
|
+
* aioson squad:tool:register . --squad=content-team --list
|
|
20
|
+
* aioson squad:tool:register . --squad=content-team --name=fetch-rss --delete
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const path = require('node:path');
|
|
24
|
+
const { openRuntimeDb } = require('../runtime-store');
|
|
25
|
+
|
|
26
|
+
function nowIso() { return new Date().toISOString(); }
|
|
27
|
+
|
|
28
|
+
async function handleList(db, squadSlug, logger) {
|
|
29
|
+
const tools = db.prepare(
|
|
30
|
+
'SELECT * FROM dynamic_squad_tools WHERE squad_slug = ? ORDER BY registered_at DESC'
|
|
31
|
+
).all(squadSlug);
|
|
32
|
+
|
|
33
|
+
if (tools.length === 0) {
|
|
34
|
+
logger.log(`No dynamic tools registered for squad "${squadSlug}"`);
|
|
35
|
+
logger.log('Register one with: aioson squad:tool:register . --squad=' + squadSlug + ' --name=<name> --description=<desc> --handler=<cmd>');
|
|
36
|
+
return { ok: true, tools: [] };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
logger.log(`Dynamic tools for "${squadSlug}" (${tools.length}):`);
|
|
40
|
+
for (const t of tools) {
|
|
41
|
+
logger.log(` • ${t.name} [${t.handler_type}]${t.registered_by ? ' by ' + t.registered_by : ''}`);
|
|
42
|
+
logger.log(` ${t.description}`);
|
|
43
|
+
if (t.handler_code) logger.log(` Handler: ${t.handler_code.slice(0, 80)}${t.handler_code.length > 80 ? '...' : ''}`);
|
|
44
|
+
if (t.handler_path) logger.log(` Script: ${t.handler_path}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return { ok: true, tools };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function handleDelete(db, squadSlug, toolName, logger) {
|
|
51
|
+
const existing = db.prepare(
|
|
52
|
+
'SELECT name FROM dynamic_squad_tools WHERE name = ? AND squad_slug = ?'
|
|
53
|
+
).get(toolName, squadSlug);
|
|
54
|
+
|
|
55
|
+
if (!existing) {
|
|
56
|
+
logger.error(`Tool "${toolName}" not found for squad "${squadSlug}"`);
|
|
57
|
+
return { ok: false, error: 'tool_not_found' };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
db.prepare('DELETE FROM dynamic_squad_tools WHERE name = ? AND squad_slug = ?').run(toolName, squadSlug);
|
|
61
|
+
logger.log(`Deleted tool "${toolName}" from squad "${squadSlug}"`);
|
|
62
|
+
return { ok: true, deleted: toolName };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function runSquadToolRegister({ args, options = {}, logger }) {
|
|
66
|
+
const projectDir = path.resolve(process.cwd(), args[0] || '.');
|
|
67
|
+
const squadSlug = String(options.squad || '').trim();
|
|
68
|
+
|
|
69
|
+
if (!squadSlug) {
|
|
70
|
+
logger.error('Error: --squad is required');
|
|
71
|
+
return { ok: false, error: 'missing_squad' };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const handle = await openRuntimeDb(projectDir);
|
|
75
|
+
if (!handle) {
|
|
76
|
+
logger.error('Runtime database unavailable. Run: aioson runtime:init .');
|
|
77
|
+
return { ok: false, error: 'no_db' };
|
|
78
|
+
}
|
|
79
|
+
const { db } = handle;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
// List mode
|
|
83
|
+
if (options.list) {
|
|
84
|
+
return handleList(db, squadSlug, logger);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const toolName = String(options.name || '').trim();
|
|
88
|
+
if (!toolName) {
|
|
89
|
+
logger.error('Error: --name is required');
|
|
90
|
+
return { ok: false, error: 'missing_name' };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Delete mode
|
|
94
|
+
if (options.delete) {
|
|
95
|
+
return handleDelete(db, squadSlug, toolName, logger);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Register mode
|
|
99
|
+
const description = String(options.description || options.desc || '').trim();
|
|
100
|
+
if (!description) {
|
|
101
|
+
logger.error('Error: --description is required');
|
|
102
|
+
return { ok: false, error: 'missing_description' };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const handlerType = String(options['handler-type'] || options.handlerType || 'shell').trim();
|
|
106
|
+
const handlerCode = String(options.handler || options['handler-code'] || '').trim() || null;
|
|
107
|
+
const handlerPath = String(options['handler-path'] || options.handlerPath || '').trim() || null;
|
|
108
|
+
|
|
109
|
+
if (!handlerCode && !handlerPath) {
|
|
110
|
+
logger.error('Error: --handler (shell command) or --handler-path (script path) is required');
|
|
111
|
+
return { ok: false, error: 'missing_handler' };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let inputSchema = '{}';
|
|
115
|
+
if (options['input-schema'] || options.inputSchema) {
|
|
116
|
+
try {
|
|
117
|
+
const raw = String(options['input-schema'] || options.inputSchema);
|
|
118
|
+
JSON.parse(raw); // validate
|
|
119
|
+
inputSchema = raw;
|
|
120
|
+
} catch {
|
|
121
|
+
logger.error('Error: --input-schema must be valid JSON');
|
|
122
|
+
return { ok: false, error: 'invalid_input_schema' };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const registeredBy = String(options['registered-by'] || options.registeredBy || '').trim() || null;
|
|
127
|
+
|
|
128
|
+
db.prepare(`
|
|
129
|
+
INSERT INTO dynamic_squad_tools
|
|
130
|
+
(name, squad_slug, description, input_schema, handler_type, handler_code, handler_path, registered_at, registered_by)
|
|
131
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
132
|
+
ON CONFLICT(name, squad_slug) DO UPDATE SET
|
|
133
|
+
description = excluded.description,
|
|
134
|
+
input_schema = excluded.input_schema,
|
|
135
|
+
handler_type = excluded.handler_type,
|
|
136
|
+
handler_code = excluded.handler_code,
|
|
137
|
+
handler_path = excluded.handler_path,
|
|
138
|
+
registered_at = excluded.registered_at,
|
|
139
|
+
registered_by = excluded.registered_by
|
|
140
|
+
`).run(toolName, squadSlug, description, inputSchema, handlerType, handlerCode, handlerPath, nowIso(), registeredBy);
|
|
141
|
+
|
|
142
|
+
logger.log(`✓ Tool "${toolName}" registered for squad "${squadSlug}"`);
|
|
143
|
+
logger.log(` Type: ${handlerType}`);
|
|
144
|
+
logger.log(` Description: ${description}`);
|
|
145
|
+
if (handlerCode) logger.log(` Handler: ${handlerCode.slice(0, 80)}${handlerCode.length > 80 ? '...' : ''}`);
|
|
146
|
+
if (handlerPath) logger.log(` Script: ${handlerPath}`);
|
|
147
|
+
logger.log('');
|
|
148
|
+
logger.log('Executors can request this tool via the bus (type: tool_request):');
|
|
149
|
+
logger.log(` { "type": "tool_request", "content": "run:${toolName}", "metadata": { "input": "..." } }`);
|
|
150
|
+
|
|
151
|
+
return { ok: true, tool: { name: toolName, squad: squadSlug, handlerType, description } };
|
|
152
|
+
} finally {
|
|
153
|
+
db.close();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = { runSquadToolRegister };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* aioson state:save — create/update dev-state.md for @dev session resumption.
|
|
5
|
+
*
|
|
6
|
+
* Replaces the manual dev-state.md update block. Stores active feature,
|
|
7
|
+
* phase, next step, spec version, and context package.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* aioson state:save . --feature=checkout --phase=3 --next="Implement notification listeners" \
|
|
11
|
+
* --spec-version=3 --status=in_progress
|
|
12
|
+
* aioson state:save . --feature=checkout --next="Continue payment webhook" --status=in_progress
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require('node:fs/promises');
|
|
16
|
+
const path = require('node:path');
|
|
17
|
+
const { contextDir, readFileSafe, parseFrontmatter, scanArtifacts } = require('../preflight-engine');
|
|
18
|
+
|
|
19
|
+
function nowDate() {
|
|
20
|
+
return new Date().toISOString().slice(0, 10);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function runStateSave({ args, options = {}, logger }) {
|
|
24
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
25
|
+
const slug = options.feature ? String(options.feature) : null;
|
|
26
|
+
const phase = options.phase ? String(options.phase) : null;
|
|
27
|
+
const next = options.next ? String(options.next) : null;
|
|
28
|
+
const specVersion = options['spec-version'] ? String(options['spec-version']) : null;
|
|
29
|
+
const status = options.status ? String(options.status) : 'in_progress';
|
|
30
|
+
const plan = options.plan ? String(options.plan) : null;
|
|
31
|
+
|
|
32
|
+
if (!slug) {
|
|
33
|
+
if (options.json) return { ok: false, reason: 'missing_feature' };
|
|
34
|
+
logger.log('--feature=<slug> is required.');
|
|
35
|
+
return { ok: false };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!next) {
|
|
39
|
+
if (options.json) return { ok: false, reason: 'missing_next' };
|
|
40
|
+
logger.log('--next="<next step>" is required.');
|
|
41
|
+
return { ok: false };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Build context package based on what exists
|
|
45
|
+
const artifacts = await scanArtifacts(targetDir, slug);
|
|
46
|
+
const contextPackage = [];
|
|
47
|
+
if (artifacts.project_context.exists) contextPackage.push('project.context.md');
|
|
48
|
+
if (artifacts.spec.exists) contextPackage.push(`spec-${slug}.md`);
|
|
49
|
+
if (plan) contextPackage.push(plan);
|
|
50
|
+
else if (artifacts.implementation_plan.exists) contextPackage.push(`implementation-plan-${slug}.md`);
|
|
51
|
+
|
|
52
|
+
const today = nowDate();
|
|
53
|
+
const statePath = path.join(contextDir(targetDir), 'dev-state.md');
|
|
54
|
+
|
|
55
|
+
const existingContent = await readFileSafe(statePath);
|
|
56
|
+
const existingFm = existingContent ? parseFrontmatter(existingContent) : {};
|
|
57
|
+
|
|
58
|
+
// Build history entry
|
|
59
|
+
const historyLine = `- ${today}: phase ${phase || existingFm.active_phase || '?'} — ${next}`;
|
|
60
|
+
const existingHistory = [];
|
|
61
|
+
if (existingContent) {
|
|
62
|
+
const historyMatch = existingContent.match(/## History\n([\s\S]*?)(?=\n##|\s*$)/);
|
|
63
|
+
if (historyMatch) {
|
|
64
|
+
const lines = historyMatch[1].split('\n').filter((l) => l.trim().startsWith('-'));
|
|
65
|
+
existingHistory.push(...lines.slice(-4)); // keep last 4 + new = 5 total
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const history = [...existingHistory, historyLine];
|
|
69
|
+
|
|
70
|
+
const lines = [
|
|
71
|
+
'---',
|
|
72
|
+
`last_updated: ${today}`,
|
|
73
|
+
`active_feature: ${slug}`,
|
|
74
|
+
phase ? `active_phase: ${phase}` : (existingFm.active_phase ? `active_phase: ${existingFm.active_phase}` : null),
|
|
75
|
+
`next_step: "${next}"`,
|
|
76
|
+
specVersion ? `last_spec_version: ${specVersion}` : (existingFm.last_spec_version ? `last_spec_version: ${existingFm.last_spec_version}` : null),
|
|
77
|
+
`status: ${status}`,
|
|
78
|
+
'---',
|
|
79
|
+
'',
|
|
80
|
+
'# Dev State',
|
|
81
|
+
'',
|
|
82
|
+
`**Feature:** ${slug}`,
|
|
83
|
+
phase ? `**Phase:** ${phase}` : null,
|
|
84
|
+
`**Status:** ${status}`,
|
|
85
|
+
`**Next step:** ${next}`,
|
|
86
|
+
'',
|
|
87
|
+
'## Context package',
|
|
88
|
+
'',
|
|
89
|
+
...contextPackage.map((f, i) => `${i + 1}. ${f}`),
|
|
90
|
+
'',
|
|
91
|
+
'## History',
|
|
92
|
+
'',
|
|
93
|
+
...history,
|
|
94
|
+
''
|
|
95
|
+
].filter((l) => l !== null);
|
|
96
|
+
|
|
97
|
+
await fs.mkdir(path.dirname(statePath), { recursive: true });
|
|
98
|
+
await fs.writeFile(statePath, lines.join('\n'), 'utf8');
|
|
99
|
+
|
|
100
|
+
const result = {
|
|
101
|
+
ok: true,
|
|
102
|
+
path: path.relative(targetDir, statePath),
|
|
103
|
+
active_feature: slug,
|
|
104
|
+
active_phase: phase,
|
|
105
|
+
next_step: next,
|
|
106
|
+
last_spec_version: specVersion,
|
|
107
|
+
context_package: contextPackage
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if (options.json) return result;
|
|
111
|
+
|
|
112
|
+
logger.log('dev-state.md updated:');
|
|
113
|
+
logger.log(` active_feature: ${slug}`);
|
|
114
|
+
if (phase) logger.log(` active_phase: ${phase}`);
|
|
115
|
+
logger.log(` next_step: "${next}"`);
|
|
116
|
+
if (specVersion) logger.log(` last_spec_version: ${specVersion}`);
|
|
117
|
+
logger.log(` context_package: [${contextPackage.join(', ')}]`);
|
|
118
|
+
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
module.exports = { runStateSave };
|
package/src/commands/update.js
CHANGED
|
@@ -9,11 +9,13 @@ const { applyAgentLocale } = require('../locales');
|
|
|
9
9
|
async function runUpdate({ args, options, logger, t }) {
|
|
10
10
|
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
11
11
|
const dryRun = Boolean(options['dry-run']);
|
|
12
|
+
const all = Boolean(options.all);
|
|
12
13
|
const requestedLanguage = options.lang || options.language;
|
|
13
14
|
|
|
14
15
|
const detection = await detectFramework(targetDir);
|
|
15
16
|
const result = await updateInstallation(targetDir, {
|
|
16
17
|
dryRun,
|
|
18
|
+
all,
|
|
17
19
|
frameworkDetection: detection.framework
|
|
18
20
|
});
|
|
19
21
|
|