@jaimevalasek/aioson 1.7.2 → 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 +35 -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 +42 -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/cypher.md +252 -0
- package/template/.aioson/agents/dev.md +112 -628
- package/template/.aioson/agents/deyvin.md +33 -236
- 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 +5 -7
- 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 +168 -514
- package/template/.aioson/agents/setup.md +52 -278
- package/template/.aioson/agents/sheldon.md +122 -754
- package/template/.aioson/agents/site-forge.md +111 -1583
- package/template/.aioson/agents/squad.md +139 -2010
- package/template/.aioson/agents/tester.md +10 -0
- package/template/.aioson/agents/ux-ui.md +104 -812
- 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.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/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/web-research-cache.md +3 -0
- package/template/.aioson/tasks/squad-create.md +35 -8
- package/template/.aioson/tasks/squad-design.md +50 -2
- package/template/.aioson/tasks/squad-investigate.md +14 -1
- 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 +5 -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/src/commands/agents.js
CHANGED
|
@@ -8,14 +8,17 @@ const {
|
|
|
8
8
|
resolveInstructionPath,
|
|
9
9
|
buildAgentPrompt
|
|
10
10
|
} = require('../agents');
|
|
11
|
-
const {
|
|
12
|
-
const { validateProjectContextFile } = require('../context');
|
|
11
|
+
const { normalizeInteractionLanguage } = require('../locales');
|
|
12
|
+
const { validateProjectContextFile, getInteractionLanguage } = require('../context');
|
|
13
13
|
const { exists } = require('../utils');
|
|
14
14
|
const { loadOrCreateState, runWorkflowNext } = require('./workflow-next');
|
|
15
15
|
const {
|
|
16
16
|
bootstrapDirectAgentPrompt,
|
|
17
17
|
classifyDirectAgentRuntime
|
|
18
18
|
} = require('../execution-gateway');
|
|
19
|
+
const { readAutonomyProtocol, resolveEffectiveMode } = require('../autonomy-policy');
|
|
20
|
+
const { readAgentManifest, buildAgentCapabilitySummary } = require('../agent-manifests');
|
|
21
|
+
const { emitSecurityRuntimeEvent } = require('../lib/security/runtime-events');
|
|
19
22
|
|
|
20
23
|
const WORKFLOW_AGENT_IDS = new Set([
|
|
21
24
|
'setup',
|
|
@@ -29,13 +32,59 @@ const WORKFLOW_AGENT_IDS = new Set([
|
|
|
29
32
|
'qa'
|
|
30
33
|
]);
|
|
31
34
|
|
|
35
|
+
function normalizePentesterTargetMode(input) {
|
|
36
|
+
const mode = String(input || '').trim().toLowerCase();
|
|
37
|
+
if (!mode) return null;
|
|
38
|
+
if (mode === 'framework_target' || mode === 'app_target') return mode;
|
|
39
|
+
return '__invalid__';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function buildPentesterActivationContext(options, t) {
|
|
43
|
+
const targetMode = normalizePentesterTargetMode(options.mode);
|
|
44
|
+
if (targetMode === '__invalid__') {
|
|
45
|
+
throw new Error(t('agents.prompt_invalid_target_mode', { mode: options.mode }));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const featureSlug = String(options.feature || options.slug || '').trim();
|
|
49
|
+
const scope = String(options.scope || '').trim();
|
|
50
|
+
|
|
51
|
+
if (targetMode !== 'app_target' && !targetMode) return '';
|
|
52
|
+
|
|
53
|
+
if (targetMode === 'app_target' && !featureSlug) {
|
|
54
|
+
throw new Error(t('agents.prompt_missing_feature_for_app_target'));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (targetMode === 'app_target' && !scope) {
|
|
58
|
+
throw new Error(t('agents.prompt_missing_scope_for_app_target'));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const lines = [`Requested target mode: ${targetMode}.`];
|
|
62
|
+
if (featureSlug) lines.push(`Feature slug: ${featureSlug}.`);
|
|
63
|
+
if (scope) lines.push(`Requested scope: ${scope}.`);
|
|
64
|
+
|
|
65
|
+
if (targetMode === 'app_target') {
|
|
66
|
+
lines.push(
|
|
67
|
+
'Use only the app_target surface catalog (`app_target_ownership_idor`, `app_target_secrets_crypto`, `app_target_injection_xss`, `app_target_insecure_design_race`, `app_target_auth_rate_limit`).'
|
|
68
|
+
);
|
|
69
|
+
lines.push(
|
|
70
|
+
'Do not mix framework surfaces unless the feature explicitly touches AIOSON runtime boundaries and you record a `cross_scope_reason`.'
|
|
71
|
+
);
|
|
72
|
+
} else {
|
|
73
|
+
lines.push(
|
|
74
|
+
'Preserve the legacy framework surface catalog (`memory_context`, `tool_invocation`, `delegation_handoff`, `protocol_contract`, `secret_handling`, `runtime_permissions`).'
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return lines.join('\n');
|
|
79
|
+
}
|
|
80
|
+
|
|
32
81
|
async function resolveLocaleForTarget(targetDir, options) {
|
|
33
82
|
const fromOption = options.language || options.lang;
|
|
34
|
-
if (fromOption) return
|
|
83
|
+
if (fromOption) return normalizeInteractionLanguage(fromOption);
|
|
35
84
|
|
|
36
85
|
const context = await validateProjectContextFile(targetDir);
|
|
37
|
-
if (context.parsed && context.data
|
|
38
|
-
return
|
|
86
|
+
if (context.parsed && context.data) {
|
|
87
|
+
return getInteractionLanguage(context.data, 'en');
|
|
39
88
|
}
|
|
40
89
|
|
|
41
90
|
return 'en';
|
|
@@ -93,6 +142,9 @@ async function runAgentPrompt({ args, options, logger, t }) {
|
|
|
93
142
|
let promptAgent = agent;
|
|
94
143
|
let instructionPath = null;
|
|
95
144
|
let prompt = null;
|
|
145
|
+
let effectiveMode = null;
|
|
146
|
+
let activationContext = '';
|
|
147
|
+
let pentesterTargetMode = null;
|
|
96
148
|
|
|
97
149
|
if (WORKFLOW_AGENT_IDS.has(requestedAgent)) {
|
|
98
150
|
const loaded = await loadOrCreateState(targetDir, options);
|
|
@@ -114,12 +166,32 @@ async function runAgentPrompt({ args, options, logger, t }) {
|
|
|
114
166
|
promptAgent = getAgentDefinition(workflowResult.agent) || agent;
|
|
115
167
|
instructionPath = workflowResult.instructionPath;
|
|
116
168
|
prompt = workflowResult.prompt;
|
|
169
|
+
effectiveMode = workflowResult.effectiveMode || null;
|
|
117
170
|
}
|
|
118
171
|
}
|
|
119
172
|
|
|
120
173
|
if (!prompt) {
|
|
121
174
|
instructionPath = await resolveExistingInstructionPath(targetDir, promptAgent, locale);
|
|
122
|
-
|
|
175
|
+
if (promptAgent.id === 'pentester') {
|
|
176
|
+
pentesterTargetMode = normalizePentesterTargetMode(options.mode);
|
|
177
|
+
activationContext = buildPentesterActivationContext(options, t);
|
|
178
|
+
}
|
|
179
|
+
const autonomyProtocol = await readAutonomyProtocol(targetDir);
|
|
180
|
+
const manifest = await readAgentManifest(targetDir, promptAgent.id);
|
|
181
|
+
effectiveMode = resolveEffectiveMode({
|
|
182
|
+
protocol: autonomyProtocol,
|
|
183
|
+
tool,
|
|
184
|
+
agentId: promptAgent.id,
|
|
185
|
+
manifest,
|
|
186
|
+
requestedMode: options.mode || null
|
|
187
|
+
});
|
|
188
|
+
prompt = buildAgentPrompt(promptAgent, tool, {
|
|
189
|
+
instructionPath,
|
|
190
|
+
interactionLanguage: locale,
|
|
191
|
+
autonomyMode: effectiveMode,
|
|
192
|
+
capabilitySummary: buildAgentCapabilitySummary(manifest, tool),
|
|
193
|
+
activationContext
|
|
194
|
+
});
|
|
123
195
|
const runtimeClass = classifyDirectAgentRuntime(promptAgent.id);
|
|
124
196
|
const handoffLabel = runtimeClass.source === 'squad_session'
|
|
125
197
|
? 'Squad session handoff'
|
|
@@ -140,6 +212,28 @@ async function runAgentPrompt({ args, options, logger, t }) {
|
|
|
140
212
|
logger.log(t('agents.prompt_title', { agent: promptAgent.id, tool, locale }));
|
|
141
213
|
logger.log(prompt);
|
|
142
214
|
|
|
215
|
+
if (
|
|
216
|
+
promptAgent.id === 'pentester' &&
|
|
217
|
+
pentesterTargetMode === 'app_target' &&
|
|
218
|
+
runtime &&
|
|
219
|
+
runtime.runKey
|
|
220
|
+
) {
|
|
221
|
+
await emitSecurityRuntimeEvent({
|
|
222
|
+
targetDir,
|
|
223
|
+
runKey: runtime.runKey,
|
|
224
|
+
eventType: 'pentester_app_target_invoked',
|
|
225
|
+
message: `@pentester app_target invoked for ${String(options.feature || options.slug || '').trim()}`,
|
|
226
|
+
status: 'queued',
|
|
227
|
+
payload: {
|
|
228
|
+
target_mode: 'app_target',
|
|
229
|
+
feature_slug: String(options.feature || options.slug || '').trim(),
|
|
230
|
+
target_scope: String(options.scope || '').trim(),
|
|
231
|
+
tool,
|
|
232
|
+
locale
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
143
237
|
return {
|
|
144
238
|
ok: true,
|
|
145
239
|
targetDir,
|
|
@@ -150,7 +244,8 @@ async function runAgentPrompt({ args, options, logger, t }) {
|
|
|
150
244
|
locale,
|
|
151
245
|
instructionPath,
|
|
152
246
|
prompt,
|
|
153
|
-
runtime
|
|
247
|
+
runtime,
|
|
248
|
+
effectiveMode
|
|
154
249
|
};
|
|
155
250
|
}
|
|
156
251
|
|
|
@@ -61,12 +61,13 @@ async function runArtifactValidate({ args, options = {}, logger }) {
|
|
|
61
61
|
? (artifacts.implementation_plan.frontmatter.status || 'present')
|
|
62
62
|
: null;
|
|
63
63
|
|
|
64
|
-
// Requirement count
|
|
64
|
+
// Requirement count. Accept both simple IDs (REQ-01) and slugged IDs
|
|
65
|
+
// (REQ-SDLC-01), because feature contracts use slugged identifiers.
|
|
65
66
|
let reqCount = null;
|
|
66
67
|
if (artifacts.requirements.exists && artifacts.requirements.content) {
|
|
67
|
-
const reqs = artifacts.requirements.content.match(/\bREQ[
|
|
68
|
-
const acs = artifacts.requirements.content.match(/\bAC[
|
|
69
|
-
reqCount = `${reqs.
|
|
68
|
+
const reqs = artifacts.requirements.content.match(/\bREQ(?:-[A-Z0-9]+)+\b/g) || [];
|
|
69
|
+
const acs = artifacts.requirements.content.match(/\bAC(?:-[A-Z0-9]+)+\b/g) || [];
|
|
70
|
+
reqCount = `${new Set(reqs).size} REQs, ${new Set(acs).size} ACs`;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
// Conformance required?
|
|
@@ -138,6 +139,26 @@ async function runArtifactValidate({ args, options = {}, logger }) {
|
|
|
138
139
|
|
|
139
140
|
const valid = missing.length === 0;
|
|
140
141
|
|
|
142
|
+
// Determine next_missing and next_agent (AC-SDLC-22)
|
|
143
|
+
const ARTIFACT_OWNER_MAP = {
|
|
144
|
+
'project.context.md': { agent: '@setup', reason: 'setup not complete' },
|
|
145
|
+
[`prd-${slug}.md`]: { agent: '@product', reason: 'PRD not produced yet' },
|
|
146
|
+
[`requirements-${slug}.md`]: { agent: '@analyst', reason: 'requirements not produced yet (Gate A)' },
|
|
147
|
+
'architecture.md': { agent: '@architect', reason: 'architecture not produced yet (Gate B)' },
|
|
148
|
+
[`implementation-plan-${slug}.md`]: { agent: '@pm', reason: 'implementation plan not produced yet (Gate C)' },
|
|
149
|
+
[`spec-${slug}.md`]: { agent: '@analyst', reason: 'spec not produced yet — @analyst seeds the feature memory' },
|
|
150
|
+
[`conformance-${slug}.yaml`]: { agent: '@analyst', reason: 'conformance contract missing — @analyst creates it for MEDIUM features' }
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
let nextMissing = null;
|
|
154
|
+
let nextAgent = null;
|
|
155
|
+
if (!valid && missing.length > 0) {
|
|
156
|
+
const firstMissing = missing[0];
|
|
157
|
+
nextMissing = firstMissing.name;
|
|
158
|
+
const ownerInfo = ARTIFACT_OWNER_MAP[firstMissing.name];
|
|
159
|
+
if (ownerInfo) nextAgent = `${ownerInfo.agent} (${ownerInfo.reason})`;
|
|
160
|
+
}
|
|
161
|
+
|
|
141
162
|
const result = {
|
|
142
163
|
ok: valid,
|
|
143
164
|
feature: slug,
|
|
@@ -150,6 +171,8 @@ async function runArtifactValidate({ args, options = {}, logger }) {
|
|
|
150
171
|
})),
|
|
151
172
|
missing_required: missing.map((c) => c.name),
|
|
152
173
|
missing_optional: missingOptional.map((c) => c.name),
|
|
174
|
+
next_missing: nextMissing,
|
|
175
|
+
next_agent: nextAgent,
|
|
153
176
|
integrity: valid ? 'VALID' : 'INVALID'
|
|
154
177
|
};
|
|
155
178
|
|
|
@@ -181,6 +204,12 @@ async function runArtifactValidate({ args, options = {}, logger }) {
|
|
|
181
204
|
logger.log(`Missing optional: ${missingOptional.map((c) => c.name).join(', ')} (${classification || 'SMALL'} — acceptable)`);
|
|
182
205
|
}
|
|
183
206
|
|
|
207
|
+
if (!valid && nextAgent) {
|
|
208
|
+
logger.log('');
|
|
209
|
+
logger.log(`Next missing: ${nextMissing}`);
|
|
210
|
+
logger.log(`Next agent: ${nextAgent}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
184
213
|
logger.log('');
|
|
185
214
|
|
|
186
215
|
return result;
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const readline = require('readline');
|
|
6
|
+
const { exec } = require('child_process');
|
|
7
|
+
const { readConfig, writeConfig, CONFIG_DIR } = require('./config');
|
|
8
|
+
|
|
9
|
+
const DEFAULT_BASE_URL = 'https://aioson.com';
|
|
10
|
+
|
|
11
|
+
function resolveBaseUrl(config, options = {}) {
|
|
12
|
+
return String(options['base-url'] || config.aiosonBaseUrl || DEFAULT_BASE_URL).replace(/\/+$/, '');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function fetchAuthMe(baseUrl, token) {
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(`${baseUrl}/api/me`, {
|
|
18
|
+
headers: { authorization: `Bearer ${token}`, accept: 'application/json' },
|
|
19
|
+
signal: AbortSignal.timeout(8000)
|
|
20
|
+
});
|
|
21
|
+
if (response.ok) {
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
return data.user || data;
|
|
24
|
+
}
|
|
25
|
+
} catch {
|
|
26
|
+
// API unreachable
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ─── Detectar ambiente sem browser ───────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
function isHeadlessEnv() {
|
|
34
|
+
// WSL2, SSH sem X11, CI
|
|
35
|
+
if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP) return true;
|
|
36
|
+
if (process.env.CI) return true;
|
|
37
|
+
if (process.env.SSH_CLIENT && !process.env.DISPLAY) return true;
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function openBrowser(url) {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const platform = process.platform;
|
|
44
|
+
const cmd =
|
|
45
|
+
platform === 'darwin' ? `open "${url}"` :
|
|
46
|
+
platform === 'win32' ? `start "" "${url}"` :
|
|
47
|
+
`xdg-open "${url}"`;
|
|
48
|
+
exec(cmd, { timeout: 5000 }, (err) => resolve(!err));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─── Fluxo A: callback local (Mac/Windows nativos) ────────────────────────
|
|
53
|
+
|
|
54
|
+
function callbackLogin(baseUrl, state, logger, t) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
let settled = false;
|
|
57
|
+
function done(err, value) {
|
|
58
|
+
if (settled) return;
|
|
59
|
+
settled = true;
|
|
60
|
+
if (err) reject(err); else resolve(value);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const timeout = setTimeout(() => {
|
|
64
|
+
server.close();
|
|
65
|
+
done(new Error(t('auth.browser_timeout')));
|
|
66
|
+
}, 120_000);
|
|
67
|
+
|
|
68
|
+
const server = http.createServer((req, res) => {
|
|
69
|
+
const url = new URL(req.url, 'http://localhost');
|
|
70
|
+
if (url.pathname !== '/callback') { res.writeHead(404); res.end(); return; }
|
|
71
|
+
|
|
72
|
+
const token = url.searchParams.get('token');
|
|
73
|
+
const receivedState = url.searchParams.get('state');
|
|
74
|
+
|
|
75
|
+
if (receivedState !== state || !token) {
|
|
76
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
77
|
+
res.end(htmlPage('Erro', 'State inválido ou token ausente. Tente novamente.', false));
|
|
78
|
+
server.close(); clearTimeout(timeout);
|
|
79
|
+
done(new Error(t('auth.browser_state_mismatch')));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
84
|
+
res.end(htmlPage('Autenticado!', 'Login realizado. Pode fechar esta aba e voltar ao terminal.', true));
|
|
85
|
+
server.close(); clearTimeout(timeout);
|
|
86
|
+
done(null, token);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
server.on('error', (err) => {
|
|
90
|
+
clearTimeout(timeout);
|
|
91
|
+
done(new Error(`${t('auth.browser_server_error')}: ${err.message}`));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
server.listen(0, '127.0.0.1');
|
|
95
|
+
server.once('listening', () => resolve({ _server: server, _port: server.address().port }));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ─── Fluxo B: paste — CLI mostra URL, usuário cola o token ───────────────
|
|
100
|
+
|
|
101
|
+
async function pasteLogin(baseUrl, logger, t) {
|
|
102
|
+
const state = crypto.randomBytes(16).toString('hex');
|
|
103
|
+
const loginUrl = `${baseUrl}/auth/cli?state=${state}`;
|
|
104
|
+
|
|
105
|
+
logger.log('');
|
|
106
|
+
logger.log(t('auth.paste_open_browser'));
|
|
107
|
+
logger.log('');
|
|
108
|
+
logger.log(` ${loginUrl}`);
|
|
109
|
+
logger.log('');
|
|
110
|
+
logger.log(t('auth.paste_instruction'));
|
|
111
|
+
logger.log('');
|
|
112
|
+
|
|
113
|
+
// Tentar abrir browser automaticamente (ignora falha)
|
|
114
|
+
openBrowser(loginUrl).catch(() => {});
|
|
115
|
+
|
|
116
|
+
// Aguardar input do usuário
|
|
117
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
118
|
+
const token = await new Promise((resolve) => {
|
|
119
|
+
rl.question(`${t('auth.paste_token_prompt')} `, (answer) => {
|
|
120
|
+
rl.close();
|
|
121
|
+
resolve(answer.trim());
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (!token) throw new Error(t('auth.paste_no_token'));
|
|
126
|
+
return token;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ─── Login principal ──────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
async function runAuthLogin({ args, options, logger, t }) {
|
|
132
|
+
const tokenOpt = String(options.token || '').trim();
|
|
133
|
+
const config = await readConfig();
|
|
134
|
+
const baseUrl = resolveBaseUrl(config, options);
|
|
135
|
+
|
|
136
|
+
let token = tokenOpt;
|
|
137
|
+
|
|
138
|
+
if (!token) {
|
|
139
|
+
const headless = isHeadlessEnv() || options['no-browser'];
|
|
140
|
+
|
|
141
|
+
if (headless) {
|
|
142
|
+
// Fluxo B: paste
|
|
143
|
+
try {
|
|
144
|
+
token = await pasteLogin(baseUrl, logger, t);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
logger.log(t('auth.browser_failed', { error: err.message }));
|
|
147
|
+
return { ok: false, error: { code: 'paste_login_failed' } };
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
// Fluxo A: callback local, com fallback para paste se browser não abrir
|
|
151
|
+
const state = crypto.randomBytes(16).toString('hex');
|
|
152
|
+
let server, port;
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const result = await new Promise((resolve, reject) => {
|
|
156
|
+
const s = http.createServer();
|
|
157
|
+
s.listen(0, '127.0.0.1', () => resolve({ server: s, port: s.address().port }));
|
|
158
|
+
s.on('error', reject);
|
|
159
|
+
});
|
|
160
|
+
server = result.server;
|
|
161
|
+
port = result.port;
|
|
162
|
+
} catch {
|
|
163
|
+
// Sem servidor local → paste
|
|
164
|
+
token = await pasteLogin(baseUrl, logger, t);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (server && port) {
|
|
168
|
+
const callbackUrl = `http://127.0.0.1:${port}/callback`;
|
|
169
|
+
const loginUrl = `${baseUrl}/auth/cli?callback=${encodeURIComponent(callbackUrl)}&state=${state}`;
|
|
170
|
+
|
|
171
|
+
const opened = await openBrowser(loginUrl);
|
|
172
|
+
|
|
173
|
+
if (!opened) {
|
|
174
|
+
// Browser não abriu → paste
|
|
175
|
+
server.close();
|
|
176
|
+
token = await pasteLogin(baseUrl, logger, t);
|
|
177
|
+
} else {
|
|
178
|
+
logger.log(t('auth.browser_opening'));
|
|
179
|
+
logger.log(t('auth.browser_waiting'));
|
|
180
|
+
|
|
181
|
+
// Aguardar callback
|
|
182
|
+
token = await new Promise((resolve, reject) => {
|
|
183
|
+
const timeout = setTimeout(() => {
|
|
184
|
+
server.close();
|
|
185
|
+
reject(new Error(t('auth.browser_timeout')));
|
|
186
|
+
}, 120_000);
|
|
187
|
+
|
|
188
|
+
server.on('request', (req, res) => {
|
|
189
|
+
const url = new URL(req.url, 'http://localhost');
|
|
190
|
+
if (url.pathname !== '/callback') { res.writeHead(404); res.end(); return; }
|
|
191
|
+
const t2 = url.searchParams.get('token');
|
|
192
|
+
const s2 = url.searchParams.get('state');
|
|
193
|
+
if (s2 !== state || !t2) {
|
|
194
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
195
|
+
res.end(htmlPage('Erro', 'State inválido. Tente novamente.', false));
|
|
196
|
+
server.close(); clearTimeout(timeout);
|
|
197
|
+
reject(new Error('State inválido'));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
201
|
+
res.end(htmlPage('Autenticado!', 'Pode fechar esta aba e voltar ao terminal.', true));
|
|
202
|
+
server.close(); clearTimeout(timeout);
|
|
203
|
+
resolve(t2);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
logger.log('');
|
|
212
|
+
logger.log(t('auth.login_verifying'));
|
|
213
|
+
const user = await fetchAuthMe(baseUrl, token);
|
|
214
|
+
|
|
215
|
+
config.aiosonToken = token;
|
|
216
|
+
if (baseUrl !== DEFAULT_BASE_URL) config.aiosonBaseUrl = baseUrl;
|
|
217
|
+
if (user?.username) config.aiosonUsername = user.username;
|
|
218
|
+
await writeConfig(config);
|
|
219
|
+
|
|
220
|
+
if (user?.username) {
|
|
221
|
+
logger.log(t('auth.login_ok', { username: user.username, path: CONFIG_DIR }));
|
|
222
|
+
} else {
|
|
223
|
+
logger.log(t('auth.login_saved', { path: CONFIG_DIR }));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return { ok: true, username: user?.username || null };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function runAuthLogout({ args, options, logger, t }) {
|
|
230
|
+
const config = await readConfig();
|
|
231
|
+
delete config.aiosonToken;
|
|
232
|
+
delete config.aiosonUsername;
|
|
233
|
+
await writeConfig(config);
|
|
234
|
+
logger.log(t('auth.logout_ok'));
|
|
235
|
+
return { ok: true };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async function runAuthStatus({ args, options, logger, t }) {
|
|
239
|
+
const config = await readConfig();
|
|
240
|
+
const token = config.aiosonToken;
|
|
241
|
+
|
|
242
|
+
if (!token) {
|
|
243
|
+
logger.log(t('auth.status_not_authenticated'));
|
|
244
|
+
logger.log(t('auth.login_hint'));
|
|
245
|
+
return { ok: true, authenticated: false };
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const baseUrl = resolveBaseUrl(config, options);
|
|
249
|
+
logger.log(t('auth.status_checking'));
|
|
250
|
+
const user = await fetchAuthMe(baseUrl, token);
|
|
251
|
+
|
|
252
|
+
if (user?.username) {
|
|
253
|
+
logger.log(t('auth.status_ok', { username: user.username }));
|
|
254
|
+
return { ok: true, authenticated: true, username: user.username, apiReachable: true };
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const savedUsername = config.aiosonUsername || '?';
|
|
258
|
+
logger.log(t('auth.status_token_offline', { username: savedUsername }));
|
|
259
|
+
return { ok: true, authenticated: true, username: savedUsername, apiReachable: false };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function htmlPage(title, message, success) {
|
|
263
|
+
const color = success ? '#22c55e' : '#ef4444';
|
|
264
|
+
const icon = success ? '✓' : '✗';
|
|
265
|
+
return `<!DOCTYPE html><html lang="pt-BR"><head><meta charset="UTF-8"><title>AIOSON CLI — ${title}</title>
|
|
266
|
+
<style>body{margin:0;font-family:system-ui,sans-serif;background:#0f1117;color:#e8eaf0;display:flex;align-items:center;justify-content:center;min-height:100vh;text-align:center}
|
|
267
|
+
.card{background:#1a1d27;border:1px solid #2e334d;border-radius:14px;padding:40px 48px;max-width:420px}
|
|
268
|
+
.icon{font-size:40px;margin-bottom:16px;color:${color}}h1{font-size:22px;font-weight:700;margin:0 0 10px}p{color:#9ca3af;margin:0;line-height:1.6}</style>
|
|
269
|
+
</head><body><div class="card"><div class="icon">${icon}</div><h1>${title}</h1><p>${message}</p></div></body></html>`;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
module.exports = { runAuthLogin, runAuthLogout, runAuthStatus };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { splitCsv, queryBrains, formatBrainNodesCompact } = require('../brain-query');
|
|
5
|
+
|
|
6
|
+
async function runBrainQuery({ args, options = {}, logger }) {
|
|
7
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
8
|
+
const result = await queryBrains({
|
|
9
|
+
targetDir,
|
|
10
|
+
tags: splitCsv(options.tags),
|
|
11
|
+
matchMode: options.match || 'any',
|
|
12
|
+
minQuality: options['min-quality'] || options.minQuality || 0,
|
|
13
|
+
agent: options.agent || '',
|
|
14
|
+
verdicts: splitCsv(options.verdict),
|
|
15
|
+
ids: splitCsv(options.id),
|
|
16
|
+
avoidOnly: Boolean(options.avoid)
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (options.json) return result;
|
|
20
|
+
|
|
21
|
+
if (!result.ok) {
|
|
22
|
+
logger.log(result.warnings.join('\n') || result.reason || 'Brain query failed.');
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (result.warnings.length > 0) {
|
|
27
|
+
for (const warning of result.warnings) logger.log(`Warning: ${warning}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const format = options.format || 'compact';
|
|
31
|
+
if (format === 'ids') {
|
|
32
|
+
logger.log(result.nodes.map((node) => node.id).join('\n'));
|
|
33
|
+
} else if (format === 'json') {
|
|
34
|
+
logger.log(JSON.stringify(result.nodes, null, 2));
|
|
35
|
+
} else {
|
|
36
|
+
logger.log(formatBrainNodesCompact(result.nodes));
|
|
37
|
+
}
|
|
38
|
+
logger.log(`${result.nodes.length} node(s) matched across ${result.brainFiles.length} brain file(s)`);
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
runBrainQuery
|
|
44
|
+
};
|