@jaimevalasek/aioson 1.7.0 → 1.8.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 +60 -0
- package/README.md +153 -10
- package/docs/en/cli-reference.md +56 -1
- package/docs/en/i18n.md +18 -18
- package/docs/en/schemas/index.json +10 -0
- package/docs/en/schemas/parallel-assign.schema.json +9 -0
- package/docs/en/schemas/parallel-doctor.schema.json +36 -0
- package/docs/en/schemas/parallel-guard.schema.json +63 -0
- package/docs/en/schemas/parallel-merge.schema.json +84 -0
- package/docs/en/schemas/parallel-status.schema.json +91 -1
- package/docs/integrations/apps-publish-marketplace.md +94 -0
- package/docs/pt/README.md +9 -0
- package/docs/pt/agentes.md +324 -3
- package/docs/pt/clientes-ai.md +7 -3
- package/docs/pt/comandos-cli.md +160 -13
- package/docs/pt/compress-agents.md +304 -0
- package/docs/pt/design-docs-governance.md +59 -0
- package/docs/pt/feature-archive.md +191 -0
- package/docs/pt/genome-3.0-spec.md +115 -4
- package/docs/pt/genome-distribution.md +232 -0
- package/docs/pt/inicio-rapido.md +1 -0
- package/docs/pt/motor-hardening.md +492 -0
- package/docs/pt/runner-system.md +113 -0
- package/package.json +2 -1
- package/src/agent-manifests.js +66 -0
- package/src/agents.js +27 -7
- package/src/autonomy-policy.js +139 -0
- package/src/brain-query.js +161 -0
- package/src/cli.js +1377 -1099
- package/src/commands/agents.js +102 -7
- package/src/commands/artifact-validate.js +33 -4
- package/src/commands/auth.js +272 -0
- package/src/commands/brain-query.js +44 -0
- package/src/commands/briefing.js +344 -0
- package/src/commands/commit-prepare.js +547 -0
- package/src/commands/compress-agents.js +416 -0
- package/src/commands/context-health.js +4 -2
- package/src/commands/context-trim.js +17 -11
- package/src/commands/design-hybrid-options.js +3 -3
- package/src/commands/devlog-process.js +6 -4
- package/src/commands/dossier.js +423 -0
- package/src/commands/feature-archive.js +513 -0
- package/src/commands/feature-close.js +123 -18
- package/src/commands/gate-approve.js +198 -0
- package/src/commands/gate-check.js +24 -5
- package/src/commands/genome-doctor.js +166 -9
- package/src/commands/git-guard.js +170 -0
- package/src/commands/harness.js +121 -0
- package/src/commands/implementation-plan.js +47 -20
- package/src/commands/init.js +6 -2
- package/src/commands/install.js +6 -2
- package/src/commands/live.js +497 -56
- package/src/commands/locale-apply.js +9 -6
- package/src/commands/locale-diff.js +11 -112
- package/src/commands/mcp-doctor.js +2 -1
- package/src/commands/mcp-init.js +4 -10
- package/src/commands/memory.js +234 -0
- package/src/commands/parallel-assign.js +107 -27
- package/src/commands/parallel-doctor.js +416 -3
- package/src/commands/parallel-guard.js +241 -0
- package/src/commands/parallel-init.js +66 -4
- package/src/commands/parallel-merge.js +299 -0
- package/src/commands/parallel-status.js +147 -3
- package/src/commands/preflight.js +63 -4
- package/src/commands/qa-init.js +10 -5
- package/src/commands/revision.js +235 -0
- package/src/commands/scaffold-complete.js +188 -0
- package/src/commands/security-audit.js +275 -0
- package/src/commands/security-scan.js +376 -0
- package/src/commands/self-implement-loop.js +46 -2
- package/src/commands/setup-context.js +11 -10
- package/src/commands/squad-agent-create.js +51 -9
- package/src/commands/squad-investigate.js +53 -0
- package/src/commands/squad-plan.js +33 -1
- package/src/commands/squad-scaffold.js +4 -3
- package/src/commands/squad-score.js +71 -14
- package/src/commands/squad-status.js +22 -1
- package/src/commands/squad-validate.js +93 -2
- package/src/commands/store-genome.js +304 -0
- package/src/commands/store-skill.js +247 -0
- package/src/commands/store-squad.js +431 -0
- package/src/commands/store-system.js +392 -0
- package/src/commands/tool-capabilities.js +63 -0
- package/src/commands/update.js +3 -3
- package/src/commands/verify-gate.js +40 -0
- package/src/commands/workflow-execute.js +644 -155
- package/src/commands/workflow-harden.js +231 -0
- package/src/commands/workflow-heal.js +136 -0
- package/src/commands/workflow-next.js +460 -22
- package/src/commands/workflow-status.js +328 -138
- package/src/commands/workspace.js +144 -0
- package/src/constants.js +55 -75
- package/src/context-memory.js +133 -4
- package/src/context-writer.js +2 -1
- package/src/context.js +32 -2
- package/src/doctor.js +46 -6
- package/src/dossier/codemap-store.js +267 -0
- package/src/dossier/dossier-bootstrap.js +222 -0
- package/src/dossier/dossier-compact.js +159 -0
- package/src/dossier/lock.js +128 -0
- package/src/dossier/revision-store.js +313 -0
- package/src/dossier/schema.js +155 -0
- package/src/dossier/store.js +400 -0
- package/src/execution-gateway.js +3 -0
- package/src/friction-scanner.js +202 -0
- package/src/genome-schema.js +24 -1
- package/src/genomes.js +33 -0
- package/src/handoff-contract.js +363 -0
- package/src/handoff-validator.js +45 -0
- package/src/harness/circuit-breaker.js +135 -0
- package/src/i18n/messages/en.js +317 -22
- package/src/i18n/messages/es.js +259 -18
- package/src/i18n/messages/fr.js +260 -18
- package/src/i18n/messages/pt-BR.js +313 -22
- package/src/install-profile.js +0 -16
- package/src/installer.js +70 -6
- package/src/lib/git-commit-guard.js +691 -0
- package/src/lib/security/artifact-reader.js +167 -0
- package/src/lib/security/exit-codes.js +51 -0
- package/src/lib/security/findings-writer.js +176 -0
- package/src/lib/security/runtime-events.js +77 -0
- package/src/lib/security/secrets-regex.js +115 -0
- package/src/lib/store/security-scan.js +173 -0
- package/src/lib/terminal-checkbox.js +130 -0
- package/src/lib/tmux-launcher.js +163 -0
- package/src/lib/tool-capabilities.js +102 -0
- package/src/locales.js +12 -8
- package/src/parallel-workspace.js +756 -0
- package/src/parser.js +8 -1
- package/src/path-guard.js +47 -0
- package/src/preflight-engine.js +237 -26
- package/src/self-healing.js +142 -0
- package/src/session-handoff.js +111 -1
- package/src/squad/squad-scaffold.js +183 -19
- package/src/test-briefing.js +226 -0
- package/src/updater.js +1 -1
- package/src/utils.js +3 -0
- package/src/workflow-gates.js +185 -0
- package/template/.aioson/agents/analyst.md +76 -130
- package/template/.aioson/agents/architect.md +53 -86
- package/template/.aioson/agents/committer.md +161 -0
- package/template/.aioson/agents/copywriter.md +463 -0
- package/template/.aioson/agents/cypher.md +252 -0
- package/template/.aioson/agents/dev.md +112 -600
- package/template/.aioson/agents/deyvin.md +33 -235
- package/template/.aioson/agents/discover.md +235 -0
- package/template/.aioson/agents/discovery-design-doc.md +17 -252
- package/template/.aioson/agents/genome.md +76 -26
- package/template/.aioson/agents/manifests/analyst.manifest.json +26 -0
- package/template/.aioson/agents/manifests/architect.manifest.json +23 -0
- package/template/.aioson/agents/manifests/committer.manifest.json +23 -0
- package/template/.aioson/agents/manifests/dev.manifest.json +37 -0
- package/template/.aioson/agents/manifests/orchestrator.manifest.json +30 -0
- package/template/.aioson/agents/manifests/pentester.manifest.json +39 -0
- package/template/.aioson/agents/manifests/pm.manifest.json +26 -0
- package/template/.aioson/agents/manifests/product.manifest.json +23 -0
- package/template/.aioson/agents/manifests/qa.manifest.json +25 -0
- package/template/.aioson/agents/manifests/setup.manifest.json +20 -0
- package/template/.aioson/agents/manifests/ux-ui.manifest.json +24 -0
- package/template/.aioson/agents/neo.md +10 -8
- package/template/.aioson/agents/orache.md +2 -6
- package/template/.aioson/agents/orchestrator.md +81 -182
- package/template/.aioson/agents/pentester.md +235 -0
- package/template/.aioson/agents/pm.md +40 -104
- package/template/.aioson/agents/product.md +99 -344
- package/template/.aioson/agents/profiler-enricher.md +57 -6
- package/template/.aioson/agents/profiler-forge.md +17 -7
- package/template/.aioson/agents/profiler-researcher.md +29 -6
- package/template/.aioson/agents/qa.md +165 -410
- package/template/.aioson/agents/setup.md +52 -262
- package/template/.aioson/agents/sheldon.md +122 -754
- package/template/.aioson/agents/site-forge.md +111 -1583
- package/template/.aioson/agents/squad.md +139 -1820
- package/template/.aioson/agents/tester.md +10 -0
- package/template/.aioson/agents/ux-ui.md +103 -645
- package/template/.aioson/agents/validator.md +69 -0
- package/template/.aioson/brains/scripts/query.js +5 -1
- package/template/.aioson/config/autonomy-protocol.json +43 -0
- package/template/.aioson/config.md +43 -15
- package/template/.aioson/constitution.md +36 -33
- package/template/.aioson/context/design-doc.md +136 -0
- package/template/.aioson/context/project-map.md +57 -0
- package/template/.aioson/design-docs/code-reuse.md +48 -0
- package/template/.aioson/design-docs/componentization.md +47 -0
- package/template/.aioson/design-docs/file-size.md +52 -0
- package/template/.aioson/design-docs/folder-structure.md +51 -0
- package/template/.aioson/design-docs/naming.md +54 -0
- package/template/.aioson/docs/LAYERS.md +12 -2
- package/template/.aioson/docs/dev/execution-discipline.md +106 -0
- package/template/.aioson/docs/dev/stack-conventions.md +83 -0
- package/template/.aioson/docs/deyvin/continuity-recovery.md +57 -0
- package/template/.aioson/docs/deyvin/debugging-escalation.md +30 -0
- package/template/.aioson/docs/deyvin/pair-execution.md +44 -0
- package/template/.aioson/docs/deyvin/runtime-handoffs.md +36 -0
- package/template/.aioson/docs/product/conversation-playbook.md +116 -0
- package/template/.aioson/docs/product/prd-contract.md +107 -0
- package/template/.aioson/docs/product/quality-lens.md +57 -0
- package/template/.aioson/docs/product/research-loop.md +65 -0
- package/template/.aioson/docs/sheldon/enrichment-paths.md +134 -0
- package/template/.aioson/docs/sheldon/quality-lens.md +57 -0
- package/template/.aioson/docs/sheldon/research-loop.md +56 -0
- package/template/.aioson/docs/sheldon/web-intelligence.md +75 -0
- package/template/.aioson/docs/site-forge-build.md +195 -0
- package/template/.aioson/docs/site-forge-extraction.md +135 -0
- package/template/.aioson/docs/site-forge-qa.md +155 -0
- package/template/.aioson/docs/site-forge-recon.md +434 -0
- package/template/.aioson/docs/site-forge-transform.md +249 -0
- package/template/.aioson/docs/squad/content-output.md +91 -0
- package/template/.aioson/docs/squad/creation-flow.md +135 -0
- package/template/.aioson/docs/squad/domain-classification.md +117 -0
- package/template/.aioson/docs/squad/genome-bindings.md +47 -0
- package/template/.aioson/docs/squad/package-contract.md +234 -0
- package/template/.aioson/docs/squad/quality-lens.md +56 -0
- package/template/.aioson/docs/squad/research-loop.md +59 -0
- package/template/.aioson/docs/squad/session-operations.md +117 -0
- package/template/.aioson/docs/squad/workflow-quality.md +165 -0
- package/template/.aioson/docs/ux-ui/accessibility-audit.md +55 -0
- package/template/.aioson/docs/ux-ui/audit-mode.md +86 -0
- package/template/.aioson/docs/ux-ui/component-map.md +35 -0
- package/template/.aioson/docs/ux-ui/design-execution.md +111 -0
- package/template/.aioson/docs/ux-ui/design-gate.md +27 -0
- package/template/.aioson/docs/ux-ui/research-mode.md +39 -0
- package/template/.aioson/docs/ux-ui/site-delivery.md +156 -0
- package/template/.aioson/docs/ux-ui/token-contract.md +57 -0
- package/template/.aioson/genomes/copywriting.md +204 -0
- package/template/.aioson/genomes/copywriting.meta.json +48 -0
- package/template/.aioson/git-guard.json +11 -0
- package/template/.aioson/mcp/servers.md +0 -1
- package/template/.aioson/rules/agent-language-policy.md +93 -0
- package/template/.aioson/rules/aioson-context-boundary.md +63 -0
- package/template/.aioson/rules/canonical-path-contract.md +47 -0
- package/template/.aioson/rules/data-format-convention.md +24 -86
- package/template/.aioson/rules/disk-first-artifacts.md +44 -0
- package/template/.aioson/rules/output-brevity.md +44 -0
- package/template/.aioson/rules/prd-section-ownership.md +49 -0
- package/template/.aioson/rules/security-baseline.md +139 -0
- package/template/.aioson/rules/spec-level-ownership.md +61 -0
- package/template/.aioson/rules/squad-driver-pattern.md +81 -0
- package/template/.aioson/schemas/squad-blueprint.schema.json +24 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +44 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +2 -0
- package/template/.aioson/skills/marketing/references/anti-patterns.md +254 -0
- package/template/.aioson/skills/marketing/references/fascinations.md +192 -0
- package/template/.aioson/skills/marketing/references/five-acts.md +248 -0
- package/template/.aioson/skills/marketing/references/market-intelligence.md +198 -0
- package/template/.aioson/skills/marketing/references/offer-structure.md +203 -0
- package/template/.aioson/skills/marketing/references/one-belief.md +149 -0
- package/template/.aioson/skills/marketing/references/patterns.md +218 -0
- package/template/.aioson/skills/marketing/references/pms-research.md +193 -0
- package/template/.aioson/skills/marketing/vsl-craft.md +385 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/pm.md +30 -0
- package/template/.aioson/skills/process/secure-tdd/SKILL.md +97 -0
- package/template/.aioson/skills/process/secure-tdd/references/nextjs.md +81 -0
- package/template/.aioson/skills/process/secure-tdd/references/node-express.md +91 -0
- package/template/.aioson/skills/process/secure-tdd/references/planned-stacks.md +33 -0
- package/template/.aioson/skills/static/harness-validate/SKILL.md +46 -0
- package/template/.aioson/skills/static/landing-page-deploy.md +192 -0
- package/template/.aioson/skills/static/landing-page-forge.md +730 -0
- package/template/.aioson/skills/static/ui-ux-modern.md +1 -0
- package/template/.aioson/skills/static/web-research-cache.md +3 -0
- package/template/.aioson/tasks/squad-create.md +56 -7
- package/template/.aioson/tasks/squad-design.md +80 -2
- package/template/.aioson/tasks/squad-investigate.md +14 -1
- package/template/.aioson/templates/squads/digital-marketing-agency/template.json +96 -0
- package/template/.claude/commands/aioson/agent/committer.md +5 -0
- package/template/.claude/commands/aioson/agent/copywriter.md +5 -0
- package/template/.claude/commands/aioson/agent/cypher.md +5 -0
- package/template/.claude/commands/aioson/agent/pair.md +5 -0
- package/template/.claude/commands/aioson/agent/validator.md +5 -0
- package/template/.gemini/commands/aios-analyst.toml +6 -3
- package/template/.gemini/commands/aios-architect.toml +7 -6
- package/template/.gemini/commands/aios-committer.toml +7 -0
- package/template/.gemini/commands/aios-copywriter.toml +7 -0
- package/template/.gemini/commands/aios-cypher.toml +7 -0
- package/template/.gemini/commands/aios-dev.toml +8 -7
- package/template/.gemini/commands/aios-deyvin.toml +6 -5
- package/template/.gemini/commands/aios-discovery-design-doc.toml +6 -3
- package/template/.gemini/commands/aios-genome.toml +7 -0
- package/template/.gemini/commands/aios-neo.toml +5 -3
- package/template/.gemini/commands/aios-orache.toml +7 -0
- package/template/.gemini/commands/aios-orchestrator.toml +8 -7
- package/template/.gemini/commands/aios-pair.toml +6 -5
- package/template/.gemini/commands/aios-pm.toml +8 -7
- package/template/.gemini/commands/aios-product.toml +5 -3
- package/template/.gemini/commands/aios-qa.toml +6 -5
- package/template/.gemini/commands/aios-setup.toml +5 -2
- package/template/.gemini/commands/aios-sheldon.toml +7 -0
- package/template/.gemini/commands/aios-site-forge.toml +7 -0
- package/template/.gemini/commands/aios-squad.toml +7 -0
- package/template/.gemini/commands/aios-tester.toml +6 -5
- package/template/.gemini/commands/aios-ux-ui.toml +8 -7
- package/template/.gemini/commands/aios-validator.toml +7 -0
- package/template/AGENTS.md +12 -1
- package/template/CLAUDE.md +6 -1
- package/template/.aioson/locales/en/agents/analyst.md +0 -244
- package/template/.aioson/locales/en/agents/architect.md +0 -245
- package/template/.aioson/locales/en/agents/dev.md +0 -397
- package/template/.aioson/locales/en/agents/deyvin.md +0 -137
- package/template/.aioson/locales/en/agents/discovery-design-doc.md +0 -27
- package/template/.aioson/locales/en/agents/genome.md +0 -212
- package/template/.aioson/locales/en/agents/neo.md +0 -8
- package/template/.aioson/locales/en/agents/orache.md +0 -6
- package/template/.aioson/locales/en/agents/orchestrator.md +0 -189
- package/template/.aioson/locales/en/agents/pair.md +0 -5
- package/template/.aioson/locales/en/agents/pm.md +0 -84
- package/template/.aioson/locales/en/agents/product.md +0 -378
- package/template/.aioson/locales/en/agents/profiler-enricher.md +0 -5
- package/template/.aioson/locales/en/agents/profiler-forge.md +0 -5
- package/template/.aioson/locales/en/agents/profiler-researcher.md +0 -5
- package/template/.aioson/locales/en/agents/qa.md +0 -270
- package/template/.aioson/locales/en/agents/setup.md +0 -421
- package/template/.aioson/locales/en/agents/sheldon.md +0 -455
- package/template/.aioson/locales/en/agents/squad.md +0 -449
- package/template/.aioson/locales/en/agents/tester.md +0 -6
- package/template/.aioson/locales/en/agents/ux-ui.md +0 -668
- package/template/.aioson/locales/es/agents/analyst.md +0 -225
- package/template/.aioson/locales/es/agents/architect.md +0 -245
- package/template/.aioson/locales/es/agents/dev.md +0 -370
- package/template/.aioson/locales/es/agents/deyvin.md +0 -99
- package/template/.aioson/locales/es/agents/discovery-design-doc.md +0 -21
- package/template/.aioson/locales/es/agents/genome.md +0 -104
- package/template/.aioson/locales/es/agents/neo.md +0 -50
- package/template/.aioson/locales/es/agents/orache.md +0 -105
- package/template/.aioson/locales/es/agents/orchestrator.md +0 -194
- package/template/.aioson/locales/es/agents/pair.md +0 -7
- package/template/.aioson/locales/es/agents/pm.md +0 -90
- package/template/.aioson/locales/es/agents/product.md +0 -372
- package/template/.aioson/locales/es/agents/profiler-enricher.md +0 -7
- package/template/.aioson/locales/es/agents/profiler-forge.md +0 -7
- package/template/.aioson/locales/es/agents/profiler-researcher.md +0 -7
- package/template/.aioson/locales/es/agents/qa.md +0 -198
- package/template/.aioson/locales/es/agents/setup.md +0 -405
- package/template/.aioson/locales/es/agents/sheldon.md +0 -309
- package/template/.aioson/locales/es/agents/squad.md +0 -532
- package/template/.aioson/locales/es/agents/tester.md +0 -9
- package/template/.aioson/locales/es/agents/ux-ui.md +0 -212
- package/template/.aioson/locales/fr/agents/analyst.md +0 -225
- package/template/.aioson/locales/fr/agents/architect.md +0 -245
- package/template/.aioson/locales/fr/agents/dev.md +0 -370
- package/template/.aioson/locales/fr/agents/deyvin.md +0 -99
- package/template/.aioson/locales/fr/agents/discovery-design-doc.md +0 -21
- package/template/.aioson/locales/fr/agents/genome.md +0 -104
- package/template/.aioson/locales/fr/agents/neo.md +0 -50
- package/template/.aioson/locales/fr/agents/orache.md +0 -106
- package/template/.aioson/locales/fr/agents/orchestrator.md +0 -194
- package/template/.aioson/locales/fr/agents/pair.md +0 -7
- package/template/.aioson/locales/fr/agents/pm.md +0 -90
- package/template/.aioson/locales/fr/agents/product.md +0 -372
- package/template/.aioson/locales/fr/agents/profiler-enricher.md +0 -7
- package/template/.aioson/locales/fr/agents/profiler-forge.md +0 -7
- package/template/.aioson/locales/fr/agents/profiler-researcher.md +0 -7
- package/template/.aioson/locales/fr/agents/qa.md +0 -198
- package/template/.aioson/locales/fr/agents/setup.md +0 -405
- package/template/.aioson/locales/fr/agents/sheldon.md +0 -309
- package/template/.aioson/locales/fr/agents/squad.md +0 -532
- package/template/.aioson/locales/fr/agents/tester.md +0 -9
- package/template/.aioson/locales/fr/agents/ux-ui.md +0 -212
- package/template/.aioson/locales/pt-BR/agents/analyst.md +0 -319
- package/template/.aioson/locales/pt-BR/agents/architect.md +0 -284
- package/template/.aioson/locales/pt-BR/agents/dev.md +0 -483
- package/template/.aioson/locales/pt-BR/agents/deyvin.md +0 -184
- package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +0 -198
- package/template/.aioson/locales/pt-BR/agents/genome.md +0 -297
- package/template/.aioson/locales/pt-BR/agents/neo.md +0 -208
- package/template/.aioson/locales/pt-BR/agents/orache.md +0 -137
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +0 -324
- package/template/.aioson/locales/pt-BR/agents/pair.md +0 -5
- package/template/.aioson/locales/pt-BR/agents/pm.md +0 -182
- package/template/.aioson/locales/pt-BR/agents/product.md +0 -466
- package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +0 -5
- package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +0 -5
- package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +0 -5
- package/template/.aioson/locales/pt-BR/agents/qa.md +0 -300
- package/template/.aioson/locales/pt-BR/agents/setup.md +0 -533
- package/template/.aioson/locales/pt-BR/agents/sheldon.md +0 -323
- package/template/.aioson/locales/pt-BR/agents/squad.md +0 -1330
- package/template/.aioson/locales/pt-BR/agents/tester.md +0 -449
- package/template/.aioson/locales/pt-BR/agents/ux-ui.md +0 -669
- package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { exists, ensureDir } = require('../utils');
|
|
6
|
+
const { readConfig } = require('./config');
|
|
7
|
+
const { readWorkspace, findProjectRoot } = require('./workspace');
|
|
8
|
+
|
|
9
|
+
const DEFAULT_BASE_URL = 'https://aioson.com';
|
|
10
|
+
const SYSTEM_PACKAGES_DIR = '.aioson/system-packages';
|
|
11
|
+
const BACKUPS_DIR = '.aioson/.backups';
|
|
12
|
+
|
|
13
|
+
// Extensions allowed in a system package (Vite React source tree)
|
|
14
|
+
const SYSTEM_ALLOWED_EXTS = new Set([
|
|
15
|
+
'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
|
|
16
|
+
'.json', '.jsonc',
|
|
17
|
+
'.css', '.scss', '.sass', '.less',
|
|
18
|
+
'.html',
|
|
19
|
+
'.svg', '.ico',
|
|
20
|
+
'.md', '.txt',
|
|
21
|
+
'.sql',
|
|
22
|
+
'.env', '.env.example', '.env.template',
|
|
23
|
+
'.yaml', '.yml',
|
|
24
|
+
'.toml',
|
|
25
|
+
'.gitignore',
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
// Dirs/files to skip when collecting sources
|
|
29
|
+
const SKIP_DIRS = new Set([
|
|
30
|
+
'node_modules', '.git', 'dist', 'build', '.turbo', '.next',
|
|
31
|
+
'.cache', 'coverage', '.nyc_output', 'out',
|
|
32
|
+
// AIOSON tooling — não faz parte do código-fonte do sistema
|
|
33
|
+
'.aioson', '.claude', '.gemini', '.codex', 'researchs',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const SKIP_FILES = new Set([
|
|
37
|
+
'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml',
|
|
38
|
+
'bun.lockb',
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const MAX_FILE_BYTES = 512 * 1024; // 512 KB per file
|
|
42
|
+
const MAX_PACKAGE_BYTES = 20 * 1024 * 1024; // 20 MB total
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Parseia lista de emails autorizados a partir de:
|
|
46
|
+
* 1. Flag CLI --invite="email1,email2,email3" (string com separadores , ; espaço quebra)
|
|
47
|
+
* 2. Fallback: campo `authorized_emails` no system.json (array ou string)
|
|
48
|
+
* Devolve array dedup, lowercase, trimmed, validado (contém @).
|
|
49
|
+
*/
|
|
50
|
+
function parseInviteEmails(cliInvite, manifestEmails) {
|
|
51
|
+
const raw = cliInvite ?? manifestEmails;
|
|
52
|
+
if (!raw) return [];
|
|
53
|
+
let parts;
|
|
54
|
+
if (Array.isArray(raw)) {
|
|
55
|
+
parts = raw.map(String);
|
|
56
|
+
} else {
|
|
57
|
+
parts = String(raw).split(/[,;\s\n]+/);
|
|
58
|
+
}
|
|
59
|
+
return Array.from(new Set(
|
|
60
|
+
parts.map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0 && s.includes('@'))
|
|
61
|
+
));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function resolveBaseUrl(config) {
|
|
65
|
+
return String(config.aiosonBaseUrl || DEFAULT_BASE_URL).replace(/\/+$/, '');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function requireToken(config, t) {
|
|
69
|
+
const token = config.aiosonToken;
|
|
70
|
+
if (!token) throw new Error(t('store.error_not_authenticated'));
|
|
71
|
+
return token;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function storePost(url, payload, token) {
|
|
75
|
+
const response = await fetch(url, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
headers: {
|
|
78
|
+
authorization: `Bearer ${token}`,
|
|
79
|
+
'content-type': 'application/json',
|
|
80
|
+
accept: 'application/json',
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify(payload),
|
|
83
|
+
signal: AbortSignal.timeout(120000),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const text = await response.text();
|
|
87
|
+
let parsed = null;
|
|
88
|
+
try { parsed = JSON.parse(text); } catch { /* */ }
|
|
89
|
+
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
|
|
92
|
+
throw new Error(`HTTP ${response.status}: ${detail}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return parsed;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function storeGet(url, token) {
|
|
99
|
+
const response = await fetch(url, {
|
|
100
|
+
headers: { authorization: `Bearer ${token}`, accept: 'application/json' },
|
|
101
|
+
signal: AbortSignal.timeout(15000),
|
|
102
|
+
});
|
|
103
|
+
const text = await response.text();
|
|
104
|
+
let parsed = null;
|
|
105
|
+
try { parsed = JSON.parse(text); } catch { /* */ }
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
|
|
108
|
+
throw new Error(`HTTP ${response.status}: ${detail}`);
|
|
109
|
+
}
|
|
110
|
+
return parsed;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Collect all eligible source files under `dir`.
|
|
115
|
+
* Returns { relativePath: content } — only text files with allowed extensions.
|
|
116
|
+
*/
|
|
117
|
+
async function collectSystemFiles(dir) {
|
|
118
|
+
const files = {};
|
|
119
|
+
let totalBytes = 0;
|
|
120
|
+
const errors = [];
|
|
121
|
+
|
|
122
|
+
async function walk(current, rel) {
|
|
123
|
+
const entries = await fs.readdir(current, { withFileTypes: true });
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
126
|
+
if (SKIP_FILES.has(entry.name)) continue;
|
|
127
|
+
|
|
128
|
+
const fullPath = path.join(current, entry.name);
|
|
129
|
+
const relPath = rel ? `${rel}/${entry.name}` : entry.name;
|
|
130
|
+
|
|
131
|
+
if (entry.isDirectory()) {
|
|
132
|
+
await walk(fullPath, relPath);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const ext = entry.name.includes('.')
|
|
137
|
+
? `.${entry.name.split('.').pop().toLowerCase()}`
|
|
138
|
+
: '';
|
|
139
|
+
|
|
140
|
+
// Allow dotfiles with no extension (like .gitignore) that match skip list check
|
|
141
|
+
if (!SYSTEM_ALLOWED_EXTS.has(ext) && ext !== '') continue;
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const stat = await fs.stat(fullPath);
|
|
145
|
+
if (stat.size > MAX_FILE_BYTES) {
|
|
146
|
+
errors.push(`File too large (skipped): "${relPath}" (${(stat.size / 1024).toFixed(0)} KB)`);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
totalBytes += stat.size;
|
|
150
|
+
if (totalBytes > MAX_PACKAGE_BYTES) {
|
|
151
|
+
errors.push(`Package exceeds ${MAX_PACKAGE_BYTES / 1024 / 1024} MB limit — stop collecting.`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const content = await fs.readFile(fullPath, 'utf8');
|
|
155
|
+
files[relPath] = content;
|
|
156
|
+
} catch {
|
|
157
|
+
// binary or unreadable — skip silently
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
await walk(dir, '');
|
|
163
|
+
return { files, totalBytes, errors };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Parse and validate system.json.
|
|
168
|
+
* Returns the parsed manifest or throws.
|
|
169
|
+
*/
|
|
170
|
+
async function readSystemJson(dir, t) {
|
|
171
|
+
const manifestPath = path.join(dir, 'system.json');
|
|
172
|
+
if (!(await exists(manifestPath))) {
|
|
173
|
+
throw new Error(t('system.error_no_manifest', { path: manifestPath }));
|
|
174
|
+
}
|
|
175
|
+
let manifest;
|
|
176
|
+
try {
|
|
177
|
+
manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
178
|
+
} catch {
|
|
179
|
+
throw new Error(t('system.error_invalid_manifest'));
|
|
180
|
+
}
|
|
181
|
+
if (!manifest.slug) throw new Error(t('system.error_manifest_missing_slug'));
|
|
182
|
+
if (!manifest.version) throw new Error(t('system.error_manifest_missing_version'));
|
|
183
|
+
if (!manifest.name) throw new Error(t('system.error_manifest_missing_name'));
|
|
184
|
+
return manifest;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ── system:package ──────────────────────────────────────────────────────────
|
|
188
|
+
|
|
189
|
+
async function runSystemPackage({ args, options, logger, t }) {
|
|
190
|
+
const dir = path.resolve(process.cwd(), args[0] || '.');
|
|
191
|
+
|
|
192
|
+
logger.log(t('system.package_reading_manifest'));
|
|
193
|
+
const manifest = await readSystemJson(dir, t);
|
|
194
|
+
logger.log(t('system.package_manifest_ok', { slug: manifest.slug, version: manifest.version, name: manifest.name }));
|
|
195
|
+
|
|
196
|
+
logger.log(t('system.package_collecting_files'));
|
|
197
|
+
const { files, totalBytes, errors } = await collectSystemFiles(dir);
|
|
198
|
+
|
|
199
|
+
if (errors.length > 0) {
|
|
200
|
+
for (const e of errors) logger.log(` [WARN] ${e}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const fileCount = Object.keys(files).length;
|
|
204
|
+
logger.log(t('system.package_files_found', { count: fileCount, kb: (totalBytes / 1024).toFixed(1) }));
|
|
205
|
+
|
|
206
|
+
if (!files['system.json']) {
|
|
207
|
+
throw new Error(t('system.error_no_manifest', { path: path.join(dir, 'system.json') }));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (options['dry-run']) {
|
|
211
|
+
logger.log(t('system.package_dry_run', { slug: manifest.slug, version: manifest.version }));
|
|
212
|
+
for (const f of Object.keys(files).sort()) logger.log(` ${f}`);
|
|
213
|
+
return { ok: true, dryRun: true, manifest, fileCount, totalBytes };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Save package descriptor locally
|
|
217
|
+
const projectDir = await findProjectRoot(dir);
|
|
218
|
+
const pkgDir = path.join(projectDir, SYSTEM_PACKAGES_DIR, manifest.slug);
|
|
219
|
+
await ensureDir(pkgDir);
|
|
220
|
+
|
|
221
|
+
const pkgFile = path.join(pkgDir, `${manifest.slug}-${manifest.version}.json`);
|
|
222
|
+
await fs.writeFile(pkgFile, JSON.stringify({ manifest, files }, null, 2), 'utf8');
|
|
223
|
+
|
|
224
|
+
logger.log(t('system.package_saved', { path: pkgFile }));
|
|
225
|
+
return { ok: true, manifest, fileCount, totalBytes, path: pkgFile };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── system:publish ──────────────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
async function runSystemPublish({ args, options, logger, t }) {
|
|
231
|
+
const config = await readConfig();
|
|
232
|
+
const token = requireToken(config, t);
|
|
233
|
+
const dir = path.resolve(process.cwd(), args[0] || '.');
|
|
234
|
+
|
|
235
|
+
logger.log(t('system.publish_reading_manifest'));
|
|
236
|
+
const manifest = await readSystemJson(dir, t);
|
|
237
|
+
logger.log(t('system.package_manifest_ok', { slug: manifest.slug, version: manifest.version, name: manifest.name }));
|
|
238
|
+
|
|
239
|
+
logger.log(t('system.package_collecting_files'));
|
|
240
|
+
const { files, totalBytes, errors } = await collectSystemFiles(dir);
|
|
241
|
+
|
|
242
|
+
if (errors.length > 0) {
|
|
243
|
+
for (const e of errors) logger.log(` [WARN] ${e}`);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const fileCount = Object.keys(files).length;
|
|
247
|
+
logger.log(t('system.package_files_found', { count: fileCount, kb: (totalBytes / 1024).toFixed(1) }));
|
|
248
|
+
|
|
249
|
+
// Basic integrity checks
|
|
250
|
+
if (!files['system.json']) {
|
|
251
|
+
throw new Error(t('system.error_no_manifest', { path: path.join(dir, 'system.json') }));
|
|
252
|
+
}
|
|
253
|
+
if (!files['package.json']) {
|
|
254
|
+
throw new Error(t('system.error_missing_package_json'));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const visibility = options.private ? 'private' : 'public';
|
|
258
|
+
const paid = Boolean(options.paid);
|
|
259
|
+
const ws = await readWorkspace(dir);
|
|
260
|
+
|
|
261
|
+
// Lista de emails autorizados a instalar quando visibility=private.
|
|
262
|
+
// Aceita via --invite="email1,email2" OU campo `authorized_emails` no
|
|
263
|
+
// manifest (system.json). Sem efeito quando visibility !== private.
|
|
264
|
+
const authorizedEmails = parseInviteEmails(options.invite, manifest.authorized_emails);
|
|
265
|
+
|
|
266
|
+
if (options['dry-run']) {
|
|
267
|
+
logger.log(t('system.publish_dry_run', { slug: manifest.slug, version: manifest.version, visibility }));
|
|
268
|
+
return { ok: true, dryRun: true, manifest, fileCount, totalBytes, visibility, authorizedEmails };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
logger.log(t('system.publish_sending'));
|
|
272
|
+
const baseUrl = resolveBaseUrl(config);
|
|
273
|
+
const response = await storePost(`${baseUrl}/api/store/systems/publish`, {
|
|
274
|
+
kind: 'aioson.store.system',
|
|
275
|
+
slug: manifest.slug,
|
|
276
|
+
version: manifest.version,
|
|
277
|
+
files,
|
|
278
|
+
manifest,
|
|
279
|
+
visibility,
|
|
280
|
+
paid,
|
|
281
|
+
authorizedEmails,
|
|
282
|
+
workspaceSlug: ws?.slug || null,
|
|
283
|
+
}, token);
|
|
284
|
+
|
|
285
|
+
logger.log(t('system.publish_done', { slug: manifest.slug, url: `${baseUrl}/store/systems/${manifest.slug}` }));
|
|
286
|
+
logger.log(t('system.publish_summary', { files: fileCount, kb: (totalBytes / 1024).toFixed(1) }));
|
|
287
|
+
return { ok: true, manifest, fileCount, totalBytes, visibility, paid, response };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ── system:list ─────────────────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
async function runSystemList({ args, options, logger, t }) {
|
|
293
|
+
if (options.remote) {
|
|
294
|
+
const config = await readConfig();
|
|
295
|
+
const token = requireToken(config, t);
|
|
296
|
+
const baseUrl = resolveBaseUrl(config);
|
|
297
|
+
logger.log(t('list_remote_fetching', { type: 'systems' }));
|
|
298
|
+
const response = await storeGet(`${baseUrl}/api/store/systems`, token);
|
|
299
|
+
const systems = response.systems || [];
|
|
300
|
+
if (systems.length === 0) {
|
|
301
|
+
logger.log(t('system.list_remote_empty'));
|
|
302
|
+
} else {
|
|
303
|
+
logger.log(t('system.list_remote_header', { count: systems.length }));
|
|
304
|
+
for (const s of systems) {
|
|
305
|
+
logger.log(t('system.list_remote_item', { slug: s.slug, name: s.name || s.slug, version: s.version || '?', visibility: s.visibility || '?' }));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return { ok: true, systems, remote: true };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Local: list cached system packages
|
|
312
|
+
const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
|
|
313
|
+
const pkgsDir = path.join(projectDir, SYSTEM_PACKAGES_DIR);
|
|
314
|
+
|
|
315
|
+
if (!(await exists(pkgsDir))) {
|
|
316
|
+
logger.log(t('system.list_local_empty'));
|
|
317
|
+
return { ok: true, systems: [] };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const entries = await fs.readdir(pkgsDir, { withFileTypes: true });
|
|
321
|
+
const systems = entries
|
|
322
|
+
.filter(e => e.isDirectory())
|
|
323
|
+
.map(e => ({ slug: e.name }));
|
|
324
|
+
|
|
325
|
+
if (systems.length === 0) {
|
|
326
|
+
logger.log(t('system.list_local_empty'));
|
|
327
|
+
} else {
|
|
328
|
+
logger.log(t('system.list_local_header', { count: systems.length }));
|
|
329
|
+
for (const s of systems) {
|
|
330
|
+
logger.log(t('system.list_local_item', { slug: s.slug }));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return { ok: true, systems };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ── system:install (developer use — downloads source from store) ─────────────
|
|
338
|
+
|
|
339
|
+
async function runSystemInstall({ args, options, logger, t }) {
|
|
340
|
+
const config = await readConfig();
|
|
341
|
+
const token = requireToken(config, t);
|
|
342
|
+
const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
|
|
343
|
+
const baseUrl = resolveBaseUrl(config);
|
|
344
|
+
|
|
345
|
+
const ref = String(options.slug || options.code || args[1] || '').trim();
|
|
346
|
+
if (!ref) throw new Error(t('store.error_missing_code_or_slug'));
|
|
347
|
+
|
|
348
|
+
logger.log(t('system.install_fetching', { ref }));
|
|
349
|
+
|
|
350
|
+
const response = await storePost(`${baseUrl}/api/store/systems/install`, {
|
|
351
|
+
ref,
|
|
352
|
+
workspaceSlug: (await readWorkspace(projectDir))?.slug || null,
|
|
353
|
+
}, token);
|
|
354
|
+
|
|
355
|
+
const slug = response.manifest?.slug || response.slug;
|
|
356
|
+
if (!slug || !response.files) throw new Error(t('store.error_invalid_response'));
|
|
357
|
+
|
|
358
|
+
const version = response.manifest?.version || '?';
|
|
359
|
+
const publisher = response.publisher || 'unknown';
|
|
360
|
+
logger.log(t('store.install_preview_header', { slug, version, publisher }));
|
|
361
|
+
|
|
362
|
+
if (options.inspect) {
|
|
363
|
+
logger.log(t('store.install_inspect_files', { count: Object.keys(response.files).length }));
|
|
364
|
+
for (const f of Object.keys(response.files).sort()) logger.log(` ${f}`);
|
|
365
|
+
logger.log(t('store.install_inspect_hint'));
|
|
366
|
+
return { ok: true, slug, inspect: true, files: Object.keys(response.files) };
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const pkgDir = path.join(projectDir, SYSTEM_PACKAGES_DIR, slug);
|
|
370
|
+
|
|
371
|
+
if ((await exists(pkgDir)) && !options.force) {
|
|
372
|
+
const backupDir = path.join(projectDir, BACKUPS_DIR, `system-packages/${slug}`);
|
|
373
|
+
logger.log(t('store.install_backing_up', { path: backupDir }));
|
|
374
|
+
await fs.rm(backupDir, { recursive: true, force: true });
|
|
375
|
+
await fs.cp(pkgDir, backupDir, { recursive: true });
|
|
376
|
+
await fs.rm(pkgDir, { recursive: true, force: true });
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Write files
|
|
380
|
+
logger.log(t('system.install_writing'));
|
|
381
|
+
for (const [relPath, content] of Object.entries(response.files)) {
|
|
382
|
+
if (typeof content !== 'string') continue;
|
|
383
|
+
const destPath = path.join(pkgDir, relPath);
|
|
384
|
+
await ensureDir(path.dirname(destPath));
|
|
385
|
+
await fs.writeFile(destPath, content, 'utf8');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
logger.log(t('system.install_done', { slug, path: pkgDir }));
|
|
389
|
+
return { ok: true, slug, path: pkgDir, manifest: response.manifest };
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
module.exports = { runSystemPackage, runSystemPublish, runSystemList, runSystemInstall };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { TOOL_CAPS, getToolCapabilities, listSupportedTools } = require('../lib/tool-capabilities');
|
|
4
|
+
|
|
5
|
+
// Expose the per-tool capability map (resume support, install command, etc.)
|
|
6
|
+
// so external clients (AIOSON Play, IDE extensions) can drive UI without
|
|
7
|
+
// hard-coding their own copy of this lookup.
|
|
8
|
+
//
|
|
9
|
+
// Usage:
|
|
10
|
+
// aioson tool:capabilities --json
|
|
11
|
+
// aioson tool:capabilities --tool=claude --json
|
|
12
|
+
async function runToolCapabilities({ args: _args, options = {}, logger, t: _t }) {
|
|
13
|
+
const tool = options.tool ? String(options.tool).trim() : null;
|
|
14
|
+
|
|
15
|
+
let payload;
|
|
16
|
+
if (tool) {
|
|
17
|
+
const caps = getToolCapabilities(tool);
|
|
18
|
+
if (!caps) {
|
|
19
|
+
const supported = listSupportedTools();
|
|
20
|
+
throw new Error(`tool_unknown:${tool} (supported: ${supported.join(', ')})`);
|
|
21
|
+
}
|
|
22
|
+
payload = { tool: tool.toLowerCase(), capabilities: caps };
|
|
23
|
+
} else {
|
|
24
|
+
payload = {
|
|
25
|
+
tools: TOOL_CAPS,
|
|
26
|
+
schema_version: 1,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (options.json) {
|
|
31
|
+
logger.log(JSON.stringify(payload, null, 2));
|
|
32
|
+
return { ok: true, payload };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Human-readable fallback
|
|
36
|
+
if (tool) {
|
|
37
|
+
const caps = payload.capabilities;
|
|
38
|
+
logger.log(`Tool: ${payload.tool}`);
|
|
39
|
+
logger.log(` binary: ${caps.binary}`);
|
|
40
|
+
logger.log(` install_command: ${caps.install_command}`);
|
|
41
|
+
logger.log(` supports_resume: ${caps.supports_resume}`);
|
|
42
|
+
if (caps.supports_resume) {
|
|
43
|
+
logger.log(` resume_last: ${(caps.resume_last || []).join(' ')}`);
|
|
44
|
+
logger.log(` supports_session_id: ${caps.supports_session_id}`);
|
|
45
|
+
if (caps.supports_session_id) {
|
|
46
|
+
logger.log(` resume_session_id: ${(caps.resume_session_id || []).join(' ')}`);
|
|
47
|
+
}
|
|
48
|
+
logger.log(` supports_session_picker: ${caps.supports_session_picker}`);
|
|
49
|
+
if (caps.supports_session_picker) {
|
|
50
|
+
logger.log(` session_picker: ${(caps.session_picker || []).join(' ')}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
logger.log(`Supported tools: ${listSupportedTools().join(', ')}`);
|
|
55
|
+
logger.log(`Run with --tool=<name> for details, or --json for the full map.`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return { ok: true, payload };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {
|
|
62
|
+
runToolCapabilities,
|
|
63
|
+
};
|
package/src/commands/update.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
const { detectFramework } = require('../detector');
|
|
5
5
|
const { updateInstallation } = require('../updater');
|
|
6
|
-
const { validateProjectContextFile } = require('../context');
|
|
6
|
+
const { validateProjectContextFile, getInteractionLanguage } = require('../context');
|
|
7
7
|
const { applyAgentLocale } = require('../locales');
|
|
8
8
|
|
|
9
9
|
async function runUpdate({ args, options, logger, t }) {
|
|
@@ -28,8 +28,8 @@ async function runUpdate({ args, options, logger, t }) {
|
|
|
28
28
|
const context = await validateProjectContextFile(targetDir);
|
|
29
29
|
const language =
|
|
30
30
|
requestedLanguage ||
|
|
31
|
-
(context.parsed && context.data
|
|
32
|
-
? context.data
|
|
31
|
+
(context.parsed && context.data
|
|
32
|
+
? getInteractionLanguage(context.data, '')
|
|
33
33
|
: null) ||
|
|
34
34
|
(result.savedProfile && result.savedProfile.locale
|
|
35
35
|
? result.savedProfile.locale
|
|
@@ -454,6 +454,35 @@ async function runVerifyGate({ args, options = {}, logger }) {
|
|
|
454
454
|
// ── Parse spec requirements ───────────────────────────────────────────────
|
|
455
455
|
const requirements = parseSpecRequirements(specContent);
|
|
456
456
|
|
|
457
|
+
// ── Harness Integration ───────────────────────────────────────────────────
|
|
458
|
+
let contractCriteria = [];
|
|
459
|
+
if (options.contract) {
|
|
460
|
+
try {
|
|
461
|
+
const contractContent = await fs.readFile(path.resolve(targetDir, options.contract), 'utf8');
|
|
462
|
+
const contract = JSON.parse(contractContent);
|
|
463
|
+
if (contract.criteria && Array.isArray(contract.criteria)) {
|
|
464
|
+
contractCriteria = contract.criteria;
|
|
465
|
+
for (const c of contract.criteria) {
|
|
466
|
+
let mapped = false;
|
|
467
|
+
// Map assertion to deterministic check if possible
|
|
468
|
+
// Pattern mapping: if assertion looks like "path/to/file.js", add to required files
|
|
469
|
+
if (c.assertion.includes('/') && !c.assertion.includes(' ')) {
|
|
470
|
+
requirements.required_files.push(c.assertion.trim());
|
|
471
|
+
mapped = true;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Only add to acceptance criteria for reporting if not deterministically mapped
|
|
475
|
+
// This prevents "Unchecked criterion" issues for things already checked via files/patterns
|
|
476
|
+
if (!mapped) {
|
|
477
|
+
requirements.acceptance_criteria.push({ text: `[Harness ${c.id}] ${c.description}`, checked: false });
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
} catch (err) {
|
|
482
|
+
logger.warn(`[VerifyGate] Falha ao ler contrato: ${err.message}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
457
486
|
// ── Collect artifact files ────────────────────────────────────────────────
|
|
458
487
|
const allFiles = await collectFiles(artifactPath);
|
|
459
488
|
|
|
@@ -499,6 +528,16 @@ async function runVerifyGate({ args, options = {}, logger }) {
|
|
|
499
528
|
const relOut = path.relative(targetDir, outPath);
|
|
500
529
|
|
|
501
530
|
if (options.json) {
|
|
531
|
+
// Map issues/passes back to contract IDs if possible
|
|
532
|
+
const criteriaResults = contractCriteria.map(c => {
|
|
533
|
+
const passed = !allIssues.some(i => i.includes(c.id) || i.includes(c.assertion));
|
|
534
|
+
return {
|
|
535
|
+
id: c.id,
|
|
536
|
+
passed,
|
|
537
|
+
reason: passed ? null : allIssues.find(i => i.includes(c.id) || i.includes(c.assertion))
|
|
538
|
+
};
|
|
539
|
+
});
|
|
540
|
+
|
|
502
541
|
return {
|
|
503
542
|
ok: verdict === 'PASS' || verdict === 'PASS_WITH_NOTES',
|
|
504
543
|
verdict,
|
|
@@ -509,6 +548,7 @@ async function runVerifyGate({ args, options = {}, logger }) {
|
|
|
509
548
|
issues: allIssues,
|
|
510
549
|
notes: allNotes,
|
|
511
550
|
passes: allPasses,
|
|
551
|
+
criteria_results: criteriaResults,
|
|
512
552
|
requirements: {
|
|
513
553
|
required_files: requirements.required_files.length,
|
|
514
554
|
acceptance_criteria: requirements.acceptance_criteria.length,
|