@harness-engineering/cli 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/skills/claude-code/add-harness-component/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/align-documentation/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/check-mechanical-constraints/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/detect-doc-drift/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-api-design/SKILL.md +304 -0
- package/dist/agents/skills/claude-code/harness-api-design/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-architecture-advisor/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-auth/SKILL.md +279 -0
- package/dist/agents/skills/claude-code/harness-auth/skill.yaml +81 -0
- package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +39 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-caching/SKILL.md +309 -0
- package/dist/agents/skills/claude-code/harness-caching/skill.yaml +73 -0
- package/dist/agents/skills/claude-code/harness-chaos/SKILL.md +295 -0
- package/dist/agents/skills/claude-code/harness-chaos/skill.yaml +72 -0
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +44 -0
- package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-compliance/SKILL.md +303 -0
- package/dist/agents/skills/claude-code/harness-compliance/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-containerization/SKILL.md +284 -0
- package/dist/agents/skills/claude-code/harness-containerization/skill.yaml +80 -0
- package/dist/agents/skills/claude-code/harness-data-pipeline/SKILL.md +274 -0
- package/dist/agents/skills/claude-code/harness-data-pipeline/skill.yaml +81 -0
- package/dist/agents/skills/claude-code/harness-data-validation/SKILL.md +343 -0
- package/dist/agents/skills/claude-code/harness-data-validation/skill.yaml +75 -0
- package/dist/agents/skills/claude-code/harness-database/SKILL.md +258 -0
- package/dist/agents/skills/claude-code/harness-database/skill.yaml +80 -0
- package/dist/agents/skills/claude-code/harness-debugging/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-deployment/SKILL.md +255 -0
- package/dist/agents/skills/claude-code/harness-deployment/skill.yaml +77 -0
- package/dist/agents/skills/claude-code/harness-design/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-design-mobile/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-design-system/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-design-web/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-diagnostics/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-dx/SKILL.md +276 -0
- package/dist/agents/skills/claude-code/harness-dx/skill.yaml +76 -0
- package/dist/agents/skills/claude-code/harness-e2e/SKILL.md +245 -0
- package/dist/agents/skills/claude-code/harness-e2e/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-event-driven/SKILL.md +280 -0
- package/dist/agents/skills/claude-code/harness-event-driven/skill.yaml +77 -0
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +44 -0
- package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-feature-flags/SKILL.md +287 -0
- package/dist/agents/skills/claude-code/harness-feature-flags/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-git-workflow/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-impact-analysis/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-incident-response/SKILL.md +223 -0
- package/dist/agents/skills/claude-code/harness-incident-response/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-infrastructure-as-code/SKILL.md +279 -0
- package/dist/agents/skills/claude-code/harness-infrastructure-as-code/skill.yaml +80 -0
- package/dist/agents/skills/claude-code/harness-integration-test/SKILL.md +271 -0
- package/dist/agents/skills/claude-code/harness-integration-test/skill.yaml +73 -0
- package/dist/agents/skills/claude-code/harness-integrity/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-knowledge-mapper/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-load-testing/SKILL.md +274 -0
- package/dist/agents/skills/claude-code/harness-load-testing/skill.yaml +79 -0
- package/dist/agents/skills/claude-code/harness-ml-ops/SKILL.md +341 -0
- package/dist/agents/skills/claude-code/harness-ml-ops/skill.yaml +79 -0
- package/dist/agents/skills/claude-code/harness-mobile-patterns/SKILL.md +326 -0
- package/dist/agents/skills/claude-code/harness-mobile-patterns/skill.yaml +82 -0
- package/dist/agents/skills/claude-code/harness-mutation-test/SKILL.md +251 -0
- package/dist/agents/skills/claude-code/harness-mutation-test/skill.yaml +70 -0
- package/dist/agents/skills/claude-code/harness-observability/SKILL.md +283 -0
- package/dist/agents/skills/claude-code/harness-observability/skill.yaml +78 -0
- package/dist/agents/skills/claude-code/harness-onboarding/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-parallel-agents/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-perf/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-perf-tdd/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +39 -0
- package/dist/agents/skills/claude-code/harness-planning/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-pre-commit-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-product-spec/SKILL.md +285 -0
- package/dist/agents/skills/claude-code/harness-product-spec/skill.yaml +72 -0
- package/dist/agents/skills/claude-code/harness-property-test/SKILL.md +281 -0
- package/dist/agents/skills/claude-code/harness-property-test/skill.yaml +71 -0
- package/dist/agents/skills/claude-code/harness-refactoring/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +3 -3
- package/dist/agents/skills/claude-code/harness-release-readiness/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-resilience/SKILL.md +255 -0
- package/dist/agents/skills/claude-code/harness-resilience/skill.yaml +76 -0
- package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-secrets/SKILL.md +293 -0
- package/dist/agents/skills/claude-code/harness-secrets/skill.yaml +76 -0
- package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-skill-authoring/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-sql-review/SKILL.md +315 -0
- package/dist/agents/skills/claude-code/harness-sql-review/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-state-management/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-tdd/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-test-advisor/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-test-data/SKILL.md +268 -0
- package/dist/agents/skills/claude-code/harness-test-data/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/harness-ux-copy/SKILL.md +271 -0
- package/dist/agents/skills/claude-code/harness-ux-copy/skill.yaml +77 -0
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +35 -0
- package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-verify/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-visual-regression/SKILL.md +257 -0
- package/dist/agents/skills/claude-code/harness-visual-regression/skill.yaml +74 -0
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +11 -3
- package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/validate-context-engineering/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/add-harness-component/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/align-documentation/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/check-mechanical-constraints/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/cleanup-dead-code/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/detect-doc-drift/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/enforce-architecture/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-api-design/SKILL.md +304 -0
- package/dist/agents/skills/gemini-cli/harness-api-design/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-architecture-advisor/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-auth/SKILL.md +279 -0
- package/dist/agents/skills/gemini-cli/harness-auth/skill.yaml +81 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +39 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-caching/SKILL.md +309 -0
- package/dist/agents/skills/gemini-cli/harness-caching/skill.yaml +73 -0
- package/dist/agents/skills/gemini-cli/harness-chaos/SKILL.md +295 -0
- package/dist/agents/skills/gemini-cli/harness-chaos/skill.yaml +72 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +44 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-compliance/SKILL.md +303 -0
- package/dist/agents/skills/gemini-cli/harness-compliance/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-containerization/SKILL.md +284 -0
- package/dist/agents/skills/gemini-cli/harness-containerization/skill.yaml +80 -0
- package/dist/agents/skills/gemini-cli/harness-data-pipeline/SKILL.md +274 -0
- package/dist/agents/skills/gemini-cli/harness-data-pipeline/skill.yaml +81 -0
- package/dist/agents/skills/gemini-cli/harness-data-validation/SKILL.md +343 -0
- package/dist/agents/skills/gemini-cli/harness-data-validation/skill.yaml +75 -0
- package/dist/agents/skills/gemini-cli/harness-database/SKILL.md +258 -0
- package/dist/agents/skills/gemini-cli/harness-database/skill.yaml +80 -0
- package/dist/agents/skills/gemini-cli/harness-debugging/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-deployment/SKILL.md +255 -0
- package/dist/agents/skills/gemini-cli/harness-deployment/skill.yaml +77 -0
- package/dist/agents/skills/gemini-cli/harness-design/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-design-mobile/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-design-system/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-design-web/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-diagnostics/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-dx/SKILL.md +276 -0
- package/dist/agents/skills/gemini-cli/harness-dx/skill.yaml +76 -0
- package/dist/agents/skills/gemini-cli/harness-e2e/SKILL.md +245 -0
- package/dist/agents/skills/gemini-cli/harness-e2e/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-event-driven/SKILL.md +280 -0
- package/dist/agents/skills/gemini-cli/harness-event-driven/skill.yaml +77 -0
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +44 -0
- package/dist/agents/skills/gemini-cli/harness-execution/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-feature-flags/SKILL.md +287 -0
- package/dist/agents/skills/gemini-cli/harness-feature-flags/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-git-workflow/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-impact-analysis/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-incident-response/SKILL.md +223 -0
- package/dist/agents/skills/gemini-cli/harness-incident-response/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-infrastructure-as-code/SKILL.md +279 -0
- package/dist/agents/skills/gemini-cli/harness-infrastructure-as-code/skill.yaml +80 -0
- package/dist/agents/skills/gemini-cli/harness-integration-test/SKILL.md +271 -0
- package/dist/agents/skills/gemini-cli/harness-integration-test/skill.yaml +73 -0
- package/dist/agents/skills/gemini-cli/harness-integrity/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-load-testing/SKILL.md +274 -0
- package/dist/agents/skills/gemini-cli/harness-load-testing/skill.yaml +79 -0
- package/dist/agents/skills/gemini-cli/harness-ml-ops/SKILL.md +341 -0
- package/dist/agents/skills/gemini-cli/harness-ml-ops/skill.yaml +79 -0
- package/dist/agents/skills/gemini-cli/harness-mobile-patterns/SKILL.md +326 -0
- package/dist/agents/skills/gemini-cli/harness-mobile-patterns/skill.yaml +82 -0
- package/dist/agents/skills/gemini-cli/harness-mutation-test/SKILL.md +251 -0
- package/dist/agents/skills/gemini-cli/harness-mutation-test/skill.yaml +70 -0
- package/dist/agents/skills/gemini-cli/harness-observability/SKILL.md +283 -0
- package/dist/agents/skills/gemini-cli/harness-observability/skill.yaml +78 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-parallel-agents/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-perf-tdd/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +39 -0
- package/dist/agents/skills/gemini-cli/harness-planning/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-pre-commit-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-product-spec/SKILL.md +285 -0
- package/dist/agents/skills/gemini-cli/harness-product-spec/skill.yaml +72 -0
- package/dist/agents/skills/gemini-cli/harness-property-test/SKILL.md +281 -0
- package/dist/agents/skills/gemini-cli/harness-property-test/skill.yaml +71 -0
- package/dist/agents/skills/gemini-cli/harness-refactoring/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +3 -3
- package/dist/agents/skills/gemini-cli/harness-release-readiness/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-resilience/SKILL.md +255 -0
- package/dist/agents/skills/gemini-cli/harness-resilience/skill.yaml +76 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-secrets/SKILL.md +293 -0
- package/dist/agents/skills/gemini-cli/harness-secrets/skill.yaml +76 -0
- package/dist/agents/skills/gemini-cli/harness-security-review/SKILL.md +240 -0
- package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-skill-authoring/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-sql-review/SKILL.md +315 -0
- package/dist/agents/skills/gemini-cli/harness-sql-review/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-state-management/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-tdd/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-test-advisor/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-test-data/SKILL.md +268 -0
- package/dist/agents/skills/gemini-cli/harness-test-data/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-ux-copy/SKILL.md +271 -0
- package/dist/agents/skills/gemini-cli/harness-ux-copy/skill.yaml +77 -0
- package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +35 -0
- package/dist/agents/skills/gemini-cli/harness-verification/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-verify/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-visual-regression/SKILL.md +257 -0
- package/dist/agents/skills/gemini-cli/harness-visual-regression/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +11 -3
- package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/validate-context-engineering/skill.yaml +1 -0
- package/dist/agents-md-YTYQDA3P.js +8 -0
- package/dist/{architecture-ESOOE26S.js → architecture-JQZYM4US.js} +4 -4
- package/dist/bin/harness-mcp.js +16 -15
- package/dist/bin/harness.js +31 -30
- package/dist/{check-phase-gate-S2MZKLFQ.js → check-phase-gate-L3RADYWO.js} +4 -3
- package/dist/{chunk-WPPDRIJL.js → chunk-3C2MLBPJ.js} +4 -4
- package/dist/chunk-6KTUUFRN.js +217 -0
- package/dist/{chunk-MI5XJQDY.js → chunk-7IP4JIFL.js} +24 -10
- package/dist/{chunk-C2ERUR3L.js → chunk-7MJAPE3Z.js} +165 -49
- package/dist/{chunk-KELT6K6M.js → chunk-ABQHQ6I5.js} +1861 -1418
- package/dist/{chunk-L2KLU56K.js → chunk-AOZRDOIP.js} +2 -2
- package/dist/{chunk-QPEH2QPG.js → chunk-DBSOCI3G.js} +53 -54
- package/dist/{chunk-MHBMTPW7.js → chunk-ERS5EVUZ.js} +9 -0
- package/dist/{chunk-JSTQ3AWB.js → chunk-FIAPHX37.js} +1 -1
- package/dist/{chunk-2YPZKGAG.js → chunk-FTMXDOR6.js} +1 -1
- package/dist/{chunk-72GHBOL2.js → chunk-GZKSBLQL.js} +1 -1
- package/dist/{chunk-K6XAPGML.js → chunk-H7Y5CKTM.js} +1 -1
- package/dist/{chunk-HD4IBGLA.js → chunk-N5G5QMS3.js} +24 -1
- package/dist/{chunk-LD3DKUK5.js → chunk-NLVUVUGD.js} +1 -1
- package/dist/{chunk-3KOLLWWE.js → chunk-O5OJVPL6.js} +26 -211
- package/dist/{chunk-NKDM3FMH.js → chunk-OD3S2NHN.js} +1 -1
- package/dist/{chunk-5VY23YK3.js → chunk-OSXBPAMK.js} +2 -2
- package/dist/{chunk-MACVXDZK.js → chunk-OXLLOSSR.js} +45 -47
- package/dist/{chunk-GNGELAXY.js → chunk-RCWZBSK5.js} +2 -2
- package/dist/{chunk-PSNN4LWX.js → chunk-S2FXOWOR.js} +3 -3
- package/dist/{chunk-VUCPTQ6G.js → chunk-SD3SQOZ2.js} +1 -1
- package/dist/{chunk-7PZWR4LI.js → chunk-TPOTOBR7.js} +9 -9
- package/dist/{chunk-RZSUJBZZ.js → chunk-XKECDXJS.js} +452 -353
- package/dist/{chunk-VRFZWGMS.js → chunk-XYLGHKG6.js} +5 -1
- package/dist/{chunk-6N4R6FVX.js → chunk-YBJ262QL.js} +1 -1
- package/dist/{chunk-2VU4MFM3.js → chunk-YPYGXRDR.js} +7 -7
- package/dist/{chunk-Q6AB7W5Z.js → chunk-YQ6KC6TE.js} +1 -1
- package/dist/{chunk-7KQSUZVG.js → chunk-YZD2MRNQ.js} +1528 -1010
- package/dist/ci-workflow-EQZFVX3P.js +8 -0
- package/dist/{create-skill-WPXHSLX2.js → create-skill-XSWHMSM5.js} +2 -2
- package/dist/{dist-M6BQODWC.js → dist-B26DFXMP.js} +573 -480
- package/dist/{dist-L7LAAQAS.js → dist-DZ63LLUD.js} +1 -1
- package/dist/{dist-WF4C7A4A.js → dist-HWXF2C3R.js} +18 -2
- package/dist/{dist-D4RYGUZE.js → dist-USY2C5JL.js} +3 -1
- package/dist/{docs-BPYCN2DR.js → docs-7ECGYMAV.js} +5 -3
- package/dist/engine-EG4EH4IX.js +8 -0
- package/dist/{entropy-4VDVV5CR.js → entropy-5USWKLVS.js} +3 -3
- package/dist/{feedback-63QB5RCA.js → feedback-UTBXZZHF.js} +1 -1
- package/dist/{generate-agent-definitions-QABOJG56.js → generate-agent-definitions-3PM5EU7V.js} +5 -5
- package/dist/{glob-helper-5OHBUQAI.js → glob-helper-R5FXNUPS.js} +1 -1
- package/dist/{graph-loader-KO4GJ5N2.js → graph-loader-2M2HXDQI.js} +1 -1
- package/dist/index.d.ts +183 -17
- package/dist/index.js +32 -30
- package/dist/loader-ZPALXIVR.js +10 -0
- package/dist/mcp-362EZHF4.js +35 -0
- package/dist/{performance-26BH47O4.js → performance-OQAFMJUD.js} +3 -3
- package/dist/{review-pipeline-GHR3WFBI.js → review-pipeline-C4GCFVGP.js} +1 -1
- package/dist/runtime-7YLVK453.js +9 -0
- package/dist/{security-UQFUZXEN.js → security-PZOX7AQS.js} +1 -1
- package/dist/skill-executor-XZLYZYAK.js +8 -0
- package/dist/templates/axum/Cargo.toml.hbs +8 -0
- package/dist/templates/axum/src/main.rs +12 -0
- package/dist/templates/axum/template.json +16 -0
- package/dist/templates/django/manage.py.hbs +19 -0
- package/dist/templates/django/requirements.txt.hbs +1 -0
- package/dist/templates/django/src/settings.py.hbs +44 -0
- package/dist/templates/django/src/urls.py +6 -0
- package/dist/templates/django/src/wsgi.py.hbs +9 -0
- package/dist/templates/django/template.json +21 -0
- package/dist/templates/express/package.json.hbs +15 -0
- package/dist/templates/express/src/app.ts +12 -0
- package/dist/templates/express/src/lib/.gitkeep +0 -0
- package/dist/templates/express/template.json +16 -0
- package/dist/templates/fastapi/requirements.txt.hbs +2 -0
- package/dist/templates/fastapi/src/main.py +8 -0
- package/dist/templates/fastapi/template.json +20 -0
- package/dist/templates/gin/go.mod.hbs +5 -0
- package/dist/templates/gin/main.go +15 -0
- package/dist/templates/gin/template.json +19 -0
- package/dist/templates/go-base/.golangci.yml +16 -0
- package/dist/templates/go-base/AGENTS.md.hbs +35 -0
- package/dist/templates/go-base/go.mod.hbs +3 -0
- package/dist/templates/go-base/harness.config.json.hbs +17 -0
- package/dist/templates/go-base/main.go +7 -0
- package/dist/templates/go-base/template.json +14 -0
- package/dist/templates/java-base/AGENTS.md.hbs +35 -0
- package/dist/templates/java-base/checkstyle.xml +20 -0
- package/dist/templates/java-base/harness.config.json.hbs +16 -0
- package/dist/templates/java-base/pom.xml.hbs +39 -0
- package/dist/templates/java-base/src/main/java/App.java.hbs +5 -0
- package/dist/templates/java-base/template.json +13 -0
- package/dist/templates/nestjs/nest-cli.json +5 -0
- package/dist/templates/nestjs/package.json.hbs +18 -0
- package/dist/templates/nestjs/src/app.module.ts +8 -0
- package/dist/templates/nestjs/src/lib/.gitkeep +0 -0
- package/dist/templates/nestjs/src/main.ts +11 -0
- package/dist/templates/nestjs/template.json +16 -0
- package/dist/templates/nextjs/template.json +15 -1
- package/dist/templates/python-base/.python-version +1 -0
- package/dist/templates/python-base/AGENTS.md.hbs +32 -0
- package/dist/templates/python-base/harness.config.json.hbs +16 -0
- package/dist/templates/python-base/pyproject.toml.hbs +18 -0
- package/dist/templates/python-base/ruff.toml +5 -0
- package/dist/templates/python-base/src/__init__.py +0 -0
- package/dist/templates/python-base/template.json +13 -0
- package/dist/templates/react-vite/index.html +12 -0
- package/dist/templates/react-vite/package.json.hbs +18 -0
- package/dist/templates/react-vite/src/App.tsx +7 -0
- package/dist/templates/react-vite/src/lib/.gitkeep +0 -0
- package/dist/templates/react-vite/src/main.tsx +9 -0
- package/dist/templates/react-vite/template.json +19 -0
- package/dist/templates/react-vite/vite.config.ts +6 -0
- package/dist/templates/rust-base/AGENTS.md.hbs +35 -0
- package/dist/templates/rust-base/Cargo.toml.hbs +6 -0
- package/dist/templates/rust-base/clippy.toml +2 -0
- package/dist/templates/rust-base/harness.config.json.hbs +17 -0
- package/dist/templates/rust-base/src/main.rs +3 -0
- package/dist/templates/rust-base/template.json +14 -0
- package/dist/templates/spring-boot/pom.xml.hbs +50 -0
- package/dist/templates/spring-boot/src/main/java/Application.java.hbs +19 -0
- package/dist/templates/spring-boot/template.json +15 -0
- package/dist/templates/vue/index.html +12 -0
- package/dist/templates/vue/package.json.hbs +16 -0
- package/dist/templates/vue/src/App.vue +7 -0
- package/dist/templates/vue/src/lib/.gitkeep +0 -0
- package/dist/templates/vue/src/main.ts +4 -0
- package/dist/templates/vue/template.json +19 -0
- package/dist/templates/vue/vite.config.ts +6 -0
- package/dist/{validate-N7QJOKFZ.js → validate-FD3Z6VJD.js} +4 -4
- package/dist/validate-cross-check-WNJM6H2D.js +8 -0
- package/package.json +6 -6
- package/dist/agents-md-P2RHSUV7.js +0 -8
- package/dist/ci-workflow-4NYBUG6R.js +0 -8
- package/dist/engine-LXLIWQQ3.js +0 -8
- package/dist/loader-Z2IT7QX3.js +0 -10
- package/dist/mcp-KQHEL5IF.js +0 -34
- package/dist/runtime-PDWD7UIK.js +0 -9
- package/dist/skill-executor-RG45LUO5.js +0 -8
- package/dist/validate-cross-check-EDQ5QGTM.js +0 -8
|
@@ -361,6 +361,53 @@ var VectorStore = class _VectorStore {
|
|
|
361
361
|
return store;
|
|
362
362
|
}
|
|
363
363
|
};
|
|
364
|
+
function edgeKey(e) {
|
|
365
|
+
return `${e.from}|${e.to}|${e.type}`;
|
|
366
|
+
}
|
|
367
|
+
function addEdge(state, edge) {
|
|
368
|
+
const key = edgeKey(edge);
|
|
369
|
+
if (!state.edgeSet.has(key)) {
|
|
370
|
+
state.edgeSet.add(key);
|
|
371
|
+
state.resultEdges.push(edge);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
function shouldPruneNode(neighbor, pruneObservability, params) {
|
|
375
|
+
if (pruneObservability && OBSERVABILITY_TYPES.has(neighbor.type)) return true;
|
|
376
|
+
if (params.includeTypes && !params.includeTypes.includes(neighbor.type)) return true;
|
|
377
|
+
if (params.excludeTypes && params.excludeTypes.includes(neighbor.type)) return true;
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
function isEdgeExcluded(edge, params) {
|
|
381
|
+
return !!(params.includeEdges && !params.includeEdges.includes(edge.type));
|
|
382
|
+
}
|
|
383
|
+
function processNeighbor(store, edge, neighborId, nextDepth, queue, state, pruneObservability, params) {
|
|
384
|
+
if (isEdgeExcluded(edge, params)) return;
|
|
385
|
+
if (state.visited.has(neighborId)) {
|
|
386
|
+
addEdge(state, edge);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const neighbor = store.getNode(neighborId);
|
|
390
|
+
if (!neighbor) return;
|
|
391
|
+
state.visited.add(neighborId);
|
|
392
|
+
if (shouldPruneNode(neighbor, pruneObservability, params)) {
|
|
393
|
+
state.pruned++;
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
state.resultNodeMap.set(neighborId, neighbor);
|
|
397
|
+
addEdge(state, edge);
|
|
398
|
+
queue.push({ id: neighborId, depth: nextDepth });
|
|
399
|
+
}
|
|
400
|
+
function addCrossEdges(store, state) {
|
|
401
|
+
const resultNodeIds = new Set(state.resultNodeMap.keys());
|
|
402
|
+
for (const nodeId of resultNodeIds) {
|
|
403
|
+
const outEdges = store.getEdges({ from: nodeId });
|
|
404
|
+
for (const edge of outEdges) {
|
|
405
|
+
if (resultNodeIds.has(edge.to)) {
|
|
406
|
+
addEdge(state, edge);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
364
411
|
var ContextQL = class {
|
|
365
412
|
store;
|
|
366
413
|
constructor(store) {
|
|
@@ -370,89 +417,69 @@ var ContextQL = class {
|
|
|
370
417
|
const maxDepth = params.maxDepth ?? 3;
|
|
371
418
|
const bidirectional = params.bidirectional ?? false;
|
|
372
419
|
const pruneObservability = params.pruneObservability ?? true;
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const addEdge = (edge) => {
|
|
381
|
-
const key = edgeKey(edge);
|
|
382
|
-
if (!edgeSet.has(key)) {
|
|
383
|
-
edgeSet.add(key);
|
|
384
|
-
resultEdges.push(edge);
|
|
385
|
-
}
|
|
420
|
+
const state = {
|
|
421
|
+
visited: /* @__PURE__ */ new Set(),
|
|
422
|
+
resultNodeMap: /* @__PURE__ */ new Map(),
|
|
423
|
+
resultEdges: [],
|
|
424
|
+
edgeSet: /* @__PURE__ */ new Set(),
|
|
425
|
+
pruned: 0,
|
|
426
|
+
depthReached: 0
|
|
386
427
|
};
|
|
387
428
|
const queue = [];
|
|
388
|
-
|
|
429
|
+
this.seedRootNodes(params.rootNodeIds, state, queue);
|
|
430
|
+
this.runBFS(queue, maxDepth, bidirectional, pruneObservability, params, state);
|
|
431
|
+
addCrossEdges(this.store, state);
|
|
432
|
+
return {
|
|
433
|
+
nodes: Array.from(state.resultNodeMap.values()),
|
|
434
|
+
edges: state.resultEdges,
|
|
435
|
+
stats: {
|
|
436
|
+
totalTraversed: state.visited.size,
|
|
437
|
+
totalReturned: state.resultNodeMap.size,
|
|
438
|
+
pruned: state.pruned,
|
|
439
|
+
depthReached: state.depthReached
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
seedRootNodes(rootNodeIds, state, queue) {
|
|
444
|
+
for (const rootId of rootNodeIds) {
|
|
389
445
|
const node = this.store.getNode(rootId);
|
|
390
446
|
if (node) {
|
|
391
|
-
visited.add(rootId);
|
|
392
|
-
resultNodeMap.set(rootId, node);
|
|
447
|
+
state.visited.add(rootId);
|
|
448
|
+
state.resultNodeMap.set(rootId, node);
|
|
393
449
|
queue.push({ id: rootId, depth: 0 });
|
|
394
450
|
}
|
|
395
451
|
}
|
|
452
|
+
}
|
|
453
|
+
runBFS(queue, maxDepth, bidirectional, pruneObservability, params, state) {
|
|
396
454
|
let head = 0;
|
|
397
455
|
while (head < queue.length) {
|
|
398
456
|
const entry = queue[head++];
|
|
399
457
|
const { id: currentId, depth } = entry;
|
|
400
458
|
if (depth >= maxDepth) continue;
|
|
401
459
|
const nextDepth = depth + 1;
|
|
402
|
-
if (nextDepth > depthReached) depthReached = nextDepth;
|
|
403
|
-
const
|
|
404
|
-
const inEdges = bidirectional ? this.store.getEdges({ to: currentId }) : [];
|
|
405
|
-
const allEdges = [
|
|
406
|
-
...outEdges.map((e) => ({ edge: e, neighborId: e.to })),
|
|
407
|
-
...inEdges.map((e) => ({ edge: e, neighborId: e.from }))
|
|
408
|
-
];
|
|
460
|
+
if (nextDepth > state.depthReached) state.depthReached = nextDepth;
|
|
461
|
+
const allEdges = this.gatherEdges(currentId, bidirectional);
|
|
409
462
|
for (const { edge, neighborId } of allEdges) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (pruneObservability && OBSERVABILITY_TYPES.has(neighbor.type)) {
|
|
421
|
-
pruned++;
|
|
422
|
-
continue;
|
|
423
|
-
}
|
|
424
|
-
if (params.includeTypes && !params.includeTypes.includes(neighbor.type)) {
|
|
425
|
-
pruned++;
|
|
426
|
-
continue;
|
|
427
|
-
}
|
|
428
|
-
if (params.excludeTypes && params.excludeTypes.includes(neighbor.type)) {
|
|
429
|
-
pruned++;
|
|
430
|
-
continue;
|
|
431
|
-
}
|
|
432
|
-
resultNodeMap.set(neighborId, neighbor);
|
|
433
|
-
addEdge(edge);
|
|
434
|
-
queue.push({ id: neighborId, depth: nextDepth });
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
const resultNodeIds = new Set(resultNodeMap.keys());
|
|
438
|
-
for (const nodeId of resultNodeIds) {
|
|
439
|
-
const outEdges = this.store.getEdges({ from: nodeId });
|
|
440
|
-
for (const edge of outEdges) {
|
|
441
|
-
if (resultNodeIds.has(edge.to)) {
|
|
442
|
-
addEdge(edge);
|
|
443
|
-
}
|
|
463
|
+
processNeighbor(
|
|
464
|
+
this.store,
|
|
465
|
+
edge,
|
|
466
|
+
neighborId,
|
|
467
|
+
nextDepth,
|
|
468
|
+
queue,
|
|
469
|
+
state,
|
|
470
|
+
pruneObservability,
|
|
471
|
+
params
|
|
472
|
+
);
|
|
444
473
|
}
|
|
445
474
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
};
|
|
475
|
+
}
|
|
476
|
+
gatherEdges(nodeId, bidirectional) {
|
|
477
|
+
const outEdges = this.store.getEdges({ from: nodeId });
|
|
478
|
+
const inEdges = bidirectional ? this.store.getEdges({ to: nodeId }) : [];
|
|
479
|
+
return [
|
|
480
|
+
...outEdges.map((e) => ({ edge: e, neighborId: e.to })),
|
|
481
|
+
...inEdges.map((e) => ({ edge: e, neighborId: e.from }))
|
|
482
|
+
];
|
|
456
483
|
}
|
|
457
484
|
};
|
|
458
485
|
function project(nodes, spec) {
|
|
@@ -497,6 +524,15 @@ function groupNodesByImpact(nodes, excludeId) {
|
|
|
497
524
|
}
|
|
498
525
|
return { tests, docs, code, other };
|
|
499
526
|
}
|
|
527
|
+
var SKIP_METHOD_NAMES = /* @__PURE__ */ new Set(["constructor", "if", "for", "while", "switch"]);
|
|
528
|
+
function countBraces(line) {
|
|
529
|
+
let net = 0;
|
|
530
|
+
for (const ch of line) {
|
|
531
|
+
if (ch === "{") net++;
|
|
532
|
+
else if (ch === "}") net--;
|
|
533
|
+
}
|
|
534
|
+
return net;
|
|
535
|
+
}
|
|
500
536
|
var CodeIngestor = class {
|
|
501
537
|
constructor(store) {
|
|
502
538
|
this.store = store;
|
|
@@ -511,41 +547,9 @@ var CodeIngestor = class {
|
|
|
511
547
|
const fileContents = /* @__PURE__ */ new Map();
|
|
512
548
|
for (const filePath of files) {
|
|
513
549
|
try {
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const fileId = `file:${relativePath}`;
|
|
518
|
-
fileContents.set(relativePath, content);
|
|
519
|
-
const fileNode = {
|
|
520
|
-
id: fileId,
|
|
521
|
-
type: "file",
|
|
522
|
-
name: path.basename(filePath),
|
|
523
|
-
path: relativePath,
|
|
524
|
-
metadata: { language: this.detectLanguage(filePath) },
|
|
525
|
-
lastModified: stat2.mtime.toISOString()
|
|
526
|
-
};
|
|
527
|
-
this.store.addNode(fileNode);
|
|
528
|
-
nodesAdded++;
|
|
529
|
-
const symbols = this.extractSymbols(content, fileId, relativePath);
|
|
530
|
-
for (const { node, edge } of symbols) {
|
|
531
|
-
this.store.addNode(node);
|
|
532
|
-
this.store.addEdge(edge);
|
|
533
|
-
nodesAdded++;
|
|
534
|
-
edgesAdded++;
|
|
535
|
-
if (node.type === "function" || node.type === "method") {
|
|
536
|
-
let files2 = nameToFiles.get(node.name);
|
|
537
|
-
if (!files2) {
|
|
538
|
-
files2 = /* @__PURE__ */ new Set();
|
|
539
|
-
nameToFiles.set(node.name, files2);
|
|
540
|
-
}
|
|
541
|
-
files2.add(relativePath);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
const imports = await this.extractImports(content, fileId, relativePath, rootDir);
|
|
545
|
-
for (const edge of imports) {
|
|
546
|
-
this.store.addEdge(edge);
|
|
547
|
-
edgesAdded++;
|
|
548
|
-
}
|
|
550
|
+
const result = await this.processFile(filePath, rootDir, nameToFiles, fileContents);
|
|
551
|
+
nodesAdded += result.nodesAdded;
|
|
552
|
+
edgesAdded += result.edgesAdded;
|
|
549
553
|
} catch (err) {
|
|
550
554
|
errors.push(`${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
551
555
|
}
|
|
@@ -564,6 +568,48 @@ var CodeIngestor = class {
|
|
|
564
568
|
durationMs: Date.now() - start
|
|
565
569
|
};
|
|
566
570
|
}
|
|
571
|
+
async processFile(filePath, rootDir, nameToFiles, fileContents) {
|
|
572
|
+
let nodesAdded = 0;
|
|
573
|
+
let edgesAdded = 0;
|
|
574
|
+
const relativePath = path.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
575
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
576
|
+
const stat2 = await fs.stat(filePath);
|
|
577
|
+
const fileId = `file:${relativePath}`;
|
|
578
|
+
fileContents.set(relativePath, content);
|
|
579
|
+
const fileNode = {
|
|
580
|
+
id: fileId,
|
|
581
|
+
type: "file",
|
|
582
|
+
name: path.basename(filePath),
|
|
583
|
+
path: relativePath,
|
|
584
|
+
metadata: { language: this.detectLanguage(filePath) },
|
|
585
|
+
lastModified: stat2.mtime.toISOString()
|
|
586
|
+
};
|
|
587
|
+
this.store.addNode(fileNode);
|
|
588
|
+
nodesAdded++;
|
|
589
|
+
const symbols = this.extractSymbols(content, fileId, relativePath);
|
|
590
|
+
for (const { node, edge } of symbols) {
|
|
591
|
+
this.store.addNode(node);
|
|
592
|
+
this.store.addEdge(edge);
|
|
593
|
+
nodesAdded++;
|
|
594
|
+
edgesAdded++;
|
|
595
|
+
this.trackCallable(node, relativePath, nameToFiles);
|
|
596
|
+
}
|
|
597
|
+
const imports = await this.extractImports(content, fileId, relativePath, rootDir);
|
|
598
|
+
for (const edge of imports) {
|
|
599
|
+
this.store.addEdge(edge);
|
|
600
|
+
edgesAdded++;
|
|
601
|
+
}
|
|
602
|
+
return { nodesAdded, edgesAdded };
|
|
603
|
+
}
|
|
604
|
+
trackCallable(node, relativePath, nameToFiles) {
|
|
605
|
+
if (node.type !== "function" && node.type !== "method") return;
|
|
606
|
+
let files = nameToFiles.get(node.name);
|
|
607
|
+
if (!files) {
|
|
608
|
+
files = /* @__PURE__ */ new Set();
|
|
609
|
+
nameToFiles.set(node.name, files);
|
|
610
|
+
}
|
|
611
|
+
files.add(relativePath);
|
|
612
|
+
}
|
|
567
613
|
async findSourceFiles(dir) {
|
|
568
614
|
const results = [];
|
|
569
615
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
@@ -580,149 +626,152 @@ var CodeIngestor = class {
|
|
|
580
626
|
extractSymbols(content, fileId, relativePath) {
|
|
581
627
|
const results = [];
|
|
582
628
|
const lines = content.split("\n");
|
|
583
|
-
|
|
584
|
-
let currentClassId = null;
|
|
585
|
-
let braceDepth = 0;
|
|
586
|
-
let insideClass = false;
|
|
629
|
+
const ctx = { className: null, classId: null, insideClass: false, braceDepth: 0 };
|
|
587
630
|
for (let i = 0; i < lines.length; i++) {
|
|
588
631
|
const line = lines[i];
|
|
589
|
-
|
|
590
|
-
if (
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
id,
|
|
597
|
-
type: "function",
|
|
598
|
-
name,
|
|
599
|
-
path: relativePath,
|
|
600
|
-
location: { fileId, startLine: i + 1, endLine },
|
|
601
|
-
metadata: {
|
|
602
|
-
exported: line.includes("export"),
|
|
603
|
-
cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
|
|
604
|
-
nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
|
|
605
|
-
lineCount: endLine - i,
|
|
606
|
-
parameterCount: this.countParameters(line)
|
|
607
|
-
}
|
|
608
|
-
},
|
|
609
|
-
edge: { from: fileId, to: id, type: "contains" }
|
|
610
|
-
});
|
|
611
|
-
if (!insideClass) {
|
|
612
|
-
currentClassName = null;
|
|
613
|
-
currentClassId = null;
|
|
614
|
-
}
|
|
615
|
-
continue;
|
|
616
|
-
}
|
|
617
|
-
const classMatch = line.match(/(?:export\s+)?class\s+(\w+)/);
|
|
618
|
-
if (classMatch) {
|
|
619
|
-
const name = classMatch[1];
|
|
620
|
-
const id = `class:${relativePath}:${name}`;
|
|
621
|
-
const endLine = this.findClosingBrace(lines, i);
|
|
622
|
-
results.push({
|
|
623
|
-
node: {
|
|
624
|
-
id,
|
|
625
|
-
type: "class",
|
|
626
|
-
name,
|
|
627
|
-
path: relativePath,
|
|
628
|
-
location: { fileId, startLine: i + 1, endLine },
|
|
629
|
-
metadata: { exported: line.includes("export") }
|
|
630
|
-
},
|
|
631
|
-
edge: { from: fileId, to: id, type: "contains" }
|
|
632
|
-
});
|
|
633
|
-
currentClassName = name;
|
|
634
|
-
currentClassId = id;
|
|
635
|
-
insideClass = true;
|
|
636
|
-
braceDepth = 0;
|
|
637
|
-
for (const ch of line) {
|
|
638
|
-
if (ch === "{") braceDepth++;
|
|
639
|
-
if (ch === "}") braceDepth--;
|
|
640
|
-
}
|
|
641
|
-
continue;
|
|
642
|
-
}
|
|
643
|
-
const ifaceMatch = line.match(/(?:export\s+)?interface\s+(\w+)/);
|
|
644
|
-
if (ifaceMatch) {
|
|
645
|
-
const name = ifaceMatch[1];
|
|
646
|
-
const id = `interface:${relativePath}:${name}`;
|
|
647
|
-
const endLine = this.findClosingBrace(lines, i);
|
|
648
|
-
results.push({
|
|
649
|
-
node: {
|
|
650
|
-
id,
|
|
651
|
-
type: "interface",
|
|
652
|
-
name,
|
|
653
|
-
path: relativePath,
|
|
654
|
-
location: { fileId, startLine: i + 1, endLine },
|
|
655
|
-
metadata: { exported: line.includes("export") }
|
|
656
|
-
},
|
|
657
|
-
edge: { from: fileId, to: id, type: "contains" }
|
|
658
|
-
});
|
|
659
|
-
currentClassName = null;
|
|
660
|
-
currentClassId = null;
|
|
661
|
-
insideClass = false;
|
|
662
|
-
continue;
|
|
663
|
-
}
|
|
664
|
-
if (insideClass) {
|
|
665
|
-
for (const ch of line) {
|
|
666
|
-
if (ch === "{") braceDepth++;
|
|
667
|
-
if (ch === "}") braceDepth--;
|
|
668
|
-
}
|
|
669
|
-
if (braceDepth <= 0) {
|
|
670
|
-
currentClassName = null;
|
|
671
|
-
currentClassId = null;
|
|
672
|
-
insideClass = false;
|
|
673
|
-
continue;
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
if (insideClass && currentClassName && currentClassId) {
|
|
677
|
-
const methodMatch = line.match(
|
|
678
|
-
/^\s+(?:(?:public|private|protected|readonly|static|abstract)\s+)*(?:async\s+)?(\w+)\s*\(/
|
|
679
|
-
);
|
|
680
|
-
if (methodMatch) {
|
|
681
|
-
const methodName = methodMatch[1];
|
|
682
|
-
if (methodName === "constructor" || methodName === "if" || methodName === "for" || methodName === "while" || methodName === "switch")
|
|
683
|
-
continue;
|
|
684
|
-
const id = `method:${relativePath}:${currentClassName}.${methodName}`;
|
|
685
|
-
const endLine = this.findClosingBrace(lines, i);
|
|
686
|
-
results.push({
|
|
687
|
-
node: {
|
|
688
|
-
id,
|
|
689
|
-
type: "method",
|
|
690
|
-
name: methodName,
|
|
691
|
-
path: relativePath,
|
|
692
|
-
location: { fileId, startLine: i + 1, endLine },
|
|
693
|
-
metadata: {
|
|
694
|
-
className: currentClassName,
|
|
695
|
-
exported: false,
|
|
696
|
-
cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
|
|
697
|
-
nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
|
|
698
|
-
lineCount: endLine - i,
|
|
699
|
-
parameterCount: this.countParameters(line)
|
|
700
|
-
}
|
|
701
|
-
},
|
|
702
|
-
edge: { from: currentClassId, to: id, type: "contains" }
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
continue;
|
|
706
|
-
}
|
|
707
|
-
const varMatch = line.match(/(?:export\s+)?(?:const|let|var)\s+(\w+)/);
|
|
708
|
-
if (varMatch) {
|
|
709
|
-
const name = varMatch[1];
|
|
710
|
-
const id = `variable:${relativePath}:${name}`;
|
|
711
|
-
results.push({
|
|
712
|
-
node: {
|
|
713
|
-
id,
|
|
714
|
-
type: "variable",
|
|
715
|
-
name,
|
|
716
|
-
path: relativePath,
|
|
717
|
-
location: { fileId, startLine: i + 1, endLine: i + 1 },
|
|
718
|
-
metadata: { exported: line.includes("export") }
|
|
719
|
-
},
|
|
720
|
-
edge: { from: fileId, to: id, type: "contains" }
|
|
721
|
-
});
|
|
722
|
-
}
|
|
632
|
+
if (this.tryExtractFunction(line, lines, i, fileId, relativePath, ctx, results)) continue;
|
|
633
|
+
if (this.tryExtractClass(line, lines, i, fileId, relativePath, ctx, results)) continue;
|
|
634
|
+
if (this.tryExtractInterface(line, lines, i, fileId, relativePath, ctx, results)) continue;
|
|
635
|
+
if (this.updateClassContext(line, ctx)) continue;
|
|
636
|
+
if (this.tryExtractMethod(line, lines, i, fileId, relativePath, ctx, results)) continue;
|
|
637
|
+
if (ctx.insideClass) continue;
|
|
638
|
+
this.tryExtractVariable(line, i, fileId, relativePath, results);
|
|
723
639
|
}
|
|
724
640
|
return results;
|
|
725
641
|
}
|
|
642
|
+
tryExtractFunction(line, lines, i, fileId, relativePath, ctx, results) {
|
|
643
|
+
const fnMatch = line.match(/(?:export\s+)?(?:async\s+)?function\s+(\w+)/);
|
|
644
|
+
if (!fnMatch) return false;
|
|
645
|
+
const name = fnMatch[1];
|
|
646
|
+
const id = `function:${relativePath}:${name}`;
|
|
647
|
+
const endLine = this.findClosingBrace(lines, i);
|
|
648
|
+
results.push({
|
|
649
|
+
node: {
|
|
650
|
+
id,
|
|
651
|
+
type: "function",
|
|
652
|
+
name,
|
|
653
|
+
path: relativePath,
|
|
654
|
+
location: { fileId, startLine: i + 1, endLine },
|
|
655
|
+
metadata: {
|
|
656
|
+
exported: line.includes("export"),
|
|
657
|
+
cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
|
|
658
|
+
nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
|
|
659
|
+
lineCount: endLine - i,
|
|
660
|
+
parameterCount: this.countParameters(line)
|
|
661
|
+
}
|
|
662
|
+
},
|
|
663
|
+
edge: { from: fileId, to: id, type: "contains" }
|
|
664
|
+
});
|
|
665
|
+
if (!ctx.insideClass) {
|
|
666
|
+
ctx.className = null;
|
|
667
|
+
ctx.classId = null;
|
|
668
|
+
}
|
|
669
|
+
return true;
|
|
670
|
+
}
|
|
671
|
+
tryExtractClass(line, lines, i, fileId, relativePath, ctx, results) {
|
|
672
|
+
const classMatch = line.match(/(?:export\s+)?class\s+(\w+)/);
|
|
673
|
+
if (!classMatch) return false;
|
|
674
|
+
const name = classMatch[1];
|
|
675
|
+
const id = `class:${relativePath}:${name}`;
|
|
676
|
+
const endLine = this.findClosingBrace(lines, i);
|
|
677
|
+
results.push({
|
|
678
|
+
node: {
|
|
679
|
+
id,
|
|
680
|
+
type: "class",
|
|
681
|
+
name,
|
|
682
|
+
path: relativePath,
|
|
683
|
+
location: { fileId, startLine: i + 1, endLine },
|
|
684
|
+
metadata: { exported: line.includes("export") }
|
|
685
|
+
},
|
|
686
|
+
edge: { from: fileId, to: id, type: "contains" }
|
|
687
|
+
});
|
|
688
|
+
ctx.className = name;
|
|
689
|
+
ctx.classId = id;
|
|
690
|
+
ctx.insideClass = true;
|
|
691
|
+
ctx.braceDepth = countBraces(line);
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
694
|
+
tryExtractInterface(line, lines, i, fileId, relativePath, ctx, results) {
|
|
695
|
+
const ifaceMatch = line.match(/(?:export\s+)?interface\s+(\w+)/);
|
|
696
|
+
if (!ifaceMatch) return false;
|
|
697
|
+
const name = ifaceMatch[1];
|
|
698
|
+
const id = `interface:${relativePath}:${name}`;
|
|
699
|
+
const endLine = this.findClosingBrace(lines, i);
|
|
700
|
+
results.push({
|
|
701
|
+
node: {
|
|
702
|
+
id,
|
|
703
|
+
type: "interface",
|
|
704
|
+
name,
|
|
705
|
+
path: relativePath,
|
|
706
|
+
location: { fileId, startLine: i + 1, endLine },
|
|
707
|
+
metadata: { exported: line.includes("export") }
|
|
708
|
+
},
|
|
709
|
+
edge: { from: fileId, to: id, type: "contains" }
|
|
710
|
+
});
|
|
711
|
+
ctx.className = null;
|
|
712
|
+
ctx.classId = null;
|
|
713
|
+
ctx.insideClass = false;
|
|
714
|
+
return true;
|
|
715
|
+
}
|
|
716
|
+
/** Update brace tracking; returns true when line is consumed (class ended or tracked). */
|
|
717
|
+
updateClassContext(line, ctx) {
|
|
718
|
+
if (!ctx.insideClass) return false;
|
|
719
|
+
ctx.braceDepth += countBraces(line);
|
|
720
|
+
if (ctx.braceDepth <= 0) {
|
|
721
|
+
ctx.className = null;
|
|
722
|
+
ctx.classId = null;
|
|
723
|
+
ctx.insideClass = false;
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
tryExtractMethod(line, lines, i, fileId, relativePath, ctx, results) {
|
|
729
|
+
if (!ctx.insideClass || !ctx.className || !ctx.classId) return false;
|
|
730
|
+
const methodMatch = line.match(
|
|
731
|
+
/^\s+(?:(?:public|private|protected|readonly|static|abstract)\s+)*(?:async\s+)?(\w+)\s*\(/
|
|
732
|
+
);
|
|
733
|
+
if (!methodMatch) return false;
|
|
734
|
+
const methodName = methodMatch[1];
|
|
735
|
+
if (SKIP_METHOD_NAMES.has(methodName)) return false;
|
|
736
|
+
const id = `method:${relativePath}:${ctx.className}.${methodName}`;
|
|
737
|
+
const endLine = this.findClosingBrace(lines, i);
|
|
738
|
+
results.push({
|
|
739
|
+
node: {
|
|
740
|
+
id,
|
|
741
|
+
type: "method",
|
|
742
|
+
name: methodName,
|
|
743
|
+
path: relativePath,
|
|
744
|
+
location: { fileId, startLine: i + 1, endLine },
|
|
745
|
+
metadata: {
|
|
746
|
+
className: ctx.className,
|
|
747
|
+
exported: false,
|
|
748
|
+
cyclomaticComplexity: this.computeCyclomaticComplexity(lines.slice(i, endLine)),
|
|
749
|
+
nestingDepth: this.computeMaxNesting(lines.slice(i, endLine)),
|
|
750
|
+
lineCount: endLine - i,
|
|
751
|
+
parameterCount: this.countParameters(line)
|
|
752
|
+
}
|
|
753
|
+
},
|
|
754
|
+
edge: { from: ctx.classId, to: id, type: "contains" }
|
|
755
|
+
});
|
|
756
|
+
return true;
|
|
757
|
+
}
|
|
758
|
+
tryExtractVariable(line, i, fileId, relativePath, results) {
|
|
759
|
+
const varMatch = line.match(/(?:export\s+)?(?:const|let|var)\s+(\w+)/);
|
|
760
|
+
if (!varMatch) return;
|
|
761
|
+
const name = varMatch[1];
|
|
762
|
+
const id = `variable:${relativePath}:${name}`;
|
|
763
|
+
results.push({
|
|
764
|
+
node: {
|
|
765
|
+
id,
|
|
766
|
+
type: "variable",
|
|
767
|
+
name,
|
|
768
|
+
path: relativePath,
|
|
769
|
+
location: { fileId, startLine: i + 1, endLine: i + 1 },
|
|
770
|
+
metadata: { exported: line.includes("export") }
|
|
771
|
+
},
|
|
772
|
+
edge: { from: fileId, to: id, type: "contains" }
|
|
773
|
+
});
|
|
774
|
+
}
|
|
726
775
|
/**
|
|
727
776
|
* Find the closing brace for a construct starting at the given line.
|
|
728
777
|
* Uses a simple brace-counting heuristic. Returns 1-indexed line number.
|
|
@@ -1324,17 +1373,33 @@ var KnowledgeIngestor = class {
|
|
|
1324
1373
|
}
|
|
1325
1374
|
};
|
|
1326
1375
|
var CODE_NODE_TYPES2 = ["file", "function", "class", "method", "interface", "variable"];
|
|
1376
|
+
var SANITIZE_RULES = [
|
|
1377
|
+
// Strip XML/HTML-like instruction tags that could be interpreted as system prompts
|
|
1378
|
+
{
|
|
1379
|
+
pattern: /<\/?(?:system|instruction|prompt|role|context|tool_call|function_call|assistant|human|user)[^>]*>/gi,
|
|
1380
|
+
replacement: ""
|
|
1381
|
+
},
|
|
1382
|
+
// Strip markdown-style system prompt markers (including trailing space)
|
|
1383
|
+
{
|
|
1384
|
+
pattern: /^#{1,3}\s*(?:system|instruction|prompt)\s*[::]\s*/gim,
|
|
1385
|
+
replacement: ""
|
|
1386
|
+
},
|
|
1387
|
+
// Strip common injection prefixes
|
|
1388
|
+
{
|
|
1389
|
+
pattern: /(?:ignore|disregard|forget)\s+(?:all\s+)?(?:previous|prior|above)\s+(?:instructions?|prompts?|context)/gi,
|
|
1390
|
+
replacement: "[filtered]"
|
|
1391
|
+
},
|
|
1392
|
+
// Strip "you are now" re-roling attempts (only when followed by AI/agent role words)
|
|
1393
|
+
{
|
|
1394
|
+
pattern: /you\s+are\s+now\s+(?:a\s+)?(?:helpful\s+)?(?:an?\s+)?(?:assistant|system|ai|bot|agent|tool)\b/gi,
|
|
1395
|
+
replacement: "[filtered]"
|
|
1396
|
+
}
|
|
1397
|
+
];
|
|
1327
1398
|
function sanitizeExternalText(text, maxLength = 2e3) {
|
|
1328
|
-
let sanitized = text
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
/(?:ignore|disregard|forget)\s+(?:all\s+)?(?:previous|prior|above)\s+(?:instructions?|prompts?|context)/gi,
|
|
1333
|
-
"[filtered]"
|
|
1334
|
-
).replace(
|
|
1335
|
-
/you\s+are\s+now\s+(?:a\s+)?(?:helpful\s+)?(?:an?\s+)?(?:assistant|system|ai|bot|agent|tool)\b/gi,
|
|
1336
|
-
"[filtered]"
|
|
1337
|
-
);
|
|
1399
|
+
let sanitized = text;
|
|
1400
|
+
for (const rule of SANITIZE_RULES) {
|
|
1401
|
+
sanitized = sanitized.replace(rule.pattern, rule.replacement);
|
|
1402
|
+
}
|
|
1338
1403
|
if (sanitized.length > maxLength) {
|
|
1339
1404
|
sanitized = sanitized.slice(0, maxLength) + "\u2026";
|
|
1340
1405
|
}
|
|
@@ -1428,6 +1493,28 @@ var SyncManager = class {
|
|
|
1428
1493
|
await fs3.writeFile(this.metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
1429
1494
|
}
|
|
1430
1495
|
};
|
|
1496
|
+
function buildIngestResult(nodesAdded, edgesAdded, errors, start) {
|
|
1497
|
+
return {
|
|
1498
|
+
nodesAdded,
|
|
1499
|
+
nodesUpdated: 0,
|
|
1500
|
+
edgesAdded,
|
|
1501
|
+
edgesUpdated: 0,
|
|
1502
|
+
errors,
|
|
1503
|
+
durationMs: Date.now() - start
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
function buildJql(config) {
|
|
1507
|
+
const project2 = config.project;
|
|
1508
|
+
let jql = project2 ? `project=${project2}` : "";
|
|
1509
|
+
const filters = config.filters;
|
|
1510
|
+
if (filters?.status?.length) {
|
|
1511
|
+
jql += `${jql ? " AND " : ""}status IN (${filters.status.map((s) => `"${s}"`).join(",")})`;
|
|
1512
|
+
}
|
|
1513
|
+
if (filters?.labels?.length) {
|
|
1514
|
+
jql += `${jql ? " AND " : ""}labels IN (${filters.labels.map((l) => `"${l}"`).join(",")})`;
|
|
1515
|
+
}
|
|
1516
|
+
return jql;
|
|
1517
|
+
}
|
|
1431
1518
|
var JiraConnector = class {
|
|
1432
1519
|
name = "jira";
|
|
1433
1520
|
source = "jira";
|
|
@@ -1437,105 +1524,81 @@ var JiraConnector = class {
|
|
|
1437
1524
|
}
|
|
1438
1525
|
async ingest(store, config) {
|
|
1439
1526
|
const start = Date.now();
|
|
1440
|
-
const errors = [];
|
|
1441
1527
|
let nodesAdded = 0;
|
|
1442
1528
|
let edgesAdded = 0;
|
|
1443
1529
|
const apiKeyEnv = config.apiKeyEnv ?? "JIRA_API_KEY";
|
|
1444
1530
|
const apiKey = process.env[apiKeyEnv];
|
|
1445
1531
|
if (!apiKey) {
|
|
1446
|
-
return
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
durationMs: Date.now() - start
|
|
1453
|
-
};
|
|
1532
|
+
return buildIngestResult(
|
|
1533
|
+
0,
|
|
1534
|
+
0,
|
|
1535
|
+
[`Missing API key: environment variable "${apiKeyEnv}" is not set`],
|
|
1536
|
+
start
|
|
1537
|
+
);
|
|
1454
1538
|
}
|
|
1455
1539
|
const baseUrlEnv = config.baseUrlEnv ?? "JIRA_BASE_URL";
|
|
1456
1540
|
const baseUrl = process.env[baseUrlEnv];
|
|
1457
1541
|
if (!baseUrl) {
|
|
1458
|
-
return
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
durationMs: Date.now() - start
|
|
1465
|
-
};
|
|
1466
|
-
}
|
|
1467
|
-
const project2 = config.project;
|
|
1468
|
-
let jql = project2 ? `project=${project2}` : "";
|
|
1469
|
-
const filters = config.filters;
|
|
1470
|
-
if (filters?.status?.length) {
|
|
1471
|
-
jql += `${jql ? " AND " : ""}status IN (${filters.status.map((s) => `"${s}"`).join(",")})`;
|
|
1472
|
-
}
|
|
1473
|
-
if (filters?.labels?.length) {
|
|
1474
|
-
jql += `${jql ? " AND " : ""}labels IN (${filters.labels.map((l) => `"${l}"`).join(",")})`;
|
|
1542
|
+
return buildIngestResult(
|
|
1543
|
+
0,
|
|
1544
|
+
0,
|
|
1545
|
+
[`Missing base URL: environment variable "${baseUrlEnv}" is not set`],
|
|
1546
|
+
start
|
|
1547
|
+
);
|
|
1475
1548
|
}
|
|
1549
|
+
const jql = buildJql(config);
|
|
1476
1550
|
const headers = {
|
|
1477
1551
|
Authorization: `Basic ${apiKey}`,
|
|
1478
1552
|
"Content-Type": "application/json"
|
|
1479
1553
|
};
|
|
1480
|
-
let startAt = 0;
|
|
1481
|
-
const maxResults = 50;
|
|
1482
|
-
let total = Infinity;
|
|
1483
1554
|
try {
|
|
1555
|
+
let startAt = 0;
|
|
1556
|
+
const maxResults = 50;
|
|
1557
|
+
let total = Infinity;
|
|
1484
1558
|
while (startAt < total) {
|
|
1485
1559
|
const url = `${baseUrl}/rest/api/2/search?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}`;
|
|
1486
1560
|
const response = await this.httpClient(url, { headers });
|
|
1487
1561
|
if (!response.ok) {
|
|
1488
|
-
return
|
|
1489
|
-
nodesAdded,
|
|
1490
|
-
nodesUpdated: 0,
|
|
1491
|
-
edgesAdded,
|
|
1492
|
-
edgesUpdated: 0,
|
|
1493
|
-
errors: ["Jira API request failed"],
|
|
1494
|
-
durationMs: Date.now() - start
|
|
1495
|
-
};
|
|
1562
|
+
return buildIngestResult(nodesAdded, edgesAdded, ["Jira API request failed"], start);
|
|
1496
1563
|
}
|
|
1497
1564
|
const data = await response.json();
|
|
1498
1565
|
total = data.total;
|
|
1499
1566
|
for (const issue of data.issues) {
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
type: "issue",
|
|
1504
|
-
name: sanitizeExternalText(issue.fields.summary, 500),
|
|
1505
|
-
metadata: {
|
|
1506
|
-
key: issue.key,
|
|
1507
|
-
status: issue.fields.status?.name,
|
|
1508
|
-
priority: issue.fields.priority?.name,
|
|
1509
|
-
assignee: issue.fields.assignee?.displayName,
|
|
1510
|
-
labels: issue.fields.labels ?? []
|
|
1511
|
-
}
|
|
1512
|
-
});
|
|
1513
|
-
nodesAdded++;
|
|
1514
|
-
const searchText = sanitizeExternalText(
|
|
1515
|
-
[issue.fields.summary, issue.fields.description ?? ""].join(" ")
|
|
1516
|
-
);
|
|
1517
|
-
edgesAdded += linkToCode(store, searchText, nodeId, "applies_to");
|
|
1567
|
+
const counts = this.processIssue(store, issue);
|
|
1568
|
+
nodesAdded += counts.nodesAdded;
|
|
1569
|
+
edgesAdded += counts.edgesAdded;
|
|
1518
1570
|
}
|
|
1519
1571
|
startAt += maxResults;
|
|
1520
1572
|
}
|
|
1521
1573
|
} catch (err) {
|
|
1522
|
-
return
|
|
1574
|
+
return buildIngestResult(
|
|
1523
1575
|
nodesAdded,
|
|
1524
|
-
nodesUpdated: 0,
|
|
1525
1576
|
edgesAdded,
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
};
|
|
1577
|
+
[`Jira API error: ${err instanceof Error ? err.message : String(err)}`],
|
|
1578
|
+
start
|
|
1579
|
+
);
|
|
1530
1580
|
}
|
|
1531
|
-
return
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1581
|
+
return buildIngestResult(nodesAdded, edgesAdded, [], start);
|
|
1582
|
+
}
|
|
1583
|
+
processIssue(store, issue) {
|
|
1584
|
+
const nodeId = `issue:jira:${issue.key}`;
|
|
1585
|
+
store.addNode({
|
|
1586
|
+
id: nodeId,
|
|
1587
|
+
type: "issue",
|
|
1588
|
+
name: sanitizeExternalText(issue.fields.summary, 500),
|
|
1589
|
+
metadata: {
|
|
1590
|
+
key: issue.key,
|
|
1591
|
+
status: issue.fields.status?.name,
|
|
1592
|
+
priority: issue.fields.priority?.name,
|
|
1593
|
+
assignee: issue.fields.assignee?.displayName,
|
|
1594
|
+
labels: issue.fields.labels ?? []
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1597
|
+
const searchText = sanitizeExternalText(
|
|
1598
|
+
[issue.fields.summary, issue.fields.description ?? ""].join(" ")
|
|
1599
|
+
);
|
|
1600
|
+
const edgesAdded = linkToCode(store, searchText, nodeId, "applies_to");
|
|
1601
|
+
return { nodesAdded: 1, edgesAdded };
|
|
1539
1602
|
}
|
|
1540
1603
|
};
|
|
1541
1604
|
var SlackConnector = class {
|
|
@@ -1566,44 +1629,10 @@ var SlackConnector = class {
|
|
|
1566
1629
|
const oldest = config.lookbackDays ? String(Math.floor((Date.now() - Number(config.lookbackDays) * 864e5) / 1e3)) : void 0;
|
|
1567
1630
|
for (const channel of channels) {
|
|
1568
1631
|
try {
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
const response = await this.httpClient(url, {
|
|
1574
|
-
headers: {
|
|
1575
|
-
Authorization: `Bearer ${apiKey}`,
|
|
1576
|
-
"Content-Type": "application/json"
|
|
1577
|
-
}
|
|
1578
|
-
});
|
|
1579
|
-
if (!response.ok) {
|
|
1580
|
-
errors.push(`Slack API request failed for channel ${channel}`);
|
|
1581
|
-
continue;
|
|
1582
|
-
}
|
|
1583
|
-
const data = await response.json();
|
|
1584
|
-
if (!data.ok) {
|
|
1585
|
-
errors.push(`Slack API error for channel ${channel}`);
|
|
1586
|
-
continue;
|
|
1587
|
-
}
|
|
1588
|
-
for (const message of data.messages) {
|
|
1589
|
-
const nodeId = `conversation:slack:${channel}:${message.ts}`;
|
|
1590
|
-
const sanitizedText = sanitizeExternalText(message.text);
|
|
1591
|
-
const snippet = sanitizedText.length > 100 ? sanitizedText.slice(0, 100) : sanitizedText;
|
|
1592
|
-
store.addNode({
|
|
1593
|
-
id: nodeId,
|
|
1594
|
-
type: "conversation",
|
|
1595
|
-
name: snippet,
|
|
1596
|
-
metadata: {
|
|
1597
|
-
author: message.user,
|
|
1598
|
-
channel,
|
|
1599
|
-
timestamp: message.ts
|
|
1600
|
-
}
|
|
1601
|
-
});
|
|
1602
|
-
nodesAdded++;
|
|
1603
|
-
edgesAdded += linkToCode(store, sanitizedText, nodeId, "references", {
|
|
1604
|
-
checkPaths: true
|
|
1605
|
-
});
|
|
1606
|
-
}
|
|
1632
|
+
const result = await this.processChannel(store, channel, apiKey, oldest);
|
|
1633
|
+
nodesAdded += result.nodesAdded;
|
|
1634
|
+
edgesAdded += result.edgesAdded;
|
|
1635
|
+
errors.push(...result.errors);
|
|
1607
1636
|
} catch (err) {
|
|
1608
1637
|
errors.push(
|
|
1609
1638
|
`Slack API error for channel ${channel}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -1619,6 +1648,52 @@ var SlackConnector = class {
|
|
|
1619
1648
|
durationMs: Date.now() - start
|
|
1620
1649
|
};
|
|
1621
1650
|
}
|
|
1651
|
+
async processChannel(store, channel, apiKey, oldest) {
|
|
1652
|
+
const errors = [];
|
|
1653
|
+
let nodesAdded = 0;
|
|
1654
|
+
let edgesAdded = 0;
|
|
1655
|
+
let url = `https://slack.com/api/conversations.history?channel=${encodeURIComponent(channel)}`;
|
|
1656
|
+
if (oldest) {
|
|
1657
|
+
url += `&oldest=${oldest}`;
|
|
1658
|
+
}
|
|
1659
|
+
const response = await this.httpClient(url, {
|
|
1660
|
+
headers: {
|
|
1661
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1662
|
+
"Content-Type": "application/json"
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1665
|
+
if (!response.ok) {
|
|
1666
|
+
return {
|
|
1667
|
+
nodesAdded: 0,
|
|
1668
|
+
edgesAdded: 0,
|
|
1669
|
+
errors: [`Slack API request failed for channel ${channel}`]
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
const data = await response.json();
|
|
1673
|
+
if (!data.ok) {
|
|
1674
|
+
return { nodesAdded: 0, edgesAdded: 0, errors: [`Slack API error for channel ${channel}`] };
|
|
1675
|
+
}
|
|
1676
|
+
for (const message of data.messages) {
|
|
1677
|
+
const nodeId = `conversation:slack:${channel}:${message.ts}`;
|
|
1678
|
+
const sanitizedText = sanitizeExternalText(message.text);
|
|
1679
|
+
const snippet = sanitizedText.length > 100 ? sanitizedText.slice(0, 100) : sanitizedText;
|
|
1680
|
+
store.addNode({
|
|
1681
|
+
id: nodeId,
|
|
1682
|
+
type: "conversation",
|
|
1683
|
+
name: snippet,
|
|
1684
|
+
metadata: {
|
|
1685
|
+
author: message.user,
|
|
1686
|
+
channel,
|
|
1687
|
+
timestamp: message.ts
|
|
1688
|
+
}
|
|
1689
|
+
});
|
|
1690
|
+
nodesAdded++;
|
|
1691
|
+
edgesAdded += linkToCode(store, sanitizedText, nodeId, "references", {
|
|
1692
|
+
checkPaths: true
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
return { nodesAdded, edgesAdded, errors };
|
|
1696
|
+
}
|
|
1622
1697
|
};
|
|
1623
1698
|
var ConfluenceConnector = class {
|
|
1624
1699
|
name = "confluence";
|
|
@@ -1648,36 +1723,10 @@ var ConfluenceConnector = class {
|
|
|
1648
1723
|
const baseUrl = process.env[baseUrlEnv] ?? "";
|
|
1649
1724
|
const spaceKey = config.spaceKey ?? "";
|
|
1650
1725
|
try {
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
});
|
|
1656
|
-
if (!response.ok) {
|
|
1657
|
-
errors.push(`Confluence API error: status ${response.status}`);
|
|
1658
|
-
break;
|
|
1659
|
-
}
|
|
1660
|
-
const data = await response.json();
|
|
1661
|
-
for (const page of data.results) {
|
|
1662
|
-
const nodeId = `confluence:${page.id}`;
|
|
1663
|
-
store.addNode({
|
|
1664
|
-
id: nodeId,
|
|
1665
|
-
type: "document",
|
|
1666
|
-
name: sanitizeExternalText(page.title, 500),
|
|
1667
|
-
metadata: {
|
|
1668
|
-
source: "confluence",
|
|
1669
|
-
spaceKey,
|
|
1670
|
-
pageId: page.id,
|
|
1671
|
-
status: page.status,
|
|
1672
|
-
url: page._links?.webui ?? ""
|
|
1673
|
-
}
|
|
1674
|
-
});
|
|
1675
|
-
nodesAdded++;
|
|
1676
|
-
const text = sanitizeExternalText(`${page.title} ${page.body?.storage?.value ?? ""}`);
|
|
1677
|
-
edgesAdded += linkToCode(store, text, nodeId, "documents");
|
|
1678
|
-
}
|
|
1679
|
-
nextUrl = data._links?.next ? `${baseUrl}${data._links.next}` : null;
|
|
1680
|
-
}
|
|
1726
|
+
const result = await this.fetchAllPages(store, baseUrl, apiKey, spaceKey);
|
|
1727
|
+
nodesAdded = result.nodesAdded;
|
|
1728
|
+
edgesAdded = result.edgesAdded;
|
|
1729
|
+
errors.push(...result.errors);
|
|
1681
1730
|
} catch (err) {
|
|
1682
1731
|
errors.push(`Confluence fetch error: ${err instanceof Error ? err.message : String(err)}`);
|
|
1683
1732
|
}
|
|
@@ -1690,6 +1739,47 @@ var ConfluenceConnector = class {
|
|
|
1690
1739
|
durationMs: Date.now() - start
|
|
1691
1740
|
};
|
|
1692
1741
|
}
|
|
1742
|
+
async fetchAllPages(store, baseUrl, apiKey, spaceKey) {
|
|
1743
|
+
const errors = [];
|
|
1744
|
+
let nodesAdded = 0;
|
|
1745
|
+
let edgesAdded = 0;
|
|
1746
|
+
let nextUrl = `${baseUrl}/wiki/api/v2/pages?spaceKey=${encodeURIComponent(spaceKey)}&limit=25&body-format=storage`;
|
|
1747
|
+
while (nextUrl) {
|
|
1748
|
+
const response = await this.httpClient(nextUrl, {
|
|
1749
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1750
|
+
});
|
|
1751
|
+
if (!response.ok) {
|
|
1752
|
+
errors.push(`Confluence API error: status ${response.status}`);
|
|
1753
|
+
break;
|
|
1754
|
+
}
|
|
1755
|
+
const data = await response.json();
|
|
1756
|
+
for (const page of data.results) {
|
|
1757
|
+
const counts = this.processPage(store, page, spaceKey);
|
|
1758
|
+
nodesAdded += counts.nodesAdded;
|
|
1759
|
+
edgesAdded += counts.edgesAdded;
|
|
1760
|
+
}
|
|
1761
|
+
nextUrl = data._links?.next ? `${baseUrl}${data._links.next}` : null;
|
|
1762
|
+
}
|
|
1763
|
+
return { nodesAdded, edgesAdded, errors };
|
|
1764
|
+
}
|
|
1765
|
+
processPage(store, page, spaceKey) {
|
|
1766
|
+
const nodeId = `confluence:${page.id}`;
|
|
1767
|
+
store.addNode({
|
|
1768
|
+
id: nodeId,
|
|
1769
|
+
type: "document",
|
|
1770
|
+
name: sanitizeExternalText(page.title, 500),
|
|
1771
|
+
metadata: {
|
|
1772
|
+
source: "confluence",
|
|
1773
|
+
spaceKey,
|
|
1774
|
+
pageId: page.id,
|
|
1775
|
+
status: page.status,
|
|
1776
|
+
url: page._links?.webui ?? ""
|
|
1777
|
+
}
|
|
1778
|
+
});
|
|
1779
|
+
const text = sanitizeExternalText(`${page.title} ${page.body?.storage?.value ?? ""}`);
|
|
1780
|
+
const edgesAdded = linkToCode(store, text, nodeId, "documents");
|
|
1781
|
+
return { nodesAdded: 1, edgesAdded };
|
|
1782
|
+
}
|
|
1693
1783
|
};
|
|
1694
1784
|
var CIConnector = class {
|
|
1695
1785
|
name = "ci";
|
|
@@ -1976,22 +2066,25 @@ var GraphEntropyAdapter = class {
|
|
|
1976
2066
|
* 3. Unreachable = code nodes NOT in visited set
|
|
1977
2067
|
*/
|
|
1978
2068
|
computeDeadCodeData() {
|
|
1979
|
-
const
|
|
2069
|
+
const entryPoints = this.findEntryPoints();
|
|
2070
|
+
const visited = this.bfsFromEntryPoints(entryPoints);
|
|
2071
|
+
const unreachableNodes = this.collectUnreachableNodes(visited);
|
|
2072
|
+
return { reachableNodeIds: visited, unreachableNodes, entryPoints };
|
|
2073
|
+
}
|
|
2074
|
+
findEntryPoints() {
|
|
1980
2075
|
const entryPoints = [];
|
|
1981
|
-
for (const node of allFileNodes) {
|
|
1982
|
-
if (node.name === "index.ts" || node.metadata?.entryPoint === true) {
|
|
1983
|
-
entryPoints.push(node.id);
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
2076
|
for (const nodeType of CODE_NODE_TYPES3) {
|
|
1987
|
-
if (nodeType === "file") continue;
|
|
1988
2077
|
const nodes = this.store.findNodes({ type: nodeType });
|
|
1989
2078
|
for (const node of nodes) {
|
|
1990
|
-
|
|
2079
|
+
const isIndexFile = nodeType === "file" && node.name === "index.ts";
|
|
2080
|
+
if (isIndexFile || node.metadata?.entryPoint === true) {
|
|
1991
2081
|
entryPoints.push(node.id);
|
|
1992
2082
|
}
|
|
1993
2083
|
}
|
|
1994
2084
|
}
|
|
2085
|
+
return entryPoints;
|
|
2086
|
+
}
|
|
2087
|
+
bfsFromEntryPoints(entryPoints) {
|
|
1995
2088
|
const visited = /* @__PURE__ */ new Set();
|
|
1996
2089
|
const queue = [...entryPoints];
|
|
1997
2090
|
let head = 0;
|
|
@@ -1999,25 +2092,22 @@ var GraphEntropyAdapter = class {
|
|
|
1999
2092
|
const nodeId = queue[head++];
|
|
2000
2093
|
if (visited.has(nodeId)) continue;
|
|
2001
2094
|
visited.add(nodeId);
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
queue.push(edge.to);
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
const containsEdges = this.store.getEdges({ from: nodeId, type: "contains" });
|
|
2015
|
-
for (const edge of containsEdges) {
|
|
2095
|
+
this.enqueueOutboundEdges(nodeId, visited, queue);
|
|
2096
|
+
}
|
|
2097
|
+
return visited;
|
|
2098
|
+
}
|
|
2099
|
+
enqueueOutboundEdges(nodeId, visited, queue) {
|
|
2100
|
+
const edgeTypes = ["imports", "calls", "contains"];
|
|
2101
|
+
for (const edgeType of edgeTypes) {
|
|
2102
|
+
const edges = this.store.getEdges({ from: nodeId, type: edgeType });
|
|
2103
|
+
for (const edge of edges) {
|
|
2016
2104
|
if (!visited.has(edge.to)) {
|
|
2017
2105
|
queue.push(edge.to);
|
|
2018
2106
|
}
|
|
2019
2107
|
}
|
|
2020
2108
|
}
|
|
2109
|
+
}
|
|
2110
|
+
collectUnreachableNodes(visited) {
|
|
2021
2111
|
const unreachableNodes = [];
|
|
2022
2112
|
for (const nodeType of CODE_NODE_TYPES3) {
|
|
2023
2113
|
const nodes = this.store.findNodes({ type: nodeType });
|
|
@@ -2032,11 +2122,7 @@ var GraphEntropyAdapter = class {
|
|
|
2032
2122
|
}
|
|
2033
2123
|
}
|
|
2034
2124
|
}
|
|
2035
|
-
return
|
|
2036
|
-
reachableNodeIds: visited,
|
|
2037
|
-
unreachableNodes,
|
|
2038
|
-
entryPoints
|
|
2039
|
-
};
|
|
2125
|
+
return unreachableNodes;
|
|
2040
2126
|
}
|
|
2041
2127
|
/**
|
|
2042
2128
|
* Count all nodes and edges by type.
|
|
@@ -2085,33 +2171,9 @@ var GraphComplexityAdapter = class {
|
|
|
2085
2171
|
const hotspots = [];
|
|
2086
2172
|
for (const fnNode of functionNodes) {
|
|
2087
2173
|
const complexity = fnNode.metadata?.cyclomaticComplexity ?? 1;
|
|
2088
|
-
const
|
|
2089
|
-
let fileId;
|
|
2090
|
-
for (const edge of containsEdges) {
|
|
2091
|
-
const sourceNode = this.store.getNode(edge.from);
|
|
2092
|
-
if (sourceNode?.type === "file") {
|
|
2093
|
-
fileId = sourceNode.id;
|
|
2094
|
-
break;
|
|
2095
|
-
}
|
|
2096
|
-
if (sourceNode?.type === "class") {
|
|
2097
|
-
const classContainsEdges = this.store.getEdges({ to: sourceNode.id, type: "contains" });
|
|
2098
|
-
for (const classEdge of classContainsEdges) {
|
|
2099
|
-
const parentNode = this.store.getNode(classEdge.from);
|
|
2100
|
-
if (parentNode?.type === "file") {
|
|
2101
|
-
fileId = parentNode.id;
|
|
2102
|
-
break;
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
if (fileId) break;
|
|
2106
|
-
}
|
|
2107
|
-
}
|
|
2174
|
+
const fileId = this.findContainingFileId(fnNode.id);
|
|
2108
2175
|
if (!fileId) continue;
|
|
2109
|
-
|
|
2110
|
-
if (changeFrequency === void 0) {
|
|
2111
|
-
const referencesEdges = this.store.getEdges({ to: fileId, type: "references" });
|
|
2112
|
-
changeFrequency = referencesEdges.length;
|
|
2113
|
-
fileChangeFrequency.set(fileId, changeFrequency);
|
|
2114
|
-
}
|
|
2176
|
+
const changeFrequency = this.getChangeFrequency(fileId, fileChangeFrequency);
|
|
2115
2177
|
const hotspotScore = changeFrequency * complexity;
|
|
2116
2178
|
const filePath = fnNode.path ?? fileId.replace(/^file:/, "");
|
|
2117
2179
|
hotspots.push({
|
|
@@ -2129,6 +2191,39 @@ var GraphComplexityAdapter = class {
|
|
|
2129
2191
|
);
|
|
2130
2192
|
return { hotspots, percentile95Score };
|
|
2131
2193
|
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Walk the 'contains' edges to find the file node that contains a given function/method.
|
|
2196
|
+
* For methods, walks through the intermediate class node.
|
|
2197
|
+
*/
|
|
2198
|
+
findContainingFileId(nodeId) {
|
|
2199
|
+
const containsEdges = this.store.getEdges({ to: nodeId, type: "contains" });
|
|
2200
|
+
for (const edge of containsEdges) {
|
|
2201
|
+
const sourceNode = this.store.getNode(edge.from);
|
|
2202
|
+
if (sourceNode?.type === "file") return sourceNode.id;
|
|
2203
|
+
if (sourceNode?.type === "class") {
|
|
2204
|
+
const fileId = this.findParentFileOfClass(sourceNode.id);
|
|
2205
|
+
if (fileId) return fileId;
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
return void 0;
|
|
2209
|
+
}
|
|
2210
|
+
findParentFileOfClass(classNodeId) {
|
|
2211
|
+
const classContainsEdges = this.store.getEdges({ to: classNodeId, type: "contains" });
|
|
2212
|
+
for (const classEdge of classContainsEdges) {
|
|
2213
|
+
const parentNode = this.store.getNode(classEdge.from);
|
|
2214
|
+
if (parentNode?.type === "file") return parentNode.id;
|
|
2215
|
+
}
|
|
2216
|
+
return void 0;
|
|
2217
|
+
}
|
|
2218
|
+
getChangeFrequency(fileId, cache) {
|
|
2219
|
+
let freq = cache.get(fileId);
|
|
2220
|
+
if (freq === void 0) {
|
|
2221
|
+
const referencesEdges = this.store.getEdges({ to: fileId, type: "references" });
|
|
2222
|
+
freq = referencesEdges.length;
|
|
2223
|
+
cache.set(fileId, freq);
|
|
2224
|
+
}
|
|
2225
|
+
return freq;
|
|
2226
|
+
}
|
|
2132
2227
|
computePercentile(descendingScores, percentile) {
|
|
2133
2228
|
if (descendingScores.length === 0) return 0;
|
|
2134
2229
|
const ascending = [...descendingScores].sort((a, b) => a - b);
|
|
@@ -2766,6 +2861,23 @@ var STOP_WORDS2 = /* @__PURE__ */ new Set([
|
|
|
2766
2861
|
var PASCAL_OR_CAMEL_RE = /\b([A-Z][a-z]+[A-Za-z]*[a-z][A-Za-z]*|[a-z]+[A-Z][A-Za-z]*)\b/g;
|
|
2767
2862
|
var FILE_PATH_RE = /(?:\.\/|[a-zA-Z0-9_-]+\/)[a-zA-Z0-9_\-./]+\.[a-zA-Z]{1,10}/g;
|
|
2768
2863
|
var QUOTED_RE = /["']([^"']+)["']/g;
|
|
2864
|
+
function isSkippableWord(cleaned, allConsumed) {
|
|
2865
|
+
if (allConsumed.has(cleaned)) return true;
|
|
2866
|
+
const lower = cleaned.toLowerCase();
|
|
2867
|
+
if (STOP_WORDS2.has(lower)) return true;
|
|
2868
|
+
if (INTENT_KEYWORDS.has(lower)) return true;
|
|
2869
|
+
if (cleaned === cleaned.toUpperCase() && /^[A-Z]+$/.test(cleaned)) return true;
|
|
2870
|
+
return false;
|
|
2871
|
+
}
|
|
2872
|
+
function buildConsumedSet(quotedConsumed, casingConsumed, pathConsumed) {
|
|
2873
|
+
const quotedWords = /* @__PURE__ */ new Set();
|
|
2874
|
+
for (const q of quotedConsumed) {
|
|
2875
|
+
for (const w of q.split(/\s+/)) {
|
|
2876
|
+
if (w.length > 0) quotedWords.add(w);
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
return /* @__PURE__ */ new Set([...quotedConsumed, ...quotedWords, ...casingConsumed, ...pathConsumed]);
|
|
2880
|
+
}
|
|
2769
2881
|
var EntityExtractor = class {
|
|
2770
2882
|
/**
|
|
2771
2883
|
* Extract candidate entity mentions from a natural language query.
|
|
@@ -2806,27 +2918,12 @@ var EntityExtractor = class {
|
|
|
2806
2918
|
add(path6);
|
|
2807
2919
|
pathConsumed.add(path6);
|
|
2808
2920
|
}
|
|
2809
|
-
const
|
|
2810
|
-
for (const q of quotedConsumed) {
|
|
2811
|
-
for (const w of q.split(/\s+/)) {
|
|
2812
|
-
if (w.length > 0) quotedWords.add(w);
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
const allConsumed = /* @__PURE__ */ new Set([
|
|
2816
|
-
...quotedConsumed,
|
|
2817
|
-
...quotedWords,
|
|
2818
|
-
...casingConsumed,
|
|
2819
|
-
...pathConsumed
|
|
2820
|
-
]);
|
|
2921
|
+
const allConsumed = buildConsumedSet(quotedConsumed, casingConsumed, pathConsumed);
|
|
2821
2922
|
const words = trimmed.split(/\s+/);
|
|
2822
2923
|
for (const raw of words) {
|
|
2823
2924
|
const cleaned = raw.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "");
|
|
2824
2925
|
if (cleaned.length === 0) continue;
|
|
2825
|
-
|
|
2826
|
-
if (allConsumed.has(cleaned)) continue;
|
|
2827
|
-
if (STOP_WORDS2.has(lower)) continue;
|
|
2828
|
-
if (INTENT_KEYWORDS.has(lower)) continue;
|
|
2829
|
-
if (cleaned === cleaned.toUpperCase() && /^[A-Z]+$/.test(cleaned)) continue;
|
|
2926
|
+
if (isSkippableWord(cleaned, allConsumed)) continue;
|
|
2830
2927
|
add(cleaned);
|
|
2831
2928
|
}
|
|
2832
2929
|
return result;
|
|
@@ -3141,14 +3238,20 @@ var Assembler = class {
|
|
|
3141
3238
|
const fusion = this.getFusionLayer();
|
|
3142
3239
|
const topResults = fusion.search(intent, 10);
|
|
3143
3240
|
if (topResults.length === 0) {
|
|
3144
|
-
return {
|
|
3145
|
-
nodes: [],
|
|
3146
|
-
edges: [],
|
|
3147
|
-
tokenEstimate: 0,
|
|
3148
|
-
intent,
|
|
3149
|
-
truncated: false
|
|
3150
|
-
};
|
|
3241
|
+
return { nodes: [], edges: [], tokenEstimate: 0, intent, truncated: false };
|
|
3151
3242
|
}
|
|
3243
|
+
const { nodeMap, collectedEdges, nodeScores } = this.expandSearchResults(topResults);
|
|
3244
|
+
const sortedNodes = Array.from(nodeMap.values()).sort((a, b) => {
|
|
3245
|
+
return (nodeScores.get(b.id) ?? 0) - (nodeScores.get(a.id) ?? 0);
|
|
3246
|
+
});
|
|
3247
|
+
const { keptNodes, tokenEstimate, truncated } = this.truncateToFit(sortedNodes, tokenBudget);
|
|
3248
|
+
const keptNodeIds = new Set(keptNodes.map((n) => n.id));
|
|
3249
|
+
const keptEdges = collectedEdges.filter(
|
|
3250
|
+
(e) => keptNodeIds.has(e.from) && keptNodeIds.has(e.to)
|
|
3251
|
+
);
|
|
3252
|
+
return { nodes: keptNodes, edges: keptEdges, tokenEstimate, intent, truncated };
|
|
3253
|
+
}
|
|
3254
|
+
expandSearchResults(topResults) {
|
|
3152
3255
|
const contextQL = new ContextQL(this.store);
|
|
3153
3256
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
3154
3257
|
const edgeSet = /* @__PURE__ */ new Set();
|
|
@@ -3176,9 +3279,9 @@ var Assembler = class {
|
|
|
3176
3279
|
}
|
|
3177
3280
|
}
|
|
3178
3281
|
}
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3282
|
+
return { nodeMap, collectedEdges, nodeScores };
|
|
3283
|
+
}
|
|
3284
|
+
truncateToFit(sortedNodes, tokenBudget) {
|
|
3182
3285
|
let tokenEstimate = 0;
|
|
3183
3286
|
const keptNodes = [];
|
|
3184
3287
|
let truncated = false;
|
|
@@ -3191,17 +3294,7 @@ var Assembler = class {
|
|
|
3191
3294
|
tokenEstimate += nodeTokens;
|
|
3192
3295
|
keptNodes.push(node);
|
|
3193
3296
|
}
|
|
3194
|
-
|
|
3195
|
-
const keptEdges = collectedEdges.filter(
|
|
3196
|
-
(e) => keptNodeIds.has(e.from) && keptNodeIds.has(e.to)
|
|
3197
|
-
);
|
|
3198
|
-
return {
|
|
3199
|
-
nodes: keptNodes,
|
|
3200
|
-
edges: keptEdges,
|
|
3201
|
-
tokenEstimate,
|
|
3202
|
-
intent,
|
|
3203
|
-
truncated
|
|
3204
|
-
};
|
|
3297
|
+
return { keptNodes, tokenEstimate, truncated };
|
|
3205
3298
|
}
|
|
3206
3299
|
/**
|
|
3207
3300
|
* Compute a token budget allocation across node types.
|
|
@@ -3370,8 +3463,8 @@ var GraphConstraintAdapter = class {
|
|
|
3370
3463
|
const { edges } = this.computeDependencyGraph();
|
|
3371
3464
|
const violations = [];
|
|
3372
3465
|
for (const edge of edges) {
|
|
3373
|
-
const fromRelative = relative2(rootDir, edge.from);
|
|
3374
|
-
const toRelative = relative2(rootDir, edge.to);
|
|
3466
|
+
const fromRelative = relative2(rootDir, edge.from).replaceAll("\\", "/");
|
|
3467
|
+
const toRelative = relative2(rootDir, edge.to).replaceAll("\\", "/");
|
|
3375
3468
|
const fromLayer = this.resolveLayer(fromRelative, layers);
|
|
3376
3469
|
const toLayer = this.resolveLayer(toRelative, layers);
|
|
3377
3470
|
if (!fromLayer || !toLayer) continue;
|