octocode-cli 1.2.7 → 1.2.9
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/README.md +42 -35
- package/out/octocode-cli.js +36 -11719
- package/package.json +36 -36
- package/skills/README.md +42 -114
- package/skills/{octocode-code-engineer → octocode-engineer}/.claude/settings.local.json +2 -1
- package/skills/octocode-engineer/README.md +99 -0
- package/skills/octocode-engineer/SKILL.md +499 -0
- package/skills/octocode-engineer/build.mjs +29 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/eslint.config.mjs +3 -13
- package/skills/{octocode-code-engineer → octocode-engineer}/package.json +28 -27
- package/skills/octocode-engineer/references/ast-reference.md +166 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/references/cli-reference.md +80 -6
- package/skills/octocode-engineer/references/externals.md +86 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/references/output-files.md +46 -6
- package/skills/octocode-engineer/references/quality-indicators.md +202 -0
- package/skills/octocode-engineer/references/tool-workflows.md +298 -0
- package/skills/octocode-engineer/references/validation-playbooks.md +99 -0
- package/skills/octocode-engineer/scripts/ast/search.js +45 -0
- package/skills/octocode-engineer/scripts/ast/tree-search.js +27 -0
- package/skills/octocode-engineer/scripts/index.js +173 -0
- package/skills/octocode-engineer/scripts/run.js +179 -0
- package/skills/octocode-engineer/src/analysis/dependencies.ts +378 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/discovery.test.ts +57 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/discovery.ts +43 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/search.test.ts +113 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/search.ts +64 -1
- package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-sitter.test.ts +118 -2
- package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-sitter.ts +65 -3
- package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/ts-analyzer.test.ts +281 -1
- package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/ts-analyzer.ts +173 -3
- package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/security.test.ts +73 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/security.ts +62 -4
- package/skills/octocode-engineer/src/detector-gating.test.ts +59 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/code-quality.ts +342 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/index.ts +8 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/index.test.ts +565 -11
- package/skills/octocode-engineer/src/index.ts +468 -0
- package/skills/octocode-engineer/src/pipeline/affected.test.ts +147 -0
- package/skills/octocode-engineer/src/pipeline/affected.ts +68 -0
- package/skills/octocode-engineer/src/pipeline/baseline.test.ts +276 -0
- package/skills/octocode-engineer/src/pipeline/baseline.ts +76 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cli.test.ts +300 -53
- package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cli.ts +180 -36
- package/skills/octocode-engineer/src/pipeline/config-loader.test.ts +264 -0
- package/skills/octocode-engineer/src/pipeline/config-loader.ts +109 -0
- package/skills/octocode-engineer/src/pipeline/create-options.ts +55 -0
- package/skills/octocode-engineer/src/pipeline/health-score.test.ts +65 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/main.ts +130 -17
- package/skills/octocode-engineer/src/pipeline/progress.ts +51 -0
- package/skills/octocode-engineer/src/pipeline/reporters.test.ts +155 -0
- package/skills/octocode-engineer/src/pipeline/reporters.ts +64 -0
- package/skills/octocode-engineer/src/reporting/graph-features.test.ts +279 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/output-contract.test.ts +6 -0
- package/skills/octocode-engineer/src/reporting/summary-md.test.ts +1066 -0
- package/skills/octocode-engineer/src/reporting/summary-md.ts +1604 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/writer.ts +136 -13
- package/skills/octocode-engineer/src/run.ts +78 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/sanity.test.ts +1 -1
- package/skills/octocode-engineer/src/types/analysis.ts +25 -0
- package/skills/octocode-engineer/src/types/collectors.ts +134 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/types/constants.ts +75 -41
- package/skills/octocode-engineer/src/types/core.ts +203 -0
- package/skills/octocode-engineer/src/types/dependency.ts +215 -0
- package/skills/octocode-engineer/src/types/file-entry.ts +108 -0
- package/skills/octocode-engineer/src/types/findings.ts +105 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/src/types/index.ts +60 -30
- package/skills/octocode-engineer/src/types/tree-sitter.ts +38 -0
- package/skills/{octocode-code-engineer → octocode-engineer}/tsconfig.json +1 -0
- package/skills/octocode-research/.octocode/scan/.cache/analysis-cache.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/architecture.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/ast-trees.txt +5566 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/code-quality.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/dead-code.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/file-inventory.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/findings.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/graph.md +189 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/security.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/summary.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-32-27-073Z/summary.md +265 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/architecture.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/ast-trees.txt +5555 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/code-quality.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/dead-code.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/file-inventory.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/findings.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/graph.md +190 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/security.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/summary.json +1 -0
- package/skills/octocode-research/.octocode/scan/2026-03-22T10-40-10-469Z/summary.md +265 -0
- package/skills/octocode-research/CHANGELOG.md +60 -0
- package/skills/octocode-research/README.md +102 -388
- package/skills/octocode-research/SKILL.md +169 -498
- package/skills/octocode-research/package.json +19 -31
- package/skills/octocode-research/references/PARALLEL_AGENT_PROTOCOL.md +19 -0
- package/skills/octocode-research/references/SESSION_MANAGEMENT.md +38 -0
- package/skills/octocode-research/scripts/server-init.js +1 -1
- package/skills/octocode-research/scripts/server.d.ts +2 -1
- package/skills/octocode-research/scripts/server.js +329 -233
- package/skills/octocode-research/src/__tests__/integration/promptsRoutes.test.ts +180 -0
- package/skills/octocode-research/src/__tests__/integration/serverHttp.test.ts +221 -0
- package/skills/octocode-research/src/__tests__/integration/serverLifecycle.test.ts +194 -0
- package/skills/octocode-research/src/__tests__/integration/toolsRoutes.test.ts +501 -0
- package/skills/octocode-research/src/__tests__/unit/readiness.test.ts +61 -0
- package/skills/octocode-research/src/__tests__/unit/resilience.test.ts +192 -0
- package/skills/octocode-research/src/__tests__/unit/responseFactory.test.ts +172 -0
- package/skills/octocode-research/src/__tests__/unit/responseParser.test.ts +288 -0
- package/skills/octocode-research/src/__tests__/unit/schemas.test.ts +509 -0
- package/skills/octocode-research/src/index.ts +4 -124
- package/skills/octocode-research/src/middleware/queryParser.ts +0 -26
- package/skills/octocode-research/src/routes/lsp.ts +58 -59
- package/skills/octocode-research/src/routes/package.ts +35 -65
- package/skills/octocode-research/src/routes/prompts.ts +3 -3
- package/skills/octocode-research/src/routes/tools.ts +8 -20
- package/skills/octocode-research/src/server-init.ts +30 -237
- package/skills/octocode-research/src/server.ts +50 -23
- package/skills/octocode-research/src/types/errorGuards.ts +9 -80
- package/skills/octocode-research/src/types/guards.ts +0 -28
- package/skills/octocode-research/src/types/mcp.ts +11 -66
- package/skills/octocode-research/src/types/responses.ts +11 -129
- package/skills/octocode-research/src/utils/circuitBreaker.ts +0 -21
- package/skills/octocode-research/src/utils/logger.ts +1 -97
- package/skills/octocode-research/src/utils/resilience.ts +2 -12
- package/skills/octocode-research/src/utils/responseFactory.ts +0 -42
- package/skills/octocode-research/src/utils/responseParser.ts +3 -25
- package/skills/octocode-research/src/utils/retry.ts +0 -63
- package/skills/octocode-research/src/utils/routeFactory.ts +1 -1
- package/skills/octocode-research/src/validation/httpPreprocess.ts +0 -3
- package/skills/octocode-research/src/validation/index.ts +0 -1
- package/skills/octocode-research/src/validation/schemas.ts +0 -63
- package/skills/octocode-research/src/validation/toolCallSchema.ts +3 -3
- package/skills/octocode-research/tsdown.config.ts +4 -0
- package/skills/octocode-research/vitest.config.ts +3 -0
- package/skills/octocode-code-engineer/.plan/VALIDATED_PLAN.md +0 -223
- package/skills/octocode-code-engineer/README.md +0 -178
- package/skills/octocode-code-engineer/SKILL.md +0 -418
- package/skills/octocode-code-engineer/minify-scripts.mjs +0 -32
- package/skills/octocode-code-engineer/references/agent-ast-reading-rfc.md +0 -95
- package/skills/octocode-code-engineer/references/architecture-techniques.md +0 -121
- package/skills/octocode-code-engineer/references/ast-search.md +0 -210
- package/skills/octocode-code-engineer/references/ast-tree-search.md +0 -151
- package/skills/octocode-code-engineer/references/concepts.md +0 -107
- package/skills/octocode-code-engineer/references/finding-categories.md +0 -128
- package/skills/octocode-code-engineer/references/improvement-roadmap.md +0 -304
- package/skills/octocode-code-engineer/references/playbooks.md +0 -204
- package/skills/octocode-code-engineer/references/present-results.md +0 -136
- package/skills/octocode-code-engineer/references/tool-workflows.md +0 -566
- package/skills/octocode-code-engineer/references/validate-investigate.md +0 -225
- package/skills/octocode-code-engineer/scripts/analysis/dependencies.js +0 -1
- package/skills/octocode-code-engineer/scripts/analysis/dependency-summary.js +0 -1
- package/skills/octocode-code-engineer/scripts/analysis/discovery.js +0 -1
- package/skills/octocode-code-engineer/scripts/analysis/graph-analytics.js +0 -1
- package/skills/octocode-code-engineer/scripts/analysis/semantic.js +0 -1
- package/skills/octocode-code-engineer/scripts/ast/helpers.js +0 -1
- package/skills/octocode-code-engineer/scripts/ast/metrics.js +0 -1
- package/skills/octocode-code-engineer/scripts/ast/search.js +0 -2
- package/skills/octocode-code-engineer/scripts/ast/tree-search.js +0 -2
- package/skills/octocode-code-engineer/scripts/ast/tree-sitter.js +0 -1
- package/skills/octocode-code-engineer/scripts/ast/ts-analyzer.js +0 -1
- package/skills/octocode-code-engineer/scripts/collectors/chains.js +0 -1
- package/skills/octocode-code-engineer/scripts/collectors/effects.js +0 -1
- package/skills/octocode-code-engineer/scripts/collectors/input-sources.js +0 -1
- package/skills/octocode-code-engineer/scripts/collectors/performance.js +0 -1
- package/skills/octocode-code-engineer/scripts/collectors/prototype-pollution.js +0 -1
- package/skills/octocode-code-engineer/scripts/collectors/security.js +0 -1
- package/skills/octocode-code-engineer/scripts/collectors/test-profile.js +0 -1
- package/skills/octocode-code-engineer/scripts/common/is-direct-run.js +0 -1
- package/skills/octocode-code-engineer/scripts/common/utils.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/code-quality.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/cohesion.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/coupling.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/cycle.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/dead-code.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/import-style.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/index.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/security.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/semantic.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/shared.js +0 -1
- package/skills/octocode-code-engineer/scripts/detectors/test-quality.js +0 -1
- package/skills/octocode-code-engineer/scripts/index.js +0 -1
- package/skills/octocode-code-engineer/scripts/pipeline/cache.js +0 -1
- package/skills/octocode-code-engineer/scripts/pipeline/cli.js +0 -1
- package/skills/octocode-code-engineer/scripts/pipeline/main.js +0 -2
- package/skills/octocode-code-engineer/scripts/reporting/analysis.js +0 -1
- package/skills/octocode-code-engineer/scripts/reporting/summary-md.js +0 -1
- package/skills/octocode-code-engineer/scripts/reporting/writer.js +0 -1
- package/skills/octocode-code-engineer/scripts/types/constants.js +0 -1
- package/skills/octocode-code-engineer/scripts/types/index.js +0 -1
- package/skills/octocode-code-engineer/scripts/types/interfaces.js +0 -1
- package/skills/octocode-code-engineer/src/analysis/dependencies.ts +0 -406
- package/skills/octocode-code-engineer/src/index.ts +0 -403
- package/skills/octocode-code-engineer/src/reporting/summary-md.test.ts +0 -421
- package/skills/octocode-code-engineer/src/reporting/summary-md.ts +0 -714
- package/skills/octocode-code-engineer/src/types/interfaces.ts +0 -682
- package/skills/octocode-research/src/types/toolTypes.ts +0 -33
- package/skills/octocode-research/src/utils/logEmoji.ts +0 -103
- /package/skills/{octocode-code-engineer → octocode-engineer}/.octocode/rfc/RFC-code-engineer-weakness-fixes.md +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/architecture.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/ast-helpers.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/ast-search.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/base.css +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/block-navigation.js +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/cache.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/cli.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/clover.xml +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-effects.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-input-sources.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-performance.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-prototype-pollution.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-security.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/collect-test-profile.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/coverage-final.json +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/dependencies.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/dependency-summary.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/discovery.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/favicon.png +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/graph-analytics.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/index.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/index.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/metrics.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/pipeline.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/prettify.css +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/prettify.js +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/report-analysis.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/report-writer.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/security-detectors.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/semantic-detectors.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/semantic.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/sort-arrow-sprite.png +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/sorter.js +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/summary-md.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/test-quality-detectors.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/tree-sitter-analyzer.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/ts-analyzer.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/types.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/coverage/utils.ts.html +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/dependencies.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/dependency-summary.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/dependency-summary.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/graph-analytics.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/graph-analytics.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/semantic.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/analysis/semantic.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/helpers.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/helpers.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/metrics.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/metrics.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-search.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/ast/tree-search.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/chains.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/effects.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/effects.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/input-sources.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/input-sources.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/performance.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/performance.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/prototype-pollution.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/prototype-pollution.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/test-profile.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/collectors/test-profile.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/is-direct-run.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/is-direct-run.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/utils.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/common/utils.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/cohesion.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/coupling.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/cycle.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/dead-code.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/import-style.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/index.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/security.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/security.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/semantic.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/shared.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/test-quality.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/detectors/test-quality.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cache.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/cache.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline/main.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/pipeline.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/analysis.test.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/src/reporting/analysis.ts +0 -0
- /package/skills/{octocode-code-engineer → octocode-engineer}/vitest.config.ts +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var $o=Object.defineProperty;var N=(e,i)=>()=>(e&&(i=e(e=0)),i);var Gt=(e,i)=>{for(var n in i)$o(e,n,{get:i[n],enumerable:!0})};import ft from"node:fs";import pt from"node:path";function xs(e){let i=pt.join(e,".octocode","scan",".cache","analysis-cache.json");try{let n=JSON.parse(ft.readFileSync(i,"utf8"));return n.version!==bs||n.root!==e||n.schemaVersion!==Ss?null:n}catch{return null}}function Es(e,i){let n=pt.join(e,".octocode","scan",".cache");ft.mkdirSync(n,{recursive:!0}),ft.writeFileSync(pt.join(n,"analysis-cache.json"),JSON.stringify(i),"utf8")}function ws(e){let i=pt.join(e,".octocode","scan",".cache","analysis-cache.json");try{ft.unlinkSync(i)}catch{}}function vs(e,i,n){if(!e)return!1;let t=e.entries[i];return t?t.mtimeMs===n.mtimeMs&&t.sizeBytes===n.size:!1}function Fs(e,i){let n=e.entries[i];return n&&(n.lastAccessMs=Date.now()),n?.result}function Wt(e,i,n,t){e.entries[i]={mtimeMs:n.mtimeMs,sizeBytes:n.size,result:t,lastAccessMs:Date.now()}}function ks(e){return{version:bs,schemaVersion:Ss,root:e,entries:{}}}function Cs(e,i=Do){let n=Date.now(),t=[];for(let[s,r]of Object.entries(e.entries))n-r.lastAccessMs>i&&t.push(s);for(let s of t)delete e.entries[s];return t.length}var Ss,bs,Do,Ts=N(()=>{"use strict";Ss="1.1.0",bs=1,Do=10080*60*1e3});var $s={};Gt($s,{ALLOWED_EXTS:()=>qe,ALL_CATEGORIES:()=>Ue,DEFAULT_OPTS:()=>Me,DEFAULT_THRESHOLDS:()=>Vt,IMPORT_RESOLVE_EXTS:()=>Je,PILLAR_CATEGORIES:()=>B,SEMANTIC_CATEGORIES:()=>gt,SEVERITY_ORDER:()=>Pe,TS_CONTROL_KINDS:()=>mt,TS_TREE_SITTER_CONTROL_TYPES:()=>ht,TS_TREE_SITTER_FUNCTION_TYPES:()=>yt});import Ro from"node:path";import*as Ee from"typescript";var Vt,Me,B,Ue,gt,qe,Je,mt,ht,yt,Pe,Qt=N(()=>{"use strict";Vt={couplingThreshold:15,fanInThreshold:20,fanOutThreshold:15,godModuleStatements:500,godModuleExports:20,barrelSymbolThreshold:30,sdpMinDelta:.15,sdpMaxSourceInstability:.6,layerOrder:[],minFunctionStatements:6,minFlowStatements:6,criticalComplexityThreshold:30,godFunctionStatements:100,godFunctionMiThreshold:10,cognitiveComplexityThreshold:15,parameterThreshold:5,halsteadEffortThreshold:5e5,maintainabilityIndexThreshold:20,anyThreshold:5,flowDupThreshold:3,similarityThreshold:.85,deepNestingThreshold:5,multipleReturnThreshold:6,magicStringMinOccurrences:3,booleanParamThreshold:3,overrideChainThreshold:3,shotgunThreshold:8,secretEntropyThreshold:4.5,secretMinLength:20,mockThreshold:10},Me={root:process.cwd(),out:null,json:!1,packageRoot:Ro.join(process.cwd(),"packages"),parser:"auto",includeTests:!1,emitTree:!0,treeDepth:4,noCache:!1,clearCache:!1,semantic:!1,graph:!1,graphAdvanced:!1,flow:!1,scope:null,scopeSymbols:null,features:null,ignoreDirs:new Set([".git",".next",".yarn",".cache",".octocode","node_modules","dist","coverage","out"]),findingsLimit:1/0,noDiversify:!1,maxRecsPerCategory:2,deepLinkTopN:12,thresholds:{...Vt},affected:null,saveBaseline:!1,ignoreKnown:null,reporter:"default",focus:null,focusDepth:1,collapse:null,atLeast:null,configFile:null},B={architecture:["dependency-cycle","dependency-critical-path","dependency-test-only","architecture-sdp-violation","high-coupling","god-module-coupling","orphan-module","unreachable-module","layer-violation","low-cohesion","mega-folder","distance-from-main-sequence","feature-envy","untested-critical-code","over-abstraction","concrete-dependency","circular-type-dependency","shotgun-surgery","import-side-effect-risk","cycle-cluster","broker-module","bridge-module","package-boundary-chatter","startup-risk-hub","namespace-import","commonjs-in-esm","export-star-leak","mixed-module-format"],"code-quality":["duplicate-function-body","duplicate-flow-structure","function-optimization","cognitive-complexity","god-module","god-function","halstead-effort","low-maintainability","excessive-parameters","unsafe-any","empty-catch","switch-no-default","unused-parameter","deep-override-chain","interface-compliance","type-assertion-escape","promise-misuse","narrowable-type","missing-error-boundary","await-in-loop","sync-io","uncleared-timer","listener-leak-risk","unbounded-collection","similar-function-body","message-chain","deep-nesting","multiple-return-paths","catch-rethrow","magic-string","boolean-parameter-cluster","promise-all-unhandled","export-surface-density","change-risk"],"dead-code":["dead-export","dead-re-export","re-export-duplication","re-export-shadowed","unused-npm-dependency","package-boundary-violation","barrel-explosion","unused-import","orphan-implementation","move-to-caller","semantic-dead-export","dead-file"],security:["hardcoded-secret","eval-usage","unsafe-html","sql-injection-risk","unsafe-regex","prototype-pollution-risk","unvalidated-input-sink","input-passthrough-risk","path-traversal-risk","command-injection-risk","debug-log-leakage","sensitive-data-logging"],"test-quality":["low-assertion-density","test-no-assertion","excessive-mocking","shared-mutable-state","missing-test-cleanup","focused-test","fake-timer-no-restore","missing-mock-restoration"]},Ue=new Set(Object.values(B).flat()),gt=new Set(["over-abstraction","concrete-dependency","circular-type-dependency","unused-parameter","deep-override-chain","interface-compliance","unused-import","orphan-implementation","shotgun-surgery","move-to-caller","narrowable-type","semantic-dead-export"]),qe=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs"]),Je=[".ts",".tsx",".js",".jsx",".mjs",".cjs",".d.ts"],mt=new Set([Ee.SyntaxKind.IfStatement,Ee.SyntaxKind.SwitchStatement,Ee.SyntaxKind.TryStatement,Ee.SyntaxKind.ForStatement,Ee.SyntaxKind.WhileStatement,Ee.SyntaxKind.DoStatement,Ee.SyntaxKind.ForOfStatement,Ee.SyntaxKind.ForInStatement,Ee.SyntaxKind.ConditionalExpression]),ht=new Set(["if_statement","switch_statement","try_statement","for_statement","while_statement","do_statement","for_in_statement","for_of_statement","for_await_statement","conditional_expression","catch_clause"]),yt=new Set(["function_declaration","function","generator_function","generator_function_declaration","method_definition","arrow_function","function_expression"]),Pe={critical:4,high:3,medium:2,low:1,info:0}});var ge=N(()=>{"use strict";Qt()});var Ds={};Gt(Ds,{OptionsError:()=>Ie,createOptions:()=>St,resolveExcludeToFeatures:()=>Jt});import Ao from"node:path";function St({args:e}){let i={...e};return i.packageRoot=Ao.join(i.root,"packages"),Mo(i),i}function Mo(e){if(e.features===null)return;let i=new Set(B["test-quality"]);[...e.features].some(n=>i.has(n))&&(e.includeTests=!0)}function Jt(e){return new Set([...Ue].filter(i=>!e.has(i)))}var Ie,Ye=N(()=>{"use strict";ge();Ie=class extends Error{constructor(i){super(i),this.name="OptionsError"}}});import Xt from"node:path";function Yt(e,i){let n=parseInt(e??"",10);return Number.isNaN(n)?i:n}function Po(e,i){let n=parseFloat(e??"");return Number.isNaN(n)?i:n}function Rs(e,i,n,t){e[i]=Yt(n,t[i])}function Io(e,i,n,t){e[i]=Po(n,t[i])}function As(e,i){let n=e.split(",").map(s=>s.trim()).filter(Boolean),t=new Set;for(let s of n)if(B[s])for(let r of B[s])t.add(r);else Ue.has(s)?t.add(s):(console.error(`Unknown ${i}: "${s}". Use pillar names (${Object.keys(B).join(", ")}) or category names.`),process.exit(1));return t}function No(e,i){let n=r=>{let o=r.lastIndexOf(":");if(o<=0||o===r.length-1)return{filePath:r,symbolName:null};let a=r.substring(o+1);return a.includes("/")||a.includes("\\")?{filePath:r,symbolName:null}:{filePath:r.substring(0,o),symbolName:a}},t=[],s=new Map;for(let r of e.split(",").map(o=>o.trim()).filter(Boolean)){let{filePath:o,symbolName:a}=n(r),l=Xt.resolve(i,o);t.push(l),a&&(s.has(l)||s.set(l,[]),s.get(l).push(a))}return{paths:t,symbols:s}}function js(e){let i={...Me,thresholds:{...Me.thresholds}},n=null;for(let t=0;t<e.length;t++){let s=e[t];if(Ms[s]){Ms[s](i,!0);continue}if(Ps[s]){let r=Ps[s];Rs(i,r,e[++t],Me);continue}if(Is[s]){let r=Is[s];Rs(i.thresholds,r,e[++t],Me.thresholds);continue}if(Ns[s]){let r=Ns[s];Io(i.thresholds,r,e[++t],Me.thresholds);continue}if(Ls[s]){t=Ls[s](i,e,t);continue}if(s.startsWith("--out=")){i.out=s.slice(6);continue}if(s==="--scope"||s.startsWith("--scope=")){let r=s.startsWith("--scope=")?s.slice(8):e[++t],{paths:o,symbols:a}=No(r,i.root);i.scope=o,a.size>0&&(i.scopeSymbols=a);continue}if(s==="--features"||s.startsWith("--features=")){let r=s.startsWith("--features=")?s.slice(11):e[++t];i.features=As(r,"feature");continue}if(s==="--exclude"||s.startsWith("--exclude=")){let r=s.startsWith("--exclude=")?s.slice(10):e[++t];n=As(r,"exclude");continue}if(s==="--affected"||s.startsWith("--affected=")){i.affected=s.startsWith("--affected=")?s.slice(11):e[t+1]&&!e[t+1].startsWith("--")?e[++t]:"HEAD";continue}if(s==="--ignore-known"||s.startsWith("--ignore-known=")){i.ignoreKnown=s.startsWith("--ignore-known=")?s.slice(15):e[t+1]&&!e[t+1].startsWith("--")?e[++t]:".octocode/baseline.json";continue}if(s==="--focus"||s.startsWith("--focus=")){i.focus=s.startsWith("--focus=")?s.slice(8):e[++t];continue}if(s==="--collapse"||s.startsWith("--collapse=")){let r=s.startsWith("--collapse=")?s.slice(11):e[++t];i.collapse=Yt(r,2);continue}if(s==="--at-least"||s.startsWith("--at-least=")){let r=s.startsWith("--at-least=")?s.slice(11):e[++t];i.atLeast=Yt(r,0);continue}s.startsWith("--")&&console.warn(`Warning: unknown flag "${s}" \u2014 ignored.`)}if(i.packageRoot=Xt.join(i.root,"packages"),i.features!==null&&n!==null)throw new Ie("--features and --exclude are mutually exclusive. Use one or the other.");if(n!==null&&(i.features=Jt(n)),i.features!==null){let t=new Set(B["test-quality"]);[...i.features].some(s=>t.has(s))&&(i.includeTests=!0)}return i}function Os(){console.log(_s)}var Ms,Ps,Is,Ns,Ls,_s,Zt=N(()=>{"use strict";ge();Ye();Ms={"--json":e=>{e.json=!0},"--include-tests":e=>{e.includeTests=!0},"--emit-tree":e=>{e.emitTree=!0},"--no-tree":e=>{e.emitTree=!1},"--graph":e=>{e.graph=!0},"--semantic":e=>{e.semantic=!0},"--no-diversify":e=>{e.noDiversify=!0},"--no-cache":e=>{e.noCache=!0},"--clear-cache":e=>{e.clearCache=!0},"--graph-advanced":e=>{e.graphAdvanced=!0},"--flow":e=>{e.flow=!0},"--all":e=>{e.includeTests=!0,e.semantic=!0},"--save-baseline":e=>{e.saveBaseline=!0}},Ps={"--findings-limit":"findingsLimit","--deep-link-topn":"deepLinkTopN","--tree-depth":"treeDepth","--max-recs-per-category":"maxRecsPerCategory","--focus-depth":"focusDepth"},Is={"--min-function-statements":"minFunctionStatements","--min-flow-statements":"minFlowStatements","--critical-complexity-threshold":"criticalComplexityThreshold","--coupling-threshold":"couplingThreshold","--fan-in-threshold":"fanInThreshold","--fan-out-threshold":"fanOutThreshold","--god-module-statements":"godModuleStatements","--god-module-exports":"godModuleExports","--god-function-statements":"godFunctionStatements","--god-function-mi-threshold":"godFunctionMiThreshold","--cognitive-complexity-threshold":"cognitiveComplexityThreshold","--barrel-symbol-threshold":"barrelSymbolThreshold","--parameter-threshold":"parameterThreshold","--halstead-effort-threshold":"halsteadEffortThreshold","--maintainability-index-threshold":"maintainabilityIndexThreshold","--any-threshold":"anyThreshold","--flow-dup-threshold":"flowDupThreshold","--override-chain-threshold":"overrideChainThreshold","--shotgun-threshold":"shotgunThreshold","--secret-min-length":"secretMinLength","--mock-threshold":"mockThreshold","--deep-nesting-threshold":"deepNestingThreshold","--multiple-return-threshold":"multipleReturnThreshold","--magic-string-min-occurrences":"magicStringMinOccurrences","--boolean-param-threshold":"booleanParamThreshold"},Ns={"--secret-entropy-threshold":"secretEntropyThreshold","--similarity-threshold":"similarityThreshold","--sdp-min-delta":"sdpMinDelta","--sdp-max-source-instability":"sdpMaxSourceInstability"},Ls={"--parser":(e,i,n)=>{let t=i[n+1];return["auto","typescript","tree-sitter"].includes(t)||(console.error(`Unsupported parser: ${t}. Use auto|typescript|tree-sitter`),process.exit(1)),e.parser=t,n+1},"--root":(e,i,n)=>(e.root=Xt.resolve(i[n+1]),n+1),"--out":(e,i,n)=>(e.out=i[n+1],n+1),"--layer-order":(e,i,n)=>(e.thresholds.layerOrder=i[n+1].split(",").map(t=>t.trim()),n+1),"--reporter":(e,i,n)=>{let t=i[n+1];return["default","compact","github-actions"].includes(t)||(console.error(`Unsupported reporter: ${t}. Use default|compact|github-actions`),process.exit(1)),e.reporter=t,n+1},"--config":(e,i,n)=>(e.configFile=i[n+1],n+1),"--help":()=>(Os(),process.exit(0)),"-h":()=>(Os(),process.exit(0))};_s=`
|
|
3
|
+
Usage:
|
|
4
|
+
node scripts/run.js [options]
|
|
5
|
+
|
|
6
|
+
Options:
|
|
7
|
+
--root <path> Analyze a different repo root (default: cwd)
|
|
8
|
+
--out <path> Output directory for split report files (timestamped dir by default).
|
|
9
|
+
If path ends with .json, writes single monolithic file (legacy mode).
|
|
10
|
+
--json Print report JSON to stdout
|
|
11
|
+
--include-tests Include *.test* and *.spec* files
|
|
12
|
+
--parser <auto|typescript|tree-sitter>
|
|
13
|
+
Parser engine for extra AST metadata (default: auto)
|
|
14
|
+
--no-tree Do not write AST trees to report
|
|
15
|
+
--emit-tree Force include tree blocks
|
|
16
|
+
--graph Emit Mermaid dependency graph to .md file alongside JSON
|
|
17
|
+
--graph-advanced Enable advanced graph overlays and additional architecture findings
|
|
18
|
+
--flow Enable lightweight flow enrichment for evidence traces and cfgFlags
|
|
19
|
+
--min-function-statements N Minimum function body statement count for duplicate matching (default 6)
|
|
20
|
+
--min-flow-statements N Minimum control-flow statement count for duplicate matching (default 6)
|
|
21
|
+
--critical-complexity-threshold N
|
|
22
|
+
Complexity threshold for HIGH complexity findings and critical path weighting.
|
|
23
|
+
--findings-limit N Cap findings in the report (default: no limit)
|
|
24
|
+
--deep-link-topn N Max number of critical dependency paths to report (default 12)
|
|
25
|
+
--tree-depth N AST tree depth when tree snapshots are emitted (default 4)
|
|
26
|
+
--coupling-threshold N Ca+Ce threshold for high-coupling findings (default 15)
|
|
27
|
+
--fan-in-threshold N Fan-in threshold for god-module-coupling (default 20)
|
|
28
|
+
--fan-out-threshold N Fan-out threshold for god-module-coupling (default 15)
|
|
29
|
+
--god-module-statements N Statement threshold for god-module findings (default 500)
|
|
30
|
+
--god-module-exports N Export threshold for god-module findings (default 20)
|
|
31
|
+
--god-function-statements N Statement threshold for god-function findings (default 100)
|
|
32
|
+
--god-function-mi-threshold N MI threshold for god-function findings (default 10, fires when MI < N and LOC > 30)
|
|
33
|
+
--cognitive-complexity-threshold N
|
|
34
|
+
Cognitive complexity threshold for findings (default 15)
|
|
35
|
+
--barrel-symbol-threshold N Re-export count threshold for barrel-explosion (default 30)
|
|
36
|
+
--layer-order <layers> Comma-separated layer names for violation detection (e.g. ui,service,repository)
|
|
37
|
+
--parameter-threshold N Max function parameters before flagging (default 5)
|
|
38
|
+
--halstead-effort-threshold N Halstead effort threshold for findings (default 500000)
|
|
39
|
+
--maintainability-index-threshold N
|
|
40
|
+
MI below this triggers a finding (default 20, scale 0-100)
|
|
41
|
+
--any-threshold N Max \`any\` type usages per file before flagging (default 5)
|
|
42
|
+
--flow-dup-threshold N Min occurrences for a repeated flow to become a finding (default 3)
|
|
43
|
+
--max-recs-per-category N Max findings per category in top recommendations (default 2)
|
|
44
|
+
--scope=X,Y,Z Limit scan to specific paths, files, or functions. Comma-separated.
|
|
45
|
+
Supports file:functionName to drill into a specific function.
|
|
46
|
+
Examples: --scope=packages/octocode-mcp
|
|
47
|
+
--scope=packages/octocode-mcp/src/tools
|
|
48
|
+
--scope=packages/octocode-mcp/src/session.ts
|
|
49
|
+
--scope=packages/octocode-mcp/src/session.ts:initSession
|
|
50
|
+
--scope=packages/foo,packages/bar
|
|
51
|
+
--features=X,Y,Z Run only selected features. Accepts pillar names (architecture,
|
|
52
|
+
code-quality, dead-code, security, test-quality) or individual
|
|
53
|
+
category names. Comma-separated.
|
|
54
|
+
Examples: --features=architecture
|
|
55
|
+
--features=dead-code,cognitive-complexity
|
|
56
|
+
--features=dependency-cycle,dead-export
|
|
57
|
+
--exclude=X,Y,Z Run everything EXCEPT the given pillars or categories. Mutually
|
|
58
|
+
exclusive with --features. Same pillar/category names as --features.
|
|
59
|
+
Examples: --exclude=architecture
|
|
60
|
+
--exclude=dead-export,unsafe-any
|
|
61
|
+
--semantic Enable semantic analysis phase (TypeChecker + LanguageService).
|
|
62
|
+
Adds 12 categories: over-abstraction, concrete-dependency,
|
|
63
|
+
circular-type-dependency, unused-parameter,
|
|
64
|
+
deep-override-chain, interface-compliance, unused-import,
|
|
65
|
+
orphan-implementation, shotgun-surgery, move-to-caller,
|
|
66
|
+
narrowable-type, semantic-dead-export.
|
|
67
|
+
--override-chain-threshold N Max method override depth before flagging (default 3, requires --semantic)
|
|
68
|
+
--shotgun-threshold N Unique-file threshold for shotgun-surgery (default 8, requires --semantic)
|
|
69
|
+
--sdp-min-delta N Min instability delta for SDP violations (default 0.15)
|
|
70
|
+
--sdp-max-source-instability N Max source instability to report SDP (default 0.6)
|
|
71
|
+
--secret-entropy-threshold N Shannon entropy threshold for secret detection (default 4.5)
|
|
72
|
+
--secret-min-length N Min string length for entropy-based secret detection (default 20)
|
|
73
|
+
--similarity-threshold N Jaccard similarity threshold for near-clone detection (default 0.85)
|
|
74
|
+
--deep-nesting-threshold N Max branch/loop nesting depth before flagging (default 5)
|
|
75
|
+
--multiple-return-threshold N Max return/throw paths per function before flagging (default 6)
|
|
76
|
+
--magic-string-min-occurrences N
|
|
77
|
+
Min repeated string comparisons to flag as magic string (default 3)
|
|
78
|
+
--boolean-param-threshold N Min boolean params per function to flag as cluster (default 3)
|
|
79
|
+
--mock-threshold N Max mock/spy calls per test file (default 10)
|
|
80
|
+
--no-diversify Disable category-aware diversification when truncating findings.
|
|
81
|
+
By default, --findings-limit interleaves categories so the
|
|
82
|
+
truncated list is diverse. Use this to get pure severity ordering.
|
|
83
|
+
--no-cache Disable incremental cache; re-parse all files
|
|
84
|
+
--clear-cache Delete the analysis cache and exit (no scan)
|
|
85
|
+
--all Enable all features: --include-tests --semantic
|
|
86
|
+
|
|
87
|
+
--affected [revision] Scope to files changed since git revision (default: HEAD) plus
|
|
88
|
+
their transitive dependents. Like dep-cruiser's --affected flag.
|
|
89
|
+
Examples: --affected
|
|
90
|
+
--affected HEAD~3
|
|
91
|
+
--affected main
|
|
92
|
+
--save-baseline Save current findings to .octocode/baseline.json for future
|
|
93
|
+
comparison. Use with --ignore-known for progressive adoption.
|
|
94
|
+
--ignore-known [file] Suppress findings matching a baseline file (default:
|
|
95
|
+
.octocode/baseline.json). Findings are matched by (category, file).
|
|
96
|
+
--reporter <format> Output format: default|compact|github-actions (default: default)
|
|
97
|
+
compact: one-line per finding for terminal/CI logs
|
|
98
|
+
github-actions: ::warning annotations for GitHub Actions
|
|
99
|
+
--focus <module> Show only this module and its neighbors in the dependency graph.
|
|
100
|
+
Requires --graph. Use with --focus-depth to control neighbor hops.
|
|
101
|
+
Examples: --focus src/session.ts
|
|
102
|
+
--focus=src/session.ts
|
|
103
|
+
--focus packages/octocode-mcp/src/tools
|
|
104
|
+
--focus-depth N Neighbor depth for --focus (default 1). 2 = friends-of-friends.
|
|
105
|
+
--collapse N Collapse graph nodes to folder depth N. Reduces large graphs to
|
|
106
|
+
high-level architecture view. Example: --collapse 2
|
|
107
|
+
--at-least N Fail (exit 1) if health score drops below N (0-100). Use in CI
|
|
108
|
+
to enforce a quality floor. Example: --at-least 60
|
|
109
|
+
--config <file> Path to config file. Also auto-discovers .octocode-scan.json,
|
|
110
|
+
.octocode-scan.jsonc, or package.json#octocode in the project root.
|
|
111
|
+
--help Show this message
|
|
112
|
+
`});import xt from"node:fs";import bt from"node:path";function en(e,i){if(i){let t=bt.isAbsolute(i)?i:bt.resolve(e,i);return Hs(t)}for(let t of Lo){let s=bt.join(e,t);if(xt.existsSync(s))return Hs(s)}let n=bt.join(e,"package.json");if(xt.existsSync(n))try{let t=JSON.parse(xt.readFileSync(n,"utf8"));if(t.octocode&&typeof t.octocode=="object")return Bs(t.octocode)}catch{}return null}function Hs(e){try{let i=xt.readFileSync(e,"utf8");return i=i.replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,""),Bs(JSON.parse(i))}catch{return null}}function Bs(e){let i={};for(let[n,t]of Object.entries(e)){let s=n.replace(/-([a-z])/g,(r,o)=>o.toUpperCase());s==="features"&&typeof t=="string"?i[s]=new Set(t.split(",").map(r=>r.trim())):s==="scope"&&typeof t=="string"?i[s]=t.split(",").map(r=>r.trim()):s==="ignoreDirs"&&Array.isArray(t)?i[s]=new Set(t):i[s]=t}return i}function tn(e,i,n){let t={...e};for(let[s,r]of Object.entries(i))s==="thresholds"&&typeof r=="object"&&r!==null?t.thresholds={...t.thresholds,...r}:t[s]=r;for(let s of Object.keys(n)){let r=n[s],o=e[s];r!==o&&(t[s]=r)}return t}var Lo,nn=N(()=>{"use strict";Lo=[".octocode-scan.json",".octocode-scan.jsonc"]});import{EventEmitter as Oo}from"node:events";function zs(){le.on("progress",e=>{e.detail?process.stderr.write(`[${e.phase}] ${e.message}: ${e.detail}
|
|
113
|
+
`):process.stderr.write(`[${e.phase}] ${e.message}
|
|
114
|
+
`)})}var sn,le,rn=N(()=>{"use strict";sn=class extends Oo{progress(i,n,t){this.emit("progress",{phase:i,message:n,detail:t})}summary(i){this.emit("summary",i)}error(i,n){this.emit("error",{message:i,detail:n})}reset(){this.removeAllListeners()}},le=new sn});import{execSync as jo}from"node:child_process";import _o from"node:path";function on(e,i,n){let t=Ho(e,i);if(t.length===0)return[];let s=new Set(t),r=new Set(s);return Bo(s,n,r),[...r]}function Ho(e,i){try{let n=jo(`git diff --name-only --diff-filter=ACMRT ${i}`,{cwd:e,encoding:"utf8",timeout:1e4}).trim();return n?n.split(`
|
|
115
|
+
`).filter(t=>{let s=_o.extname(t);return qe.has(s)}):[]}catch{return[]}}function Bo(e,i,n){let t=[...e];for(;t.length>0;){let s=t.pop(),r=i.incoming.get(s);if(r)for(let o of r)n.has(o)||(n.add(o),t.push(o))}}var an=N(()=>{"use strict";ge()});import Et from"node:fs";import wt from"node:path";function ln(e,i){let n=wt.join(e,".octocode","baseline.json"),t=wt.dirname(n);Et.mkdirSync(t,{recursive:!0});let s=i.map(o=>({category:o.category,file:o.file,title:o.title})),r={generatedAt:new Date().toISOString(),count:s.length,entries:s};return Et.writeFileSync(n,JSON.stringify(r,null,2),"utf8"),n}function cn(e,i,n){let t=wt.isAbsolute(i)?i:wt.resolve(n,i);if(!Et.existsSync(t))return{filtered:e,suppressedCount:0};try{let r=JSON.parse(Et.readFileSync(t,"utf8")).entries||[],o=new Set(r.map(l=>`${l.category}::${l.file}`)),a=e.filter(l=>!o.has(`${l.category}::${l.file}`));return{filtered:a,suppressedCount:e.length-a.length}}catch{return{filtered:e,suppressedCount:0}}}var dn=N(()=>{"use strict"});function un(e,i,n){switch(i){case"compact":return Ko(e,n);case"github-actions":return Uo(e,n);default:return""}}function Ks(e,i){return e.startsWith(i)?e.slice(i.length+1):e}function zo(e){switch(e){case"critical":return"error";case"high":return"error";case"medium":return"warning";case"low":return"notice";default:return"warning"}}function Ko(e,i){return e.map(n=>{let t=Ks(n.file,i),s=n.lineStart?`${t}:${n.lineStart}`:t;return`${n.severity}:${s} - [${n.category}] ${n.title}`}).join(`
|
|
116
|
+
`)}function Uo(e,i){return e.map(n=>{let t=Ks(n.file,i),s=n.lineStart||1;return`::${zo(n.severity)} file=${t},line=${s}::${n.title} [${n.category}]`}).join(`
|
|
117
|
+
`)}var fn=N(()=>{"use strict"});import qo from"node:crypto";import Go from"node:fs";import Xe from"node:path";import*as Z from"typescript";function Us(e){switch(e){case".tsx":return Z.ScriptKind.TSX;case".jsx":return Z.ScriptKind.JSX;case".js":case".mjs":case".cjs":return Z.ScriptKind.JS;default:return Z.ScriptKind.TS}}function Ge(e){return qo.createHash("sha1").update(e).digest("hex").slice(0,16)}function Wo(e){switch(e){case Z.SyntaxKind.Identifier:return"ID";case Z.SyntaxKind.StringLiteral:case Z.SyntaxKind.NoSubstitutionTemplateLiteral:case Z.SyntaxKind.TemplateMiddle:case Z.SyntaxKind.TemplateHead:return"STR";case Z.SyntaxKind.NumericLiteral:return"NUM";case Z.SyntaxKind.BigIntLiteral:return"BIGINT";case Z.SyntaxKind.TrueKeyword:case Z.SyntaxKind.FalseKeyword:return"BOOL";case Z.SyntaxKind.NullKeyword:return"NULL";default:return Z.SyntaxKind[e]||"UNKNOWN"}}function pn(e,i=new WeakMap){if(i.has(e))return i.get(e);let n=[],t=r=>{n.push(Wo(r.kind)),Z.forEachChild(r,t)};t(e);let s=Ge(n.join("|"));return i.set(e,s),s}function gn(e){let i=[],n=t=>{i.push(t.type);for(let s of t.children)n(s)};return n(e),Ge(i.join("|"))}function R(e,i){let n=e.getLineAndCharacterOfPosition(i.getStart(e)),t=e.getLineAndCharacterOfPosition(i.getEnd());return{lineStart:n.line+1,lineEnd:t.line+1,columnStart:n.character+1,columnEnd:t.character+1}}function mn(e,i,n,t,s=new WeakSet){if(!e||t.size<=0)return null;t.size-=1;let r=R(i,e),o={kind:Z.SyntaxKind[e.kind]||"UNKNOWN",startLine:r.lineStart,endLine:r.lineEnd,children:[]};return n<=0||s.has(e)?(o.truncated=!0,o):(s.add(e),Z.forEachChild(e,a=>{if(t.size<=0)return;let l=mn(a,i,n-1,t,s);l&&o.children.push(l)}),o)}function hn(e,i,n,t,s=new WeakSet){if(!e||t.size<=0)return null;t.size-=1;let r={kind:e.type,startLine:e.startPosition.row+1,endLine:e.endPosition.row+1,children:[]};if(n<=0||s.has(e))return r.truncated=!0,r;s.add(e);for(let o of e.children){if(t.size<=0)break;let a=hn(o,i,n-1,t,s);a&&r.children.push(a)}return r}function qs(e,i=0){let n=" ".repeat(i),t=e.startLine===e.endLine?`${e.startLine}`:`${e.startLine}:${e.endLine}`,s=e.truncated?" ...":"",r=`${n}${e.kind}[${t}]${s}
|
|
118
|
+
`;for(let o of e.children)r+=qs(o,i+1);return r}function Gs(e,i){let n=[`# AST Trees \u2014 ${i}`,""];for(let t of e)n.push(`## ${t.package} \u2014 ${t.file}`),n.push(qs(t.tree));return n.join(`
|
|
119
|
+
`)}function x(e){return/(?:^|[\\/])(?:__tests__|__test__|tests)(?:[\\/]|$)/.test(e)||/(?:\.test|_test|\.spec)\.(?:ts|tsx|js|jsx|mjs|cjs)$/.test(e)}function Ws(e,i){return Xe.relative(i,e).replace(/\\/g,"/")}function yn(e){return Xe.normalize(e).replace(/\\/g,"/")}function Ze(e,i,n){e.has(i)||e.set(i,new Set),e.get(i).add(n)}function Vs(e){return e.startsWith("./")||e.startsWith("../")||e.startsWith(".\\")||e.startsWith("..\\")}function Qs(e,i){let n=i.replace(/[?#].*$/,""),t=Xe.resolve(e,n),s=[],r=Xe.extname(t),o={".js":[".ts",".tsx"],".jsx":[".tsx"],".mjs":[".ts",".tsx"],".cjs":[".ts",".tsx"]};if(r){s.push(t);let a=o[r];if(a){let l=t.slice(0,-r.length);for(let c of a){let u=`${l}${c}`;s.push(u)}}}else{for(let a of Je)s.push(`${t}${a}`);for(let a of Je)s.push(Xe.join(t,`index${a}`))}for(let a of s)if(Go.existsSync(a))return a;return null}function Se(e,i,n){e.has(i)||e.set(i,[]),e.get(i).push(n)}var G=N(()=>{"use strict";ge()});import Js from"node:path";import*as L from"typescript";function Oe(e,i){return{lineStart:e.getLineAndCharacterOfPosition(i.getStart(e)).line+1,lineEnd:e.getLineAndCharacterOfPosition(i.getEnd()).line+1}}function vt(e){return L.canHaveModifiers(e)?!!L.getModifiers(e)?.some(i=>i.kind===L.SyntaxKind.ExportKeyword):!1}function Vo(e,i){if(!e.moduleSpecifier||!L.isStringLiteral(e.moduleSpecifier))return;let n=e.moduleSpecifier.text,t=i.resolveSpecifier(n)??void 0,s=Oe(i.sourceFile,e),r=e.importClause;if(r&&(r.name&&i.importedSymbols.push({sourceModule:n,resolvedModule:t,importedName:"default",localName:r.name.text,isTypeOnly:r.isTypeOnly,...s}),!!r.namedBindings))if(L.isNamespaceImport(r.namedBindings))i.importedSymbols.push({sourceModule:n,resolvedModule:t,importedName:"*",localName:r.namedBindings.name.text,isTypeOnly:r.isTypeOnly,...s});else for(let o of r.namedBindings.elements)i.importedSymbols.push({sourceModule:n,resolvedModule:t,importedName:o.propertyName?.text??o.name.text,localName:o.name.text,isTypeOnly:r.isTypeOnly||o.isTypeOnly,...s})}function Qo(e,i){if(!e.moduleSpecifier||!L.isStringLiteral(e.moduleSpecifier))return;let n=e.moduleSpecifier.text,t=i.resolveSpecifier(n)??void 0;if(e.exportClause&&L.isNamedExports(e.exportClause))for(let s of e.exportClause.elements)i.reExports.push({sourceModule:n,resolvedModule:t,exportedAs:s.name.text,importedName:s.propertyName?.text??s.name.text,isStar:!1,isTypeOnly:e.isTypeOnly||s.isTypeOnly,...Oe(i.sourceFile,s)});else i.reExports.push({sourceModule:n,resolvedModule:t,exportedAs:"*",importedName:"*",isStar:!0,isTypeOnly:e.isTypeOnly,...Oe(i.sourceFile,e)})}function Jo(e,i){let n=Oe(i.sourceFile,e);if(L.isExportAssignment(e)){i.pushDeclaredExport({name:"default",kind:"value",isDefault:!0,...n});return}if((L.isFunctionDeclaration(e)||L.isClassDeclaration(e))&&vt(e)){i.pushDeclaredExport({name:e.name?.text||"default",kind:"value",isDefault:!e.name,...n});return}if(L.isEnumDeclaration(e)&&vt(e)){i.pushDeclaredExport({name:e.name.text,kind:"value",...n});return}if((L.isTypeAliasDeclaration(e)||L.isInterfaceDeclaration(e))&&vt(e)){i.pushDeclaredExport({name:e.name.text,kind:"type",...n});return}if(L.isVariableStatement(e)&&vt(e)){for(let t of e.declarationList.declarations)L.isIdentifier(t.name)&&i.pushDeclaredExport({name:t.name.text,kind:"value",...Oe(i.sourceFile,t)});return}if(L.isExportDeclaration(e)&&!e.moduleSpecifier&&e.exportClause&&L.isNamedExports(e.exportClause))for(let t of e.exportClause.elements)i.pushDeclaredExport({name:t.name.text,kind:t.isTypeOnly?"type":"unknown",...Oe(i.sourceFile,t)})}function Yo(e,i){if(!L.isIdentifier(e.expression)||e.expression.text!=="require"||e.arguments.length!==1||!L.isStringLiteral(e.arguments[0]))return;let n=e.arguments[0].text,t=i.resolveSpecifier(n)??void 0;i.importedSymbols.push({sourceModule:n,resolvedModule:t,importedName:"*",localName:"require",isTypeOnly:!1,...Oe(i.sourceFile,e)})}function Xo(e,i,n){let t=Js.dirname(i),s=new Set,r=new Set,o=new Set,a=[],u={sourceFile:e,importedSymbols:[],reExports:[],pushDeclaredExport:f=>{a.some(p=>p.name===f.name&&p.kind===f.kind)||a.push(f)},resolveSpecifier:f=>{if(!f||typeof f!="string")return null;if(!Vs(f))return r.add(f),null;let p=Qs(t,f);if(!p)return o.add(f),null;if(!p.startsWith(n))return r.add(f),null;let g=yn(Js.relative(n,p));return s.add(g),g}},d=f=>{L.isImportDeclaration(f)&&Vo(f,u),L.isExportDeclaration(f)&&f.moduleSpecifier&&Qo(f,u),Jo(f,u),L.isCallExpression(f)&&Yo(f,u),L.forEachChild(f,d)};return d(e),{internalDependencies:[...s].sort(),externalDependencies:[...r].sort(),unresolvedDependencies:[...o].sort(),declaredExports:a,importedSymbols:u.importedSymbols,reExports:u.reExports}}function Zo(e,i,n,t){Ze(e.outgoing,i,n),Ze(e.incoming,n,i),t?Ze(e.incomingFromTests,n,i):Ze(e.incomingFromProduction,n,i)}function Ys(e,i,n,t,s){let r=Ws(i,t.root);s.files.add(r);let o=Xo(e,i,t.root),a=x(i);for(let l of o.internalDependencies){let c=yn(l);Zo(s,r,c,a)}return o.externalDependencies.length>0&&s.externalCounts.set(r,new Set(o.externalDependencies)),o.unresolvedDependencies.length>0&&s.unresolvedCounts.set(r,new Set(o.unresolvedDependencies)),s.declaredExportsByFile.set(r,o.declaredExports),s.importedSymbolsByFile.set(r,o.importedSymbols),s.reExportsByFile.set(r,o.reExports),{...o,package:n,file:r}}function Ft(e,i){let n=i.outgoing.get(e)||new Set,t=i.incoming.get(e)||new Set,s=i.incomingFromProduction.get(e)||new Set,r=i.incomingFromTests.get(e)||new Set,o=i.externalCounts.get(e)||new Set,a=i.unresolvedCounts.get(e)||new Set;return{file:e,outboundCount:n.size,inboundCount:t.size,inboundFromProduction:s.size,inboundFromTests:r.size,externalDependencyCount:o.size,unresolvedDependencyCount:a.size}}var Sn=N(()=>{"use strict";G()});function bn(e,i,n){let t=[...e.files].sort(),s=0,r=0,o=[],a=[];for(let g of t){s+=e.outgoing.get(g)?.size||0;let m=Ft(g,e),S=i.get(g)||{score:1};o.push({file:g,count:m.outboundCount,score:S.score}),a.push({file:g,count:m.inboundCount,score:S.score}),r+=m.unresolvedDependencyCount}let l=t.filter(g=>(e.incoming.get(g)||new Set).size===0),c=t.filter(g=>(e.outgoing.get(g)||new Set).size===0),u=t.filter(g=>!x(g)).filter(g=>{let m=e.incomingFromProduction.get(g),S=e.incomingFromTests.get(g);return(!m||m.size===0)&&S&&S.size>0}).map(g=>({...Ft(g,e)})).sort((g,m)=>g.file.localeCompare(m.file)),d=t.map(g=>({...Ft(g,e),...i.get(g)||{}})).filter(g=>(g.score||0)>12||g.outboundCount>5||g.inboundCount>8).sort((g,m)=>(m.score||0)+m.inboundCount*.8+m.outboundCount*.4-((g.score||0)+g.inboundCount*.8+g.outboundCount*.4)).slice(0,150).map(g=>({...g,score:Math.round(g.score||0),riskBand:(g.score||0)>=60?"high":(g.score||0)>=30?"medium":"low"})),f=Xs(e),p=Zs(e,i,n);return{totalModules:t.length,totalEdges:s,unresolvedEdgeCount:r,externalDependencyFiles:[...e.externalCounts.keys()].length,rootsCount:l.length,leavesCount:c.length,roots:l.slice(0,20),leaves:c.slice(0,20),criticalModules:d.slice(0,20),testOnlyModules:u.slice(0,50),unresolvedSample:r>0?[...e.unresolvedCounts.keys()].slice(0,40):[],outgoingTop:o.sort((g,m)=>m.count-g.count).slice(0,20),inboundTop:a.sort((g,m)=>m.count-g.count).slice(0,20),cycles:f.slice(0,20),criticalPaths:p.slice(0,Math.max(1,n.deepLinkTopN))}}function Xs(e){let i=[],n=new Set,t=new Set,s=[],r=new Set,o=l=>{let c=[...l],u=c.slice();for(let d=1;d<c.length;d++){let f=[...c.slice(d),...c.slice(0,d)];f.join(" => ")<u.join(" => ")&&(u=f)}return u.join(" => ")},a=l=>{if(n.has(l)||t.has(l))return;t.add(l),s.push(l);let c=e.outgoing.get(l)||new Set;for(let u of c){let d=s.indexOf(u);if(d!==-1){let f=[...s.slice(d),u],p=o(f);r.has(p)||(r.add(p),i.push({path:f,nodeCount:f.length-1}));continue}e.files.has(u)&&a(u)}s.pop(),t.delete(l),n.add(l)};for(let l of e.files)a(l);return i.sort((l,c)=>c.nodeCount-l.nodeCount)}function Zs(e,i,n){let t=new Map,s=new Set,r=l=>{let c=i.get(l);return c?c.score:1},o=l=>{if(t.has(l))return t.get(l);if(s.has(l))return{path:[l],score:r(l)*.5,containsCycle:!0};s.add(l);let c=e.outgoing.get(l)||new Set,u={path:[l],score:r(l),containsCycle:!1};for(let d of c){if(!e.files.has(d))continue;let f=o(d),p=r(l)+f.score;(p>u.score||p===u.score&&f.path.length>u.path.length)&&(u={path:[l,...f.path],score:p,containsCycle:f.containsCycle})}return s.delete(l),t.set(l,u),u},a=[];for(let l of e.files){let c=o(l);a.push({start:l,path:c.path,score:Math.round(c.score),length:c.path.length,containsCycle:c.containsCycle})}return a.filter(l=>l.length>1).sort((l,c)=>{let u=c.score-l.score;return u!==0?u:c.length-l.length}).slice(0,Math.max(1,n.deepLinkTopN))}var xn=N(()=>{"use strict";Sn();G()});import Ce from"node:fs";import me from"node:path";function ta(e,i){if(!i||i.length===0)return!1;let n=me.normalize(e);return i.some(t=>{let s=me.normalize(t);return n===s||n.startsWith(s+me.sep)})}function na(e){return/\.min\.(?:js|mjs|cjs)$/i.test(e)}function ia(e,i){let n=me.relative(i,e);if(!n||n.startsWith(".."))return!1;let t=n.split(me.sep);if(t[0]!=="scripts"||t.length<2)return!1;let s=me.extname(e),r=t.slice(1).join(me.sep).slice(0,-s.length);for(let o of ea){let a=me.join(i,"src",`${r}${o}`);if(Ce.existsSync(a)&&Ce.statSync(a).isFile())return!0}return!1}function En(e,i){let n=[],t=s=>{let r=Ce.readdirSync(s,{withFileTypes:!0});r.sort((o,a)=>o.name.localeCompare(a.name));for(let o of r){if(i.ignoreDirs.has(o.name)||o.isSymbolicLink())continue;let a=me.join(s,o.name);if(o.isDirectory()){t(a);continue}if(!o.isFile()||o.name.endsWith(".d.ts")||!ta(a,i.scope)&&(na(o.name)||ia(a,e)))continue;let l=me.extname(o.name);qe.has(l)&&(!i.includeTests&&x(a)||n.push(a))}};return t(e),n}function er(e){try{return Ce.readFileSync(e,"utf8")}catch{return null}}function tr(e,i){if(!Ce.existsSync(i)||!Ce.statSync(i).isDirectory())return[];let n=Ce.readdirSync(i,{withFileTypes:!0}).filter(s=>s.isDirectory()).sort((s,r)=>s.name.localeCompare(r.name)),t=[];for(let s of n){let r=me.join(i,s.name),o=me.join(r,"package.json");if(Ce.existsSync(o))try{let a=JSON.parse(Ce.readFileSync(o,"utf8"));typeof a.name=="string"&&t.push({name:a.name,dir:r,folder:s.name})}catch{}}return t}function nr(e,i){return e.map(n=>({...n,issueIds:i.get(n.file)||[]}))}var ea,ir=N(()=>{"use strict";G();ge();ea=[".ts",".tsx",".js",".jsx",".mjs",".cjs"]});function wn(e){let i=e.replace(/\\/g,"/").replace(/^\.?\//,""),n=i.match(/^packages\/([^/]+)/);if(n)return`packages/${n[1]}`;let[t]=i.split("/");return t||"<root>"}function sa(e){let i=[...e.files].sort(),n=new Map,t=new Map,s=[],r=new Set,o=0,a=[],l=c=>{n.set(c,o),t.set(c,o),o+=1,s.push(c),r.add(c);let u=e.outgoing.get(c)||new Set;for(let y of u)e.files.has(y)&&(n.has(y)?r.has(y)&&t.set(c,Math.min(t.get(c),n.get(y))):(l(y),t.set(c,Math.min(t.get(c),t.get(y)))));if(t.get(c)!==n.get(c))return;let d=[];for(;s.length>0;){let y=s.pop();if(r.delete(y),d.push(y),y===c)break}let f=(e.outgoing.get(c)||new Set).has(c);if(d.length<=1&&!f)return;let p=new Set(d),g=0,m=0,S=0;for(let y of d){for(let D of e.outgoing.get(y)||new Set)e.files.has(D)&&(p.has(D)?g+=1:S+=1);for(let D of e.incoming.get(y)||new Set)p.has(D)||(m+=1)}let h=[...d].sort((y,D)=>{let b=(e.incoming.get(y)||new Set).size*2+(e.outgoing.get(y)||new Set).size;return(e.incoming.get(D)||new Set).size*2+(e.outgoing.get(D)||new Set).size-b}).slice(0,3);a.push({id:`scc-${a.length+1}`,files:d.sort(),nodeCount:d.length,edgeCount:g,entryEdges:m,exitEdges:S,hubFiles:h})};for(let c of i)n.has(c)||l(c);return a.sort((c,u)=>u.nodeCount-c.nodeCount||u.edgeCount-c.edgeCount)}function ra(e){let i=new Map,n=new Map;for(let s of e.files){let r=wn(s);i.has(r)||i.set(r,{package:r,inbound:0,outbound:0,internalFiles:0}),i.get(r).internalFiles+=1}for(let[s,r]of e.outgoing.entries()){let o=wn(s);for(let a of r){if(!e.files.has(a))continue;let l=wn(a);if(o===l)continue;let c=`${o}=>${l}`;n.set(c,(n.get(c)||0)+1),i.get(o).outbound+=1,i.get(l).inbound+=1}}let t=[...n.entries()].map(([s,r])=>{let[o,a]=s.split("=>");return{from:o,to:a,edges:r}}).sort((s,r)=>r.edges-s.edges).slice(0,20);return{packageCount:i.size,edgeCount:[...n.values()].reduce((s,r)=>s+r,0),packages:[...i.values()].sort((s,r)=>r.inbound+r.outbound-(s.inbound+s.outbound)),hotspots:t}}function sr(e){let i=[...e.files].sort(),n=new Map;for(let d of i)n.set(d,new Set);for(let[d,f]of e.outgoing.entries())for(let p of f)e.files.has(p)&&(n.get(d).add(p),n.get(p).add(d));let t=new Set,s=new Map,r=new Map,o=new Map,a=new Set,l=[],c=0,u=d=>{t.add(d),s.set(d,c),r.set(d,c),c+=1;let f=0;for(let p of n.get(d)||new Set)t.has(p)?p!==o.get(d)&&r.set(d,Math.min(r.get(d),s.get(p))):(f+=1,o.set(p,d),u(p),r.set(d,Math.min(r.get(d),r.get(p))),o.get(d)==null&&f>1&&a.add(d),o.get(d)!=null&&r.get(p)>=s.get(d)&&a.add(d),r.get(p)>s.get(d)&&l.push(d<p?{from:d,to:p}:{from:p,to:d}))};for(let d of i)t.has(d)||(o.set(d,null),u(d));return{articulationPoints:a,bridgeEdges:l}}function oa(e,i,n,t){let{articulationPoints:s,bridgeEdges:r}=sr(e),o=new Set;for(let c of i.criticalPaths||[])for(let u of c.path)o.add(u);let a=new Map;for(let c of t)for(let u of c.files)a.set(u,(a.get(u)||0)+1);let l=new Map;for(let c of r)l.set(c.from,(l.get(c.from)||0)+1),l.set(c.to,(l.get(c.to)||0)+1);return[...e.files].map(c=>{let u=(e.incoming.get(c)||new Set).size,d=(e.outgoing.get(c)||new Set).size,f=s.has(c),p=l.get(c)||0,g=a.get(c)||0,m=o.has(c),S=n.get(c)?.score||0,h=Math.round(u*3+d*1.2+S/10+(f?12:0)+p*4+g*6+(m?8:0)),y=[];return u>=8&&y.push(`high fan-in (${u})`),d>=6&&y.push(`high fan-out (${d})`),f&&y.push("articulation point"),p>0&&y.push(`${p} bridge edge(s)`),g>0&&y.push(`in ${g} cycle cluster(s)`),m&&y.push("on critical path"),S>=20&&y.push(`high complexity risk (${S})`),{file:c,score:h,reasons:y,fanIn:u,fanOut:d,articulation:f,bridgeCount:p,cycleClusterCount:g,onCriticalPath:m}}).filter(c=>c.score>0&&c.reasons.length>0).sort((c,u)=>u.score-c.score).slice(0,40)}function kt(e,i,n){let t=sa(e),{articulationPoints:s,bridgeEdges:r}=sr(e),o=oa(e,i,n,t);return{sccClusters:t,chokepoints:o,packageGraphSummary:ra(e),articulationPoints:[...s].sort(),bridgeEdges:r}}function vn(e,i,n){let t=e.importedSymbolsByFile.get(i)||[];for(let s of t)if(!n||s.resolvedModule===n)return{lineStart:s.lineStart||1,lineEnd:s.lineEnd||s.lineStart||1};return{lineStart:1,lineEnd:1}}function rr(e,i,n){let t=[];for(let r of e.sccClusters.slice(0,6)){if(r.nodeCount<3)continue;let o=r.hubFiles[0]||r.files[0],a=vn(i,o);t.push({severity:r.nodeCount>=5?"high":"medium",category:"cycle-cluster",file:o,lineStart:a.lineStart,lineEnd:a.lineEnd,title:`Cycle cluster detected (${r.nodeCount} files)`,reason:`Strongly connected cluster ${r.id} has ${r.nodeCount} files, ${r.entryEdges} entry edge(s), and ${r.exitEdges} exit edge(s).`,files:r.files,suggestedFix:{strategy:"Break the cluster at one of the hub files and move shared contracts lower.",steps:["Inspect the hub files first.","Extract shared interfaces or types from the cluster.","Remove at least one high-traffic edge to split the SCC."]},impact:"Large cycle clusters spread change risk across multiple files and hide the true architectural boundary.",tags:["architecture","cycle","graph","change-risk"],ruleId:"architecture.cycle-cluster",confidence:"high",evidence:{clusterId:r.id,nodeCount:r.nodeCount,entryEdges:r.entryEdges,exitEdges:r.exitEdges,hubFiles:r.hubFiles}})}for(let r of e.chokepoints.slice(0,8)){if(r.fanIn<3||r.fanOut<3||r.score<18)continue;let o=vn(i,r.file);t.push({severity:r.articulation||r.score>=30?"high":"medium",category:"broker-module",file:r.file,lineStart:o.lineStart,lineEnd:o.lineEnd,title:`Broker module chokepoint: ${r.file}`,reason:`Module concentrates dependency traffic (${r.reasons.join(", ")}).`,files:[r.file],suggestedFix:{strategy:"Split orchestration responsibilities and reduce fan-in/fan-out through narrower seams.",steps:["Identify which consumers rely on this file for unrelated concerns.","Extract narrower APIs or introduce an internal facade.","Move side-effectful or persistence-specific logic into dedicated modules."]},impact:"Broker modules silently become architecture bottlenecks \u2014 a small change cascades broadly.",tags:["architecture","graph","chokepoint","coupling"],ruleId:"architecture.broker-module",confidence:r.articulation?"high":"medium",evidence:{score:r.score,reasons:r.reasons,fanIn:r.fanIn,fanOut:r.fanOut}})}for(let r of e.chokepoints.filter(o=>o.articulation).slice(0,8)){let o=vn(i,r.file);t.push({severity:r.bridgeCount>=2?"high":"medium",category:"bridge-module",file:r.file,lineStart:o.lineStart,lineEnd:o.lineEnd,title:`Bridge module detected: ${r.file}`,reason:`Module acts as a graph articulation point with ${r.bridgeCount} bridge edge(s).`,files:[r.file],suggestedFix:{strategy:"Reduce the amount of architecture that depends on this single bridge module.",steps:["Split unrelated responsibilities out of the bridge module.","Add lower-level contracts so adjacent subsystems do not all route through one file.","Prefer explicit package boundaries over central catch-all utilities."]},impact:"Bridge modules are structurally brittle \u2014 they become the single point where subsystem changes collide.",tags:["architecture","graph","bridge","fragility"],ruleId:"architecture.bridge-module",confidence:"high",evidence:{score:r.score,bridgeCount:r.bridgeCount,reasons:r.reasons}})}for(let r of e.packageGraphSummary.hotspots.slice(0,5))r.edges<4||t.push({severity:r.edges>=8?"high":"medium",category:"package-boundary-chatter",file:r.from,lineStart:1,lineEnd:1,title:`Heavy package chatter: ${r.from} -> ${r.to}`,reason:`Detected ${r.edges} cross-package dependency edge(s) between these package groups.`,files:[r.from,r.to],suggestedFix:{strategy:"Reduce cross-package chatter by consolidating APIs or introducing a narrower shared contract.",steps:["Map the symbols crossing this boundary most often.","Promote a smaller public API surface between the packages.","Move implementation detail imports behind a dedicated package boundary."]},impact:"High package chatter is a sign of architectural erosion \u2014 packages stop behaving like isolated subsystems.",tags:["architecture","packages","boundary","graph"],ruleId:"architecture.package-boundary-chatter",confidence:"medium",evidence:r});let s=new Map(e.chokepoints.map(r=>[r.file,r]));for(let r of n){let o=r.topLevelEffects||[];if(o.length===0)continue;let a=s.get(r.file);if(!a||a.fanIn<8||a.score<18)continue;let l=o[0];t.push({severity:a.fanIn>=20?"high":"medium",category:"startup-risk-hub",file:r.file,lineStart:l.lineStart,lineEnd:l.lineEnd,title:`Startup risk hub: ${r.file}`,reason:`Module performs ${o.length} import-time effect(s) and also behaves as a chokepoint (${a.reasons.join(", ")}).`,files:[r.file],suggestedFix:{strategy:"Move import-time work behind explicit initialization and reduce inbound dependency pressure.",steps:["Extract side effects into init() or lazy code paths.","Avoid importing this module from broad utility or entrypoint chains.","Keep only declarations and light configuration at module scope."]},impact:"Import-time side effects in a high fan-in hub create startup latency, hidden ordering bugs, and broad runtime blast radius.",tags:["architecture","startup","side-effects","graph"],ruleId:"architecture.startup-risk-hub",confidence:"high",evidence:{fanIn:a.fanIn,chokepointScore:a.score,topLevelEffects:o.map(c=>c.kind)}})}return t}var Fn=N(()=>{"use strict"});import kn from"node:fs";import et from"node:path";import*as v from"typescript";function aa(e){let i=v.findConfigFile(e,v.sys.fileExists,"tsconfig.json");if(!i)return null;let n=v.readConfigFile(i,v.sys.readFile);return n.error?null:v.parseJsonConfigFileContent(n.config,v.sys,et.dirname(i))}function or(e,i){let t=aa(i)?.options??{target:v.ScriptTarget.ES2022,module:v.ModuleKind.ESNext,moduleResolution:v.ModuleResolutionKind.Node10,strict:!0,esModuleInterop:!0,skipLibCheck:!0,allowJs:!0},s=new Set(e),r=new Map;for(let u of e)try{r.set(u,kn.readFileSync(u,"utf8"))}catch{}let o={getScriptFileNames:()=>[...s],getScriptVersion:()=>"1",getScriptSnapshot:u=>{let d=r.get(u);if(d!=null)return v.ScriptSnapshot.fromString(d);try{let f=kn.readFileSync(u,"utf8");return v.ScriptSnapshot.fromString(f)}catch{return}},getCurrentDirectory:()=>i,getCompilationSettings:()=>t,getDefaultLibFileName:v.getDefaultLibFilePath,fileExists:v.sys.fileExists,readFile:v.sys.readFile,readDirectory:v.sys.readDirectory,directoryExists:v.sys.directoryExists,getDirectories:v.sys.getDirectories},a=v.createLanguageService(o,v.createDocumentRegistry()),l=a.getProgram(),c=l.getTypeChecker();return{service:a,checker:c,program:l,root:i}}function la(e,i,n,t,s){let r=e.program.getSourceFile(i);if(!r)return{count:-1,uniqueFiles:0};let o=ar(r,n,t);if(!o)return{count:-1,uniqueFiles:0};let a=e.service.findReferences(i,o.getStart(r));if(!a)return{count:0,uniqueFiles:0};let l=0,c=new Set;for(let u of a)for(let d of u.references)d.isDefinition||!s&&x(d.fileName)||(l++,c.add(d.fileName));return{count:l,uniqueFiles:c.size}}function ar(e,i,n){let t=e.getPositionOfLineAndCharacter(Math.max(0,n-1),0),s=n<e.getLineAndCharacterOfPosition(e.getEnd()).line+1?e.getPositionOfLineAndCharacter(n,0):e.getEnd(),r,o=a=>{if(!r){if(a.getStart(e)>=t&&a.getEnd()<=s&&v.isIdentifier(a)&&a.text===i){r=a;return}v.forEachChild(a,o)}};return v.forEachChild(e,o),r}function ca(e,i){let n=[],t=i,s=0,r=new Set;for(;;){let o=t.getBaseTypes?.()??[];if(o.length===0)break;let a=o[0],l=e.typeToString(a);if(r.has(l)||(r.add(l),n.push(l),s++,t=a,s>20))break}return{depth:s,chain:n}}function da(e,i,n,t){let s=new Map,r=n.dependencyProfile?.declaredExports??[];for(let o of r){if(o.lineStart==null)continue;let a=la(e,i,o.name,o.lineStart,t);s.set(o.name,{count:a.count,uniqueFiles:a.uniqueFiles,lineStart:o.lineStart,lineEnd:o.lineEnd??o.lineStart})}return s}function ua(e,i,n,t){let s=e.getPositionOfLineAndCharacter(Math.max(0,n-1),0),r,o=a=>{if(!r){if(a.getStart(e)>=s&&a.getEnd()<=e.getPositionOfLineAndCharacter(Math.min(t,e.getLineAndCharacterOfPosition(e.getEnd()).line+1)-1,0)+200&&(v.isFunctionDeclaration(a)||v.isMethodDeclaration(a)||v.isArrowFunction(a)||v.isFunctionExpression(a))&&((a.name&&v.isIdentifier(a.name)?a.name.text:"")===i||i==="<anonymous>")){r=a;return}v.forEachChild(a,o)}};return v.forEachChild(e,o),r}function fa(e,i,n,t){let s=[];for(let r of t.functions){if(!r.params||r.params===0||r.name==="<anonymous>"||r.name==="")continue;let o=ua(n,r.name,r.lineStart,r.lineEnd);if(!(!o||!(v.isFunctionDeclaration(o)||v.isMethodDeclaration(o)||v.isArrowFunction(o)||v.isFunctionExpression(o))))for(let a of o.parameters){if(!v.isIdentifier(a.name))continue;let l=a.name.text;if(l.startsWith("_"))continue;let c=e.service.findReferences(i,a.name.getStart(n)),u=0;if(c)for(let d of c)for(let f of d.references)f.isDefinition||u++;u===0&&s.push({functionName:r.name,paramName:l,lineStart:r.lineStart,lineEnd:r.lineEnd})}}return s}function pa(e,i,n,t){let s=0,r=0,o=n.dependencyProfile?.declaredExports??[],a=l=>{if(v.isClassDeclaration(l)&&l.name){let c=e.checker.getTypeAtLocation(l),{depth:u,chain:d}=ca(e.checker,c);if(u>0&&(t.typeHierarchies.push({name:l.name.text,depth:u,chain:d,lineStart:i.getLineAndCharacterOfPosition(l.getStart(i)).line+1}),u>t.typeHierarchyDepth&&(t.typeHierarchyDepth=u)),l.heritageClauses){for(let S of l.heritageClauses)if(S.token===v.SyntaxKind.ImplementsKeyword)for(let h of S.types){let y=e.checker.getTypeAtLocation(h),D=e.checker.typeToString(y),b=e.checker.getTypeAtLocation(l),k=y.getProperties?.()??[],C=new Set((b.getProperties?.()??[]).map(E=>E.name)),A=k.filter(E=>!C.has(E.name)).map(E=>E.name),M=[];for(let E of k)if(C.has(E.name)){let _=b.getProperty?.(E.name);if(_){let K=e.checker.getTypeOfSymbolAtLocation(_,l);e.checker.typeToString(K)==="any"&&M.push(E.name)}}(A.length>0||M.length>0)&&t.interfaceImpls.push({interfaceName:D,className:l.name.text,classFile:n.file,classLine:i.getLineAndCharacterOfPosition(l.getStart(i)).line+1,missingMembers:A,anycastMembers:M})}}l.modifiers?.some(S=>S.kind===v.SyntaxKind.AbstractKeyword)&&s++;let f=new Map,g=e.checker.getTypeAtLocation(l),m=0;for(;;){let S=g.getBaseTypes?.()??[];if(S.length===0)break;m++;let h=S[0];for(let y of h.getProperties?.()??[]){let D=y.getDeclarations?.()?.[0];D&&(v.isMethodDeclaration(D)||v.isMethodSignature(D))&&f.set(y.name,Math.max(f.get(y.name)??0,m))}if(g=h,m>20)break}for(let S of l.members)if(v.isMethodDeclaration(S)&&S.name&&v.isIdentifier(S.name)){let h=S.name.text,y=f.get(h);y!=null&&y>0&&t.overrideChains.push({methodName:h,className:l.name.text,depth:y,chain:[],lineStart:i.getLineAndCharacterOfPosition(S.getStart(i)).line+1})}}v.isInterfaceDeclaration(l)&&(s++,r++),v.isTypeAliasDeclaration(l)&&r++,v.forEachChild(l,a)};return v.forEachChild(i,a),r+=o.length,r>0?s/r:0}function ga(e,i,n,t){let s=[],r=[],o=t.dependencyProfile?.importedSymbols??[];for(let a of o){if(a.lineStart==null)continue;let l=ar(n,a.localName,a.lineStart);if(!l)continue;let c=e.service.findReferences(i,l.getStart(n)),u=0;if(c)for(let d of c)for(let f of d.references)f.isDefinition||f.fileName===i&&u++;if(u===0&&s.push({name:a.localName,lineStart:a.lineStart}),a.resolvedModule&&e.program.getSourceFile(et.resolve(e.root,a.resolvedModule))){let f=e.checker.getSymbolAtLocation(l);if(f){let g=(f.flags&v.SymbolFlags.Alias?e.checker.getAliasedSymbol(f):f).getDeclarations?.()?.[0];g&&v.isClassDeclaration(g)&&(g.modifiers?.some(S=>S.kind===v.SyntaxKind.AbstractKeyword)||r.push({name:a.localName,targetFile:a.resolvedModule,lineStart:a.lineStart}))}}}return{unusedImports:s,concreteImports:r}}function ma(e,i,n,t){let s=[],r=t.functions.filter(o=>t.dependencyProfile?.declaredExports?.some(a=>a.name===o.name));for(let o of r){let a=n.getPositionOfLineAndCharacter(Math.max(0,o.lineStart-1),0),l,c=u=>{if(!l){if((v.isFunctionDeclaration(u)||v.isMethodDeclaration(u))&&u.name&&v.isIdentifier(u.name)&&u.name.text===o.name&&u.getStart(n)>=a){l=u;return}v.forEachChild(u,c)}};if(v.forEachChild(n,c),l){let u=e.checker.getSignatureFromDeclaration(l);if(u){let d=e.checker.getReturnTypeOfSignature(u),f=d.symbol||d.aliasSymbol;if(f?.declarations?.[0]){let p=f.declarations[0].getSourceFile().fileName,g=et.relative(e.root,p);p!==i&&!g.startsWith("node_modules")&&!p.includes("lib.")&&s.push({functionName:o.name,returnType:e.checker.typeToString(d),sourceFile:g,lineStart:o.lineStart})}}}}return s}function ha(e,i,n,t){let s=[],r=t.functions.filter(o=>t.dependencyProfile?.declaredExports?.some(a=>a.name===o.name));for(let o of r){if(!o.params||o.params<1)continue;let a=n.getPositionOfLineAndCharacter(Math.max(0,o.lineStart-1),0),l,c=u=>{if(!l){if(v.isFunctionDeclaration(u)&&u.name?.text===o.name&&u.getStart(n)>=a){l=u;return}v.forEachChild(u,c)}};if(v.forEachChild(n,c),!!l)for(let u of l.parameters){if(!v.isIdentifier(u.name))continue;let d=e.checker.getTypeAtLocation(u);if(!d.isUnion()&&!(d.flags&(v.TypeFlags.Any|v.TypeFlags.Unknown)))continue;let f=e.checker.typeToString(d),p=e.service.findReferences(i,l.name.getStart(n));if(!p)continue;let g=[],m=!0,S=0;for(let h of p)for(let y of h.references){if(y.isDefinition)continue;let D=e.program.getSourceFile(y.fileName);if(!D)continue;let b=D,k=K=>{K.getStart(D)<=y.textSpan.start&&K.getEnd()>=y.textSpan.start+y.textSpan.length&&(b=K,v.forEachChild(K,k))};v.forEachChild(D,k);let C,A=b;for(;A;){if(v.isCallExpression(A)){C=A;break}A=A.parent}if(!C?.arguments)continue;let M=l.parameters.indexOf(u);if(M<0||M>=C.arguments.length){m=!1;continue}let E=e.checker.getTypeAtLocation(C.arguments[M]),_=e.checker.typeToString(E);g.push(_),S++,(_===f||_==="any"||_==="unknown")&&(m=!1)}if(m&&S>=2&&g.length>0){let h=[...new Set(g)];h.length<=2&&s.push({functionName:o.name,paramName:u.name.text,declaredType:f,actualTypes:h,narrowedType:h.length===1?h[0]:h.join(" | "),lineStart:o.lineStart,lineEnd:o.lineEnd})}}}return s}function lr(e,i,n,t=!0){let s={file:n.file,referenceCountByExport:new Map,unusedParams:[],interfaceImpls:[],typeHierarchyDepth:0,typeHierarchies:[],overrideChains:[],abstractnessRatio:0,unusedImports:[],concreteImports:[],leakyReturns:[],narrowableParams:[]},r=e.program.getSourceFile(i);if(!r)return s;s.referenceCountByExport=da(e,i,n,t),s.unusedParams=fa(e,i,r,n),s.abstractnessRatio=pa(e,r,n,s);let o=ga(e,i,r,n);return s.unusedImports=o.unusedImports,s.concreteImports=o.concreteImports,s.leakyReturns=ma(e,i,r,n),s.narrowableParams=ha(e,i,r,n),s}function cr(e,i,n){let t=new Set;for(let s of e)t.add(et.resolve(n,s.file));for(let s of i.files)t.add(et.resolve(n,s));return[...t].filter(s=>{try{return kn.statSync(s).isFile()}catch{return!1}})}var dr=N(()=>{"use strict";G()});import Cn from"node:path";function ya(e){for(let i of e.children)if(!i.isNamed&&(i.type==="&&"||i.type==="||"))return!0;return!1}function Sa(e,i){let n={complexity:1,maxBranchDepth:0,maxLoopDepth:0,returns:0,awaits:0,calls:0,loops:0,statements:0},t=(s,r,o)=>{if(n.statements+=1,["if_statement","while_statement","do_statement","for_statement","for_in_statement","for_of_statement","for_await_statement","switch_statement","catch_clause"].includes(s.type)&&(n.complexity+=1,r+=1,n.maxBranchDepth=Math.max(n.maxBranchDepth,r)),s.type==="conditional_expression"&&(n.complexity+=1),s.type==="binary_expression"&&ya(s)&&(n.complexity+=1),(s.type==="return_statement"||s.type==="throw_statement")&&(n.returns+=1),s.type==="await_expression"&&(n.awaits+=1),s.type==="call_expression"&&(n.calls+=1),["for_statement","for_in_statement","for_of_statement","for_await_statement","while_statement","do_statement"].includes(s.type)){let a=o+1;n.loops+=1,n.maxLoopDepth=Math.max(n.maxLoopDepth,a);for(let l of s.children)t(l,r,a);return}for(let a of s.children)t(a,r,o)};return t(e,0,0),n}function Ea(e){let i=0,n=(t,s)=>{let r=0,o=!1;if(ba.has(t.type)&&(r=1,o=!0),t.type==="binary_expression"){for(let a of t.children)if(!a.isNamed&&xa.has(a.type)){r=1;break}}if(t.type==="if_statement"&&t.parent?.type==="else_clause"&&(r=1,o=!1),o){i+=r+s;for(let a of t.children)n(a,s+1);return}i+=r;for(let a of t.children)n(a,s)};return n(e,0),i}function wa(e,i){let n=e.namedChildren.find(s=>["identifier","property_identifier","type_identifier"].includes(s.type));if(n)return n.text;let t=e.parent;for(;t;){if(t.type==="variable_declarator"){let s=t.namedChildren.find(r=>["identifier","property_identifier","array_pattern","object_pattern","shorthand_property_identifier_pattern"].includes(r.type));if(s&&s.type==="identifier")return s.text;break}if(t.type==="pair"){let s=t.namedChildren.find(r=>["identifier","string","shorthand_property_identifier_pattern","property_identifier"].includes(r.type));if(s)return s.text;break}if(["assignment_expression","method_definition","property_signature","public_field_definition"].includes(t.type)){let s=t.namedChildren.find(r=>["identifier","property_identifier","string","private_property_identifier"].includes(r.type));if(s)return s.text}if(t.type==="statement_block"||t.type==="program")break;t=t.parent}return"<anonymous>"}function va(e){let i=e.namedChildren.find(n=>n.type==="statement_block");return i?i.namedChildren.length:1}function Fa(e){let i=e.namedChildren.find(n=>n.type==="statement_block"||n.type==="switch_body");return i?i.namedChildren.length:e.namedChildren.length}function ur(e,i,n){return{file:Cn.relative(i,n),lineStart:e.startPosition.row+1,lineEnd:e.endPosition.row+1,columnStart:e.startPosition.column+1,columnEnd:e.endPosition.column+1}}function Tn(e,i,n,t,s){if(!Te?.available)return null;let r=Cn.extname(e),o=r===".tsx"||r===".jsx"?Te.parserTsx:Te.parserTs;if(!o)return null;let a=o.parse(i),l=Cn.relative(n.root,e),c={parseEngine:"tree-sitter",nodeCount:0,functions:[],flows:[]};if(n.emitTree){let d={size:8e3},f=hn(a.rootNode,i,n.treeDepth,d);f&&(c.tree=f)}let u=d=>{if(c.nodeCount+=1,yt.has(d.type)){let f=ur(d,n.root,e),p=Sa(d,i),g=va(d),m=wa(d,i),S=d.childForFieldName("parameters"),h=S?S.namedChildren.length:0,y={kind:d.type,name:m,nameHint:m,file:l,lineStart:f.lineStart,lineEnd:f.lineEnd,columnStart:f.columnStart,columnEnd:f.columnEnd,statementCount:g,lengthLines:f.lineEnd-f.lineStart+1,params:h,complexity:p.complexity,maxBranchDepth:p.maxBranchDepth,maxLoopDepth:p.maxLoopDepth,returns:p.returns,awaits:p.awaits,calls:p.calls,loops:p.loops,cognitiveComplexity:Ea(d),source:"tree-sitter"};if(c.functions.push(y),s&&g>=n.thresholds.minFunctionStatements){let D=d.namedChildren.find(k=>k.type==="statement_block"),b=D?gn(D):Ge(l);Se(s.flowMap,`${b}|${d.type}`,{...y,hash:b,metrics:p})}}if(ht.has(d.type)){let f=ur(d,n.root,e),p=Fa(d),g={kind:d.type,file:l,lineStart:f.lineStart,lineEnd:f.lineEnd,columnStart:f.columnStart,columnEnd:f.columnEnd,statementCount:p};if(c.flows.push(g),s&&p>=n.thresholds.minFlowStatements){let m=gn(d);Se(s.controlMap,`${m}|${d.type}`,{...g,hash:m})}}for(let f of d.children)u(f)};return u(a.rootNode),c}async function fr(){if(Te!==null)return Te;try{let e=await import("tree-sitter"),i=await import("tree-sitter-typescript"),n=e.default||e,t=i.typescript||i.default?.typescript,s=i.tsx||i.default?.tsx;if(!n||!t)throw new Error("Tree-sitter or tree-sitter-typescript did not expose expected exports");let r=new n;r.setLanguage(t);let o=new n;return o.setLanguage(s||t),Te={available:!0,parserTs:r,parserTsx:o},Te}catch(e){return Te={available:!1,parserTs:null,parserTsx:null,error:String(e?.message||e)},Te}}var Te,ba,xa,pr=N(()=>{"use strict";G();ge();Te=null;ba=new Set(["if_statement","for_statement","for_in_statement","for_of_statement","for_await_statement","while_statement","do_statement","catch_clause","conditional_expression","switch_statement"]),xa=new Set(["&&","||","??"])});import*as U from"typescript";function ae(e){return U.isFunctionDeclaration(e)||U.isFunctionExpression(e)||U.isArrowFunction(e)||U.isMethodDeclaration(e)||U.isConstructorDeclaration(e)||U.isGetAccessor(e)||U.isSetAccessor(e)}function We(e,i){if("name"in e&&e.name&&U.isIdentifier(e.name))return e.name.getText(i);let n=e.parent;return n&&U.isVariableDeclaration(n)&&n.name&&U.isIdentifier(n.name)||n&&U.isPropertyAssignment(n)&&U.isIdentifier(n.name)||n&&U.isPropertyDeclaration(n)&&n.name&&U.isIdentifier(n.name)||n&&U.isMethodDeclaration(n)&&n.name||n&&U.isGetAccessor(n)&&n.name||n&&U.isSetAccessor(n)&&n.name?n.name.getText(i):"<anonymous>"}var je=N(()=>{"use strict"});import*as T from"typescript";function $n(e){let i={complexity:1,maxBranchDepth:0,maxLoopDepth:0,returns:0,awaits:0,calls:0,loops:0},n=(t,s,r)=>{switch(t.kind){case T.SyntaxKind.IfStatement:case T.SyntaxKind.WhileStatement:case T.SyntaxKind.DoStatement:case T.SyntaxKind.ForStatement:case T.SyntaxKind.ForInStatement:case T.SyntaxKind.ForOfStatement:case T.SyntaxKind.SwitchStatement:case T.SyntaxKind.CatchClause:i.complexity+=1,s+=1,i.maxBranchDepth=Math.max(i.maxBranchDepth,s);break;case T.SyntaxKind.ConditionalExpression:i.complexity+=1;break;case T.SyntaxKind.ReturnStatement:case T.SyntaxKind.ThrowStatement:i.returns+=1;break;case T.SyntaxKind.AwaitExpression:i.awaits+=1;break;case T.SyntaxKind.CallExpression:i.calls+=1;break;default:t.kind===T.SyntaxKind.BinaryExpression&&(t.operatorToken.kind===T.SyntaxKind.AmpersandAmpersandToken||t.operatorToken.kind===T.SyntaxKind.BarBarToken)&&(i.complexity+=1)}if(t.kind===T.SyntaxKind.ForStatement||t.kind===T.SyntaxKind.ForInStatement||t.kind===T.SyntaxKind.ForOfStatement){let o=r+1;i.loops+=1,i.maxLoopDepth=Math.max(i.maxLoopDepth,o),T.forEachChild(t,a=>n(a,s,o));return}T.forEachChild(t,o=>n(o,s,r))};return n(e,0,0),i}function Dn(e){let i=new Map,n=new Map,t=m=>{if(T.isIdentifier(m)||T.isPrivateIdentifier(m)){let S=m.text;n.set(S,(n.get(S)||0)+1)}else if(T.isNumericLiteral(m)||T.isStringLiteral(m)||T.isNoSubstitutionTemplateLiteral(m)){let S=m.getText();n.set(S,(n.get(S)||0)+1)}else if(T.isToken(m)&&ka.has(m.kind)){let S=T.SyntaxKind[m.kind];i.set(S,(i.get(S)||0)+1)}T.forEachChild(m,t)};t(e);let s=i.size,r=n.size,o=0;for(let m of i.values())o+=m;let a=0;for(let m of n.values())a+=m;let l=s+r,c=o+a,u=l>0?c*Math.log2(l):0,d=r>0?s/2*(a/r):0,f=u*d,p=f/18,g=u/3e3;return{operators:o,operands:a,distinctOperators:s,distinctOperands:r,vocabulary:l,length:c,volume:u,difficulty:d,effort:f,time:p,estimatedBugs:g}}function Rn(e,i,n){let t=Math.max(e,1),s=Math.max(n,1),r=171-5.2*Math.log(t)-.23*i-16.2*Math.log(s);return Math.max(0,r*100/171)}function An(e,i){let n=R(e,i);return Math.max(1,n.lineEnd-n.lineStart+1)}var ka,Mn=N(()=>{"use strict";G();ka=new Set([T.SyntaxKind.PlusToken,T.SyntaxKind.MinusToken,T.SyntaxKind.AsteriskToken,T.SyntaxKind.SlashToken,T.SyntaxKind.PercentToken,T.SyntaxKind.AsteriskAsteriskToken,T.SyntaxKind.PlusPlusToken,T.SyntaxKind.MinusMinusToken,T.SyntaxKind.EqualsToken,T.SyntaxKind.PlusEqualsToken,T.SyntaxKind.MinusEqualsToken,T.SyntaxKind.AsteriskEqualsToken,T.SyntaxKind.SlashEqualsToken,T.SyntaxKind.EqualsEqualsToken,T.SyntaxKind.EqualsEqualsEqualsToken,T.SyntaxKind.ExclamationEqualsToken,T.SyntaxKind.ExclamationEqualsEqualsToken,T.SyntaxKind.LessThanToken,T.SyntaxKind.GreaterThanToken,T.SyntaxKind.LessThanEqualsToken,T.SyntaxKind.GreaterThanEqualsToken,T.SyntaxKind.AmpersandAmpersandToken,T.SyntaxKind.BarBarToken,T.SyntaxKind.ExclamationToken,T.SyntaxKind.QuestionQuestionToken,T.SyntaxKind.IfKeyword,T.SyntaxKind.ElseKeyword,T.SyntaxKind.ForKeyword,T.SyntaxKind.WhileKeyword,T.SyntaxKind.DoKeyword,T.SyntaxKind.SwitchKeyword,T.SyntaxKind.CaseKeyword,T.SyntaxKind.ReturnKeyword,T.SyntaxKind.ThrowKeyword,T.SyntaxKind.NewKeyword,T.SyntaxKind.DeleteKeyword,T.SyntaxKind.TypeOfKeyword,T.SyntaxKind.AwaitKeyword,T.SyntaxKind.YieldKeyword,T.SyntaxKind.DotToken,T.SyntaxKind.OpenParenToken,T.SyntaxKind.OpenBracketToken,T.SyntaxKind.EqualsGreaterThanToken,T.SyntaxKind.DotDotDotToken])});import*as be from"typescript";function Ta(e,i){let n=0,t=e;for(;be.isPropertyAccessExpression(t)||be.isElementAccessExpression(t);)n++,t=t.expression;if(n<Ca)return null;let s=e.parent;return be.isPropertyAccessExpression(s)||be.isElementAccessExpression(s)?null:{text:e.getText(i),depth:n}}function gr(e,i,n){let t=[],s=r=>{if(be.isPropertyAccessExpression(r)||be.isElementAccessExpression(r)){let o=Ta(r,e);if(o){let a=R(e,r);t.push({chain:o.text.slice(0,80),depth:o.depth,lineStart:a.lineStart,lineEnd:a.lineEnd})}}be.forEachChild(r,s)};be.forEachChild(e,s),t.length>0&&(n.messageChains=t)}var Ca,mr=N(()=>{"use strict";G();Ca=4});import*as $ from"typescript";function Sr(e,i){let n=[];for(let t of e.statements){if($.isImportDeclaration(t)){if(!t.importClause){let s=t.moduleSpecifier,r=$.isStringLiteral(s)?s.text:"<unknown>",o=R(e,t);n.push({kind:"side-effect-import",lineStart:o.lineStart,lineEnd:o.lineEnd,detail:`import '${r}'`,weight:3,confidence:"medium"})}continue}if(!($.isExportDeclaration(t)||$.isExportAssignment(t))&&!($.isTypeAliasDeclaration(t)||$.isInterfaceDeclaration(t)||$.isEnumDeclaration(t))&&!$.isModuleDeclaration(t)&&!(ae(t)||$.isFunctionDeclaration(t)||$.isClassDeclaration(t))){if($.isVariableStatement(t)){for(let s of t.declarationList.declarations)s.initializer&&yr(s.initializer,e,n);continue}if($.isExpressionStatement(t)){yr(t.expression,e,n);continue}($.isIfStatement(t)||$.isForStatement(t)||$.isWhileStatement(t)||$.isDoStatement(t)||$.isForOfStatement(t)||$.isForInStatement(t)||$.isSwitchStatement(t)||$.isTryStatement(t))&&br(t,e,n)}}return n}function yr(e,i,n){if($.isAwaitExpression(e)){let t=R(i,e);n.push({kind:"top-level-await",lineStart:t.lineStart,lineEnd:t.lineEnd,detail:"top-level await",weight:4,confidence:"high"});return}if($.isCallExpression(e)){Pn(e,i,n);return}if($.isNewExpression(e)&&e.expression.getText(i)==="Function"){let t=R(i,e);n.push({kind:"eval",lineStart:t.lineStart,lineEnd:t.lineEnd,detail:"new Function()",weight:8,confidence:"high"});return}$.isBinaryExpression(e)&&e.operatorToken.kind===$.SyntaxKind.EqualsToken&&$.isCallExpression(e.right)&&Pn(e.right,i,n)}function Pn(e,i,n){let t=e.expression.getText(i),s=R(i,e);if(t==="eval"||t==="Function"){n.push({kind:"eval",lineStart:s.lineStart,lineEnd:s.lineEnd,detail:`${t}()`,weight:8,confidence:"high"});return}if(t==="setInterval"||t==="setTimeout"){n.push({kind:"timer",lineStart:s.lineStart,lineEnd:s.lineEnd,detail:`${t}()`,weight:4,confidence:"high"});return}if($.isPropertyAccessExpression(e.expression)){let r=e.expression.name.getText(i),o=e.expression.expression.getText(i);if(hr.has(r)||hr.has(t)){n.push({kind:"exec-sync",lineStart:s.lineStart,lineEnd:s.lineEnd,detail:t,weight:8,confidence:"high"});return}if($a.has(r)){n.push({kind:"sync-io",lineStart:s.lineStart,lineEnd:s.lineEnd,detail:t,weight:5,confidence:"high"});return}if(o==="process"&&(r==="on"||r==="once"||r==="addListener")){n.push({kind:"process-handler",lineStart:s.lineStart,lineEnd:s.lineEnd,detail:`${t}()`,weight:4,confidence:"high"});return}if(r==="addEventListener"||r==="on"||r==="addListener"){n.push({kind:"listener",lineStart:s.lineStart,lineEnd:s.lineEnd,detail:`${t}()`,weight:4,confidence:"medium"});return}}($.isCallExpression(e.expression)||t==="import")&&(t.startsWith("import(")||$.isCallExpression(e)&&e.expression.kind===$.SyntaxKind.ImportKeyword)&&n.push({kind:"dynamic-import",lineStart:s.lineStart,lineEnd:s.lineEnd,detail:"dynamic import()",weight:3,confidence:"medium"})}function br(e,i,n){if(!(ae(e)||$.isClassDeclaration(e))){if($.isCallExpression(e)){Pn(e,i,n);return}if($.isAwaitExpression(e)){let t=R(i,e);n.push({kind:"top-level-await",lineStart:t.lineStart,lineEnd:t.lineEnd,detail:"top-level await",weight:4,confidence:"high"});return}if($.isNewExpression(e)&&e.expression.getText(i)==="Function"){let t=R(i,e);n.push({kind:"eval",lineStart:t.lineStart,lineEnd:t.lineEnd,detail:"new Function()",weight:8,confidence:"high"});return}$.forEachChild(e,t=>br(t,i,n))}}function Ct(e){let i=e.parent;for(;i;){if($.isBlock(i)||$.isSourceFile(i))return i;i=i.parent}return null}function xr(e,i,n){let t=!1,s=r=>{if(!t){if($.isCallExpression(r)&&r.expression.getText(i)===n){t=!0;return}$.forEachChild(r,s)}};return $.forEachChild(e,s),t}var $a,hr,Tt=N(()=>{"use strict";je();G();$a=new Set(["readFileSync","writeFileSync","existsSync","mkdirSync","readdirSync","statSync","lstatSync","unlinkSync","rmdirSync","renameSync","copyFileSync","accessSync","appendFileSync","chmodSync","chownSync","openSync","closeSync"]),hr=new Set(["execSync","execFileSync","spawnSync"])});import*as z from"typescript";function Ma(e){let i=!1;for(let n of e){if(Da.test(n))return"high";Ra.test(n)&&(i=!0)}return i?"medium":"low"}function Er(e,i,n){let t=[],s=r=>{if(!ae(r)){z.forEachChild(r,s);return}let o=r,a=o.parameters,l=[];for(let h of a){let y=h.name.getText(e);Aa.test(y)&&l.push(y)}if(l.length===0){z.forEachChild(r,s);return}let c=o.body;if(!c){z.forEachChild(r,s);return}let u=new Set,d=!1,f=[],p=new Set(l),g=h=>{if(!(ae(h)&&h!==r)){if(z.isCallExpression(h)){let y=h.expression.getText(e);for(let D of Pa)if(D.pattern.test(y)){u.add(D.kind);break}(Ia.test(y)||Na.test(y))&&(d=!0);for(let D of h.arguments){let b=D.getText(e);for(let k of p)if(b===k||b.startsWith(k+".")||b.startsWith(k+"[")){let C=R(e,h);f.push({callee:y,lineStart:C.lineStart});break}}}if(z.isTypeOfExpression(h)){let y=h.expression.getText(e);p.has(y)&&(d=!0)}if(z.isPrefixUnaryExpression(h)&&h.operator===z.SyntaxKind.ExclamationToken){let y=h.operand.getText(e);p.has(y)&&(d=!0)}if(z.isIfStatement(h)||z.isConditionalExpression(h)){let D=(z.isIfStatement(h)?h.expression:h.condition).getText(e);for(let b of p)if(D.includes(b)){d=!0;break}}if(z.isCallExpression(h)&&h.expression.getText(e).endsWith("instanceof")&&(d=!0),z.isBinaryExpression(h)&&h.operatorToken.kind===z.SyntaxKind.InstanceOfKeyword){let y=h.left.getText(e);p.has(y)&&(d=!0)}z.forEachChild(h,g)}};if(z.forEachChild(c,g),z.isTemplateExpression(c)||z.isBlock(c)){let h=c.getText(e);for(let y of p)if(h.includes(y+"?.")){d=!0;break}}let m=R(e,r),S=We(r,e);t.push({functionName:S,lineStart:m.lineStart,lineEnd:m.lineEnd,sourceParams:l,hasSinkInBody:u.size>0,sinkKinds:[...u],hasValidation:d,callsWithInputArgs:f,paramConfidence:Ma(l)}),z.forEachChild(r,s)};z.forEachChild(e,s),n.inputSources=t}var Da,Ra,Aa,Pa,Ia,Na,wr=N(()=>{"use strict";je();G();Da=/^(req|request|body|rawBody|formData|payload|query|headers|params)$/i,Ra=/^(input|event|message)$/i,Aa=/^(req|request|body|input|payload|data|params|query|headers|event|message|ctx|context|args|rawBody|formData)/i;Pa=[{pattern:/^eval$/,kind:"eval"},{pattern:/^Function$/,kind:"eval"},{pattern:/\.exec(Sync)?$/,kind:"exec"},{pattern:/^child_process\.(exec|spawn|fork)/,kind:"exec"},{pattern:/^execSync$|^spawnSync$/,kind:"exec"},{pattern:/^cp\.exec$|^cp\.spawn$/,kind:"exec"},{pattern:/\.innerHTML$|\.outerHTML$/,kind:"innerHTML"},{pattern:/dangerouslySetInnerHTML/,kind:"innerHTML"},{pattern:/\.query$|\.execute$/,kind:"sql"},{pattern:/\.redirect$/,kind:"redirect"},{pattern:/\.send$|\.json$|\.write$/,kind:"response"},{pattern:/fs\.(writeFile|appendFile)/,kind:"fs-write"},{pattern:/writeFileSync|appendFileSync/,kind:"fs-write"},{pattern:/fs\.(readFile|readFileSync|createReadStream)/,kind:"fs-read"},{pattern:/readFileSync|readFile/,kind:"fs-read"},{pattern:/path\.(resolve|join)/,kind:"path-resolve"},{pattern:/^fetch$/,kind:"ssrf"},{pattern:/^(http|https)\.(request|get)/,kind:"ssrf"},{pattern:/axios\.(get|post|put|delete|request)/,kind:"ssrf"}],Ia=/\.(validate|parse|safeParse|parseAsync|check|verify)\s*\(/,Na=/^(z|zod|Joi|yup|ajv|validator|superstruct|io-ts)\./});import*as ne from"typescript";function vr(e,i,n){let t=[],s=[],r=[],o=[],a=[],l=u=>{let d=u.parent;for(;d;){if(ne.isForStatement(d)||ne.isWhileStatement(d)||ne.isDoStatement(d)||ne.isForOfStatement(d)||ne.isForInStatement(d))return!0;if(ae(d))return!1;d=d.parent}return!1},c=u=>{if(ne.isAwaitExpression(u)&&l(u)){let d=R(e,u);t.push({file:i,lineStart:d.lineStart,lineEnd:d.lineEnd})}if(ne.isCallExpression(u)&&ne.isPropertyAccessExpression(u.expression)){let d=u.expression.name.getText(e);if(La.has(d)){let f=R(e,u);s.push({name:d,lineStart:f.lineStart,lineEnd:f.lineEnd})}if(d==="addEventListener"||d==="on"||d==="addListener"){let f=R(e,u);o.push({file:i,lineStart:f.lineStart,lineEnd:f.lineEnd})}if(d==="removeEventListener"||d==="off"||d==="removeListener"){let f=R(e,u);a.push({file:i,lineStart:f.lineStart,lineEnd:f.lineEnd})}}if(ne.isCallExpression(u)){let d=u.expression.getText(e);if(d==="setInterval"||d==="setTimeout"){let f=R(e,u),p=d==="setInterval"?"clearInterval":"clearTimeout",g=Ct(u),m=g?xr(g,e,p):!1;r.push({kind:d,lineStart:f.lineStart,lineEnd:f.lineEnd,hasCleanup:m})}}ne.forEachChild(u,c)};ne.forEachChild(e,c),n.awaitInLoopLocations=t,n.syncIoCalls=s,n.timerCalls=r,n.listenerRegistrations=o,n.listenerRemovals=a}var La,Fr=N(()=>{"use strict";Tt();je();G();La=new Set(["readFileSync","writeFileSync","existsSync","mkdirSync","readdirSync","statSync","lstatSync","unlinkSync","rmdirSync","renameSync","copyFileSync","accessSync","appendFileSync","chmodSync","chownSync","openSync","closeSync","execSync","execFileSync","spawnSync"])});import*as Q from"typescript";function ja(e,i){let n=e.argumentExpression;if(!n||!Q.isIdentifier(n))return!1;let t=n.getText(i),s=e.parent;for(;s;){if(Q.isForOfStatement(s)||Q.isForInStatement(s)){let r=s.initializer;if(r&&r.getText(i).includes(t)){let a=s.expression.getText(i);if(/Object\.(keys|values|entries|getOwnPropertyNames)\(/.test(a)||/\.keys\(\)|\.values\(\)|\.entries\(\)/.test(a)||/Array\.from\(/.test(a))return!0}}if(ae(s))break;s=s.parent}return!1}function _a(e,i){let n=Ct(e);if(!n)return!1;let t=n.getText(i);return/__proto__|constructor|prototype/.test(t)&&(t.includes("===")||t.includes("!==")||t.includes("includes(")||t.includes("hasOwnProperty"))}function Ha(e,i){let n=e.expression.getText(i),t=e.parent;for(;t;){if(Q.isBlock(t)||Q.isSourceFile(t)){let s=t.getText(i),r=new RegExp(`${n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\s*=\\s*Object\\.create\\(null\\)`),o=new RegExp(`${n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\s*=\\s*new\\s+(Map|Set)\\b`);if(r.test(s)||o.test(s))return!0;break}t=t.parent}return!1}function kr(e){let i=[],n=t=>{if(Q.isCallExpression(t)){let s=t.expression.getText(e);if(s==="Object.assign"&&t.arguments.length>=2){let o=R(e,t);i.push({kind:"object-assign",detail:"Object.assign() merges properties without __proto__ guard",lineStart:o.lineStart,lineEnd:o.lineEnd,guarded:!1})}let r=s.split(".").pop()||"";if(Oa.has(r)&&t.arguments.length>=1){let o=R(e,t);i.push({kind:"deep-merge",detail:`${r}() deep-merges without prototype guard`,lineStart:o.lineStart,lineEnd:o.lineEnd,guarded:!1})}}if(Q.isElementAccessExpression(t)&&t.argumentExpression&&!Q.isStringLiteral(t.argumentExpression)&&!Q.isNumericLiteral(t.argumentExpression)&&t.parent&&Q.isBinaryExpression(t.parent)&&t.parent.operatorToken.kind===Q.SyntaxKind.EqualsToken&&t.parent.left===t){let s=ja(t,e)||_a(t,e)||Ha(t,e),r=R(e,t);i.push({kind:"computed-property-write",detail:`Dynamic bracket assignment: ${t.getText(e).slice(0,40)}`,lineStart:r.lineStart,lineEnd:r.lineEnd,guarded:s})}Q.forEachChild(t,n)};return Q.forEachChild(e,n),i}var Oa,Cr=N(()=>{"use strict";Tt();je();G();Oa=new Set(["merge","deepMerge","deepAssign","extend","deepExtend","defaults","defaultsDeep","assign","mixin"])});import*as I from"typescript";function Ja(e){let i=e.parent;for(;i;){if(I.isRegularExpressionLiteral(i)||I.isNewExpression(i)&&i.expression.getText(e.getSourceFile())==="RegExp")return!0;i=i.parent}return!1}function Ya(e){return Va.test(e)||Qa.test(e)}function $r(e){let i=e.parent;for(;i;){if(I.isPropertyAssignment(i)&&I.isIdentifier(i.name)&&Xa.has(i.name.text))return!0;i=i.parent}return!1}function Za(e){let i=new Map;for(let t of e)i.set(t,(i.get(t)||0)+1);let n=0;for(let t of i.values()){let s=t/e.length;s>0&&(n-=s*Math.log2(s))}return n}function el(e,i){let n=e.parent;return I.isVariableDeclaration(n)?I.isIdentifier(n.name)?$t.test(n.name.text):!1:I.isPropertyAssignment(n)&&(I.isIdentifier(n.name)||I.isStringLiteral(n.name)||I.isNumericLiteral(n.name))?$t.test(n.name.text):I.isBinaryExpression(n)&&I.isPropertyAccessExpression(n.left)?$t.test(n.left.name.getText(i)):!1}function tl(e){return qa.test(e)?!1:Ba.some(n=>n.test(e))?!0:!za.some(n=>n.test(e))||Ka.test(e)?!1:Ua.test(e)}function Dr(e,i,n){let t=[],s=[],r=[],o=[],a=[],l=c=>{if(I.isDebuggerStatement(c)){let u=R(e,c);o.push({method:"debugger",lineStart:u.lineStart,lineEnd:u.lineEnd,hasSensitiveArg:!1})}if(I.isCallExpression(c)){let u=c.expression;if(I.isPropertyAccessExpression(u)){let d=u.expression.getText(e),f=u.name.getText(e);if(d==="console"&&Ga.has(f)){let p=R(e,c),g=c.arguments.map(S=>S.getText(e)).join(" "),m=tl(g);o.push({method:f,lineStart:p.lineStart,lineEnd:p.lineEnd,hasSensitiveArg:m,argSnippet:g.slice(0,80)})}}}if(I.isCallExpression(c)){let u=c.expression.getText(e);if(u==="eval"||u==="Function"){let d=R(e,c);t.push({file:i,lineStart:d.lineStart,lineEnd:d.lineEnd})}if(u==="new Function"){let d=R(e,c);t.push({file:i,lineStart:d.lineStart,lineEnd:d.lineEnd})}if((u==="setTimeout"||u==="setInterval")&&c.arguments.length>0){let d=c.arguments[0];if(I.isStringLiteral(d)||I.isNoSubstitutionTemplateLiteral(d)){let f=R(e,c);t.push({file:i,lineStart:f.lineStart,lineEnd:f.lineEnd})}}if(u==="document.write"||u==="document.writeln"){let d=R(e,c);s.push({file:i,lineStart:d.lineStart,lineEnd:d.lineEnd})}}if(I.isNewExpression(c)&&c.expression.getText(e)==="Function"){let u=R(e,c);t.push({file:i,lineStart:u.lineStart,lineEnd:u.lineEnd})}if(I.isBinaryExpression(c)&&c.operatorToken.kind===I.SyntaxKind.EqualsToken&&I.isPropertyAccessExpression(c.left)){let u=c.left.name.getText(e);if(u==="innerHTML"||u==="outerHTML"){let d=R(e,c);s.push({file:i,lineStart:d.lineStart,lineEnd:d.lineEnd})}}if(I.isJsxAttribute(c)&&c.name.getText(e)==="dangerouslySetInnerHTML"){let u=R(e,c);s.push({file:i,lineStart:u.lineStart,lineEnd:u.lineEnd})}if((I.isStringLiteral(c)||I.isNoSubstitutionTemplateLiteral(c))&&!$r(c)&&!Ja(c)){let u=c.text;if(!Ya(u)){let d=!1;for(let f of Tr)if(f.test(u)){let p=R(e,c);r.push({lineStart:p.lineStart,lineEnd:p.lineEnd,kind:"hardcoded-secret",snippet:u.slice(0,40),context:"literal"}),d=!0;break}if(!d&&u.length>=20&&Za(u)>4.5&&el(c,e)){let f=R(e,c);r.push({lineStart:f.lineStart,lineEnd:f.lineEnd,kind:"hardcoded-secret",context:"literal"})}}}if(I.isRegularExpressionLiteral(c)){let u=c.getText(e);for(let d of Tr)if(d.test(u)){let f=R(e,c);r.push({lineStart:f.lineStart,lineEnd:f.lineEnd,kind:"hardcoded-secret",snippet:u.slice(0,40),context:"regex-definition"});break}}if(I.isTemplateExpression(c)&&!$r(c)){let u=c.getText(e);if(Wa.test(u)&&c.templateSpans.length>0){let d=R(e,c);r.push({lineStart:d.lineStart,lineEnd:d.lineEnd,kind:"sql-injection",snippet:u.slice(0,60)})}}if(I.isRegularExpressionLiteral(c)){let u=c.text,d=R(e,c);a.push({lineStart:d.lineStart,lineEnd:d.lineEnd,pattern:u})}I.forEachChild(c,l)};I.forEachChild(e,l),n.evalUsages=t,n.unsafeHtmlAssignments=s,n.suspiciousStrings=r,n.consoleLogs=o,n.regexLiterals=a}var Ba,za,Ka,Ua,qa,$t,Ga,Tr,Wa,Va,Qa,Xa,Rr=N(()=>{"use strict";G();Ba=[/password/i,/passwd/i,/\bsecret\b/i,/\btoken\b/i,/credential/i,/credit.?card/i,/\bssn\b/i,/social.?security/i,/api[_-]?key/i,/private[_-]?key/i,/access[_-]?key/i],za=[/\bauth\b/i,/\bsession\b/i],Ka=/\b(auth|session)\b.{0,40}\b(flow|status|state|start(?:ed)?|success(?:ful|fully)?|fail(?:ed|ure)?|refresh(?:ed)?|renew(?:ed)?|expire(?:d)?|invalid|chang(?:e|ed)|required|created|destroyed)\b/i,Ua=/\b(id|sid|jwt|bearer|cookie|header|authorization|credential|secret|token|key)\b|[:=]|\{|\}/i,qa=/\busage:\b|\boptions:\b|--[a-z0-9-]+|\bunknown\b.{0,20}\btoken\b|\bpillar names?\b|\bcategory names?\b/i,$t=/(password|passwd|secret|token|api[_-]?key|private[_-]?key|access[_-]?key|credential|auth|session|jwt|bearer|ssn)/i,Ga=new Set(["log","debug","trace","info","warn","error","dir","table"]),Tr=[/password\s*[:=]\s*['"`]/i,/api[_-]?key\s*[:=]\s*['"`]/i,/secret\s*[:=]\s*['"`]/i,/token\s*[:=]\s*['"`]/i,/-----BEGIN.*KEY/,/private[_-]?key\s*[:=]\s*['"`]/i,/auth[_-]?token\s*[:=]\s*['"`]/i],Wa=/\b(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|TRUNCATE)\b/i,Va=/^(YOUR_|REPLACE_ME|<[a-z_-]+>|\$\{|{{)/i,Qa=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;Xa=new Set(["suggestedFix","strategy","steps","reason","impact","expectedResult","title"])});import*as q from"typescript";function cl(e,i){if(!q.isPropertyAccessExpression(e.expression))return;let n=e.expression.name.getText(i),t=e.expression.expression.getText(i);if((t==="jest"||t==="vi")&&n==="spyOn")return"spy";if(t==="sinon"&&(n==="stub"||n==="mock"))return"stub"}function dl(e,i){let n=e;for(;n.parent;){let t=n.parent;if(q.isVariableDeclaration(t)&&t.initializer===n&&q.isIdentifier(t.name))return t.name.getText(i);if(q.isBinaryExpression(t)&&t.operatorToken.kind===q.SyntaxKind.EqualsToken&&t.right===n)return t.left.getText(i).trim();n=t}}function ul(e,i){if(q.isPropertyAccessExpression(e.expression))return e.expression.expression.getText(i).trim()}function Ar(e,i,n){let t=[],s=[],r=[],o=[],a=[],l=[],c=[],u=[],d=(f,p,g)=>{if(q.isCallExpression(f)){let m=f.expression.getText(e);if(ol.has(m)){let S=R(e,f);a.push({kind:m,lineStart:S.lineStart,lineEnd:S.lineEnd})}if((m==="it"||m==="test"||m==="it.only"||m==="test.only")&&f.arguments.length>=2){let S=f.arguments[0],h=q.isStringLiteral(S)?S.text:m,y=f.arguments[1],D=R(e,f),b=0,k=C=>{if(q.isCallExpression(C)){let A=C.expression.getText(e);(nl.has(A.split(".")[0])||A.includes(".to.")||A.includes(".should"))&&b++}q.forEachChild(C,k)};q.forEachChild(y,k),t.push({name:h,lineStart:D.lineStart,lineEnd:D.lineEnd,assertionCount:b}),q.forEachChild(f,C=>d(C,p,!0));return}if(il.some(S=>m===S||m.startsWith(S+"("))){let S=R(e,f);s.push({file:i,lineStart:S.lineStart,lineEnd:S.lineEnd});let h=cl(f,e);h&&u.push({kind:h,file:i,lineStart:S.lineStart,lineEnd:S.lineEnd,target:dl(f,e)})}if(al.has(m)){let S=R(e,f);l.push({kind:m,lineStart:S.lineStart,lineEnd:S.lineEnd})}if(ll.has(m)){let S=R(e,f);l.push({kind:m,lineStart:S.lineStart,lineEnd:S.lineEnd})}if(sl.has(m)){let S=R(e,f);c.push({kind:"restoreAll",file:i,lineStart:S.lineStart,lineEnd:S.lineEnd})}else if(m.endsWith(".mockRestore")){let S=R(e,f);c.push({kind:"restore",file:i,lineStart:S.lineStart,lineEnd:S.lineEnd,target:ul(f,e)})}if(rl.has(m)){let S=R(e,f);r.push({kind:m,lineStart:S.lineStart})}if(m==="describe"||m==="describe.only"){q.forEachChild(f,S=>d(S,!0,g));return}}if(p&&!g&&q.isVariableStatement(f)){let m=f.declarationList;if(m.flags&q.NodeFlags.Let||!(m.flags&q.NodeFlags.Const)){let S=R(e,f);o.push({file:i,lineStart:S.lineStart,lineEnd:S.lineEnd})}}q.forEachChild(f,m=>d(m,p,g))};q.forEachChild(e,f=>d(f,!1,!1)),n.testProfile={testBlocks:t,mockCalls:s,setupCalls:r,mutableStateDecls:o,focusedCalls:a,timerControls:l,mockRestores:c,spyOrStubCalls:u}}var nl,il,sl,rl,ol,al,ll,Mr=N(()=>{"use strict";G();nl=new Set(["expect","assert","should"]),il=["jest.mock","vi.mock","sinon.stub","jest.spyOn","vi.spyOn","sinon.mock"],sl=new Set(["jest.restoreAllMocks","vi.restoreAllMocks"]),rl=new Set(["beforeAll","beforeEach","afterAll","afterEach"]),ol=new Set(["it.only","test.only","describe.only","it.skip","test.skip","describe.skip","it.todo","test.todo"]),al=new Set(["jest.useFakeTimers","vi.useFakeTimers"]),ll=new Set(["jest.useRealTimers","vi.useRealTimers"])});function W(e){return e.length<200}function we(e,i,n){let t=e.importedSymbolsByFile.get(i);if(t){for(let r of t)if(r.resolvedModule===n&&r.lineStart)return{lineStart:r.lineStart,lineEnd:r.lineEnd??r.lineStart}}let s=e.reExportsByFile.get(i);if(s){for(let r of s)if(r.resolvedModule===n&&r.lineStart)return{lineStart:r.lineStart,lineEnd:r.lineEnd??r.lineStart}}return{lineStart:1,lineEnd:1}}function de(e){let i=e.toLowerCase();return!!(/(^|\/)(index|main|app|server|cli|public)\.[mc]?[jt]sx?$/.test(i)||/\.(config)\.[mc]?[jt]sx?$/.test(i))}var he=N(()=>{"use strict"});function In(e){let i=[];if(e.testOnlyModules?.length===0)return i;for(let n of(e.testOnlyModules||[]).slice(0,25)){if(!W(i))break;i.push({severity:"medium",category:"dependency-test-only",file:n.file,lineStart:n.lineStart||1,lineEnd:n.lineEnd||1,title:`Module imported only from tests: ${n.file}`,reason:"No production file imports this module, but tests do. Verify if this module belongs in test fixtures/helpers.",files:[n.file],suggestedFix:{strategy:"Move test-only utilities to test scope or make production usage explicit.",steps:["Re-run import scanning after moving test-only modules to __tests__ or helper folders.","If this is shared production utility, add a non-test entrypoint/import.","Remove dead or stale production references and delete unused module if confirmed."]},impact:"Reduces shipping of non-production-only modules and clarifies ownership boundaries.",tags:["testing","dead-code","dependency"]})}return i}function Nn(e,i){let n=[];if(e.cycles?.length===0)return n;for(let t of(e.cycles||[]).slice(0,15)){let s=we(i,t.path[0],t.path[1]);if(!W(n))break;n.push({severity:"high",category:"dependency-cycle",file:t.path[0],lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Dependency cycle detected (${t.nodeCount} node cycle)`,reason:`Import cycle exists across: ${t.path.join(" -> ")}`,files:t.path,suggestedFix:{strategy:"Break the cycle with a lower-level abstraction or interface module.",steps:["Extract shared contracts/types to a dedicated contract/shared package.","Move implementation in one direction using dependency inversion.","Split stateful modules into protocol and runtime layers."]},impact:"Cycles increase coupling and make incremental loading/debugging and refactors riskier.",tags:["cycle","coupling","dependency","change-risk"],lspHints:[{tool:"lspGotoDefinition",symbolName:t.path[1],lineHint:s.lineStart,file:t.path[0],expectedResult:"navigate to the import that creates the cycle edge"}]})}return n}function fl(e,i){let n={module:e[0],fanOut:0,fanIn:0};for(let t of e){let s=(i.outgoing.get(t)||new Set).size,r=(i.incoming.get(t)||new Set).size;s>n.fanOut&&(n={module:t,fanOut:s,fanIn:r})}return n}function Pr(e,i=.8){if(e.length<=1)return e;let n=[],t=new Set;for(let s=0;s<e.length;s++){if(t.has(s))continue;let r=e[s],o=new Set(r.files),a=[r.file];for(let l=s+1;l<e.length;l++){if(t.has(l))continue;let c=e[l],u=new Set(c.files),d=[...o].filter(g=>u.has(g)).length,f=new Set([...o,...u]).size;if((f>0?d/f:0)>=i){t.add(l),a.push(c.file);for(let g of c.files)o.add(g)}}if(a.length>1){let l=[...o];n.push({...r,title:`Critical dependency chain risk: ${l.length} files (${a.length} entry points)`,reason:r.reason+` Also reached from: ${a.slice(1).join(", ")}.`,files:l})}else n.push(r)}return n}function Ln(e,i,n){let t=[];if(e.criticalPaths?.length===0)return t;for(let s of(e.criticalPaths||[]).slice(0,10)){if(s.score<n*3)continue;let r=we(i,s.path[0],s.path[1]),o=fl(s.path,i);t.push({severity:s.score>=n*6?"critical":"high",category:"dependency-critical-path",file:s.path[0],lineStart:r.lineStart,lineEnd:r.lineEnd,title:`Critical dependency chain risk: ${s.length} files`,reason:`Potentially high-change surface: ${s.path.join(" -> ")} (${s.score} weight).`,files:s.path,suggestedFix:{strategy:`Break chain at \`${o.module}\` (fan-out: ${o.fanOut}, fan-in: ${o.fanIn}).`,steps:[`Extract interface from \`${o.module}\` \u2014 it has ${o.fanOut} outbound dependencies.`,"Downstream modules depend on the interface, not the implementation.","This splits the chain into two independent segments."]},impact:"Critical refactor opportunities; shorter chains reduce blast radius of change.",tags:["change-risk","dependency","blast-radius"]})}return Pr(t)}function On(e,i){let n=[];for(let t of e.roots||[]){if(x(t)||de(t))continue;let s=(i.incoming.get(t)||new Set).size,r=(i.outgoing.get(t)||new Set).size;if(s===0&&!(r>0)){if(!W(n))break;n.push({severity:"medium",category:"dead-file",file:t,lineStart:1,lineEnd:1,title:`Potential dead file: ${t}`,reason:"File has no inbound imports and no outbound dependencies. It may be stale or orphaned.",files:[t],suggestedFix:{strategy:"Validate ownership and remove if truly unused.",steps:["Confirm the file is not an explicit runtime entrypoint.","Search runtime config/router/bootstrap references for this file path.","Delete file if confirmed dead and re-run scan."]},impact:"Reduces dead surface area and maintenance overhead.",tags:["dead-code","cleanup","hygiene"],lspHints:[{tool:"lspFindReferences",symbolName:t.split("/").pop()||t,lineHint:1,file:t,expectedResult:"confirm zero references exist before deletion"}]})}}return n}function jn(e){let i=[];for(let n of e.files){if(x(n)||de(n))continue;let t=(e.incoming.get(n)||new Set).size,s=(e.outgoing.get(n)||new Set).size;t===0&&s===0&&i.push({severity:"medium",category:"orphan-module",file:n,lineStart:1,lineEnd:1,title:`Orphan module: ${n}`,reason:"Module has no inbound or outbound dependencies \u2014 completely disconnected from the module graph.",files:[n],suggestedFix:{strategy:"Delete if truly unused, or wire into module graph.",steps:["Check if the file is a runtime entrypoint, route, or config.","If truly disconnected, delete and re-run scan.","If needed, add an explicit import from the appropriate parent module."]},impact:"Removes dead surface area and clarifies module ownership.",tags:["dead-code","dependency","isolation"]})}return i}function _n(e){let i=[],n=new Set;for(let r of e.files)de(r)&&n.add(r);if(n.size===0)for(let r of e.files)(e.incoming.get(r)||new Set).size===0&&n.add(r);let t=new Set,s=[...n];for(;s.length>0;){let r=s.pop();if(!t.has(r)){t.add(r);for(let o of e.outgoing.get(r)||new Set)e.files.has(o)&&!t.has(o)&&s.push(o)}}for(let r of e.files)if(!(x(r)||t.has(r)||de(r))){if(!W(i))break;i.push({severity:"high",category:"unreachable-module",file:r,lineStart:1,lineEnd:1,title:`Unreachable module: ${r}`,reason:"Module is not reachable from any entrypoint via the import graph.",files:[r],suggestedFix:{strategy:"Verify reachability and remove if truly dead.",steps:["Check if this module is loaded dynamically or via framework conventions.","Verify it is not registered as a route, plugin, or middleware.","If confirmed unreachable, delete and re-run scan."]},impact:"Identifies potentially large sections of dead code missed by direct-import checks.",tags:["dead-code","dependency","reachability"]})}return i}var Ir=N(()=>{"use strict";he();he();G()});function Hn(e,i){let n=e+i;return n===0?0:i/n}function Bn(e,i=.15,n=.6){let t=[],s=new Map,r=o=>{if(s.has(o))return s.get(o);let a=(e.incoming.get(o)||new Set).size,l=(e.outgoing.get(o)||new Set).size,c=Hn(a,l);return s.set(o,c),c};for(let o of e.files){if(x(o))continue;let a=e.outgoing.get(o)||new Set,l=r(o);for(let c of a){if(!e.files.has(c)||x(c))continue;let u=r(c),d=u-l;if(d>i&&l<n){let f=we(e,o,c);t.push({severity:d>.3?"high":"medium",category:"architecture-sdp-violation",file:o,lineStart:f.lineStart,lineEnd:f.lineEnd,title:"SDP violation: stable module depends on unstable module",reason:`"${o}" (I=${l.toFixed(2)}) depends on "${c}" (I=${u.toFixed(2)}). Delta=${d.toFixed(2)}.`,files:[o,c],suggestedFix:{strategy:"Invert dependency via interface/abstraction or move shared code to a stable utility.",steps:["Extract a stable interface that the stable module depends on.","Have the unstable module implement that interface.","Consider moving shared logic to a lower-instability utility module."]},impact:"Prevents cascading instability and reduces change propagation risk.",tags:["stability","coupling","architecture","sdp"]})}}}return t}function zn(e,i=15){let n=[];for(let t of e.files){if(x(t))continue;let s=(e.incoming.get(t)||new Set).size,r=(e.outgoing.get(t)||new Set).size,o=s+r;o>i&&n.push({severity:o>25?"high":"medium",category:"high-coupling",file:t,lineStart:1,lineEnd:1,title:`High coupling: ${t}`,reason:`Module has ${o} total connections (Ca=${s}, Ce=${r}). Threshold: ${i}.`,files:[t],suggestedFix:{strategy:"Reduce coupling by extracting interfaces or splitting module responsibilities.",steps:["Identify groups of related imports/dependents that can be isolated.","Extract focused sub-modules with single responsibilities.","Use dependency inversion to reduce direct coupling."]},impact:"Lower coupling reduces change ripple effects and improves testability.",tags:["coupling","change-risk","architecture"]})}return n}function Kn(e,i=20,n=15){let t=[];for(let s of e.files){if(x(s))continue;let r=(e.incoming.get(s)||new Set).size,o=(e.outgoing.get(s)||new Set).size;r>i&&t.push({severity:r>i*1.5?"high":"medium",category:"god-module-coupling",file:s,lineStart:1,lineEnd:1,title:`High fan-in bottleneck: ${s}`,reason:`Module is depended on by ${r} modules (threshold: ${i}). Changes ripple widely.`,files:[s],suggestedFix:{strategy:"Split this module into focused sub-modules to reduce blast radius.",steps:["Identify distinct groups of consumers using different parts of this module.","Extract each group into a dedicated module.","Update import paths incrementally."]},impact:"Reduces change blast radius and improves parallel development.",tags:["coupling","blast-radius","bottleneck"]}),o>n&&t.push({severity:o>n*1.5?"high":"medium",category:"god-module-coupling",file:s,lineStart:1,lineEnd:1,title:`High fan-out: ${s}`,reason:`Module depends on ${o} modules (threshold: ${n}). It may violate single responsibility.`,files:[s],suggestedFix:{strategy:"Reduce dependencies by introducing facade or mediator patterns.",steps:["Group related imports behind a single facade module.","Consider splitting this module by responsibility.","Use dependency injection to reduce direct coupling."]},impact:"Cleaner architecture and easier testing through reduced dependencies.",tags:["coupling","responsibility","sprawl"]})}return t}function Un(e,i){if(i.length<2)return[];let n=[],t=s=>{for(let r=0;r<i.length;r++)if(s.includes(i[r]))return r;return-1};for(let s of e.files){if(x(s))continue;let r=t(s);if(r!==-1)for(let o of e.outgoing.get(s)||new Set){if(!e.files.has(o)||x(o))continue;let a=t(o);if(a!==-1&&a<r){let l=we(e,s,o);n.push({severity:"high",category:"layer-violation",file:s,lineStart:l.lineStart,lineEnd:l.lineEnd,title:`Layer violation: ${i[r]} imports from ${i[a]}`,reason:`"${s}" (layer: ${i[r]}) imports "${o}" (layer: ${i[a]}). Layer order: ${i.join(" \u2192 ")}.`,files:[s,o],suggestedFix:{strategy:"Respect layer boundaries by inverting the dependency or moving shared logic.",steps:["Extract shared contracts to a lower layer that both can depend on.","Use dependency inversion: define an interface in the lower layer, implement in higher.","If the dependency is justified, reconsider your layer boundaries."]},impact:"Prevents architectural erosion and keeps dependency flow unidirectional.",tags:["architecture","layering","coupling"]})}}}return n}function Nr(e){return e.length===0?0:e.filter(n=>n.kind==="type").length/e.length}function qn(e,i=.7,n=3){let t=[];for(let s of e.files){if(x(s))continue;let r=e.declaredExportsByFile.get(s);if(!r||r.length===0)continue;let o=(e.incoming.get(s)||new Set).size,a=(e.outgoing.get(s)||new Set).size;if(o+a<n)continue;let l=Hn(o,a),c=Nr(r),u=Math.abs(c+l-1);if(u<i)continue;let d=c<.2&&l<.3,f=c>.7&&l>.7,p="";if(d?p="Zone of Pain (concrete + stable): hard to extend, painful to change.":f?p="Zone of Uselessness (abstract + unstable): over-abstracted and unused.":p="Far from Main Sequence: balance between abstraction and stability is off.",!W(t))break;t.push({severity:u>.85?"high":"medium",category:"distance-from-main-sequence",file:s,lineStart:1,lineEnd:1,title:`Distance from Main Sequence: ${s} (D=${u.toFixed(2)})`,reason:`${p} A=${c.toFixed(2)}, I=${l.toFixed(2)}, D=${u.toFixed(2)} (threshold: ${i}).`,files:[s],suggestedFix:{strategy:d?"Add abstractions (interfaces/types) or reduce inbound coupling.":f?"Add concrete implementations or remove unused abstractions.":"Rebalance by adjusting abstraction level or dependency direction.",steps:d?["Extract interfaces for key behaviors to increase abstractness.","Consider splitting into abstract contracts + concrete implementations.","Reduce inbound coupling by narrowing the public API surface."]:f?["Verify abstractions have concrete implementations.","Remove unused interfaces/types that serve no consumer.","Consider consolidating with concrete modules."]:["Review the balance between interfaces/types and concrete exports.","Adjust dependency direction to move closer to the Main Sequence.","Consider splitting responsibilities between abstract and concrete modules."]},impact:"Modules on the Main Sequence (D\u22480) have optimal balance between stability and extensibility.",tags:["architecture","stability","abstractness","sdp"]})}return t}var Lr=N(()=>{"use strict";he();he();G()});function Gn(e,i,n=500,t=20){let s=[];for(let r of e){if(x(r.file))continue;let o=r.functions.reduce((c,u)=>c+u.statementCount,0),a=(i.declaredExportsByFile.get(r.file)||[]).length,l=[];if(o>n&&l.push(`${o} statements (threshold: ${n})`),a>t&&l.push(`${a} exports (threshold: ${t})`),l.length!==0){if(!W(s))break;s.push({severity:"high",category:"god-module",file:r.file,lineStart:1,lineEnd:1,title:`God module: ${r.file}`,reason:`Module is excessively large: ${l.join("; ")}.`,files:[r.file],suggestedFix:{strategy:"Split module into focused sub-modules with single responsibilities.",steps:["Identify distinct functional groups within the module.","Extract each group into a dedicated module.","Create a barrel if backward compatibility is needed.","Update imports incrementally."]},impact:"Smaller modules are easier to understand, test, and maintain.",tags:["complexity","responsibility","size"],lspHints:[{tool:"lspFindReferences",symbolName:r.file.split("/").pop()||r.file,lineHint:1,file:r.file,expectedResult:"identify consumer clusters to guide module splitting strategy"}]})}}return s}function pl(e){let i=e.replace(/\\/g,"/"),n=i.lastIndexOf("/");return n===-1?".":i.slice(0,n)}function Wn(e,i=25,n=.25){let t=[],s=e.filter(a=>!x(a.file));if(s.length===0)return t;let r=new Map;for(let a of s){let l=pl(a.file);r.has(l)||r.set(l,[]),r.get(l).push(a)}let o=[...r.entries()].map(([a,l])=>({folder:a,entries:l,count:l.length})).filter(({count:a})=>a>=i&&a/s.length>=n).sort((a,l)=>l.count-a.count);for(let a of o){let l=a.count/s.length,c=l>=.5||a.count>=50?"high":"medium",u=a.entries.map(f=>f.file).sort().slice(0,8),d=a.entries[0]?.file??a.folder;if(!W(t))break;t.push({severity:c,category:"mega-folder",file:d,lineStart:1,lineEnd:1,title:`Mega folder: ${a.folder} (${a.count} files)`,reason:`${a.folder} contains ${a.count} production files (${(l*100).toFixed(1)}% of the codebase), which usually indicates mixed responsibilities and weak module boundaries.`,files:u,suggestedFix:{strategy:"Map the import graph, identify domain clusters, then restructure with an automated migration script.",steps:["Extract the local import graph (rg/localSearchCode) and group files into clusters by what imports what.","Design target directories that follow the data flow (e.g., types \u2192 parsing \u2192 analysis \u2192 detection \u2192 reporting \u2192 orchestration).","Write a disposable migration script that maps old basenames to { dir, name } targets, moves files, and rewrites all relative import paths atomically.","Validate after each phase: tsc --noEmit, eslint --fix, test suite.","Move shared primitives into a dedicated common/ folder to avoid cross-domain coupling."]},impact:"Improves navigability, ownership boundaries, and change isolation.",tags:["architecture","modularity","folder-structure","maintainability"],evidence:{folderPath:a.folder,fileCount:a.count,totalProductionFiles:s.length,concentration:l},lspHints:[{tool:"lspGotoDefinition",symbolName:a.folder,lineHint:1,file:d,expectedResult:"inventory representative modules in this folder before planning decomposition"}]})}return t}function Vn(e,i=100,n=10){let t=[];for(let r of e)if(!x(r.file))for(let o of r.functions){let a=o.statementCount>i,l=o.maintainabilityIndex!==void 0&&o.maintainabilityIndex<n&&o.lengthLines>30;if(a||l){let c=l&&o.maintainabilityIndex!==void 0?` MI=${o.maintainabilityIndex.toFixed(1)} (threshold: ${n}).`:"",u=a?`${o.statementCount} statements (threshold: ${i}).`:"";t.push({severity:"high",category:"god-function",file:r.file,lineStart:o.lineStart,lineEnd:o.lineEnd,title:`God function: ${o.name}`,reason:`Function "${o.name}" triggers god-function detection. ${u}${c}`.trim(),files:[`${r.file}:${o.lineStart}-${o.lineEnd}`],suggestedFix:{strategy:"Break down into smaller, focused functions.",steps:["Identify logical steps within the function.","Extract each step into a named helper.","Keep the original as a high-level orchestrator.","Test each extracted function independently."]},impact:"Improves readability, testability, and maintenance.",tags:["complexity","responsibility","size"],lspHints:[{tool:"lspCallHierarchy",symbolName:o.name,lineHint:o.lineStart,file:r.file,expectedResult:`map callers and callees to identify safe extraction boundaries for ${o.name}`}]})}}return t}function Qn(e,i=3){let n=[];for(let t of e.files){if(x(t)||de(t))continue;let s=e.declaredExportsByFile.get(t);if(!s||s.length<i)continue;let r=new Set(s.map(d=>d.name)),o=new Map;for(let[d,f]of e.importedSymbolsByFile.entries())for(let p of f)p.resolvedModule===t&&r.has(p.importedName)&&(o.has(p.importedName)||o.set(p.importedName,new Set),o.get(p.importedName).add(d));let a=[...o.keys()];if(a.length<2)continue;let l=new Map;for(let d of a)l.set(d,new Set);for(let d of e.importedSymbolsByFile.values()){let f=d.filter(p=>p.resolvedModule===t&&r.has(p.importedName)).map(p=>p.importedName);for(let p=0;p<f.length;p++)for(let g=p+1;g<f.length;g++)l.get(f[p])?.add(f[g]),l.get(f[g])?.add(f[p])}let c=new Set,u=0;for(let d of a){if(c.has(d))continue;u++;let f=[d];for(;f.length>0;){let p=f.pop();if(!c.has(p)){c.add(p);for(let g of l.get(p)||[])c.has(g)||f.push(g)}}}u>1&&n.push({severity:u>=4?"high":"medium",category:"low-cohesion",file:t,lineStart:1,lineEnd:1,title:`Low cohesion: ${t} (LCOM=${u})`,reason:`Module exports ${a.length} consumed symbols that form ${u} independent groups. Consumers never import symbols across groups \u2014 the module serves unrelated purposes.`,files:[t],suggestedFix:{strategy:`Split into ${u} focused modules, one per cohesion group.`,steps:["Identify which exports belong to each independent group.","Create a new module for each group with a descriptive name.","Move exports and their dependencies to the appropriate module.","Update consumer imports to point to the new modules."]},impact:"Higher cohesion = easier navigation, focused testing, and smaller change blast radius.",tags:["cohesion","responsibility","architecture"]})}return n}function _e(e,i,n,t=20){let s=new Set;for(let a of i.cycles)for(let l of a.path)s.add(l);let r=new Set;for(let a of i.criticalPaths)for(let l of a.path)r.add(l);let o=[];for(let a of e.files){if(x(a))continue;let l=(e.incoming.get(a)||new Set).size,c=(e.outgoing.get(a)||new Set).size,d=n.get(a)?.score??0,f=(e.declaredExportsByFile.get(a)||[]).length,p=s.has(a),g=r.has(a),m=Math.round(l*3+d*.5+f*1.5+c*.5+(p?20:0)+(g?10:0));m>0&&o.push({file:a,riskScore:m,fanIn:l,fanOut:c,complexityScore:d,exportCount:f,inCycle:p,onCriticalPath:g})}return o.sort((a,l)=>l.riskScore-a.riskScore),o.slice(0,t)}function Jn(e,i,n,t=40){let s=[],r=new Set,o=l=>{let c=e.incomingFromTests.get(l);return!!c&&c.size>0},a=(l,c,u)=>{if(r.has(l)||(r.add(l),x(l))||o(l))return;let d=c>=60;W(s)&&s.push({severity:d?"critical":"high",category:"untested-critical-code",file:l,lineStart:1,lineEnd:1,title:`Untested critical code: ${l}`,reason:`High-risk file has no test imports. ${u.join("; ")} (risk score: ${c}).`,files:[l],suggestedFix:{strategy:"Add test coverage for this critical module.",steps:["Create a test file that imports and exercises the public API of this module.","Focus on the highest-complexity functions and exported behaviors first.","Add integration tests if this module sits on a critical dependency path.","Consider property-based tests for complex data transformations."]},impact:"Untested critical code is the highest-risk area for regressions and undetected bugs.",tags:["testing","coverage","change-risk","critical"]})};for(let l of i){let c=[];c.push(`fan-in=${l.fanIn}, fan-out=${l.fanOut}, complexity=${l.complexityScore}`),l.inCycle&&c.push("in dependency cycle"),l.onCriticalPath&&c.push("on critical dependency path"),a(l.file,l.riskScore,c)}for(let[l,c]of n){if(c.score<t)continue;let u=[`high complexity score (${c.score}), ${c.highComplexityFunctions} high-complexity functions`];a(l,c.score,u)}return s.sort((l,c)=>{let u={critical:4,high:3,medium:2,low:1,info:0};return(u[c.severity]||0)-(u[l.severity]||0)}),s.slice(0,25)}function Yn(e,i=.6,n=5){let t=[];for(let[s,r]of e.importedSymbolsByFile.entries()){if(x(s)||!e.files.has(s))continue;let o=r.filter(l=>l.resolvedModule&&!l.isTypeOnly);if(o.length<n)continue;let a=new Map;for(let l of o)l.resolvedModule&&a.set(l.resolvedModule,(a.get(l.resolvedModule)||0)+1);for(let[l,c]of a){let u=c/o.length;if(u>=i&&c>=n){let d=we(e,s,l);t.push({severity:u>.8?"high":"medium",category:"feature-envy",file:s,lineStart:d.lineStart,lineEnd:d.lineEnd,title:`Feature envy: ${s} \u2192 ${l}`,reason:`Module imports ${c}/${o.length} symbols (${(u*100).toFixed(0)}%) from "${l}". This suggests the logic may belong in or closer to the target module.`,files:[s,l],suggestedFix:{strategy:"Move dependent logic to the target module or extract a shared module.",steps:["Identify which functions/logic in this file use the imported symbols.","Move that logic to the target module if it belongs there.","If shared, extract a dedicated module that both can import from.","Reduce the import surface by passing data instead of importing behaviors."]},impact:"Misplaced logic increases coupling and makes changes ripple across module boundaries.",tags:["coupling","responsibility","misplaced-logic"],lspHints:[{tool:"lspCallHierarchy",symbolName:s.split("/").pop()||s,lineHint:d.lineStart,file:s,expectedResult:`trace which functions use imports from ${l} to decide what to move`},{tool:"lspGotoDefinition",symbolName:l.split("/").pop()||l,lineHint:d.lineStart,file:s,expectedResult:"inspect target module to evaluate if logic belongs there"}]})}}}return t}var Or=N(()=>{"use strict";he();he();G()});function Xn(e,i,n=new Set){if(n.has(e))return 0;n.add(e);let t=i.reExportsByFile.get(e);if(!t||t.length===0)return 0;let s=0;for(let r of t){let o=r.resolvedModule;if(!o)continue;let a=i.reExportsByFile.get(o);a&&a.length>0&&(s=Math.max(s,Xn(o,i,n)))}return 1+s}function Zn(e,i=30){let n=[];for(let[t,s]of e.reExportsByFile.entries()){if(x(t)||s.length===0)continue;s.length>i&&n.push({severity:s.length>i*2?"high":"medium",category:"barrel-explosion",file:t,lineStart:1,lineEnd:1,title:`Barrel explosion: ${t}`,reason:`Barrel re-exports ${s.length} symbols (threshold: ${i}). Large barrels hurt bundling.`,files:[t],suggestedFix:{strategy:"Split barrel or use direct imports to reduce bundler cost.",steps:["Group re-exports by domain into sub-barrels.","Let consumers import directly from source modules.","Remove unused re-exports (check dead-re-export findings)."]},impact:"Reduces bundle size and speeds up IDE/tooling.",tags:["barrel","bundle-size","tree-shaking"]});let r=Xn(t,e);r>2&&n.push({severity:"high",category:"barrel-explosion",file:t,lineStart:1,lineEnd:1,title:`Deep barrel chain: ${t} (depth ${r})`,reason:`Barrel chain is ${r} levels deep. Deep chains defeat tree-shaking.`,files:[t],suggestedFix:{strategy:"Flatten barrel chain to at most 2 levels.",steps:["Re-export directly from source modules instead of intermediate barrels.","Remove intermediate barrel layers that add no value."]},impact:"Improves tree-shaking efficiency and import resolution speed.",tags:["barrel","bundle-size","tree-shaking"]})}return n}function ei(e,i,n,t){let s=[],r=new Set;for(let l of n.cycles)for(let c of l.path)r.add(c);let o=new Set;for(let l of n.criticalPaths)for(let c of l.path)o.add(c);let a=new Map;for(let l of t)a.set(l.file,l);for(let l of e){if(x(l.file))continue;let c=l.topLevelEffects;if(!c||c.length===0)continue;let u=0;for(let C of c)u+=C.weight;let d=(i.incoming.get(l.file)||new Set).size,f=0;d>=20?f+=8:d>=8&&(f+=4),o.has(l.file)&&(f+=6),r.has(l.file)&&(f+=3);let p=0;de(l.file)&&(p+=4);let g=u+f-p;if(g<4)continue;let m=g>=18?"critical":g>=12?"high":g>=7?"medium":"low",h=c.filter(C=>C.confidence==="high").length>0?"high":c.some(C=>C.confidence==="medium")?"medium":"low",y=c.map(C=>`${C.detail} (line ${C.lineStart})`).join("; "),D=[];d>=8&&D.push(`fan-in=${d}`),o.has(l.file)&&D.push("on critical path"),r.has(l.file)&&D.push("in dependency cycle"),de(l.file)&&D.push("entrypoint (discounted)");let b=D.length>0?` Architecture context: ${D.join(", ")}.`:"",k=c[0];if(!W(s))break;s.push({severity:m,category:"import-side-effect-risk",file:l.file,lineStart:k.lineStart,lineEnd:k.lineEnd,title:`Import-time side effect${c.length>1?`s (${c.length})`:""}: ${l.file}`,reason:`Module executes work at import time: ${y}. Risk score: ${g} (ast=${u}, impact=+${f}, role=-${p}). Confidence: ${h}.${b}`,files:[l.file],suggestedFix:{strategy:"Move import-time side effects behind explicit initialization or lazy loading.",steps:["Wrap startup logic in an exported init() function instead of running at module scope.","Replace synchronous I/O with async alternatives called at runtime.","Guard side-effect imports with dynamic import() behind feature checks.","If this is an intentional entrypoint, consider adding a suppression comment."]},impact:`Importing this module triggers ${c.length} side effect(s). With fan-in=${d}, unintended imports can degrade startup latency and cause surprising runtime behavior.`,tags:["import-side-effect","startup","architecture","performance"],lspHints:[{tool:"lspFindReferences",symbolName:l.file.split("/").pop()?.replace(/\.[^.]+$/,"")||l.file,lineHint:1,file:l.file,expectedResult:"find all modules that import this file and may trigger side effects"}]})}return s}function ti(e){let i=[];for(let[n,t]of e.importedSymbolsByFile.entries())if(!x(n))for(let s of t){if(s.importedName!=="*"||s.isTypeOnly||s.localName==="require")continue;let r=s.resolvedModule!=null,o=r?(e.incoming.get(s.resolvedModule)||new Set).size:0;i.push({severity:r&&o>5?"high":"medium",category:"namespace-import",file:n,lineStart:s.lineStart||1,lineEnd:s.lineEnd||s.lineStart||1,title:`Namespace import blocks tree-shaking: import * as ${s.localName}`,reason:`\`import * as ${s.localName} from '${s.sourceModule}'\` forces bundlers to include the entire module. Named imports allow dead-code elimination of unused exports.${r?` Target module has fan-in=${o}.`:""}`,files:[`${n}:${s.lineStart||1}-${s.lineEnd||s.lineStart||1}`],suggestedFix:{strategy:"Replace namespace import with named imports for used symbols.",steps:[`Find which properties of \`${s.localName}\` are actually accessed in this file.`,`Replace \`import * as ${s.localName}\` with \`import { usedA, usedB } from '${s.sourceModule}'\`.`,"If many properties are used, consider splitting the source module into smaller modules."]},impact:"Enables bundlers to tree-shake unused exports, reducing bundle size.",tags:["tree-shaking","bundle-size","namespace-import"]})}return i}function ni(e){let i=[];for(let[n,t]of e.importedSymbolsByFile.entries()){if(x(n))continue;let s=t.filter(a=>a.localName==="require"&&!a.isTypeOnly);if(s.length===0)continue;let r=t.some(a=>a.localName!=="require"),o=r?"high":"medium";for(let a of s)i.push({severity:o,category:r?"mixed-module-format":"commonjs-in-esm",file:n,lineStart:a.lineStart||1,lineEnd:a.lineEnd||a.lineStart||1,title:r?`Mixed ESM/CJS: require('${a.sourceModule}') in ESM file`:`CommonJS require blocks tree-shaking: require('${a.sourceModule}')`,reason:r?`File uses both ESM \`import\` and CJS \`require()\`. Mixed formats force bundlers to treat the module as CJS, disabling tree-shaking entirely. Found ${s.length} require() call(s).`:`\`require('${a.sourceModule}')\` is a CommonJS pattern that bundlers cannot statically analyze. ESM \`import\` enables tree-shaking.`,files:[`${n}:${a.lineStart||1}-${a.lineEnd||a.lineStart||1}`],suggestedFix:{strategy:"Convert require() to ESM import.",steps:[`Replace \`const mod = require('${a.sourceModule}')\` with \`import mod from '${a.sourceModule}'\` or named imports.`,"If the require is conditional, use dynamic `import()` instead.",'Ensure the target module supports ESM (check package.json "type" or "module" field).']},impact:"ESM imports enable tree-shaking; CJS requires pull the entire module.",tags:["tree-shaking","bundle-size","commonjs","module-format"]})}return i}function ii(e){let i=[];for(let[n,t]of e.reExportsByFile.entries()){if(x(n))continue;let s=t.filter(r=>r.isStar&&!r.isTypeOnly);if(s.length!==0)for(let r of s){let o=r.resolvedModule?(e.declaredExportsByFile.get(r.resolvedModule)||[]).length:0,a=r.resolvedModule?(e.reExportsByFile.get(r.resolvedModule)||[]).some(c=>c.isStar):!1,l=a||o>20?"high":"medium";i.push({severity:l,category:"export-star-leak",file:n,lineStart:r.lineStart||1,lineEnd:r.lineEnd||r.lineStart||1,title:`export * leaks entire module surface: ${r.sourceModule}`,reason:`\`export * from '${r.sourceModule}'\` re-exports every symbol from the source, defeating granular tree-shaking.${o>0?` Target exports ${o} symbols.`:""}${a?" Target itself contains export-star chains, amplifying the leak.":""}`,files:[`${n}:${r.lineStart||1}-${r.lineEnd||r.lineStart||1}`],suggestedFix:{strategy:"Replace export * with explicit named re-exports.",steps:[`List the symbols actually consumed from \`${r.sourceModule}\` by downstream modules.`,`Replace \`export * from '${r.sourceModule}'\` with \`export { A, B, C } from '${r.sourceModule}'\`.`,"This lets bundlers eliminate unused re-exports during tree-shaking."]},impact:"Explicit re-exports enable precise tree-shaking and make the public API surface visible.",tags:["tree-shaking","bundle-size","export-star","api-surface"]})}}return i}var jr=N(()=>{"use strict";he();he();G()});function si(e){let i=new Map,n=new Map;for(let[t,s]of e.importedSymbolsByFile.entries()){let r=x(t)?n:i;for(let o of s){let a=o.resolvedModule;a&&(r.has(a)||r.set(a,new Set),r.get(a).add(o.importedName))}}for(let[t,s]of e.reExportsByFile.entries()){let r=x(t)?n:i;for(let o of s){let a=o.resolvedModule;a&&(r.has(a)||r.set(a,new Set),r.get(a).add(o.importedName))}}return{production:i,test:n}}function ri(e,i,n){let t=[];for(let[s,r]of e.declaredExportsByFile.entries()){if(x(s)||de(s))continue;let o=i.get(s)||new Set,a=n?.get(s)||new Set,l=o.has("*"),c=a.has("*");for(let u of r)u.name==="default"&&de(s)||l||o.has(u.name)||c||a.has(u.name)||t.push({severity:u.kind==="type"?"medium":"high",category:"dead-export",file:s,lineStart:u.lineStart||1,lineEnd:u.lineEnd||u.lineStart||1,title:`Unused export: ${u.name}`,reason:`Exported symbol "${u.name}" has no observed import or re-export usage in production or test files.`,files:[`${s}:${u.lineStart||1}-${u.lineEnd||u.lineStart||1}`],suggestedFix:{strategy:"Remove or internalize unused exports.",steps:["Confirm symbol is not part of intentional public API surface.","Remove export modifier or delete symbol if truly unused.","Re-run scan and tests to ensure no hidden runtime usage."]},impact:"Shrinks public API surface and reduces accidental coupling.",tags:["dead-code","api-surface","cleanup"],lspHints:[{tool:"lspFindReferences",symbolName:u.name,lineHint:u.lineStart||1,file:s,expectedResult:`confirm "${u.name}" has no import references before removing`}]})}return t}function oi(e,i){let n=[];for(let[t,s]of e.reExportsByFile.entries()){if(x(t))continue;let r=i.get(t)||new Set,o=r.has("*"),a=new Map,l=new Set((e.declaredExportsByFile.get(t)||[]).map(c=>c.name));for(let c of s){let u=c.exportedAs;a.has(u)||a.set(u,new Set),a.get(u).add(c.resolvedModule||c.sourceModule),o||r.has(u)||c.isStar&&r.size>0||n.push({severity:"medium",category:"dead-re-export",file:t,lineStart:c.lineStart||1,lineEnd:c.lineEnd||c.lineStart||1,title:`Unused re-export: ${u}`,reason:`Re-exported symbol "${u}" from ${c.sourceModule} has no observed downstream imports from this module.`,files:[`${t}:${c.lineStart||1}-${c.lineEnd||c.lineStart||1}`],suggestedFix:{strategy:"Remove stale barrel re-exports.",steps:["Verify no dynamic import/runtime reflection depends on this export.","Remove the re-export clause.","Re-run scan to confirm barrel surface is still complete."]},impact:"Keeps barrel modules focused and easier to reason about.",tags:["dead-code","barrel","cleanup"]})}for(let[c,u]of a.entries())u.size>1&&n.push({severity:"medium",category:"re-export-duplication",file:t,lineStart:1,lineEnd:1,title:`Duplicate re-export paths: ${c}`,reason:`Symbol "${c}" is re-exported from multiple sources in the same barrel.`,files:[t],suggestedFix:{strategy:"Keep one canonical re-export source per symbol.",steps:["Select a canonical module for the symbol.","Remove duplicate re-export paths.","Document intended public export map for the barrel."]},impact:"Reduces API ambiguity and import inconsistency.",tags:["duplication","barrel","api-surface"]}),c!=="*"&&l.has(c)&&n.push({severity:"high",category:"re-export-shadowed",file:t,lineStart:1,lineEnd:1,title:`Shadowed export in barrel: ${c}`,reason:`Barrel exports "${c}" both locally and through re-export, which can hide origin and create ambiguity.`,files:[t],suggestedFix:{strategy:"Disambiguate local vs re-exported symbol ownership.",steps:["Pick a single source of truth for the symbol in this barrel.","Rename or remove the conflicting export path.","Update import call-sites to use the canonical export."]},impact:"Prevents subtle API conflicts and shadowing confusion.",tags:["barrel","api-surface","ambiguity"]})}return n}function ai(e,i,n={}){let t=[],s=new Set;for(let r of e.values())for(let o of r){let a=o.split("/");s.add(o.startsWith("@")&&a.length>=2?`${a[0]}/${a[1]}`:a[0])}for(let r of Object.keys(i))s.has(r)||t.push({severity:"medium",category:"unused-npm-dependency",file:"package.json",lineStart:1,lineEnd:1,title:`Unused dependency: ${r}`,reason:`Package "${r}" is in dependencies but no import was found.`,files:["package.json"],suggestedFix:{strategy:"Remove unused dependency from package.json.",steps:["Verify the package is not loaded dynamically or via CLI scripts.","Check if it is a peer dependency required at runtime.","Run `npm uninstall` or remove from package.json."]},impact:"Reduces install size and attack surface.",tags:["dependency","hygiene","bundle-size"]});for(let r of Object.keys(n))s.has(r)||t.push({severity:"low",category:"unused-npm-dependency",file:"package.json",lineStart:1,lineEnd:1,title:`Unused devDependency: ${r}`,reason:`Package "${r}" is in devDependencies but no import was found.`,files:["package.json"],suggestedFix:{strategy:"Remove unused devDependency from package.json.",steps:["Verify the package is not used by build scripts, config files, or CLI tools.","Run `npm uninstall` or remove from package.json."]},impact:"Reduces install size and dependency maintenance burden.",tags:["dependency","hygiene","dev-tooling"]});return t}function li(e){let i=[];for(let n of e.files){if(x(n))continue;let t=n.match(/^packages\/([^/]+)\//);if(!t)continue;let s=t[1];for(let r of e.outgoing.get(n)||new Set){let o=r.match(/^packages\/([^/]+)\//);if(!o||o[1]===s)continue;if(!/^packages\/[^/]+\/(src\/)?index\.[mc]?[jt]sx?$/.test(r)){let l=r.includes("/internal/")||r.includes("/private/"),c=we(e,n,r);i.push({severity:l?"high":"medium",category:"package-boundary-violation",file:n,lineStart:c.lineStart,lineEnd:c.lineEnd,title:"Cross-package import bypasses public API",reason:`"${n}" imports "${r}" directly instead of through the package public entry.`,files:[n,r],suggestedFix:{strategy:"Import through the package public API (index file).",steps:["Re-export the needed symbol from the target package index.","Update the import to use the package name or index path.","If the symbol is internal, reconsider the dependency."]},impact:"Enforces clean package boundaries and prevents coupling to internals.",tags:["boundary","coupling","encapsulation"]})}}}return i}var _r=N(()=>{"use strict";he();G()});import*as ie from"typescript";function ci(e){let i=[];for(let n of e){let t=n.locations[0],s=`Same ${n.kind} body shape appears in ${n.occurrences} places (${n.filesCount} file${n.filesCount>1?"s":""}).`,r=n.occurrences>=6?"high":n.occurrences>=3?"medium":"low";if(!W(i))break;i.push({...t,severity:r,category:"duplicate-function-body",title:`Deduplicate function body: ${n.signature}`,reason:s,files:n.locations.map(o=>`${o.file}:${o.lineStart}-${o.lineEnd}`),suggestedFix:{strategy:"Create a shared helper function once and replace duplicate call sites.",steps:["Extract one function to a dedicated utility module.","Keep behavior unchanged by passing function-specific differences as params.","Replace duplicated blocks with calls to the shared helper.","Add/extend tests around each entry point that previously used duplicates."]},impact:"Lower maintenance cost and reduce regression risk when behavior changes.",tags:["duplication","maintainability","dryness"],lspHints:[{tool:"lspGotoDefinition",symbolName:n.signature,lineHint:t.lineStart,file:t.file,expectedResult:"navigate to one instance to compare implementations side-by-side"}]})}return i}function di(e,i){let n=[];for(let t of e){if(t.occurrences<i)continue;let s=t.locations[0],r=`${t.kind} structure appears ${t.occurrences} times across ${t.filesCount} file(s).`,o=t.occurrences>=10?"high":"medium";if(!W(n))break;n.push({...s,severity:o,category:"duplicate-flow-structure",title:`Extract repeated flow structure: ${t.kind}`,reason:r,files:t.locations.map(a=>`${a.file}:${a.lineStart}-${a.lineEnd}`),suggestedFix:{strategy:"Extract a reusable flow helper around the repeated structure.",steps:["Create one clear helper that accepts varying inputs as parameters.","Call helper from each repeated site.","Keep variable names aligned and add local adapter logic where needed.","Document expected invariants for the shared flow."]},impact:"Reduces duplicate control branches and normalizes edge-case handling.",tags:["duplication","control-flow","dryness"]})}return n}function ui(e,i){let n=[];for(let t of e)for(let s of t.functions){let r=[];if(s.complexity>=i&&r.push(`Cyclomatic-like complexity is high (>=${i}).`),s.maxBranchDepth>=7&&r.push("Branch depth is very deep and hard to reason about."),s.maxLoopDepth>=4&&r.push("Nested loops are high and likely expensive."),s.statementCount>=24&&r.push("Function body is large and may be doing multiple responsibilities."),r.length===0)continue;let o=s.complexity>=i||s.maxBranchDepth>=7||s.maxLoopDepth>=4;n.push({...s,severity:o?"high":"medium",category:"function-optimization",title:`Potential function refactor: ${s.name}`,reason:r.join(" "),files:[`${s.file}:${s.lineStart}-${s.lineEnd}`],suggestedFix:{strategy:"Refactor for readability and testability.",steps:["Split into smaller subroutines with single responsibilities.","Convert deeply nested branches into guard clauses when safe.","Replace loops with intent-specific helpers if one loop owns most lines.","Add unit coverage for each extracted piece before deleting old logic."]},impact:"Cleaner flow, easier review and safer refactors.",tags:["complexity","readability","refactor"],lspHints:[{tool:"lspCallHierarchy",symbolName:s.name,lineHint:s.lineStart,file:s.file,expectedResult:`inspect callers and callees to plan safe decomposition of ${s.name}`}]})}return n}function fi(e){let i=0,n=(t,s)=>{let r=0,o=!1;switch(t.kind){case ie.SyntaxKind.IfStatement:case ie.SyntaxKind.ForStatement:case ie.SyntaxKind.ForInStatement:case ie.SyntaxKind.ForOfStatement:case ie.SyntaxKind.WhileStatement:case ie.SyntaxKind.DoStatement:case ie.SyntaxKind.CatchClause:case ie.SyntaxKind.ConditionalExpression:case ie.SyntaxKind.SwitchStatement:r=1,o=!0;break;default:break}if(t.kind===ie.SyntaxKind.BinaryExpression&&(t.operatorToken.kind===ie.SyntaxKind.AmpersandAmpersandToken||t.operatorToken.kind===ie.SyntaxKind.BarBarToken||t.operatorToken.kind===ie.SyntaxKind.QuestionQuestionToken)&&(r=1),t.kind===ie.SyntaxKind.IfStatement&&t.parent&&ie.isIfStatement(t.parent)&&t.parent.elseStatement===t&&(r=1,o=!1),o){i+=r+s,ie.forEachChild(t,a=>n(a,s+1));return}i+=r,ie.forEachChild(t,a=>n(a,s))};return n(e,0),i}function pi(e,i=15){let n=[];for(let t of e)if(!x(t.file))for(let s of t.functions)s.cognitiveComplexity>i&&n.push({severity:s.cognitiveComplexity>25?"high":"medium",category:"cognitive-complexity",file:t.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`High cognitive complexity: ${s.name} (${s.cognitiveComplexity})`,reason:`Function cognitive complexity is ${s.cognitiveComplexity} (threshold: ${i}). Nested branches compound reading difficulty.`,files:[`${t.file}:${s.lineStart}-${s.lineEnd}`],suggestedFix:{strategy:"Reduce nesting and simplify control flow.",steps:["Convert nested branches into early returns / guard clauses.","Extract deeply nested blocks into named helper functions.","Replace complex boolean chains with named predicates."]},impact:"Lower cognitive complexity directly correlates with fewer bugs and faster code reviews.",tags:["complexity","readability","nesting"],lspHints:[{tool:"lspCallHierarchy",symbolName:s.name,lineHint:s.lineStart,file:t.file,expectedResult:`understand call graph before simplifying ${s.name}`}]});return n}function gi(e,i=5){let n=[];for(let t of e)if(!x(t.file))for(let s of t.functions)s.params==null||s.params<=i||n.push({severity:s.params>7?"high":"medium",category:"excessive-parameters",file:t.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Excessive parameters: ${s.name} (${s.params} params)`,reason:`Function has ${s.params} parameters (threshold: ${i}). High parameter counts make call sites hard to read and signal the function may be doing too much.`,files:[`${t.file}:${s.lineStart}-${s.lineEnd}`],suggestedFix:{strategy:"Introduce a parameter object or split the function.",steps:["Group related parameters into an options/config object.","Use destructuring at the function signature for clarity.","Consider splitting into smaller, focused functions if params serve different concerns."]},impact:"Improves call-site readability and makes the API easier to evolve.",tags:["api-design","readability","refactor"]});return n}function mi(e){let i=[];for(let n of e)if(!x(n.file)&&!(!n.emptyCatches||n.emptyCatches.length===0))for(let t of n.emptyCatches)i.push({severity:"medium",category:"empty-catch",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Empty catch block silently swallows errors",reason:`Catch block at line ${t.lineStart} has no statements \u2014 errors are silently ignored.`,files:[`${n.file}:${t.lineStart}-${t.lineEnd}`],suggestedFix:{strategy:"Log, re-throw, or handle the error explicitly.",steps:["Add error logging (console.error or a logger) at minimum.","Re-throw if the caller should handle the error.","Add a comment explaining why swallowing is intentional, if it truly is."]},impact:"Prevents silent failures that are extremely hard to debug in production.",tags:["error-handling","reliability","silent-failure"]});return i}function hi(e){let i=[];for(let n of e)if(!x(n.file)&&!(!n.switchesWithoutDefault||n.switchesWithoutDefault.length===0))for(let t of n.switchesWithoutDefault)i.push({severity:"low",category:"switch-no-default",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Switch statement missing default case",reason:`Switch at line ${t.lineStart} has no default clause \u2014 unexpected values fall through silently.`,files:[`${n.file}:${t.lineStart}-${t.lineEnd}`],suggestedFix:{strategy:"Add a default case with error handling or exhaustive check.",steps:["Add a default clause that throws an unreachable error for exhaustiveness.","Or log a warning for unexpected values.","In TypeScript, use `never` type assertion for compile-time exhaustive checks."]},impact:"Catches unexpected values early and prevents silent logic bugs.",tags:["control-flow","exhaustiveness","safety"]});return i}function yi(e,i=5){let n=[];for(let t of e)if(!x(t.file)&&!(t.anyCount==null||t.anyCount<=i)){if(!W(n))break;n.push({severity:t.anyCount>10?"high":"medium",category:"unsafe-any",file:t.file,lineStart:1,lineEnd:1,title:`Excessive \`any\` usage: ${t.file} (${t.anyCount} occurrences)`,reason:`File uses \`any\` type ${t.anyCount} times (threshold: ${i}). Each \`any\` disables type checking and allows silent runtime errors.`,files:[t.file],suggestedFix:{strategy:"Replace `any` with specific types, `unknown`, or generics.",steps:["Replace `any` with `unknown` and add type guards where needed.","Use generics for functions that operate on multiple types.","Define proper interfaces for complex data shapes.","Use `as const` assertions instead of `as any` where possible."]},impact:"Restores TypeScript safety and catches bugs at compile time instead of runtime.",tags:["type-safety","reliability","typescript"]})}return n}function Si(e,i=5e5,n=2){let t=[];for(let s of e)if(!x(s.file))for(let r of s.functions){if(!r.halstead)continue;let{effort:o,estimatedBugs:a,volume:l}=r.halstead;if(o<=i&&a<=n)continue;let c=[];o>i&&c.push(`effort=${Math.round(o)} (threshold: ${i})`),a>n&&c.push(`estimatedBugs=${a.toFixed(2)} (threshold: ${n})`),t.push({severity:o>i*2||a>5?"high":"medium",category:"halstead-effort",file:s.file,lineStart:r.lineStart,lineEnd:r.lineEnd,title:`High Halstead complexity: ${r.name}`,reason:`Function has high implementation complexity: ${c.join("; ")}. Volume=${Math.round(l)}.`,files:[`${s.file}:${r.lineStart}-${r.lineEnd}`],suggestedFix:{strategy:"Reduce operator/operand count by extracting helpers and simplifying expressions.",steps:["Extract complex sub-expressions into named intermediate variables.","Split into smaller functions with fewer unique operators/operands.","Replace imperative loops with declarative array methods where clearer."]},impact:"Lower Halstead effort correlates with fewer bugs and faster comprehension.",tags:["complexity","maintainability","effort"]})}return t}function bi(e,i=20){let n=[];for(let t of e)if(!x(t.file))for(let s of t.functions)s.maintainabilityIndex==null||s.maintainabilityIndex>=i||n.push({severity:s.maintainabilityIndex<10?"critical":"high",category:"low-maintainability",file:t.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Low maintainability: ${s.name} (MI=${s.maintainabilityIndex.toFixed(1)})`,reason:`Maintainability Index is ${s.maintainabilityIndex.toFixed(1)} (threshold: ${i}, scale 0-100). Combines Halstead volume, cyclomatic complexity, and lines of code.`,files:[`${t.file}:${s.lineStart}-${s.lineEnd}`],suggestedFix:{strategy:"Reduce complexity, shorten the function, and simplify expressions.",steps:["Split into smaller functions to reduce LOC and cyclomatic complexity.","Extract complex expressions to reduce Halstead volume.","Convert nested logic to early returns and guard clauses.","Consider if parts of the function belong in separate modules."]},impact:"Higher MI directly predicts lower maintenance cost and defect rate.",tags:["maintainability","complexity","technical-debt"]});return n}function xi(e){let i=[];for(let n of e){if(x(n.file))continue;let t=n.typeAssertionEscapes;if(!t)continue;let s=t.asAny.length+t.doubleAssertion.length+t.nonNull.length;if(s===0)continue;let r=[];t.asAny.length>0&&r.push(`${t.asAny.length} \`as any\``),t.doubleAssertion.length>0&&r.push(`${t.doubleAssertion.length} double-assertion`),t.nonNull.length>0&&r.push(`${t.nonNull.length} non-null \`!\``);let o=[...t.asAny,...t.doubleAssertion,...t.nonNull].map(l=>l.lineStart),a=Math.min(...o);if(!W(i))break;i.push({severity:t.asAny.length+t.doubleAssertion.length>3?"high":"medium",category:"type-assertion-escape",file:n.file,lineStart:a,lineEnd:a,title:`Type-safety escapes in ${n.file} (${s})`,reason:`Found ${r.join(", ")}. Each assertion bypasses TypeScript's type checker.`,files:[n.file],suggestedFix:{strategy:"Replace type assertions with proper type guards or narrow types.",steps:["Replace `as any` with `unknown` and add runtime type checks.","Replace `as unknown as T` with proper generic constraints.","Replace `!` assertions with explicit null checks."]},impact:"Type assertions silence the compiler \u2014 runtime errors go undetected.",tags:["type-safety","assertions","code-quality"]})}return i}function Ei(e){let i=[];for(let n of e)if(!x(n.file)&&n.unprotectedAsync)for(let t of n.unprotectedAsync){let s=t.awaitCount>=4?"high":t.awaitCount>=2?"medium":"low";i.push({severity:s,category:"missing-error-boundary",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Missing error boundary: ${t.name} (${t.awaitCount} awaits, no try-catch)`,reason:`Async function "${t.name}" has ${t.awaitCount} await(s) but no try-catch. Rejected promises propagate as unhandled rejections.`,files:[n.file],suggestedFix:{strategy:"Wrap await calls in try-catch or add a .catch() handler.",steps:["Add a try-catch block around the await expressions.","Handle errors appropriately (log, return default, re-throw with context).","If the caller handles errors, document it with a comment."]},impact:"Unhandled promise rejections crash Node.js processes and cause silent failures in browsers.",tags:["error-handling","async","reliability"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.name,lineHint:t.lineStart,file:n.file,expectedResult:"check if callers wrap this in try-catch or .catch() \u2014 if so, the boundary may exist upstream"}]})}return i}function wi(e){let i=[];for(let n of e)if(!x(n.file)&&n.asyncWithoutAwait)for(let t of n.asyncWithoutAwait)i.push({severity:"medium",category:"promise-misuse",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Unnecessary async: ${t.name} has no await`,reason:`Function "${t.name}" is declared \`async\` but never uses \`await\`. The \`async\` keyword adds unnecessary Promise wrapping.`,files:[n.file],suggestedFix:{strategy:"Remove the async keyword or add the missing await.",steps:["If the function does not need to be async, remove the `async` keyword.","If an `await` was forgotten, add it to the appropriate call.","Verify callers handle the return value correctly after the change."]},impact:"Unnecessary async wrapping adds microtask overhead and misleads readers.",tags:["async","performance","clarity"]});return i}function vi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.awaitInLoopLocations||[])i.push({severity:"high",category:"await-in-loop",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"await inside loop \u2014 sequential async execution",reason:"Each await runs serially. For N iterations this takes N * latency instead of max(latency). Use Promise.all() or Promise.allSettled() for parallel execution.",files:[n.file],suggestedFix:{strategy:"Collect promises and await them in parallel with Promise.all().",steps:["Collect all async operations into an array of promises.","Use await Promise.all(promises) or Promise.allSettled(promises).","If order matters or rate limiting is needed, use a batching utility."]},impact:"Sequential awaits multiply latency by N iterations \u2014 parallelizing can reduce total time to max(single-latency).",tags:["performance","async","n-plus-one"],lspHints:[{tool:"lspGotoDefinition",symbolName:"await",lineHint:t.lineStart,file:n.file,expectedResult:"navigate to the awaited call to check if parallelization is safe"}]});return i}function Fi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.syncIoCalls||[])i.push({severity:"medium",category:"sync-io",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Synchronous I/O: ${t.name}`,reason:`${t.name} blocks the event loop. In server or UI code this degrades responsiveness for all concurrent operations.`,files:[n.file],suggestedFix:{strategy:"Replace with async equivalent.",steps:[`Replace ${t.name} with its async counterpart (e.g. fs.promises.readFile).`,"Sync I/O is acceptable in CLI scripts, build tools, or one-time init code."]},impact:"Synchronous I/O blocks the event loop, stalling all concurrent requests until the operation completes.",tags:["performance","blocking","io"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.name,lineHint:t.lineStart,file:n.file,expectedResult:"find callers to assess if this sync I/O is in a hot path"}]});return i}function ki(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.timerCalls||[])t.kind==="setInterval"&&!t.hasCleanup&&i.push({severity:"medium",category:"uncleared-timer",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"setInterval without clearInterval in scope",reason:"setInterval without cleanup runs indefinitely, causing memory leaks and unexpected behavior after component unmount or scope exit.",files:[n.file],suggestedFix:{strategy:"Store the timer ID and call clearInterval in cleanup.",steps:["Assign the return value: const id = setInterval(...).","Call clearInterval(id) in cleanup (useEffect return, componentWillUnmount, or scope exit)."]},impact:"Uncleared intervals run indefinitely, leaking memory and CPU cycles after their scope is no longer relevant.",tags:["performance","memory-leak","timer"]});return i}function Ci(e){let i=[];for(let n of e){if(x(n.file))continue;let t=n.listenerRegistrations||[],s=n.listenerRemovals||[];t.length>0&&s.length===0&&i.push({severity:"medium",category:"listener-leak-risk",file:n.file,lineStart:t[0].lineStart,lineEnd:t[t.length-1].lineEnd,title:`${t.length} event listener(s) added without any removal`,reason:"addEventListener/on without corresponding removeEventListener/off risks memory leaks if the target outlives the subscriber.",files:[n.file],suggestedFix:{strategy:"Add corresponding listener removal in cleanup.",steps:["Store the handler reference in a variable.","Call removeEventListener/off in cleanup (unmount, dispose, close).","Or use AbortController signal for automatic cleanup."]},impact:"Listener references prevent garbage collection of the subscriber, causing memory growth proportional to event-target lifetime.",tags:["performance","memory-leak","events"]})}return i}function Ti(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.functions)t.loops>=2&&t.calls>=5&&t.maxLoopDepth>=2&&i.push({severity:"low",category:"unbounded-collection",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Potential unbounded collection growth in ${t.name}`,reason:`Function "${t.name}" has ${t.loops} loops nested ${t.maxLoopDepth} levels deep with ${t.calls} calls \u2014 structural signal for unbounded growth. Validate with tools: read the function body and check for collection mutations (.push, .add, .set) inside loops.`,files:[n.file],suggestedFix:{strategy:"Add size limits, pagination, or streaming.",steps:["Add a maximum size check before adding to collections.","Use pagination or streaming for large datasets.","Consider using generators for lazy evaluation."]},impact:"Unbounded collection growth inside nested loops can cause out-of-memory crashes under large input.",tags:["performance","memory","collection"]});return i}function $i(e,i=.85){let n=[],t=[];for(let r of e.values())for(let o of r)x(o.file)||t.push(o);let s=new Map;for(let r of t){let o=`${r.kind}|${Math.round(r.statementCount/3)}`;s.has(o)||s.set(o,[]),s.get(o).push(r)}for(let[,r]of s)if(!(r.length<2||r.length>50))for(let o=0;o<r.length;o++)for(let a=o+1;a<r.length;a++){let l=r[o],c=r[a];if(l.hash===c.hash||l.file===c.file&&l.lineStart===c.lineStart||Math.min(l.statementCount,c.statementCount)/Math.max(l.statementCount,c.statementCount)<.8)continue;let d=gl(l,c);d>=i&&n.push({severity:d>=.95?"high":"medium",category:"similar-function-body",file:l.file,lineStart:l.lineStart,lineEnd:l.lineEnd,title:`Similar function: ${l.name} (${(d*100).toFixed(0)}% similar to ${c.name} in ${c.file})`,reason:`"${l.name}" and "${c.name}" have ${(d*100).toFixed(0)}% structural similarity. Near-duplicates diverge over time and should be consolidated.`,files:[l.file,c.file],suggestedFix:{strategy:"Extract shared logic into a parameterized helper.",steps:[`Compare ${l.file}:${l.lineStart} with ${c.file}:${c.lineStart}.`,"Identify the varying parts and extract them as parameters.","Create a shared function and call it from both locations."]},impact:"Near-clone functions diverge over time, causing inconsistent behavior and multiplied maintenance cost.",tags:["duplication","maintainability","near-clone"]})}return n}function gl(e,i){let n=[[e.metrics.complexity,i.metrics.complexity],[e.metrics.maxBranchDepth,i.metrics.maxBranchDepth],[e.metrics.maxLoopDepth,i.metrics.maxLoopDepth],[e.metrics.returns,i.metrics.returns],[e.metrics.awaits,i.metrics.awaits],[e.metrics.calls,i.metrics.calls],[e.metrics.loops,i.metrics.loops],[e.statementCount,i.statementCount]],t=0;for(let[s,r]of n){let o=Math.max(s,r,1);t+=1-Math.abs(s-r)/o}return t/n.length}function Di(e){let i=[];for(let n of e){if(!n.messageChains||n.messageChains.length===0)continue;let t=new Map;for(let s of n.messageChains){let r=t.get(s.lineStart);(!r||s.depth>r.depth)&&t.set(s.lineStart,s)}for(let s of t.values()){let r=s.depth>=6?"high":"medium";i.push({severity:r,category:"message-chain",file:n.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Message chain of depth ${s.depth}: ${s.chain.slice(0,50)}`,reason:`A property-access chain of ${s.depth} steps violates the Law of Demeter \u2014 the caller navigates through ${s.depth-1} intermediate objects to reach its target. Deep chains tightly couple the caller to internal object structure, making refactoring brittle.`,files:[n.file],suggestedFix:{strategy:"Apply the Law of Demeter \u2014 talk only to immediate friends.",steps:["Identify the root object and the final method/property being used.","Add a delegating method to the root object (Tell, Don't Ask).","Replace the chain with a single call on the immediate object.","If the chain crosses module boundaries, consider whether the intermediate objects should be passed directly."]},impact:"Deep property chains tightly couple code to internal object structure. When intermediate objects change, every chain accessing them must be updated.",tags:["coupling","law-of-demeter","maintainability"],lspHints:[{tool:"lspGotoDefinition",symbolName:s.chain.split(".")[0],lineHint:s.lineStart,file:n.file,expectedResult:"find the type of the root object to understand what intermediate types the chain traverses"}]})}}return i}function Ri(e,i){let n=[];for(let t of e)if(!x(t.file))for(let s of t.functions){let r=Math.max(s.maxBranchDepth,s.maxLoopDepth);if(r<i)continue;if(!W(n))return n;let o=r>=i+3?"high":r>=i+1?"medium":"low";n.push({severity:o,category:"deep-nesting",file:t.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Deep nesting ${r} levels in ${s.name||"<anon>"}`,reason:`Function has ${r}-level nesting (branch=${s.maxBranchDepth}, loop=${s.maxLoopDepth}), exceeding the ${i}-level threshold. Each nesting level multiplies the reader's cognitive load and increases the likelihood of logic errors.`,files:[t.file],suggestedFix:{strategy:"Flatten nesting with guard clauses, early returns, or extraction.",steps:["Convert nested if-blocks to guard clauses with early returns.","Extract deeply nested logic into named helper functions.","Replace nested loops with array methods (map/filter/reduce)."]},impact:"Deeply nested code is hard to read, test, and modify. Each nesting level compounds the number of control-flow paths.",tags:["nesting","readability","complexity"]})}return n}function Ai(e,i){let n=[];for(let t of e)if(!x(t.file))for(let s of t.functions){if(s.returns<i)continue;if(!W(n))return n;let r=s.returns>=i+4?"high":s.returns>=i+2?"medium":"low";n.push({severity:r,category:"multiple-return-paths",file:t.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`${s.returns} return paths in ${s.name||"<anon>"}`,reason:`Function has ${s.returns} return/throw points \u2014 the reader must track every exit path to understand the function's behavior. This exceeds the ${i} threshold.`,files:[t.file],suggestedFix:{strategy:"Consolidate return points to reduce exit-path tracking.",steps:["Replace scattered returns with a single result variable assigned conditionally.","Use early guard clauses for error cases only.","Consider splitting into smaller functions with clear single-responsibility."]},impact:"Many return paths make it harder to reason about what a function returns and to add post-processing.",tags:["returns","readability","flow"]})}return n}function Mi(e){let i=[];for(let n of e)if(!x(n.file)&&!(!n.catchRethrows||n.catchRethrows.length===0))for(let t of n.catchRethrows){if(!W(i))return i;i.push({severity:"low",category:"catch-rethrow",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Catch-rethrow without transformation",reason:"A catch block that only re-throws the caught error is a no-op \u2014 it adds indentation and obscures the stack trace without adding value.",files:[n.file],suggestedFix:{strategy:"Remove the try-catch or add meaningful error handling.",steps:["If no transformation is needed, remove the try-catch entirely.","If logging is intended, add a log statement before re-throwing.","If wrapping, throw a new error with the original as cause."]},impact:"Pointless catch blocks add noise and can accidentally swallow stack-trace context.",tags:["error-handling","noise","cleanup"]})}return i}function Pi(e,i){let n=[],t=new Map;for(let s of e)if(!x(s.file)&&s.magicStrings)for(let r of s.magicStrings){let o=t.get(r.value)||[];o.push({file:r.file,lineStart:r.lineStart,lineEnd:r.lineEnd}),t.set(r.value,o)}for(let[s,r]of t){if(r.length<i)continue;if(!W(n))return n;let o=[...new Set(r.map(l=>l.file))],a=r.length>=8?"high":r.length>=5?"medium":"low";n.push({severity:a,category:"magic-string",file:r[0].file,lineStart:r[0].lineStart,lineEnd:r[0].lineEnd,title:`Magic string "${s.length>30?s.slice(0,27)+"...":s}" appears ${r.length} times`,reason:`The string literal "${s}" is used in ${r.length} comparisons across ${o.length} file(s). If the value changes, every occurrence must be updated \u2014 a classic source of silent bugs.`,files:o,suggestedFix:{strategy:"Extract to a named constant or enum.",steps:[`Create a const (e.g. const ${s.toUpperCase().replace(/[^A-Z0-9]/g,"_")} = '${s}').`,"Replace all usages with the constant reference.","Consider an enum if there are multiple related string values."]},impact:"Magic strings scatter domain knowledge across the codebase and are invisible to refactoring tools.",tags:["magic-value","maintainability","duplication"]})}return n}function Ii(e,i){let n=[];for(let t of e)if(!x(t.file)&&t.booleanParamClusters){for(let s of t.booleanParamClusters)if(!(s.booleanCount<i)){if(!W(n))return n;n.push({severity:"medium",category:"boolean-parameter-cluster",file:t.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`${s.booleanCount} boolean params in ${s.name||"<anon>"}`,reason:`Function has ${s.booleanCount} boolean parameters out of ${s.totalParams} total. Boolean flags are opaque at call sites (e.g. doThing(true, false, true)) and each flag doubles the function's behavior space.`,files:[t.file],suggestedFix:{strategy:"Replace boolean clusters with an options object or separate functions.",steps:["Create an options/config object type with named fields.","Replace boolean parameters with the options object.","Consider splitting into distinct functions for each behavior variant."]},impact:"Boolean parameter clusters make call sites unreadable and the function hard to test \u2014 2^N behavior combinations.",tags:["api-design","readability","parameters"]})}}return n}function Ni(e){let i=[];for(let n of e)if(!x(n.file)&&n.promiseAllUnhandled)for(let t of n.promiseAllUnhandled){if(!W(i))return i;i.push({severity:"medium",category:"promise-all-unhandled",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`${t.kind} without error handling`,reason:`${t.kind} is called without a surrounding try-catch or .catch() chain. If any of the composed promises reject, the rejection will propagate unhandled.`,files:[n.file],suggestedFix:{strategy:"Wrap in try-catch or add .catch() to the promise chain.",steps:["Add a try-catch around the await expression.","Or chain a .catch() handler onto the Promise combinator.","Consider Promise.allSettled if partial failure is acceptable."]},impact:"Unhandled rejections from promise combinators crash Node.js processes and cause silent failures in browsers.",tags:["error-handling","async","reliability"]})}return i}function Li(e,i){let n=[];if(!i)return n;for(let t of e){if(x(t.file))continue;let s=t.dependencyProfile;if(!s)continue;let r=t.functions.reduce((c,u)=>c+u.statementCount,0)+t.flows.length;if(r<20)continue;let o=s.declaredExports?.length||0;if(o===0)continue;let a=o/r;if(a<.5)continue;if(!W(n))return n;let l=a>=.8?"high":a>=.6?"medium":"low";n.push({severity:l,category:"export-surface-density",file:t.file,lineStart:1,lineEnd:1,title:`${Math.round(a*100)}% export density (${o} exports / ~${r} statements)`,reason:`This module exports ${o} symbols from ~${r} total statements \u2014 a ${Math.round(a*100)}% export surface. High export density means nearly everything is public API, increasing coupling and reducing the ability to refactor internals.`,files:[t.file],suggestedFix:{strategy:"Reduce the public API by making non-essential symbols internal.",steps:["Audit each export \u2014 does it need to be consumed externally?","Convert unnecessary exports to module-private functions.","Consider splitting into a public facade and private implementation module."]},impact:"High export density couples consumers to internal implementation, making any change a potential breaking change.",tags:["encapsulation","api-surface","coupling"]})}return n}function Oi(e,i,n){let t=[];for(let s of e){if(x(s.file))continue;let r=0,o=[],a=s.functions.length>0?s.functions.reduce((f,p)=>f+p.complexity,0)/s.functions.length:0;a>15&&(r+=2,o.push(`high avg complexity (${a.toFixed(1)})`));let l=s.functions.reduce((f,p)=>Math.max(f,p.cognitiveComplexity),0);l>20&&(r+=2,o.push(`high cognitive complexity (${l})`));let c=s.functions.filter(f=>f.maintainabilityIndex!==void 0&&f.maintainabilityIndex<20).length;c>0&&(r+=c,o.push(`${c} function(s) with low MI`)),s.emptyCatches&&s.emptyCatches.length>0&&(r+=1,o.push(`${s.emptyCatches.length} empty catches`)),s.promiseAllUnhandled&&s.promiseAllUnhandled.length>0&&(r+=1,o.push(`${s.promiseAllUnhandled.length} unhandled promise combinators`));let u=s.dependencyProfile;if(u&&u.declaredExports){let f=u.declaredExports.length;f>15&&(r+=1,o.push(`${f} exports`))}if(r<4)continue;if(!W(t))return t;let d=r>=8?"critical":r>=6?"high":"medium";t.push({severity:d,category:"change-risk",file:s.file,lineStart:1,lineEnd:1,title:`Change-risk score ${r}: ${o.slice(0,3).join(", ")}`,reason:`This file has a composite change-risk score of ${r}, derived from: ${o.join("; ")}. Files with multiple overlapping quality signals are the most likely to introduce regressions when modified.`,files:[s.file],suggestedFix:{strategy:"Reduce risk incrementally \u2014 address the highest-impact signal first.",steps:["Check test coverage for this file \u2014 add tests if missing.","Address the highest-severity individual finding first.","Consider splitting the module to isolate high-risk logic."]},impact:"Files with multiple quality issues compound risk \u2014 each change is likely to trigger regressions in hard-to-predict ways.",tags:["risk","composite","priority"]})}return t}var Hr=N(()=>{"use strict";he();G()});function ji(e){let i=[];for(let n of e){if(x(n.file))continue;let t=(n.suspiciousStrings||[]).filter(s=>s.kind==="hardcoded-secret"&&s.context!=="regex-definition"&&s.context!=="error-message");if(t.length!==0)for(let s of t)i.push(ue({severity:"high",category:"hardcoded-secret",file:n.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Potential hardcoded secret${s.snippet?`: ${s.snippet.slice(0,20)}\u2026`:""}`,reason:"String literal matches a secret pattern (password, API key, token, high-entropy string). Secrets in source code risk credential leaks. Validate: use localSearchCode to find the variable, then lspFindReferences to check if it is used in auth or network calls.",files:[n.file],suggestedFix:{strategy:"Move secret to environment variable or secrets manager.",steps:["Replace the hardcoded value with process.env.YOUR_SECRET.","Add the variable to your .env file (excluded from git).","Verify the secret is not committed in git history."]},impact:"Credential leak in source code exposes API access, database credentials, or authentication tokens to anyone with repo access.",tags:["security","secrets"],lspHints:[{tool:"lspFindReferences",symbolName:s.snippet?.split(/[=:]/)[0]?.trim()||"secret",lineHint:s.lineStart,file:n.file,expectedResult:"find all usages of this secret value \u2014 if used only in tests or as a regex pattern, it is a false positive"}]},"security.hardcoded-secret","high",{source:s.snippet||"",sink:"runtime usage",context:s.context||"literal",sanitizerStatus:"missing",propagationSteps:[`${n.file}:${s.lineStart}`]}))}return i}function _i(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.evalUsages||[])i.push(ue({severity:"critical",category:"eval-usage",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Dynamic code execution (eval/Function)",reason:"eval(), new Function(), or string-based setTimeout/setInterval allows arbitrary code execution. This is a code injection vector.",files:[n.file],suggestedFix:{strategy:"Replace dynamic code execution with safe alternatives.",steps:["For JSON parsing: use JSON.parse() instead of eval().","For dynamic dispatch: use a lookup table or switch statement.","For setTimeout: pass a function reference, not a string."]},impact:"Arbitrary code execution enables full application takeover \u2014 the most severe class of injection vulnerability.",tags:["security","injection","critical"],lspHints:[{tool:"lspCallHierarchy",symbolName:"eval",lineHint:t.lineStart,file:n.file,expectedResult:"trace callers to find how user input reaches the eval site"}]},"security.eval-usage","high",{sink:`eval at ${n.file}:${t.lineStart}-${t.lineEnd}`,sanitizerStatus:"missing"}));return i}function Hi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.unsafeHtmlAssignments||[])i.push(ue({severity:"high",category:"unsafe-html",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Unsafe HTML manipulation",reason:"innerHTML, outerHTML, dangerouslySetInnerHTML, or document.write can execute unsanitized user input as HTML/script. XSS vector.",files:[n.file],suggestedFix:{strategy:"Use safe DOM APIs or sanitize input before insertion.",steps:["Replace innerHTML with textContent for plain text.","Use a sanitizer library (e.g. DOMPurify) if HTML is required.","In React, avoid dangerouslySetInnerHTML \u2014 use JSX instead."]},impact:"Unsanitized HTML insertion enables cross-site scripting (XSS) \u2014 attackers can steal sessions, credentials, or execute actions as the victim.",tags:["security","xss"]},"security.unsafe-html","high",{sink:"DOM assignment",sanitizerStatus:"missing",propagationSteps:["html assignment"]}));return i}function Bi(e){let i=[];for(let n of e){if(x(n.file))continue;let t=(n.suspiciousStrings||[]).filter(s=>s.kind==="sql-injection");for(let s of t)i.push(ue({severity:"high",category:"sql-injection-risk",file:n.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:"SQL query built with template literal interpolation",reason:"Template literals with SQL keywords and interpolated expressions risk SQL injection if user input flows into the query.",files:[n.file],suggestedFix:{strategy:"Use parameterized queries or a query builder.",steps:["Replace template literal with parameterized query (e.g. db.query(sql, [param])).","Use an ORM or query builder that handles escaping.","If raw SQL is necessary, validate and sanitize all interpolated values."]},impact:"SQL injection can expose, modify, or destroy database contents and potentially escalate to full server compromise.",tags:["security","injection","sql"]},"security.sql-injection-risk","high",{sink:"sql template literal",sanitizerStatus:"missing",propagationSteps:[`${n.file}:${s.lineStart}-${s.lineEnd}`]}))}return i}function zi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.regexLiterals||[])ml.test(t.pattern)&&i.push(ue({severity:"medium",category:"unsafe-regex",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Regex with catastrophic backtracking risk",reason:`Pattern "${t.pattern.slice(0,40)}" has nested quantifiers that can cause exponential backtracking (ReDoS).`,files:[n.file],suggestedFix:{strategy:"Simplify the regex or use atomic groups / possessive quantifiers.",steps:["Remove nested quantifiers \u2014 e.g. change (a+)+ to a+.","Use a regex linter (e.g. safe-regex) to validate patterns.","Consider using string methods instead of complex regexes."]},impact:"Catastrophic backtracking causes CPU exhaustion \u2014 a single crafted input string can hang the event loop (ReDoS).",tags:["security","regex","performance"],lspHints:[{tool:"lspFindReferences",symbolName:t.pattern.slice(0,20),lineHint:t.lineStart,file:n.file,expectedResult:"find where this regex is used to assess if user input reaches it"}]},"security.unsafe-regex","medium",{source:t.pattern,sink:"Regex execution",sanitizerStatus:"not-applicable",propagationSteps:[`${n.file}:${t.lineStart}-${t.lineEnd}`]}));return i}function Ki(e){let i=[];for(let n of e)if(!x(n.file)&&!(!n.prototypePollutionSites||n.prototypePollutionSites.length===0))for(let t of n.prototypePollutionSites){let s,r;t.kind==="computed-property-write"?t.guarded?(s="low",r="low"):(s="high",r="medium"):(s="medium",r="medium"),i.push(ue({severity:s,category:"prototype-pollution-risk",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Prototype pollution risk: ${t.kind}${t.guarded?" (guarded)":""}`,reason:`${t.detail}${t.guarded?" \u2014 guards detected (internal iteration or key check), likely false positive. Verify the key variable does not trace to external input.":""}`,files:[n.file],suggestedFix:{strategy:"Guard against __proto__, constructor, and prototype keys before merging.",steps:['Validate keys: reject "__proto__", "constructor", "prototype" before assignment.',"Use Object.create(null) as the target for merges when possible.","Replace custom deep-merge with a hardened library (e.g. lodash.merge with prototype guard).","For Object.assign, ensure the source is sanitized or use structuredClone()."]},impact:"Prototype pollution can override built-in methods, bypass security checks, or achieve remote code execution.",tags:["security","prototype-pollution","injection"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.kind==="computed-property-write"?"bracket-assignment":t.detail.split("(")[0],lineHint:t.lineStart,file:n.file,expectedResult:"trace callers to determine if user-controlled data reaches this site \u2014 if key comes from Object.keys() on internal object, dismiss as false positive"}]},"security.prototype-pollution-risk",r,{source:t.kind,sink:t.detail,guarded:t.guarded,sanitizerStatus:t.guarded?"present":"missing",propagationSteps:[`${n.file}:${t.lineStart}`]}))}return i}function Ui(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.inputSources||[]){if(!t.hasSinkInBody||t.hasValidation)continue;let s=t.sinkKinds.join(", "),r=t.paramConfidence==="low"?"medium":"high";i.push(ue({severity:r,category:"unvalidated-input-sink",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Unvalidated input reaches ${s} sink in ${t.functionName}(${t.sourceParams.join(", ")})`,reason:`Parameter${t.sourceParams.length>1?"s":""} '${t.sourceParams.join("', '")}' (external input) flow${t.sourceParams.length===1?"s":""} into ${s} without validation (no type guard, schema call, or conditional check).`,files:[n.file],suggestedFix:{strategy:"Add input validation before the sink operation.",steps:["Add schema validation (e.g. zod, joi) for input parameters.","Use parameterized APIs instead of template interpolation for SQL/exec.",`Trace data flow: lspCallHierarchy(outgoing) on ${t.functionName}.`]},impact:"Unvalidated external input reaching a dangerous sink (eval, SQL, exec, innerHTML, file write) enables injection attacks.",tags:["security","input-validation","injection"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.functionName,lineHint:t.lineStart,file:n.file,expectedResult:`trace outgoing calls to see where ${t.sourceParams.join(", ")} data flows`},{tool:"lspFindReferences",symbolName:t.sourceParams[0],lineHint:t.lineStart,file:n.file,expectedResult:`check all usages of ${t.sourceParams[0]} parameter within function`}]},"security.unvalidated-input-sink",r==="high"?"high":"medium",{sourceParameters:t.sourceParams,sink:s,sanitizerStatus:t.hasValidation?"present":"missing",propagationSteps:t.callsWithInputArgs.map(o=>`${o.callee}:${o.lineStart}`)}))}return i}function qi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.inputSources||[]){if(t.callsWithInputArgs.length===0||t.hasValidation||t.hasSinkInBody||t.paramConfidence==="low")continue;let s=t.callsWithInputArgs.map(a=>a.callee),r=[...new Set(s)],o=t.paramConfidence==="high"?"medium":"low";i.push(ue({severity:o,category:"input-passthrough-risk",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Input passthrough without validation in ${t.functionName}(${t.sourceParams.join(", ")})`,reason:`Parameter${t.sourceParams.length>1?"s":""} '${t.sourceParams.join("', '")}' (external input) ${t.sourceParams.length===1?"is":"are"} passed to ${r.join(", ")} without validation. Downstream callees may not validate either.`,files:[n.file],suggestedFix:{strategy:"Validate input before passing to downstream functions.",steps:["Add schema validation (e.g. zod, joi) at the entry point.",`Trace downstream: lspCallHierarchy(outgoing) on ${t.functionName} to verify callees validate.`,"Search for validation middleware: localSearchCode for guard/validate/sanitize patterns."]},impact:"Unchecked input passed downstream can reach sinks in callees \u2014 validation gaps compound across the call chain.",tags:["security","input-validation","passthrough"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.functionName,lineHint:t.lineStart,file:n.file,expectedResult:`trace outgoing calls to verify downstream validation of ${t.sourceParams.join(", ")}`},{tool:"lspFindReferences",symbolName:t.sourceParams[0],lineHint:t.lineStart,file:n.file,expectedResult:`find all usages of ${t.sourceParams[0]} to check if validation occurs upstream`}]},"security.input-passthrough-risk",o,{sourceParameters:t.sourceParams,sink:r.join(", "),sanitizerStatus:t.hasValidation?"present":"missing",propagationSteps:t.callsWithInputArgs.map(a=>`${a.callee}:${a.lineStart}`)}))}return i}function Gi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.inputSources||[]){let s=t.sinkKinds.filter(l=>l==="fs-read"||l==="path-resolve");if(s.length===0||t.paramConfidence==="low")continue;let r=t.hasValidation,o=r?"medium":"high",a=s.join(", ");i.push(ue({severity:o,category:"path-traversal-risk",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Path traversal risk: ${t.functionName}(${t.sourceParams.join(", ")}) \u2192 ${a}`,reason:`Parameter${t.sourceParams.length>1?"s":""} '${t.sourceParams.join("', '")}' (external input) flow${t.sourceParams.length===1?"s":""} into ${a} ${r?"with partial validation \u2014 verify path normalization + prefix check + realpath resolution":"without validation. Path traversal (e.g. ../../etc/passwd) can read or write arbitrary files"}.`,files:[n.file],suggestedFix:{strategy:"Add multi-layer path validation before file system operations.",steps:["Normalize the path: path.resolve(basePath, userInput).","Prefix check: resolvedPath.startsWith(basePath + path.sep).","Resolve symlinks: fs.realpathSync() to prevent symlink escape.","Re-validate after symlink resolution."]},impact:"Path traversal enables reading sensitive files (credentials, configs, source code) or writing to arbitrary locations (code injection via file overwrite).",tags:["security","path-traversal","agentic"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.functionName,lineHint:t.lineStart,file:n.file,expectedResult:"trace incoming callers to determine if path parameter comes from user input \u2014 then trace outgoing to the fs/path call"}]},"security.path-traversal-risk",t.paramConfidence==="high"?"high":"medium",{sourceParameters:t.sourceParams,sink:a,sanitizerStatus:r?"partial":"missing",propagationSteps:t.callsWithInputArgs.map(l=>`${l.callee}:${l.lineStart}`)}))}return i}function Wi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.inputSources||[]){if(t.sinkKinds.filter(a=>a==="exec").length===0||t.paramConfidence==="low")continue;let r=t.callsWithInputArgs.filter(a=>/\.exec\b|^exec$|^execSync$|child_process\.exec/.test(a.callee)),o=t.callsWithInputArgs.filter(a=>/\.spawn\b|^spawn$|^spawnSync$|child_process\.spawn/.test(a.callee));if(r.length>0){let a=t.paramConfidence==="high"?"critical":"high";i.push(ue({severity:a,category:"command-injection-risk",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Command injection risk: ${t.functionName}(${t.sourceParams.join(", ")}) \u2192 exec`,reason:`Parameter${t.sourceParams.length>1?"s":""} '${t.sourceParams.join("', '")}' (external input) flow${t.sourceParams.length===1?"s":""} into exec/execSync. exec() runs commands through a shell \u2014 string interpolation enables command injection.`,files:[n.file],suggestedFix:{strategy:"Replace exec with spawn using array arguments (no shell interpretation).",steps:["Replace child_process.exec(cmd) with child_process.spawn(binary, [args]).","Never interpolate user input into command strings.","Use an allowlist for permitted commands if dynamic dispatch is needed.","If shell features are required, validate input against a strict allowlist."]},impact:"Command injection enables arbitrary OS command execution \u2014 full server compromise, data exfiltration, or lateral movement.",tags:["security","command-injection","critical","agentic"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.functionName,lineHint:t.lineStart,file:n.file,expectedResult:"trace incoming callers to verify if user input reaches the exec call \u2014 check for allowlist or sanitization"}]},"security.command-injection-risk",t.paramConfidence==="high"?"high":"medium",{sourceParameters:t.sourceParams,sink:"exec",sanitizerStatus:t.hasValidation?"partial":"missing",propagationSteps:r.map(l=>`${l.callee}:${l.lineStart}`)}))}o.length>0&&r.length===0&&i.push(ue({severity:"high",category:"command-injection-risk",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Potential command injection: ${t.functionName}(${t.sourceParams.join(", ")}) \u2192 spawn`,reason:`Parameter${t.sourceParams.length>1?"s":""} '${t.sourceParams.join("', '")}' (external input) flow${t.sourceParams.length===1?"s":""} into spawn. If shell:true is set, this is equivalent to exec. Verify spawn uses array args without shell option.`,files:[n.file],suggestedFix:{strategy:"Ensure spawn uses array arguments without shell: true.",steps:["Verify spawn is called as spawn(binary, [arg1, arg2]) \u2014 NOT spawn(cmd, { shell: true }).","Remove shell: true if present.","Validate command arguments against an allowlist."]},impact:"spawn with shell:true enables the same command injection as exec. Without shell:true, spawn with array args is safe from injection.",tags:["security","command-injection","agentic"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.functionName,lineHint:t.lineStart,file:n.file,expectedResult:"trace incoming callers \u2014 check if spawn uses shell:true option"}]},"security.command-injection-risk","medium",{sourceParameters:t.sourceParams,sink:"spawn",sanitizerStatus:t.hasValidation?"partial":"missing",propagationSteps:o.map(a=>`${a.callee}:${a.lineStart}`)}))}return i}function Vi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.consoleLogs||[])t.method==="debugger"?i.push(ue({severity:"high",category:"debug-log-leakage",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Debugger statement in production code",reason:"A `debugger` statement pauses execution when DevTools are open. In production it can expose internal state and halt the application.",files:[n.file],suggestedFix:{strategy:"Remove the debugger statement before shipping.",steps:["Delete the `debugger;` line.","Use structured logging (pino, winston) or feature-flagged debug helpers instead."]},impact:"Debugger statements in production can halt request processing and expose internal runtime state to anyone with browser DevTools open.",tags:["security","debug","production-safety"]},"security.debug-log-leakage","high",{method:"debugger",line:t.lineStart})):(t.method==="debug"||t.method==="trace")&&i.push(ue({severity:"medium",category:"debug-log-leakage",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`console.${t.method}() in production code`,reason:`console.${t.method}() is a development-only call. Left in production it leaks internal state, variable values, and execution paths \u2014 all useful to attackers.`,files:[n.file],suggestedFix:{strategy:"Replace with a structured logger that respects log-level configuration.",steps:[`Remove or gate the console.${t.method}() call behind a LOG_LEVEL check.`,"Use a structured logger (pino, winston) with level filtering instead.","Ensure debug/trace levels are disabled in production config."]},impact:"Debug/trace logs expose internal object state and execution flow, making reconnaissance easier for attackers and violating minimal disclosure.",tags:["security","debug","information-disclosure"],lspHints:[{tool:"lspFindReferences",symbolName:`console.${t.method}`,lineHint:t.lineStart,file:n.file,expectedResult:"find all debug/trace log calls in this file to assess total leakage surface"}]},"security.debug-log-leakage","medium",{method:t.method,snippet:t.argSnippet,line:t.lineStart}));return i}function Qi(e){let i=[];for(let n of e)if(!x(n.file))for(let t of n.consoleLogs||[])t.method==="debugger"||!t.hasSensitiveArg||i.push(ue({severity:"high",category:"sensitive-data-logging",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Sensitive data logged via console.${t.method}()${t.argSnippet?`: ${t.argSnippet.slice(0,40)}`:""}`,reason:`console.${t.method}() argument matches a sensitive-data pattern (password, token, secret, credential, API key, session, SSN). Logging secrets writes them to stdout/stderr, log aggregators, error monitoring services, and persistent log files.`,files:[n.file],suggestedFix:{strategy:"Remove or redact sensitive values before logging.",steps:["Never log raw passwords, tokens, API keys, or session identifiers.",'If logging for debugging, redact: log({ ...user, password: "[REDACTED]" }).',"Use a structured logger with field-level redaction hooks (e.g. pino redact option).","Audit all log aggregation pipelines (Datadog, Splunk, CloudWatch) for secret exposure."]},impact:"Sensitive data in logs is written to stdout/stderr, forwarded to log aggregators (Splunk, Datadog, CloudWatch), and often stored long-term \u2014 creating a persistent credential leak accessible to anyone with log access.",tags:["security","sensitive-data","credential-leak","compliance"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.method,lineHint:t.lineStart,file:n.file,expectedResult:`trace incoming callers to understand where sensitive data originates before reaching console.${t.method}`}]},"security.sensitive-data-logging","high",{method:t.method,snippet:t.argSnippet,line:t.lineStart,sanitizerStatus:"missing"}));return i}var ml,ue,Ji=N(()=>{"use strict";G();ml=/(\(.+[+*]\))[+*]|(\(.+\?\))\{/,ue=(e,i,n,t)=>({...e,ruleId:i,confidence:n,evidence:t})});var tt=N(()=>{"use strict";he();Ir();Lr();Or();jr();_r();Hr();Ji()});import zr from"node:path";import*as w from"typescript";function Kr(e,i){if(!e||!Array.isArray(e.functions))return{file:e?.file||"<unknown>",complexityRisk:1,highComplexityFunctions:0,functionCount:0,flows:0,score:1};let n=0,t=0;for(let o of e.functions){let a=Number(o.complexity)||0;n+=a,a>=i.thresholds.criticalComplexityThreshold&&(t+=1)}let s=e.flows?e.flows.length:0,r=Math.max(1,Math.round(n*.7+e.functions.length*2+s*.2));return{file:e.file,functionCount:e.functions.length,highComplexityFunctions:t,flows:s,complexitySum:n,complexityRisk:t,score:r}}function hl(e){if(w.isIfStatement(e)){let i=e.thenStatement;return w.isBlock(i)?i.statements.length:1}if(w.isSwitchStatement(e))return e.caseBlock.clauses.length;if(w.isTryStatement(e))return e.tryBlock.statements.length;if(w.isForStatement(e)||w.isWhileStatement(e)||w.isDoStatement(e)||w.isForOfStatement(e)||w.isForInStatement(e)){let i=e.statement;return w.isBlock(i)?i.statements.length:1}return 1}function Br(e,i,n){let t=R(i,e);return{file:zr.relative(n,e.getSourceFile().fileName),lineStart:t.lineStart,lineEnd:t.lineEnd,columnStart:t.columnStart,columnEnd:t.columnEnd}}function Yi(e,i,n,t,s,r,o){let a=e.fileName,l=zr.relative(t.root,a);n.fileCount+=1,n.nodeCount+=1,n.kindCounts.SourceFile=(n.kindCounts.SourceFile||0)+1;let c={package:i,file:l,parseEngine:"typescript",nodeCount:0,kindCounts:{},functions:[],flows:[],dependencyProfile:o};if(t.emitTree){let b={size:8e3},k=mn(e,e,t.treeDepth,b);k&&r.push({package:i,file:l,tree:k})}let u=mt,d=[],f=[],p=[],g=0,m=[],S=[],h=[],y=new Set([0,1,-1,2,100]),D=b=>{c.nodeCount+=1,n.nodeCount+=1;let k=w.SyntaxKind[b.kind]||"UNKNOWN";if(c.kindCounts[k]=(c.kindCounts[k]||0)+1,n.kindCounts[k]=(n.kindCounts[k]||0)+1,w.isCatchClause(b)&&b.block.statements.length===0){let A=R(e,b);d.push({file:l,lineStart:A.lineStart,lineEnd:A.lineEnd})}if(w.isSwitchStatement(b)&&!b.caseBlock.clauses.some(A=>A.kind===w.SyntaxKind.DefaultClause)){let A=R(e,b);f.push({file:l,lineStart:A.lineStart,lineEnd:A.lineEnd})}if(b.kind===w.SyntaxKind.AnyKeyword&&(g+=1),w.isAsExpression(b)&&b.type.kind===w.SyntaxKind.AnyKeyword&&(g+=1),w.isAsExpression(b)){if(b.type.kind===w.SyntaxKind.AnyKeyword){let C=R(e,b);m.push({file:l,lineStart:C.lineStart,lineEnd:C.lineEnd})}if(w.isAsExpression(b.expression)&&b.expression.type.kind===w.SyntaxKind.UnknownKeyword){let C=R(e,b);S.push({file:l,lineStart:C.lineStart,lineEnd:C.lineEnd})}}if(w.isNonNullExpression(b)){let C=R(e,b);h.push({file:l,lineStart:C.lineStart,lineEnd:C.lineEnd})}if(w.isNumericLiteral(b)){let C=Number(b.text);if(!y.has(C)){let A=b.parent,M=A&&w.isVariableDeclaration(A)&&A.parent&&w.isVariableDeclarationList(A.parent)&&(A.parent.flags&w.NodeFlags.Const)!==0,E=A&&w.isEnumMember(A);if(!M&&!E){let _=R(e,b);p.push({value:C,file:l,lineStart:_.lineStart,lineEnd:_.lineEnd})}}}if(ae(b)){let C=b,A=C.body,M=A&&w.isBlock(A)?A.statements.length:1,E=Br(b,e,t.root),_=We(b,e),K=A?$n(A):{complexity:1,maxBranchDepth:0,maxLoopDepth:0,returns:0,awaits:0,calls:0,loops:0},V={kind:k,name:_,nameHint:_,file:l,lineStart:E.lineStart,lineEnd:E.lineEnd,columnStart:E.columnStart,columnEnd:E.columnEnd,statementCount:M,complexity:K.complexity,maxBranchDepth:K.maxBranchDepth,maxLoopDepth:K.maxLoopDepth,returns:K.returns,awaits:K.awaits,calls:K.calls,loops:K.loops,lengthLines:An(e,b),cognitiveComplexity:A?fi(A):0};if(A&&(V.halstead=Dn(A),V.maintainabilityIndex=Rn(V.halstead.volume,K.complexity,V.lengthLines)),w.isFunctionDeclaration(b)&&(V.declared=!0),M>=t.thresholds.minFunctionStatements){let se=A?pn(A):Ge(l);Se(s.flowMap,`${se}|${b.kind}`,{...V,hash:se,metrics:K})}C.parameters&&(V.params=C.parameters.length),c.functions.push(V),n.functions.push(V),n.functionCount+=1}if(u.has(b.kind)){let C=hl(b),A=Br(b,e,t.root),M={kind:k,file:l,lineStart:A.lineStart,lineEnd:A.lineEnd,columnStart:A.columnStart,columnEnd:A.columnEnd,statementCount:C};if(c.flows.push(M),n.flowCount+=1,C>=t.thresholds.minFlowStatements){let E=pn(b);Se(s.controlMap,`${E}|${b.kind}`,{...M,hash:E})}}w.forEachChild(b,D)};return w.forEachChild(e,D),c.emptyCatches=d,c.switchesWithoutDefault=f,c.anyCount=g,c.magicNumbers=p,c.typeAssertionEscapes={asAny:m,doubleAssertion:S,nonNull:h},yl(e,c),Sl(e,l,c),El(e,l,c),c}function yl(e,i){let n=[],t=[];for(let s of i.functions){if(s.awaits===0)continue;let r=e.getPositionOfLineAndCharacter(Math.max(0,s.lineStart-1),0),o,a=p=>{if(!o){if(ae(p)&&p.getStart(e)>=r&&R(e,p).lineStart===s.lineStart){o=p;return}w.forEachChild(p,a)}};if(w.forEachChild(e,a),!o||!o.modifiers?.some(p=>p.kind===w.SyntaxKind.AsyncKeyword))continue;let c=0,u=!1,d=!1,f=p=>{w.isAwaitExpression(p)&&c++,w.isTryStatement(p)&&(u=!0),w.isCallExpression(p)&&w.isPropertyAccessExpression(p.expression)&&p.expression.name.text==="catch"&&(d=!0),!(ae(p)&&p!==o)&&w.forEachChild(p,f)};w.forEachChild(o,f),c===0?n.push({name:s.name,lineStart:s.lineStart,lineEnd:s.lineEnd}):!u&&!d&&t.push({name:s.name,awaitCount:c,lineStart:s.lineStart,lineEnd:s.lineEnd})}i.asyncWithoutAwait=n,i.unprotectedAsync=t}function Sl(e,i,n){if(Dr(e,i,n),x(i)||(Er(e,i,n),gr(e,i,n)),vr(e,i,n),x(i)&&Ar(e,i,n),!x(i)){let t=Sr(e,i);t.length>0&&(n.topLevelEffects=t);let s=kr(e);s.length>0&&(n.prototypePollutionSites=s)}}function El(e,i,n){if(x(i))return;let t=[],s=[],r=[],o=[],a=new Map,l=c=>{if(w.isBinaryExpression(c)&&(c.operatorToken.kind===w.SyntaxKind.EqualsEqualsEqualsToken||c.operatorToken.kind===w.SyntaxKind.ExclamationEqualsEqualsToken||c.operatorToken.kind===w.SyntaxKind.EqualsEqualsToken||c.operatorToken.kind===w.SyntaxKind.ExclamationEqualsToken)){let u=d=>{if(w.isStringLiteral(d)&&d.text.length>0){let f=R(e,d),p=a.get(d.text)||[];p.push({file:i,lineStart:f.lineStart,lineEnd:f.lineEnd}),a.set(d.text,p)}};u(c.left),u(c.right)}if(w.isSwitchStatement(c)){for(let u of c.caseBlock.clauses)if(w.isCaseClause(u)&&w.isStringLiteral(u.expression)){let d=u.expression.text;if(d.length>0){let f=R(e,u.expression),p=a.get(d)||[];p.push({file:i,lineStart:f.lineStart,lineEnd:f.lineEnd}),a.set(d,p)}}}if(w.isCatchClause(c)){let u=c.block;if(u.statements.length===1&&w.isThrowStatement(u.statements[0])){let d=u.statements[0].expression,f=c.variableDeclaration?.name;if(d&&f&&w.isIdentifier(f)&&w.isIdentifier(d)&&d.text===f.text){let p=R(e,c);s.push({file:i,lineStart:p.lineStart,lineEnd:p.lineEnd})}}}if(ae(c)){let u=c;if(u.parameters&&u.parameters.length>=2){let d=0;for(let f of u.parameters)f.type&&f.type.kind===w.SyntaxKind.BooleanKeyword&&d++;if(d>=3){let f=We(c,e),p=R(e,c);r.push({name:f,booleanCount:d,totalParams:u.parameters.length,lineStart:p.lineStart,lineEnd:p.lineEnd})}}}if(w.isCallExpression(c)&&w.isPropertyAccessExpression(c.expression)&&w.isIdentifier(c.expression.expression)&&c.expression.expression.text==="Promise"&&bl.has(c.expression.name.text)){let u=c.expression.name.text,d=!1,f=!1,p=c.parent;for(;p;){if(w.isTryStatement(p)){d=!0;break}if(w.isCallExpression(p)&&w.isPropertyAccessExpression(p.expression)&&p.expression.name.text==="catch"){f=!0;break}if(ae(p))break;p=p.parent}if(!d&&!f){let g=R(e,c);o.push({file:i,lineStart:g.lineStart,lineEnd:g.lineEnd,kind:xl[u]||"Promise.all"})}}w.forEachChild(c,l)};w.forEachChild(e,l);for(let[c,u]of a)if(u.length>=2)for(let d of u)t.push({...d,value:c});t.length>0&&(n.magicStrings=t),s.length>0&&(n.catchRethrows=s),r.length>0&&(n.booleanParamClusters=r),o.length>0&&(n.promiseAllUnhandled=o)}var bl,xl,Ur=N(()=>{"use strict";je();Mn();mr();Tt();wr();Fr();Cr();Rr();Mr();G();tt();ge();je();Mn();bl=new Set(["all","allSettled","race","any"]),xl={all:"Promise.all",allSettled:"Promise.allSettled",race:"Promise.race",any:"Promise.any"}});import wl from"node:path";import{fileURLToPath as vl}from"node:url";function qr(e,i=process.argv[1]){return i?vl(e)===wl.resolve(i):!1}var Gr=N(()=>{"use strict"});import $e from"node:path";import*as Y from"typescript";function Fl(e){let i=[];for(let n of e)for(let[t,s]of n.referenceCountByExport)s.count===0&&i.push({severity:"high",category:"semantic-dead-export",file:n.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Semantically dead export: ${t}`,reason:`Exported symbol "${t}" has zero semantic references across the entire program (confirmed via TypeChecker, not just import matching).`,files:[n.file],suggestedFix:{strategy:"Remove the export or delete the symbol if unused internally.",steps:["Verify the symbol is not used via dynamic imports or runtime reflection.","Remove the export keyword, or delete the symbol entirely if also unused locally.","Re-run scan to confirm finding is resolved."]},impact:"Dead exports bloat the public API surface and confuse contributors.",tags:["architecture","dead-code","semantic"],lspHints:[{tool:"lspFindReferences",symbolName:t,lineHint:s.lineStart,file:n.file,expectedResult:"zero references confirms dead export"}]});return i}function kl(e,i){let n=[],t=new Map;for(let s of i){let r=e.program.getSourceFile($e.resolve(e.root,s.file));if(!r)continue;let o=a=>{if(Y.isInterfaceDeclaration(a)&&a.name){let l=a.name.text,c=r.getLineAndCharacterOfPosition(a.getStart(r)).line+1,u=e.service.getImplementationAtPosition($e.resolve(e.root,s.file),a.name.getStart(r)),d=new Set;if(u)for(let p of u){let g=p.fileName;(g!==$e.resolve(e.root,s.file)||p.textSpan.start!==a.getStart(r))&&d.add(g)}t.has(l)||t.set(l,{files:new Set,line:c,file:s.file});let f=t.get(l);for(let p of d)f.files.add(p)}Y.forEachChild(a,o)};Y.forEachChild(r,o)}for(let[s,r]of t)if(r.files.size===1){let o=[...r.files][0],a=$e.relative(e.root,o);n.push({severity:"medium",category:"over-abstraction",file:r.file,lineStart:r.line,lineEnd:r.line,title:`Over-abstraction: interface ${s} has exactly 1 implementor`,reason:`Interface "${s}" is implemented only by one class in "${a}". The abstraction layer adds complexity without enabling polymorphism.`,files:[r.file,a],suggestedFix:{strategy:"Inline the interface into the concrete class or keep it only if future implementors are planned.",steps:["Evaluate whether the interface is needed for testing (mocking) or future extensibility.","If not, merge the interface declaration into the concrete class.","Update consumers to depend on the concrete class directly."]},impact:"Over-abstraction adds indirection without polymorphic benefit, increasing cognitive load.",tags:["architecture","abstraction","semantic"],lspHints:[{tool:"lspFindReferences",symbolName:s,lineHint:r.line,file:r.file,expectedResult:"exactly 1 implementation confirms over-abstraction"}]})}return n}function Cl(e){let i=[];for(let n of e)for(let t of n.concreteImports)i.push({severity:"medium",category:"concrete-dependency",file:n.file,lineStart:t.lineStart,lineEnd:t.lineStart,title:`Concrete dependency: ${n.file} imports class ${t.name}`,reason:`Module imports concrete class "${t.name}" from "${t.targetFile}" instead of an interface or abstract class. This violates the Dependency Inversion Principle (DIP).`,files:[n.file,t.targetFile],suggestedFix:{strategy:"Depend on an interface or abstract class instead of the concrete implementation.",steps:["Extract an interface from the concrete class covering the methods used by this module.","Update imports to reference the interface instead of the concrete class.","Use dependency injection to provide the concrete implementation at runtime."]},impact:"Concrete dependencies make modules harder to test and tightly coupled to implementation details.",tags:["architecture","dip","coupling","semantic"],lspHints:[{tool:"lspGotoDefinition",symbolName:t.name,lineHint:t.lineStart,file:n.file,expectedResult:"resolves to concrete class (not interface/abstract)"}]});return i}function Tl(e,i){let n=[],t=new Map;for(let l of i){let c=e.program.getSourceFile($e.resolve(e.root,l.file));if(!c)continue;let u=new Set,d=new Map,f=p=>{if((Y.isInterfaceDeclaration(p)||Y.isTypeAliasDeclaration(p))&&p.name){let g=`${l.file}::${p.name.text}`;u.add(g);let m=new Set,S=h=>{if(Y.isTypeReferenceNode(h)&&Y.isIdentifier(h.typeName)){let y=h.typeName.text,D=e.checker.getSymbolAtLocation(h.typeName);if(D){let b=D.getDeclarations?.()?.[0];if(b){let k=b.getSourceFile().fileName,C=$e.relative(e.root,k);m.add(`${C}::${y}`)}}}Y.forEachChild(h,S)};Y.forEachChild(p,S),d.set(g,m)}Y.forEachChild(p,f)};Y.forEachChild(c,f);for(let[p,g]of d){t.has(p)||t.set(p,new Set);for(let m of g)t.get(p).add(m)}}let s=new Set,r=new Set,o=new Set,a=(l,c)=>{if(r.has(l)){let u=c.indexOf(l);if(u>=0){let d=c.slice(u),f=[...d].sort().join("\u2192");if(!o.has(f)&&d.length>=2){o.add(f);let p=d[0],[g]=p.split("::");n.push({severity:"high",category:"circular-type-dependency",file:g,lineStart:1,lineEnd:1,title:`Circular type dependency: ${d.map(m=>m.split("::")[1]).join(" \u2192 ")}`,reason:`Type-level circular dependency detected: ${d.map(m=>m.split("::")[1]).join(" \u2192 ")} \u2192 ${d[0].split("::")[1]}. Types reference each other creating a cycle.`,files:[...new Set(d.map(m=>m.split("::")[0]))],suggestedFix:{strategy:"Break the type cycle by extracting shared type definitions.",steps:["Identify the minimal set of type properties causing the cycle.","Extract shared types to a dedicated types file that both sides can import.","Replace direct type references with the shared type."]},impact:"Circular type dependencies make types harder to understand, refactor, and can cause issues with type inference.",tags:["architecture","types","cycle","semantic"]})}}return}if(!s.has(l)){r.add(l),c.push(l);for(let u of t.get(l)??[])a(u,c);c.pop(),r.delete(l),s.add(l)}};for(let l of t.keys())a(l,[]);return n}function $l(e){let i=[];for(let n of e)for(let t of n.unusedParams)i.push({severity:"medium",category:"unused-parameter",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Unused parameter: ${t.paramName} in ${t.functionName}`,reason:`Parameter "${t.paramName}" in function "${t.functionName}" is never referenced in the function body (confirmed via semantic analysis).`,files:[n.file],suggestedFix:{strategy:"Remove the parameter or prefix with underscore to indicate intentional non-use.",steps:["Check if the parameter is required by an interface or callback signature.","If not required, remove it and update all call sites.","If required by contract, prefix with _ (e.g. _unused) to signal intent."]},impact:"Unused parameters add noise to function signatures and confuse callers about what the function actually needs.",tags:["code-quality","parameters","semantic"],lspHints:[{tool:"lspFindReferences",symbolName:t.paramName,lineHint:t.lineStart,file:n.file,expectedResult:"zero non-declaration references confirms unused"}]});return i}function Dl(e,i=3){let n=[];for(let t of e)for(let s of t.overrideChains)s.depth>i&&n.push({severity:s.depth>4?"high":"medium",category:"deep-override-chain",file:t.file,lineStart:s.lineStart,lineEnd:s.lineStart,title:`Deep override chain: ${s.className}.${s.methodName} (depth ${s.depth})`,reason:`Method "${s.methodName}" in class "${s.className}" overrides a method ${s.depth} levels up in the inheritance chain (threshold: ${i}).`,files:[t.file],suggestedFix:{strategy:"Reduce override depth by flattening the class hierarchy or using the template method pattern.",steps:["Identify if intermediate overrides are necessary or if they just pass through.","Consider extracting the behavior into a strategy or template method.","Flatten unnecessary intermediate classes."]},impact:"Deep override chains make method behavior unpredictable \u2014 understanding what runs requires tracing through many classes.",tags:["code-quality","inheritance","override","semantic"]});return n}function Rl(e){let i=[];for(let n of e)for(let t of n.interfaceImpls){let s=[];t.missingMembers.length>0&&s.push(`missing members: ${t.missingMembers.join(", ")}`),t.anycastMembers.length>0&&s.push(`any-cast members: ${t.anycastMembers.join(", ")}`),s.length>0&&i.push({severity:t.missingMembers.length>0?"high":"medium",category:"interface-compliance",file:t.classFile,lineStart:t.classLine,lineEnd:t.classLine,title:`Fragile interface compliance: ${t.className} implements ${t.interfaceName}`,reason:`Class "${t.className}" implements "${t.interfaceName}" with issues: ${s.join("; ")}.`,files:[t.classFile],suggestedFix:{strategy:"Fix the implementation to fully satisfy the interface contract.",steps:[...t.missingMembers.length>0?[`Implement missing members: ${t.missingMembers.join(", ")}.`]:[],...t.anycastMembers.length>0?[`Replace \`any\` types with proper types for: ${t.anycastMembers.join(", ")}.`]:[],"Enable strict type checking to catch these at compile time."]},impact:"Incomplete interface implementations create runtime surprises and defeat the purpose of type contracts.",tags:["code-quality","types","interface","semantic"],lspHints:[{tool:"lspGotoDefinition",symbolName:t.interfaceName,lineHint:t.classLine,file:t.classFile,expectedResult:"interface definition showing expected contract"}]})}return i}function Al(e){let i=[];for(let n of e)for(let t of n.unusedImports)i.push({severity:"low",category:"unused-import",file:n.file,lineStart:t.lineStart,lineEnd:t.lineStart,title:`Unused import: ${t.name}`,reason:`Imported symbol "${t.name}" is never referenced in this file (confirmed via semantic analysis, not just text matching).`,files:[n.file],suggestedFix:{strategy:"Remove the unused import statement.",steps:["Verify the import is not used for side effects (e.g. polyfills, CSS).","Remove the import statement.","If part of a multi-import, remove only the unused symbol."]},impact:"Unused imports slow down IDE performance, increase bundle size (if not tree-shaken), and add noise.",tags:["dead-code","imports","semantic"],lspHints:[{tool:"lspFindReferences",symbolName:t.name,lineHint:t.lineStart,file:n.file,expectedResult:"zero usage references confirms unused import"}]});return i}function Ml(e,i){let n=[];for(let t of i){let s=e.program.getSourceFile($e.resolve(e.root,t.file));if(!s)continue;let r=o=>{if(Y.isClassDeclaration(o)&&o.name){if(o.heritageClauses&&o.heritageClauses.length>0){Y.forEachChild(o,r);return}if(!o.modifiers?.some(d=>d.kind===Y.SyntaxKind.ExportKeyword)){Y.forEachChild(o,r);return}let c=e.service.findReferences($e.resolve(e.root,t.file),o.name.getStart(s)),u=0;if(c)for(let d of c)for(let f of d.references)f.isDefinition||f.fileName!==$e.resolve(e.root,t.file)&&u++;if(u===0){let d=s.getLineAndCharacterOfPosition(o.getStart(s)).line+1;n.push({severity:"medium",category:"orphan-implementation",file:t.file,lineStart:d,lineEnd:d,title:`Orphan implementation: class ${o.name.text}`,reason:`Exported class "${o.name.text}" has no external references and does not implement any interface or extend any base class. It may be unreachable dead code.`,files:[t.file],suggestedFix:{strategy:"Verify the class is needed and wire it in, or remove it.",steps:["Check if the class is used via dynamic imports, reflection, or DI containers.","If unused, remove the class and its export.","If needed, wire it into the dependency graph via an interface or direct import."]},impact:"Orphan implementations waste maintenance effort and bloat the codebase.",tags:["dead-code","class","orphan","semantic"],lspHints:[{tool:"lspFindReferences",symbolName:o.name.text,lineHint:d,file:t.file,expectedResult:"zero external references confirms orphan"}]})}}Y.forEachChild(o,r)};Y.forEachChild(s,r)}return n}function Pl(e,i=8){let n=[];for(let t of e)for(let[s,r]of t.referenceCountByExport)r.uniqueFiles>=i&&n.push({severity:r.uniqueFiles>12?"high":"medium",category:"shotgun-surgery",file:t.file,lineStart:r.lineStart,lineEnd:r.lineEnd,title:`Shotgun surgery risk: ${s} used in ${r.uniqueFiles} files`,reason:`Exported symbol "${s}" is referenced from ${r.uniqueFiles} unique files (threshold: ${i}). Any change to this symbol forces coordinated edits across all consumers.`,files:[t.file],suggestedFix:{strategy:"Reduce coupling by introducing a facade, adapter, or event-based decoupling.",steps:["Identify the consumers and group them by usage pattern.","Extract a stable interface that consumers depend on instead of the implementation.","Consider the Mediator or Facade pattern to reduce direct dependencies.","If the symbol is a utility, ensure it has a single, well-defined responsibility."]},impact:"High fan-out symbols are the #1 source of cascading changes during refactoring.",tags:["architecture","coupling","change-risk","semantic"],lspHints:[{tool:"lspFindReferences",symbolName:s,lineHint:r.lineStart,file:t.file,expectedResult:`${r.uniqueFiles}+ unique referencing files confirms shotgun surgery risk`}]});return n}function Il(e){let i=[];for(let n of e)for(let[t,s]of n.referenceCountByExport)s.uniqueFiles===1&&s.count>0&&i.push({severity:"low",category:"move-to-caller",file:n.file,lineStart:s.lineStart,lineEnd:s.lineEnd,title:`Single-consumer export: ${t} (used by 1 file)`,reason:`Exported symbol "${t}" is consumed by exactly 1 file. Consider moving it to the consumer or inlining it to reduce module surface.`,files:[n.file],suggestedFix:{strategy:"Move the symbol to its only consumer or inline it.",steps:["Verify no dynamic or reflection-based usage exists.","Move the function/class/constant to the consumer file.","Remove the export and the import from the consumer.","If the symbol is large, keep it but remove the export keyword."]},impact:"Single-consumer exports add unnecessary module surface and indirection.",tags:["dead-code","module-surface","refactoring","semantic"],lspHints:[{tool:"lspFindReferences",symbolName:t,lineHint:s.lineStart,file:n.file,expectedResult:"exactly 1 referencing file confirms single-consumer"}]});return i}function Nl(e){let i=[];for(let n of e)for(let t of n.narrowableParams)i.push({severity:"low",category:"narrowable-type",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Narrowable param: ${t.functionName}(${t.paramName}: ${t.declaredType}) \u2192 ${t.narrowedType}`,reason:`Parameter "${t.paramName}" in "${t.functionName}" is declared as \`${t.declaredType}\` but all call sites pass \`${t.narrowedType}\`. The type can be safely narrowed.`,files:[n.file],suggestedFix:{strategy:"Narrow the parameter type to match actual usage.",steps:[`Change the parameter type from \`${t.declaredType}\` to \`${t.narrowedType}\`.`,"Verify no future callers need the broader type.","If the function is part of a public API, consider keeping the broad type with a narrower overload."]},impact:"Overly broad parameter types weaken type checking \u2014 narrowing catches bugs at compile time.",tags:["code-quality","types","refactoring","semantic"],lspHints:[{tool:"lspCallHierarchy",symbolName:t.functionName,lineHint:t.lineStart,file:n.file,expectedResult:`all incoming calls pass ${t.narrowedType}`}]});return i}function Wr(e,i,n={}){let t=[];return t.push(...kl(e,i)),t.push(...Cl(i)),t.push(...Tl(e,i)),t.push(...$l(i)),t.push(...Dl(i,n.overrideChainThreshold??3)),t.push(...Rl(i)),t.push(...Al(i)),t.push(...Ml(e,i)),t.push(...Pl(i,n.shotgunThreshold??8)),t.push(...Il(i)),t.push(...Nl(i)),t.push(...Fl(i)),t}var Vr=N(()=>{"use strict"});function Qr(e){let i=[];for(let n of e){if(!x(n.file)||!n.testProfile)continue;let{testBlocks:t}=n.testProfile;if(t.length===0)continue;let s=t.reduce((o,a)=>o+a.assertionCount,0),r=s/t.length;r<1&&i.push({severity:"medium",category:"low-assertion-density",file:n.file,lineStart:t[0].lineStart,lineEnd:t[t.length-1].lineEnd,title:`Low assertion density: ${s} assertions across ${t.length} tests`,reason:`Average ${r.toFixed(1)} assertions per test. Tests with few assertions may pass without verifying actual behavior.`,files:[n.file],suggestedFix:{strategy:"Add meaningful assertions to each test case.",steps:["Review each test block and add expect() calls that verify outcomes.","Test both success and failure paths.","Assert return values, state changes, and side effects."]},impact:"Low assertion density means tests pass without verifying behavior \u2014 bugs slip through with false confidence.",tags:["test-quality","assertions"]})}return i}function Jr(e){let i=[];for(let n of e)if(!(!x(n.file)||!n.testProfile))for(let t of n.testProfile.testBlocks)t.assertionCount===0&&i.push({severity:"high",category:"test-no-assertion",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Test "${t.name}" has no assertions`,reason:"A test without assertions always passes. It provides no verification of behavior.",files:[n.file],suggestedFix:{strategy:"Add at least one expect() or assert() call.",steps:["Identify what behavior this test should verify.","Add expect(result).toBe(expected) or similar assertion.","If the test only checks that code does not throw, use expect(() => fn()).not.toThrow()."]},impact:"Zero-assertion tests always pass \u2014 they provide no safety net and create a false sense of coverage.",tags:["test-quality","assertions","false-pass"]});return i}function Yr(e,i=10){let n=[];for(let t of e){if(!x(t.file)||!t.testProfile)continue;let{mockCalls:s}=t.testProfile;s.length>i&&n.push({severity:"medium",category:"excessive-mocking",file:t.file,lineStart:s[0].lineStart,lineEnd:s[s.length-1].lineEnd,title:`${s.length} mock/spy calls in test file (threshold: ${i})`,reason:"Excessive mocking couples tests to implementation details, making them brittle and hard to maintain.",files:[t.file],suggestedFix:{strategy:"Reduce mocks by testing through public interfaces.",steps:["Identify mocks that can be replaced with real implementations.","Use dependency injection to simplify test setup.","Consider integration tests for complex interaction chains."]},impact:"Heavy mocking couples tests to implementation details \u2014 any refactor breaks them even if behavior is unchanged.",tags:["test-quality","mocking","brittleness"]})}return n}function Xr(e){let i=[];for(let n of e)if(!(!x(n.file)||!n.testProfile))for(let t of n.testProfile.mutableStateDecls)i.push({severity:"medium",category:"shared-mutable-state",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:"Mutable variable at describe scope",reason:"let/var at describe scope creates shared mutable state between tests. Tests may pass or fail depending on execution order.",files:[n.file],suggestedFix:{strategy:"Move variable declaration inside each test or use beforeEach.",steps:["Move the variable into each it()/test() block that uses it.","Or initialize it in beforeEach() so each test gets a fresh copy.","Use const where possible."]},impact:"Shared mutable state causes order-dependent test results \u2014 tests pass in isolation but fail or flake in suite runs.",tags:["test-quality","isolation","flaky"]});return i}function Zr(e){let i=[];for(let n of e){if(!x(n.file)||!n.testProfile)continue;let{setupCalls:t}=n.testProfile,s=t.some(l=>l.kind==="beforeAll"),r=t.some(l=>l.kind==="afterAll"),o=t.some(l=>l.kind==="beforeEach"),a=t.some(l=>l.kind==="afterEach");if(s&&!r){let l=t.find(c=>c.kind==="beforeAll");i.push({severity:"medium",category:"missing-test-cleanup",file:n.file,lineStart:l.lineStart,lineEnd:l.lineStart,title:"beforeAll without afterAll",reason:"Setup in beforeAll without teardown in afterAll can leak state (open connections, modified globals, temp files) across test suites.",files:[n.file],suggestedFix:{strategy:"Add afterAll() to clean up resources allocated in beforeAll().",steps:["Identify what beforeAll() sets up (connections, mocks, temp state).","Add afterAll() to tear it down."]},impact:"Missing teardown leaks resources (connections, file handles, globals) that poison subsequent test suites.",tags:["test-quality","cleanup","leak"]})}if(o&&!a){let l=t.find(c=>c.kind==="beforeEach");i.push({severity:"medium",category:"missing-test-cleanup",file:n.file,lineStart:l.lineStart,lineEnd:l.lineStart,title:"beforeEach without afterEach",reason:"Setup in beforeEach without teardown in afterEach can accumulate side effects across tests.",files:[n.file],suggestedFix:{strategy:"Add afterEach() to clean up resources allocated in beforeEach().",steps:["Identify what beforeEach() sets up.","Add afterEach() to tear it down or restore state."]},impact:"Per-test setup without teardown accumulates side effects, causing cascading failures in later tests.",tags:["test-quality","cleanup"]})}}return i}function eo(e){let i=[];for(let n of e)if(!(!x(n.file)||!n.testProfile))for(let t of n.testProfile.focusedCalls)i.push({severity:"medium",category:"focused-test",file:n.file,lineStart:t.lineStart,lineEnd:t.lineEnd,title:`Focused test marker: ${t.kind}`,reason:`${t.kind} limits scan or production of focused tests; it can hide unrelated failures and reduce suite coverage when committed.`,files:[n.file],suggestedFix:{strategy:"Avoid focused/skip patterns in committed tests.",steps:["Remove `.only`/`.skip`/`.todo` markers before merging.","Use local test filtering only for interactive local debugging.","If temporarily needed, add a TODO and a tracked follow-up task."]},impact:"Focused tests can create a false green signal by skipping broader test coverage.",tags:["test-quality","selection","flaky","coverage"],ruleId:"test-quality.focused-test",confidence:"high",evidence:{marker:t.kind,lineStart:t.lineStart,lineEnd:t.lineEnd,category:"focused-test"}});return i}function to(e){let i=[];for(let n of e){if(!x(n.file)||!n.testProfile)continue;let t=n.testProfile.timerControls.filter(o=>o.kind==="jest.useFakeTimers"||o.kind==="vi.useFakeTimers");if(t.length===0||n.testProfile.timerControls.some(o=>o.kind==="jest.useRealTimers"||o.kind==="vi.useRealTimers"))continue;let r=t[0];i.push({severity:"medium",category:"fake-timer-no-restore",file:n.file,lineStart:r.lineStart,lineEnd:r.lineEnd,title:"Fake timers activated without restore",reason:"Tests that switch to fake timers without restoring real timers can leak timing behavior into subsequent tests.",files:[n.file],suggestedFix:{strategy:"Pair fake timer activation with a restore in the same test scope.",steps:["Call `jest.useRealTimers()` or `vi.useRealTimers()` in afterEach() or afterAll().","Prefer per-test setup/teardown with explicit timer cleanup."]},impact:"Leaked fake-timer configuration can cause subtle, order-dependent failures across unrelated suites.",tags:["test-quality","timers","isolation"],ruleId:"test-quality.fake-timer-no-restore",confidence:"medium",evidence:{fakeTimerActivationLines:t.map(o=>`${o.kind}:${o.lineStart}`)}})}return i}function no(e){let i=[];for(let n of e){if(!x(n.file)||!n.testProfile||n.testProfile.spyOrStubCalls.length===0||n.testProfile.mockRestores.some(a=>a.kind==="restoreAll"))continue;let s=new Set(n.testProfile.mockRestores.filter(a=>a.kind==="restore"&&!!a.target).map(a=>a.target)),r=n.testProfile.spyOrStubCalls.find(a=>!a.target||!s.has(a.target));if(!r)continue;let o=r;i.push({severity:"medium",category:"missing-mock-restoration",file:n.file,lineStart:o.lineStart,lineEnd:o.lineEnd,title:"Spy/stub not restored",reason:"Spies/stubs modify implementation behavior and must be restored to avoid cross-test leakage.",files:[n.file],suggestedFix:{strategy:"Restore every spy/stub after each test or in a file-level teardown.",steps:["Call `mockRestore()` on each spy/stub returned handle.","Or use `jest.restoreAllMocks()`/`vi.restoreAllMocks()` in afterEach/afterAll."]},impact:"Unrestored spies/stubs make tests order-dependent and can mask regressions.",tags:["test-quality","cleanup","mocks","isolation"],ruleId:"test-quality.missing-mock-restoration",confidence:"high",evidence:{spyOrStubCalls:n.testProfile.spyOrStubCalls.map(a=>`${a.lineStart}`)}})}return i}var io=N(()=>{"use strict";G()});import Ll from"node:fs";import He from"node:path";function Fe(e){let i={critical:0,high:0,medium:0,low:0,info:0};for(let n of e)i[n.severity]=(i[n.severity]||0)+1;return i}function Le(e){let i={};for(let n of e)i[n.category]=(i[n.category]||0)+1;return i}function Xi(e,i){if(i===0)return 100;let n={critical:25,high:10,medium:3,low:1,info:0},t=0;for(let[o,a]of Object.entries(e))t+=(n[o]||0)*a;let s=t/i,r=Math.max(0,Math.min(100,Math.round(100/(1+s/10))));return t===0?r:(e.critical??0)>0?Math.min(r,95):(e.high??0)>0?Math.min(r,98):Math.min(r,99)}function so(e){let i=new Map;for(let n of e)if(n.tags)for(let t of n.tags)i.set(t,(i.get(t)||0)+1);return[...i.entries()].map(([n,t])=>({tag:n,count:t})).sort((n,t)=>t.count-n.count)}function ro(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Ol(e){let i=new Set(e),n=[];for(let[t,s]of Object.entries(B))if(s.length>0&&s.every(r=>i.has(r))){n.push(t);for(let r of s)i.delete(r)}return[...n,...[...i].sort()]}function oo(e,i){return i?(B[e]||[]).some(t=>i.has(t)):!0}function es(e,i){if(!Number.isFinite(i)||i>=e.length)return e;let n=new Map;for(let o of e){let a=o.category;n.has(a)||n.set(a,[]),n.get(a).push(o)}let t=[...n.entries()].sort((o,a)=>{let l=Pe[o[1][0].severity]??0;return(Pe[a[1][0].severity]??0)-l}),s=[],r=new Map;for(let[o]of t)r.set(o,0);for(;s.length<i;){let o=!1;for(let[a,l]of t){if(s.length>=i)break;let c=r.get(a);c<l.length&&(s.push(l[c]),r.set(a,c+1),o=!0)}if(!o)break}return s}function ts(e,i=20,n=2){let t=[],s=new Map;for(let r of e){let o=s.get(r.category)||0;if(!(o>=n)&&(t.push(r),s.set(r.category,o+1),t.length>=i))break}return t}function jl(e){return JSON.stringify(e.replace(/\\/g,"/"))}function ns(e){let{dir:i,report:n,outputFiles:t,architectureFindings:s,codeQualityFindings:r,deadCodeFindings:o,hotFiles:a=[],activeFeatures:l=null,scope:c=null,root:u=process.cwd(),scopeSymbols:d=null,semanticEnabled:f=!1,securityFindings:p=[],testQualityFindings:g=[],reportAnalysis:m=null,fileInventory:S=n.fileInventory||[]}=e,h=n.optimizationFindings||[],y=n.summary,D=n.agentOutput,b=D?.findingStats??null,k=n.dependencyGraph,C=He.relative(u,i)||".",A=((c?.[0]??"src/index").split(":")[0]||"src/index").replace(/\\/g,"/"),M=b?.overall??{totalFindings:h.length,severityBreakdown:Fe(h)},E=[];E.push(`# Code Quality Scan Report
|
|
120
|
+
`),E.push(`**Generated**: ${n.generatedAt} `),E.push(`**Root**: \`${n.repoRoot}\`
|
|
121
|
+
`),E.push(`## Scan Scope
|
|
122
|
+
`),E.push("| Metric | Count |"),E.push("|--------|-------|"),E.push(`| Files analyzed | ${y.totalFiles??"\u2014"} |`),E.push(`| Functions | ${y.totalFunctions??"\u2014"} |`),E.push(`| Flow nodes | ${y.totalFlows??"\u2014"} |`),E.push(`| Dependency files | ${y.totalDependencyFiles??"\u2014"} |`),E.push(`| Packages | ${y.totalPackages??"\u2014"} |`),E.push(""),E.push(`## Findings Overview
|
|
123
|
+
`),E.push("| Severity | Count |"),E.push("|----------|-------|"),E.push(`| Critical | ${M.severityBreakdown.critical??0} |`),E.push(`| High | ${M.severityBreakdown.high??0} |`),E.push(`| Medium | ${M.severityBreakdown.medium??0} |`),E.push(`| Low | ${M.severityBreakdown.low??0} |`),E.push(`| **Total** | **${M.totalFindings}** |`),E.push(""),Zl(E,{allFindings:h,overallFindingStats:M,agentOutput:D,activeFeatures:l,scope:c,root:u,scopeSymbols:d,semanticEnabled:f});let _=(j,X)=>{let re=Le(X),P=B[j]||[],oe=l!==null;for(let ce of P){let Ae=re[ce]||0,ze=oe&&!l.has(ce);E.push(ze?`- \`${ce}\`: \u2014 *(skipped)*`:`- \`${ce}\`: ${Ae}`)}E.push("")},K=y.totalFiles||1,V=b?.pillars?.architecture,se=b?.pillars?.["code-quality"],fe=b?.pillars?.["dead-code"],H=b?.pillars?.security,te=b?.pillars?.["test-quality"],ye=Wl(K,M,{archStats:V,qualStats:se,deadStats:fe,secStats:H,testStats:te,architectureFindings:s,codeQualityFindings:r,deadCodeFindings:o,securityFindings:p,testQualityFindings:g}),xe=Xl(E,l,t),O=Dt(h,{fileInventory:S,hotFiles:a,reportAnalysis:m,includeTests:!!n.options?.includeTests});if(Ql(E,ye,l),Jl(E,Rt(h,K,l,{hotFiles:a})),Yl(E,O),ec(E,h),m&&tc(E,m),nc(E,t,h),E.push(`## Architecture Health
|
|
124
|
+
`),xe("architecture",V?.totalFindings??s.length,ye.archHealth,"architecture","architecture.json"),k&&(E.push("| Metric | Value |"),E.push("|--------|-------|"),E.push(`| Modules | ${k.totalModules} |`),E.push(`| Import edges | ${k.totalEdges} |`),E.push(`| Cycles | ${k.cycles?.length??0} |`),E.push(`| Critical paths | ${k.criticalPaths?.length??0} |`),E.push(`| Root modules | ${k.rootsCount} |`),E.push(`| Leaf modules | ${k.leavesCount} |`),E.push(`| Test-only modules | ${k.testOnlyModules?.length??0} |`),E.push(`| Unresolved imports | ${k.unresolvedEdgeCount} |`),E.push("")),_("architecture",s),ic(E,a),sc(E,{architectureFindings:s,codeQualityFindings:r,deadCodeFindings:o,securityFindings:p,testQualityFindings:g,archStats:V,qualStats:se,deadStats:fe,secStats:H,testStats:te,...ye,activeFeatures:l,outputFiles:t,renderPillarCategories:_,pushPillarSummary:xe}),rc(E,D),t.astTrees&&oc(E,i,t,u,C,A),ac(E,i,t),n.parseErrors?.length>0){E.push(`## Parse Errors
|
|
125
|
+
`),E.push(`${n.parseErrors.length} file(s) failed to parse:
|
|
126
|
+
`);for(let j of n.parseErrors.slice(0,10))E.push(`- \`${j.file}\`: ${j.message}`);E.push("")}return E.join(`
|
|
127
|
+
`)}function Ne(e){return Math.max(0,Math.min(100,Math.round(e)))}function ee(e,i,n=1.4){return e<=0?0:Math.round(i*(1-Math.exp(-e*n)))}function Ve(e){return e>=25?"high":e>=8?"medium":"low"}function nt(e){return e.length===0?0:e.reduce((i,n)=>i+n,0)/e.length}function rt(e){return e.replace(/\\/g,"/")}function Bl(e){let i=rt(e).toLowerCase();return/(?:^|\/)(?:dist|build|coverage|out|vendor|vendors|generated|gen|\.cache)(?:\/|$)/.test(i)||/\.min\.(?:js|jsx|mjs|cjs|css)$/i.test(i)||/\.bundle\./i.test(i)}function Zi(e,i){let n=rt(e);return!(!i.includeTests&&x(n)||!i.includeGenerated&&Bl(n))}function zl(e,i){let n=new Set;e.file&&n.add(e.file);for(let t of e.files||[])n.add(t);if(n.size===0)return!0;for(let t of n)if(Zi(t,i))return!0;return!1}function Kl(e,i){return e.file&&i.has(e.file)?!0:(e.files||[]).some(n=>i.has(n))}function Ul(e){return/^[a-z0-9]+(?:-[a-z0-9]+)+$/.test(e)?"kebab":/^[a-z0-9]+(?:_[a-z0-9]+)+$/.test(e)?"snake":/^[a-z]+(?:[A-Z][a-z0-9]*)+$/.test(e)?"camel":/^[a-z0-9]+$/.test(e)?"flat":"other"}function ql(e,i){let n=new Set;for(let t of i)n.add(t.file);for(let t of e){t.file&&n.add(t.file);for(let s of t.files||[])n.add(s)}return n}function Qe(e,i,n={}){return e.length===0?0:e.reduce((s,r)=>{let o=_l[r.severity]??.2,a=n.applyCategoryWeight?Hl[r.category]??1:1;return s+o*a},0)/Math.max(1,i)}function Gl(e){if(e.length===0)return[];let i=e.map(t=>rt(t).split("/").filter(Boolean)),n=0;for(;;){let t=i[0][n];if(!t)break;if(i.every(s=>s[n]===t)){n+=1;continue}break}return i.map(t=>{let s=t.slice(n);return s.length>0?s.join("/"):t.join("/")})}function Dt(e,i={}){let n=i.includeTests??!1,t=i.includeGenerated??!1,s={includeTests:n,includeGenerated:t},r=(i.fileInventory||[]).filter(F=>Zi(F.file,s)),o=(i.hotFiles||[]).filter(F=>Zi(F.file,s)),a=i.reportAnalysis||null,l=e.filter(F=>zl(F,s)),c=ql(l,r),u=Math.max(1,c.size),d=r.flatMap(F=>F.functions||[]),f=Math.max(1,d.length),p={architecture:l.filter(F=>(st[F.category]||"unmapped")==="architecture"),codeQuality:l.filter(F=>(st[F.category]||"unmapped")==="code-quality"),deadCode:l.filter(F=>(st[F.category]||"unmapped")==="dead-code"),testQuality:l.filter(F=>(st[F.category]||"unmapped")==="test-quality")},g=l.filter(F=>F.severity==="critical"||F.severity==="high"),m=[],S=p.architecture.filter(F=>F.severity==="critical"||F.severity==="high"),h=Qe(p.architecture,u,{applyCategoryWeight:!0}),y=Qe(S,u,{applyCategoryWeight:!0}),D=Qe(p.architecture.filter(F=>F.category==="dependency-cycle"||F.category==="cycle-cluster"),u,{applyCategoryWeight:!0}),b=[...o].sort((F,pe)=>pe.riskScore-F.riskScore).slice(0,8),k=Math.min(1,nt(b.map(F=>Math.max(0,F.riskScore)))/100),C=a?.strongestGraphSignal?.confidence==="high"?3:a?.strongestGraphSignal?.confidence==="medium"?1:0,A=Ne(100-ee(h,24,1.35)-ee(y,22,1.9)-ee(D,16,2.2)-ee(k,12,1.3)+C);m.push({aspect:"architecture-structure",label:"Architecture & Structure",weight:30,score:A,grade:ve(A),confidence:Ve(p.architecture.length),rationale:"Rates structural integrity using architecture findings, severity concentration, cycle pressure, and hotspot intensity, then tempers it with AI graph-signal confidence.",signals:[{label:"Architecture findings / file",value:h.toFixed(2),effect:p.architecture.length>0?"negative":"neutral"},{label:"Severe architecture findings",value:y.toFixed(2),effect:S.length>0?"negative":"neutral"},{label:"Hotspot pressure (avg risk top files)",value:nt(b.map(F=>F.riskScore)).toFixed(1),effect:b.length>0?"negative":"neutral"}]});let M=[...c],E=Gl(M),_=E.map(F=>rt(F).split("/").filter(Boolean).length),K=nt(_),V=new Map,se=new Set,fe=/^(util|utils|common|shared|misc|helper|helpers|tmp|temp)$/i;for(let F of E){let dt=rt(F).split("/").filter(Boolean),ut=dt[0]||".";V.set(ut,(V.get(ut)||0)+1);for(let To of dt.slice(0,-1))se.add(To)}let H=V.size===0?0:Math.max(...V.values())/u,te=se.size===0?0:[...se].filter(F=>fe.test(F)).length/se.size,ye=Ne(100-ee(Math.max(0,(K-4)/3),20,1.3)-ee(Math.max(0,H-.55),18,2)-ee(te,24,2.2));m.push({aspect:"folder-topology",label:"Folder Topology",weight:15,score:ye,grade:ve(ye),confidence:Ve(M.length),rationale:"Rates how navigable the folder model is by blending depth balance, top-level concentration, and reliance on vague utility/common directories.",signals:[{label:"Average path depth",value:K.toFixed(1),effect:K>6?"negative":"neutral"},{label:"Dominant root share",value:`${Math.round(H*100)}%`,effect:H>.65?"negative":"neutral"},{label:"Vague directory ratio",value:`${Math.round(te*100)}%`,effect:te>.2?"negative":"neutral"}]});let xe=/^(foo|bar|baz|tmp|temp|data|value|handler|util|helper|thing|stuff|fn|func)$/i,O=/^(utils?|helpers?|common|shared|misc|tmp|temp|new|old|types?)$/i,j=d.map(F=>F.name||F.nameHint||"").filter(F=>F.length>0),X=j.filter(F=>F==="<anonymous>"||F==="default").length,re=j.filter(F=>F!=="<anonymous>"&&F!=="default"),P=re.filter(F=>xe.test(F)).length,oe=re.filter(F=>F.length<=2).length,ce=M.map(F=>He.basename(F,He.extname(F))),Ae=ce.filter(F=>O.test(F)).length,ze=Ne(100-ee(X/f,30,2.3)-ee(P/Math.max(1,re.length),24,2)-ee(Ae/u,15,1.8)-ee(oe/Math.max(1,re.length),10,1.8));m.push({aspect:"naming-quality",label:"Naming Quality",weight:15,score:ze,grade:ve(ze),confidence:Ve(d.length),rationale:"Rates naming clarity by balancing anonymous/generic function names, short ambiguous names, and generic file basenames.",signals:[{label:"Anonymous function share",value:`${Math.round(X/f*100)}%`,effect:X>0?"negative":"neutral"},{label:"Generic function names",value:String(P),effect:P>0?"negative":"neutral"},{label:"Generic file names",value:String(Ae),effect:Ae>0?"negative":"neutral"}]});let xo=/(^|\/)(common|shared|utils?|lib|core)(\/|$)/i,ke=r.filter(F=>xo.test(F.file.replace(/\\/g,"/"))),Eo=new Set(ke.map(F=>F.file)),ct=l.filter(F=>Kl(F,Eo)),wo=ct.filter(F=>F.severity==="critical"||F.severity==="high"),Bt=nt(ke.map(F=>{let pe=F.symbolUsageSummary?.internalImportCount??F.dependencyProfile.importedSymbols.filter(ut=>!!ut.resolvedModule).length,dt=F.symbolUsageSummary?.declaredExportCount??F.dependencyProfile.declaredExports.length;return pe/(dt+1)})),ds=ke.length===0?88:Ne(100-ee(ct.length/ke.length,24,1.6)-ee(wo.length/ke.length,28,2.2)-ee(Bt,18,1.5));m.push({aspect:"common-layer-health",label:"Common/Shared Layer Health",weight:15,score:ds,grade:ve(ds),confidence:Ve(ke.length),rationale:ke.length===0?"No explicit common/shared layer was detected, so this aspect is neutral-positive by default.":"Rates whether shared/common code stays stable and lightweight by combining finding density, severe issue concentration, and internal dependency pressure.",signals:[{label:"Shared files",value:String(ke.length),effect:ke.length===0?"neutral":"positive"},{label:"Shared-layer findings",value:String(ct.length),effect:ct.length>0?"negative":"neutral"},{label:"Shared import pressure",value:Bt.toFixed(2),effect:Bt>1?"negative":"neutral"}]});let zt=[...p.codeQuality,...p.deadCode,...p.testQuality],vo=new Set(["test-no-assertion","low-assertion-density","excessive-mocking","missing-test-cleanup","focused-test","fake-timer-no-restore","missing-mock-restoration"]),Kt=l.filter(F=>vo.has(F.category)),Ut=nt(d.map(F=>F.cognitiveComplexity||F.complexity||0)),us=Qe(zt,u,{applyCategoryWeight:!0}),Fo=Qe(g,u),ko=Qe(Kt,u,{applyCategoryWeight:!0}),fs=Ne(100-ee(us,20,1.3)-ee(Fo,22,1.8)-ee(Math.max(0,(Ut-8)/12),22,1.4)-ee(ko,12,1.5));m.push({aspect:"maintainability-evolvability",label:"Maintainability & Evolvability",weight:15,score:fs,grade:ve(fs),confidence:Ve(zt.length),rationale:"Rates how safely the codebase can evolve by blending quality/dead-code/test debt density, severe issue concentration, and cognitive complexity pressure.",signals:[{label:"Maintainability findings / file",value:us.toFixed(2),effect:zt.length>0?"negative":"neutral"},{label:"Average cognitive complexity",value:Ut.toFixed(1),effect:Ut>12?"negative":"neutral"},{label:"Test debt findings",value:String(Kt.length),effect:Kt.length>0?"negative":"neutral"}]});let Ke=new Map;for(let F of ce){let pe=Ul(F);Ke.set(pe,(Ke.get(pe)||0)+1)}let qt=Ke.size===0?1:Math.max(...Ke.values())/u,ps=M.filter(F=>/\.(ts|tsx)$/i.test(F)).length,gs=M.filter(F=>/\.(js|jsx|mjs|cjs)$/i.test(F)).length,ms=Math.min(ps,gs)/u*2,hs=Ne(100-ee(1-qt,24,2)-ee(ms,12,1.6)-ee(Ae/u,10,1.6));m.push({aspect:"codebase-consistency",label:"Codebase Consistency",weight:10,score:hs,grade:ve(hs),confidence:Ve(M.length),rationale:"Rates naming/structure consistency with soft penalties for mixed filename styles, mixed TS/JS surface area, and generic file naming concentration.",signals:[{label:"Dominant naming style",value:`${Math.round(qt*100)}%`,effect:qt>=.7?"positive":"negative"},{label:"TS/JS mix ratio",value:`${Math.round(Math.min(ps,gs)/u*100)}%`,effect:ms>.5?"negative":"neutral"},{label:"Detected file naming styles",value:String(Ke.size),effect:Ke.size>3?"negative":"neutral"}]});let Co=m.reduce((F,pe)=>F+pe.weight,0)||1,ys=m.reduce((F,pe)=>F+pe.score*pe.weight,0)/Co;return{model:"hybrid-ai-structure-v1",overallScore:Ne(ys),overallGrade:ve(Ne(ys)),aspects:m}}function it(e,i){if(e<=0)return 0;let n=new Set;for(let s of i){s.file&&n.add(s.file);for(let r of s.files??[])n.add(r)}if(n.size===0)return e;let t=Math.max(1,Math.ceil(e*.1));return Math.max(t,Math.min(e,n.size))}function Wl(e,i,n){let t=(c,u,d)=>Xi(c?.severityBreakdown??Fe(u),d),s=it(e,n.architectureFindings),r=it(e,n.codeQualityFindings),o=it(e,n.deadCodeFindings),a=it(e,n.securityFindings),l=it(e,n.testQualityFindings);return{overallHealth:Xi(i.severityBreakdown,e),archHealth:t(n.archStats,n.architectureFindings,s),qualHealth:t(n.qualStats,n.codeQualityFindings,r),deadHealth:t(n.deadStats,n.deadCodeFindings,o),secHealth:t(n.secStats,n.securityFindings,a),testHealth:t(n.testStats,n.testQualityFindings,l)}}function ve(e){return e>=80?"A":e>=60?"B":e>=40?"C":e>=20?"D":"F"}function Vl(e){let i=Object.values(B).flat();return e?i.filter(n=>e.has(n)):i}function Rt(e,i,n,t={}){let s=new Map;for(let l of t.hotFiles||[])s.set(l.file,l.riskScore);let r=Vl(n),o=new Set(r);for(let l of e)o.has(l.category)||(!n||n.has(l.category))&&(r.push(l.category),o.add(l.category));let a=new Map;for(let l of e)a.has(l.category)||a.set(l.category,[]),a.get(l.category).push(l);return r.map(l=>{let c=a.get(l)||[],u=Fe(c),d=new Set;for(let b of c){b.file&&d.add(b.file);for(let k of b.files??[])d.add(k)}let f=d.size>0?Math.max(1,d.size):Math.max(1,i),p=Xi(u,f),g=0,m=0;for(let b of d){let k=s.get(b)||0;k<=0||(g+=1,m=Math.max(m,k))}let S=d.size>0?g/d.size:0,h=m>=90?10:m>=75?7:m>=60?4:2,y=g===0?0:Math.min(20,Math.round(S*10+h)),D=Math.max(0,p-y);return{category:l,pillar:st[l]||"unmapped",findings:c.length,affectedFiles:d.size,hotspotHits:g,hotspotMaxRisk:m,contextPenalty:y,severityBreakdown:u,score:D,grade:ve(D)}}).sort((l,c)=>l.score!==c.score?l.score-c.score:l.findings!==c.findings?c.findings-l.findings:l.category.localeCompare(c.category))}function Ql(e,i,n){e.push(`## Health Scores
|
|
128
|
+
`),e.push("| Pillar | Score | Grade |"),e.push("|--------|-------|-------|");let t=(s,r,o)=>{if(!oo(r,n)){e.push(`| ${s} | \u2014 | skipped |`);return}e.push(`| ${s} | ${o}/100 | ${ve(o)} |`)};e.push(`| **Overall** | **${i.overallHealth}/100** | **${ve(i.overallHealth)}** |`),t("Architecture","architecture",i.archHealth),t("Code Quality","code-quality",i.qualHealth),t("Dead Code & Hygiene","dead-code",i.deadHealth),t("Security","security",i.secHealth),t("Test Quality","test-quality",i.testHealth),e.push("")}function Jl(e,i){e.push(`## Feature Scores
|
|
129
|
+
`),e.push(`Per-category scoring for all active features (or all categories when unfiltered).
|
|
130
|
+
`),e.push("| Category | Pillar | Findings | Affected Files | Hotspot Hits | Context Penalty | Score | Grade |"),e.push("|----------|--------|----------|----------------|--------------|-----------------|-------|-------|");for(let n of i)e.push(`| \`${n.category}\` | ${n.pillar} | ${n.findings} | ${n.affectedFiles} | ${n.hotspotHits} | -${n.contextPenalty} | ${n.score}/100 | ${n.grade} |`);e.push("")}function Yl(e,i){e.push(`## AI + Structure Ratings
|
|
131
|
+
`),e.push(`Hybrid, soft-signal scoring that blends structural findings with architecture context, naming quality, folder topology, and shared-layer health.
|
|
132
|
+
`),e.push(`**Overall Hybrid Rating**: ${i.overallScore}/100 (${i.overallGrade}) `),e.push(`**Model**: \`${i.model}\`
|
|
133
|
+
`),e.push("| Aspect | Weight | Score | Grade | Confidence | Why it scored this way |"),e.push("|--------|--------|-------|-------|------------|------------------------|");for(let n of i.aspects)e.push(`| ${n.label} | ${n.weight}% | ${n.score}/100 | ${n.grade} | ${n.confidence} | ${n.rationale} |`);e.push("")}function Xl(e,i,n){return(t,s,r,o,a)=>{if(!oo(t,i)){e.push(`> skipped by feature filter
|
|
134
|
+
`);return}if(o&&n[o]){e.push(`> ${s} findings (score: ${r}/100) \u2014 see [\`${a}\`](./${n[o]})
|
|
135
|
+
`);return}if(a){e.push(`> ${s} findings (score: ${r}/100) \u2014 no \`${a}\` written for this scan
|
|
136
|
+
`);return}e.push(`> ${s} findings (score: ${r}/100)
|
|
137
|
+
`)}}function Zl(e,i){let{allFindings:n,overallFindingStats:t,agentOutput:s}=i,r=t.totalFindings||s?.totalBeforeTruncation,o=s?.droppedCategories;if(r&&r>n.length&&(e.push(`> **Truncated**: Showing ${n.length} of ${r} findings (\`--findings-limit ${n.length}\`).`),o&&o.length>0&&e.push(`> Dropped categories: ${o.map(a=>`\`${a}\``).join(", ")}`),e.push("")),i.activeFeatures){let a=Ol(i.activeFeatures);e.push(`> **Features filter**: \`--features=${a.join(",")}\``),e.push("")}if(i.scope&&i.scope.length>0){let a=i.scope.map(l=>He.relative(i.root,l)).filter(Boolean);if(a.length>0){let l=a.map(c=>`\`${c}\``).join(", ");if(i.scopeSymbols&&i.scopeSymbols.size>0){let c=[];for(let[u,d]of i.scopeSymbols){let f=He.relative(i.root,u);c.push(...d.map(p=>`\`${f}:${p}\``))}l=c.join(", ")}e.push(`> **Scoped scan**: Only showing findings for: ${l}`),e.push("")}}i.semanticEnabled&&(e.push("> **Semantic analysis**: TypeChecker + LanguageService enabled (14 additional categories)"),e.push(""))}function ec(e,i){let n=so(i);if(n.length!==0){e.push(`## Top Concern Tags
|
|
138
|
+
`),e.push("Searchable tags across all findings \u2014 use to filter `findings.json` with `jq`.\n");for(let{tag:t,count:s}of n.slice(0,12))e.push(`- \`${t}\`: ${s} findings`);e.push("")}}function tc(e,i){e.push(`## Analysis Signals
|
|
139
|
+
`),e.push(`- **Graph Signal**: ${i.strongestGraphSignal?.summary||"No dominant graph signal in this scan."}`),e.push(`- **AST Signal**: ${i.strongestAstSignal?.summary||"No dominant AST signal in this scan."}`),e.push(`- **Combined Interpretation**: ${i.combinedInterpretation?.summary||"No combined interpretation available yet."}`),e.push(`- **Confidence**: ${i.combinedInterpretation?.confidence||i.strongestGraphSignal?.confidence||i.strongestAstSignal?.confidence||"low"}`);let n=i.recommendedValidation?`${i.recommendedValidation.summary} (tools: ${i.recommendedValidation.tools.join(" -> ")})`:"Use Octocode local tools to confirm the strongest signal before presenting it as fact.";e.push(`- **Recommended Validation**: ${n}`);let t=i.graphSignals.find(s=>s.kind==="mega-folder-cluster");if(t&&e.push(`- **Structural Layout Alert**: ${t.summary}`),i.investigationPrompts.length>0){e.push(""),e.push("**Investigation Prompts**");for(let s of i.investigationPrompts.slice(0,4))e.push(`- ${s}`)}e.push("")}function nc(e,i,n){let t=n.some(s=>s.severity==="critical"||s.severity==="high");e.push(`## Agent Instructions \u2014 Validate Before Presenting
|
|
140
|
+
`),e.push(`> **Core rule**: Findings are hypotheses from deterministic AST/graph detectors. Validate with Octocode local + LSP tools before presenting any finding as fact.
|
|
141
|
+
`),e.push(`### Triage Order
|
|
142
|
+
`),e.push("1. **This file first** \u2014 health scores + analysis signals drive triage priority"),t?e.push('2. **High/critical findings** \u2014 filter `findings.json`: `jq \'.optimizationFindings[] | select(.severity == "critical" or .severity == "high")\' findings.json`'):e.push("2. **Findings by severity** \u2014 start from the top of `findings.json` (already sorted by severity)"),e.push("3. **Pillar JSONs** \u2014 drill into `architecture.json`, `code-quality.json`, etc. only for categories that need investigation"),e.push("4. **`file-inventory.json`** \u2014 per-file deep dives: functions, flows, `effectProfile`, `cfgFlags`, `dependencyProfile`"),e.push(""),e.push(`### Validation Tool Chain
|
|
143
|
+
`),e.push("Each finding includes `lspHints[]`, `correlatedSignals[]`, and `recommendedValidation`. Use them.\n"),e.push("```"),e.push("Finding \u2192 localSearchCode (get lineHint) \u2192 LSP tool \u2192 localGetFileContent \u2192 verdict"),e.push("```\n"),e.push("| Step | Tool | Purpose |"),e.push("|------|------|---------|"),e.push("| 1. Search | `localSearchCode(pattern, path)` | **Always first** \u2014 get `lineHint` for LSP. Never guess lineHint. |"),e.push("| 2. Locate | `lspGotoDefinition(lineHint)` | Jump to definition across files |"),e.push("| 3. Consumers | `lspFindReferences(lineHint)` | Count usages, split test/prod with `includePattern`/`excludePattern` |"),e.push("| 4. Call flow | `lspCallHierarchy(lineHint, incoming/outgoing)` | Trace call chains \u2014 **functions only**, fails on types/vars |"),e.push("| 5. Read code | `localGetFileContent(path, matchString=...)` | Confirm code at reported location |"),e.push("| 6. AST proof | `ast/search.js -p <pattern> --root <path>` | Structural proof on **live source** \u2014 zero false positives |"),i.astTrees&&e.push("| 7. AST triage | `ast/tree-search.js -i <scan-dir> -k <Kind>` | Fast triage on scan snapshot \u2014 `-k FunctionDeclaration`, `-p 'IfStatement\\|ForStatement'`, `--file` filter, `-C 2` context |"),e.push(""),e.push(`### False Positive Checklist
|
|
144
|
+
`),e.push(`Before reporting a finding to the user:
|
|
145
|
+
`),e.push("- [ ] Ran `lspHints[]` from the finding \u2014 result matches expectation?"),e.push("- [ ] Code exists at reported `file:lineStart` \u2014 confirmed with `localGetFileContent`?"),e.push("- [ ] Pattern confirmed in live source \u2014 `ast/search.js -p` or `localSearchCode`?"),e.push("- [ ] Not in generated, vendored, or test-only code?"),e.push("- [ ] `correlatedSignals[]` \u2014 multiple signals on same file strengthen confidence"),e.push("- [ ] Consumer count verified with `lspFindReferences` \u2014 matches claimed impact?"),e.push(""),e.push("**Rate each finding**: `confirmed` (evidence supports) \xB7 `dismissed` (explain why) \xB7 `uncertain` (state what's missing)\n")}function ic(e,i){if(!(!i||i.length===0)){e.push(`## Change Risk Hotspots
|
|
146
|
+
`),e.push(`Files most dangerous to change \u2014 high fan-in, complexity, or cycle membership.
|
|
147
|
+
`),e.push("| File | Risk | Fan-In | Fan-Out | Complexity | Exports | Cycle | Critical Path |"),e.push("|------|------|--------|---------|------------|---------|-------|---------------|");for(let n of i.slice(0,15))e.push(`| \`${n.file}\` | ${n.riskScore} | ${n.fanIn} | ${n.fanOut} | ${n.complexityScore} | ${n.exportCount} | ${n.inCycle?"Y":"-"} | ${n.onCriticalPath?"Y":"-"} |`);e.push("")}}function sc(e,i){let{architectureFindings:n,codeQualityFindings:t,deadCodeFindings:s,securityFindings:r,testQualityFindings:o}=i,{qualStats:a,deadStats:l,secStats:c,testStats:u}=i,{qualHealth:d,deadHealth:f,secHealth:p,testHealth:g}=i,{renderPillarCategories:m,pushPillarSummary:S}=i;e.push(`## Code Quality
|
|
148
|
+
`),S("code-quality",a?.totalFindings??t.length,d,"codeQuality","code-quality.json"),m("code-quality",t),e.push(`## Dead Code & Hygiene
|
|
149
|
+
`),S("dead-code",l?.totalFindings??s.length,f,"deadCode","dead-code.json"),m("dead-code",s),e.push(`## Security
|
|
150
|
+
`),S("security",c?.totalFindings??r.length,p,"security","security.json"),m("security",r),e.push(`## Test Quality
|
|
151
|
+
`),S("test-quality",u?.totalFindings??o.length,g,"testQuality","test-quality.json"),m("test-quality",o);let h=n.filter(y=>y.category==="untested-critical-code").length;h>0&&(u?.totalFindings??o.length)===0&&e.push(`> **Note**: Test Quality reflects analyzed test files only. ${h} modules flagged as \`untested-critical-code\` (architecture pillar) have no test coverage \u2014 use \`--include-tests\` for test-quality analysis.
|
|
152
|
+
`)}function rc(e,i){let n=i?.topRecommendations??[];if(n.length>0){e.push(`## Top Recommendations
|
|
153
|
+
`);for(let t of n.slice(0,10))e.push(`- **[${t.severity.toUpperCase()}]** \`${t.file}\` \u2014 ${t.title} *(${t.category})* `);e.push("")}}function oc(e,i,n,t,s,r){let o=He.resolve(i,n.astTrees),a=jl(o);e.push("## AST Trees (`ast-trees.txt`)\n"),e.push("Compact indented text format \u2014 each node is `Kind[startLine:endLine]`, nesting = indentation.\n"),e.push(`Run these commands from the skill directory. Current scan: \`${s}\`.
|
|
154
|
+
`),e.push("```"),e.push("SourceFile[1:152]"),e.push(" ImportDeclaration[1]"),e.push(" FunctionDeclaration[3:20]"),e.push(" Block[4:19]"),e.push(" IfStatement[5:12] ..."),e.push("```\n"),e.push(`**Smart navigation:**
|
|
155
|
+
`),e.push(`- Find functions: \`node scripts/ast/tree-search.js -i ${a} -k function_declaration --limit 25\``),e.push(`- Find classes: \`node scripts/ast/tree-search.js -i ${a} -k class_declaration --limit 25\``),e.push(`- Find control flow: \`node scripts/ast/tree-search.js -i ${a} -p 'IfStatement|SwitchStatement|ForStatement|WhileStatement' --limit 25\``),e.push(`- Narrow to one file: \`node scripts/ast/tree-search.js -i ${a} --file "${r}" -k function_declaration --limit 10\``),e.push(`- Raw text fallback: \`rg 'FunctionDeclaration|IfStatement' ${a}\``),e.push("")}function ac(e,i,n){e.push(`## Output Files
|
|
156
|
+
`),e.push("| File | Size | Description |"),e.push("|------|------|-------------|");let t={summary:"Scan metadata, agent output, parse errors",architecture:"Dependency graph, cycles, critical paths, architecture findings",codeQuality:"Duplicate detection, complexity, god modules/functions",deadCode:"Dead files/exports/re-exports, unused deps, boundary violations",fileInventory:"Per-file function/flow/dependency details",findings:"All findings across all categories (master list)",graph:"Mermaid dependency graph",astTrees:"AST tree snapshots (compact indented text \u2014 grep/regex friendly)",summaryMd:"This file \u2014 human-readable overview"};for(let[s,r]of Object.entries(n)){let o="\u2014";try{o=ro(Ll.statSync(He.join(i,r)).size)}catch{o="\u2014"}e.push(`| [\`${r}\`](./${r}) | ${o} | ${t[s]||s} |`)}e.push("")}var st,_l,Hl,ot=N(()=>{"use strict";G();ge();st=Object.entries(B).reduce((e,[i,n])=>{for(let t of n)e[t]=i;return e},{});_l={critical:1,high:.75,medium:.45,low:.2,info:.05},Hl={"dependency-critical-path":.45,"broker-module":.55,"bridge-module":.55,"distance-from-main-sequence":.6,"over-abstraction":.65,"concrete-dependency":.65,"move-to-caller":.35,"similar-function-body":.55,"dead-export":.65,"semantic-dead-export":.6}});function lc(e){let i=e.topLevelEffects||[];if(i.length===0)return;let n={},t=0,s=null,r=-1;for(let o of i)n[o.kind]=(n[o.kind]||0)+1,t+=o.weight,o.weight>r&&(r=o.weight,s=o.kind);return{totalEffects:i.length,totalWeight:t,byKind:n,highestRisk:s}}function cc(e){let i=e.dependencyProfile.importedSymbols.filter(t=>!!t.resolvedModule),n=i.length===0?null:[...i.reduce((t,s)=>{let r=s.resolvedModule||s.sourceModule;return t.set(r,(t.get(r)||0)+1),t},new Map).entries()].sort((t,s)=>s[1]-t[1])[0]?.[0]||null;return{declaredExportCount:e.dependencyProfile.declaredExports.length,importedSymbolCount:e.dependencyProfile.importedSymbols.length,internalImportCount:i.length,externalImportCount:e.dependencyProfile.externalDependencies.length,reExportCount:e.dependencyProfile.reExports.length,dominantInternalDependency:n}}function dc(e){let i=e.file.replace(/\\/g,"/").toLowerCase(),n=[],t=(s,r,o)=>{n.push({role:s,confidence:r,reasons:o})};if(/(^|\/)(index|main|app|server|cli)\.[mc]?[jt]sx?$/.test(i)&&t("entrypoint","high",["path matches a conventional entrypoint filename"]),/(^|\/)(components|ui|pages|screens)\//.test(i)&&t("ui","high",["path indicates UI-facing code"]),/(^|\/)(routes|controllers|handlers|http|api)\//.test(i)&&t("transport","medium",["path indicates controller, handler, or API transport code"]),/(^|\/)(service|services|use-cases|usecases)\//.test(i)&&t("service","medium",["path indicates orchestration or service logic"]),/(^|\/)(repo|repos|repository|repositories|db|persistence)\//.test(i)&&t("persistence","high",["path indicates persistence or repository code"]),(e.topLevelEffects?.length||0)>0&&t("runtime-bootstrap","medium",["module has import-time side effects"]),e.dependencyProfile.declaredExports.length>=8&&e.dependencyProfile.importedSymbols.length<=2&&t("shared-utility","medium",["exports many symbols and imports little internal behavior"]),n.length!==0)return n.slice(0,3)}function uc(e){let i=(e.inputSources||[]).some(o=>o.hasValidation),n=!!e.testProfile?.setupCalls.some(o=>o.kind==="afterAll"||o.kind==="afterEach"),t=e.functions.reduce((o,a)=>o+a.returns,0),s=e.functions.reduce((o,a)=>o+a.awaits,0),r=(e.topLevelEffects?.length||0)>0;return{hasValidationChecks:i,hasCleanupHooks:n,exitPointCount:t,asyncBoundaryCount:s,hasTopLevelEffects:r}}function At(e,i={}){let{flowEnabled:n=!1}=i;return e.map(t=>({...t,effectProfile:t.effectProfile||lc(t),symbolUsageSummary:t.symbolUsageSummary||cc(t),boundaryRoleHints:t.boundaryRoleHints||dc(t)||[],cfgFlags:n?t.cfgFlags||uc(t):void 0}))}function fc(e){return["dependency-cycle","dependency-critical-path","architecture-sdp-violation","high-coupling","god-module-coupling","orphan-module","unreachable-module","cycle-cluster","broker-module","bridge-module","mega-folder"].includes(e)?"graph":["layer-violation","low-cohesion","feature-envy","import-side-effect-risk","package-boundary-chatter","startup-risk-hub","unvalidated-input-sink","input-passthrough-risk","missing-test-cleanup","fake-timer-no-restore","missing-mock-restoration"].includes(e)?"hybrid":e.startsWith("dependency-")?"graph":e.startsWith("test-")||e==="focused-test"||["hardcoded-secret","eval-usage","unsafe-html","sql-injection-risk","unsafe-regex","prototype-pollution-risk","path-traversal-risk","command-injection-risk","debug-log-leakage","sensitive-data-logging"].includes(e)||["over-abstraction","concrete-dependency","circular-type-dependency","unused-parameter","deep-override-chain","interface-compliance","unused-import","orphan-implementation","shotgun-surgery","move-to-caller","narrowable-type","semantic-dead-export"].includes(e)?"hybrid":"ast"}function pc(e){return e.confidence?e.confidence:e.severity==="critical"?"high":e.analysisLens==="graph"||e.analysisLens==="hybrid"?"medium":"low"}function gc(e,i){if(!i)return;if(e.flowTrace&&e.flowTrace.length>0)return e.flowTrace;let n=e.evidence?.propagationSteps;if(!Array.isArray(n))return;let t=n.map(s=>{if(typeof s!="string")return null;let r=s.match(/^(.*?):(\d+)(?:-(\d+))?$/);return r?{file:r[1],lineStart:Number(r[2]),lineEnd:Number(r[3]||r[2]),label:"propagation step"}:null}).filter(s=>s!==null);return t.length>0?t:void 0}function mc(e){let i=e.lspHints?.[0];return i?{summary:i.expectedResult,tools:["localSearchCode",i.tool]}:e.analysisLens==="graph"?{summary:"Confirm the dependency edge or hub behavior with localSearchCode and an LSP navigation step.",tools:["localSearchCode","lspGotoDefinition"]}:e.analysisLens==="hybrid"?{summary:"Validate both the structural location and the behavioral path before presenting the claim as fact.",tools:["localSearchCode","lspCallHierarchy"]}:{summary:"Confirm the code location and inspect the matched structure before proposing a refactor.",tools:["localSearchCode"]}}function Mt(e,i,n,t,s={}){let{flowEnabled:r=!1}=s,o=new Map(i.map(d=>[d.file,d])),a=new Set(n.map(d=>d.file)),l=new Set,c=new Set;if(t){for(let d of t.sccClusters)for(let f of d.files)l.add(f);for(let d of t.chokepoints)d.onCriticalPath&&c.add(d.file)}let u=new Map;for(let d of e)u.has(d.file)||u.set(d.file,new Set),u.get(d.file).add(d.category);return e.map(d=>{let f=d.analysisLens||fc(d.category),p=o.get(d.file),g=new Set(d.correlatedSignals||[]);a.has(d.file)&&g.add("hot-file"),l.has(d.file)&&g.add("cycle-context"),c.has(d.file)&&g.add("critical-path-context"),p?.effectProfile?.totalEffects&&g.add("top-level-effects");for(let S of u.get(d.file)||new Set)S!==d.category&&g.add(`paired:${S}`);let m={category:d.category,location:`${d.file}:${d.lineStart}-${d.lineEnd}`,...d.evidence||{}};return{...d,ruleId:d.ruleId||`${f}.${d.category}`,analysisLens:f,confidence:pc({...d,analysisLens:f}),evidence:m,correlatedSignals:[...g].slice(0,8),recommendedValidation:d.recommendedValidation||mc({...d,analysisLens:f}),flowTrace:gc({...d,evidence:m},r)}})}function De(e,i,n,t,s,r,o,a,l){return{kind:e,lens:i,title:n,summary:t,confidence:s,score:r,files:o,categories:a,evidence:l}}function Pt(e,i,n,t){let s=new Map;for(let h of e)s.has(h.file)||s.set(h.file,new Set),s.get(h.file).add(h.category);let r=[],o=[];if(t?.chokepoints.length){let h=t.chokepoints[0];r.push(De("structural-chokepoint","graph","Structural chokepoint",`${h.file} concentrates dependency pressure (${h.reasons.join(", ")}).`,h.articulation?"high":"medium",h.score,[h.file],["broker-module","bridge-module"],{score:h.score,reasons:h.reasons}))}if(t?.sccClusters.length){let h=t.sccClusters[0];r.push(De("cycle-cluster","graph","Cycle cluster",`${h.id} links ${h.nodeCount} files into a single strongly connected group.`,h.nodeCount>=5?"high":"medium",h.nodeCount*6+h.edgeCount,h.files,["dependency-cycle","cycle-cluster"],{clusterId:h.id,nodeCount:h.nodeCount,hubFiles:h.hubFiles}))}if(t?.packageGraphSummary.hotspots.length){let h=t.packageGraphSummary.hotspots[0];r.push(De("package-chatter","graph","Package boundary chatter",`${h.from} and ${h.to} exchange ${h.edges} cross-package dependency edge(s).`,h.edges>=8?"high":"medium",h.edges*4,[h.from,h.to],["package-boundary-chatter"],h))}let a=e.filter(h=>h.category==="mega-folder").sort((h,y)=>{let D=Number(h.evidence?.fileCount||0);return Number(y.evidence?.fileCount||0)-D});if(a.length>0){let h=a[0],y=h.evidence||{},D=typeof y.folderPath=="string"?y.folderPath:hc(h.file),b=Number(y.fileCount||h.files.length||0),k=Number(y.concentration||0);r.push(De("mega-folder-cluster","graph","Mega folder concentration",`${D} concentrates ${b} files (${(k*100).toFixed(1)}% of analyzed production files), which is a structural decomposition risk.`,k>=.5||b>=50?"high":"medium",Math.round(b*3+k*100),h.files.length>0?h.files:[h.file],["mega-folder"],{folderPath:D,fileCount:b,concentration:k}))}for(let h of i){let y=s.get(h.file)||new Set;y.has("low-cohesion")&&y.has("feature-envy")&&o.push(De("boundary-leak-shape","ast","Boundary leak shape",`${h.file} shows both low cohesion and feature envy, suggesting the module boundary is doing multiple jobs.`,"high",90,[h.file],["low-cohesion","feature-envy"],{file:h.file})),(h.effectProfile?.totalEffects||0)>0&&y.has("import-side-effect-risk")&&o.push(De("hidden-initialization","ast","Hidden initialization logic",`${h.file} performs import-time work that matches the reported side-effect risk.`,"medium",75,[h.file],["import-side-effect-risk"],{totalEffects:h.effectProfile?.totalEffects,highestRisk:h.effectProfile?.highestRisk})),y.has("duplicate-flow-structure")&&y.has("function-optimization")&&o.push(De("orchestration-duplication","ast","Repeated orchestration shape",`${h.file} combines repeated control-flow shape with complex functions, which usually means orchestration duplication.`,"medium",70,[h.file],["duplicate-flow-structure","function-optimization"],{file:h.file}))}let l=r.sort((h,y)=>y.score-h.score)[0]||null,c=o.sort((h,y)=>y.score-h.score)[0]||null,u=null;if(l&&c){let h=l.files.find(D=>c.files.includes(D)),y=h?"high":"medium";u=De("combined-interpretation","hybrid","Combined interpretation",h?`${h} is both a structural hotspot and a suspicious code-shape hotspot, so it should be investigated first.`:`${l.title} and ${c.title} both appear in this scan, so use a hybrid investigation instead of a single-lens conclusion.`,y,Math.round((l.score+c.score)/2),h?[h]:[...new Set([...l.files,...c.files])].slice(0,4),[...new Set([...l.categories,...c.categories])],{graphKind:l.kind,astKind:c.kind,sharedFile:h||null})}else if(l||c){let h=l||c;u=De("combined-interpretation",h.lens,"Combined interpretation",h.summary,h.confidence,h.score,h.files,h.categories,h.evidence)}let d=new Set(u?.files||[]),f=new Set(u?.categories||[]),g=(e.find(h=>d.has(h.file)||f.has(h.category))||e[0])?.recommendedValidation||null,m=new Set;l&&m.add(`Inspect ${l.files[0]} first and validate the graph claim with localSearchCode plus LSP navigation.`),c&&m.add(`Use file-inventory.json for ${c.files[0]} to explain why the code shape matches the finding.`),u?.confidence==="high"?m.add("Treat the aligned graph and AST signal as an architecture priority, not just a local cleanup task."):u&&m.add("Use a hybrid investigation before proposing a refactor because the signals do not fully align yet."),n.length>0&&m.add(`Cross-check the top hotspot ${n[0].file} with the strongest architecture finding before editing code.`);let S=r.find(h=>h.kind==="mega-folder-cluster");return S&&m.add(`Map the import graph of ${S.evidence.folderPath}, identify domain clusters, and restructure with an automated migration script that moves files and rewrites import paths atomically. Validate with tsc + lint + tests after each phase.`),{graphSignals:r.sort((h,y)=>y.score-h.score),astSignals:o.sort((h,y)=>y.score-h.score),combinedSignals:u?[u]:[],strongestGraphSignal:l,strongestAstSignal:c,combinedInterpretation:u,recommendedValidation:g,investigationPrompts:[...m]}}function hc(e){let i=e.replace(/\\/g,"/"),n=i.lastIndexOf("/");return n===-1?".":i.slice(0,n)}var is=N(()=>{"use strict"});import at from"node:fs";import It from"node:path";function ss(e,i,n,t,s,r,o={}){at.mkdirSync(e,{recursive:!0});let a=(C,A)=>{at.writeFileSync(It.join(e,C),JSON.stringify(A),"utf8")},l={summary:"summary.json",architecture:"architecture.json",codeQuality:"code-quality.json",deadCode:"dead-code.json",fileInventory:"file-inventory.json",findings:"findings.json"},c=_e(t,s,r),u=i.graphAnalytics??kt(t,s,r),d=At(i.fileInventory||[],{flowEnabled:!!n.flow}),f=Mt(i.optimizationFindings||[],d,c,u,{flowEnabled:!!n.flow}),p=f.filter(C=>ao.has(C.category)),g=f.filter(C=>lo.has(C.category)),m=f.filter(C=>co.has(C.category)),S=f.filter(C=>uo.has(C.category)),h=f.filter(C=>fo.has(C.category)),y=i.reportAnalysis??Pt(f,d,c,u),D=Dt(f,{fileInventory:d,hotFiles:c,reportAnalysis:y,includeTests:n.includeTests});if(a("architecture.json",{schemaVersion:Re,generatedAt:i.generatedAt,dependencyGraph:i.dependencyGraph,dependencyFindings:i.dependencyFindings,findings:p,findingsCount:p.length,severityBreakdown:Fe(p),categoryBreakdown:Le(p),hotFiles:c,graphSignals:y.graphSignals,chokepoints:u.chokepoints,criticalHubCandidates:u.chokepoints.slice(0,10),sccClusters:n.graphAdvanced?u.sccClusters:[],packageGraphSummary:n.graphAdvanced?u.packageGraphSummary:null,packageHotspots:n.graphAdvanced?u.packageGraphSummary.hotspots:[]}),a("code-quality.json",{schemaVersion:Re,generatedAt:i.generatedAt,duplicateFlows:i.duplicateFlows,optimizationOpportunities:i.optimizationOpportunities,findings:g,findingsCount:g.length,severityBreakdown:Fe(g),categoryBreakdown:Le(g)}),a("dead-code.json",{schemaVersion:Re,generatedAt:i.generatedAt,findings:m,findingsCount:m.length,severityBreakdown:Fe(m),categoryBreakdown:Le(m)}),S.length>0&&(a("security.json",{schemaVersion:Re,generatedAt:i.generatedAt,findings:S,findingsCount:S.length,severityBreakdown:Fe(S),categoryBreakdown:Le(S)}),l.security="security.json"),h.length>0&&(a("test-quality.json",{schemaVersion:Re,generatedAt:i.generatedAt,findings:h,findingsCount:h.length,severityBreakdown:Fe(h),categoryBreakdown:Le(h)}),l.testQuality="test-quality.json"),a("file-inventory.json",{schemaVersion:Re,generatedAt:i.generatedAt,fileInventory:d,fileCount:d.length}),a("findings.json",{schemaVersion:Re,generatedAt:i.generatedAt,optimizationFindings:f,totalFindings:f.length}),n.graph){let C=Nt(t,s,r,o);at.writeFileSync(It.join(e,"graph.md"),C,"utf8"),l.graph="graph.md"}i.astTrees&&(at.writeFileSync(It.join(e,"ast-trees.txt"),Gs(i.astTrees,i.generatedAt),"utf8"),l.astTrees="ast-trees.txt");let b={schemaVersion:Re,generatedAt:i.generatedAt,repoRoot:i.repoRoot,options:i.options,parser:i.parser,summary:i.summary,agentOutput:i.agentOutput,analysisSummary:{graphSignals:y.graphSignals,astSignals:y.astSignals,strongestGraphSignal:y.strongestGraphSignal,strongestAstSignal:y.strongestAstSignal,combinedSignals:y.combinedSignals,recommendedValidation:y.recommendedValidation},strongestGraphSignal:y.strongestGraphSignal,strongestAstSignal:y.strongestAstSignal,combinedSignals:y.combinedSignals,featureScores:Rt(f,i.summary.totalFiles??0,n.features,{hotFiles:c}),qualityRating:D,recommendedValidation:y.recommendedValidation,investigationPrompts:y.investigationPrompts,parseErrors:i.parseErrors,outputFiles:l};a("summary.json",b);let k=ns({dir:e,report:i,outputFiles:l,architectureFindings:p,codeQualityFindings:g,deadCodeFindings:m,hotFiles:c,activeFeatures:n.features,scope:n.scope,root:n.root,scopeSymbols:n.scopeSymbols,semanticEnabled:n.semantic,securityFindings:S,testQualityFindings:h,reportAnalysis:y,fileInventory:d});return at.writeFileSync(It.join(e,"summary.md"),k,"utf8"),l.summaryMd="summary.md",a("summary.json",{...b,outputFiles:l}),l}function Nt(e,i,n,t={}){let s=[];s.push(`# Dependency Graph
|
|
157
|
+
`),s.push(`## Module Dependency Map
|
|
158
|
+
`),s.push("```mermaid"),s.push("graph LR");let r=new Set((i.criticalModules||[]).map(f=>f.file)),o=new Set;for(let f of i.cycles||[])for(let p of f.path)o.add(p);let a=f=>{let p=f.split("/");return p.length<=2?p.join("/"):`${p[0]}/\u2026/${p[p.length-1]}`},l=f=>f.replace(/[^a-zA-Z0-9]/g,"_"),c=new Set,u=new Set,d;if(t.focus)d=yc(t.focus,t.focusDepth??1,e),s.push(`%% Focus: ${t.focus} (depth=${t.focusDepth??1})`);else{let f=[...(i.outgoingTop||[]).slice(0,15),...(i.inboundTop||[]).slice(0,15),...(i.criticalModules||[]).slice(0,10)];d=new Set(f.map(p=>p.file));for(let p of(i.cycles||[]).slice(0,5))for(let g of p.path)d.add(g)}if(t.collapse!=null&&t.collapse>0){let f=Sc(d,e,t.collapse);return bc(f,s)}for(let f of d){let p=l(f);if(c.has(p))continue;c.add(p);let g=a(f);o.has(f)?s.push(` ${p}["\u{1F534} ${g}"]`):r.has(f)?s.push(` ${p}["\u26A0\uFE0F ${g}"]`):s.push(` ${p}["${g}"]`)}for(let f of d){let p=e.outgoing.get(f)||new Set;for(let g of p){if(!d.has(g))continue;let m=`${l(f)}-->${l(g)}`;u.has(m)||(u.add(m),o.has(f)&&o.has(g)?s.push(` ${l(f)} -. cycle .-> ${l(g)}`):s.push(` ${l(f)} --> ${l(g)}`))}}if(s.push("```\n"),i.cycles?.length>0){s.push(`## Dependency Cycles
|
|
159
|
+
`),s.push("```mermaid"),s.push("graph LR");for(let[f,p]of i.cycles.slice(0,10).entries())for(let g=0;g<p.path.length-1;g++){let m=l(p.path[g]),S=l(p.path[g+1]);s.push(` ${m}["${a(p.path[g])}"] -. "cycle ${f+1}" .-> ${S}["${a(p.path[g+1])}"]`)}s.push("```\n")}if(i.criticalPaths?.length>0){s.push(`## Critical Dependency Chains
|
|
160
|
+
`),s.push("```mermaid"),s.push("graph LR");for(let f of i.criticalPaths.slice(0,8))for(let p=0;p<f.path.length-1;p++){let g=l(f.path[p]),m=l(f.path[p+1]);s.push(` ${g}["${a(f.path[p])}"] ==> ${m}["${a(f.path[p+1])}"]`)}s.push("```\n")}if(s.push(`## Summary
|
|
161
|
+
`),s.push("| Metric | Value |"),s.push("|--------|-------|"),s.push(`| Total modules | ${i.totalModules} |`),s.push(`| Total edges | ${i.totalEdges} |`),s.push(`| Root modules | ${i.rootsCount} |`),s.push(`| Leaf modules | ${i.leavesCount} |`),s.push(`| Cycles | ${i.cycles?.length||0} |`),s.push(`| Critical paths | ${i.criticalPaths?.length||0} |`),s.push(`| Test-only modules | ${i.testOnlyModules?.length||0} |`),s.push(`| Unresolved imports | ${i.unresolvedEdgeCount||0} |`),s.push(""),i.criticalModules?.length>0){s.push(`## Critical Modules (Hub Nodes)
|
|
162
|
+
`),s.push("| Module | Score | Risk | Inbound | Outbound |"),s.push("|--------|-------|------|---------|----------|");for(let f of i.criticalModules.slice(0,20))s.push(`| \`${f.file}\` | ${f.score} | ${f.riskBand||"-"} | ${f.inboundCount} | ${f.outboundCount} |`);s.push("")}if(i.testOnlyModules?.length>0){s.push(`## Test-Only Modules
|
|
163
|
+
`);for(let f of i.testOnlyModules.slice(0,20))s.push(`- \`${f.file}\``);s.push("")}return s.join(`
|
|
164
|
+
`)}function yc(e,i,n){let t=[...n.outgoing.keys()].find(o=>o===e||o.endsWith(`/${e}`));if(!t)return new Set;let s=new Set([t]),r=new Set([t]);for(let o=0;o<i;o++){let a=new Set;for(let l of r){for(let c of n.outgoing.get(l)||[])s.has(c)||(s.add(c),a.add(c));for(let c of n.incoming.get(l)||[])s.has(c)||(s.add(c),a.add(c))}if(r=a,r.size===0)break}return s}function Sc(e,i,n){let t=a=>a.split("/").slice(0,n).join("/"),s=new Set,r=new Map;for(let a of e)s.add(t(a));for(let a of e){let l=t(a);for(let c of i.outgoing.get(a)||[]){let u=t(c);if(l===u)continue;s.add(u);let d=`${l}::${u}`;r.set(d,(r.get(d)||0)+1)}}let o=[];for(let[a,l]of r){let[c,u]=a.split("::");o.push({from:c,to:u,weight:l})}return{nodes:s,edges:o}}function bc(e,i){let n=t=>t.replace(/[^a-zA-Z0-9]/g,"_");for(let t of e.nodes)i.push(` ${n(t)}["${t}"]`);for(let t of e.edges){let s=t.weight>1?`|${t.weight}|`:"";i.push(` ${n(t.from)} -->${s} ${n(t.to)}`)}return i.push("```\n"),i.push(`> Collapsed to folder depth. ${e.nodes.size} folders, ${e.edges.length} edges.
|
|
165
|
+
`),i.join(`
|
|
166
|
+
`)}var Re,ao,lo,co,uo,fo,rs=N(()=>{"use strict";is();ot();Fn();G();tt();ge();Re="1.1.0",ao=new Set(B.architecture),lo=new Set(B["code-quality"]),co=new Set(B["dead-code"]),uo=new Set(B.security),fo=new Set(B["test-quality"])});function lt(e,i){return i.some(n=>e.has(n))}function xc(e){return e?{architecture:lt(e,B.architecture),codeQuality:lt(e,B["code-quality"]),deadCode:lt(e,B["dead-code"]),security:lt(e,B.security),testQuality:lt(e,B["test-quality"])}:{architecture:!0,codeQuality:!0,deadCode:!0,security:!0,testQuality:!0}}function Ec(e,i,n,t,s,r,o,a,l){let c=_e(i,e,s),u=[()=>In(e),()=>Nn(e,i),()=>Ln(e,i,t.thresholds.criticalComplexityThreshold),()=>On(e,i),()=>ri(i,r,o),()=>oi(i,r),()=>Bn(i,t.thresholds.sdpMinDelta,t.thresholds.sdpMaxSourceInstability),()=>zn(i,t.thresholds.couplingThreshold),()=>Kn(i,t.thresholds.fanInThreshold,t.thresholds.fanOutThreshold),()=>jn(i),()=>_n(i),()=>ai(i.externalCounts,a,l),()=>li(i),()=>Zn(i,t.thresholds.barrelSymbolThreshold),()=>Wn(n),()=>Qn(i),()=>qn(i),()=>Yn(i),()=>Jn(i,c,s),()=>ei(n,i,e,c),()=>ti(i),()=>ni(i),()=>ii(i)];return t.thresholds.layerOrder.length>=2&&u.push(()=>Un(i,t.thresholds.layerOrder)),u}function wc(e,i,n,t,s,r){return[()=>ci(e),()=>di(i,t.thresholds.flowDupThreshold),()=>ui(n,t.thresholds.criticalComplexityThreshold),()=>Vn(n,t.thresholds.godFunctionStatements,t.thresholds.godFunctionMiThreshold),()=>pi(n,t.thresholds.cognitiveComplexityThreshold),()=>gi(n,t.thresholds.parameterThreshold),()=>mi(n),()=>hi(n),()=>yi(n,t.thresholds.anyThreshold),()=>Si(n,t.thresholds.halsteadEffortThreshold),()=>bi(n,t.thresholds.maintainabilityIndexThreshold),()=>xi(n),()=>Ei(n),()=>wi(n),()=>vi(n),()=>Fi(n),()=>ki(n),()=>Ci(n),()=>Ti(n),()=>Di(n),()=>$i(s,t.thresholds.similarityThreshold),()=>Ri(n,t.thresholds.deepNestingThreshold),()=>Ai(n,t.thresholds.multipleReturnThreshold),()=>Mi(n),()=>Pi(n,t.thresholds.magicStringMinOccurrences),()=>Ii(n,t.thresholds.booleanParamThreshold),()=>Ni(n),()=>Li(n,r),()=>Oi(n,s,r),...r?[()=>Gn(n,r,t.thresholds.godModuleStatements,t.thresholds.godModuleExports)]:[]]}function vc(e){return[()=>ji(e),()=>_i(e),()=>Hi(e),()=>Bi(e),()=>zi(e),()=>Ui(e),()=>qi(e),()=>Ki(e),()=>Gi(e),()=>Wi(e),()=>Vi(e),()=>Qi(e)]}function Fc(e,i){return[()=>Qr(e),()=>Jr(e),()=>Yr(e,i.thresholds.mockThreshold),()=>Xr(e),()=>Zr(e),()=>eo(e),()=>to(e),()=>no(e)]}function po(e,i,n,t,s,r,o={},a={},l=new Map,c=[],u=new Map,d=[]){let f=[],p=M=>{r.features&&!r.features.has(M.category)||f.push(M)},{production:g,test:m}=si(s),S=xc(r.features),h=[...S.architecture||S.deadCode?Ec(t,s,n,r,l,g,m,o,a):[],...S.codeQuality?wc(e,i,n,r,u,s):[],...S.security?vc(n):[],...S.testQuality?Fc(n,r):[]];for(let M of h)for(let E of M())p(E);for(let M of c)p(M);for(let M of d)p(M);let y=f.sort((M,E)=>{let _=Pe[E.severity]-Pe[M.severity];return _!==0?_:M.category<E.category?-1:M.category>E.category?1:0}),{findings:D,totalBeforeTruncation:b,droppedCategories:k}=os(y,r),{findings:C,byFile:A}=as(D);return{allFindings:y,findings:C,byFile:A,totalBeforeTruncation:b,droppedCategories:k}}function os(e,i){let n=e.length,t=new Set(e.map(l=>l.category)),s=i.findingsLimit,r=!Number.isFinite(s)||s==null?e:i.noDiversify?e.slice(0,s):es(e,s),o=new Set(r.map(l=>l.category)),a=[...t].filter(l=>!o.has(l));return{findings:r,totalBeforeTruncation:n,droppedCategories:a}}function as(e){let i=[],n=new Map;for(let[t,s]of e.entries()){let r=`AST-ISSUE-${String(t+1).padStart(4,"0")}`,o={id:r,...s};i.push(o),o.file&&(n.has(o.file)||n.set(o.file,[]),n.get(o.file).push(r))}return{findings:i,byFile:n}}var go=N(()=>{"use strict";tt();Ji();io();ot();ge();rn();Ye();Zt();cs();an();dn();fn();nn();xn();rs();ot()});var ho={};Gt(ho,{EXIT_ERROR:()=>jt,EXIT_FINDINGS:()=>Ot,EXIT_SUCCESS:()=>Lt,computeGateScore:()=>ls,main:()=>mo});import Be from"node:fs";import J from"node:path";import*as _t from"typescript";function kc(e,i){let n=tr(e,i);if(!n.length){let t=J.join(e,"package.json");if(Be.existsSync(t))try{let s=JSON.parse(Be.readFileSync(t,"utf8"));n=[{name:typeof s.name=="string"?s.name:J.basename(e),dir:e,folder:J.basename(e)}]}catch{console.error(`No packages found in ${i} and root package.json is unreadable`),process.exit(1)}else console.error(`No packages found in ${i} and no package.json in root`),process.exit(1)}return n}function Cc(e,i,n){let t=[...e.entries()].map(([o,a])=>{if(a.length<2)return null;let[l]=a,[c]=o.split("|"),u=l.name||l.kind||"<flow>",d=[...new Set(a.map(f=>f.file))];return{hash:c,signature:u,kind:l.kind,occurrences:a.length,filesCount:d.length,locations:a.slice(0,20)}}).filter(o=>o!==null).sort((o,a)=>a.occurrences-o.occurrences),s=[...i.entries()].map(([o,a])=>{if(a.length<=1)return null;let[,l]=o.split("|"),c=[...new Set(a.map(u=>u.file))];return{kind:l,occurrences:a.length,filesCount:c.length,locations:a.slice(0,20)}}).filter(o=>o!==null).sort((o,a)=>a.occurrences-o.occurrences),r=[];for(let o of t.slice(0,200))o.occurrences>=2&&r.push({type:"duplicate-function-body",message:`Identical function body for ${o.signature}`,file:o.locations[0]?.file,lineStart:o.locations[0]?.lineStart,lineEnd:o.locations[0]?.lineEnd,details:`Occurs ${o.occurrences} times in ${o.filesCount} files.`});for(let[o,a]of s.slice(0,100).entries())if(a.occurrences>=n&&r.push({type:"repeated-flow",message:`Repeated ${a.kind} control structure`,file:a.locations[0]?.file,lineStart:a.locations[0]?.lineStart,lineEnd:a.locations[0]?.lineEnd,details:`Structure appears ${a.occurrences} times across ${a.filesCount} file(s).`}),o>100)break;return{duplicateFunctions:t,redundantFlows:s,duplicateFlowHints:r}}function Tc(e,i,n,t){if(!n.semantic)return[];if(!(!n.features||[...gt].some(r=>n.features.has(r))))return[];try{let r=cr(e,i,n.root),o=or(r,n.root),a=[];for(let l of e){let c=J.resolve(n.root,l.file);try{a.push(lr(o,c,l,n.includeTests))}catch{}}return Wr(o,a,{overrideChainThreshold:n.thresholds.overrideChainThreshold,shotgunThreshold:n.thresholds.shotgunThreshold})}catch(r){return t.push({file:"<semantic>",message:`Semantic analysis failed: ${String(r?.message||r)}`}),[]}}function $c(e,i,n){if(!i.scope)return e;let t=r=>{let o=J.resolve(i.root,r);return i.scope.some(a=>{let l=J.normalize(a),c=J.normalize(o);return c===l||c.startsWith(l+J.sep)})},s=e.filter(r=>t(r.file)||(r.files?.some(t)??!1));if(i.scopeSymbols&&i.scopeSymbols.size>0){let r=[],o=[];for(let[a,l]of i.scopeSymbols){let c=J.relative(i.root,a),u=n.find(d=>d.file===c);if(!u){for(let d of l)o.push(`${c}:${d}`);continue}for(let d of l){let f=u.functions.find(g=>g.name===d);if(f){r.push({file:c,lineStart:f.lineStart,lineEnd:f.lineEnd,name:d});continue}let p=u.dependencyProfile?.declaredExports?.find(g=>g.name===d&&g.lineStart!=null&&g.lineEnd!=null);p?r.push({file:c,lineStart:p.lineStart,lineEnd:p.lineEnd,name:d}):o.push(`${c}:${d}`)}}if(o.length>0&&console.warn(`Warning: symbol scope could not resolve: ${o.join(", ")}. Falling back to file-level scope for those entries.`),r.length>0){let a=(l,c,u,d)=>l<=d&&c>=u;s=s.filter(l=>r.some(c=>l.file===c.file&&a(l.lineStart,l.lineEnd,c.lineStart,c.lineEnd)))}}return s}function Dc(e,i,n,t,s,r,o,a){console.log(`AST analysis complete: ${e.totalFiles} files, ${e.totalFunctions} functions, ${e.totalFlows} flow nodes`),e.totalDependencyFiles!==e.totalFiles&&console.log(`Dependency scan analyzed ${e.totalDependencyFiles} files (including tests where present).`),console.log(`Duplicate function bodies: ${i.length}`);for(let l of i.slice(0,20))console.log(`- ${l.kind} "${l.signature}" occurs ${l.occurrences}x in ${l.filesCount} file(s)`);console.log(`
|
|
167
|
+
Repeated control-flow structures: ${n.length}`);for(let l of n.slice(0,20))console.log(`- ${l.kind} appears ${l.occurrences}x across ${l.filesCount} file(s)`);console.log(`
|
|
168
|
+
Dependency graph: ${t.totalModules} modules, ${t.totalEdges} import edges`),t.totalModules>0&&(console.log(`- Critical chains: ${t.criticalPaths.length} (showing top ${Math.min(o.deepLinkTopN,t.criticalPaths.length)})`),console.log(`- Root modules: ${t.rootsCount}, Leaf modules: ${t.leavesCount}`),console.log(`- Test-only modules: ${t.testOnlyModules.length}`),console.log(`- Cycles: ${t.cycles.length}`)),console.log(`
|
|
169
|
+
Agent Findings: ${s.length}`);for(let l of s.slice(0,20))console.log(`- [${l.severity.toUpperCase()}] ${l.title}`),console.log(` - ${l.reason}`),console.log(` - fix: ${l.suggestedFix.strategy}`);r.length>0&&(console.log(`
|
|
170
|
+
Parse errors: ${r.length}`),r.slice(0,10).forEach(l=>{console.log(`- ${l.file}: ${l.message}`)})),console.log(`
|
|
171
|
+
Parser engine used: ${a}`)}async function Rc(e){let i;if(e)i=e;else{let{DEFAULT_OPTS:f}=await Promise.resolve().then(()=>(Qt(),$s)),p=St({args:js(process.argv.slice(2))}),g=en(p.root,p.configFile);i=g?tn(f,g,p):p}if(!i.json&&!e&&zs(),le.progress("startup","Options parsed",`root=${i.root}`),i.clearCache)return ws(i.root),console.error("Cache cleared."),null;let n=new Date().toISOString().replace(/[:.]/g,"-"),t=i.out?.endsWith(".json")??!1,s=t?null:i.out||J.join(i.root,".octocode","scan",n),r=t?i.out??null:null,o=kc(i.root,i.packageRoot),a=i.parser,l=i.parser==="tree-sitter"||i.parser==="auto"?await fr():{available:!1,error:null,parserTs:null,parserTsx:null},c=(i.parser==="tree-sitter"||i.parser==="auto")&&!!l?.available;i.parser==="tree-sitter"&&!l?.available&&(console.warn(`Tree-sitter requested but unavailable: ${l?.error||"missing parser modules"}`),console.warn("Falling back to TypeScript parser for duplicate detection."),a="typescript"),i.parser==="tree-sitter"&&l?.available&&(a="tree-sitter (primary) + typescript (dependencies)"),i.parser==="auto"&&l?.available&&(a="typescript (primary) + tree-sitter (node count)");let u={},d={};for(let f of o)try{let p=JSON.parse(Be.readFileSync(J.join(f.dir,"package.json"),"utf8"));Object.assign(u,p.dependencies||{}),Object.assign(d,p.devDependencies||{})}catch{}return le.progress("discovery",`Found ${o.length} package(s)`,o.map(f=>f.name).join(", ")),{options:i,packages:o,effectiveParser:a,useTreeSitter:c,summary:{totalPackages:o.length,totalFiles:0,totalNodes:0,totalFunctions:0,totalFlows:0,totalDependencyFiles:0,byPackage:{}},flowMap:new Map,controlMap:new Map,trees:[],fileSummaries:[],parseErrors:[],dependencyState:{files:new Set,outgoing:new Map,incoming:new Map,incomingFromTests:new Map,incomingFromProduction:new Map,externalCounts:new Map,unresolvedCounts:new Map,declaredExportsByFile:new Map,importedSymbolsByFile:new Map,reExportsByFile:new Map},packageFileStats:Object.fromEntries(o.map(f=>[f.name,{fileCount:0,nodeCount:0,functionCount:0,flowCount:0,kindCounts:{},functions:[],flows:[]}])),allPkgJsonDeps:u,allPkgJsonDevDeps:d,cacheHits:0,isLegacyMode:t,outputDir:s,outputPath:r,treeSitterAvailable:c,treeSitterError:l?.available?null:l?.error||null}}function Ac(e){let{options:i,packages:n,useTreeSitter:t,summary:s,flowMap:r,controlMap:o,trees:a,fileSummaries:l,parseErrors:c,dependencyState:u,packageFileStats:d}=e;le.progress("cache-check",i.noCache?"Cache disabled":"Loading cache");let f=i.noCache?null:xs(i.root),p=ks(i.root);for(let g of n){let m=d[g.name];m||(m={fileCount:0,nodeCount:0,functionCount:0,flowCount:0,kindCounts:{},functions:[],flows:[]},d[g.name]=m);let S=En(g.dir,i),h=En(g.dir,{...i,includeTests:!0}),y=k=>i.scope!=null&&i.scope.some(C=>{let A=J.normalize(C),M=J.normalize(k);return M===A||M.startsWith(A+J.sep)}),D=i.scope?S.filter(k=>y(k)):S,b=new Set(D);for(let k of h){let C=er(k);if(C===null){c.push({file:J.relative(i.root,k),message:"Failed to read file"});continue}let A=J.extname(k),M=_t.createSourceFile(k,C,_t.ScriptTarget.ESNext,!0,Us(A));try{let E=Ys(M,k,g.name,i,u);if(!b.has(k))continue;let _=J.relative(i.root,k),K=Be.statSync(k),V={mtimeMs:K.mtimeMs,size:K.size};if(f&&vs(f,_,V)){let O=Fs(f,_);if(O?.fileEntry){for(let[X,re]of O.flowMapEntries??[])for(let P of re)Se(r,X,P);for(let[X,re]of O.controlMapEntries??[])for(let P of re)Se(o,X,P);let j={...O.fileEntry,dependencyProfile:E};m.fileCount+=1,m.nodeCount+=j.nodeCount,m.functionCount+=j.functions.length,m.flowCount+=j.flows.length;for(let[X,re]of Object.entries(j.kindCounts))m.kindCounts[X]=(m.kindCounts[X]||0)+re;for(let X of j.functions)m.functions.push(X);O.treeEntry&&a.push(O.treeEntry),s.totalFiles+=1,s.totalNodes+=j.nodeCount,s.totalFunctions+=j.functions.length,s.totalFlows+=j.flows.length,l.push(j),Wt(p,_,V,O),e.cacheHits++;continue}}let se=new Map,fe=new Map,H=t&&i.parser==="tree-sitter",te;if(H){let O=Tn(k,C,i,g.name,{flowMap:se,controlMap:fe});if(O){let j=J.relative(i.root,k);te={package:g.name,file:j,parseEngine:"tree-sitter",nodeCount:O.nodeCount,kindCounts:{},functions:O.functions,flows:O.flows,dependencyProfile:E},O.tree&&i.emitTree&&a.push({package:g.name,file:j,tree:O.tree}),m.fileCount+=1,m.nodeCount+=O.nodeCount,m.functionCount+=O.functions.length,m.flowCount+=O.flows.length;for(let X of O.functions)m.functions.push(X)}else{let j=Yi(M,g.name,m,i,{flowMap:se,controlMap:fe},a,E);j.parserFallback="typescript (tree-sitter failed)",te=j}}else if(te=Yi(M,g.name,m,i,{flowMap:se,controlMap:fe},a,E),t)try{let O=Tn(k,C,i,g.name,null);O&&(te.treeSitterNodeCount=O.nodeCount)}catch(O){te.treeSitterError=String(O?.message||O)}for(let[O,j]of se)for(let X of j)Se(r,O,X);for(let[O,j]of fe)for(let X of j)Se(o,O,X);let ye=i.emitTree?a.find(O=>O.file===_):void 0,xe={fileEntry:te,flowMapEntries:[...se.entries()],controlMapEntries:[...fe.entries()],...ye&&{treeEntry:ye}};Wt(p,_,V,xe),s.totalFiles+=1,s.totalNodes+=te.nodeCount,s.totalFunctions+=te.functions.length,s.totalFlows+=te.flows.length,l.push(te)}catch(E){c.push({file:J.relative(i.root,k),message:String(E?.message||E)})}}s.byPackage[g.name]={files:m.fileCount,nodes:m.nodeCount,functions:m.functionCount,flows:m.flowCount,topKinds:Object.entries(m.kindCounts).sort((k,C)=>C[1]-k[1]).slice(0,8),rootPath:g.folder}}i.noCache||(Cs(p),Es(i.root,p)),e.cacheHits>0&&!i.json&&console.error(`Cache: ${e.cacheHits} hits, ${l.length-e.cacheHits} misses`),s.totalDependencyFiles=u.files.size,le.progress("parse",`Parsed ${l.length} files`,`${e.cacheHits} cache hits`)}function Mc(e){le.progress("detect","Running detectors");let{options:i,effectiveParser:n,summary:t,flowMap:s,controlMap:r,trees:o,fileSummaries:a,parseErrors:l,dependencyState:c,allPkgJsonDeps:u,allPkgJsonDevDeps:d,isLegacyMode:f,outputDir:p,outputPath:g,treeSitterAvailable:m,treeSitterError:S}=e,{duplicateFunctions:h,redundantFlows:y,duplicateFlowHints:D}=Cc(s,r,i.thresholds.flowDupThreshold),b=new Map(a.map(P=>[P.file,Kr(P,i)])),k=bn(c,b,i);le.progress("graph","Computing graph analytics");let C=kt(c,k,b),A=i.graphAdvanced?rr(C,c,a):[];le.progress("semantic",i.semantic?"Running semantic analysis":"Skipping semantic (not requested)");let M=Tc(a,c,i,l),_=po(h,y,a,k,c,i,u,d,b,M,s,A).allFindings;_=$c(_,i,a);let{findings:K,totalBeforeTruncation:V,droppedCategories:se}=os(_,i),fe=as(K),H=fe.findings,te=fe.byFile,ye=Pc(_),xe=At(a,{flowEnabled:!!i.flow}),O=_e(c,k,b);if(H=Mt(H,xe,O,C,{flowEnabled:!!i.flow}),i.affected){let P=on(i.root,i.affected,c);if(P.length>0){let oe=new Set(P);H=H.filter(ce=>oe.has(ce.file)),le.progress("detect",`--affected: ${P.length} files in scope, ${H.length} findings`)}}if(i.ignoreKnown){let{filtered:P,suppressedCount:oe}=cn(H,i.ignoreKnown,i.root);oe>0&&le.progress("detect",`--ignore-known: suppressed ${oe} known findings`),H=P}let j=Pt(H,xe,O,C),X=nr(xe,te),re={generatedAt:new Date().toISOString(),repoRoot:i.root,options:{...i,ignoreDirs:[...i.ignoreDirs]},parser:{requested:i.parser,effective:n,treeSitterAvailable:m,treeSitterError:S},summary:t,fileInventory:X,duplicateFlows:{duplicatedFunctions:h.slice(0,200),duplicatedControlFlow:y.slice(0,200),totalFunctionGroups:h.length,totalFlowGroups:y.length},dependencyGraph:k,dependencyFindings:H.filter(P=>P.category?.startsWith("dependency")),agentOutput:{totalFindings:H.length,totalBeforeTruncation:V,droppedCategories:se,findingStats:ye,analysisSummary:{strongestGraphSignal:j.strongestGraphSignal,strongestAstSignal:j.strongestAstSignal,combinedSignals:j.combinedSignals,recommendedValidation:j.recommendedValidation},highPriority:H.filter(P=>P.severity==="high"||P.severity==="critical").length,mediumPriority:H.filter(P=>P.severity==="medium").length,lowPriority:H.filter(P=>P.severity==="low"||P.severity==="info").length,topRecommendations:ts(H,20,i.maxRecsPerCategory).map(P=>({id:P.id,file:P.file,severity:P.severity,category:P.category,title:P.title,reason:P.reason,suggestedFix:P.suggestedFix})),filesWithIssues:[...te.entries()].map(([P,oe])=>({file:P,issueCount:oe.length,issueIds:oe}))},optimizationOpportunities:D,optimizationFindings:H,parseErrors:l,astTrees:void 0,graphAnalytics:C,reportAnalysis:j};if(i.emitTree&&(re.astTrees=o),le.progress("report",`${H.length} findings generated`),i.saveBaseline){let P=ln(i.root,H);i.json||console.error(`Baseline saved: ${J.relative(i.root,P)} (${H.length} findings)`)}if(i.reporter!=="default"){let P=un(H,i.reporter,i.root);process.stdout.write(P+`
|
|
172
|
+
`)}else i.json?console.log(JSON.stringify(re)):Dc(t,h,y,k,H,l,i,re.parser.effective);if(f&&g){if(Be.mkdirSync(J.dirname(g),{recursive:!0}),Be.writeFileSync(g,JSON.stringify(re),"utf8"),i.json||console.log(`
|
|
173
|
+
Full report written to ${J.relative(i.root,g)}`),i.graph){let P={focus:i.focus,focusDepth:i.focusDepth,collapse:i.collapse},oe=Nt(c,k,b,P),ce=g.replace(/\.json$/,"-graph.md");Be.writeFileSync(ce,oe,"utf8"),i.json||console.log(`Dependency graph written to ${J.relative(i.root,ce)}`)}}else if(p){le.progress("write",`Writing report to ${J.relative(i.root,p)}`);let P={focus:i.focus,focusDepth:i.focusDepth,collapse:i.collapse},oe=ss(p,re,i,c,k,b,P);if(!i.json){let ce=J.relative(i.root,p);console.log(`
|
|
174
|
+
Report written to ${ce}/`);for(let[Ae,ze]of Object.entries(oe))console.log(` ${Ae}: ${ze}`)}}if(le.progress("done","Scan complete",`${H.length} findings`),i.atLeast!=null){let P=t.totalFiles??1,oe=ls(H.length,P);if(oe<i.atLeast)return console.error(`Gate score ${oe} is below --at-least threshold ${i.atLeast}`),-1}return H.length}function ls(e,i){let n=e/Math.max(i,1);return Math.round(100/(1+n/10))}async function mo(e){let i=await Rc(e);if(!i)return Lt;Ac(i);let n=Mc(i);return n<0||n>0?Ot:Lt}function Pc(e){let i=s=>{let r={critical:0,high:0,medium:0,low:0,info:0};for(let o of s)r[o.severity]=(r[o.severity]||0)+1;return r},n={totalFindings:e.length,severityBreakdown:i(e)},t=Object.fromEntries(Object.entries(B).map(([s,r])=>{let o=new Set(r),a=e.filter(l=>o.has(l.category));return[s,{totalFindings:a.length,severityBreakdown:i(a)}]}));return{overall:n,pillars:t}}var Lt,Ot,jt,cs=N(()=>{"use strict";Ts();Zt();nn();Ye();rn();an();dn();fn();Sn();xn();ir();Fn();dr();pr();Ur();Gr();G();tt();Vr();go();is();ot();rs();ge();Lt=0,Ot=1,jt=2;qr(import.meta.url)&&mo().then(e=>{process.exitCode=e}).catch(e=>{e instanceof Ie?(console.error(e.message),process.exitCode=jt):(console.error(e),process.exitCode=jt)})});import{spawnSync as Ic}from"node:child_process";import{existsSync as Nc}from"node:fs";import{createRequire as Lc}from"node:module";import{dirname as yo,join as bo}from"node:path";import{fileURLToPath as Oc}from"node:url";var jc=Oc(import.meta.url),Ht=yo(yo(jc)),_c=bo(Ht,"node_modules"),Hc=Lc(import.meta.url),Bc=["typescript","@ast-grep/napi","tree-sitter","tree-sitter-typescript"];function zc(e){if(Nc(bo(_c,e)))return!0;try{return Hc.resolve(e,{paths:[Ht]}),!0}catch{return!1}}var So=Bc.filter(e=>!zc(e));So.length>0&&(process.stderr.write(`[octocode-scan] Missing dependencies (${So.join(", ")}). Installing...
|
|
175
|
+
`),Ic("npm",["install","--prefix",Ht,"--no-audit","--no-fund"],{stdio:"inherit",shell:!1}).status!==0&&(process.stderr.write(`[octocode-scan] Failed to install dependencies.
|
|
176
|
+
Run manually: cd ${Ht} && npm install
|
|
177
|
+
`),process.exit(1)),process.stderr.write(`[octocode-scan] Dependencies installed.
|
|
178
|
+
`));var{main:Kc,EXIT_ERROR:Uc}=await Promise.resolve().then(()=>(cs(),ho)),{OptionsError:qc}=await Promise.resolve().then(()=>(Ye(),Ds));try{let e=await Kc();process.exitCode=e}catch(e){e instanceof qc?process.stderr.write(`${e.message}
|
|
179
|
+
`):console.error(e),process.exitCode=Uc}
|