@jaimevalasek/aioson 1.5.1 → 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 -226
- package/docs/design-previews/aurora-command-ui-website.html +884 -0
- package/docs/design-previews/aurora-command-ui.html +682 -0
- package/docs/design-previews/bold-editorial-ui-website.html +658 -0
- package/docs/design-previews/bold-editorial-ui.html +717 -0
- package/docs/design-previews/clean-saas-ui-website.html +1202 -0
- package/docs/design-previews/clean-saas-ui.html +549 -0
- package/docs/design-previews/cognitive-core-ui-website.html +1009 -0
- package/docs/design-previews/cognitive-core-ui.html +463 -0
- package/docs/design-previews/glassmorphism-ui-website.html +572 -0
- package/docs/design-previews/glassmorphism-ui.html +886 -0
- package/docs/design-previews/index.html +699 -0
- package/docs/design-previews/interface-design-website.html +1187 -0
- package/docs/design-previews/interface-design.html +513 -0
- package/docs/design-previews/neo-brutalist-ui-website.html +621 -0
- package/docs/design-previews/neo-brutalist-ui.html +797 -0
- package/docs/design-previews/premium-command-center-ui-website.html +1217 -0
- package/docs/design-previews/premium-command-center-ui.html +552 -0
- package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
- package/docs/design-previews/warm-craft-ui-website.html +684 -0
- package/docs/design-previews/warm-craft-ui.html +739 -0
- package/docs/en/cli-reference.md +20 -9
- 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 +10 -0
- package/docs/pt/agent-sharding.md +132 -0
- package/docs/pt/agentes.md +9 -2
- package/docs/pt/busca-de-contexto.md +129 -0
- package/docs/pt/cache-de-contexto.md +156 -0
- package/docs/pt/comandos-cli.md +915 -1
- package/docs/pt/design-hybrid-forge.md +356 -0
- 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/inicio-rapido.md +54 -3
- package/docs/pt/inteligencia-adaptativa.md +324 -0
- package/docs/pt/monitor-de-contexto.md +158 -0
- package/docs/pt/recuperacao-de-sessao.md +125 -0
- package/docs/pt/sandbox.md +125 -0
- package/docs/pt/sdd-automation-scripts.md +557 -0
- package/docs/pt/site-forge.md +309 -0
- package/docs/pt/skills.md +98 -6
- 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/agent-loader.js +280 -0
- package/src/cli.js +329 -1
- package/src/commands/agent-audit.js +397 -0
- package/src/commands/agent-export-skill.js +229 -0
- package/src/commands/agent-loader.js +85 -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-cache.js +90 -0
- package/src/commands/context-compact.js +49 -0
- package/src/commands/context-health.js +175 -0
- package/src/commands/context-monitor.js +163 -0
- package/src/commands/context-search.js +66 -0
- package/src/commands/context-trim.js +177 -0
- package/src/commands/design-hybrid-options.js +385 -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/health.js +214 -0
- package/src/commands/hooks-emit.js +253 -0
- package/src/commands/hooks-install.js +347 -0
- package/src/commands/init.js +54 -13
- package/src/commands/install.js +52 -13
- package/src/commands/learning-auto-promote.js +195 -0
- package/src/commands/learning-evolve.js +364 -0
- package/src/commands/learning-export.js +103 -0
- package/src/commands/learning-rollback.js +164 -0
- package/src/commands/live.js +59 -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/recovery.js +43 -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/sandbox.js +37 -0
- package/src/commands/self-implement-loop.js +256 -0
- package/src/commands/session-guard.js +218 -0
- package/src/commands/setup-context.js +22 -2
- package/src/commands/setup.js +178 -0
- package/src/commands/sizing.js +165 -0
- package/src/commands/skill.js +144 -32
- 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/tool-registry-cmd.js +232 -0
- package/src/commands/update.js +9 -0
- package/src/commands/verify-gate.js +572 -0
- package/src/commands/workflow-execute.js +241 -0
- package/src/constants.js +18 -0
- package/src/context-cache.js +159 -0
- package/src/context-search.js +326 -0
- package/src/design-variation-catalog.js +503 -0
- package/src/i18n/messages/en.js +32 -2
- package/src/i18n/messages/es.js +30 -2
- package/src/i18n/messages/fr.js +30 -2
- package/src/i18n/messages/pt-BR.js +32 -2
- package/src/install-animation.js +260 -0
- package/src/install-profile.js +143 -0
- package/src/install-wizard.js +475 -0
- package/src/installer.js +44 -10
- 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/parser.js +7 -1
- package/src/preflight-engine.js +443 -0
- package/src/recovery-context-session.js +154 -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 +158 -4
- package/src/sandbox.js +177 -0
- 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/tool-executor.js +94 -0
- package/src/updater.js +10 -3
- package/src/worker-runner.js +186 -1
- package/template/.aioson/agents/analyst.md +119 -3
- package/template/.aioson/agents/architect.md +98 -0
- package/template/.aioson/agents/design-hybrid-forge.md +141 -0
- package/template/.aioson/agents/dev.md +335 -14
- package/template/.aioson/agents/deyvin.md +117 -2
- 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 +93 -0
- package/template/.aioson/agents/product.md +77 -4
- 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 +249 -19
- package/template/.aioson/agents/setup.md +144 -12
- package/template/.aioson/agents/sheldon.md +237 -11
- package/template/.aioson/agents/site-forge.md +1753 -0
- package/template/.aioson/agents/squad.md +162 -0
- package/template/.aioson/agents/tester.md +209 -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 +158 -13
- package/template/.aioson/constitution.md +33 -0
- package/template/.aioson/context/forensics/.gitkeep +0 -0
- package/template/.aioson/context/project-pulse.md +34 -0
- package/template/.aioson/context/seeds/seed-example.md +27 -0
- package/template/.aioson/context/user-profile.md +42 -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/setup.md +33 -1
- 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 +35 -1
- 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 +35 -1
- 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 +134 -19
- 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/aurora-command-ui/SKILL.md +243 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +482 -0
- package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +387 -0
- package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +222 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -0
- package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +213 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -0
- package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -0
- 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 +46 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/approval-gates.md +109 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/artifact-map.md +44 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/classification-map.md +37 -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/hardening-lane.md +49 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +101 -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/aioson-spec-driven/references/ui-language.md +75 -0
- package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +147 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/crossover-protocol.md +221 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/naming-registry.md +88 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +306 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +149 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +208 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/variation-library.md +125 -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 +75 -1
- package/template/CLAUDE.md +31 -0
- package/template/OPENCODE.md +4 -0
- package/template/researchs/.gitkeep +0 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* aioson agent:audit — Token and size audit for AIOSON agent files
|
|
5
|
+
*
|
|
6
|
+
* Scans .aioson/agents/*.md (and optionally locale variants) and reports:
|
|
7
|
+
* - Size in chars and estimated tokens per file
|
|
8
|
+
* - Size per section (## headings)
|
|
9
|
+
* - Files and sections over budget thresholds
|
|
10
|
+
* - Sections that are candidates to move to .aioson/docs/ (on-demand loading)
|
|
11
|
+
* - Estimated token savings per session if candidates are moved
|
|
12
|
+
*
|
|
13
|
+
* Budget thresholds (from config.md guidelines):
|
|
14
|
+
* Auto-loaded files (CLAUDE.md, AGENTS.md): 3,500 chars recommended / 4,000 hard
|
|
15
|
+
* Agent files (read manually):
|
|
16
|
+
* focused agents (analyst, qa, tester): 8,000 chars
|
|
17
|
+
* generalist agents (dev, architect): 15,000 chars
|
|
18
|
+
* orchestrator agents (orchestrator, squad): 12,000 chars
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* aioson agent:audit .
|
|
22
|
+
* aioson agent:audit . --verbose Show per-section breakdown
|
|
23
|
+
* aioson agent:audit . --locales Include locale variant files
|
|
24
|
+
* aioson agent:audit . --fix Write savings report to .aioson/docs/agent-audit.md
|
|
25
|
+
* aioson agent:audit . --json
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const fs = require('node:fs/promises');
|
|
29
|
+
const path = require('node:path');
|
|
30
|
+
|
|
31
|
+
// ─── Thresholds ───────────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
const CHARS_PER_TOKEN = 4;
|
|
34
|
+
|
|
35
|
+
// Agent type classification by slug keywords
|
|
36
|
+
const AGENT_TYPES = [
|
|
37
|
+
{ type: 'auto-loaded', slugs: ['CLAUDE', 'AGENTS'], target: 3500, hard: 4000 },
|
|
38
|
+
{ type: 'orchestrator', slugs: ['orchestrator', 'squad'], target: 12000, hard: 20000 },
|
|
39
|
+
{ type: 'generalist', slugs: ['dev', 'architect', 'deyvin', 'sheldon', 'setup', 'product', 'ux-ui', 'site-forge'], target: 15000, hard: 40000 },
|
|
40
|
+
{ type: 'focused', slugs: [], target: 8000, hard: 16000 } // default
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
// Sections considered "on-demand candidates" — rarely needed at session start
|
|
44
|
+
const ON_DEMAND_KEYWORDS = [
|
|
45
|
+
'conventions', 'folder structure', 'stack', 'laravel', 'next.js', 'node',
|
|
46
|
+
'web3', 'dapp', 'brownfield', 'debugging', 'git worktree', 'worktree',
|
|
47
|
+
'motion', 'animation', 'output contract', 'output targets', 'format',
|
|
48
|
+
'devlog', 'observabilidade', 'observability', 'exemplos', 'examples',
|
|
49
|
+
'reference', 'template', 'esquema'
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
function estimateTokens(chars) {
|
|
55
|
+
return Math.ceil(chars / CHARS_PER_TOKEN);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function formatKb(chars) {
|
|
59
|
+
return `${(chars / 1024).toFixed(1)}KB`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function formatTokens(chars) {
|
|
63
|
+
return `~${estimateTokens(chars).toLocaleString()} tok`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function classifyAgent(slug) {
|
|
67
|
+
for (const def of AGENT_TYPES) {
|
|
68
|
+
if (def.slugs.some((s) => slug.toLowerCase().includes(s.toLowerCase()))) {
|
|
69
|
+
return def;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return AGENT_TYPES[AGENT_TYPES.length - 1]; // focused (default)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isOnDemandCandidate(sectionTitle) {
|
|
76
|
+
const lower = sectionTitle.toLowerCase();
|
|
77
|
+
return ON_DEMAND_KEYWORDS.some((kw) => lower.includes(kw));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ─── Section parser ───────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
function parseSections(content) {
|
|
83
|
+
const sections = [];
|
|
84
|
+
const lines = content.split(/\r?\n/);
|
|
85
|
+
const headingRe = /^(#{1,4})\s+(.+)/;
|
|
86
|
+
|
|
87
|
+
let currentSection = null;
|
|
88
|
+
let currentLines = [];
|
|
89
|
+
|
|
90
|
+
function flush() {
|
|
91
|
+
if (currentSection !== null) {
|
|
92
|
+
const body = currentLines.join('\n');
|
|
93
|
+
sections.push({
|
|
94
|
+
title: currentSection.title,
|
|
95
|
+
level: currentSection.level,
|
|
96
|
+
chars: body.length,
|
|
97
|
+
tokens: estimateTokens(body.length),
|
|
98
|
+
onDemandCandidate: isOnDemandCandidate(currentSection.title)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
const match = line.match(headingRe);
|
|
105
|
+
if (match) {
|
|
106
|
+
flush();
|
|
107
|
+
currentSection = { level: match[1].length, title: match[2].trim() };
|
|
108
|
+
currentLines = [line];
|
|
109
|
+
} else {
|
|
110
|
+
currentLines.push(line);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
flush();
|
|
114
|
+
|
|
115
|
+
return sections;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ─── File scanner ─────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
async function scanAgentFile(filePath, relativePath) {
|
|
121
|
+
let content;
|
|
122
|
+
try {
|
|
123
|
+
content = await fs.readFile(filePath, 'utf8');
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const slug = path.basename(filePath, '.md');
|
|
129
|
+
const typeDef = classifyAgent(slug);
|
|
130
|
+
const chars = content.length;
|
|
131
|
+
const sections = parseSections(content);
|
|
132
|
+
|
|
133
|
+
const onDemandSections = sections.filter((s) => s.onDemandCandidate);
|
|
134
|
+
const onDemandChars = onDemandSections.reduce((sum, s) => sum + s.chars, 0);
|
|
135
|
+
|
|
136
|
+
const status =
|
|
137
|
+
chars > typeDef.hard
|
|
138
|
+
? 'over_hard'
|
|
139
|
+
: chars > typeDef.target
|
|
140
|
+
? 'over_target'
|
|
141
|
+
: 'ok';
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
file: relativePath,
|
|
145
|
+
slug,
|
|
146
|
+
agent_type: typeDef.type,
|
|
147
|
+
chars,
|
|
148
|
+
tokens: estimateTokens(chars),
|
|
149
|
+
target_chars: typeDef.target,
|
|
150
|
+
hard_chars: typeDef.hard,
|
|
151
|
+
status,
|
|
152
|
+
sections,
|
|
153
|
+
on_demand_candidates: onDemandSections,
|
|
154
|
+
savings_if_moved: onDemandChars,
|
|
155
|
+
savings_tokens: estimateTokens(onDemandChars)
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function scanDir(dirPath, projectDir, results) {
|
|
160
|
+
let entries;
|
|
161
|
+
try {
|
|
162
|
+
entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
163
|
+
} catch {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const entry of entries) {
|
|
168
|
+
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
|
+
}
|
|
175
|
+
|
|
176
|
+
// ─── Report writer ────────────────────────────────────────────────────────────
|
|
177
|
+
|
|
178
|
+
function buildMarkdownReport(files, projectDir) {
|
|
179
|
+
const overHard = files.filter((f) => f.status === 'over_hard');
|
|
180
|
+
const overTarget = files.filter((f) => f.status === 'over_target');
|
|
181
|
+
const totalTokens = files.reduce((s, f) => s + f.tokens, 0);
|
|
182
|
+
const totalSavings = files.reduce((s, f) => s + f.savings_tokens, 0);
|
|
183
|
+
|
|
184
|
+
const lines = [
|
|
185
|
+
'# Agent Audit Report',
|
|
186
|
+
`Generated: ${new Date().toISOString()}`,
|
|
187
|
+
'',
|
|
188
|
+
'## Summary',
|
|
189
|
+
`Total agent files scanned : ${files.length}`,
|
|
190
|
+
`Total estimated tokens : ~${totalTokens.toLocaleString()}`,
|
|
191
|
+
`Over hard limit : ${overHard.length}`,
|
|
192
|
+
`Over target : ${overTarget.length}`,
|
|
193
|
+
`Potential savings (on-demand split): ~${totalSavings.toLocaleString()} tokens/session`,
|
|
194
|
+
''
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
if (overHard.length > 0) {
|
|
198
|
+
lines.push('## Over hard limit (split recommended)');
|
|
199
|
+
for (const f of overHard) {
|
|
200
|
+
lines.push(`- **${f.file}** — ${formatKb(f.chars)} (${formatTokens(f.chars)}) — type: ${f.agent_type}, hard: ${formatKb(f.hard_chars)}`);
|
|
201
|
+
}
|
|
202
|
+
lines.push('');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (overTarget.length > 0) {
|
|
206
|
+
lines.push('## Over target (consider splitting)');
|
|
207
|
+
for (const f of overTarget) {
|
|
208
|
+
lines.push(`- ${f.file} — ${formatKb(f.chars)} (${formatTokens(f.chars)}) — target: ${formatKb(f.target_chars)}`);
|
|
209
|
+
}
|
|
210
|
+
lines.push('');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
lines.push('## On-demand candidates (sections to move to .aioson/docs/)');
|
|
214
|
+
lines.push('These sections are loaded every session but are rarely needed at start.');
|
|
215
|
+
lines.push('Moving them to `.aioson/docs/` files saves tokens without losing capability.');
|
|
216
|
+
lines.push('');
|
|
217
|
+
|
|
218
|
+
for (const f of files) {
|
|
219
|
+
if (f.on_demand_candidates.length === 0) continue;
|
|
220
|
+
lines.push(`### ${f.file}`);
|
|
221
|
+
lines.push(`Current size: ${formatKb(f.chars)} — savings if moved: ~${f.savings_tokens.toLocaleString()} tokens`);
|
|
222
|
+
for (const s of f.on_demand_candidates) {
|
|
223
|
+
lines.push(`- \`## ${s.title}\` (${formatKb(s.chars)})`);
|
|
224
|
+
}
|
|
225
|
+
lines.push('');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
lines.push('## All files');
|
|
229
|
+
lines.push('| File | Type | Size | Tokens | Target | Status |');
|
|
230
|
+
lines.push('|------|------|------|--------|--------|--------|');
|
|
231
|
+
for (const f of [...files].sort((a, b) => b.chars - a.chars)) {
|
|
232
|
+
const statusLabel = { ok: '✓', over_target: '⚠', over_hard: '✗' }[f.status];
|
|
233
|
+
lines.push(`| ${f.file} | ${f.agent_type} | ${formatKb(f.chars)} | ${formatTokens(f.chars)} | ${formatKb(f.target_chars)} | ${statusLabel} |`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return lines.join('\n');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ─── Main command ─────────────────────────────────────────────────────────────
|
|
240
|
+
|
|
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
|
+
const agentsDir = path.join(targetDir, 'template', '.aioson', 'agents');
|
|
248
|
+
const rootAgentsDir = path.join(targetDir, '.aioson', 'agents');
|
|
249
|
+
|
|
250
|
+
const files = [];
|
|
251
|
+
|
|
252
|
+
// Scan template agents (this project)
|
|
253
|
+
if (await dirExists(agentsDir)) {
|
|
254
|
+
await scanDir(agentsDir, targetDir, files);
|
|
255
|
+
}
|
|
256
|
+
// Scan project agents (when used inside a project)
|
|
257
|
+
if (await dirExists(rootAgentsDir)) {
|
|
258
|
+
await scanDir(rootAgentsDir, targetDir, files);
|
|
259
|
+
}
|
|
260
|
+
// Scan auto-loaded files
|
|
261
|
+
for (const name of ['CLAUDE.md', 'AGENTS.md']) {
|
|
262
|
+
for (const base of [path.join(targetDir, 'template'), targetDir]) {
|
|
263
|
+
const fp = path.join(base, name);
|
|
264
|
+
const rel = path.relative(targetDir, fp).split(path.sep).join('/');
|
|
265
|
+
const r = await scanAgentFile(fp, rel);
|
|
266
|
+
if (r) files.push(r);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Optionally include locales
|
|
271
|
+
if (includeLocales) {
|
|
272
|
+
const localesBase = path.join(targetDir, 'template', '.aioson', 'locales');
|
|
273
|
+
try {
|
|
274
|
+
const langs = await fs.readdir(localesBase, { withFileTypes: true });
|
|
275
|
+
for (const lang of langs) {
|
|
276
|
+
if (!lang.isDirectory()) continue;
|
|
277
|
+
await scanDir(
|
|
278
|
+
path.join(localesBase, lang.name, 'agents'),
|
|
279
|
+
targetDir,
|
|
280
|
+
files
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
} catch { /* locales dir optional */ }
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (files.length === 0) {
|
|
287
|
+
if (!options.json) logger.log('No agent files found. Run from the aioson project root or a project with .aioson/agents/.');
|
|
288
|
+
return { ok: false, reason: 'no_files' };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Sort by size descending
|
|
292
|
+
files.sort((a, b) => b.chars - a.chars);
|
|
293
|
+
|
|
294
|
+
if (options.json) return { ok: true, files };
|
|
295
|
+
|
|
296
|
+
// ── Console report ─────────────────────────────────────────────────────────
|
|
297
|
+
const overHard = files.filter((f) => f.status === 'over_hard');
|
|
298
|
+
const overTarget = files.filter((f) => f.status === 'over_target');
|
|
299
|
+
const totalTokens = files.reduce((s, f) => s + f.tokens, 0);
|
|
300
|
+
const totalSavings = files.reduce((s, f) => s + f.savings_tokens, 0);
|
|
301
|
+
|
|
302
|
+
logger.log('Agent Audit');
|
|
303
|
+
logger.log('─'.repeat(70));
|
|
304
|
+
logger.log(`Files scanned : ${files.length}`);
|
|
305
|
+
logger.log(`Total tokens : ~${totalTokens.toLocaleString()} per session`);
|
|
306
|
+
logger.log(`Over hard limit: ${overHard.length} Over target: ${overTarget.length}`);
|
|
307
|
+
logger.log(`Potential save : ~${totalSavings.toLocaleString()} tokens/session (on-demand split)`);
|
|
308
|
+
logger.log('');
|
|
309
|
+
|
|
310
|
+
// File table
|
|
311
|
+
const COL = { file: 45, type: 14, size: 9, tokens: 12, status: 8 };
|
|
312
|
+
logger.log(
|
|
313
|
+
'File'.padEnd(COL.file) +
|
|
314
|
+
'Type'.padEnd(COL.type) +
|
|
315
|
+
'Size'.padEnd(COL.size) +
|
|
316
|
+
'Tokens'.padEnd(COL.tokens) +
|
|
317
|
+
'Status'
|
|
318
|
+
);
|
|
319
|
+
logger.log('─'.repeat(70));
|
|
320
|
+
|
|
321
|
+
for (const f of files) {
|
|
322
|
+
const statusLabel = { ok: '✓ ok', over_target: '⚠ target', over_hard: '✗ hard' }[f.status];
|
|
323
|
+
logger.log(
|
|
324
|
+
f.file.slice(0, COL.file - 1).padEnd(COL.file) +
|
|
325
|
+
f.agent_type.padEnd(COL.type) +
|
|
326
|
+
formatKb(f.chars).padEnd(COL.size) +
|
|
327
|
+
formatTokens(f.chars).padEnd(COL.tokens) +
|
|
328
|
+
statusLabel
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
if (verbose && f.sections.length > 0) {
|
|
332
|
+
const topSections = [...f.sections].sort((a, b) => b.chars - a.chars).slice(0, 5);
|
|
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
|
+
}
|
|
339
|
+
|
|
340
|
+
logger.log('');
|
|
341
|
+
|
|
342
|
+
// On-demand candidates summary
|
|
343
|
+
const withCandidates = files.filter((f) => f.on_demand_candidates.length > 0);
|
|
344
|
+
if (withCandidates.length > 0) {
|
|
345
|
+
logger.log('On-demand candidates (move to .aioson/docs/ to save tokens):');
|
|
346
|
+
for (const f of withCandidates) {
|
|
347
|
+
logger.log(` ${f.file.slice(0, 42)} save ~${f.savings_tokens.toLocaleString()} tok (${f.on_demand_candidates.length} section${f.on_demand_candidates.length > 1 ? 's' : ''})`);
|
|
348
|
+
if (verbose) {
|
|
349
|
+
for (const s of f.on_demand_candidates) {
|
|
350
|
+
logger.log(` § ${s.title.slice(0, 50)} ${formatKb(s.chars)}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
logger.log('');
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (overHard.length > 0) {
|
|
358
|
+
logger.log('✗ Files over hard limit (will be truncated in auto-loaded contexts):');
|
|
359
|
+
for (const f of overHard) {
|
|
360
|
+
logger.log(` ${f.file} — ${formatKb(f.chars)} (target: ${formatKb(f.target_chars)}, hard: ${formatKb(f.hard_chars)})`);
|
|
361
|
+
}
|
|
362
|
+
logger.log('');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Write fix report
|
|
366
|
+
if (writeFix) {
|
|
367
|
+
const reportPath = path.join(targetDir, '.aioson', 'docs', 'agent-audit.md');
|
|
368
|
+
const reportDir = path.dirname(reportPath);
|
|
369
|
+
await fs.mkdir(reportDir, { recursive: true });
|
|
370
|
+
await fs.writeFile(reportPath, buildMarkdownReport(files, targetDir), 'utf8');
|
|
371
|
+
logger.log(`✓ Full report saved: .aioson/docs/agent-audit.md`);
|
|
372
|
+
logger.log(' Review the "On-demand candidates" section to decide which sections to move.');
|
|
373
|
+
} else {
|
|
374
|
+
logger.log('Tip: Run with --fix to save a full markdown report with split recommendations.');
|
|
375
|
+
logger.log(' Run with --verbose to see per-section breakdown.');
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return {
|
|
379
|
+
ok: true,
|
|
380
|
+
files: files.length,
|
|
381
|
+
over_hard: overHard.length,
|
|
382
|
+
over_target: overTarget.length,
|
|
383
|
+
total_tokens: totalTokens,
|
|
384
|
+
potential_savings_tokens: totalSavings
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async function dirExists(dirPath) {
|
|
389
|
+
try {
|
|
390
|
+
const s = await fs.stat(dirPath);
|
|
391
|
+
return s.isDirectory();
|
|
392
|
+
} catch {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
module.exports = { runAgentAudit };
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* aioson agent:export-skill — Export AIOSON agent as portable Agent Skills Standard
|
|
5
|
+
*
|
|
6
|
+
* Converts an AIOSON agent (.aioson/agents/<name>.md) into the Agent Skills Standard
|
|
7
|
+
* format (SKILL.md + resources), making it usable in Cursor, Copilot, Gemini CLI,
|
|
8
|
+
* Codex, JetBrains, and 32+ other tools.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* aioson agent:export-skill . --agent=dev
|
|
12
|
+
* aioson agent:export-skill . --agent=dev --output=.claude/skills/aioson-dev/
|
|
13
|
+
* aioson agent:export-skill . --agent=qa --json
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('node:fs/promises');
|
|
17
|
+
const path = require('node:path');
|
|
18
|
+
|
|
19
|
+
const AGENTS_DIR = path.join('.aioson', 'agents');
|
|
20
|
+
|
|
21
|
+
// ─── Frontmatter extraction ─────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Extract YAML-like frontmatter from a markdown file.
|
|
25
|
+
*/
|
|
26
|
+
function extractFrontmatter(content) {
|
|
27
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
28
|
+
if (!match) return { meta: {}, body: content };
|
|
29
|
+
|
|
30
|
+
const meta = {};
|
|
31
|
+
for (const line of match[1].split('\n')) {
|
|
32
|
+
const kv = line.match(/^(\w[\w_-]*):\s*(.+)$/);
|
|
33
|
+
if (kv) meta[kv[1]] = kv[2].trim().replace(/^["']|["']$/g, '');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return { meta, body: match[2] };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Extract template sections from agent body (```template blocks or ## Template sections).
|
|
41
|
+
*/
|
|
42
|
+
function extractTemplates(body) {
|
|
43
|
+
const templates = [];
|
|
44
|
+
const templatePattern = /```template(?:\s+(\S+))?\n([\s\S]*?)```/g;
|
|
45
|
+
let match;
|
|
46
|
+
|
|
47
|
+
while ((match = templatePattern.exec(body)) !== null) {
|
|
48
|
+
templates.push({
|
|
49
|
+
name: match[1] || `template-${templates.length + 1}`,
|
|
50
|
+
content: match[2].trim()
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return templates;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Extract tool references from agent body.
|
|
59
|
+
*/
|
|
60
|
+
function extractTools(body) {
|
|
61
|
+
const tools = new Set();
|
|
62
|
+
const toolPattern = /\b(Read|Write|Edit|Bash|Glob|Grep|Agent|WebFetch|WebSearch|NotebookEdit)\b/g;
|
|
63
|
+
let match;
|
|
64
|
+
|
|
65
|
+
while ((match = toolPattern.exec(body)) !== null) {
|
|
66
|
+
tools.add(match[1]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return [...tools];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Infer activation patterns from agent content.
|
|
74
|
+
*/
|
|
75
|
+
function inferActivation(agentName, body) {
|
|
76
|
+
const activation = [];
|
|
77
|
+
|
|
78
|
+
// Always activate for .aioson files
|
|
79
|
+
activation.push({ path: '.aioson/**' });
|
|
80
|
+
|
|
81
|
+
// Keyword-based activation from agent name/role
|
|
82
|
+
const keywords = {
|
|
83
|
+
dev: ['implement', 'code', 'build', 'feature'],
|
|
84
|
+
qa: ['test', 'quality', 'verify', 'bug'],
|
|
85
|
+
architect: ['architecture', 'structure', 'design'],
|
|
86
|
+
analyst: ['analyze', 'discover', 'map'],
|
|
87
|
+
'ux-ui': ['design', 'interface', 'component'],
|
|
88
|
+
product: ['product', 'prd', 'requirement'],
|
|
89
|
+
pm: ['sprint', 'backlog', 'story']
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const agentKeywords = keywords[agentName] || [agentName];
|
|
93
|
+
for (const kw of agentKeywords) {
|
|
94
|
+
activation.push({ keyword: kw });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return activation;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ─── SKILL.md generator ──────────────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Generate Agent Skills Standard SKILL.md from AIOSON agent.
|
|
104
|
+
*/
|
|
105
|
+
function generateSkillMd(agentName, agentContent, options = {}) {
|
|
106
|
+
const { meta, body } = extractFrontmatter(agentContent);
|
|
107
|
+
const tools = extractTools(body);
|
|
108
|
+
const activation = inferActivation(agentName, body);
|
|
109
|
+
|
|
110
|
+
// Build skills-standard frontmatter
|
|
111
|
+
const frontmatter = {
|
|
112
|
+
name: meta.name || `AIOSON ${capitalize(agentName)} Agent`,
|
|
113
|
+
description: meta.description || `${capitalize(agentName)} agent from AIOSON framework`,
|
|
114
|
+
version: options.version || '1.0.0',
|
|
115
|
+
tools: tools.length > 0 ? tools : ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep'],
|
|
116
|
+
context: 'fork',
|
|
117
|
+
activation
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const fmLines = [
|
|
121
|
+
'---',
|
|
122
|
+
`name: ${frontmatter.name}`,
|
|
123
|
+
`description: ${frontmatter.description}`,
|
|
124
|
+
`version: ${frontmatter.version}`,
|
|
125
|
+
`tools: [${frontmatter.tools.join(', ')}]`,
|
|
126
|
+
`context: ${frontmatter.context}`,
|
|
127
|
+
'activation:',
|
|
128
|
+
...frontmatter.activation.map((a) => {
|
|
129
|
+
if (a.path) return ` - path: "${a.path}"`;
|
|
130
|
+
if (a.keyword) return ` - keyword: "${a.keyword}"`;
|
|
131
|
+
return '';
|
|
132
|
+
}).filter(Boolean),
|
|
133
|
+
'---',
|
|
134
|
+
''
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
// Clean body: remove AIOSON-specific sections that don't apply portably
|
|
138
|
+
let cleanBody = body;
|
|
139
|
+
// Remove runtime boundary sections
|
|
140
|
+
cleanBody = cleanBody.replace(/## AIOSON Runtime boundary[\s\S]*?(?=\n## |$)/g, '');
|
|
141
|
+
// Remove observability sections
|
|
142
|
+
cleanBody = cleanBody.replace(/## Observability[\s\S]*?(?=\n## |$)/g, '');
|
|
143
|
+
|
|
144
|
+
return fmLines.join('\n') + cleanBody.trim() + '\n';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function capitalize(str) {
|
|
148
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Export an AIOSON agent as an Agent Skills Standard skill.
|
|
155
|
+
*
|
|
156
|
+
* @param {object} params — { args, options, logger }
|
|
157
|
+
*/
|
|
158
|
+
async function runAgentExportSkill({ args, options = {}, logger }) {
|
|
159
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
160
|
+
const agentName = String(options.agent || options.a || '').trim();
|
|
161
|
+
const outputDir = options.output
|
|
162
|
+
? path.resolve(targetDir, options.output)
|
|
163
|
+
: path.join(targetDir, '.claude', 'skills', `aioson-${agentName}`);
|
|
164
|
+
|
|
165
|
+
if (!agentName) {
|
|
166
|
+
logger.error('Error: --agent is required');
|
|
167
|
+
return { ok: false, error: 'missing_agent' };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Read agent file
|
|
171
|
+
const agentPath = path.join(targetDir, AGENTS_DIR, `${agentName}.md`);
|
|
172
|
+
let agentContent;
|
|
173
|
+
try {
|
|
174
|
+
agentContent = await fs.readFile(agentPath, 'utf8');
|
|
175
|
+
} catch {
|
|
176
|
+
logger.error(`Agent not found: ${agentPath}`);
|
|
177
|
+
return { ok: false, error: 'agent_not_found' };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Generate SKILL.md
|
|
181
|
+
const skillContent = generateSkillMd(agentName, agentContent, {
|
|
182
|
+
version: options.version || '1.0.0'
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Extract templates
|
|
186
|
+
const templates = extractTemplates(agentContent);
|
|
187
|
+
|
|
188
|
+
// Write output
|
|
189
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
190
|
+
await fs.writeFile(path.join(outputDir, 'SKILL.md'), skillContent, 'utf8');
|
|
191
|
+
|
|
192
|
+
const written = ['SKILL.md'];
|
|
193
|
+
|
|
194
|
+
// Write templates
|
|
195
|
+
if (templates.length > 0) {
|
|
196
|
+
const templatesDir = path.join(outputDir, 'templates');
|
|
197
|
+
await fs.mkdir(templatesDir, { recursive: true });
|
|
198
|
+
for (const t of templates) {
|
|
199
|
+
const ext = t.content.includes('{') ? '.json' : '.md';
|
|
200
|
+
await fs.writeFile(path.join(templatesDir, `${t.name}${ext}`), t.content, 'utf8');
|
|
201
|
+
written.push(`templates/${t.name}${ext}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Write scripts directory (empty, for custom scripts)
|
|
206
|
+
const scriptsDir = path.join(outputDir, 'scripts');
|
|
207
|
+
await fs.mkdir(scriptsDir, { recursive: true });
|
|
208
|
+
|
|
209
|
+
if (options.json) {
|
|
210
|
+
return {
|
|
211
|
+
ok: true,
|
|
212
|
+
agent: agentName,
|
|
213
|
+
outputDir: path.relative(targetDir, outputDir),
|
|
214
|
+
files: written
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
logger.log(`Exported @${agentName} as Agent Skills Standard:`);
|
|
219
|
+
logger.log(` Output: ${path.relative(targetDir, outputDir)}/`);
|
|
220
|
+
for (const f of written) {
|
|
221
|
+
logger.log(` ✓ ${f}`);
|
|
222
|
+
}
|
|
223
|
+
logger.log('');
|
|
224
|
+
logger.log('This skill is now portable to Cursor, Copilot, Gemini CLI, and 32+ tools.');
|
|
225
|
+
|
|
226
|
+
return { ok: true, agent: agentName, outputDir: path.relative(targetDir, outputDir), files: written };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
module.exports = { runAgentExportSkill, generateSkillMd };
|