@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
|
@@ -1,125 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const fs = require('node:fs/promises');
|
|
4
|
-
const path = require('node:path');
|
|
5
|
-
const { TEMPLATE_DIR } = require('../installer');
|
|
6
|
-
|
|
7
|
-
const AGENTS = ['setup', 'analyst', 'architect', 'pm', 'ux-ui', 'dev', 'qa', 'orchestrator'];
|
|
8
|
-
const LOCALES = ['en', 'pt-BR', 'es', 'fr'];
|
|
9
|
-
|
|
10
|
-
// Extract ## Section headings from markdown content
|
|
11
|
-
function extractSections(content) {
|
|
12
|
-
const sections = [];
|
|
13
|
-
for (const line of content.split('\n')) {
|
|
14
|
-
if (/^#{1,3} /.test(line)) {
|
|
15
|
-
sections.push(line.trim());
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return sections;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Normalize a heading to a comparable key (remove locale-specific punctuation/accents)
|
|
22
|
-
function normalizeHeading(heading) {
|
|
23
|
-
return heading
|
|
24
|
-
.toLowerCase()
|
|
25
|
-
.replace(/[áàâãä]/g, 'a')
|
|
26
|
-
.replace(/[éèêë]/g, 'e')
|
|
27
|
-
.replace(/[íìîï]/g, 'i')
|
|
28
|
-
.replace(/[óòôõö]/g, 'o')
|
|
29
|
-
.replace(/[úùûü]/g, 'u')
|
|
30
|
-
.replace(/[ç]/g, 'c')
|
|
31
|
-
.replace(/[ñ]/g, 'n')
|
|
32
|
-
.replace(/[^a-z0-9# ]/g, '')
|
|
33
|
-
.replace(/\s+/g, ' ')
|
|
34
|
-
.trim();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function readFile(filePath) {
|
|
38
|
-
try {
|
|
39
|
-
return await fs.readFile(filePath, 'utf8');
|
|
40
|
-
} catch {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
3
|
async function runLocaleDiff({ args, options, logger }) {
|
|
46
4
|
const jsonMode = Boolean(options.json);
|
|
47
5
|
const log = jsonMode ? () => {} : logger.log.bind(logger);
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
const filterLocale = options.lang || options.language || null;
|
|
51
|
-
|
|
52
|
-
const baseAgentsDir = path.join(TEMPLATE_DIR, '.aioson', 'agents');
|
|
53
|
-
const localesDir = path.join(TEMPLATE_DIR, '.aioson', 'locales');
|
|
54
|
-
|
|
55
|
-
const agentsToCheck = filterAgent
|
|
56
|
-
? AGENTS.filter(a => a === filterAgent)
|
|
57
|
-
: AGENTS;
|
|
58
|
-
const localesToCheck = filterLocale
|
|
59
|
-
? LOCALES.filter(l => l === filterLocale)
|
|
60
|
-
: LOCALES;
|
|
61
|
-
|
|
62
|
-
const report = [];
|
|
63
|
-
let totalMissing = 0;
|
|
64
|
-
|
|
65
|
-
for (const agent of agentsToCheck) {
|
|
66
|
-
const baseFile = path.join(baseAgentsDir, `${agent}.md`);
|
|
67
|
-
const baseContent = await readFile(baseFile);
|
|
68
|
-
if (!baseContent) {
|
|
69
|
-
log(`WARN: base agent @${agent} not found`);
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const baseSections = extractSections(baseContent);
|
|
74
|
-
const baseNorm = baseSections.map(s => ({ original: s, key: normalizeHeading(s) }));
|
|
75
|
-
|
|
76
|
-
for (const locale of localesToCheck) {
|
|
77
|
-
const localeFile = path.join(localesDir, locale, 'agents', `${agent}.md`);
|
|
78
|
-
const localeContent = await readFile(localeFile);
|
|
79
|
-
if (!localeContent) {
|
|
80
|
-
log(`WARN: @${agent} (${locale}) not found`);
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const localeSections = extractSections(localeContent);
|
|
85
|
-
const localeNormSet = new Set(localeSections.map(s => normalizeHeading(s)));
|
|
86
|
-
|
|
87
|
-
const missing = baseNorm.filter(({ key }) => !localeNormSet.has(key));
|
|
88
|
-
|
|
89
|
-
if (missing.length > 0) {
|
|
90
|
-
totalMissing += missing.length;
|
|
91
|
-
const entry = {
|
|
92
|
-
agent,
|
|
93
|
-
locale,
|
|
94
|
-
missingSections: missing.map(m => m.original)
|
|
95
|
-
};
|
|
96
|
-
report.push(entry);
|
|
97
|
-
if (!jsonMode) {
|
|
98
|
-
log(`@${agent} (${locale}) — ${missing.length} section(s) missing in locale:`);
|
|
99
|
-
for (const m of missing) {
|
|
100
|
-
log(` - ${m.original}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
6
|
+
const requestedAgent = args[0] || null;
|
|
7
|
+
const requestedLanguage = options.lang || options.language || null;
|
|
106
8
|
|
|
107
9
|
if (!jsonMode) {
|
|
108
|
-
log('');
|
|
109
|
-
|
|
110
|
-
log('No drift detected — all locale files contain equivalent sections to base.');
|
|
111
|
-
} else {
|
|
112
|
-
log(`${totalMissing} section(s) present in base but missing in locale files.`);
|
|
113
|
-
log('These may be intentional simplifications or unintentional drift.');
|
|
114
|
-
}
|
|
10
|
+
log('Agent locale packs are no longer shipped.');
|
|
11
|
+
log('Canonical agent prompts now live only in `.aioson/agents/` and user-facing language is controlled by `interaction_language`.');
|
|
115
12
|
}
|
|
116
13
|
|
|
117
14
|
return {
|
|
118
|
-
ok:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
15
|
+
ok: true,
|
|
16
|
+
deprecated: true,
|
|
17
|
+
mode: 'canonical-english-only',
|
|
18
|
+
agent: requestedAgent,
|
|
19
|
+
language: requestedLanguage,
|
|
20
|
+
totalMissing: 0,
|
|
21
|
+
drifts: []
|
|
123
22
|
};
|
|
124
23
|
}
|
|
125
24
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('node:fs/promises');
|
|
4
4
|
const path = require('node:path');
|
|
5
|
-
const { validateProjectContextFile } = require('../context');
|
|
5
|
+
const { validateProjectContextFile, getInteractionLanguage } = require('../context');
|
|
6
6
|
const { localizeContextParseReason } = require('../context-parse-reason');
|
|
7
7
|
const { exists, readTextIfExists } = require('../utils');
|
|
8
8
|
const { extractStackValue, normalizeDatabaseEngine } = require('./mcp-init');
|
|
@@ -354,6 +354,7 @@ async function runMcpDoctor({ args, options = {}, logger, t }) {
|
|
|
354
354
|
filePath: contextPath,
|
|
355
355
|
projectType: String(contextData.project_type || ''),
|
|
356
356
|
framework: String(contextData.framework || ''),
|
|
357
|
+
interactionLanguage: getInteractionLanguage(contextData, 'en'),
|
|
357
358
|
conversationLanguage: String(contextData.conversation_language || '')
|
|
358
359
|
},
|
|
359
360
|
plan: {
|
package/src/commands/mcp-init.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('node:fs/promises');
|
|
4
4
|
const path = require('node:path');
|
|
5
|
-
const { validateProjectContextFile } = require('../context');
|
|
5
|
+
const { validateProjectContextFile, getInteractionLanguage } = require('../context');
|
|
6
6
|
const { createTranslator } = require('../i18n');
|
|
7
7
|
const { ensureDir, readTextIfExists } = require('../utils');
|
|
8
8
|
|
|
@@ -151,14 +151,7 @@ function buildMcpPlan(targetDir, contextData, contextMarkdown, t) {
|
|
|
151
151
|
reason: translate('mcp_init.reason_web_search'),
|
|
152
152
|
env: []
|
|
153
153
|
},
|
|
154
|
-
buildChainRpcServer(web3Enabled, networks, t)
|
|
155
|
-
{
|
|
156
|
-
id: 'makopy',
|
|
157
|
-
enabled: false,
|
|
158
|
-
recommended: false,
|
|
159
|
-
reason: translate('mcp_init.reason_makopy'),
|
|
160
|
-
env: ['MAKOPY_API_KEY']
|
|
161
|
-
}
|
|
154
|
+
buildChainRpcServer(web3Enabled, networks, t)
|
|
162
155
|
];
|
|
163
156
|
|
|
164
157
|
return {
|
|
@@ -167,7 +160,8 @@ function buildMcpPlan(targetDir, contextData, contextMarkdown, t) {
|
|
|
167
160
|
path: targetDir,
|
|
168
161
|
framework: contextData.framework || '',
|
|
169
162
|
project_type: contextData.project_type || '',
|
|
170
|
-
|
|
163
|
+
interaction_language: getInteractionLanguage(contextData, 'en'),
|
|
164
|
+
conversation_language: getInteractionLanguage(contextData, 'en')
|
|
171
165
|
},
|
|
172
166
|
database_engine: databaseEngine,
|
|
173
167
|
web3_enabled: web3Enabled,
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { openRuntimeDb } = require('../runtime-store');
|
|
6
|
+
|
|
7
|
+
const REQUIRED_BOOTSTRAP = ['what-is.md', 'what-it-does.md', 'how-it-works.md', 'current-state.md'];
|
|
8
|
+
|
|
9
|
+
async function fileExists(filePath) {
|
|
10
|
+
try {
|
|
11
|
+
const stat = await fs.stat(filePath);
|
|
12
|
+
return stat.isFile();
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function readText(filePath) {
|
|
19
|
+
try {
|
|
20
|
+
return await fs.readFile(filePath, 'utf8');
|
|
21
|
+
} catch {
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function listFiles(dirPath, predicate = () => true) {
|
|
27
|
+
try {
|
|
28
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
29
|
+
return entries
|
|
30
|
+
.filter((entry) => entry.isFile() && predicate(entry.name))
|
|
31
|
+
.map((entry) => entry.name)
|
|
32
|
+
.sort();
|
|
33
|
+
} catch {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function firstLine(text) {
|
|
39
|
+
const withoutFrontmatter = String(text || '').replace(/^---[\s\S]*?---\r?\n?/, '');
|
|
40
|
+
return withoutFrontmatter
|
|
41
|
+
.split(/\r?\n/)
|
|
42
|
+
.map((line) => line.trim())
|
|
43
|
+
.find((line) => line && !line.startsWith('#')) || '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function collectRuntimeSummary(targetDir) {
|
|
47
|
+
let handle;
|
|
48
|
+
try {
|
|
49
|
+
handle = await openRuntimeDb(targetDir, { mustExist: true });
|
|
50
|
+
} catch {
|
|
51
|
+
return { exists: false, taskCounts: {}, recentRuns: [], learnings: 0 };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!handle || !handle.db) {
|
|
55
|
+
return { exists: false, taskCounts: {}, recentRuns: [], learnings: 0 };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const { db, dbPath } = handle;
|
|
59
|
+
try {
|
|
60
|
+
const rows = db.prepare('SELECT status, COUNT(*) AS count FROM tasks GROUP BY status').all();
|
|
61
|
+
const taskCounts = {};
|
|
62
|
+
for (const row of rows) taskCounts[row.status] = Number(row.count || 0);
|
|
63
|
+
|
|
64
|
+
const recentRuns = db.prepare(`
|
|
65
|
+
SELECT agent_name, status, summary, title, finished_at, updated_at
|
|
66
|
+
FROM agent_runs
|
|
67
|
+
ORDER BY COALESCE(finished_at, updated_at, started_at) DESC
|
|
68
|
+
LIMIT 8
|
|
69
|
+
`).all();
|
|
70
|
+
|
|
71
|
+
let learnings = 0;
|
|
72
|
+
try {
|
|
73
|
+
const row = db.prepare("SELECT COUNT(*) AS count FROM project_learnings WHERE status = 'active'").get();
|
|
74
|
+
learnings = Number(row?.count || 0);
|
|
75
|
+
} catch {
|
|
76
|
+
learnings = 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { exists: true, dbPath, taskCounts, recentRuns, learnings };
|
|
80
|
+
} finally {
|
|
81
|
+
db.close();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function collectMemoryStatus(targetDir) {
|
|
86
|
+
const bootstrapDir = path.join(targetDir, '.aioson', 'context', 'bootstrap');
|
|
87
|
+
const bootstrapFiles = [];
|
|
88
|
+
for (const name of REQUIRED_BOOTSTRAP) {
|
|
89
|
+
bootstrapFiles.push({
|
|
90
|
+
path: `.aioson/context/bootstrap/${name}`,
|
|
91
|
+
exists: await fileExists(path.join(bootstrapDir, name))
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const memoryIndexPath = path.join(targetDir, '.aioson', 'context', 'memory-index.md');
|
|
96
|
+
const contextPackPath = path.join(targetDir, '.aioson', 'context', 'context-pack.md');
|
|
97
|
+
const projectPulsePath = path.join(targetDir, '.aioson', 'context', 'project-pulse.md');
|
|
98
|
+
const logsDir = path.join(targetDir, 'aioson-logs');
|
|
99
|
+
const devlogs = await listFiles(logsDir, (name) => name.startsWith('devlog-') && name.endsWith('.md'));
|
|
100
|
+
const devlogManifestPath = path.join(logsDir, 'manifest.md');
|
|
101
|
+
|
|
102
|
+
const brainsDir = path.join(targetDir, '.aioson', 'brains');
|
|
103
|
+
const brainIndexPath = path.join(brainsDir, '_index.json');
|
|
104
|
+
let brainIndex = null;
|
|
105
|
+
const brainWarnings = [];
|
|
106
|
+
try {
|
|
107
|
+
brainIndex = JSON.parse(await fs.readFile(brainIndexPath, 'utf8'));
|
|
108
|
+
} catch {
|
|
109
|
+
brainWarnings.push(`Missing or invalid ${path.relative(targetDir, brainIndexPath)}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const brains = Array.isArray(brainIndex?.brains) ? brainIndex.brains : [];
|
|
113
|
+
for (const brain of brains) {
|
|
114
|
+
const rel = String(brain.path || '');
|
|
115
|
+
const brainPath = rel.startsWith('.aioson/brains/')
|
|
116
|
+
? path.join(targetDir, rel)
|
|
117
|
+
: path.join(brainsDir, rel);
|
|
118
|
+
if (!(await fileExists(brainPath))) {
|
|
119
|
+
brainWarnings.push(`Missing brain file: ${rel || brain.id || '(unknown)'}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const runtime = await collectRuntimeSummary(targetDir);
|
|
124
|
+
const bootstrapCoverage = bootstrapFiles.filter((file) => file.exists).length;
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
ok: bootstrapCoverage === REQUIRED_BOOTSTRAP.length && brainWarnings.length === 0,
|
|
128
|
+
targetDir,
|
|
129
|
+
bootstrap: {
|
|
130
|
+
required: REQUIRED_BOOTSTRAP.length,
|
|
131
|
+
present: bootstrapCoverage,
|
|
132
|
+
missing: bootstrapFiles.filter((file) => !file.exists).map((file) => file.path),
|
|
133
|
+
files: bootstrapFiles
|
|
134
|
+
},
|
|
135
|
+
context: {
|
|
136
|
+
memoryIndex: await fileExists(memoryIndexPath),
|
|
137
|
+
contextPack: await fileExists(contextPackPath),
|
|
138
|
+
projectPulse: await fileExists(projectPulsePath)
|
|
139
|
+
},
|
|
140
|
+
devlogs: {
|
|
141
|
+
count: devlogs.length,
|
|
142
|
+
manifest: await fileExists(devlogManifestPath),
|
|
143
|
+
files: devlogs.map((name) => `aioson-logs/${name}`)
|
|
144
|
+
},
|
|
145
|
+
brains: {
|
|
146
|
+
index: await fileExists(brainIndexPath),
|
|
147
|
+
count: brains.length,
|
|
148
|
+
files: brains.map((brain) => brain.path).filter(Boolean),
|
|
149
|
+
warnings: brainWarnings
|
|
150
|
+
},
|
|
151
|
+
runtime
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function formatTaskCounts(counts) {
|
|
156
|
+
const entries = Object.entries(counts || {});
|
|
157
|
+
if (entries.length === 0) return 'none';
|
|
158
|
+
return entries.map(([key, value]) => `${key}:${value}`).join(', ');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function runMemoryStatus({ args, options = {}, logger }) {
|
|
162
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
163
|
+
const status = await collectMemoryStatus(targetDir);
|
|
164
|
+
|
|
165
|
+
if (options.json) return status;
|
|
166
|
+
|
|
167
|
+
logger.log('AIOSON Memory Status');
|
|
168
|
+
logger.log(`Bootstrap: ${status.bootstrap.present}/${status.bootstrap.required}`);
|
|
169
|
+
if (status.bootstrap.missing.length > 0) {
|
|
170
|
+
logger.log(`Missing bootstrap: ${status.bootstrap.missing.join(', ')}`);
|
|
171
|
+
}
|
|
172
|
+
logger.log(`Memory index: ${status.context.memoryIndex ? 'present' : 'missing'}`);
|
|
173
|
+
logger.log(`Context pack: ${status.context.contextPack ? 'present' : 'missing'}`);
|
|
174
|
+
logger.log(`Project pulse: ${status.context.projectPulse ? 'present' : 'missing'}`);
|
|
175
|
+
logger.log(`Devlogs: ${status.devlogs.count} (${status.devlogs.manifest ? 'manifest present' : 'no manifest'})`);
|
|
176
|
+
logger.log(`Brains: ${status.brains.count} indexed${status.brains.warnings.length ? `, ${status.brains.warnings.length} warning(s)` : ''}`);
|
|
177
|
+
for (const warning of status.brains.warnings) logger.log(`- ${warning}`);
|
|
178
|
+
logger.log(`Runtime: ${status.runtime.exists ? formatTaskCounts(status.runtime.taskCounts) : 'missing'}`);
|
|
179
|
+
logger.log(`Active learnings: ${status.runtime.learnings || 0}`);
|
|
180
|
+
return status;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function runMemorySummary({ args, options = {}, logger }) {
|
|
184
|
+
const targetDir = path.resolve(process.cwd(), args[0] || '.');
|
|
185
|
+
const status = await collectMemoryStatus(targetDir);
|
|
186
|
+
const pulse = await readText(path.join(targetDir, '.aioson', 'context', 'project-pulse.md'));
|
|
187
|
+
const whatIs = await readText(path.join(targetDir, '.aioson', 'context', 'bootstrap', 'what-is.md'));
|
|
188
|
+
const currentState = await readText(path.join(targetDir, '.aioson', 'context', 'bootstrap', 'current-state.md'));
|
|
189
|
+
|
|
190
|
+
const recentRuns = (status.runtime.recentRuns || []).slice(0, Number(options.last || 5));
|
|
191
|
+
const lines = [
|
|
192
|
+
'# AIOSON Memory Summary',
|
|
193
|
+
'',
|
|
194
|
+
'## Bootstrap',
|
|
195
|
+
`- Coverage: ${status.bootstrap.present}/${status.bootstrap.required}`,
|
|
196
|
+
`- Identity: ${firstLine(whatIs) || 'not available'}`,
|
|
197
|
+
`- Current state: ${firstLine(currentState) || 'not available'}`,
|
|
198
|
+
'',
|
|
199
|
+
'## Project Pulse',
|
|
200
|
+
pulse ? pulse.split(/\r?\n/).slice(0, 28).join('\n') : '_No project-pulse.md found_',
|
|
201
|
+
'',
|
|
202
|
+
'## Recent Runtime',
|
|
203
|
+
status.runtime.exists
|
|
204
|
+
? `- Tasks: ${formatTaskCounts(status.runtime.taskCounts)}`
|
|
205
|
+
: '- Runtime database missing',
|
|
206
|
+
`- Active learnings: ${status.runtime.learnings || 0}`
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
if (recentRuns.length > 0) {
|
|
210
|
+
lines.push('', '## Recent Runs');
|
|
211
|
+
for (const run of recentRuns) {
|
|
212
|
+
const when = run.finished_at || run.updated_at || '';
|
|
213
|
+
const summary = run.summary || run.title || '(no summary)';
|
|
214
|
+
lines.push(`- ${when} ${run.agent_name}: ${summary}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
lines.push('', '## Retrieval Hints');
|
|
219
|
+
lines.push('- Use `aioson context:pack . --agent=<agent> --goal="<task>"` for focused project context.');
|
|
220
|
+
lines.push('- Use `aioson brain:query . --tags=<tags> --min-quality=4` for procedural patterns.');
|
|
221
|
+
lines.push('- Use Git only when memory and runtime do not explain recent work.');
|
|
222
|
+
|
|
223
|
+
const summary = lines.join('\n');
|
|
224
|
+
if (options.json) return { ok: true, status, summary };
|
|
225
|
+
logger.log(summary);
|
|
226
|
+
return { ok: true, status, summary };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
module.exports = {
|
|
230
|
+
REQUIRED_BOOTSTRAP,
|
|
231
|
+
collectMemoryStatus,
|
|
232
|
+
runMemoryStatus,
|
|
233
|
+
runMemorySummary
|
|
234
|
+
};
|
|
@@ -6,6 +6,20 @@ const { validateProjectContextFile } = require('../context');
|
|
|
6
6
|
const { exists, toRelativeSafe } = require('../utils');
|
|
7
7
|
const { parseWorkers, normalizeClassification } = require('./parallel-init');
|
|
8
8
|
const { recordRuntimeOperation } = require('../execution-gateway');
|
|
9
|
+
const {
|
|
10
|
+
WORKSPACE_MANIFEST_RELATIVE_PATH,
|
|
11
|
+
OWNERSHIP_MAP_RELATIVE_PATH,
|
|
12
|
+
MERGE_PLAN_RELATIVE_PATH,
|
|
13
|
+
buildLaneOwnershipEntries,
|
|
14
|
+
buildWorkspaceManifest,
|
|
15
|
+
buildOwnershipMap,
|
|
16
|
+
buildMergePlan,
|
|
17
|
+
extractStatusDependencyItems,
|
|
18
|
+
extractStatusWritePathItems,
|
|
19
|
+
extractStatusMergeRank,
|
|
20
|
+
replaceSection,
|
|
21
|
+
replaceMetadataLine
|
|
22
|
+
} = require('../parallel-workspace');
|
|
9
23
|
|
|
10
24
|
const SOURCE_ALIAS = {
|
|
11
25
|
prd: '.aioson/context/prd.md',
|
|
@@ -164,30 +178,11 @@ function distributeScopes(scopes, workers) {
|
|
|
164
178
|
}
|
|
165
179
|
|
|
166
180
|
function replaceScopeSection(content, items) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (start === -1) {
|
|
173
|
-
const suffix = lines.length > 0 && lines[lines.length - 1] === '' ? '' : '\n';
|
|
174
|
-
return `${text}${suffix}\n## Scope\n${scopeLines.join('\n')}\n`;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
let end = lines.length;
|
|
178
|
-
for (let i = start + 1; i < lines.length; i += 1) {
|
|
179
|
-
if (lines[i].startsWith('## ')) {
|
|
180
|
-
end = i;
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const replaced = [
|
|
186
|
-
...lines.slice(0, start + 1),
|
|
187
|
-
...scopeLines,
|
|
188
|
-
...lines.slice(end)
|
|
189
|
-
];
|
|
190
|
-
return `${replaced.join('\n').replace(/\n*$/, '\n')}`;
|
|
181
|
+
return replaceSection(
|
|
182
|
+
content,
|
|
183
|
+
'Scope',
|
|
184
|
+
items.length > 0 ? items.map((item) => `- ${item}`) : ['- [unassigned]']
|
|
185
|
+
);
|
|
191
186
|
}
|
|
192
187
|
|
|
193
188
|
function updateTimestamp(content, generatedAt) {
|
|
@@ -198,6 +193,13 @@ function updateTimestamp(content, generatedAt) {
|
|
|
198
193
|
return text;
|
|
199
194
|
}
|
|
200
195
|
|
|
196
|
+
function extractMetadata(content, key, fallback = '') {
|
|
197
|
+
const regex = new RegExp(`^-\\s*${key}:\\s*(.*)$`, 'im');
|
|
198
|
+
const match = String(content || '').match(regex);
|
|
199
|
+
if (!match) return fallback;
|
|
200
|
+
return String(match[1] || '').trim() || fallback;
|
|
201
|
+
}
|
|
202
|
+
|
|
201
203
|
function appendSharedDecision(content, generatedAt, sourcePath, workers, scopeCount) {
|
|
202
204
|
const row =
|
|
203
205
|
`| ${generatedAt} | Scope assignment initialized | ` +
|
|
@@ -290,19 +292,90 @@ async function runParallelAssign({ args, options = {}, logger, t }) {
|
|
|
290
292
|
const assignments = distributeScopes(extracted.scopes, workers);
|
|
291
293
|
const generatedAt = new Date().toISOString();
|
|
292
294
|
const filesUpdated = [];
|
|
295
|
+
const projectName =
|
|
296
|
+
String((context.data && context.data.project_name) || '').trim() || path.basename(targetDir) || 'project';
|
|
297
|
+
const laneStatusByIndex = new Map();
|
|
298
|
+
const enrichedAssignments = [];
|
|
293
299
|
|
|
294
300
|
for (const lane of assignments) {
|
|
295
301
|
const rel = `.aioson/context/parallel/agent-${lane.lane}.status.md`;
|
|
296
302
|
const lanePath = path.join(targetDir, rel);
|
|
297
303
|
const current = await fs.readFile(lanePath, 'utf8');
|
|
304
|
+
laneStatusByIndex.set(lane.lane, current);
|
|
305
|
+
enrichedAssignments.push({
|
|
306
|
+
...lane,
|
|
307
|
+
owner: extractMetadata(current, 'owner', `lane-${lane.lane}`),
|
|
308
|
+
dependsOn: extractStatusDependencyItems(current),
|
|
309
|
+
writePaths: extractStatusWritePathItems(current),
|
|
310
|
+
mergeRank: extractStatusMergeRank(current, lane.lane)
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const laneEntries = buildLaneOwnershipEntries(enrichedAssignments);
|
|
315
|
+
|
|
316
|
+
for (const lane of assignments) {
|
|
317
|
+
const rel = `.aioson/context/parallel/agent-${lane.lane}.status.md`;
|
|
318
|
+
const lanePath = path.join(targetDir, rel);
|
|
319
|
+
const current = laneStatusByIndex.get(lane.lane);
|
|
320
|
+
const laneEntry = laneEntries.find((item) => item.lane === lane.lane);
|
|
298
321
|
let next = replaceScopeSection(current, lane.items);
|
|
299
322
|
next = updateTimestamp(next, generatedAt);
|
|
323
|
+
next = replaceMetadataLine(next, 'owner', laneEntry.owner);
|
|
324
|
+
next = replaceSection(next, 'Ownership', [
|
|
325
|
+
`- lane_key: ${laneEntry.lane_key}`,
|
|
326
|
+
`- scope_keys: ${laneEntry.scope_keys.length > 0 ? laneEntry.scope_keys.join(', ') : '[unassigned]'}`,
|
|
327
|
+
`- write_scope: ${laneEntry.scope_labels.length > 0 ? laneEntry.scope_labels.join(' | ') : '[unassigned]'}`,
|
|
328
|
+
`- write_paths: ${laneEntry.write_paths.length > 0 ? laneEntry.write_paths.join(', ') : '[unassigned]'}`
|
|
329
|
+
]);
|
|
330
|
+
next = replaceSection(next, 'Merge', [
|
|
331
|
+
`- merge_rank: ${laneEntry.merge_rank}`,
|
|
332
|
+
'- merge_strategy: lane-index-asc'
|
|
333
|
+
]);
|
|
300
334
|
if (!dryRun) {
|
|
301
335
|
await fs.writeFile(lanePath, next, 'utf8');
|
|
302
336
|
}
|
|
303
337
|
filesUpdated.push(rel);
|
|
304
338
|
}
|
|
305
339
|
|
|
340
|
+
const workspaceManifest = buildWorkspaceManifest({
|
|
341
|
+
projectName,
|
|
342
|
+
classification: classification || 'MEDIUM',
|
|
343
|
+
workers,
|
|
344
|
+
generatedAt,
|
|
345
|
+
lanes: laneEntries,
|
|
346
|
+
sourceFile: sourceFile.relPath
|
|
347
|
+
});
|
|
348
|
+
const ownershipMap = buildOwnershipMap({
|
|
349
|
+
generatedAt,
|
|
350
|
+
lanes: laneEntries
|
|
351
|
+
});
|
|
352
|
+
const mergePlan = buildMergePlan({
|
|
353
|
+
generatedAt,
|
|
354
|
+
lanes: laneEntries,
|
|
355
|
+
sourceFile: sourceFile.relPath
|
|
356
|
+
});
|
|
357
|
+
const machineFiles = [
|
|
358
|
+
{
|
|
359
|
+
rel: WORKSPACE_MANIFEST_RELATIVE_PATH,
|
|
360
|
+
payload: workspaceManifest
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
rel: OWNERSHIP_MAP_RELATIVE_PATH,
|
|
364
|
+
payload: ownershipMap
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
rel: MERGE_PLAN_RELATIVE_PATH,
|
|
368
|
+
payload: mergePlan
|
|
369
|
+
}
|
|
370
|
+
];
|
|
371
|
+
|
|
372
|
+
for (const file of machineFiles) {
|
|
373
|
+
if (!dryRun) {
|
|
374
|
+
await fs.writeFile(path.join(targetDir, file.rel), `${JSON.stringify(file.payload, null, 2)}\n`, 'utf8');
|
|
375
|
+
}
|
|
376
|
+
filesUpdated.push(file.rel);
|
|
377
|
+
}
|
|
378
|
+
|
|
306
379
|
const sharedPath = path.join(parallelDir, 'shared-decisions.md');
|
|
307
380
|
if (await exists(sharedPath)) {
|
|
308
381
|
const sharedContent = await fs.readFile(sharedPath, 'utf8');
|
|
@@ -335,9 +408,15 @@ async function runParallelAssign({ args, options = {}, logger, t }) {
|
|
|
335
408
|
assignments: assignments.map((item) => ({
|
|
336
409
|
lane: item.lane,
|
|
337
410
|
file: `.aioson/context/parallel/agent-${item.lane}.status.md`,
|
|
338
|
-
items: item.items
|
|
411
|
+
items: item.items,
|
|
412
|
+
writePaths: (laneEntries.find((laneEntry) => laneEntry.lane === item.lane) || {}).write_paths || []
|
|
339
413
|
})),
|
|
340
|
-
filesUpdated
|
|
414
|
+
filesUpdated,
|
|
415
|
+
machineFiles: {
|
|
416
|
+
workspaceManifest: WORKSPACE_MANIFEST_RELATIVE_PATH,
|
|
417
|
+
ownershipMap: OWNERSHIP_MAP_RELATIVE_PATH,
|
|
418
|
+
mergePlan: MERGE_PLAN_RELATIVE_PATH
|
|
419
|
+
}
|
|
341
420
|
};
|
|
342
421
|
|
|
343
422
|
if (!dryRun) {
|
|
@@ -361,7 +440,8 @@ async function runParallelAssign({ args, options = {}, logger, t }) {
|
|
|
361
440
|
extractionMethod: output.extractionMethod,
|
|
362
441
|
fallbackUsed: output.fallbackUsed,
|
|
363
442
|
scopeCount: output.scopeCount,
|
|
364
|
-
filesUpdated
|
|
443
|
+
filesUpdated,
|
|
444
|
+
machineFiles: output.machineFiles
|
|
365
445
|
}
|
|
366
446
|
});
|
|
367
447
|
}
|