aios-core 4.2.15 → 4.4.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/.aios-core/cli/commands/validate/index.js +1 -1
- package/.aios-core/core/code-intel/code-intel-client.js +19 -5
- package/.aios-core/core/code-intel/helpers/creation-helper.js +183 -0
- package/.aios-core/core/code-intel/helpers/devops-helper.js +166 -0
- package/.aios-core/core/code-intel/helpers/planning-helper.js +248 -0
- package/.aios-core/core/code-intel/helpers/qa-helper.js +187 -0
- package/.aios-core/core/code-intel/helpers/story-helper.js +146 -0
- package/.aios-core/core/code-intel/hook-runtime.js +186 -0
- package/.aios-core/core/code-intel/index.js +2 -0
- package/.aios-core/core/code-intel/providers/code-graph-provider.js +8 -0
- package/.aios-core/core/code-intel/providers/provider-interface.js +9 -0
- package/.aios-core/core/code-intel/providers/registry-provider.js +515 -0
- package/.aios-core/core/config/schemas/framework-config.schema.json +155 -7
- package/.aios-core/core/config/schemas/project-config.schema.json +329 -15
- package/.aios-core/core/config/template-overrides.js +84 -0
- package/.aios-core/core/docs/troubleshooting-guide.md +1 -1
- package/.aios-core/core/doctor/checks/agent-memory.js +63 -0
- package/.aios-core/core/doctor/checks/claude-md.js +56 -0
- package/.aios-core/core/doctor/checks/code-intel.js +131 -0
- package/.aios-core/core/doctor/checks/commands-count.js +81 -0
- package/.aios-core/core/doctor/checks/core-config.js +53 -0
- package/.aios-core/core/doctor/checks/entity-registry.js +53 -0
- package/.aios-core/core/doctor/checks/git-hooks.js +50 -0
- package/.aios-core/core/doctor/checks/graph-dashboard.js +48 -0
- package/.aios-core/core/doctor/checks/hooks-claude-count.js +118 -0
- package/.aios-core/core/doctor/checks/ide-sync.js +85 -0
- package/.aios-core/core/doctor/checks/index.js +46 -0
- package/.aios-core/core/doctor/checks/node-version.js +33 -0
- package/.aios-core/core/doctor/checks/npm-packages.js +35 -0
- package/.aios-core/core/doctor/checks/rules-files.js +61 -0
- package/.aios-core/core/doctor/checks/settings-json.js +121 -0
- package/.aios-core/core/doctor/checks/skills-count.js +72 -0
- package/.aios-core/core/doctor/fix-handler.js +165 -0
- package/.aios-core/core/doctor/formatters/json.js +14 -0
- package/.aios-core/core/doctor/formatters/text.js +59 -0
- package/.aios-core/core/doctor/index.js +94 -0
- package/.aios-core/core/graph-dashboard/cli.js +361 -0
- package/.aios-core/core/graph-dashboard/data-sources/code-intel-source.js +234 -0
- package/.aios-core/core/graph-dashboard/data-sources/metrics-source.js +95 -0
- package/.aios-core/core/graph-dashboard/data-sources/registry-source.js +106 -0
- package/.aios-core/core/graph-dashboard/formatters/dot-formatter.js +45 -0
- package/.aios-core/core/graph-dashboard/formatters/html-formatter.js +1437 -0
- package/.aios-core/core/graph-dashboard/formatters/json-formatter.js +13 -0
- package/.aios-core/core/graph-dashboard/formatters/mermaid-formatter.js +59 -0
- package/.aios-core/core/graph-dashboard/index.js +21 -0
- package/.aios-core/core/graph-dashboard/renderers/stats-renderer.js +217 -0
- package/.aios-core/core/graph-dashboard/renderers/status-renderer.js +125 -0
- package/.aios-core/core/graph-dashboard/renderers/tree-renderer.js +119 -0
- package/.aios-core/core/health-check/base-check.js +1 -1
- package/.aios-core/core/health-check/check-registry.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/build-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/ci-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/deployment-readiness.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/docker-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/env-file.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/index.js +1 -1
- package/.aios-core/core/health-check/checks/index.js +1 -1
- package/.aios-core/core/health-check/checks/local/disk-space.js +1 -1
- package/.aios-core/core/health-check/checks/local/environment-vars.js +1 -1
- package/.aios-core/core/health-check/checks/local/git-install.js +1 -1
- package/.aios-core/core/health-check/checks/local/ide-detection.js +1 -1
- package/.aios-core/core/health-check/checks/local/index.js +1 -1
- package/.aios-core/core/health-check/checks/local/memory.js +1 -1
- package/.aios-core/core/health-check/checks/local/network.js +1 -1
- package/.aios-core/core/health-check/checks/local/npm-install.js +1 -1
- package/.aios-core/core/health-check/checks/local/shell-environment.js +1 -1
- package/.aios-core/core/health-check/checks/project/agent-config.js +1 -1
- package/.aios-core/core/health-check/checks/project/aios-directory.js +1 -1
- package/.aios-core/core/health-check/checks/project/dependencies.js +1 -1
- package/.aios-core/core/health-check/checks/project/framework-config.js +1 -1
- package/.aios-core/core/health-check/checks/project/index.js +1 -1
- package/.aios-core/core/health-check/checks/project/node-version.js +1 -1
- package/.aios-core/core/health-check/checks/project/package-json.js +1 -1
- package/.aios-core/core/health-check/checks/project/task-definitions.js +1 -1
- package/.aios-core/core/health-check/checks/project/workflow-dependencies.js +1 -1
- package/.aios-core/core/health-check/checks/repository/branch-protection.js +1 -1
- package/.aios-core/core/health-check/checks/repository/commit-history.js +1 -1
- package/.aios-core/core/health-check/checks/repository/conflicts.js +1 -1
- package/.aios-core/core/health-check/checks/repository/git-repo.js +1 -1
- package/.aios-core/core/health-check/checks/repository/git-status.js +1 -1
- package/.aios-core/core/health-check/checks/repository/gitignore.js +1 -1
- package/.aios-core/core/health-check/checks/repository/index.js +1 -1
- package/.aios-core/core/health-check/checks/repository/large-files.js +1 -1
- package/.aios-core/core/health-check/checks/repository/lockfile-integrity.js +1 -1
- package/.aios-core/core/health-check/checks/services/api-endpoints.js +1 -1
- package/.aios-core/core/health-check/checks/services/claude-code.js +1 -1
- package/.aios-core/core/health-check/checks/services/gemini-cli.js +1 -1
- package/.aios-core/core/health-check/checks/services/github-cli.js +1 -1
- package/.aios-core/core/health-check/checks/services/index.js +1 -1
- package/.aios-core/core/health-check/checks/services/mcp-integration.js +1 -1
- package/.aios-core/core/health-check/engine.js +1 -1
- package/.aios-core/core/health-check/healers/backup-manager.js +1 -1
- package/.aios-core/core/health-check/healers/index.js +1 -1
- package/.aios-core/core/health-check/index.js +9 -2
- package/.aios-core/core/health-check/reporters/console.js +1 -1
- package/.aios-core/core/health-check/reporters/index.js +1 -1
- package/.aios-core/core/health-check/reporters/json.js +1 -1
- package/.aios-core/core/health-check/reporters/markdown.js +1 -1
- package/.aios-core/core/ids/layer-classifier.js +65 -0
- package/.aios-core/core/ids/registry-updater.js +49 -0
- package/.aios-core/core/index.esm.js +1 -1
- package/.aios-core/core/index.js +1 -1
- package/.aios-core/core/session/context-detector.js +2 -7
- package/.aios-core/core/synapse/context/context-tracker.js +9 -1
- package/.aios-core/core/synapse/engine.js +33 -13
- package/.aios-core/core/synapse/memory/memory-bridge.js +17 -43
- package/.aios-core/core/synapse/memory/synapse-memory-provider.js +201 -0
- package/.aios-core/core/synapse/runtime/hook-runtime.js +40 -2
- package/.aios-core/core/synapse/session/session-manager.js +3 -2
- package/.aios-core/core/synapse/utils/atomic-write.js +79 -0
- package/.aios-core/core-config.yaml +34 -1
- package/.aios-core/data/aios-kb.md +2 -2
- package/.aios-core/data/capability-detection.js +290 -0
- package/.aios-core/data/entity-registry.yaml +10450 -2129
- package/.aios-core/data/mcp-discipline.js +166 -0
- package/.aios-core/data/mcp-tool-examples.yaml +215 -0
- package/.aios-core/data/tok2-validation.js +168 -0
- package/.aios-core/data/tok3-token-comparison.js +123 -0
- package/.aios-core/data/tool-registry.yaml +648 -0
- package/.aios-core/data/tool-search-validation.js +174 -0
- package/.aios-core/data/workflow-chains.yaml +156 -0
- package/.aios-core/development/agents/aios-master.md +17 -10
- package/.aios-core/development/agents/analyst/MEMORY.md +33 -0
- package/.aios-core/development/agents/analyst.md +17 -10
- package/.aios-core/development/agents/architect/MEMORY.md +39 -0
- package/.aios-core/development/agents/architect.md +17 -10
- package/.aios-core/development/agents/data-engineer/MEMORY.md +32 -0
- package/.aios-core/development/agents/data-engineer.md +17 -10
- package/.aios-core/development/agents/dev/MEMORY.md +46 -0
- package/.aios-core/development/agents/dev.md +18 -11
- package/.aios-core/development/agents/devops/MEMORY.md +39 -0
- package/.aios-core/development/agents/devops.md +44 -10
- package/.aios-core/development/agents/pm/MEMORY.md +38 -0
- package/.aios-core/development/agents/pm.md +17 -10
- package/.aios-core/development/agents/po/MEMORY.md +45 -0
- package/.aios-core/development/agents/po.md +17 -10
- package/.aios-core/development/agents/qa/MEMORY.md +42 -0
- package/.aios-core/development/agents/qa.md +18 -11
- package/.aios-core/development/agents/sm/MEMORY.md +31 -0
- package/.aios-core/development/agents/sm.md +17 -10
- package/.aios-core/development/agents/squad-creator.md +18 -9
- package/.aios-core/development/agents/ux/MEMORY.md +31 -0
- package/.aios-core/development/agents/ux-design-expert.md +16 -9
- package/.aios-core/development/checklists/issue-triage-checklist.md +35 -0
- package/.aios-core/development/checklists/memory-audit-checklist.md +53 -0
- package/.aios-core/development/scripts/issue-triage.js +171 -0
- package/.aios-core/development/scripts/populate-entity-registry.js +412 -19
- package/.aios-core/development/scripts/unified-activation-pipeline.js +31 -10
- package/.aios-core/development/tasks/analyze-project-structure.md +48 -0
- package/.aios-core/development/tasks/apply-qa-fixes.md +7 -0
- package/.aios-core/development/tasks/architect-analyze-impact.md +8 -1
- package/.aios-core/development/tasks/brownfield-create-epic.md +41 -0
- package/.aios-core/development/tasks/brownfield-create-story.md +7 -0
- package/.aios-core/development/tasks/build-autonomous.md +7 -0
- package/.aios-core/development/tasks/create-deep-research-prompt.md +7 -0
- package/.aios-core/development/tasks/create-doc.md +44 -0
- package/.aios-core/development/tasks/create-next-story.md +17 -0
- package/.aios-core/development/tasks/create-suite.md +7 -0
- package/.aios-core/development/tasks/dev-develop-story.md +9 -1
- package/.aios-core/development/tasks/execute-checklist.md +7 -0
- package/.aios-core/development/tasks/github-devops-github-pr-automation.md +56 -0
- package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +70 -0
- package/.aios-core/development/tasks/github-issue-triage.md +118 -0
- package/.aios-core/development/tasks/health-check.yaml +206 -171
- package/.aios-core/development/tasks/kb-mode-interaction.md +3 -3
- package/.aios-core/development/tasks/plan-create-context.md +47 -1
- package/.aios-core/development/tasks/plan-create-implementation.md +55 -0
- package/.aios-core/development/tasks/po-close-story.md +7 -0
- package/.aios-core/development/tasks/pr-automation.md +5 -5
- package/.aios-core/development/tasks/qa-create-fix-request.md +7 -0
- package/.aios-core/development/tasks/qa-fix-issues.md +7 -0
- package/.aios-core/development/tasks/qa-gate.md +56 -0
- package/.aios-core/development/tasks/qa-review-story.md +32 -1
- package/.aios-core/development/tasks/release-management.md +7 -0
- package/.aios-core/development/tasks/resolve-github-issue.md +608 -0
- package/.aios-core/development/tasks/review-contributor-pr.md +152 -0
- package/.aios-core/development/tasks/setup-llm-routing.md +1 -1
- package/.aios-core/development/tasks/spec-critique.md +8 -0
- package/.aios-core/development/tasks/spec-gather-requirements.md +7 -0
- package/.aios-core/development/tasks/spec-research-dependencies.md +4 -0
- package/.aios-core/development/tasks/spec-write-spec.md +5 -0
- package/.aios-core/development/tasks/triage-github-issues.md +356 -0
- package/.aios-core/development/tasks/validate-agents.md +4 -0
- package/.aios-core/development/tasks/validate-next-story.md +17 -0
- package/.aios-core/development/templates/agent-handoff-tmpl.yaml +48 -0
- package/.aios-core/development/templates/code-intel-integration-pattern.md +199 -0
- package/.aios-core/development/templates/ptc-entity-validation.md +113 -0
- package/.aios-core/development/templates/ptc-qa-gate.md +100 -0
- package/.aios-core/development/templates/ptc-research-aggregation.md +94 -0
- package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
- package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
- package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
- package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
- package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
- package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
- package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
- package/.aios-core/development/templates/squad/agent-template.md +11 -0
- package/.aios-core/development/templates/squad/task-template.md +21 -0
- package/.aios-core/development/templates/squad-template/LICENSE +21 -21
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +1 -1
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +1 -1
- package/.aios-core/framework-config.yaml +8 -0
- package/.aios-core/index.esm.js +1 -1
- package/.aios-core/index.js +1 -1
- package/.aios-core/infrastructure/integrations/ai-providers/index.js +1 -1
- package/.aios-core/infrastructure/schemas/task-v3-schema.json +6 -0
- package/.aios-core/infrastructure/scripts/collect-tool-usage.js +311 -0
- package/.aios-core/infrastructure/scripts/generate-optimization-report.js +497 -0
- package/.aios-core/infrastructure/scripts/generate-settings-json.js +300 -0
- package/.aios-core/infrastructure/scripts/git-config-detector.js +65 -9
- package/.aios-core/infrastructure/scripts/ide-sync/index.js +3 -1
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/github-copilot.js +184 -0
- package/.aios-core/infrastructure/scripts/repository-detector.js +3 -3
- package/.aios-core/infrastructure/templates/aios-sync.yaml.template +182 -182
- package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
- package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
- package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
- package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
- package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
- package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
- package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
- package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
- package/.aios-core/install-manifest.yaml +613 -305
- package/.aios-core/lib/build.json +1 -0
- package/.aios-core/local-config.yaml.template +71 -71
- package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
- package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
- package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
- package/.aios-core/monitor/hooks/notification.py +29 -29
- package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
- package/.aios-core/monitor/hooks/pre_compact.py +29 -29
- package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
- package/.aios-core/monitor/hooks/stop.py +29 -29
- package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
- package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
- package/.aios-core/product/templates/adr.hbs +125 -125
- package/.aios-core/product/templates/dbdr.hbs +241 -241
- package/.aios-core/product/templates/epic.hbs +212 -212
- package/.aios-core/product/templates/ide-rules/claude-rules.md +125 -0
- package/.aios-core/product/templates/pmdr.hbs +186 -186
- package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
- package/.aios-core/product/templates/prd.hbs +201 -201
- package/.aios-core/product/templates/story.hbs +263 -263
- package/.aios-core/product/templates/task.hbs +170 -170
- package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
- package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
- package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
- package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
- package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
- package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
- package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
- package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
- package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
- package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
- package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
- package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
- package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
- package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
- package/.aios-core/product/templates/tmpl-view.sql +177 -177
- package/.aios-core/scripts/pm.sh +0 -0
- package/.aios-core/user-guide.md +15 -15
- package/.aios-core/utils/filters/constants.js +10 -0
- package/.aios-core/utils/filters/content-filter.js +223 -0
- package/.aios-core/utils/filters/field-filter.js +126 -0
- package/.aios-core/utils/filters/index.js +180 -0
- package/.aios-core/utils/filters/schema-filter.js +157 -0
- package/.claude/CLAUDE.md +62 -0
- package/.claude/hooks/enforce-architecture-first.py +196 -196
- package/.claude/hooks/enforce-git-push-authority.sh +33 -0
- package/.claude/hooks/mind-clone-governance.py +192 -192
- package/.claude/hooks/read-protection.py +151 -151
- package/.claude/hooks/slug-validation.py +176 -176
- package/.claude/hooks/sql-governance.py +182 -182
- package/.claude/hooks/synapse-engine.cjs +28 -5
- package/.claude/hooks/write-path-validation.py +194 -194
- package/.claude/rules/agent-authority.md +105 -0
- package/.claude/rules/agent-handoff.md +97 -0
- package/.claude/rules/agent-memory-imports.md +15 -0
- package/.claude/rules/coderabbit-integration.md +101 -0
- package/.claude/rules/ids-principles.md +119 -0
- package/.claude/rules/story-lifecycle.md +145 -0
- package/.claude/rules/tool-examples.md +64 -0
- package/.claude/rules/tool-response-filtering.md +57 -0
- package/.claude/rules/workflow-execution.md +150 -0
- package/LICENSE +33 -33
- package/bin/aios-graph.js +9 -0
- package/bin/aios-init.js +2 -2
- package/bin/aios-minimal.js +0 -0
- package/bin/aios.js +17 -221
- package/bin/utils/detect-fsmonitor.js +70 -0
- package/bin/utils/framework-guard.js +238 -0
- package/bin/utils/validate-publish.js +108 -0
- package/package.json +6 -3
- package/packages/aios-install/bin/aios-install.js +0 -0
- package/packages/aios-install/bin/edmcp.js +0 -0
- package/packages/aios-pro-cli/bin/aios-pro.js +2 -0
- package/packages/installer/src/config/templates/core-config-template.js +25 -0
- package/packages/installer/src/installer/brownfield-upgrader.js +68 -5
- package/packages/installer/src/merger/index.js +3 -0
- package/packages/installer/src/merger/strategies/index.js +6 -0
- package/packages/installer/src/merger/strategies/yaml-merger.js +181 -0
- package/packages/installer/src/updater/index.js +4 -4
- package/packages/installer/src/wizard/i18n.js +321 -3
- package/packages/installer/src/wizard/ide-config-generator.js +173 -25
- package/packages/installer/src/wizard/index.js +119 -1
- package/packages/installer/src/wizard/pro-setup.js +137 -121
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +271 -0
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +192 -0
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +610 -0
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +134 -0
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +186 -0
- package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +309 -0
- package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +230 -0
- package/packages/installer/tests/unit/merger/strategies.test.js +2 -2
- package/packages/installer/tests/unit/merger/yaml-merger.test.js +327 -0
- package/scripts/check-markdown-links.py +352 -352
- package/scripts/dashboard-parallel-dev.sh +0 -0
- package/scripts/dashboard-parallel-phase3.sh +0 -0
- package/scripts/dashboard-parallel-phase4.sh +0 -0
- package/scripts/install-monitor-hooks.sh +0 -0
- package/scripts/package-synapse.js +2 -1
- package/pro/README.md +0 -66
- package/pro/license/degradation.js +0 -220
- package/pro/license/errors.js +0 -450
- package/pro/license/feature-gate.js +0 -354
- package/pro/license/index.js +0 -181
- package/pro/license/license-api.js +0 -651
- package/pro/license/license-cache.js +0 -523
- package/pro/license/license-crypto.js +0 -303
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getEnricher, getClient, isCodeIntelAvailable } = require('../index');
|
|
4
|
+
|
|
5
|
+
// Risk level thresholds based on blast radius (reference count)
|
|
6
|
+
// Consistent with dev-helper.js
|
|
7
|
+
const RISK_THRESHOLDS = {
|
|
8
|
+
LOW_MAX: 4, // 0-4 refs = LOW
|
|
9
|
+
MEDIUM_MAX: 15, // 5-15 refs = MEDIUM
|
|
10
|
+
// >15 refs = HIGH
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Coverage status thresholds based on test reference count
|
|
14
|
+
const COVERAGE_THRESHOLDS = {
|
|
15
|
+
INDIRECT_MAX: 2, // 1-2 test refs = INDIRECT
|
|
16
|
+
MINIMAL_MAX: 5, // 3-5 test refs = MINIMAL
|
|
17
|
+
// >5 test refs = GOOD
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* QaHelper — Code intelligence helper for @qa agent tasks.
|
|
22
|
+
*
|
|
23
|
+
* All functions return null gracefully when no provider is available.
|
|
24
|
+
* Never throws — safe to call unconditionally in task workflows.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get blast radius and risk level for a set of files.
|
|
29
|
+
* Used by qa-gate to assess impact of changes in gate decisions.
|
|
30
|
+
*
|
|
31
|
+
* @param {string[]} files - Files to assess blast radius for
|
|
32
|
+
* @returns {Promise<{blastRadius: number, riskLevel: string, references: Array}|null>}
|
|
33
|
+
*/
|
|
34
|
+
async function getBlastRadius(files) {
|
|
35
|
+
if (!files || files.length === 0) return null;
|
|
36
|
+
if (!isCodeIntelAvailable()) return null;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const enricher = getEnricher();
|
|
40
|
+
const impact = await enricher.assessImpact(files);
|
|
41
|
+
|
|
42
|
+
if (!impact) return null;
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
blastRadius: impact.blastRadius,
|
|
46
|
+
riskLevel: _calculateRiskLevel(impact.blastRadius),
|
|
47
|
+
references: impact.references || [],
|
|
48
|
+
};
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get test coverage status for a list of symbols.
|
|
56
|
+
* Used by qa-gate to assess test coverage per modified function.
|
|
57
|
+
*
|
|
58
|
+
* @param {string[]} symbols - Symbol names to check test coverage for
|
|
59
|
+
* @returns {Promise<Array<{symbol: string, status: string, testCount: number, tests: Array}>|null>}
|
|
60
|
+
*/
|
|
61
|
+
async function getTestCoverage(symbols) {
|
|
62
|
+
if (!symbols || symbols.length === 0) return null;
|
|
63
|
+
if (!isCodeIntelAvailable()) return null;
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const enricher = getEnricher();
|
|
67
|
+
const results = await Promise.all(
|
|
68
|
+
symbols.map(async (symbol) => {
|
|
69
|
+
try {
|
|
70
|
+
const tests = await enricher.findTests(symbol);
|
|
71
|
+
const testCount = tests ? tests.length : 0;
|
|
72
|
+
return {
|
|
73
|
+
symbol,
|
|
74
|
+
status: _calculateCoverageStatus(testCount),
|
|
75
|
+
testCount,
|
|
76
|
+
tests: tests || [],
|
|
77
|
+
};
|
|
78
|
+
} catch {
|
|
79
|
+
return {
|
|
80
|
+
symbol,
|
|
81
|
+
status: 'NO_TESTS',
|
|
82
|
+
testCount: 0,
|
|
83
|
+
tests: [],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
return results;
|
|
90
|
+
} catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get reference impact for a set of files — which consumers are affected.
|
|
97
|
+
* Used by qa-review-story to show consumers affected by each change.
|
|
98
|
+
*
|
|
99
|
+
* @param {string[]} files - Files to check reference impact for
|
|
100
|
+
* @returns {Promise<Array<{file: string, consumers: Array}>|null>}
|
|
101
|
+
*/
|
|
102
|
+
async function getReferenceImpact(files) {
|
|
103
|
+
if (!files || files.length === 0) return null;
|
|
104
|
+
if (!isCodeIntelAvailable()) return null;
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const client = getClient();
|
|
108
|
+
const results = await Promise.all(
|
|
109
|
+
files.map(async (file) => {
|
|
110
|
+
try {
|
|
111
|
+
const refs = await client.findReferences(file);
|
|
112
|
+
return {
|
|
113
|
+
file,
|
|
114
|
+
consumers: refs || [],
|
|
115
|
+
};
|
|
116
|
+
} catch {
|
|
117
|
+
return {
|
|
118
|
+
file,
|
|
119
|
+
consumers: [],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}),
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
return results;
|
|
126
|
+
} catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Suggest gate influence based on blast radius risk level.
|
|
133
|
+
* Returns advisory message when HIGH risk detected — never changes verdict automatically.
|
|
134
|
+
*
|
|
135
|
+
* @param {string} riskLevel - Risk level from getBlastRadius ('LOW'|'MEDIUM'|'HIGH')
|
|
136
|
+
* @returns {{advisory: string, suggestedGate: string}|null}
|
|
137
|
+
*/
|
|
138
|
+
function suggestGateInfluence(riskLevel) {
|
|
139
|
+
if (!riskLevel) return null;
|
|
140
|
+
|
|
141
|
+
if (riskLevel === 'HIGH') {
|
|
142
|
+
return {
|
|
143
|
+
advisory: 'HIGH blast radius detected. Consider CONCERNS gate with additional review recommended.',
|
|
144
|
+
suggestedGate: 'CONCERNS',
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Calculate risk level from blast radius count.
|
|
153
|
+
* Consistent with dev-helper.js thresholds.
|
|
154
|
+
* @param {number} blastRadius - Number of references affected
|
|
155
|
+
* @returns {string} 'LOW' | 'MEDIUM' | 'HIGH'
|
|
156
|
+
* @private
|
|
157
|
+
*/
|
|
158
|
+
function _calculateRiskLevel(blastRadius) {
|
|
159
|
+
if (blastRadius <= RISK_THRESHOLDS.LOW_MAX) return 'LOW';
|
|
160
|
+
if (blastRadius <= RISK_THRESHOLDS.MEDIUM_MAX) return 'MEDIUM';
|
|
161
|
+
return 'HIGH';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Calculate coverage status from test reference count.
|
|
166
|
+
* @param {number} testCount - Number of test references found
|
|
167
|
+
* @returns {string} 'NO_TESTS' | 'INDIRECT' | 'MINIMAL' | 'GOOD'
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
function _calculateCoverageStatus(testCount) {
|
|
171
|
+
if (testCount === 0) return 'NO_TESTS';
|
|
172
|
+
if (testCount <= COVERAGE_THRESHOLDS.INDIRECT_MAX) return 'INDIRECT';
|
|
173
|
+
if (testCount <= COVERAGE_THRESHOLDS.MINIMAL_MAX) return 'MINIMAL';
|
|
174
|
+
return 'GOOD';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
module.exports = {
|
|
178
|
+
getBlastRadius,
|
|
179
|
+
getTestCoverage,
|
|
180
|
+
getReferenceImpact,
|
|
181
|
+
suggestGateInfluence,
|
|
182
|
+
// Exposed for testing
|
|
183
|
+
_calculateRiskLevel,
|
|
184
|
+
_calculateCoverageStatus,
|
|
185
|
+
RISK_THRESHOLDS,
|
|
186
|
+
COVERAGE_THRESHOLDS,
|
|
187
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getEnricher, getClient, isCodeIntelAvailable } = require('../index');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* StoryHelper — Code intelligence helper for @sm/@po agent tasks.
|
|
7
|
+
*
|
|
8
|
+
* All functions return null gracefully when no provider is available.
|
|
9
|
+
* Never throws — safe to call unconditionally in task workflows.
|
|
10
|
+
*
|
|
11
|
+
* Functions:
|
|
12
|
+
* - detectDuplicateStory(description) — for @sm story creation (advisory warning)
|
|
13
|
+
* - suggestRelevantFiles(description) — for @sm story creation (file suggestions)
|
|
14
|
+
* - validateNoDuplicates(description) — for @po story validation (checklist boolean)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Detect duplicate stories/functionality in the codebase.
|
|
19
|
+
* Used by @sm during story creation — returns advisory warning only, never blocks.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} description - Story description to check for duplicates
|
|
22
|
+
* @returns {Promise<{matches: Array, warning: string}|null>} Duplicate info or null
|
|
23
|
+
*/
|
|
24
|
+
async function detectDuplicateStory(description) {
|
|
25
|
+
if (!description) return null;
|
|
26
|
+
if (!isCodeIntelAvailable()) return null;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const enricher = getEnricher();
|
|
30
|
+
const result = await enricher.detectDuplicates(description, { path: '.' });
|
|
31
|
+
|
|
32
|
+
if (!result || !result.matches || result.matches.length === 0) return null;
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
matches: result.matches,
|
|
36
|
+
warning: _formatDuplicateWarning(result.matches),
|
|
37
|
+
};
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Suggest relevant files for a new story based on description.
|
|
45
|
+
* Composes findReferences + analyzeCodebase for comprehensive file suggestions.
|
|
46
|
+
* Used by @sm during story creation to pre-populate "Suggested Files" section.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} description - Story description to find relevant files for
|
|
49
|
+
* @returns {Promise<{files: Array, codebaseContext: Object|null}|null>} File suggestions or null
|
|
50
|
+
*/
|
|
51
|
+
async function suggestRelevantFiles(description) {
|
|
52
|
+
if (!description) return null;
|
|
53
|
+
if (!isCodeIntelAvailable()) return null;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const client = getClient();
|
|
57
|
+
|
|
58
|
+
// Per-capability try/catch — partial results accepted
|
|
59
|
+
let files = null;
|
|
60
|
+
let codebaseContext = null;
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const refs = await client.findReferences(description);
|
|
64
|
+
if (refs) {
|
|
65
|
+
files = refs;
|
|
66
|
+
}
|
|
67
|
+
} catch { /* skip — partial result ok */ }
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const analysis = await client.analyzeCodebase('.');
|
|
71
|
+
if (analysis) {
|
|
72
|
+
codebaseContext = analysis;
|
|
73
|
+
}
|
|
74
|
+
} catch { /* skip — partial result ok */ }
|
|
75
|
+
|
|
76
|
+
// Return null only if we got nothing at all
|
|
77
|
+
if (!files && !codebaseContext) return null;
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
files: files || [],
|
|
81
|
+
codebaseContext,
|
|
82
|
+
};
|
|
83
|
+
} catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validate that a story description does not duplicate existing functionality.
|
|
90
|
+
* Used by @po during story validation — returns boolean for checklist item.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} description - Story description to validate
|
|
93
|
+
* @returns {Promise<{hasDuplicates: boolean, matches: Array, suggestion: string|null}|null>} Validation result or null
|
|
94
|
+
*/
|
|
95
|
+
async function validateNoDuplicates(description) {
|
|
96
|
+
if (!description) return null;
|
|
97
|
+
if (!isCodeIntelAvailable()) return null;
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const enricher = getEnricher();
|
|
101
|
+
const result = await enricher.detectDuplicates(description, { path: '.' });
|
|
102
|
+
|
|
103
|
+
if (!result) {
|
|
104
|
+
return {
|
|
105
|
+
hasDuplicates: false,
|
|
106
|
+
matches: [],
|
|
107
|
+
suggestion: null,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const hasDuplicates = result.matches && result.matches.length > 0;
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
hasDuplicates,
|
|
115
|
+
matches: result.matches || [],
|
|
116
|
+
suggestion: hasDuplicates ? 'Consider ADAPT instead of CREATE — similar functionality exists' : null,
|
|
117
|
+
};
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Format a human-readable warning message from duplicate matches.
|
|
125
|
+
* @param {Array} matches - Array of duplicate match objects
|
|
126
|
+
* @returns {string} Formatted warning message
|
|
127
|
+
* @private
|
|
128
|
+
*/
|
|
129
|
+
function _formatDuplicateWarning(matches) {
|
|
130
|
+
if (!matches || matches.length === 0) return '';
|
|
131
|
+
|
|
132
|
+
const fileList = matches
|
|
133
|
+
.map((m) => m.file || m.path || 'unknown')
|
|
134
|
+
.slice(0, 5)
|
|
135
|
+
.join(', ');
|
|
136
|
+
|
|
137
|
+
return `Similar functionality already exists in: ${fileList}. Consider ADAPT instead of CREATE.`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = {
|
|
141
|
+
detectDuplicateStory,
|
|
142
|
+
suggestRelevantFiles,
|
|
143
|
+
validateNoDuplicates,
|
|
144
|
+
// Exposed for testing
|
|
145
|
+
_formatDuplicateWarning,
|
|
146
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { RegistryProvider } = require('./providers/registry-provider');
|
|
5
|
+
|
|
6
|
+
/** Cached provider instance (survives across hook invocations in same process). */
|
|
7
|
+
let _provider = null;
|
|
8
|
+
let _providerRoot = null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get or create a RegistryProvider singleton.
|
|
12
|
+
* Resets if projectRoot changes between calls.
|
|
13
|
+
* @param {string} projectRoot - Project root directory
|
|
14
|
+
* @returns {RegistryProvider}
|
|
15
|
+
*/
|
|
16
|
+
function getProvider(projectRoot) {
|
|
17
|
+
if (!_provider || _providerRoot !== projectRoot) {
|
|
18
|
+
_provider = new RegistryProvider({ projectRoot });
|
|
19
|
+
_providerRoot = projectRoot;
|
|
20
|
+
}
|
|
21
|
+
return _provider;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve code intelligence context for a file being written/edited.
|
|
26
|
+
*
|
|
27
|
+
* Queries RegistryProvider for:
|
|
28
|
+
* - Entity definition (path, layer, purpose, type)
|
|
29
|
+
* - References (files that use this entity)
|
|
30
|
+
* - Dependencies (entities this file depends on)
|
|
31
|
+
*
|
|
32
|
+
* @param {string} filePath - Absolute or relative path to the target file
|
|
33
|
+
* @param {string} cwd - Project root / working directory
|
|
34
|
+
* @returns {{ entity: Object|null, references: Array|null, dependencies: Object|null }|null}
|
|
35
|
+
*/
|
|
36
|
+
async function resolveCodeIntel(filePath, cwd) {
|
|
37
|
+
if (!filePath || !cwd) return null;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const provider = getProvider(cwd);
|
|
41
|
+
if (!provider.isAvailable()) return null;
|
|
42
|
+
|
|
43
|
+
// Normalize to relative path (registry uses relative paths)
|
|
44
|
+
let relativePath = filePath;
|
|
45
|
+
if (path.isAbsolute(filePath)) {
|
|
46
|
+
relativePath = path.relative(cwd, filePath).replace(/\\/g, '/');
|
|
47
|
+
} else {
|
|
48
|
+
relativePath = filePath.replace(/\\/g, '/');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Run all three queries in parallel
|
|
52
|
+
const [definition, references, dependencies] = await Promise.all([
|
|
53
|
+
provider.findDefinition(relativePath),
|
|
54
|
+
provider.findReferences(relativePath),
|
|
55
|
+
provider.analyzeDependencies(relativePath),
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
// Treat empty dependency graph as no data
|
|
59
|
+
const hasUsefulDeps = dependencies && dependencies.nodes && dependencies.nodes.length > 0;
|
|
60
|
+
|
|
61
|
+
// If nothing found at all, try searching by the file basename
|
|
62
|
+
if (!definition && !references && !hasUsefulDeps) {
|
|
63
|
+
const basename = path.basename(relativePath, path.extname(relativePath));
|
|
64
|
+
const fallbackDef = await provider.findDefinition(basename);
|
|
65
|
+
if (!fallbackDef) return null;
|
|
66
|
+
|
|
67
|
+
const [fallbackRefs, fallbackDeps] = await Promise.all([
|
|
68
|
+
provider.findReferences(basename),
|
|
69
|
+
provider.analyzeDependencies(basename),
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
entity: fallbackDef,
|
|
74
|
+
references: fallbackRefs,
|
|
75
|
+
dependencies: fallbackDeps,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
entity: definition,
|
|
81
|
+
references,
|
|
82
|
+
dependencies,
|
|
83
|
+
};
|
|
84
|
+
} catch (_err) {
|
|
85
|
+
// Guard against provider exceptions to avoid unhandled rejections in hook runtime
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Format code intelligence data as XML for injection into Claude context.
|
|
92
|
+
*
|
|
93
|
+
* @param {Object|null} intel - Result from resolveCodeIntel()
|
|
94
|
+
* @param {string} filePath - Target file path (for display)
|
|
95
|
+
* @returns {string|null} XML string or null if no data
|
|
96
|
+
*/
|
|
97
|
+
function formatAsXml(intel, filePath) {
|
|
98
|
+
if (!intel) return null;
|
|
99
|
+
|
|
100
|
+
const { entity, references, dependencies } = intel;
|
|
101
|
+
|
|
102
|
+
// At least one piece of data must exist
|
|
103
|
+
if (!entity && !references && !dependencies) return null;
|
|
104
|
+
|
|
105
|
+
const lines = ['<code-intel-context>'];
|
|
106
|
+
lines.push(` <target-file>${escapeXml(filePath)}</target-file>`);
|
|
107
|
+
|
|
108
|
+
// Entity definition
|
|
109
|
+
if (entity) {
|
|
110
|
+
lines.push(' <existing-entity>');
|
|
111
|
+
if (entity.file) lines.push(` <path>${escapeXml(entity.file)}</path>`);
|
|
112
|
+
if (entity.context) lines.push(` <purpose>${escapeXml(entity.context)}</purpose>`);
|
|
113
|
+
lines.push(' </existing-entity>');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// References
|
|
117
|
+
if (references && references.length > 0) {
|
|
118
|
+
// Deduplicate by file path
|
|
119
|
+
const uniqueRefs = [];
|
|
120
|
+
const seen = new Set();
|
|
121
|
+
for (const ref of references) {
|
|
122
|
+
if (ref.file && !seen.has(ref.file)) {
|
|
123
|
+
seen.add(ref.file);
|
|
124
|
+
uniqueRefs.push(ref);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
lines.push(` <referenced-by count="${uniqueRefs.length}">`);
|
|
129
|
+
for (const ref of uniqueRefs.slice(0, 15)) {
|
|
130
|
+
const ctx = ref.context ? ` context="${escapeXml(ref.context)}"` : '';
|
|
131
|
+
lines.push(` <ref file="${escapeXml(ref.file)}"${ctx} />`);
|
|
132
|
+
}
|
|
133
|
+
if (uniqueRefs.length > 15) {
|
|
134
|
+
lines.push(` <!-- ...and ${uniqueRefs.length - 15} more -->`);
|
|
135
|
+
}
|
|
136
|
+
lines.push(' </referenced-by>');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Dependencies
|
|
140
|
+
if (dependencies && dependencies.nodes && dependencies.nodes.length > 1) {
|
|
141
|
+
// First node is the target itself, rest are dependencies
|
|
142
|
+
const depNodes = dependencies.nodes.slice(1);
|
|
143
|
+
lines.push(` <dependencies count="${depNodes.length}">`);
|
|
144
|
+
for (const dep of depNodes.slice(0, 10)) {
|
|
145
|
+
const layer = dep.layer ? ` layer="${dep.layer}"` : '';
|
|
146
|
+
lines.push(` <dep name="${escapeXml(dep.name)}"${layer} />`);
|
|
147
|
+
}
|
|
148
|
+
if (depNodes.length > 10) {
|
|
149
|
+
lines.push(` <!-- ...and ${depNodes.length - 10} more -->`);
|
|
150
|
+
}
|
|
151
|
+
lines.push(' </dependencies>');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
lines.push('</code-intel-context>');
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Escape special XML characters.
|
|
160
|
+
* @param {string} str
|
|
161
|
+
* @returns {string}
|
|
162
|
+
*/
|
|
163
|
+
function escapeXml(str) {
|
|
164
|
+
if (!str) return '';
|
|
165
|
+
return String(str)
|
|
166
|
+
.replace(/&/g, '&')
|
|
167
|
+
.replace(/</g, '<')
|
|
168
|
+
.replace(/>/g, '>')
|
|
169
|
+
.replace(/"/g, '"');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Reset cached provider (for testing).
|
|
174
|
+
*/
|
|
175
|
+
function _resetForTesting() {
|
|
176
|
+
_provider = null;
|
|
177
|
+
_providerRoot = null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = {
|
|
181
|
+
resolveCodeIntel,
|
|
182
|
+
formatAsXml,
|
|
183
|
+
escapeXml,
|
|
184
|
+
getProvider,
|
|
185
|
+
_resetForTesting,
|
|
186
|
+
};
|
|
@@ -4,6 +4,7 @@ const { CodeIntelClient } = require('./code-intel-client');
|
|
|
4
4
|
const { CodeIntelEnricher } = require('./code-intel-enricher');
|
|
5
5
|
const { CodeIntelProvider, CAPABILITIES } = require('./providers/provider-interface');
|
|
6
6
|
const { CodeGraphProvider, TOOL_MAP } = require('./providers/code-graph-provider');
|
|
7
|
+
const { RegistryProvider } = require('./providers/registry-provider');
|
|
7
8
|
|
|
8
9
|
// Singleton client instance (lazily initialized)
|
|
9
10
|
let _defaultClient = null;
|
|
@@ -127,6 +128,7 @@ module.exports = {
|
|
|
127
128
|
CodeIntelEnricher,
|
|
128
129
|
CodeIntelProvider,
|
|
129
130
|
CodeGraphProvider,
|
|
131
|
+
RegistryProvider,
|
|
130
132
|
|
|
131
133
|
// Constants
|
|
132
134
|
CAPABILITIES,
|
|
@@ -29,6 +29,14 @@ class CodeGraphProvider extends CodeIntelProvider {
|
|
|
29
29
|
this._mcpServerName = options.mcpServerName || 'code-graph';
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Code Graph provider is available when mcpCallFn is configured.
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
isAvailable() {
|
|
37
|
+
return typeof this.options.mcpCallFn === 'function';
|
|
38
|
+
}
|
|
39
|
+
|
|
32
40
|
/**
|
|
33
41
|
* Execute an MCP tool call via the configured server.
|
|
34
42
|
* This method is the single point of MCP communication — all capabilities route through here.
|
|
@@ -14,6 +14,15 @@ class CodeIntelProvider {
|
|
|
14
14
|
this.options = options;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Check if this provider is available and can serve requests.
|
|
19
|
+
* Subclasses MUST override this to indicate availability.
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
isAvailable() {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
/**
|
|
18
27
|
* Locate the definition of a symbol.
|
|
19
28
|
* @param {string} symbol - Symbol name to find
|