@jaimevalasek/aioson 1.3.0 → 1.5.1
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 +31 -1
- package/LICENSE +661 -21
- package/README.md +22 -3
- package/docs/en/squad-dashboard.md +372 -0
- package/docs/openclaw-bridge.md +308 -0
- package/docs/pt/README.md +62 -2
- package/docs/pt/advisor-spec.md +5 -5
- package/docs/pt/agentes-customizados.md +670 -0
- package/docs/pt/agentes.md +235 -23
- package/docs/pt/automacao-squads.md +407 -0
- package/docs/pt/cenarios.md +49 -5
- package/docs/pt/clientes-ai.md +62 -0
- package/docs/pt/comandos-cli.md +226 -17
- package/docs/pt/deyvin.md +115 -0
- package/docs/pt/genome-3.0-spec.md +11 -11
- package/docs/pt/inicio-rapido.md +63 -2
- package/docs/pt/memoria-contexto.md +255 -0
- package/docs/pt/output-strategy-delivery.md +655 -0
- package/docs/pt/profiler-system.md +17 -17
- package/docs/pt/runtime-observability.md +5 -1
- package/docs/pt/skills.md +175 -0
- package/docs/pt/squad-dashboard.md +373 -0
- package/docs/pt/{squad-genoma.md → squad-genome.md} +81 -75
- package/docs/testing/genome-2.0-matrix.md +5 -5
- package/docs/testing/genome-2.0-rollout.md +10 -10
- package/package.json +4 -4
- package/src/agents.js +21 -5
- package/src/backup-local.js +74 -0
- package/src/backup-provider.js +303 -0
- package/src/cli.js +276 -2
- package/src/commands/agents.js +22 -4
- package/src/commands/backup-local-cmd.js +25 -0
- package/src/commands/backup.js +533 -0
- package/src/commands/cloud.js +17 -17
- package/src/commands/context-pack.js +45 -0
- package/src/commands/implementation-plan.js +340 -0
- package/src/commands/learning.js +134 -0
- package/src/commands/live.js +1583 -0
- package/src/commands/runtime.js +1075 -2
- package/src/commands/scan-project.js +288 -24
- package/src/commands/setup-context.js +30 -2
- package/src/commands/skill.js +558 -0
- package/src/commands/squad-agent-create.js +788 -0
- package/src/commands/squad-daemon.js +209 -0
- package/src/commands/squad-dashboard.js +39 -0
- package/src/commands/squad-deploy.js +64 -0
- package/src/commands/squad-doctor.js +103 -1
- package/src/commands/squad-investigate.js +261 -0
- package/src/commands/squad-learning.js +209 -0
- package/src/commands/squad-mcp.js +270 -0
- package/src/commands/squad-pipeline.js +247 -1
- package/src/commands/squad-plan.js +329 -0
- package/src/commands/squad-processes.js +56 -0
- package/src/commands/squad-recovery.js +42 -0
- package/src/commands/squad-roi.js +291 -0
- package/src/commands/squad-score.js +250 -0
- package/src/commands/squad-status.js +38 -2
- package/src/commands/squad-validate.js +118 -1
- package/src/commands/squad-webhook.js +160 -0
- package/src/commands/squad-worker.js +191 -0
- package/src/commands/squad-worktrees.js +75 -0
- package/src/commands/test-agents.js +6 -1
- package/src/commands/web-map.js +70 -0
- package/src/commands/web-scrape.js +71 -0
- package/src/commands/workflow-next.js +8 -1
- package/src/commands/workflow-status.js +250 -0
- package/src/constants.js +88 -16
- package/src/context-memory.js +837 -0
- package/src/context-writer.js +47 -1
- package/src/delivery-runner.js +319 -0
- package/src/genome-files.js +1 -1
- package/src/genome-format.js +1 -1
- package/src/i18n/messages/en.js +333 -8
- package/src/i18n/messages/es.js +240 -6
- package/src/i18n/messages/fr.js +239 -5
- package/src/i18n/messages/pt-BR.js +330 -12
- package/src/installer.js +30 -2
- package/src/lib/genomes/compat.js +1 -1
- package/src/lib/webhook-server.js +328 -0
- package/src/mcp-connectors/registry.js +602 -0
- package/src/runtime-store.js +1037 -42
- package/src/session-handoff.js +77 -0
- package/src/squad/external-session.js +180 -0
- package/src/squad/inter-squad.js +74 -0
- package/src/squad/recovery-context.js +201 -0
- package/src/squad/worktree-manager.js +114 -0
- package/src/squad-daemon.js +490 -0
- package/src/squad-dashboard/api.js +223 -0
- package/src/squad-dashboard/attachment-handler.js +93 -0
- package/src/squad-dashboard/context-monitor.js +157 -0
- package/src/squad-dashboard/execution-logs.js +115 -0
- package/src/squad-dashboard/hunk-review.js +209 -0
- package/src/squad-dashboard/metrics.js +133 -0
- package/src/squad-dashboard/process-monitor.js +125 -0
- package/src/squad-dashboard/renderer.js +858 -0
- package/src/squad-dashboard/server.js +232 -0
- package/src/squad-dashboard/styles.js +525 -0
- package/src/squad-dashboard/token-tracker.js +99 -0
- package/src/web.js +284 -0
- package/src/worker-runner.js +339 -0
- package/template/.aioson/agents/analyst.md +40 -9
- package/template/.aioson/agents/architect.md +24 -5
- package/template/.aioson/agents/dev.md +254 -25
- package/template/.aioson/agents/deyvin.md +174 -0
- package/template/.aioson/agents/discovery-design-doc.md +25 -1
- package/template/.aioson/agents/{genoma.md → genome.md} +20 -20
- package/template/.aioson/agents/neo.md +152 -0
- package/template/.aioson/agents/orache.md +388 -0
- package/template/.aioson/agents/orchestrator.md +63 -2
- package/template/.aioson/agents/pair.md +5 -0
- package/template/.aioson/agents/pm.md +17 -5
- package/template/.aioson/agents/product.md +113 -29
- package/template/.aioson/agents/profiler-enricher.md +1 -1
- package/template/.aioson/agents/profiler-forge.md +9 -9
- package/template/.aioson/agents/profiler-researcher.md +1 -1
- package/template/.aioson/agents/qa.md +18 -5
- package/template/.aioson/agents/setup.md +138 -18
- package/template/.aioson/agents/sheldon.md +603 -0
- package/template/.aioson/agents/squad.md +866 -28
- package/template/.aioson/agents/tester.md +254 -0
- package/template/.aioson/agents/ux-ui.md +289 -34
- package/template/.aioson/config.md +181 -0
- package/template/.aioson/context/spec.md.template +17 -0
- package/template/.aioson/genomes/.gitkeep +0 -0
- package/template/.aioson/installed-skills/.gitkeep +0 -0
- package/template/.aioson/locales/en/agents/analyst.md +34 -4
- package/template/.aioson/locales/en/agents/architect.md +18 -0
- package/template/.aioson/locales/en/agents/dev.md +155 -11
- package/template/.aioson/locales/en/agents/deyvin.md +137 -0
- package/template/.aioson/locales/en/agents/{genoma.md → genome.md} +14 -14
- package/template/.aioson/locales/en/agents/neo.md +8 -0
- package/template/.aioson/locales/en/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/en/agents/pair.md +5 -0
- package/template/.aioson/locales/en/agents/pm.md +7 -0
- package/template/.aioson/locales/en/agents/product.md +35 -17
- package/template/.aioson/locales/en/agents/qa.md +56 -0
- package/template/.aioson/locales/en/agents/setup.md +53 -6
- package/template/.aioson/locales/en/agents/sheldon.md +340 -0
- package/template/.aioson/locales/en/agents/squad.md +203 -15
- package/template/.aioson/locales/en/agents/ux-ui.md +383 -35
- package/template/.aioson/locales/es/agents/analyst.md +24 -4
- package/template/.aioson/locales/es/agents/architect.md +18 -0
- package/template/.aioson/locales/es/agents/dev.md +136 -9
- package/template/.aioson/locales/es/agents/deyvin.md +97 -0
- package/template/.aioson/locales/es/agents/{genoma.md → genome.md} +13 -13
- package/template/.aioson/locales/es/agents/neo.md +48 -0
- package/template/.aioson/locales/es/agents/orache.md +103 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/es/agents/pair.md +5 -0
- package/template/.aioson/locales/es/agents/pm.md +7 -0
- package/template/.aioson/locales/es/agents/product.md +13 -3
- package/template/.aioson/locales/es/agents/qa.md +33 -0
- package/template/.aioson/locales/es/agents/setup.md +30 -6
- package/template/.aioson/locales/es/agents/sheldon.md +192 -0
- package/template/.aioson/locales/es/agents/squad.md +284 -15
- package/template/.aioson/locales/es/agents/ux-ui.md +34 -25
- package/template/.aioson/locales/fr/agents/analyst.md +24 -4
- package/template/.aioson/locales/fr/agents/architect.md +18 -0
- package/template/.aioson/locales/fr/agents/dev.md +136 -9
- package/template/.aioson/locales/fr/agents/deyvin.md +97 -0
- package/template/.aioson/locales/fr/agents/{genoma.md → genome.md} +7 -7
- package/template/.aioson/locales/fr/agents/neo.md +48 -0
- package/template/.aioson/locales/fr/agents/orache.md +104 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/fr/agents/pair.md +5 -0
- package/template/.aioson/locales/fr/agents/pm.md +7 -0
- package/template/.aioson/locales/fr/agents/product.md +13 -3
- package/template/.aioson/locales/fr/agents/qa.md +33 -0
- package/template/.aioson/locales/fr/agents/setup.md +30 -6
- package/template/.aioson/locales/fr/agents/sheldon.md +192 -0
- package/template/.aioson/locales/fr/agents/squad.md +279 -10
- package/template/.aioson/locales/fr/agents/ux-ui.md +34 -25
- package/template/.aioson/locales/pt-BR/agents/analyst.md +45 -4
- package/template/.aioson/locales/pt-BR/agents/architect.md +29 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +167 -15
- package/template/.aioson/locales/pt-BR/agents/deyvin.md +137 -0
- package/template/.aioson/locales/pt-BR/agents/{genoma.md → genome.md} +49 -49
- package/template/.aioson/locales/pt-BR/agents/neo.md +147 -0
- package/template/.aioson/locales/pt-BR/agents/orache.md +137 -0
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +62 -2
- package/template/.aioson/locales/pt-BR/agents/pair.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/pm.md +7 -0
- package/template/.aioson/locales/pt-BR/agents/product.md +43 -20
- package/template/.aioson/locales/pt-BR/agents/qa.md +67 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +53 -6
- package/template/.aioson/locales/pt-BR/agents/sheldon.md +192 -0
- package/template/.aioson/locales/pt-BR/agents/squad.md +591 -47
- package/template/.aioson/locales/pt-BR/agents/ux-ui.md +369 -22
- package/template/.aioson/my-agents/.gitkeep +0 -0
- package/template/.aioson/rules/.gitkeep +0 -0
- package/template/.aioson/rules/squad/.gitkeep +0 -0
- package/template/.aioson/rules/squad/README.md +50 -0
- package/template/.aioson/schemas/genome-meta.schema.json +1 -1
- package/template/.aioson/schemas/genome.schema.json +1 -1
- package/template/.aioson/schemas/squad-blueprint.schema.json +32 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +434 -1
- package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +205 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -0
- package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -0
- package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +210 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -0
- package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -0
- package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +203 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +407 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +272 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +524 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +277 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +289 -0
- package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +437 -0
- package/template/.aioson/skills/design/interface-design/SKILL.md +47 -0
- package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -0
- package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -0
- package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +71 -0
- package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -0
- package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -0
- package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +62 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -0
- package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -0
- package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +209 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -0
- package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -0
- package/template/.aioson/skills/design-system/SKILL.md +92 -0
- package/template/.aioson/skills/design-system/cognitive-core-ui.skill +0 -0
- package/template/.aioson/skills/design-system/components/SKILL.md +274 -0
- package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md +184 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md +250 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md +197 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md +231 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/premium-visual-design/SKILL.md +83 -0
- package/template/.aioson/skills/premium-visual-design/components/agent-badge.md +92 -0
- package/template/.aioson/skills/premium-visual-design/components/dependency-node.md +102 -0
- package/template/.aioson/skills/premium-visual-design/components/mention-autocomplete.md +136 -0
- package/template/.aioson/skills/premium-visual-design/components/notification-center.md +136 -0
- package/template/.aioson/skills/premium-visual-design/components/review-action-bar.md +188 -0
- package/template/.aioson/skills/premium-visual-design/components/team-switcher.md +131 -0
- package/template/.aioson/skills/premium-visual-design/patterns/agent-message-thread.md +198 -0
- package/template/.aioson/skills/premium-visual-design/patterns/notification-panel.md +275 -0
- package/template/.aioson/skills/premium-visual-design/patterns/review-workflow-ui.md +234 -0
- package/template/.aioson/skills/premium-visual-design/patterns/task-dependency-graph.md +147 -0
- package/template/.aioson/skills/premium-visual-design/tokens/status-extended.md +142 -0
- package/template/.aioson/skills/squad/SKILL.md +58 -0
- package/template/.aioson/skills/squad/domains/.gitkeep +0 -0
- package/template/.aioson/skills/squad/formats/.gitkeep +0 -0
- package/template/.aioson/skills/squad/formats/catalog.json +15 -0
- package/template/.aioson/skills/squad/formats/content/blog-post.md +47 -0
- package/template/.aioson/skills/squad/formats/content/newsletter.md +47 -0
- package/template/.aioson/skills/squad/formats/creative/podcast-script.md +43 -0
- package/template/.aioson/skills/squad/formats/creative/video-script.md +41 -0
- package/template/.aioson/skills/squad/formats/social/instagram-feed.md +42 -0
- package/template/.aioson/skills/squad/formats/social/linkedin-post.md +42 -0
- package/template/.aioson/skills/squad/formats/social/tiktok.md +39 -0
- package/template/.aioson/skills/squad/formats/social/twitter-thread.md +39 -0
- package/template/.aioson/skills/squad/formats/social/youtube-long.md +47 -0
- package/template/.aioson/skills/squad/formats/social/youtube-shorts.md +39 -0
- package/template/.aioson/skills/squad/patterns/.gitkeep +0 -0
- package/template/.aioson/skills/squad/patterns/multi-platform-pattern.md +108 -0
- package/template/.aioson/skills/squad/patterns/persona-based-pattern.md +98 -0
- package/template/.aioson/skills/squad/patterns/pipeline-pattern.md +106 -0
- package/template/.aioson/skills/squad/patterns/review-loop-pattern.md +81 -0
- package/template/.aioson/skills/squad/references/.gitkeep +0 -0
- package/template/.aioson/skills/squad/references/checklist-templates.md +122 -0
- package/template/.aioson/skills/squad/references/executor-archetypes.md +123 -0
- package/template/.aioson/skills/squad/references/workflow-templates.md +169 -0
- package/template/.aioson/skills/static/debugging-protocol.md +42 -0
- package/template/.aioson/skills/static/git-worktrees.md +36 -0
- package/template/.aioson/tasks/implementation-plan.md +307 -0
- package/template/.aioson/tasks/squad-create.md +1 -1
- package/template/.aioson/tasks/squad-design.md +28 -0
- package/template/.aioson/tasks/squad-execution-plan.md +279 -0
- package/template/.aioson/tasks/squad-export.md +1 -1
- package/template/.aioson/tasks/squad-investigate.md +44 -0
- package/template/.aioson/tasks/squad-learning-review.md +44 -0
- package/template/.aioson/tasks/squad-output-config.md +177 -0
- package/template/.aioson/tasks/squad-profile.md +48 -0
- package/template/.aioson/tasks/squad-review.md +61 -0
- package/template/.aioson/tasks/squad-task-decompose.md +66 -0
- package/template/.aioson/tasks/squad-validate.md +1 -1
- package/template/.claude/commands/aioson/agent/deyvin.md +5 -0
- package/template/.claude/commands/aioson/agent/discovery-design-doc.md +5 -0
- package/template/.claude/commands/aioson/agent/genome.md +5 -0
- package/template/.claude/commands/aioson/agent/neo.md +5 -0
- package/template/.claude/commands/aioson/agent/product.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-enricher.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-forge.md +5 -0
- package/template/.claude/commands/aioson/agent/profiler-researcher.md +5 -0
- package/template/.claude/commands/aioson/agent/squad.md +5 -0
- package/template/.claude/commands/aioson/agent/tester.md +5 -0
- package/template/.gemini/GEMINI.md +3 -0
- package/template/.gemini/commands/aios-deyvin.toml +6 -0
- package/template/.gemini/commands/aios-neo.toml +4 -0
- package/template/.gemini/commands/aios-pair.toml +6 -0
- package/template/.gemini/commands/aios-tester.toml +6 -0
- package/template/AGENTS.md +37 -6
- package/template/CLAUDE.md +34 -4
- package/template/OPENCODE.md +8 -2
- package/template/squad-searches/.gitkeep +0 -0
- package/template/.aioson/skills/static/interface-design.md +0 -372
- package/template/.aioson/skills/static/premium-command-center-ui.md +0 -190
- /package/template/.aioson/{genomas → docs}/.gitkeep +0 -0
- /package/template/.claude/commands/aioson/{analyst.md → agent/analyst.md} +0 -0
- /package/template/.claude/commands/aioson/{architect.md → agent/architect.md} +0 -0
- /package/template/.claude/commands/aioson/{dev.md → agent/dev.md} +0 -0
- /package/template/.claude/commands/aioson/{orchestrator.md → agent/orchestrator.md} +0 -0
- /package/template/.claude/commands/aioson/{pm.md → agent/pm.md} +0 -0
- /package/template/.claude/commands/aioson/{qa.md → agent/qa.md} +0 -0
- /package/template/.claude/commands/aioson/{setup.md → agent/setup.md} +0 -0
- /package/template/.claude/commands/aioson/{ux-ui.md → agent/ux-ui.md} +0 -0
|
@@ -15,7 +15,14 @@ const path = require('node:path');
|
|
|
15
15
|
const fs = require('node:fs/promises');
|
|
16
16
|
const https = require('node:https');
|
|
17
17
|
const http = require('node:http');
|
|
18
|
-
const { ensureDir, exists } = require('../utils');
|
|
18
|
+
const { ensureDir, exists, copyFileWithDir, nowStamp, toRelativeSafe } = require('../utils');
|
|
19
|
+
const { ensureGitignoreEntry, ensureProjectGitignorePolicy } = require('../installer');
|
|
20
|
+
const {
|
|
21
|
+
MEMORY_INDEX_FILE,
|
|
22
|
+
SPEC_CURRENT_FILE,
|
|
23
|
+
SPEC_HISTORY_FILE,
|
|
24
|
+
writeDerivedContextMemory
|
|
25
|
+
} = require('../context-memory');
|
|
19
26
|
|
|
20
27
|
// ── Constants ────────────────────────────────────────────────────────────────
|
|
21
28
|
|
|
@@ -29,10 +36,11 @@ const CONTEXT_FILE = '.aioson/context/project.context.md';
|
|
|
29
36
|
const SPEC_FILE = '.aioson/context/spec.md';
|
|
30
37
|
const DELIMITER = '<<<SKELETON>>>';
|
|
31
38
|
const SUMMARY_MODES = new Set(['titles', 'summaries', 'raw']);
|
|
39
|
+
const CONTEXT_MODES = new Set(['merge', 'rewrite']);
|
|
32
40
|
const FORGE_SCAN_ROOTS = [
|
|
33
41
|
'.aioson/context',
|
|
34
42
|
'.aioson/squads',
|
|
35
|
-
'.aioson/
|
|
43
|
+
'.aioson/genomes',
|
|
36
44
|
'.aioson/mcp'
|
|
37
45
|
];
|
|
38
46
|
const FORGE_SECTION_ROOTS = [
|
|
@@ -47,9 +55,9 @@ const FORGE_SECTION_ROOTS = [
|
|
|
47
55
|
empty: '_No squads detected yet_'
|
|
48
56
|
},
|
|
49
57
|
{
|
|
50
|
-
root: '.aioson/
|
|
51
|
-
title: '
|
|
52
|
-
empty: '_No
|
|
58
|
+
root: '.aioson/genomes',
|
|
59
|
+
title: 'Genomes',
|
|
60
|
+
empty: '_No genomes detected yet_'
|
|
53
61
|
},
|
|
54
62
|
{
|
|
55
63
|
root: '.aioson/mcp',
|
|
@@ -62,6 +70,7 @@ const FORGE_SKIP_GENERATED_FILES = new Set([
|
|
|
62
70
|
'.aioson/context/spec.md.template',
|
|
63
71
|
'.aioson/install.json'
|
|
64
72
|
]);
|
|
73
|
+
const BACKUPS_GITIGNORE_ENTRY = '.aioson/backups/';
|
|
65
74
|
|
|
66
75
|
const SKIP_DIRS = new Set([
|
|
67
76
|
'.git', 'node_modules', 'vendor', '.next', 'dist', 'build',
|
|
@@ -133,6 +142,30 @@ async function readFileSafe(filePath, maxChars) {
|
|
|
133
142
|
}
|
|
134
143
|
}
|
|
135
144
|
|
|
145
|
+
async function backupProjectFiles(targetDir, relPaths) {
|
|
146
|
+
const uniqueRelPaths = [...new Set(relPaths.filter(Boolean))];
|
|
147
|
+
if (uniqueRelPaths.length === 0) {
|
|
148
|
+
return { backupRoot: null, backedUp: [] };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const backupRoot = path.join(targetDir, '.aioson/backups', nowStamp());
|
|
152
|
+
const backedUp = [];
|
|
153
|
+
|
|
154
|
+
for (const relPath of uniqueRelPaths) {
|
|
155
|
+
const source = path.join(targetDir, relPath);
|
|
156
|
+
if (!(await exists(source))) continue;
|
|
157
|
+
const dest = path.join(backupRoot, relPath);
|
|
158
|
+
await copyFileWithDir(source, dest);
|
|
159
|
+
backedUp.push(toRelativeSafe(targetDir, dest));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (backedUp.length === 0) {
|
|
163
|
+
return { backupRoot: null, backedUp: [] };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return { backupRoot, backedUp };
|
|
167
|
+
}
|
|
168
|
+
|
|
136
169
|
async function loadGitignorePatterns(root) {
|
|
137
170
|
const patterns = new Set();
|
|
138
171
|
try {
|
|
@@ -291,11 +324,36 @@ function httpPost(url, headers, body) {
|
|
|
291
324
|
|
|
292
325
|
async function callOpenAICompatible(baseUrl, apiKey, model, prompt) {
|
|
293
326
|
const url = `${baseUrl.replace(/\/$/, '')}/chat/completions`;
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
{
|
|
297
|
-
|
|
298
|
-
|
|
327
|
+
const baseBody = {
|
|
328
|
+
model,
|
|
329
|
+
messages: [{ role: 'user', content: prompt }],
|
|
330
|
+
temperature: 0.2
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
let text;
|
|
334
|
+
try {
|
|
335
|
+
text = await httpPost(
|
|
336
|
+
url,
|
|
337
|
+
{ Authorization: `Bearer ${apiKey}` },
|
|
338
|
+
{ ...baseBody, max_tokens: 4096 }
|
|
339
|
+
);
|
|
340
|
+
} catch (error) {
|
|
341
|
+
const message = String(error && error.message || '');
|
|
342
|
+
const requiresMaxCompletionTokens =
|
|
343
|
+
message.includes("Unsupported parameter: 'max_tokens'") &&
|
|
344
|
+
message.includes('max_completion_tokens');
|
|
345
|
+
|
|
346
|
+
if (!requiresMaxCompletionTokens) {
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
text = await httpPost(
|
|
351
|
+
url,
|
|
352
|
+
{ Authorization: `Bearer ${apiKey}` },
|
|
353
|
+
{ ...baseBody, max_completion_tokens: 4096 }
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
299
357
|
const data = JSON.parse(text);
|
|
300
358
|
return data.choices[0].message.content;
|
|
301
359
|
}
|
|
@@ -336,6 +394,11 @@ function resolveSummaryMode(value) {
|
|
|
336
394
|
return SUMMARY_MODES.has(normalized) ? normalized : 'summaries';
|
|
337
395
|
}
|
|
338
396
|
|
|
397
|
+
function resolveContextMode(value) {
|
|
398
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
399
|
+
return CONTEXT_MODES.has(normalized) ? normalized : 'merge';
|
|
400
|
+
}
|
|
401
|
+
|
|
339
402
|
function formatBytesCompact(sizeBytes) {
|
|
340
403
|
const bytes = Number(sizeBytes || 0);
|
|
341
404
|
const kb = bytes / 1024;
|
|
@@ -631,7 +694,7 @@ function buildForgeArtifactsMarkdown({ entries, generatedAt, managedForgePaths }
|
|
|
631
694
|
'',
|
|
632
695
|
'## Scope',
|
|
633
696
|
'- Shows generated or project-specific artifacts inside `.aioson/`.',
|
|
634
|
-
'- Groups what matters for client analysis, especially context pages, squads,
|
|
697
|
+
'- Groups what matters for client analysis, especially context pages, squads, genomes and local MCP artifacts.',
|
|
635
698
|
'- Hides framework-managed defaults such as agents, locales, schemas, static skills and task docs.'
|
|
636
699
|
];
|
|
637
700
|
|
|
@@ -664,7 +727,11 @@ function buildScanIndexMarkdown({
|
|
|
664
727
|
foldersPath,
|
|
665
728
|
folderScans = [],
|
|
666
729
|
forgePath,
|
|
667
|
-
forgeArtifactCount = 0
|
|
730
|
+
forgeArtifactCount = 0,
|
|
731
|
+
memoryIndexPath = null,
|
|
732
|
+
specCurrentPath = null,
|
|
733
|
+
specHistoryPath = null,
|
|
734
|
+
moduleDocs = []
|
|
668
735
|
}) {
|
|
669
736
|
const lines = [
|
|
670
737
|
'# Scan Index',
|
|
@@ -679,6 +746,18 @@ function buildScanIndexMarkdown({
|
|
|
679
746
|
`| ${scan.relativePath} | Full folder and file map for requested folder \`${scan.folder}/\` |`
|
|
680
747
|
),
|
|
681
748
|
`| ${FORGE_FILE} | Generated or project-specific artifacts inside .aioson/ |`,
|
|
749
|
+
...(memoryIndexPath
|
|
750
|
+
? [`| ${MEMORY_INDEX_FILE} | Read-this-first index of context docs and when to load them |`]
|
|
751
|
+
: []),
|
|
752
|
+
...(specCurrentPath
|
|
753
|
+
? [`| ${SPEC_CURRENT_FILE} | Current development snapshot derived from spec.md |`]
|
|
754
|
+
: []),
|
|
755
|
+
...(specHistoryPath
|
|
756
|
+
? [`| ${SPEC_HISTORY_FILE} | Historical implementation and decision view derived from spec.md |`]
|
|
757
|
+
: []),
|
|
758
|
+
...moduleDocs.map((doc) =>
|
|
759
|
+
`| ${doc.relativePath} | Focused module memory for requested folder \`${doc.folder}/\` |`
|
|
760
|
+
),
|
|
682
761
|
'',
|
|
683
762
|
`- Folder map: \`${foldersPath}\``,
|
|
684
763
|
...(
|
|
@@ -688,6 +767,10 @@ function buildScanIndexMarkdown({
|
|
|
688
767
|
),
|
|
689
768
|
`- AIOSON generated map: \`${forgePath}\``,
|
|
690
769
|
`- AIOSON generated entries: ${forgeArtifactCount}`,
|
|
770
|
+
...(memoryIndexPath ? [`- Memory index: \`${memoryIndexPath}\``] : []),
|
|
771
|
+
...(specCurrentPath ? [`- Spec current view: \`${specCurrentPath}\``] : []),
|
|
772
|
+
...(specHistoryPath ? [`- Spec history view: \`${specHistoryPath}\``] : []),
|
|
773
|
+
...moduleDocs.map((doc) => `- Module memory \`${doc.folder}/\`: \`${doc.absolutePath}\``),
|
|
691
774
|
'',
|
|
692
775
|
'## Top-level footprint',
|
|
693
776
|
'| Path | Files | Approx size |',
|
|
@@ -726,6 +809,8 @@ function buildPrompt({
|
|
|
726
809
|
keyContents,
|
|
727
810
|
projectContext,
|
|
728
811
|
specContent,
|
|
812
|
+
existingDiscoveryContent,
|
|
813
|
+
existingSkeletonContent,
|
|
729
814
|
summaryMode
|
|
730
815
|
}) {
|
|
731
816
|
const now = new Date().toISOString().replace(/\.\d+Z$/, 'Z');
|
|
@@ -752,11 +837,25 @@ function buildPrompt({
|
|
|
752
837
|
parts.push(`## Development Memory (spec.md)\n\`\`\`\n${specContent}\n\`\`\`\n`);
|
|
753
838
|
}
|
|
754
839
|
|
|
840
|
+
if (existingDiscoveryContent) {
|
|
841
|
+
parts.push(`## Existing Discovery Memory (update in place)\n\`\`\`md\n${existingDiscoveryContent}\n\`\`\`\n`);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
if (existingSkeletonContent) {
|
|
845
|
+
parts.push(`## Existing Skeleton Memory (update in place)\n\`\`\`md\n${existingSkeletonContent}\n\`\`\`\n`);
|
|
846
|
+
}
|
|
847
|
+
|
|
755
848
|
parts.push(`
|
|
756
849
|
## Task
|
|
757
850
|
Generate TWO documents. Separate them with exactly this delimiter on its own line:
|
|
758
851
|
<<<SKELETON>>>
|
|
759
852
|
|
|
853
|
+
If existing discovery or skeleton documents were provided above, treat them as the current memory baseline and UPDATE them in place.
|
|
854
|
+
- Preserve stable system knowledge, conventions, and still-valid human notes.
|
|
855
|
+
- Remove or correct only what is clearly contradicted by the current scan, project.context.md, or spec.md.
|
|
856
|
+
- Do not throw away useful prior context just because the current scan sample is smaller.
|
|
857
|
+
- Keep the required output sections exactly as specified below.
|
|
858
|
+
|
|
760
859
|
### Document 1: \`.aioson/context/discovery.md\`
|
|
761
860
|
Generate with exactly these sections:
|
|
762
861
|
|
|
@@ -844,8 +943,10 @@ function listTopLevelDirectories(entries) {
|
|
|
844
943
|
// ── Main ─────────────────────────────────────────────────────────────────────
|
|
845
944
|
|
|
846
945
|
async function runScanProject({ args, options = {}, logger, t }) {
|
|
847
|
-
const
|
|
946
|
+
const targetArg = args[0] || '.';
|
|
947
|
+
const targetDir = path.resolve(process.cwd(), targetArg);
|
|
848
948
|
const summaryMode = resolveSummaryMode(options['summary-mode']);
|
|
949
|
+
const contextMode = resolveContextMode(options['context-mode']);
|
|
849
950
|
const requestedFolders = resolveRequestedFolders(options.folder);
|
|
850
951
|
const llmRequested = Boolean(options['with-llm']);
|
|
851
952
|
const llmModelOverride = String(options['llm-model'] || options.model || '').trim();
|
|
@@ -854,6 +955,13 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
854
955
|
|
|
855
956
|
if (requestedFolders.length === 0) {
|
|
856
957
|
logger.error(t('scan_project.folder_required'));
|
|
958
|
+
logger.error(t('scan_project.folder_required_examples_title'));
|
|
959
|
+
logger.error(t('scan_project.folder_required_example_local'));
|
|
960
|
+
logger.error(t('scan_project.folder_required_example_multi'));
|
|
961
|
+
logger.error(t('scan_project.folder_required_example_llm'));
|
|
962
|
+
logger.error(t('scan_project.folder_required_example_cli'));
|
|
963
|
+
logger.error(t('scan_project.folder_required_example_prompt'));
|
|
964
|
+
logger.error(t('scan_project.folder_required_example_next'));
|
|
857
965
|
process.exitCode = 1;
|
|
858
966
|
return { ok: false, error: 'folder_required' };
|
|
859
967
|
}
|
|
@@ -862,6 +970,14 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
862
970
|
let providerCfg = null;
|
|
863
971
|
let model = null;
|
|
864
972
|
|
|
973
|
+
if (!options['dry-run']) {
|
|
974
|
+
const gitignoreRulesAdded = await ensureProjectGitignorePolicy(targetDir);
|
|
975
|
+
if (gitignoreRulesAdded > 0) {
|
|
976
|
+
logger.log(t('scan_project.gitignore_policy_written', { path: path.join(targetDir, '.gitignore') }));
|
|
977
|
+
logger.log(t('scan_project.gitignore_tracked_note'));
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
865
981
|
if (!llmRequested) {
|
|
866
982
|
logger.log(t('scan_project.local_only'));
|
|
867
983
|
} else if (!options['dry-run']) {
|
|
@@ -900,10 +1016,18 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
900
1016
|
// Read context files
|
|
901
1017
|
const projectContext = await readFileSafe(path.join(targetDir, CONTEXT_FILE));
|
|
902
1018
|
const specContent = await readFileSafe(path.join(targetDir, SPEC_FILE));
|
|
1019
|
+
const existingDiscoveryPath = path.join(targetDir, OUTPUT_FILE);
|
|
1020
|
+
const existingSkeletonPath = path.join(targetDir, SKELETON_FILE);
|
|
1021
|
+
const existingDiscoveryContent = contextMode === 'merge' ? await readFileSafe(existingDiscoveryPath) : null;
|
|
1022
|
+
const existingSkeletonContent = contextMode === 'merge' ? await readFileSafe(existingSkeletonPath) : null;
|
|
903
1023
|
|
|
904
1024
|
if (projectContext) logger.log(t('scan_project.context_found'));
|
|
905
1025
|
else logger.log(t('scan_project.context_missing'));
|
|
906
1026
|
if (specContent) logger.log(t('scan_project.spec_found'));
|
|
1027
|
+
if (llmRequested && existingDiscoveryContent) logger.log(t('scan_project.existing_discovery_found', { path: existingDiscoveryPath }));
|
|
1028
|
+
if (llmRequested && existingSkeletonContent) logger.log(t('scan_project.existing_skeleton_found', { path: existingSkeletonPath }));
|
|
1029
|
+
if (llmRequested && (existingDiscoveryContent || existingSkeletonContent)) logger.log(t('scan_project.context_update_mode'));
|
|
1030
|
+
if (llmRequested) logger.log(t('scan_project.context_mode', { mode: contextMode }));
|
|
907
1031
|
|
|
908
1032
|
// Walk project
|
|
909
1033
|
logger.log(t('scan_project.walking'));
|
|
@@ -953,34 +1077,37 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
953
1077
|
};
|
|
954
1078
|
});
|
|
955
1079
|
|
|
1080
|
+
const scanIndexPath = path.join(targetDir, INDEX_FILE);
|
|
1081
|
+
const scanFoldersPath = path.join(targetDir, FOLDERS_FILE);
|
|
1082
|
+
const scanForgePath = path.join(targetDir, FORGE_FILE);
|
|
956
1083
|
const scanIndexMarkdown = buildScanIndexMarkdown({
|
|
957
1084
|
keyFiles,
|
|
958
1085
|
topLevelStats,
|
|
959
1086
|
generatedAt,
|
|
960
1087
|
includeSummaries: summaryMode !== 'titles',
|
|
961
|
-
foldersPath:
|
|
1088
|
+
foldersPath: scanFoldersPath,
|
|
962
1089
|
folderScans,
|
|
963
|
-
forgePath:
|
|
1090
|
+
forgePath: scanForgePath,
|
|
964
1091
|
forgeArtifactCount: forgeArtifacts.artifactCount
|
|
965
1092
|
});
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1093
|
+
let derivedArtifacts = {
|
|
1094
|
+
memoryIndexPath: null,
|
|
1095
|
+
specCurrentPath: null,
|
|
1096
|
+
specHistoryPath: null,
|
|
1097
|
+
moduleDocs: []
|
|
1098
|
+
};
|
|
970
1099
|
if (!options['dry-run']) {
|
|
971
1100
|
await ensureDir(path.dirname(scanIndexPath));
|
|
972
|
-
await fs.writeFile(scanIndexPath, scanIndexMarkdown, 'utf8');
|
|
973
1101
|
await fs.writeFile(scanFoldersPath, folderMapMarkdown, 'utf8');
|
|
974
1102
|
for (const scan of folderScans) {
|
|
975
1103
|
await fs.writeFile(scan.absolutePath, scan.markdown, 'utf8');
|
|
976
1104
|
}
|
|
1105
|
+
await fs.writeFile(scanIndexPath, scanIndexMarkdown, 'utf8');
|
|
977
1106
|
await fs.writeFile(scanForgePath, forgeArtifacts.markdown, 'utf8');
|
|
978
|
-
logger.log(t('scan_project.index_written', { path: scanIndexPath, mode: summaryMode }));
|
|
979
1107
|
logger.log(t('scan_project.folders_written', { path: scanFoldersPath }));
|
|
980
1108
|
for (const scan of folderScans) {
|
|
981
1109
|
logger.log(t('scan_project.folder_written', { folder: `${scan.folder}/`, path: scan.absolutePath }));
|
|
982
1110
|
}
|
|
983
|
-
logger.log(t('scan_project.forge_written', { path: scanForgePath }));
|
|
984
1111
|
}
|
|
985
1112
|
|
|
986
1113
|
if (options['dry-run']) {
|
|
@@ -993,6 +1120,7 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
993
1120
|
model,
|
|
994
1121
|
llmRequested,
|
|
995
1122
|
summaryMode,
|
|
1123
|
+
contextMode,
|
|
996
1124
|
requestedFolders,
|
|
997
1125
|
scanIndexPath,
|
|
998
1126
|
scanFoldersPath,
|
|
@@ -1005,7 +1133,61 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1005
1133
|
}
|
|
1006
1134
|
|
|
1007
1135
|
if (!llmRequested) {
|
|
1136
|
+
derivedArtifacts = await writeDerivedContextMemory({
|
|
1137
|
+
targetDir,
|
|
1138
|
+
generatedAt,
|
|
1139
|
+
folderScans
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
const refreshedWalk = await walkProject(targetDir);
|
|
1143
|
+
const refreshedForgeArtifacts = buildForgeArtifactsMarkdown({
|
|
1144
|
+
entries: refreshedWalk.entries,
|
|
1145
|
+
generatedAt,
|
|
1146
|
+
managedForgePaths
|
|
1147
|
+
});
|
|
1148
|
+
const refreshedScanIndexMarkdown = buildScanIndexMarkdown({
|
|
1149
|
+
keyFiles: refreshedWalk.keyFiles,
|
|
1150
|
+
topLevelStats: refreshedWalk.topLevelStats,
|
|
1151
|
+
generatedAt,
|
|
1152
|
+
includeSummaries: summaryMode !== 'titles',
|
|
1153
|
+
foldersPath: path.join(targetDir, FOLDERS_FILE),
|
|
1154
|
+
folderScans,
|
|
1155
|
+
forgePath: path.join(targetDir, FORGE_FILE),
|
|
1156
|
+
forgeArtifactCount: refreshedForgeArtifacts.artifactCount,
|
|
1157
|
+
memoryIndexPath: derivedArtifacts.memoryIndexPath,
|
|
1158
|
+
specCurrentPath: derivedArtifacts.specCurrentPath,
|
|
1159
|
+
specHistoryPath: derivedArtifacts.specHistoryPath,
|
|
1160
|
+
moduleDocs: derivedArtifacts.moduleDocs
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
await fs.writeFile(scanIndexPath, refreshedScanIndexMarkdown, 'utf8');
|
|
1164
|
+
await fs.writeFile(scanForgePath, refreshedForgeArtifacts.markdown, 'utf8');
|
|
1165
|
+
logger.log(t('scan_project.index_written', { path: scanIndexPath, mode: summaryMode }));
|
|
1166
|
+
logger.log(t('scan_project.forge_written', { path: scanForgePath }));
|
|
1167
|
+
if (derivedArtifacts.memoryIndexPath) logger.log(t('scan_project.memory_index_written', { path: derivedArtifacts.memoryIndexPath }));
|
|
1168
|
+
if (derivedArtifacts.specCurrentPath) logger.log(t('scan_project.spec_current_written', { path: derivedArtifacts.specCurrentPath }));
|
|
1169
|
+
if (derivedArtifacts.specHistoryPath) logger.log(t('scan_project.spec_history_written', { path: derivedArtifacts.specHistoryPath }));
|
|
1170
|
+
for (const doc of derivedArtifacts.moduleDocs) {
|
|
1171
|
+
logger.log(t('scan_project.module_memory_written', { folder: `${doc.folder}/`, path: doc.absolutePath }));
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1008
1174
|
logger.log(t('scan_project.local_done', { path: scanIndexPath }));
|
|
1175
|
+
logger.log(t('scan_project.local_missing'));
|
|
1176
|
+
logger.log(t('scan_project.architecture_note'));
|
|
1177
|
+
logger.log(t('scan_project.local_paths_title'));
|
|
1178
|
+
logger.log(t('scan_project.local_path_api'));
|
|
1179
|
+
logger.log(t('scan_project.local_next_steps', {
|
|
1180
|
+
target: targetArg,
|
|
1181
|
+
folders: requestedFolders.join(',')
|
|
1182
|
+
}));
|
|
1183
|
+
logger.log(t('scan_project.local_path_cli'));
|
|
1184
|
+
logger.log(t('scan_project.local_cli_step_analyst'));
|
|
1185
|
+
logger.log(t('scan_project.local_cli_step_prompt_codex'));
|
|
1186
|
+
logger.log(t('scan_project.local_cli_step_prompt_claude'));
|
|
1187
|
+
logger.log(t('scan_project.local_cli_step_model_hint'));
|
|
1188
|
+
logger.log(t('scan_project.local_workflow_title'));
|
|
1189
|
+
logger.log(t('scan_project.local_step_architect'));
|
|
1190
|
+
logger.log(t('scan_project.local_step_dev'));
|
|
1009
1191
|
return {
|
|
1010
1192
|
ok: true,
|
|
1011
1193
|
targetDir,
|
|
@@ -1013,11 +1195,16 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1013
1195
|
model: null,
|
|
1014
1196
|
llmRequested: false,
|
|
1015
1197
|
summaryMode,
|
|
1198
|
+
contextMode,
|
|
1016
1199
|
requestedFolders,
|
|
1017
1200
|
scanIndexPath,
|
|
1018
1201
|
scanFoldersPath,
|
|
1019
1202
|
scanFolderPaths: folderScans.map((scan) => scan.absolutePath),
|
|
1020
1203
|
scanForgePath,
|
|
1204
|
+
memoryIndexPath: derivedArtifacts.memoryIndexPath,
|
|
1205
|
+
specCurrentPath: derivedArtifacts.specCurrentPath,
|
|
1206
|
+
specHistoryPath: derivedArtifacts.specHistoryPath,
|
|
1207
|
+
moduleDocPaths: derivedArtifacts.moduleDocs.map((doc) => doc.absolutePath),
|
|
1021
1208
|
discoveryPath: null,
|
|
1022
1209
|
skeletonPath: null
|
|
1023
1210
|
};
|
|
@@ -1032,6 +1219,8 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1032
1219
|
keyContents,
|
|
1033
1220
|
projectContext,
|
|
1034
1221
|
specContent,
|
|
1222
|
+
existingDiscoveryContent,
|
|
1223
|
+
existingSkeletonContent,
|
|
1035
1224
|
summaryMode
|
|
1036
1225
|
});
|
|
1037
1226
|
logger.log(t('scan_project.calling_llm', { provider: providerName, model }));
|
|
@@ -1050,8 +1239,8 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1050
1239
|
}
|
|
1051
1240
|
|
|
1052
1241
|
// Parse and write both documents
|
|
1053
|
-
const outputPath
|
|
1054
|
-
const skeletonPath =
|
|
1242
|
+
const outputPath = existingDiscoveryPath;
|
|
1243
|
+
const skeletonPath = existingSkeletonPath;
|
|
1055
1244
|
|
|
1056
1245
|
await ensureDir(path.dirname(outputPath));
|
|
1057
1246
|
|
|
@@ -1065,6 +1254,37 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1065
1254
|
skeletonContent = null;
|
|
1066
1255
|
}
|
|
1067
1256
|
|
|
1257
|
+
if (!discoveryContent) {
|
|
1258
|
+
logger.error(t('scan_project.invalid_llm_output_discovery_empty'));
|
|
1259
|
+
process.exitCode = 1;
|
|
1260
|
+
return { ok: false, error: 'empty_discovery' };
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
if (result.includes(DELIMITER) && !skeletonContent) {
|
|
1264
|
+
logger.error(t('scan_project.invalid_llm_output_skeleton_empty'));
|
|
1265
|
+
process.exitCode = 1;
|
|
1266
|
+
return { ok: false, error: 'empty_skeleton' };
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
const contextFilesToBackup = [];
|
|
1270
|
+
if (await exists(existingDiscoveryPath)) contextFilesToBackup.push(OUTPUT_FILE);
|
|
1271
|
+
if (skeletonContent && await exists(existingSkeletonPath)) contextFilesToBackup.push(SKELETON_FILE);
|
|
1272
|
+
|
|
1273
|
+
if (contextFilesToBackup.length > 0) {
|
|
1274
|
+
const gitignoreChanged = await ensureGitignoreEntry(targetDir, BACKUPS_GITIGNORE_ENTRY);
|
|
1275
|
+
if (gitignoreChanged) {
|
|
1276
|
+
logger.log(t('scan_project.gitignore_backups_written', { path: path.join(targetDir, '.gitignore') }));
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
const backupResult = await backupProjectFiles(targetDir, contextFilesToBackup);
|
|
1280
|
+
if (backupResult.backedUp.length > 0) {
|
|
1281
|
+
logger.log(t('scan_project.backups_written', {
|
|
1282
|
+
count: backupResult.backedUp.length,
|
|
1283
|
+
path: backupResult.backupRoot
|
|
1284
|
+
}));
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1068
1288
|
await fs.writeFile(outputPath, discoveryContent, 'utf8');
|
|
1069
1289
|
logger.log(t('scan_project.discovery_written', { path: outputPath, chars: discoveryContent.length }));
|
|
1070
1290
|
|
|
@@ -1075,8 +1295,46 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1075
1295
|
logger.log(t('scan_project.skeleton_missing'));
|
|
1076
1296
|
}
|
|
1077
1297
|
|
|
1298
|
+
derivedArtifacts = await writeDerivedContextMemory({
|
|
1299
|
+
targetDir,
|
|
1300
|
+
generatedAt,
|
|
1301
|
+
folderScans
|
|
1302
|
+
});
|
|
1303
|
+
const refreshedWalk = await walkProject(targetDir);
|
|
1304
|
+
const refreshedForgeArtifacts = buildForgeArtifactsMarkdown({
|
|
1305
|
+
entries: refreshedWalk.entries,
|
|
1306
|
+
generatedAt,
|
|
1307
|
+
managedForgePaths
|
|
1308
|
+
});
|
|
1309
|
+
const refreshedScanIndexMarkdown = buildScanIndexMarkdown({
|
|
1310
|
+
keyFiles: refreshedWalk.keyFiles,
|
|
1311
|
+
topLevelStats: refreshedWalk.topLevelStats,
|
|
1312
|
+
generatedAt,
|
|
1313
|
+
includeSummaries: summaryMode !== 'titles',
|
|
1314
|
+
foldersPath: path.join(targetDir, FOLDERS_FILE),
|
|
1315
|
+
folderScans,
|
|
1316
|
+
forgePath: path.join(targetDir, FORGE_FILE),
|
|
1317
|
+
forgeArtifactCount: refreshedForgeArtifacts.artifactCount,
|
|
1318
|
+
memoryIndexPath: derivedArtifacts.memoryIndexPath,
|
|
1319
|
+
specCurrentPath: derivedArtifacts.specCurrentPath,
|
|
1320
|
+
specHistoryPath: derivedArtifacts.specHistoryPath,
|
|
1321
|
+
moduleDocs: derivedArtifacts.moduleDocs
|
|
1322
|
+
});
|
|
1323
|
+
await fs.writeFile(scanIndexPath, refreshedScanIndexMarkdown, 'utf8');
|
|
1324
|
+
await fs.writeFile(scanForgePath, refreshedForgeArtifacts.markdown, 'utf8');
|
|
1325
|
+
logger.log(t('scan_project.index_written', { path: scanIndexPath, mode: summaryMode }));
|
|
1326
|
+
logger.log(t('scan_project.forge_written', { path: scanForgePath }));
|
|
1327
|
+
if (derivedArtifacts.memoryIndexPath) logger.log(t('scan_project.memory_index_written', { path: derivedArtifacts.memoryIndexPath }));
|
|
1328
|
+
if (derivedArtifacts.specCurrentPath) logger.log(t('scan_project.spec_current_written', { path: derivedArtifacts.specCurrentPath }));
|
|
1329
|
+
if (derivedArtifacts.specHistoryPath) logger.log(t('scan_project.spec_history_written', { path: derivedArtifacts.specHistoryPath }));
|
|
1330
|
+
for (const doc of derivedArtifacts.moduleDocs) {
|
|
1331
|
+
logger.log(t('scan_project.module_memory_written', { folder: `${doc.folder}/`, path: doc.absolutePath }));
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
logger.log(t('scan_project.architecture_note'));
|
|
1078
1335
|
logger.log(t('scan_project.next_steps'));
|
|
1079
1336
|
logger.log(t('scan_project.step_analyst'));
|
|
1337
|
+
logger.log(t('scan_project.step_architect'));
|
|
1080
1338
|
logger.log(t('scan_project.step_dev'));
|
|
1081
1339
|
|
|
1082
1340
|
const output = {
|
|
@@ -1086,11 +1344,16 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1086
1344
|
model,
|
|
1087
1345
|
llmRequested: true,
|
|
1088
1346
|
summaryMode,
|
|
1347
|
+
contextMode,
|
|
1089
1348
|
requestedFolders,
|
|
1090
1349
|
scanIndexPath,
|
|
1091
1350
|
scanFoldersPath,
|
|
1092
1351
|
scanFolderPaths: folderScans.map((scan) => scan.absolutePath),
|
|
1093
1352
|
scanForgePath,
|
|
1353
|
+
memoryIndexPath: derivedArtifacts.memoryIndexPath,
|
|
1354
|
+
specCurrentPath: derivedArtifacts.specCurrentPath,
|
|
1355
|
+
specHistoryPath: derivedArtifacts.specHistoryPath,
|
|
1356
|
+
moduleDocPaths: derivedArtifacts.moduleDocs.map((doc) => doc.absolutePath),
|
|
1094
1357
|
discoveryPath: outputPath,
|
|
1095
1358
|
skeletonPath: skeletonContent ? skeletonPath : null
|
|
1096
1359
|
};
|
|
@@ -1101,6 +1364,7 @@ async function runScanProject({ args, options = {}, logger, t }) {
|
|
|
1101
1364
|
module.exports = {
|
|
1102
1365
|
runScanProject,
|
|
1103
1366
|
resolveSummaryMode,
|
|
1367
|
+
resolveContextMode,
|
|
1104
1368
|
resolveRequestedFolders,
|
|
1105
1369
|
buildScanIndexMarkdown,
|
|
1106
1370
|
buildPrompt
|
|
@@ -8,9 +8,11 @@ const {
|
|
|
8
8
|
calculateClassification,
|
|
9
9
|
normalizeBoolean,
|
|
10
10
|
renderProjectContext,
|
|
11
|
-
writeProjectContext
|
|
11
|
+
writeProjectContext,
|
|
12
|
+
renderSquadApiSection
|
|
12
13
|
} = require('../context-writer');
|
|
13
14
|
const { applyAgentLocale } = require('../locales');
|
|
15
|
+
const { openRuntimeDb, logAgentEvent } = require('../runtime-store');
|
|
14
16
|
const {
|
|
15
17
|
BACKEND_CHOICES,
|
|
16
18
|
FRONTEND_CHOICES,
|
|
@@ -206,6 +208,8 @@ function applyExplicitOverrides(data, options, detectedInstalled) {
|
|
|
206
208
|
}
|
|
207
209
|
const langValue = options.language ?? options.lang;
|
|
208
210
|
if (langValue !== undefined) output.conversationLanguage = String(langValue);
|
|
211
|
+
if (hasOption(options, 'design-skill')) output.designSkill = String(options['design-skill']);
|
|
212
|
+
if (hasOption(options, 'test-runner')) output.testRunner = String(options['test-runner']);
|
|
209
213
|
if (hasOption(options, 'web3-enabled')) {
|
|
210
214
|
output.web3Enabled = normalizeBoolean(options['web3-enabled'], output.web3Enabled);
|
|
211
215
|
}
|
|
@@ -466,6 +470,8 @@ async function runSetupContext({ args, options, logger, t }) {
|
|
|
466
470
|
framework: detectedFramework,
|
|
467
471
|
frameworkInstalled: detectedInstalled,
|
|
468
472
|
conversationLanguage: 'en',
|
|
473
|
+
designSkill: '',
|
|
474
|
+
testRunner: '',
|
|
469
475
|
web3Enabled: inferredWeb3Enabled,
|
|
470
476
|
web3Networks: inferredWeb3Enabled ? inferWeb3Network(detectedFramework) : '',
|
|
471
477
|
contractFramework: inferredWeb3Enabled ? detectedFramework : '',
|
|
@@ -613,7 +619,9 @@ async function runSetupContext({ args, options, logger, t }) {
|
|
|
613
619
|
}
|
|
614
620
|
|
|
615
621
|
const content = renderProjectContext(data);
|
|
616
|
-
const
|
|
622
|
+
const squadApiSection = await renderSquadApiSection(targetDir);
|
|
623
|
+
const fullContent = squadApiSection ? content + '\n' + squadApiSection + '\n' : content;
|
|
624
|
+
const filePath = await writeProjectContext(targetDir, fullContent);
|
|
617
625
|
const localeApplyResult = await applyAgentLocale(targetDir, data.conversationLanguage, {
|
|
618
626
|
dryRun: false
|
|
619
627
|
});
|
|
@@ -632,6 +640,26 @@ async function runSetupContext({ args, options, logger, t }) {
|
|
|
632
640
|
})
|
|
633
641
|
);
|
|
634
642
|
|
|
643
|
+
try {
|
|
644
|
+
const handle = await openRuntimeDb(targetDir);
|
|
645
|
+
const { db, runtimeDir } = handle;
|
|
646
|
+
try {
|
|
647
|
+
await logAgentEvent(db, runtimeDir, {
|
|
648
|
+
agentName: '@setup',
|
|
649
|
+
message: `Project context created: ${data.projectName} (${data.classification} / ${data.framework})`,
|
|
650
|
+
type: 'completed',
|
|
651
|
+
taskTitle: `@setup — ${data.projectName}`,
|
|
652
|
+
finish: true,
|
|
653
|
+
status: 'completed',
|
|
654
|
+
summary: `Setup: ${data.projectType} · ${data.framework} · ${data.classification}`
|
|
655
|
+
});
|
|
656
|
+
} finally {
|
|
657
|
+
db.close();
|
|
658
|
+
}
|
|
659
|
+
} catch {
|
|
660
|
+
// Runtime DB may not exist yet on first setup — not a fatal error
|
|
661
|
+
}
|
|
662
|
+
|
|
635
663
|
return {
|
|
636
664
|
ok: true,
|
|
637
665
|
targetDir,
|