aios-core 4.2.15 → 4.3.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/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/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 +57 -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 +107 -0
- package/.aios-core/core/doctor/checks/ide-sync.js +68 -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/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 +10424 -2127
- 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/development/agents/analyst/MEMORY.md +33 -0
- package/.aios-core/development/agents/architect/MEMORY.md +39 -0
- package/.aios-core/development/agents/data-engineer/MEMORY.md +32 -0
- package/.aios-core/development/agents/dev/MEMORY.md +46 -0
- package/.aios-core/development/agents/dev.md +1 -1
- package/.aios-core/development/agents/devops/MEMORY.md +39 -0
- package/.aios-core/development/agents/devops.md +22 -0
- package/.aios-core/development/agents/pm/MEMORY.md +38 -0
- package/.aios-core/development/agents/po/MEMORY.md +45 -0
- package/.aios-core/development/agents/qa/MEMORY.md +42 -0
- package/.aios-core/development/agents/qa.md +1 -1
- package/.aios-core/development/agents/sm/MEMORY.md +31 -0
- package/.aios-core/development/agents/ux/MEMORY.md +31 -0
- 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/brownfield-create-epic.md +41 -0
- package/.aios-core/development/tasks/create-doc.md +44 -0
- package/.aios-core/development/tasks/create-next-story.md +10 -0
- package/.aios-core/development/tasks/dev-develop-story.md +1 -1
- package/.aios-core/development/tasks/github-devops-github-pr-automation.md +49 -0
- package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +63 -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/pr-automation.md +5 -5
- package/.aios-core/development/tasks/qa-gate.md +48 -0
- package/.aios-core/development/tasks/qa-review-story.md +24 -1
- 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-research-dependencies.md +4 -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 +10 -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 +541 -249
- 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 +77 -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/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 +152 -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 +261 -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 +551 -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
|
@@ -189,7 +189,7 @@ async function runValidation(options) {
|
|
|
189
189
|
const possibleSources = [
|
|
190
190
|
path.join(__dirname, '../../../../..'), // npm package root
|
|
191
191
|
path.join(projectRoot, 'node_modules/aios-core'),
|
|
192
|
-
path.join(projectRoot, 'node_modules
|
|
192
|
+
path.join(projectRoot, 'node_modules/aios-core'),
|
|
193
193
|
];
|
|
194
194
|
|
|
195
195
|
for (const src of possibleSources) {
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getEnricher, getClient, isCodeIntelAvailable } = require('../index');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CreationHelper — Code intelligence helper for squad-creator and artefact creation 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
|
+
* - getCodebaseContext(targetPath) — project structure + conventions for agent creation
|
|
13
|
+
* - checkDuplicateArtefact(name, description) — duplicate detection before artefact creation
|
|
14
|
+
* - enrichRegistryEntry(entityName, entityPath) — pre-populate usedBy/dependencies for entity registry
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get codebase context for enriching agent/artefact creation.
|
|
19
|
+
* Combines describeProject + getConventions to provide full awareness.
|
|
20
|
+
* Used by squad-creator when creating new agents — advisory, never blocks creation.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} [targetPath='.'] - Path to analyze
|
|
23
|
+
* @returns {Promise<{project: Object, conventions: Object}|null>} Codebase context or null
|
|
24
|
+
*/
|
|
25
|
+
async function getCodebaseContext(targetPath) {
|
|
26
|
+
const path = targetPath || '.';
|
|
27
|
+
if (!isCodeIntelAvailable()) return null;
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const enricher = getEnricher();
|
|
31
|
+
|
|
32
|
+
// Per-capability try/catch — partial results accepted
|
|
33
|
+
let project = null;
|
|
34
|
+
let conventions = null;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
project = await enricher.describeProject(path);
|
|
38
|
+
} catch { /* skip — partial result ok */ }
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
conventions = await enricher.getConventions(path);
|
|
42
|
+
} catch { /* skip — partial result ok */ }
|
|
43
|
+
|
|
44
|
+
// Return null only if we got nothing at all
|
|
45
|
+
if (!project && !conventions) return null;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
project,
|
|
49
|
+
conventions,
|
|
50
|
+
};
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check for duplicate artefacts before creating a new one.
|
|
58
|
+
* Combines detectDuplicates + findReferences for comprehensive detection.
|
|
59
|
+
* Used by task creation workflows — returns advisory warning, never blocks.
|
|
60
|
+
*
|
|
61
|
+
* @param {string} name - Name of the artefact to create
|
|
62
|
+
* @param {string} description - Description of the artefact
|
|
63
|
+
* @returns {Promise<{duplicates: Array, references: Array, warning: string}|null>} Duplicate info or null
|
|
64
|
+
*/
|
|
65
|
+
async function checkDuplicateArtefact(name, description) {
|
|
66
|
+
if (!name && !description) return null;
|
|
67
|
+
if (!isCodeIntelAvailable()) return null;
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const enricher = getEnricher();
|
|
71
|
+
const client = getClient();
|
|
72
|
+
|
|
73
|
+
// Per-capability try/catch — partial results accepted
|
|
74
|
+
let dupes = null;
|
|
75
|
+
let refs = null;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const searchText = description || name;
|
|
79
|
+
dupes = await enricher.detectDuplicates(searchText, { path: '.' });
|
|
80
|
+
} catch { /* skip — partial result ok */ }
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
refs = await client.findReferences(name);
|
|
84
|
+
} catch { /* skip — partial result ok */ }
|
|
85
|
+
|
|
86
|
+
const hasMatches = (dupes && dupes.matches && dupes.matches.length > 0) ||
|
|
87
|
+
(refs && refs.length > 0);
|
|
88
|
+
|
|
89
|
+
if (!hasMatches) return null;
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
duplicates: dupes ? (dupes.matches || []) : [],
|
|
93
|
+
references: refs || [],
|
|
94
|
+
warning: _formatDuplicateWarning(name, dupes, refs),
|
|
95
|
+
};
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Enrich an entity registry entry with real dependency data.
|
|
103
|
+
* Combines findReferences + analyzeDependencies to pre-populate usedBy/dependencies.
|
|
104
|
+
* Used during entity auto-registration — advisory, registry works without it.
|
|
105
|
+
*
|
|
106
|
+
* @param {string} entityName - Name of the entity being registered
|
|
107
|
+
* @param {string} entityPath - File path of the entity
|
|
108
|
+
* @returns {Promise<{usedBy: Array, dependencies: Object}|null>} Registry enrichment data or null
|
|
109
|
+
*/
|
|
110
|
+
async function enrichRegistryEntry(entityName, entityPath) {
|
|
111
|
+
if (!entityName && !entityPath) return null;
|
|
112
|
+
if (!isCodeIntelAvailable()) return null;
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const client = getClient();
|
|
116
|
+
|
|
117
|
+
// Per-capability try/catch — partial results accepted
|
|
118
|
+
let usedBy = null;
|
|
119
|
+
let dependencies = null;
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const refs = await client.findReferences(entityName);
|
|
123
|
+
if (refs && refs.length > 0) {
|
|
124
|
+
usedBy = refs.map((ref) => ref.file).filter(Boolean);
|
|
125
|
+
// Deduplicate
|
|
126
|
+
usedBy = [...new Set(usedBy)];
|
|
127
|
+
}
|
|
128
|
+
} catch { /* skip — partial result ok */ }
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
if (entityPath) {
|
|
132
|
+
const deps = await client.analyzeDependencies(entityPath);
|
|
133
|
+
if (deps) {
|
|
134
|
+
dependencies = deps;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch { /* skip — partial result ok */ }
|
|
138
|
+
|
|
139
|
+
// Return null only if we got nothing at all
|
|
140
|
+
if (!usedBy && !dependencies) return null;
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
usedBy: usedBy || [],
|
|
144
|
+
dependencies: dependencies || { nodes: [], edges: [] },
|
|
145
|
+
};
|
|
146
|
+
} catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Format a human-readable duplicate warning message.
|
|
153
|
+
* @param {string} name - Artefact name
|
|
154
|
+
* @param {Object|null} dupes - Result from detectDuplicates
|
|
155
|
+
* @param {Array|null} refs - Result from findReferences
|
|
156
|
+
* @returns {string} Formatted warning message
|
|
157
|
+
* @private
|
|
158
|
+
*/
|
|
159
|
+
function _formatDuplicateWarning(name, dupes, refs) {
|
|
160
|
+
const parts = [];
|
|
161
|
+
|
|
162
|
+
if (dupes && dupes.matches && dupes.matches.length > 0) {
|
|
163
|
+
const firstMatch = dupes.matches[0];
|
|
164
|
+
const location = firstMatch.file || firstMatch.path || 'unknown';
|
|
165
|
+
parts.push(`Similar artefact exists: ${location}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (refs && refs.length > 0) {
|
|
169
|
+
parts.push(`"${name}" already referenced in ${refs.length} location(s)`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
parts.push('Consider extending instead of creating new (IDS Article IV-A)');
|
|
173
|
+
|
|
174
|
+
return parts.join('. ') + '.';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
module.exports = {
|
|
178
|
+
getCodebaseContext,
|
|
179
|
+
checkDuplicateArtefact,
|
|
180
|
+
enrichRegistryEntry,
|
|
181
|
+
// Exposed for testing
|
|
182
|
+
_formatDuplicateWarning,
|
|
183
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getEnricher, isCodeIntelAvailable } = require('../index');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DevOpsHelper — Code intelligence helper for @devops 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
|
+
* - assessPrePushImpact(files) — for @devops pre-push quality gate (blast radius + risk)
|
|
13
|
+
* - generateImpactSummary(files) — for @devops PR automation (impact summary for PR description)
|
|
14
|
+
* - classifyRiskLevel(blastRadius) — pure logic risk classification (LOW/MEDIUM/HIGH)
|
|
15
|
+
* - _formatImpactReport(impact, riskLevel) — private formatting helper
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Assess impact of changed files for the pre-push quality gate.
|
|
20
|
+
* Used by @devops during *pre-push — returns blast radius, risk level, and formatted report.
|
|
21
|
+
*
|
|
22
|
+
* @param {string[]} files - Array of changed file paths
|
|
23
|
+
* @returns {Promise<{impact: Object, riskLevel: string, report: string}|null>} Impact analysis or null
|
|
24
|
+
*/
|
|
25
|
+
async function assessPrePushImpact(files) {
|
|
26
|
+
if (!files || files.length === 0) return null;
|
|
27
|
+
if (!isCodeIntelAvailable()) return null;
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const enricher = getEnricher();
|
|
31
|
+
const impact = await enricher.assessImpact(files);
|
|
32
|
+
|
|
33
|
+
if (!impact) {
|
|
34
|
+
return {
|
|
35
|
+
impact: null,
|
|
36
|
+
riskLevel: 'LOW',
|
|
37
|
+
report: _formatImpactReport(null, 'LOW'),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const riskLevel = classifyRiskLevel(impact.blastRadius);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
impact,
|
|
45
|
+
riskLevel,
|
|
46
|
+
report: _formatImpactReport(impact, riskLevel),
|
|
47
|
+
};
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Generate an impact summary for PR description enrichment.
|
|
55
|
+
* Composes assessImpact + findTests to provide summary text and test coverage info.
|
|
56
|
+
* Used by @devops during *create-pr — returns summary for PR body.
|
|
57
|
+
*
|
|
58
|
+
* @param {string[]} files - Array of changed file paths
|
|
59
|
+
* @returns {Promise<{summary: string, testCoverage: Array|null}|null>} Impact summary or null
|
|
60
|
+
*/
|
|
61
|
+
async function generateImpactSummary(files) {
|
|
62
|
+
if (!files || files.length === 0) return null;
|
|
63
|
+
if (!isCodeIntelAvailable()) return null;
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const enricher = getEnricher();
|
|
67
|
+
const impact = await enricher.assessImpact(files);
|
|
68
|
+
|
|
69
|
+
if (!impact) return null;
|
|
70
|
+
|
|
71
|
+
// Per-capability try/catch — partial results accepted
|
|
72
|
+
let testCoverage = null;
|
|
73
|
+
try {
|
|
74
|
+
const tests = await enricher.findTests(files[0]);
|
|
75
|
+
if (tests) {
|
|
76
|
+
testCoverage = tests;
|
|
77
|
+
}
|
|
78
|
+
} catch { /* skip — partial result ok */ }
|
|
79
|
+
|
|
80
|
+
const riskLevel = classifyRiskLevel(impact.blastRadius);
|
|
81
|
+
const fileCount = impact.references ? impact.references.length : 0;
|
|
82
|
+
const topFiles = (impact.references || [])
|
|
83
|
+
.map((r) => r.file || r.path || 'unknown')
|
|
84
|
+
.slice(0, 10);
|
|
85
|
+
|
|
86
|
+
const summaryLines = [
|
|
87
|
+
`**Blast Radius:** ${impact.blastRadius} files affected`,
|
|
88
|
+
`**Risk Level:** ${riskLevel}`,
|
|
89
|
+
`**Avg Complexity:** ${impact.complexity ? impact.complexity.average.toFixed(1) : 'N/A'}`,
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
if (topFiles.length > 0) {
|
|
93
|
+
summaryLines.push('', '**Affected Files:**');
|
|
94
|
+
topFiles.forEach((f) => summaryLines.push(`- ${f}`));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (testCoverage && testCoverage.length > 0) {
|
|
98
|
+
summaryLines.push('', `**Related Tests:** ${testCoverage.length} test file(s) found`);
|
|
99
|
+
} else {
|
|
100
|
+
summaryLines.push('', '**Related Tests:** No related tests found');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
summary: summaryLines.join('\n'),
|
|
105
|
+
testCoverage,
|
|
106
|
+
};
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Classify risk level based on blast radius count.
|
|
114
|
+
* Pure logic function — no provider dependency.
|
|
115
|
+
*
|
|
116
|
+
* @param {number} blastRadius - Number of affected files
|
|
117
|
+
* @returns {string} 'LOW' | 'MEDIUM' | 'HIGH'
|
|
118
|
+
*/
|
|
119
|
+
function classifyRiskLevel(blastRadius) {
|
|
120
|
+
if (!blastRadius || blastRadius <= 5) return 'LOW';
|
|
121
|
+
if (blastRadius <= 15) return 'MEDIUM';
|
|
122
|
+
return 'HIGH';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Format a human-readable impact report for pre-push output.
|
|
127
|
+
* @param {Object|null} impact - Impact analysis result from enricher.assessImpact
|
|
128
|
+
* @param {string} riskLevel - Risk level classification
|
|
129
|
+
* @returns {string} Formatted report string
|
|
130
|
+
* @private
|
|
131
|
+
*/
|
|
132
|
+
function _formatImpactReport(impact, riskLevel) {
|
|
133
|
+
if (!impact) {
|
|
134
|
+
return '📊 Impact Analysis: No impact data available (code intelligence returned empty result)';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const lines = [
|
|
138
|
+
'📊 Impact Analysis:',
|
|
139
|
+
` Blast Radius: ${impact.blastRadius} files affected`,
|
|
140
|
+
` Risk Level: ${riskLevel}`,
|
|
141
|
+
` Avg Complexity: ${impact.complexity ? impact.complexity.average.toFixed(1) : 'N/A'}`,
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
const topFiles = (impact.references || [])
|
|
145
|
+
.map((r) => r.file || r.path || 'unknown')
|
|
146
|
+
.slice(0, 10);
|
|
147
|
+
|
|
148
|
+
if (topFiles.length > 0) {
|
|
149
|
+
lines.push(' Top affected files:');
|
|
150
|
+
topFiles.forEach((f) => lines.push(` - ${f}`));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (riskLevel === 'HIGH') {
|
|
154
|
+
lines.push('', ` ⚠️ HIGH RISK: ${impact.blastRadius} files affected. Confirm push?`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return lines.join('\n');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
module.exports = {
|
|
161
|
+
assessPrePushImpact,
|
|
162
|
+
generateImpactSummary,
|
|
163
|
+
classifyRiskLevel,
|
|
164
|
+
// Exposed for testing
|
|
165
|
+
_formatImpactReport,
|
|
166
|
+
};
|
|
@@ -0,0 +1,248 @@
|
|
|
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 and qa-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
|
+
/**
|
|
14
|
+
* PlanningHelper — Code intelligence helper for @pm/@architect agent tasks.
|
|
15
|
+
*
|
|
16
|
+
* All functions return null gracefully when no provider is available.
|
|
17
|
+
* Never throws — safe to call unconditionally in task workflows.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get codebase overview with project description and statistics.
|
|
22
|
+
* Used by brownfield-create-epic and create-doc for Codebase Intelligence section.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} path - Path to analyze
|
|
25
|
+
* @returns {Promise<{codebase: Object, stats: Object}|null>}
|
|
26
|
+
*/
|
|
27
|
+
async function getCodebaseOverview(path) {
|
|
28
|
+
if (!path) return null;
|
|
29
|
+
if (!isCodeIntelAvailable()) return null;
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const enricher = getEnricher();
|
|
33
|
+
const project = await enricher.describeProject(path);
|
|
34
|
+
|
|
35
|
+
if (!project) return null;
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
codebase: project.codebase || null,
|
|
39
|
+
stats: project.stats || null,
|
|
40
|
+
};
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get dependency graph summary for a path.
|
|
48
|
+
* Used by brownfield-create-epic and analyze-project-structure for dependency analysis.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} path - Path to analyze dependencies for
|
|
51
|
+
* @returns {Promise<{dependencies: Object, summary: {totalDeps: number, depth: string}}|null>}
|
|
52
|
+
*/
|
|
53
|
+
async function getDependencyGraph(path) {
|
|
54
|
+
if (!path) return null;
|
|
55
|
+
if (!isCodeIntelAvailable()) return null;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const client = getClient();
|
|
59
|
+
const deps = await client.analyzeDependencies(path);
|
|
60
|
+
|
|
61
|
+
if (!deps) return null;
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
dependencies: deps,
|
|
65
|
+
summary: _buildDependencySummary(deps),
|
|
66
|
+
};
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get complexity analysis for a set of files.
|
|
74
|
+
* Used by analyze-project-structure for complexity metrics per file.
|
|
75
|
+
*
|
|
76
|
+
* @param {string[]} files - Files to analyze complexity for
|
|
77
|
+
* @returns {Promise<{perFile: Array<{file: string, complexity: Object}>, average: number}|null>}
|
|
78
|
+
*/
|
|
79
|
+
async function getComplexityAnalysis(files) {
|
|
80
|
+
if (!files || files.length === 0) return null;
|
|
81
|
+
if (!isCodeIntelAvailable()) return null;
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const client = getClient();
|
|
85
|
+
const results = await Promise.all(
|
|
86
|
+
files.map(async (file) => {
|
|
87
|
+
try {
|
|
88
|
+
const complexity = await client.analyzeComplexity(file);
|
|
89
|
+
return {
|
|
90
|
+
file,
|
|
91
|
+
complexity: complexity || null,
|
|
92
|
+
};
|
|
93
|
+
} catch {
|
|
94
|
+
return {
|
|
95
|
+
file,
|
|
96
|
+
complexity: null,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const validResults = results.filter((r) => r.complexity !== null);
|
|
103
|
+
const scores = validResults
|
|
104
|
+
.map((r) => r.complexity && typeof r.complexity.score === 'number' ? r.complexity.score : null)
|
|
105
|
+
.filter((s) => s !== null);
|
|
106
|
+
const average = scores.length > 0
|
|
107
|
+
? scores.reduce((sum, s) => sum + s, 0) / scores.length
|
|
108
|
+
: 0;
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
perFile: results,
|
|
112
|
+
average,
|
|
113
|
+
};
|
|
114
|
+
} catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get implementation context for a set of symbols.
|
|
121
|
+
* Composes findDefinition + analyzeDependencies + findTests for each symbol.
|
|
122
|
+
* Used by plan-create-context for precise implementation context.
|
|
123
|
+
*
|
|
124
|
+
* @param {string[]} symbols - Symbol names to get context for
|
|
125
|
+
* @returns {Promise<{definitions: Array, dependencies: Array, relatedTests: Array}|null>}
|
|
126
|
+
*/
|
|
127
|
+
async function getImplementationContext(symbols) {
|
|
128
|
+
if (!symbols || symbols.length === 0) return null;
|
|
129
|
+
if (!isCodeIntelAvailable()) return null;
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const client = getClient();
|
|
133
|
+
const enricher = getEnricher();
|
|
134
|
+
|
|
135
|
+
const definitions = [];
|
|
136
|
+
const dependencies = [];
|
|
137
|
+
const relatedTests = [];
|
|
138
|
+
|
|
139
|
+
await Promise.all(
|
|
140
|
+
symbols.map(async (symbol) => {
|
|
141
|
+
// Per-item try/catch — partial results accepted
|
|
142
|
+
try {
|
|
143
|
+
const def = await client.findDefinition(symbol);
|
|
144
|
+
if (def) definitions.push({ symbol, ...def });
|
|
145
|
+
} catch { /* skip */ }
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const deps = await client.analyzeDependencies(symbol);
|
|
149
|
+
if (deps) dependencies.push({ symbol, deps });
|
|
150
|
+
} catch { /* skip */ }
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const tests = await enricher.findTests(symbol);
|
|
154
|
+
if (tests) relatedTests.push({ symbol, tests });
|
|
155
|
+
} catch { /* skip */ }
|
|
156
|
+
}),
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
definitions,
|
|
161
|
+
dependencies,
|
|
162
|
+
relatedTests,
|
|
163
|
+
};
|
|
164
|
+
} catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get implementation impact analysis for a set of files.
|
|
171
|
+
* Used by plan-create-implementation for blast radius and risk assessment.
|
|
172
|
+
*
|
|
173
|
+
* @param {string[]} files - Files to assess impact for
|
|
174
|
+
* @returns {Promise<{blastRadius: number, riskLevel: string, references: Array}|null>}
|
|
175
|
+
*/
|
|
176
|
+
async function getImplementationImpact(files) {
|
|
177
|
+
if (!files || files.length === 0) return null;
|
|
178
|
+
if (!isCodeIntelAvailable()) return null;
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const enricher = getEnricher();
|
|
182
|
+
const impact = await enricher.assessImpact(files);
|
|
183
|
+
|
|
184
|
+
if (!impact) return null;
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
blastRadius: impact.blastRadius,
|
|
188
|
+
riskLevel: _calculateRiskLevel(impact.blastRadius),
|
|
189
|
+
references: impact.references || [],
|
|
190
|
+
};
|
|
191
|
+
} catch {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Build a summary from dependency analysis results.
|
|
198
|
+
* @param {Object} deps - Raw dependency graph from analyzeDependencies
|
|
199
|
+
* @returns {{totalDeps: number, depth: string}}
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
function _buildDependencySummary(deps) {
|
|
203
|
+
if (!deps) return { totalDeps: 0, depth: 'none' };
|
|
204
|
+
|
|
205
|
+
// Handle various shapes of dependency data
|
|
206
|
+
let totalDeps = 0;
|
|
207
|
+
if (Array.isArray(deps)) {
|
|
208
|
+
totalDeps = deps.length;
|
|
209
|
+
} else if (deps.dependencies && Array.isArray(deps.dependencies)) {
|
|
210
|
+
totalDeps = deps.dependencies.length;
|
|
211
|
+
} else if (typeof deps === 'object') {
|
|
212
|
+
totalDeps = Object.keys(deps).length;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
let depth = 'shallow';
|
|
216
|
+
if (totalDeps > RISK_THRESHOLDS.MEDIUM_MAX) {
|
|
217
|
+
depth = 'deep';
|
|
218
|
+
} else if (totalDeps > RISK_THRESHOLDS.LOW_MAX) {
|
|
219
|
+
depth = 'moderate';
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return { totalDeps, depth };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Calculate risk level from blast radius count.
|
|
227
|
+
* Consistent with dev-helper.js and qa-helper.js thresholds.
|
|
228
|
+
* @param {number} blastRadius - Number of references affected
|
|
229
|
+
* @returns {string} 'LOW' | 'MEDIUM' | 'HIGH'
|
|
230
|
+
* @private
|
|
231
|
+
*/
|
|
232
|
+
function _calculateRiskLevel(blastRadius) {
|
|
233
|
+
if (blastRadius <= RISK_THRESHOLDS.LOW_MAX) return 'LOW';
|
|
234
|
+
if (blastRadius <= RISK_THRESHOLDS.MEDIUM_MAX) return 'MEDIUM';
|
|
235
|
+
return 'HIGH';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = {
|
|
239
|
+
getCodebaseOverview,
|
|
240
|
+
getDependencyGraph,
|
|
241
|
+
getComplexityAnalysis,
|
|
242
|
+
getImplementationContext,
|
|
243
|
+
getImplementationImpact,
|
|
244
|
+
// Exposed for testing
|
|
245
|
+
_buildDependencySummary,
|
|
246
|
+
_calculateRiskLevel,
|
|
247
|
+
RISK_THRESHOLDS,
|
|
248
|
+
};
|