@harness-engineering/cli 1.13.0 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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.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.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.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.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.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.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.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.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.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.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.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.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.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.yaml +1 -0
- package/dist/agents/skills/gemini-cli/validate-context-engineering/skill.yaml +1 -0
- package/dist/{agents-md-P2RHSUV7.js → agents-md-XU3BHE22.js} +1 -1
- package/dist/{architecture-ESOOE26S.js → architecture-2R5Z4ZAF.js} +2 -2
- package/dist/bin/harness-mcp.js +14 -13
- package/dist/bin/harness.js +22 -21
- package/dist/{check-phase-gate-S2MZKLFQ.js → check-phase-gate-2OFZ7OWW.js} +3 -2
- package/dist/{chunk-LD3DKUK5.js → chunk-4ZMOCPYO.js} +1 -1
- package/dist/{chunk-5VY23YK3.js → chunk-65FRIL4D.js} +2 -2
- package/dist/{chunk-L2KLU56K.js → chunk-AOZRDOIP.js} +2 -2
- package/dist/{chunk-MACVXDZK.js → chunk-DZS7CJKL.js} +4 -4
- package/dist/{chunk-7PZWR4LI.js → chunk-IM32EEDM.js} +9 -9
- package/dist/{chunk-2YPZKGAG.js → chunk-IMFVFNJE.js} +1 -1
- package/dist/{chunk-HD4IBGLA.js → chunk-N5G5QMS3.js} +24 -1
- package/dist/{chunk-MI5XJQDY.js → chunk-ND6PNADU.js} +23 -9
- package/dist/{chunk-7KQSUZVG.js → chunk-NERR4TAO.js} +729 -436
- package/dist/{chunk-PSNN4LWX.js → chunk-NOPU4RZ4.js} +2 -2
- package/dist/{chunk-KELT6K6M.js → chunk-PQ5YK4AY.js} +287 -258
- package/dist/{chunk-WPPDRIJL.js → chunk-QY4T6YAZ.js} +3 -3
- package/dist/{chunk-RZSUJBZZ.js → chunk-SSKDAOX5.js} +31 -28
- package/dist/{chunk-2VU4MFM3.js → chunk-TKJZKICB.js} +6 -6
- package/dist/{chunk-GNGELAXY.js → chunk-TS3XWPW5.js} +1 -1
- package/dist/chunk-UAX4I5ZE.js +217 -0
- package/dist/{chunk-VRFZWGMS.js → chunk-XYLGHKG6.js} +5 -1
- package/dist/{chunk-6N4R6FVX.js → chunk-YBJ262QL.js} +1 -1
- package/dist/{chunk-3KOLLWWE.js → chunk-Z77YQRQT.js} +11 -207
- package/dist/{ci-workflow-4NYBUG6R.js → ci-workflow-EHV65NQB.js} +1 -1
- package/dist/{create-skill-WPXHSLX2.js → create-skill-XSWHMSM5.js} +2 -2
- package/dist/{dist-WF4C7A4A.js → dist-2B363XUH.js} +1 -1
- package/dist/{dist-M6BQODWC.js → dist-HXHWB7SV.js} +2 -2
- package/dist/{docs-BPYCN2DR.js → docs-FZOPM4GK.js} +4 -2
- package/dist/{engine-LXLIWQQ3.js → engine-OL4T6NZS.js} +1 -1
- package/dist/{entropy-4VDVV5CR.js → entropy-LVHJMFGH.js} +2 -2
- package/dist/{feedback-63QB5RCA.js → feedback-IHLVLMRD.js} +1 -1
- package/dist/{generate-agent-definitions-QABOJG56.js → generate-agent-definitions-64S3CLEZ.js} +3 -3
- package/dist/{glob-helper-5OHBUQAI.js → glob-helper-R5FXNUPS.js} +1 -1
- package/dist/{graph-loader-KO4GJ5N2.js → graph-loader-GJZ4FN4Y.js} +1 -1
- package/dist/index.d.ts +35 -8
- package/dist/index.js +23 -21
- package/dist/{loader-Z2IT7QX3.js → loader-DPYFB6R6.js} +1 -1
- package/dist/{mcp-KQHEL5IF.js → mcp-JQUI7BVZ.js} +14 -13
- package/dist/{performance-26BH47O4.js → performance-ZTVSUANN.js} +2 -2
- package/dist/{review-pipeline-GHR3WFBI.js → review-pipeline-76JHKGSV.js} +1 -1
- package/dist/{runtime-PDWD7UIK.js → runtime-X7U6SC7K.js} +1 -1
- package/dist/{security-UQFUZXEN.js → security-FWQZF2IZ.js} +1 -1
- package/dist/skill-executor-XZLYZYAK.js +8 -0
- package/dist/{validate-N7QJOKFZ.js → validate-GCHZJIL7.js} +2 -2
- package/dist/{validate-cross-check-EDQ5QGTM.js → validate-cross-check-STFHYMAZ.js} +1 -1
- package/package.json +3 -3
- package/dist/skill-executor-RG45LUO5.js +0 -8
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectEntropyDefinition,
|
|
3
3
|
handleDetectEntropy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DZS7CJKL.js";
|
|
5
5
|
import {
|
|
6
6
|
checkPerformanceDefinition,
|
|
7
7
|
getCriticalPathsDefinition,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
handleGetPerfBaselines,
|
|
12
12
|
handleUpdatePerfBaselines,
|
|
13
13
|
updatePerfBaselinesDefinition
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-TKJZKICB.js";
|
|
15
15
|
import {
|
|
16
16
|
analyzeDiffDefinition,
|
|
17
17
|
createSelfReviewDefinition,
|
|
@@ -19,15 +19,15 @@ import {
|
|
|
19
19
|
handleCreateSelfReview,
|
|
20
20
|
handleRequestPeerReview,
|
|
21
21
|
requestPeerReviewDefinition
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-IM32EEDM.js";
|
|
23
23
|
import {
|
|
24
24
|
handleRunSecurityScan,
|
|
25
25
|
runSecurityScanDefinition
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-65FRIL4D.js";
|
|
27
27
|
import {
|
|
28
28
|
handleRunCodeReview,
|
|
29
29
|
runCodeReviewDefinition
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-4ZMOCPYO.js";
|
|
31
31
|
import {
|
|
32
32
|
GENERATED_HEADER_CLAUDE,
|
|
33
33
|
GENERATED_HEADER_GEMINI,
|
|
@@ -38,21 +38,24 @@ import {
|
|
|
38
38
|
import {
|
|
39
39
|
handleValidateProject,
|
|
40
40
|
validateToolDefinition
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-NOPU4RZ4.js";
|
|
42
42
|
import {
|
|
43
43
|
loadGraphStore
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-IMFVFNJE.js";
|
|
45
45
|
import {
|
|
46
46
|
checkDependenciesDefinition,
|
|
47
47
|
handleCheckDependencies
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-QY4T6YAZ.js";
|
|
49
49
|
import {
|
|
50
50
|
resolveProjectConfig
|
|
51
51
|
} from "./chunk-K6XAPGML.js";
|
|
52
52
|
import {
|
|
53
53
|
checkDocsDefinition,
|
|
54
54
|
handleCheckDocs
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-ND6PNADU.js";
|
|
56
|
+
import {
|
|
57
|
+
resolveConfig
|
|
58
|
+
} from "./chunk-Z77YQRQT.js";
|
|
56
59
|
import {
|
|
57
60
|
resultToMcpResponse
|
|
58
61
|
} from "./chunk-IDZNPTYD.js";
|
|
@@ -60,13 +63,14 @@ import {
|
|
|
60
63
|
sanitizePath
|
|
61
64
|
} from "./chunk-W6Y7ZW3Y.js";
|
|
62
65
|
import {
|
|
66
|
+
resolveAllSkillsDirs,
|
|
63
67
|
resolveCommunitySkillsDir,
|
|
64
68
|
resolveGlobalSkillsDir,
|
|
65
69
|
resolvePersonasDir,
|
|
66
70
|
resolveProjectSkillsDir,
|
|
67
71
|
resolveSkillsDir,
|
|
68
72
|
resolveTemplatesDir
|
|
69
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-N5G5QMS3.js";
|
|
70
74
|
import {
|
|
71
75
|
CLIError,
|
|
72
76
|
ExitCode,
|
|
@@ -74,7 +78,7 @@ import {
|
|
|
74
78
|
} from "./chunk-3WGJMBKH.js";
|
|
75
79
|
import {
|
|
76
80
|
SkillMetadataSchema
|
|
77
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-XYLGHKG6.js";
|
|
78
82
|
import {
|
|
79
83
|
Err,
|
|
80
84
|
Ok
|
|
@@ -180,7 +184,7 @@ var initProjectDefinition = {
|
|
|
180
184
|
};
|
|
181
185
|
async function handleInitProject(input) {
|
|
182
186
|
try {
|
|
183
|
-
const { TemplateEngine } = await import("./engine-
|
|
187
|
+
const { TemplateEngine } = await import("./engine-OL4T6NZS.js");
|
|
184
188
|
const templatesDir = resolveTemplatesDir();
|
|
185
189
|
const engine = new TemplateEngine(templatesDir);
|
|
186
190
|
const level = input.level ?? "basic";
|
|
@@ -218,7 +222,7 @@ var listPersonasDefinition = {
|
|
|
218
222
|
inputSchema: { type: "object", properties: {} }
|
|
219
223
|
};
|
|
220
224
|
async function handleListPersonas() {
|
|
221
|
-
const { listPersonas } = await import("./loader-
|
|
225
|
+
const { listPersonas } = await import("./loader-DPYFB6R6.js");
|
|
222
226
|
const result = listPersonas(resolvePersonasDir());
|
|
223
227
|
return resultToMcpResponse(result);
|
|
224
228
|
}
|
|
@@ -242,10 +246,10 @@ async function handleGeneratePersonaArtifacts(input) {
|
|
|
242
246
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.name)) {
|
|
243
247
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.name}`)));
|
|
244
248
|
}
|
|
245
|
-
const { loadPersona } = await import("./loader-
|
|
246
|
-
const { generateRuntime } = await import("./runtime-
|
|
247
|
-
const { generateAgentsMd } = await import("./agents-md-
|
|
248
|
-
const { generateCIWorkflow } = await import("./ci-workflow-
|
|
249
|
+
const { loadPersona } = await import("./loader-DPYFB6R6.js");
|
|
250
|
+
const { generateRuntime } = await import("./runtime-X7U6SC7K.js");
|
|
251
|
+
const { generateAgentsMd } = await import("./agents-md-XU3BHE22.js");
|
|
252
|
+
const { generateCIWorkflow } = await import("./ci-workflow-EHV65NQB.js");
|
|
249
253
|
const personasDir = resolvePersonasDir();
|
|
250
254
|
const filePath = path2.join(personasDir, `${input.name}.yaml`);
|
|
251
255
|
if (!filePath.startsWith(personasDir)) {
|
|
@@ -300,9 +304,9 @@ async function handleRunPersona(input) {
|
|
|
300
304
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.persona)) {
|
|
301
305
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.persona}`)));
|
|
302
306
|
}
|
|
303
|
-
const { loadPersona } = await import("./loader-
|
|
307
|
+
const { loadPersona } = await import("./loader-DPYFB6R6.js");
|
|
304
308
|
const { runPersona } = await import("./runner-VMYLHWOC.js");
|
|
305
|
-
const { executeSkill } = await import("./skill-executor-
|
|
309
|
+
const { executeSkill } = await import("./skill-executor-XZLYZYAK.js");
|
|
306
310
|
const personasDir = resolvePersonasDir();
|
|
307
311
|
const filePath = path2.join(personasDir, `${input.persona}.yaml`);
|
|
308
312
|
if (!filePath.startsWith(personasDir)) {
|
|
@@ -466,8 +470,243 @@ async function handleRunAgentTask(input) {
|
|
|
466
470
|
}
|
|
467
471
|
|
|
468
472
|
// src/mcp/tools/skill.ts
|
|
469
|
-
import * as
|
|
470
|
-
import * as
|
|
473
|
+
import * as fs3 from "fs";
|
|
474
|
+
import * as path5 from "path";
|
|
475
|
+
|
|
476
|
+
// src/skill/dispatcher.ts
|
|
477
|
+
var TIER_1_SKILLS = /* @__PURE__ */ new Set([
|
|
478
|
+
"harness-brainstorming",
|
|
479
|
+
"harness-planning",
|
|
480
|
+
"harness-execution",
|
|
481
|
+
"harness-autopilot",
|
|
482
|
+
"harness-tdd",
|
|
483
|
+
"harness-debugging",
|
|
484
|
+
"harness-refactoring"
|
|
485
|
+
]);
|
|
486
|
+
function isTier1Skill(skillName) {
|
|
487
|
+
return TIER_1_SKILLS.has(skillName);
|
|
488
|
+
}
|
|
489
|
+
function scoreSkill(entry, queryTerms, profile, recentFiles) {
|
|
490
|
+
const matchedKeywords = entry.keywords.filter(
|
|
491
|
+
(kw) => queryTerms.some(
|
|
492
|
+
(term) => kw.toLowerCase().includes(term.toLowerCase()) || term.toLowerCase().includes(kw.toLowerCase())
|
|
493
|
+
)
|
|
494
|
+
);
|
|
495
|
+
const keywordScore = queryTerms.length > 0 ? matchedKeywords.length / queryTerms.length : 0;
|
|
496
|
+
let stackScore = 0;
|
|
497
|
+
if (profile && entry.stackSignals.length > 0) {
|
|
498
|
+
const matchedSignals = entry.stackSignals.filter((signal) => {
|
|
499
|
+
if (profile.signals[signal]) return true;
|
|
500
|
+
return profile.detectedDomains.some(
|
|
501
|
+
(domain) => entry.keywords.some((kw) => kw.toLowerCase() === domain.toLowerCase())
|
|
502
|
+
);
|
|
503
|
+
});
|
|
504
|
+
stackScore = matchedSignals.length / entry.stackSignals.length;
|
|
505
|
+
}
|
|
506
|
+
let recencyBoost = 0;
|
|
507
|
+
if (recentFiles.length > 0) {
|
|
508
|
+
const hasRecentMatch = entry.stackSignals.some((signal) => {
|
|
509
|
+
const cleanSignal = signal.replace(/\*/g, "").replace(/\*\*/g, "");
|
|
510
|
+
return recentFiles.some((f) => f.includes(cleanSignal));
|
|
511
|
+
});
|
|
512
|
+
recencyBoost = hasRecentMatch ? 1 : 0;
|
|
513
|
+
}
|
|
514
|
+
return 0.5 * keywordScore + 0.3 * stackScore + 0.2 * recencyBoost;
|
|
515
|
+
}
|
|
516
|
+
function suggest(index, taskDescription, profile, recentFiles, config) {
|
|
517
|
+
const queryTerms = taskDescription.toLowerCase().split(/\s+/).filter((t) => t.length > 2);
|
|
518
|
+
const scored = [];
|
|
519
|
+
for (const [name, entry] of Object.entries(index.skills)) {
|
|
520
|
+
if (config?.neverSuggest?.includes(name)) continue;
|
|
521
|
+
const score = scoreSkill(entry, queryTerms, profile, recentFiles);
|
|
522
|
+
const isForced = config?.alwaysSuggest?.includes(name);
|
|
523
|
+
if (score >= 0.4 || isForced) {
|
|
524
|
+
scored.push({
|
|
525
|
+
name,
|
|
526
|
+
description: entry.description,
|
|
527
|
+
score: isForced ? Math.max(score, 1) : score
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return scored.sort((a, b) => b.score - a.score).slice(0, 3);
|
|
532
|
+
}
|
|
533
|
+
function formatSuggestions(suggestions) {
|
|
534
|
+
if (suggestions.length === 0) return "";
|
|
535
|
+
const lines = suggestions.map((s) => `- **${s.name}** \u2014 ${s.description}`);
|
|
536
|
+
return [
|
|
537
|
+
"",
|
|
538
|
+
"---",
|
|
539
|
+
"## Suggested Domain Skills",
|
|
540
|
+
"Based on your task and project stack, these catalog skills may be relevant:",
|
|
541
|
+
...lines,
|
|
542
|
+
"",
|
|
543
|
+
'To load a skill: call search_skills("<skill-name>") for full details.',
|
|
544
|
+
"---"
|
|
545
|
+
].join("\n");
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// src/skill/index-builder.ts
|
|
549
|
+
import fs from "fs";
|
|
550
|
+
import path3 from "path";
|
|
551
|
+
import crypto from "crypto";
|
|
552
|
+
import { parse } from "yaml";
|
|
553
|
+
function computeSkillsDirHash(skillsDirs) {
|
|
554
|
+
const hash = crypto.createHash("sha256");
|
|
555
|
+
for (const dir of skillsDirs) {
|
|
556
|
+
if (!fs.existsSync(dir)) continue;
|
|
557
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
558
|
+
if (!entry.isDirectory()) continue;
|
|
559
|
+
const yamlPath = path3.join(dir, entry.name, "skill.yaml");
|
|
560
|
+
if (!fs.existsSync(yamlPath)) continue;
|
|
561
|
+
const stat = fs.statSync(yamlPath);
|
|
562
|
+
hash.update(`${yamlPath}:${stat.mtimeMs}`);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return hash.digest("hex");
|
|
566
|
+
}
|
|
567
|
+
function parseSkillEntry(yamlPath, source, tierOverrides) {
|
|
568
|
+
const raw = fs.readFileSync(yamlPath, "utf-8");
|
|
569
|
+
const parsed = parse(raw);
|
|
570
|
+
const result = SkillMetadataSchema.safeParse(parsed);
|
|
571
|
+
if (!result.success) return null;
|
|
572
|
+
const meta = result.data;
|
|
573
|
+
const effectiveTier = tierOverrides?.[meta.name] ?? meta.tier;
|
|
574
|
+
if (meta.internal) return null;
|
|
575
|
+
if (effectiveTier !== 3 && source !== "community") return null;
|
|
576
|
+
return {
|
|
577
|
+
tier: effectiveTier ?? 3,
|
|
578
|
+
description: meta.description,
|
|
579
|
+
keywords: meta.keywords ?? [],
|
|
580
|
+
stackSignals: meta.stack_signals ?? [],
|
|
581
|
+
cognitiveMode: meta.cognitive_mode,
|
|
582
|
+
phases: (meta.phases ?? []).map((p) => p.name),
|
|
583
|
+
source
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
function scanDirectory(dir, source, index, tierOverrides) {
|
|
587
|
+
if (!fs.existsSync(dir)) return;
|
|
588
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
589
|
+
if (!entry.isDirectory()) continue;
|
|
590
|
+
if (index.skills[entry.name]) continue;
|
|
591
|
+
const yamlPath = path3.join(dir, entry.name, "skill.yaml");
|
|
592
|
+
if (!fs.existsSync(yamlPath)) continue;
|
|
593
|
+
try {
|
|
594
|
+
const parsed = parseSkillEntry(yamlPath, source, tierOverrides);
|
|
595
|
+
if (parsed) index.skills[entry.name] = parsed;
|
|
596
|
+
} catch {
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
function buildIndex(platform, _projectRoot, tierOverrides) {
|
|
602
|
+
const skillsDirs = resolveAllSkillsDirs(platform);
|
|
603
|
+
const sourceMap = ["project", "community", "bundled"];
|
|
604
|
+
const index = {
|
|
605
|
+
version: 1,
|
|
606
|
+
hash: computeSkillsDirHash(skillsDirs),
|
|
607
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
608
|
+
skills: {}
|
|
609
|
+
};
|
|
610
|
+
for (let i = 0; i < skillsDirs.length; i++) {
|
|
611
|
+
scanDirectory(skillsDirs[i], sourceMap[i] ?? "bundled", index, tierOverrides);
|
|
612
|
+
}
|
|
613
|
+
return index;
|
|
614
|
+
}
|
|
615
|
+
function loadOrRebuildIndex(platform, projectRoot, tierOverrides) {
|
|
616
|
+
const indexPath = path3.join(projectRoot, ".harness", "skills-index.json");
|
|
617
|
+
const skillsDirs = resolveAllSkillsDirs(platform);
|
|
618
|
+
const currentHash = computeSkillsDirHash(skillsDirs);
|
|
619
|
+
if (fs.existsSync(indexPath)) {
|
|
620
|
+
try {
|
|
621
|
+
const existing = JSON.parse(fs.readFileSync(indexPath, "utf-8"));
|
|
622
|
+
if (existing.hash === currentHash) return existing;
|
|
623
|
+
} catch {
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
const index = buildIndex(platform, projectRoot, tierOverrides);
|
|
627
|
+
fs.mkdirSync(path3.dirname(indexPath), { recursive: true });
|
|
628
|
+
fs.writeFileSync(indexPath, JSON.stringify(index, null, 2));
|
|
629
|
+
return index;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/skill/stack-profile.ts
|
|
633
|
+
import fs2 from "fs";
|
|
634
|
+
import path4 from "path";
|
|
635
|
+
var SIGNAL_DOMAIN_MAP = {
|
|
636
|
+
"prisma/schema.prisma": ["database"],
|
|
637
|
+
"drizzle.config.ts": ["database"],
|
|
638
|
+
"knexfile.js": ["database"],
|
|
639
|
+
"knexfile.ts": ["database"],
|
|
640
|
+
migrations: ["database"],
|
|
641
|
+
Dockerfile: ["containerization"],
|
|
642
|
+
"docker-compose.yml": ["containerization"],
|
|
643
|
+
"docker-compose.yaml": ["containerization"],
|
|
644
|
+
k8s: ["containerization"],
|
|
645
|
+
kubernetes: ["containerization"],
|
|
646
|
+
helm: ["containerization"],
|
|
647
|
+
".github/workflows": ["deployment"],
|
|
648
|
+
".gitlab-ci.yml": ["deployment"],
|
|
649
|
+
Jenkinsfile: ["deployment"],
|
|
650
|
+
terraform: ["infrastructure-as-code"],
|
|
651
|
+
"Pulumi.yaml": ["infrastructure-as-code"],
|
|
652
|
+
"cdk.json": ["infrastructure-as-code"],
|
|
653
|
+
"openapi.yaml": ["api-design"],
|
|
654
|
+
"openapi.json": ["api-design"],
|
|
655
|
+
"swagger.yaml": ["api-design"],
|
|
656
|
+
"swagger.json": ["api-design"],
|
|
657
|
+
"schema.graphql": ["api-design"],
|
|
658
|
+
".env": ["secrets"],
|
|
659
|
+
".env.example": ["secrets"],
|
|
660
|
+
"vault.hcl": ["secrets"],
|
|
661
|
+
e2e: ["e2e"],
|
|
662
|
+
cypress: ["e2e"],
|
|
663
|
+
"playwright.config.ts": ["e2e"],
|
|
664
|
+
"playwright.config.js": ["e2e"],
|
|
665
|
+
"stryker.conf.js": ["mutation-test"],
|
|
666
|
+
"stryker.conf.mjs": ["mutation-test"],
|
|
667
|
+
k6: ["load-testing"],
|
|
668
|
+
"artillery.yml": ["load-testing"],
|
|
669
|
+
"dbt_project.yml": ["data-pipeline"],
|
|
670
|
+
airflow: ["data-pipeline"],
|
|
671
|
+
ios: ["mobile-patterns"],
|
|
672
|
+
android: ["mobile-patterns"],
|
|
673
|
+
"pubspec.yaml": ["mobile-patterns"],
|
|
674
|
+
"App.tsx": ["mobile-patterns"],
|
|
675
|
+
runbooks: ["incident-response"],
|
|
676
|
+
"docs/runbooks": ["incident-response"]
|
|
677
|
+
};
|
|
678
|
+
function generateStackProfile(projectRoot) {
|
|
679
|
+
const signals = {};
|
|
680
|
+
const domainSet = /* @__PURE__ */ new Set();
|
|
681
|
+
for (const [pattern, domains] of Object.entries(SIGNAL_DOMAIN_MAP)) {
|
|
682
|
+
const fullPath = path4.join(projectRoot, pattern);
|
|
683
|
+
const exists = fs2.existsSync(fullPath);
|
|
684
|
+
signals[pattern] = exists;
|
|
685
|
+
if (exists) {
|
|
686
|
+
for (const domain of domains) domainSet.add(domain);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return {
|
|
690
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
691
|
+
signals,
|
|
692
|
+
detectedDomains: [...domainSet].sort()
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
function loadOrGenerateProfile(projectRoot) {
|
|
696
|
+
const profilePath = path4.join(projectRoot, ".harness", "stack-profile.json");
|
|
697
|
+
if (fs2.existsSync(profilePath)) {
|
|
698
|
+
try {
|
|
699
|
+
return JSON.parse(fs2.readFileSync(profilePath, "utf-8"));
|
|
700
|
+
} catch {
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
const profile = generateStackProfile(projectRoot);
|
|
704
|
+
fs2.mkdirSync(path4.dirname(profilePath), { recursive: true });
|
|
705
|
+
fs2.writeFileSync(profilePath, JSON.stringify(profile, null, 2));
|
|
706
|
+
return profile;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// src/mcp/tools/skill.ts
|
|
471
710
|
var runSkillDefinition = {
|
|
472
711
|
name: "run_skill",
|
|
473
712
|
description: "Load and return the content of a skill (SKILL.md), optionally with project state context",
|
|
@@ -492,23 +731,23 @@ async function handleRunSkill(input) {
|
|
|
492
731
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.skill)) {
|
|
493
732
|
return resultToMcpResponse(Err(new Error(`Invalid skill name: ${input.skill}`)));
|
|
494
733
|
}
|
|
495
|
-
const skillDir =
|
|
734
|
+
const skillDir = path5.join(skillsDir, input.skill);
|
|
496
735
|
if (!skillDir.startsWith(skillsDir)) {
|
|
497
736
|
return resultToMcpResponse(Err(new Error(`Invalid skill path: ${input.skill}`)));
|
|
498
737
|
}
|
|
499
|
-
if (!
|
|
738
|
+
if (!fs3.existsSync(skillDir)) {
|
|
500
739
|
return resultToMcpResponse(Err(new Error(`Skill not found: ${input.skill}`)));
|
|
501
740
|
}
|
|
502
|
-
const skillMdPath =
|
|
503
|
-
if (!
|
|
741
|
+
const skillMdPath = path5.join(skillDir, "SKILL.md");
|
|
742
|
+
if (!fs3.existsSync(skillMdPath)) {
|
|
504
743
|
return resultToMcpResponse(Err(new Error(`SKILL.md not found for skill: ${input.skill}`)));
|
|
505
744
|
}
|
|
506
|
-
let content =
|
|
745
|
+
let content = fs3.readFileSync(skillMdPath, "utf-8");
|
|
507
746
|
if (input.path) {
|
|
508
747
|
const projectPath = sanitizePath(input.path);
|
|
509
|
-
const stateFile =
|
|
510
|
-
if (
|
|
511
|
-
const stateContent =
|
|
748
|
+
const stateFile = path5.join(projectPath, ".harness", "state.json");
|
|
749
|
+
if (fs3.existsSync(stateFile)) {
|
|
750
|
+
const stateContent = fs3.readFileSync(stateFile, "utf-8");
|
|
512
751
|
content += `
|
|
513
752
|
|
|
514
753
|
---
|
|
@@ -519,6 +758,23 @@ ${stateContent}
|
|
|
519
758
|
`;
|
|
520
759
|
}
|
|
521
760
|
}
|
|
761
|
+
if (isTier1Skill(input.skill)) {
|
|
762
|
+
try {
|
|
763
|
+
const projectRoot = input.path ? sanitizePath(input.path) : process.cwd();
|
|
764
|
+
const platform = "claude-code";
|
|
765
|
+
const configResult = resolveConfig();
|
|
766
|
+
const skillsConfig = configResult.ok ? configResult.value.skills : void 0;
|
|
767
|
+
const index = loadOrRebuildIndex(platform, projectRoot, skillsConfig?.tierOverrides);
|
|
768
|
+
const profile = loadOrGenerateProfile(projectRoot);
|
|
769
|
+
const taskDesc = [input.skill, input.phase].filter(Boolean).join(" ");
|
|
770
|
+
const suggestions = suggest(index, taskDesc, profile, [], skillsConfig);
|
|
771
|
+
const suggestionText = formatSuggestions(suggestions);
|
|
772
|
+
if (suggestionText) {
|
|
773
|
+
content += suggestionText;
|
|
774
|
+
}
|
|
775
|
+
} catch {
|
|
776
|
+
}
|
|
777
|
+
}
|
|
522
778
|
return resultToMcpResponse(Ok(content));
|
|
523
779
|
}
|
|
524
780
|
var createSkillDefinition = {
|
|
@@ -548,7 +804,7 @@ var createSkillDefinition = {
|
|
|
548
804
|
};
|
|
549
805
|
async function handleCreateSkill(input) {
|
|
550
806
|
try {
|
|
551
|
-
const { generateSkillFiles } = await import("./create-skill-
|
|
807
|
+
const { generateSkillFiles } = await import("./create-skill-XSWHMSM5.js");
|
|
552
808
|
const result = generateSkillFiles({
|
|
553
809
|
name: input.name,
|
|
554
810
|
description: input.description,
|
|
@@ -570,22 +826,22 @@ async function handleCreateSkill(input) {
|
|
|
570
826
|
}
|
|
571
827
|
|
|
572
828
|
// src/mcp/resources/skills.ts
|
|
573
|
-
import * as
|
|
574
|
-
import * as
|
|
829
|
+
import * as fs4 from "fs";
|
|
830
|
+
import * as path6 from "path";
|
|
575
831
|
import * as yaml from "yaml";
|
|
576
832
|
async function getSkillsResource(projectRoot) {
|
|
577
|
-
const skillsDir =
|
|
833
|
+
const skillsDir = path6.join(projectRoot, "agents", "skills", "claude-code");
|
|
578
834
|
const skills = [];
|
|
579
|
-
if (!
|
|
835
|
+
if (!fs4.existsSync(skillsDir)) {
|
|
580
836
|
return JSON.stringify(skills, null, 2);
|
|
581
837
|
}
|
|
582
|
-
const entries =
|
|
838
|
+
const entries = fs4.readdirSync(skillsDir, { withFileTypes: true });
|
|
583
839
|
for (const entry of entries) {
|
|
584
840
|
if (!entry.isDirectory()) continue;
|
|
585
|
-
const skillYamlPath =
|
|
586
|
-
if (!
|
|
841
|
+
const skillYamlPath = path6.join(skillsDir, entry.name, "skill.yaml");
|
|
842
|
+
if (!fs4.existsSync(skillYamlPath)) continue;
|
|
587
843
|
try {
|
|
588
|
-
const content =
|
|
844
|
+
const content = fs4.readFileSync(skillYamlPath, "utf-8");
|
|
589
845
|
const parsed = yaml.parse(content);
|
|
590
846
|
skills.push({
|
|
591
847
|
name: parsed.name,
|
|
@@ -601,14 +857,14 @@ async function getSkillsResource(projectRoot) {
|
|
|
601
857
|
}
|
|
602
858
|
|
|
603
859
|
// src/mcp/resources/rules.ts
|
|
604
|
-
import * as
|
|
605
|
-
import * as
|
|
860
|
+
import * as fs5 from "fs";
|
|
861
|
+
import * as path7 from "path";
|
|
606
862
|
async function getRulesResource(projectRoot) {
|
|
607
863
|
const rules = [];
|
|
608
|
-
const configPath =
|
|
609
|
-
if (
|
|
864
|
+
const configPath = path7.join(projectRoot, "harness.config.json");
|
|
865
|
+
if (fs5.existsSync(configPath)) {
|
|
610
866
|
try {
|
|
611
|
-
const config = JSON.parse(
|
|
867
|
+
const config = JSON.parse(fs5.readFileSync(configPath, "utf-8"));
|
|
612
868
|
if (config.layers) {
|
|
613
869
|
rules.push({ type: "layer-enforcement", config: config.layers });
|
|
614
870
|
}
|
|
@@ -621,10 +877,10 @@ async function getRulesResource(projectRoot) {
|
|
|
621
877
|
} catch {
|
|
622
878
|
}
|
|
623
879
|
}
|
|
624
|
-
const linterPath =
|
|
625
|
-
if (
|
|
880
|
+
const linterPath = path7.join(projectRoot, ".harness", "linter.json");
|
|
881
|
+
if (fs5.existsSync(linterPath)) {
|
|
626
882
|
try {
|
|
627
|
-
const linterConfig = JSON.parse(
|
|
883
|
+
const linterConfig = JSON.parse(fs5.readFileSync(linterPath, "utf-8"));
|
|
628
884
|
rules.push({ type: "linter", config: linterConfig });
|
|
629
885
|
} catch {
|
|
630
886
|
}
|
|
@@ -633,28 +889,28 @@ async function getRulesResource(projectRoot) {
|
|
|
633
889
|
}
|
|
634
890
|
|
|
635
891
|
// src/mcp/resources/project.ts
|
|
636
|
-
import * as
|
|
637
|
-
import * as
|
|
892
|
+
import * as fs6 from "fs";
|
|
893
|
+
import * as path8 from "path";
|
|
638
894
|
async function getProjectResource(projectRoot) {
|
|
639
|
-
const agentsPath =
|
|
640
|
-
if (
|
|
641
|
-
return
|
|
895
|
+
const agentsPath = path8.join(projectRoot, "AGENTS.md");
|
|
896
|
+
if (fs6.existsSync(agentsPath)) {
|
|
897
|
+
return fs6.readFileSync(agentsPath, "utf-8");
|
|
642
898
|
}
|
|
643
899
|
return "# No AGENTS.md found";
|
|
644
900
|
}
|
|
645
901
|
|
|
646
902
|
// src/mcp/resources/learnings.ts
|
|
647
|
-
import * as
|
|
648
|
-
import * as
|
|
903
|
+
import * as fs7 from "fs";
|
|
904
|
+
import * as path9 from "path";
|
|
649
905
|
async function getLearningsResource(projectRoot) {
|
|
650
906
|
const sections = [];
|
|
651
|
-
const reviewPath =
|
|
652
|
-
if (
|
|
653
|
-
sections.push("## Review Learnings\n\n" +
|
|
907
|
+
const reviewPath = path9.join(projectRoot, ".harness", "review-learnings.md");
|
|
908
|
+
if (fs7.existsSync(reviewPath)) {
|
|
909
|
+
sections.push("## Review Learnings\n\n" + fs7.readFileSync(reviewPath, "utf-8"));
|
|
654
910
|
}
|
|
655
|
-
const antiPath =
|
|
656
|
-
if (
|
|
657
|
-
sections.push("## Anti-Pattern Log\n\n" +
|
|
911
|
+
const antiPath = path9.join(projectRoot, ".harness", "anti-patterns.md");
|
|
912
|
+
if (fs7.existsSync(antiPath)) {
|
|
913
|
+
sections.push("## Anti-Pattern Log\n\n" + fs7.readFileSync(antiPath, "utf-8"));
|
|
658
914
|
}
|
|
659
915
|
return sections.length > 0 ? sections.join("\n\n---\n\n") : "No learnings files found.";
|
|
660
916
|
}
|
|
@@ -709,7 +965,7 @@ async function handleManageState(input) {
|
|
|
709
965
|
archiveFailures,
|
|
710
966
|
runMechanicalGate,
|
|
711
967
|
DEFAULT_STATE
|
|
712
|
-
} = await import("./dist-
|
|
968
|
+
} = await import("./dist-2B363XUH.js");
|
|
713
969
|
const projectPath = sanitizePath(input.path);
|
|
714
970
|
switch (input.action) {
|
|
715
971
|
case "show": {
|
|
@@ -795,7 +1051,7 @@ async function handleManageState(input) {
|
|
|
795
1051
|
isError: true
|
|
796
1052
|
};
|
|
797
1053
|
}
|
|
798
|
-
const { saveHandoff } = await import("./dist-
|
|
1054
|
+
const { saveHandoff } = await import("./dist-2B363XUH.js");
|
|
799
1055
|
const result = await saveHandoff(
|
|
800
1056
|
projectPath,
|
|
801
1057
|
input.handoff,
|
|
@@ -805,7 +1061,7 @@ async function handleManageState(input) {
|
|
|
805
1061
|
return resultToMcpResponse(result.ok ? Ok({ saved: true }) : result);
|
|
806
1062
|
}
|
|
807
1063
|
case "load-handoff": {
|
|
808
|
-
const { loadHandoff } = await import("./dist-
|
|
1064
|
+
const { loadHandoff } = await import("./dist-2B363XUH.js");
|
|
809
1065
|
const result = await loadHandoff(projectPath, input.stream, input.session);
|
|
810
1066
|
return resultToMcpResponse(result);
|
|
811
1067
|
}
|
|
@@ -841,7 +1097,7 @@ var listStreamsDefinition = {
|
|
|
841
1097
|
};
|
|
842
1098
|
async function handleListStreams(input) {
|
|
843
1099
|
try {
|
|
844
|
-
const { listStreams, loadStreamIndex } = await import("./dist-
|
|
1100
|
+
const { listStreams, loadStreamIndex } = await import("./dist-2B363XUH.js");
|
|
845
1101
|
const projectPath = sanitizePath(input.path);
|
|
846
1102
|
const indexResult = await loadStreamIndex(projectPath);
|
|
847
1103
|
const streamsResult = await listStreams(projectPath);
|
|
@@ -879,7 +1135,7 @@ var checkPhaseGateDefinition = {
|
|
|
879
1135
|
};
|
|
880
1136
|
async function handleCheckPhaseGate(input) {
|
|
881
1137
|
try {
|
|
882
|
-
const { runCheckPhaseGate } = await import("./check-phase-gate-
|
|
1138
|
+
const { runCheckPhaseGate } = await import("./check-phase-gate-2OFZ7OWW.js");
|
|
883
1139
|
const result = await runCheckPhaseGate({ cwd: sanitizePath(input.path) });
|
|
884
1140
|
if (result.ok) {
|
|
885
1141
|
return { content: [{ type: "text", text: JSON.stringify(result.value) }] };
|
|
@@ -899,7 +1155,7 @@ async function handleCheckPhaseGate(input) {
|
|
|
899
1155
|
}
|
|
900
1156
|
|
|
901
1157
|
// src/mcp/tools/cross-check.ts
|
|
902
|
-
import * as
|
|
1158
|
+
import * as path10 from "path";
|
|
903
1159
|
var validateCrossCheckDefinition = {
|
|
904
1160
|
name: "validate_cross_check",
|
|
905
1161
|
description: "Validate plan-to-implementation coverage: checks that specs have plans and plans have implementations, detects staleness",
|
|
@@ -935,15 +1191,15 @@ async function handleValidateCrossCheck(input) {
|
|
|
935
1191
|
};
|
|
936
1192
|
}
|
|
937
1193
|
try {
|
|
938
|
-
const { runCrossCheck } = await import("./validate-cross-check-
|
|
939
|
-
const specsDir =
|
|
1194
|
+
const { runCrossCheck } = await import("./validate-cross-check-STFHYMAZ.js");
|
|
1195
|
+
const specsDir = path10.resolve(projectPath, input.specsDir ?? "docs/specs");
|
|
940
1196
|
if (!specsDir.startsWith(projectPath)) {
|
|
941
1197
|
return {
|
|
942
1198
|
content: [{ type: "text", text: "Error: specsDir escapes project root" }],
|
|
943
1199
|
isError: true
|
|
944
1200
|
};
|
|
945
1201
|
}
|
|
946
|
-
const plansDir =
|
|
1202
|
+
const plansDir = path10.resolve(projectPath, input.plansDir ?? "docs/plans");
|
|
947
1203
|
if (!plansDir.startsWith(projectPath)) {
|
|
948
1204
|
return {
|
|
949
1205
|
content: [{ type: "text", text: "Error: plansDir escapes project root" }],
|
|
@@ -974,15 +1230,15 @@ async function handleValidateCrossCheck(input) {
|
|
|
974
1230
|
|
|
975
1231
|
// src/commands/generate-slash-commands.ts
|
|
976
1232
|
import { Command } from "commander";
|
|
977
|
-
import
|
|
978
|
-
import
|
|
1233
|
+
import fs9 from "fs";
|
|
1234
|
+
import path12 from "path";
|
|
979
1235
|
import os from "os";
|
|
980
1236
|
import readline from "readline";
|
|
981
1237
|
|
|
982
1238
|
// src/slash-commands/normalize.ts
|
|
983
|
-
import
|
|
984
|
-
import
|
|
985
|
-
import { parse as
|
|
1239
|
+
import fs8 from "fs";
|
|
1240
|
+
import path11 from "path";
|
|
1241
|
+
import { parse as parse3 } from "yaml";
|
|
986
1242
|
|
|
987
1243
|
// src/slash-commands/normalize-name.ts
|
|
988
1244
|
function normalizeName(skillName) {
|
|
@@ -1002,18 +1258,18 @@ function normalizeSkills(skillSources, platforms) {
|
|
|
1002
1258
|
const specs = [];
|
|
1003
1259
|
const nameMap = /* @__PURE__ */ new Map();
|
|
1004
1260
|
for (const { dir: skillsDir, source } of skillSources) {
|
|
1005
|
-
if (!
|
|
1006
|
-
const entries =
|
|
1261
|
+
if (!fs8.existsSync(skillsDir)) continue;
|
|
1262
|
+
const entries = fs8.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1007
1263
|
for (const entry of entries) {
|
|
1008
|
-
const yamlPath =
|
|
1009
|
-
if (!
|
|
1264
|
+
const yamlPath = path11.join(skillsDir, entry.name, "skill.yaml");
|
|
1265
|
+
if (!fs8.existsSync(yamlPath)) continue;
|
|
1010
1266
|
let raw;
|
|
1011
1267
|
try {
|
|
1012
|
-
raw =
|
|
1268
|
+
raw = fs8.readFileSync(yamlPath, "utf-8");
|
|
1013
1269
|
} catch {
|
|
1014
1270
|
continue;
|
|
1015
1271
|
}
|
|
1016
|
-
const parsed =
|
|
1272
|
+
const parsed = parse3(raw);
|
|
1017
1273
|
const result = SkillMetadataSchema.safeParse(parsed);
|
|
1018
1274
|
if (!result.success) {
|
|
1019
1275
|
console.warn(`Skipping ${entry.name}: invalid skill.yaml`);
|
|
@@ -1022,6 +1278,9 @@ function normalizeSkills(skillSources, platforms) {
|
|
|
1022
1278
|
const meta = result.data;
|
|
1023
1279
|
const matchesPlatform = platforms.some((p) => meta.platforms.includes(p));
|
|
1024
1280
|
if (!matchesPlatform) continue;
|
|
1281
|
+
const tier = meta.tier;
|
|
1282
|
+
const isInternal = meta.internal;
|
|
1283
|
+
if (tier === 3 || isInternal) continue;
|
|
1025
1284
|
const normalized = normalizeName(meta.name);
|
|
1026
1285
|
const existing = nameMap.get(normalized);
|
|
1027
1286
|
if (existing) {
|
|
@@ -1033,16 +1292,10 @@ function normalizeSkills(skillSources, platforms) {
|
|
|
1033
1292
|
continue;
|
|
1034
1293
|
}
|
|
1035
1294
|
nameMap.set(normalized, { skillName: meta.name, source });
|
|
1036
|
-
const skillMdPath =
|
|
1037
|
-
const skillMdContent =
|
|
1038
|
-
const skillMdRelative =
|
|
1039
|
-
|
|
1040
|
-
path9.join(skillsDir, entry.name, "SKILL.md")
|
|
1041
|
-
);
|
|
1042
|
-
const skillYamlRelative = path9.relative(
|
|
1043
|
-
process.cwd(),
|
|
1044
|
-
path9.join(skillsDir, entry.name, "skill.yaml")
|
|
1045
|
-
);
|
|
1295
|
+
const skillMdPath = path11.join(skillsDir, entry.name, "SKILL.md");
|
|
1296
|
+
const skillMdContent = fs8.existsSync(skillMdPath) ? fs8.readFileSync(skillMdPath, "utf-8") : "";
|
|
1297
|
+
const skillMdRelative = path11.relative(process.cwd(), path11.join(skillsDir, entry.name, "SKILL.md")).replaceAll("\\", "/");
|
|
1298
|
+
const skillYamlRelative = path11.relative(process.cwd(), path11.join(skillsDir, entry.name, "skill.yaml")).replaceAll("\\", "/");
|
|
1046
1299
|
const args = (meta.cli?.args ?? []).map((a) => ({
|
|
1047
1300
|
name: a.name,
|
|
1048
1301
|
description: a.description ?? "",
|
|
@@ -1207,13 +1460,13 @@ function renderGemini(spec, skillMdContent, skillYamlContent) {
|
|
|
1207
1460
|
// src/commands/generate-slash-commands.ts
|
|
1208
1461
|
function resolveOutputDir(platform, opts) {
|
|
1209
1462
|
if (opts.output) {
|
|
1210
|
-
return
|
|
1463
|
+
return path12.join(opts.output, "harness");
|
|
1211
1464
|
}
|
|
1212
1465
|
if (opts.global) {
|
|
1213
1466
|
const home = os.homedir();
|
|
1214
|
-
return platform === "claude-code" ?
|
|
1467
|
+
return platform === "claude-code" ? path12.join(home, ".claude", "commands", "harness") : path12.join(home, ".gemini", "commands", "harness");
|
|
1215
1468
|
}
|
|
1216
|
-
return platform === "claude-code" ?
|
|
1469
|
+
return platform === "claude-code" ? path12.join("agents", "commands", "claude-code", "harness") : path12.join("agents", "commands", "gemini-cli", "harness");
|
|
1217
1470
|
}
|
|
1218
1471
|
function fileExtension(platform) {
|
|
1219
1472
|
return platform === "claude-code" ? ".md" : ".toml";
|
|
@@ -1238,12 +1491,12 @@ function generateSlashCommands(opts) {
|
|
|
1238
1491
|
skillSources.push({ dir: projectDir, source: "project" });
|
|
1239
1492
|
}
|
|
1240
1493
|
const communityDir = resolveCommunitySkillsDir();
|
|
1241
|
-
if (
|
|
1494
|
+
if (fs9.existsSync(communityDir)) {
|
|
1242
1495
|
skillSources.push({ dir: communityDir, source: "community" });
|
|
1243
1496
|
}
|
|
1244
1497
|
if (opts.includeGlobal || skillSources.length === 0) {
|
|
1245
1498
|
const globalDir = resolveGlobalSkillsDir();
|
|
1246
|
-
if (!projectDir ||
|
|
1499
|
+
if (!projectDir || path12.resolve(globalDir) !== path12.resolve(projectDir)) {
|
|
1247
1500
|
skillSources.push({ dir: globalDir, source: "global" });
|
|
1248
1501
|
}
|
|
1249
1502
|
}
|
|
@@ -1265,7 +1518,7 @@ function generateSlashCommands(opts) {
|
|
|
1265
1518
|
executionContext: spec.prompt.executionContext.split("\n").map((line) => {
|
|
1266
1519
|
if (line.startsWith("@")) {
|
|
1267
1520
|
const relPath = line.slice(1);
|
|
1268
|
-
return `@${
|
|
1521
|
+
return `@${path12.resolve(relPath)}`;
|
|
1269
1522
|
}
|
|
1270
1523
|
return line;
|
|
1271
1524
|
}).join("\n")
|
|
@@ -1273,10 +1526,10 @@ function generateSlashCommands(opts) {
|
|
|
1273
1526
|
} : spec;
|
|
1274
1527
|
rendered.set(filename, renderClaudeCode(renderSpec));
|
|
1275
1528
|
} else {
|
|
1276
|
-
const mdPath =
|
|
1277
|
-
const yamlPath =
|
|
1278
|
-
const mdContent =
|
|
1279
|
-
const yamlContent =
|
|
1529
|
+
const mdPath = path12.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
|
|
1530
|
+
const yamlPath = path12.join(spec.skillsBaseDir, spec.sourceDir, "skill.yaml");
|
|
1531
|
+
const mdContent = fs9.existsSync(mdPath) ? fs9.readFileSync(mdPath, "utf-8") : "";
|
|
1532
|
+
const yamlContent = fs9.existsSync(yamlPath) ? fs9.readFileSync(yamlPath, "utf-8") : "";
|
|
1280
1533
|
rendered.set(filename, renderGemini(spec, mdContent, yamlContent));
|
|
1281
1534
|
}
|
|
1282
1535
|
}
|
|
@@ -1302,9 +1555,9 @@ async function handleOrphanDeletion(results, opts) {
|
|
|
1302
1555
|
const shouldDelete = opts.yes || await confirmDeletion(result.removed);
|
|
1303
1556
|
if (shouldDelete) {
|
|
1304
1557
|
for (const filename of result.removed) {
|
|
1305
|
-
const filePath =
|
|
1306
|
-
if (
|
|
1307
|
-
|
|
1558
|
+
const filePath = path12.join(result.outputDir, filename);
|
|
1559
|
+
if (fs9.existsSync(filePath)) {
|
|
1560
|
+
fs9.unlinkSync(filePath);
|
|
1308
1561
|
}
|
|
1309
1562
|
}
|
|
1310
1563
|
}
|
|
@@ -1430,7 +1683,7 @@ async function handleGenerateSlashCommands(input) {
|
|
|
1430
1683
|
// src/mcp/resources/state.ts
|
|
1431
1684
|
async function getStateResource(projectRoot) {
|
|
1432
1685
|
try {
|
|
1433
|
-
const { loadState, migrateToStreams } = await import("./dist-
|
|
1686
|
+
const { loadState, migrateToStreams } = await import("./dist-2B363XUH.js");
|
|
1434
1687
|
await migrateToStreams(projectRoot);
|
|
1435
1688
|
const result = await loadState(projectRoot);
|
|
1436
1689
|
if (result.ok) {
|
|
@@ -1454,8 +1707,7 @@ async function getStateResource(projectRoot) {
|
|
|
1454
1707
|
}
|
|
1455
1708
|
}
|
|
1456
1709
|
|
|
1457
|
-
// src/mcp/tools/graph.ts
|
|
1458
|
-
import * as path11 from "path";
|
|
1710
|
+
// src/mcp/tools/graph/shared.ts
|
|
1459
1711
|
function graphNotFoundError() {
|
|
1460
1712
|
return {
|
|
1461
1713
|
content: [
|
|
@@ -1467,6 +1719,8 @@ function graphNotFoundError() {
|
|
|
1467
1719
|
isError: true
|
|
1468
1720
|
};
|
|
1469
1721
|
}
|
|
1722
|
+
|
|
1723
|
+
// src/mcp/tools/graph/query-graph.ts
|
|
1470
1724
|
var queryGraphDefinition = {
|
|
1471
1725
|
name: "query_graph",
|
|
1472
1726
|
description: "Query the project knowledge graph using ContextQL. Traverses from root nodes outward, filtering by node/edge types.",
|
|
@@ -1517,7 +1771,7 @@ async function handleQueryGraph(input) {
|
|
|
1517
1771
|
const projectPath = sanitizePath(input.path);
|
|
1518
1772
|
const store = await loadGraphStore(projectPath);
|
|
1519
1773
|
if (!store) return graphNotFoundError();
|
|
1520
|
-
const { ContextQL } = await import("./dist-
|
|
1774
|
+
const { ContextQL } = await import("./dist-HXHWB7SV.js");
|
|
1521
1775
|
const cql = new ContextQL(store);
|
|
1522
1776
|
const result = cql.execute({
|
|
1523
1777
|
rootNodeIds: input.rootNodeIds,
|
|
@@ -1583,6 +1837,8 @@ async function handleQueryGraph(input) {
|
|
|
1583
1837
|
};
|
|
1584
1838
|
}
|
|
1585
1839
|
}
|
|
1840
|
+
|
|
1841
|
+
// src/mcp/tools/graph/search-similar.ts
|
|
1586
1842
|
var searchSimilarDefinition = {
|
|
1587
1843
|
name: "search_similar",
|
|
1588
1844
|
description: "Search the knowledge graph for nodes similar to a query string using keyword and semantic fusion.",
|
|
@@ -1606,7 +1862,7 @@ async function handleSearchSimilar(input) {
|
|
|
1606
1862
|
const projectPath = sanitizePath(input.path);
|
|
1607
1863
|
const store = await loadGraphStore(projectPath);
|
|
1608
1864
|
if (!store) return graphNotFoundError();
|
|
1609
|
-
const { FusionLayer } = await import("./dist-
|
|
1865
|
+
const { FusionLayer } = await import("./dist-HXHWB7SV.js");
|
|
1610
1866
|
const fusion = new FusionLayer(store);
|
|
1611
1867
|
const results = fusion.search(input.query, input.topK ?? 10);
|
|
1612
1868
|
if (input.mode === "summary") {
|
|
@@ -1638,6 +1894,8 @@ async function handleSearchSimilar(input) {
|
|
|
1638
1894
|
};
|
|
1639
1895
|
}
|
|
1640
1896
|
}
|
|
1897
|
+
|
|
1898
|
+
// src/mcp/tools/graph/find-context-for.ts
|
|
1641
1899
|
var findContextForDefinition = {
|
|
1642
1900
|
name: "find_context_for",
|
|
1643
1901
|
description: "Find relevant context for a given intent by searching the graph and expanding around top results. Returns assembled context within a token budget.",
|
|
@@ -1659,7 +1917,7 @@ async function handleFindContextFor(input) {
|
|
|
1659
1917
|
const projectPath = sanitizePath(input.path);
|
|
1660
1918
|
const store = await loadGraphStore(projectPath);
|
|
1661
1919
|
if (!store) return graphNotFoundError();
|
|
1662
|
-
const { FusionLayer, ContextQL } = await import("./dist-
|
|
1920
|
+
const { FusionLayer, ContextQL } = await import("./dist-HXHWB7SV.js");
|
|
1663
1921
|
const fusion = new FusionLayer(store);
|
|
1664
1922
|
const cql = new ContextQL(store);
|
|
1665
1923
|
const tokenBudget = input.tokenBudget ?? 4e3;
|
|
@@ -1725,6 +1983,8 @@ async function handleFindContextFor(input) {
|
|
|
1725
1983
|
};
|
|
1726
1984
|
}
|
|
1727
1985
|
}
|
|
1986
|
+
|
|
1987
|
+
// src/mcp/tools/graph/get-relationships.ts
|
|
1728
1988
|
var getRelationshipsDefinition = {
|
|
1729
1989
|
name: "get_relationships",
|
|
1730
1990
|
description: "Get relationships for a specific node in the knowledge graph, with configurable direction and depth.",
|
|
@@ -1753,7 +2013,7 @@ async function handleGetRelationships(input) {
|
|
|
1753
2013
|
const projectPath = sanitizePath(input.path);
|
|
1754
2014
|
const store = await loadGraphStore(projectPath);
|
|
1755
2015
|
if (!store) return graphNotFoundError();
|
|
1756
|
-
const { ContextQL } = await import("./dist-
|
|
2016
|
+
const { ContextQL } = await import("./dist-HXHWB7SV.js");
|
|
1757
2017
|
const cql = new ContextQL(store);
|
|
1758
2018
|
const direction = input.direction ?? "both";
|
|
1759
2019
|
const bidirectional = direction === "both" || direction === "inbound";
|
|
@@ -1820,6 +2080,8 @@ async function handleGetRelationships(input) {
|
|
|
1820
2080
|
};
|
|
1821
2081
|
}
|
|
1822
2082
|
}
|
|
2083
|
+
|
|
2084
|
+
// src/mcp/tools/graph/get-impact.ts
|
|
1823
2085
|
var getImpactDefinition = {
|
|
1824
2086
|
name: "get_impact",
|
|
1825
2087
|
description: "Analyze the impact of changing a node or file. Returns affected tests, docs, code, and other nodes grouped by type.",
|
|
@@ -1857,7 +2119,7 @@ async function handleGetImpact(input) {
|
|
|
1857
2119
|
const projectPath = sanitizePath(input.path);
|
|
1858
2120
|
const store = await loadGraphStore(projectPath);
|
|
1859
2121
|
if (!store) return graphNotFoundError();
|
|
1860
|
-
const { ContextQL } = await import("./dist-
|
|
2122
|
+
const { ContextQL } = await import("./dist-HXHWB7SV.js");
|
|
1861
2123
|
let targetNodeId = input.nodeId;
|
|
1862
2124
|
if (!targetNodeId && input.filePath) {
|
|
1863
2125
|
const fileNodes = store.findNodes({ type: "file" });
|
|
@@ -1966,6 +2228,9 @@ async function handleGetImpact(input) {
|
|
|
1966
2228
|
};
|
|
1967
2229
|
}
|
|
1968
2230
|
}
|
|
2231
|
+
|
|
2232
|
+
// src/mcp/tools/graph/ingest-source.ts
|
|
2233
|
+
import * as path13 from "path";
|
|
1969
2234
|
var ingestSourceDefinition = {
|
|
1970
2235
|
name: "ingest_source",
|
|
1971
2236
|
description: "Ingest sources into the project knowledge graph. Supports code analysis, knowledge documents, git history, or all at once.",
|
|
@@ -1985,10 +2250,10 @@ var ingestSourceDefinition = {
|
|
|
1985
2250
|
async function handleIngestSource(input) {
|
|
1986
2251
|
try {
|
|
1987
2252
|
const projectPath = sanitizePath(input.path);
|
|
1988
|
-
const graphDir =
|
|
1989
|
-
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-
|
|
1990
|
-
const
|
|
1991
|
-
await
|
|
2253
|
+
const graphDir = path13.join(projectPath, ".harness", "graph");
|
|
2254
|
+
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-HXHWB7SV.js");
|
|
2255
|
+
const fs12 = await import("fs/promises");
|
|
2256
|
+
await fs12.mkdir(graphDir, { recursive: true });
|
|
1992
2257
|
const store = new GraphStore();
|
|
1993
2258
|
await store.load(graphDir);
|
|
1994
2259
|
const results = [];
|
|
@@ -2037,6 +2302,8 @@ async function handleIngestSource(input) {
|
|
|
2037
2302
|
};
|
|
2038
2303
|
}
|
|
2039
2304
|
}
|
|
2305
|
+
|
|
2306
|
+
// src/mcp/tools/graph/detect-anomalies.ts
|
|
2040
2307
|
var detectAnomaliesDefinition = {
|
|
2041
2308
|
name: "detect_anomalies",
|
|
2042
2309
|
description: "Detect structural anomalies \u2014 statistical outliers across code metrics and topological single points of failure in the import graph",
|
|
@@ -2059,7 +2326,7 @@ async function handleDetectAnomalies(input) {
|
|
|
2059
2326
|
const projectPath = sanitizePath(input.path);
|
|
2060
2327
|
const store = await loadGraphStore(projectPath);
|
|
2061
2328
|
if (!store) return graphNotFoundError();
|
|
2062
|
-
const { GraphAnomalyAdapter } = await import("./dist-
|
|
2329
|
+
const { GraphAnomalyAdapter } = await import("./dist-HXHWB7SV.js");
|
|
2063
2330
|
const adapter = new GraphAnomalyAdapter(store);
|
|
2064
2331
|
const report = adapter.detect({
|
|
2065
2332
|
...input.threshold !== void 0 && { threshold: input.threshold },
|
|
@@ -2080,6 +2347,8 @@ async function handleDetectAnomalies(input) {
|
|
|
2080
2347
|
};
|
|
2081
2348
|
}
|
|
2082
2349
|
}
|
|
2350
|
+
|
|
2351
|
+
// src/mcp/tools/graph/ask-graph.ts
|
|
2083
2352
|
var askGraphDefinition = {
|
|
2084
2353
|
name: "ask_graph",
|
|
2085
2354
|
description: 'Ask a natural language question about the codebase knowledge graph. Supports questions about impact ("what breaks if I change X?"), finding entities ("where is the auth middleware?"), relationships ("what calls UserService?"), explanations ("what is GraphStore?"), and anomalies ("what looks wrong?"). Returns a human-readable summary and raw graph data.',
|
|
@@ -2097,7 +2366,7 @@ async function handleAskGraph(input) {
|
|
|
2097
2366
|
const projectPath = sanitizePath(input.path);
|
|
2098
2367
|
const store = await loadGraphStore(projectPath);
|
|
2099
2368
|
if (!store) return graphNotFoundError();
|
|
2100
|
-
const { askGraph } = await import("./dist-
|
|
2369
|
+
const { askGraph } = await import("./dist-HXHWB7SV.js");
|
|
2101
2370
|
const result = await askGraph(store, input.question);
|
|
2102
2371
|
return {
|
|
2103
2372
|
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
@@ -2116,8 +2385,8 @@ async function handleAskGraph(input) {
|
|
|
2116
2385
|
}
|
|
2117
2386
|
|
|
2118
2387
|
// src/mcp/resources/graph.ts
|
|
2119
|
-
import * as
|
|
2120
|
-
import * as
|
|
2388
|
+
import * as fs10 from "fs/promises";
|
|
2389
|
+
import * as path14 from "path";
|
|
2121
2390
|
var MAX_ITEMS = 5e3;
|
|
2122
2391
|
function formatStaleness(isoTimestamp) {
|
|
2123
2392
|
const then = new Date(isoTimestamp).getTime();
|
|
@@ -2140,11 +2409,11 @@ async function getGraphResource(projectRoot) {
|
|
|
2140
2409
|
message: "No knowledge graph found. Run harness scan to build one."
|
|
2141
2410
|
});
|
|
2142
2411
|
}
|
|
2143
|
-
const graphDir =
|
|
2144
|
-
const metadataPath =
|
|
2412
|
+
const graphDir = path14.join(projectRoot, ".harness", "graph");
|
|
2413
|
+
const metadataPath = path14.join(graphDir, "metadata.json");
|
|
2145
2414
|
let lastScanTimestamp = null;
|
|
2146
2415
|
try {
|
|
2147
|
-
const raw = JSON.parse(await
|
|
2416
|
+
const raw = JSON.parse(await fs10.readFile(metadataPath, "utf-8"));
|
|
2148
2417
|
lastScanTimestamp = raw.lastScanTimestamp ?? null;
|
|
2149
2418
|
} catch {
|
|
2150
2419
|
}
|
|
@@ -2233,7 +2502,7 @@ var generateAgentDefinitionsDefinition = {
|
|
|
2233
2502
|
}
|
|
2234
2503
|
};
|
|
2235
2504
|
async function handleGenerateAgentDefinitions(input) {
|
|
2236
|
-
const { generateAgentDefinitions } = await import("./generate-agent-definitions-
|
|
2505
|
+
const { generateAgentDefinitions } = await import("./generate-agent-definitions-64S3CLEZ.js");
|
|
2237
2506
|
const platforms = input.platform === "all" || !input.platform ? ["claude-code", "gemini-cli"] : [input.platform];
|
|
2238
2507
|
const results = generateAgentDefinitions({
|
|
2239
2508
|
platforms: [...platforms],
|
|
@@ -2244,8 +2513,8 @@ async function handleGenerateAgentDefinitions(input) {
|
|
|
2244
2513
|
}
|
|
2245
2514
|
|
|
2246
2515
|
// src/mcp/tools/roadmap.ts
|
|
2247
|
-
import * as
|
|
2248
|
-
import * as
|
|
2516
|
+
import * as fs11 from "fs";
|
|
2517
|
+
import * as path15 from "path";
|
|
2249
2518
|
var manageRoadmapDefinition = {
|
|
2250
2519
|
name: "manage_roadmap",
|
|
2251
2520
|
description: "Manage the project roadmap: show, add, update, remove, sync features, or query by filter. Reads and writes docs/roadmap.md.",
|
|
@@ -2300,309 +2569,261 @@ var manageRoadmapDefinition = {
|
|
|
2300
2569
|
}
|
|
2301
2570
|
};
|
|
2302
2571
|
function roadmapPath(projectRoot) {
|
|
2303
|
-
return
|
|
2572
|
+
return path15.join(projectRoot, "docs", "roadmap.md");
|
|
2304
2573
|
}
|
|
2305
2574
|
function readRoadmapFile(projectRoot) {
|
|
2306
2575
|
const filePath = roadmapPath(projectRoot);
|
|
2307
2576
|
try {
|
|
2308
|
-
return
|
|
2577
|
+
return fs11.readFileSync(filePath, "utf-8");
|
|
2309
2578
|
} catch {
|
|
2310
2579
|
return null;
|
|
2311
2580
|
}
|
|
2312
2581
|
}
|
|
2313
2582
|
function writeRoadmapFile(projectRoot, content) {
|
|
2314
2583
|
const filePath = roadmapPath(projectRoot);
|
|
2315
|
-
const dir =
|
|
2316
|
-
|
|
2317
|
-
|
|
2584
|
+
const dir = path15.dirname(filePath);
|
|
2585
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
2586
|
+
fs11.writeFileSync(filePath, content, "utf-8");
|
|
2587
|
+
}
|
|
2588
|
+
function roadmapNotFoundError() {
|
|
2589
|
+
return {
|
|
2590
|
+
content: [
|
|
2591
|
+
{
|
|
2592
|
+
type: "text",
|
|
2593
|
+
text: "Error: docs/roadmap.md not found. Create a roadmap first."
|
|
2594
|
+
}
|
|
2595
|
+
],
|
|
2596
|
+
isError: true
|
|
2597
|
+
};
|
|
2598
|
+
}
|
|
2599
|
+
function handleShow(projectPath, input, deps) {
|
|
2600
|
+
const { parseRoadmap, Ok: Ok2 } = deps;
|
|
2601
|
+
const raw = readRoadmapFile(projectPath);
|
|
2602
|
+
if (raw === null) return roadmapNotFoundError();
|
|
2603
|
+
const result = parseRoadmap(raw);
|
|
2604
|
+
if (!result.ok) return resultToMcpResponse(result);
|
|
2605
|
+
let roadmap = result.value;
|
|
2606
|
+
if (input.milestone) {
|
|
2607
|
+
const milestoneFilter = input.milestone;
|
|
2608
|
+
roadmap = {
|
|
2609
|
+
...roadmap,
|
|
2610
|
+
milestones: roadmap.milestones.filter(
|
|
2611
|
+
(m) => m.name.toLowerCase() === milestoneFilter.toLowerCase()
|
|
2612
|
+
)
|
|
2613
|
+
};
|
|
2614
|
+
}
|
|
2615
|
+
if (input.status) {
|
|
2616
|
+
const statusFilter = input.status;
|
|
2617
|
+
roadmap = {
|
|
2618
|
+
...roadmap,
|
|
2619
|
+
milestones: roadmap.milestones.map((m) => ({
|
|
2620
|
+
...m,
|
|
2621
|
+
features: m.features.filter((f) => f.status === statusFilter)
|
|
2622
|
+
})).filter((m) => m.features.length > 0)
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2625
|
+
return resultToMcpResponse(Ok2(roadmap));
|
|
2626
|
+
}
|
|
2627
|
+
function handleAdd(projectPath, input, deps) {
|
|
2628
|
+
const { parseRoadmap, serializeRoadmap, Ok: Ok2 } = deps;
|
|
2629
|
+
if (!input.feature) {
|
|
2630
|
+
return {
|
|
2631
|
+
content: [{ type: "text", text: "Error: feature is required for add action" }],
|
|
2632
|
+
isError: true
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
if (!input.milestone) {
|
|
2636
|
+
return {
|
|
2637
|
+
content: [{ type: "text", text: "Error: milestone is required for add action" }],
|
|
2638
|
+
isError: true
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2641
|
+
if (!input.status) {
|
|
2642
|
+
return {
|
|
2643
|
+
content: [{ type: "text", text: "Error: status is required for add action" }],
|
|
2644
|
+
isError: true
|
|
2645
|
+
};
|
|
2646
|
+
}
|
|
2647
|
+
if (!input.summary) {
|
|
2648
|
+
return {
|
|
2649
|
+
content: [{ type: "text", text: "Error: summary is required for add action" }],
|
|
2650
|
+
isError: true
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
2653
|
+
const raw = readRoadmapFile(projectPath);
|
|
2654
|
+
if (raw === null) return roadmapNotFoundError();
|
|
2655
|
+
const result = parseRoadmap(raw);
|
|
2656
|
+
if (!result.ok) return resultToMcpResponse(result);
|
|
2657
|
+
const roadmap = result.value;
|
|
2658
|
+
const milestone = roadmap.milestones.find(
|
|
2659
|
+
(m) => m.name.toLowerCase() === input.milestone.toLowerCase()
|
|
2660
|
+
);
|
|
2661
|
+
if (!milestone) {
|
|
2662
|
+
return {
|
|
2663
|
+
content: [{ type: "text", text: `Error: milestone "${input.milestone}" not found` }],
|
|
2664
|
+
isError: true
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
milestone.features.push({
|
|
2668
|
+
name: input.feature,
|
|
2669
|
+
status: input.status,
|
|
2670
|
+
spec: input.spec ?? null,
|
|
2671
|
+
plans: input.plans ?? [],
|
|
2672
|
+
blockedBy: input.blocked_by ?? [],
|
|
2673
|
+
summary: input.summary
|
|
2674
|
+
});
|
|
2675
|
+
roadmap.frontmatter.lastManualEdit = (/* @__PURE__ */ new Date()).toISOString();
|
|
2676
|
+
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2677
|
+
return resultToMcpResponse(Ok2(roadmap));
|
|
2678
|
+
}
|
|
2679
|
+
function handleUpdate(projectPath, input, deps) {
|
|
2680
|
+
const { parseRoadmap, serializeRoadmap, Ok: Ok2 } = deps;
|
|
2681
|
+
if (!input.feature) {
|
|
2682
|
+
return {
|
|
2683
|
+
content: [{ type: "text", text: "Error: feature is required for update action" }],
|
|
2684
|
+
isError: true
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
const raw = readRoadmapFile(projectPath);
|
|
2688
|
+
if (raw === null) return roadmapNotFoundError();
|
|
2689
|
+
const result = parseRoadmap(raw);
|
|
2690
|
+
if (!result.ok) return resultToMcpResponse(result);
|
|
2691
|
+
const roadmap = result.value;
|
|
2692
|
+
let found = false;
|
|
2693
|
+
for (const m of roadmap.milestones) {
|
|
2694
|
+
const feature = m.features.find((f) => f.name.toLowerCase() === input.feature.toLowerCase());
|
|
2695
|
+
if (feature) {
|
|
2696
|
+
if (input.status) feature.status = input.status;
|
|
2697
|
+
if (input.summary !== void 0) feature.summary = input.summary;
|
|
2698
|
+
if (input.spec !== void 0) feature.spec = input.spec || null;
|
|
2699
|
+
if (input.plans !== void 0) feature.plans = input.plans;
|
|
2700
|
+
if (input.blocked_by !== void 0) feature.blockedBy = input.blocked_by;
|
|
2701
|
+
found = true;
|
|
2702
|
+
break;
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
if (!found) {
|
|
2706
|
+
return {
|
|
2707
|
+
content: [{ type: "text", text: `Error: feature "${input.feature}" not found` }],
|
|
2708
|
+
isError: true
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
roadmap.frontmatter.lastManualEdit = (/* @__PURE__ */ new Date()).toISOString();
|
|
2712
|
+
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2713
|
+
return resultToMcpResponse(Ok2(roadmap));
|
|
2714
|
+
}
|
|
2715
|
+
function handleRemove(projectPath, input, deps) {
|
|
2716
|
+
const { parseRoadmap, serializeRoadmap, Ok: Ok2 } = deps;
|
|
2717
|
+
if (!input.feature) {
|
|
2718
|
+
return {
|
|
2719
|
+
content: [{ type: "text", text: "Error: feature is required for remove action" }],
|
|
2720
|
+
isError: true
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
const raw = readRoadmapFile(projectPath);
|
|
2724
|
+
if (raw === null) return roadmapNotFoundError();
|
|
2725
|
+
const result = parseRoadmap(raw);
|
|
2726
|
+
if (!result.ok) return resultToMcpResponse(result);
|
|
2727
|
+
const roadmap = result.value;
|
|
2728
|
+
let found = false;
|
|
2729
|
+
for (const m of roadmap.milestones) {
|
|
2730
|
+
const idx = m.features.findIndex((f) => f.name.toLowerCase() === input.feature.toLowerCase());
|
|
2731
|
+
if (idx !== -1) {
|
|
2732
|
+
m.features.splice(idx, 1);
|
|
2733
|
+
found = true;
|
|
2734
|
+
break;
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
if (!found) {
|
|
2738
|
+
return {
|
|
2739
|
+
content: [{ type: "text", text: `Error: feature "${input.feature}" not found` }],
|
|
2740
|
+
isError: true
|
|
2741
|
+
};
|
|
2742
|
+
}
|
|
2743
|
+
roadmap.frontmatter.lastManualEdit = (/* @__PURE__ */ new Date()).toISOString();
|
|
2744
|
+
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2745
|
+
return resultToMcpResponse(Ok2(roadmap));
|
|
2746
|
+
}
|
|
2747
|
+
function handleQuery(projectPath, input, deps) {
|
|
2748
|
+
const { parseRoadmap, Ok: Ok2 } = deps;
|
|
2749
|
+
if (!input.filter) {
|
|
2750
|
+
return {
|
|
2751
|
+
content: [{ type: "text", text: "Error: filter is required for query action" }],
|
|
2752
|
+
isError: true
|
|
2753
|
+
};
|
|
2754
|
+
}
|
|
2755
|
+
const raw = readRoadmapFile(projectPath);
|
|
2756
|
+
if (raw === null) return roadmapNotFoundError();
|
|
2757
|
+
const result = parseRoadmap(raw);
|
|
2758
|
+
if (!result.ok) return resultToMcpResponse(result);
|
|
2759
|
+
const roadmap = result.value;
|
|
2760
|
+
const allFeatures = roadmap.milestones.flatMap(
|
|
2761
|
+
(m) => m.features.map((f) => ({ ...f, milestone: m.name }))
|
|
2762
|
+
);
|
|
2763
|
+
const filter = input.filter.toLowerCase();
|
|
2764
|
+
let filtered;
|
|
2765
|
+
if (filter.startsWith("milestone:")) {
|
|
2766
|
+
const milestoneName = filter.slice("milestone:".length).trim();
|
|
2767
|
+
filtered = allFeatures.filter((f) => f.milestone.toLowerCase().includes(milestoneName));
|
|
2768
|
+
} else {
|
|
2769
|
+
filtered = allFeatures.filter((f) => f.status === filter);
|
|
2770
|
+
}
|
|
2771
|
+
return resultToMcpResponse(Ok2(filtered));
|
|
2772
|
+
}
|
|
2773
|
+
function handleSync(projectPath, input, deps) {
|
|
2774
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap, Ok: Ok2 } = deps;
|
|
2775
|
+
const raw = readRoadmapFile(projectPath);
|
|
2776
|
+
if (raw === null) return roadmapNotFoundError();
|
|
2777
|
+
const result = parseRoadmap(raw);
|
|
2778
|
+
if (!result.ok) return resultToMcpResponse(result);
|
|
2779
|
+
const roadmap = result.value;
|
|
2780
|
+
const syncResult = syncRoadmap({
|
|
2781
|
+
projectPath,
|
|
2782
|
+
roadmap,
|
|
2783
|
+
forceSync: input.force_sync ?? false
|
|
2784
|
+
});
|
|
2785
|
+
if (!syncResult.ok) return resultToMcpResponse(syncResult);
|
|
2786
|
+
const changes = syncResult.value;
|
|
2787
|
+
if (changes.length === 0) {
|
|
2788
|
+
return resultToMcpResponse(Ok2({ changes: [], message: "Roadmap is up to date." }));
|
|
2789
|
+
}
|
|
2790
|
+
if (input.apply) {
|
|
2791
|
+
for (const change of changes) {
|
|
2792
|
+
for (const m of roadmap.milestones) {
|
|
2793
|
+
const feature = m.features.find(
|
|
2794
|
+
(f) => f.name.toLowerCase() === change.feature.toLowerCase()
|
|
2795
|
+
);
|
|
2796
|
+
if (feature) {
|
|
2797
|
+
feature.status = change.to;
|
|
2798
|
+
break;
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
roadmap.frontmatter.lastSynced = (/* @__PURE__ */ new Date()).toISOString();
|
|
2803
|
+
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2804
|
+
return resultToMcpResponse(Ok2({ changes, applied: true, roadmap }));
|
|
2805
|
+
}
|
|
2806
|
+
return resultToMcpResponse(Ok2({ changes, applied: false }));
|
|
2318
2807
|
}
|
|
2319
2808
|
async function handleManageRoadmap(input) {
|
|
2320
2809
|
try {
|
|
2321
|
-
const { parseRoadmap, serializeRoadmap, syncRoadmap } = await import("./dist-
|
|
2810
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap } = await import("./dist-2B363XUH.js");
|
|
2322
2811
|
const { Ok: Ok2 } = await import("./dist-D4RYGUZE.js");
|
|
2323
2812
|
const projectPath = sanitizePath(input.path);
|
|
2813
|
+
const deps = { parseRoadmap, serializeRoadmap, syncRoadmap, Ok: Ok2 };
|
|
2324
2814
|
switch (input.action) {
|
|
2325
|
-
case "show":
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
}
|
|
2338
|
-
const result = parseRoadmap(raw);
|
|
2339
|
-
if (!result.ok) return resultToMcpResponse(result);
|
|
2340
|
-
let roadmap = result.value;
|
|
2341
|
-
if (input.milestone) {
|
|
2342
|
-
const milestoneFilter = input.milestone;
|
|
2343
|
-
roadmap = {
|
|
2344
|
-
...roadmap,
|
|
2345
|
-
milestones: roadmap.milestones.filter(
|
|
2346
|
-
(m) => m.name.toLowerCase() === milestoneFilter.toLowerCase()
|
|
2347
|
-
)
|
|
2348
|
-
};
|
|
2349
|
-
}
|
|
2350
|
-
if (input.status) {
|
|
2351
|
-
const statusFilter = input.status;
|
|
2352
|
-
roadmap = {
|
|
2353
|
-
...roadmap,
|
|
2354
|
-
milestones: roadmap.milestones.map((m) => ({
|
|
2355
|
-
...m,
|
|
2356
|
-
features: m.features.filter((f) => f.status === statusFilter)
|
|
2357
|
-
})).filter((m) => m.features.length > 0)
|
|
2358
|
-
};
|
|
2359
|
-
}
|
|
2360
|
-
return resultToMcpResponse(Ok2(roadmap));
|
|
2361
|
-
}
|
|
2362
|
-
case "add": {
|
|
2363
|
-
if (!input.feature) {
|
|
2364
|
-
return {
|
|
2365
|
-
content: [{ type: "text", text: "Error: feature is required for add action" }],
|
|
2366
|
-
isError: true
|
|
2367
|
-
};
|
|
2368
|
-
}
|
|
2369
|
-
if (!input.milestone) {
|
|
2370
|
-
return {
|
|
2371
|
-
content: [
|
|
2372
|
-
{ type: "text", text: "Error: milestone is required for add action" }
|
|
2373
|
-
],
|
|
2374
|
-
isError: true
|
|
2375
|
-
};
|
|
2376
|
-
}
|
|
2377
|
-
if (!input.status) {
|
|
2378
|
-
return {
|
|
2379
|
-
content: [{ type: "text", text: "Error: status is required for add action" }],
|
|
2380
|
-
isError: true
|
|
2381
|
-
};
|
|
2382
|
-
}
|
|
2383
|
-
if (!input.summary) {
|
|
2384
|
-
return {
|
|
2385
|
-
content: [{ type: "text", text: "Error: summary is required for add action" }],
|
|
2386
|
-
isError: true
|
|
2387
|
-
};
|
|
2388
|
-
}
|
|
2389
|
-
const raw = readRoadmapFile(projectPath);
|
|
2390
|
-
if (raw === null) {
|
|
2391
|
-
return {
|
|
2392
|
-
content: [
|
|
2393
|
-
{
|
|
2394
|
-
type: "text",
|
|
2395
|
-
text: "Error: docs/roadmap.md not found. Create a roadmap first."
|
|
2396
|
-
}
|
|
2397
|
-
],
|
|
2398
|
-
isError: true
|
|
2399
|
-
};
|
|
2400
|
-
}
|
|
2401
|
-
const result = parseRoadmap(raw);
|
|
2402
|
-
if (!result.ok) return resultToMcpResponse(result);
|
|
2403
|
-
const roadmap = result.value;
|
|
2404
|
-
const milestone = roadmap.milestones.find(
|
|
2405
|
-
(m) => m.name.toLowerCase() === input.milestone.toLowerCase()
|
|
2406
|
-
);
|
|
2407
|
-
if (!milestone) {
|
|
2408
|
-
return {
|
|
2409
|
-
content: [
|
|
2410
|
-
{ type: "text", text: `Error: milestone "${input.milestone}" not found` }
|
|
2411
|
-
],
|
|
2412
|
-
isError: true
|
|
2413
|
-
};
|
|
2414
|
-
}
|
|
2415
|
-
milestone.features.push({
|
|
2416
|
-
name: input.feature,
|
|
2417
|
-
status: input.status,
|
|
2418
|
-
spec: input.spec ?? null,
|
|
2419
|
-
plans: input.plans ?? [],
|
|
2420
|
-
blockedBy: input.blocked_by ?? [],
|
|
2421
|
-
summary: input.summary
|
|
2422
|
-
});
|
|
2423
|
-
roadmap.frontmatter.lastManualEdit = (/* @__PURE__ */ new Date()).toISOString();
|
|
2424
|
-
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2425
|
-
return resultToMcpResponse(Ok2(roadmap));
|
|
2426
|
-
}
|
|
2427
|
-
case "update": {
|
|
2428
|
-
if (!input.feature) {
|
|
2429
|
-
return {
|
|
2430
|
-
content: [
|
|
2431
|
-
{ type: "text", text: "Error: feature is required for update action" }
|
|
2432
|
-
],
|
|
2433
|
-
isError: true
|
|
2434
|
-
};
|
|
2435
|
-
}
|
|
2436
|
-
const raw = readRoadmapFile(projectPath);
|
|
2437
|
-
if (raw === null) {
|
|
2438
|
-
return {
|
|
2439
|
-
content: [
|
|
2440
|
-
{
|
|
2441
|
-
type: "text",
|
|
2442
|
-
text: "Error: docs/roadmap.md not found. Create a roadmap first."
|
|
2443
|
-
}
|
|
2444
|
-
],
|
|
2445
|
-
isError: true
|
|
2446
|
-
};
|
|
2447
|
-
}
|
|
2448
|
-
const result = parseRoadmap(raw);
|
|
2449
|
-
if (!result.ok) return resultToMcpResponse(result);
|
|
2450
|
-
const roadmap = result.value;
|
|
2451
|
-
let found = false;
|
|
2452
|
-
for (const m of roadmap.milestones) {
|
|
2453
|
-
const feature = m.features.find(
|
|
2454
|
-
(f) => f.name.toLowerCase() === input.feature.toLowerCase()
|
|
2455
|
-
);
|
|
2456
|
-
if (feature) {
|
|
2457
|
-
if (input.status) feature.status = input.status;
|
|
2458
|
-
if (input.summary !== void 0) feature.summary = input.summary;
|
|
2459
|
-
if (input.spec !== void 0) feature.spec = input.spec || null;
|
|
2460
|
-
if (input.plans !== void 0) feature.plans = input.plans;
|
|
2461
|
-
if (input.blocked_by !== void 0) feature.blockedBy = input.blocked_by;
|
|
2462
|
-
found = true;
|
|
2463
|
-
break;
|
|
2464
|
-
}
|
|
2465
|
-
}
|
|
2466
|
-
if (!found) {
|
|
2467
|
-
return {
|
|
2468
|
-
content: [
|
|
2469
|
-
{ type: "text", text: `Error: feature "${input.feature}" not found` }
|
|
2470
|
-
],
|
|
2471
|
-
isError: true
|
|
2472
|
-
};
|
|
2473
|
-
}
|
|
2474
|
-
roadmap.frontmatter.lastManualEdit = (/* @__PURE__ */ new Date()).toISOString();
|
|
2475
|
-
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2476
|
-
return resultToMcpResponse(Ok2(roadmap));
|
|
2477
|
-
}
|
|
2478
|
-
case "remove": {
|
|
2479
|
-
if (!input.feature) {
|
|
2480
|
-
return {
|
|
2481
|
-
content: [
|
|
2482
|
-
{ type: "text", text: "Error: feature is required for remove action" }
|
|
2483
|
-
],
|
|
2484
|
-
isError: true
|
|
2485
|
-
};
|
|
2486
|
-
}
|
|
2487
|
-
const raw = readRoadmapFile(projectPath);
|
|
2488
|
-
if (raw === null) {
|
|
2489
|
-
return {
|
|
2490
|
-
content: [
|
|
2491
|
-
{
|
|
2492
|
-
type: "text",
|
|
2493
|
-
text: "Error: docs/roadmap.md not found. Create a roadmap first."
|
|
2494
|
-
}
|
|
2495
|
-
],
|
|
2496
|
-
isError: true
|
|
2497
|
-
};
|
|
2498
|
-
}
|
|
2499
|
-
const result = parseRoadmap(raw);
|
|
2500
|
-
if (!result.ok) return resultToMcpResponse(result);
|
|
2501
|
-
const roadmap = result.value;
|
|
2502
|
-
let found = false;
|
|
2503
|
-
for (const m of roadmap.milestones) {
|
|
2504
|
-
const idx = m.features.findIndex(
|
|
2505
|
-
(f) => f.name.toLowerCase() === input.feature.toLowerCase()
|
|
2506
|
-
);
|
|
2507
|
-
if (idx !== -1) {
|
|
2508
|
-
m.features.splice(idx, 1);
|
|
2509
|
-
found = true;
|
|
2510
|
-
break;
|
|
2511
|
-
}
|
|
2512
|
-
}
|
|
2513
|
-
if (!found) {
|
|
2514
|
-
return {
|
|
2515
|
-
content: [
|
|
2516
|
-
{ type: "text", text: `Error: feature "${input.feature}" not found` }
|
|
2517
|
-
],
|
|
2518
|
-
isError: true
|
|
2519
|
-
};
|
|
2520
|
-
}
|
|
2521
|
-
roadmap.frontmatter.lastManualEdit = (/* @__PURE__ */ new Date()).toISOString();
|
|
2522
|
-
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2523
|
-
return resultToMcpResponse(Ok2(roadmap));
|
|
2524
|
-
}
|
|
2525
|
-
case "query": {
|
|
2526
|
-
if (!input.filter) {
|
|
2527
|
-
return {
|
|
2528
|
-
content: [
|
|
2529
|
-
{ type: "text", text: "Error: filter is required for query action" }
|
|
2530
|
-
],
|
|
2531
|
-
isError: true
|
|
2532
|
-
};
|
|
2533
|
-
}
|
|
2534
|
-
const raw = readRoadmapFile(projectPath);
|
|
2535
|
-
if (raw === null) {
|
|
2536
|
-
return {
|
|
2537
|
-
content: [
|
|
2538
|
-
{
|
|
2539
|
-
type: "text",
|
|
2540
|
-
text: "Error: docs/roadmap.md not found. Create a roadmap first."
|
|
2541
|
-
}
|
|
2542
|
-
],
|
|
2543
|
-
isError: true
|
|
2544
|
-
};
|
|
2545
|
-
}
|
|
2546
|
-
const result = parseRoadmap(raw);
|
|
2547
|
-
if (!result.ok) return resultToMcpResponse(result);
|
|
2548
|
-
const roadmap = result.value;
|
|
2549
|
-
const allFeatures = roadmap.milestones.flatMap(
|
|
2550
|
-
(m) => m.features.map((f) => ({ ...f, milestone: m.name }))
|
|
2551
|
-
);
|
|
2552
|
-
const filter = input.filter.toLowerCase();
|
|
2553
|
-
let filtered;
|
|
2554
|
-
if (filter.startsWith("milestone:")) {
|
|
2555
|
-
const milestoneName = filter.slice("milestone:".length).trim();
|
|
2556
|
-
filtered = allFeatures.filter((f) => f.milestone.toLowerCase().includes(milestoneName));
|
|
2557
|
-
} else {
|
|
2558
|
-
filtered = allFeatures.filter((f) => f.status === filter);
|
|
2559
|
-
}
|
|
2560
|
-
return resultToMcpResponse(Ok2(filtered));
|
|
2561
|
-
}
|
|
2562
|
-
case "sync": {
|
|
2563
|
-
const raw = readRoadmapFile(projectPath);
|
|
2564
|
-
if (raw === null) {
|
|
2565
|
-
return {
|
|
2566
|
-
content: [
|
|
2567
|
-
{
|
|
2568
|
-
type: "text",
|
|
2569
|
-
text: "Error: docs/roadmap.md not found. Create a roadmap first."
|
|
2570
|
-
}
|
|
2571
|
-
],
|
|
2572
|
-
isError: true
|
|
2573
|
-
};
|
|
2574
|
-
}
|
|
2575
|
-
const result = parseRoadmap(raw);
|
|
2576
|
-
if (!result.ok) return resultToMcpResponse(result);
|
|
2577
|
-
const roadmap = result.value;
|
|
2578
|
-
const syncResult = syncRoadmap({
|
|
2579
|
-
projectPath,
|
|
2580
|
-
roadmap,
|
|
2581
|
-
forceSync: input.force_sync ?? false
|
|
2582
|
-
});
|
|
2583
|
-
if (!syncResult.ok) return resultToMcpResponse(syncResult);
|
|
2584
|
-
const changes = syncResult.value;
|
|
2585
|
-
if (changes.length === 0) {
|
|
2586
|
-
return resultToMcpResponse(Ok2({ changes: [], message: "Roadmap is up to date." }));
|
|
2587
|
-
}
|
|
2588
|
-
if (input.apply) {
|
|
2589
|
-
for (const change of changes) {
|
|
2590
|
-
for (const m of roadmap.milestones) {
|
|
2591
|
-
const feature = m.features.find(
|
|
2592
|
-
(f) => f.name.toLowerCase() === change.feature.toLowerCase()
|
|
2593
|
-
);
|
|
2594
|
-
if (feature) {
|
|
2595
|
-
feature.status = change.to;
|
|
2596
|
-
break;
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
}
|
|
2600
|
-
roadmap.frontmatter.lastSynced = (/* @__PURE__ */ new Date()).toISOString();
|
|
2601
|
-
writeRoadmapFile(projectPath, serializeRoadmap(roadmap));
|
|
2602
|
-
return resultToMcpResponse(Ok2({ changes, applied: true, roadmap }));
|
|
2603
|
-
}
|
|
2604
|
-
return resultToMcpResponse(Ok2({ changes, applied: false }));
|
|
2605
|
-
}
|
|
2815
|
+
case "show":
|
|
2816
|
+
return handleShow(projectPath, input, deps);
|
|
2817
|
+
case "add":
|
|
2818
|
+
return handleAdd(projectPath, input, deps);
|
|
2819
|
+
case "update":
|
|
2820
|
+
return handleUpdate(projectPath, input, deps);
|
|
2821
|
+
case "remove":
|
|
2822
|
+
return handleRemove(projectPath, input, deps);
|
|
2823
|
+
case "query":
|
|
2824
|
+
return handleQuery(projectPath, input, deps);
|
|
2825
|
+
case "sync":
|
|
2826
|
+
return handleSync(projectPath, input, deps);
|
|
2606
2827
|
default: {
|
|
2607
2828
|
return {
|
|
2608
2829
|
content: [{ type: "text", text: `Error: unknown action` }],
|
|
@@ -3089,7 +3310,7 @@ async function handleEmitInteraction(input) {
|
|
|
3089
3310
|
const transition = transitionResult.data;
|
|
3090
3311
|
const prompt = renderTransition(transition);
|
|
3091
3312
|
try {
|
|
3092
|
-
const { saveHandoff } = await import("./dist-
|
|
3313
|
+
const { saveHandoff } = await import("./dist-2B363XUH.js");
|
|
3093
3314
|
await saveHandoff(
|
|
3094
3315
|
projectPath,
|
|
3095
3316
|
{
|
|
@@ -3191,7 +3412,7 @@ async function handleEmitInteraction(input) {
|
|
|
3191
3412
|
}
|
|
3192
3413
|
async function recordInteraction(projectPath, id, type, decision, stream) {
|
|
3193
3414
|
try {
|
|
3194
|
-
const { loadState, saveState } = await import("./dist-
|
|
3415
|
+
const { loadState, saveState } = await import("./dist-2B363XUH.js");
|
|
3195
3416
|
const stateResult = await loadState(projectPath, stream);
|
|
3196
3417
|
if (stateResult.ok) {
|
|
3197
3418
|
const state = stateResult.value;
|
|
@@ -3271,10 +3492,10 @@ async function handleGatherContext(input) {
|
|
|
3271
3492
|
input.include ?? ["state", "learnings", "handoff", "graph", "validation"]
|
|
3272
3493
|
);
|
|
3273
3494
|
const errors = [];
|
|
3274
|
-
const statePromise = includeSet.has("state") ? import("./dist-
|
|
3495
|
+
const statePromise = includeSet.has("state") ? import("./dist-2B363XUH.js").then(
|
|
3275
3496
|
(core) => core.loadState(projectPath, void 0, input.session)
|
|
3276
3497
|
) : Promise.resolve(null);
|
|
3277
|
-
const learningsPromise = includeSet.has("learnings") ? import("./dist-
|
|
3498
|
+
const learningsPromise = includeSet.has("learnings") ? import("./dist-2B363XUH.js").then(
|
|
3278
3499
|
(core) => core.loadBudgetedLearnings(projectPath, {
|
|
3279
3500
|
intent: input.intent,
|
|
3280
3501
|
tokenBudget: input.learningsBudget ?? 1e3,
|
|
@@ -3282,14 +3503,14 @@ async function handleGatherContext(input) {
|
|
|
3282
3503
|
...input.session !== void 0 && { session: input.session }
|
|
3283
3504
|
})
|
|
3284
3505
|
) : Promise.resolve(null);
|
|
3285
|
-
const handoffPromise = includeSet.has("handoff") ? import("./dist-
|
|
3506
|
+
const handoffPromise = includeSet.has("handoff") ? import("./dist-2B363XUH.js").then(
|
|
3286
3507
|
(core) => core.loadHandoff(projectPath, void 0, input.session)
|
|
3287
3508
|
) : Promise.resolve(null);
|
|
3288
3509
|
const graphPromise = includeSet.has("graph") ? (async () => {
|
|
3289
|
-
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-
|
|
3510
|
+
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-GJZ4FN4Y.js");
|
|
3290
3511
|
const store = await loadGraphStore2(projectPath);
|
|
3291
3512
|
if (!store) return null;
|
|
3292
|
-
const { FusionLayer, ContextQL } = await import("./dist-
|
|
3513
|
+
const { FusionLayer, ContextQL } = await import("./dist-HXHWB7SV.js");
|
|
3293
3514
|
const fusion = new FusionLayer(store);
|
|
3294
3515
|
const cql = new ContextQL(store);
|
|
3295
3516
|
const tokenBudget = input.tokenBudget ?? 4e3;
|
|
@@ -3327,7 +3548,7 @@ async function handleGatherContext(input) {
|
|
|
3327
3548
|
};
|
|
3328
3549
|
})() : Promise.resolve(null);
|
|
3329
3550
|
const validationPromise = includeSet.has("validation") ? (async () => {
|
|
3330
|
-
const { handleValidateProject: handleValidateProject2 } = await import("./validate-
|
|
3551
|
+
const { handleValidateProject: handleValidateProject2 } = await import("./validate-GCHZJIL7.js");
|
|
3331
3552
|
const result = await handleValidateProject2({ path: projectPath });
|
|
3332
3553
|
const first = result.content[0];
|
|
3333
3554
|
return first ? JSON.parse(first.text) : null;
|
|
@@ -3401,7 +3622,7 @@ async function handleGatherContext(input) {
|
|
|
3401
3622
|
};
|
|
3402
3623
|
if (input.session) {
|
|
3403
3624
|
try {
|
|
3404
|
-
const core = await import("./dist-
|
|
3625
|
+
const core = await import("./dist-2B363XUH.js");
|
|
3405
3626
|
core.updateSessionIndex(
|
|
3406
3627
|
projectPath,
|
|
3407
3628
|
input.session,
|
|
@@ -3471,7 +3692,7 @@ async function handleAssessProject(input) {
|
|
|
3471
3692
|
let validateResult = null;
|
|
3472
3693
|
if (checksToRun.has("validate")) {
|
|
3473
3694
|
try {
|
|
3474
|
-
const { handleValidateProject: handleValidateProject2 } = await import("./validate-
|
|
3695
|
+
const { handleValidateProject: handleValidateProject2 } = await import("./validate-GCHZJIL7.js");
|
|
3475
3696
|
const result = await handleValidateProject2({ path: projectPath });
|
|
3476
3697
|
const first = result.content[0];
|
|
3477
3698
|
const parsed = first ? JSON.parse(first.text) : {};
|
|
@@ -3496,7 +3717,7 @@ async function handleAssessProject(input) {
|
|
|
3496
3717
|
parallelChecks.push(
|
|
3497
3718
|
(async () => {
|
|
3498
3719
|
try {
|
|
3499
|
-
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-
|
|
3720
|
+
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-2R5Z4ZAF.js");
|
|
3500
3721
|
const result = await handleCheckDependencies2({ path: projectPath });
|
|
3501
3722
|
const first = result.content[0];
|
|
3502
3723
|
const parsed = first ? JSON.parse(first.text) : {};
|
|
@@ -3523,7 +3744,7 @@ async function handleAssessProject(input) {
|
|
|
3523
3744
|
parallelChecks.push(
|
|
3524
3745
|
(async () => {
|
|
3525
3746
|
try {
|
|
3526
|
-
const { handleCheckDocs: handleCheckDocs2 } = await import("./docs-
|
|
3747
|
+
const { handleCheckDocs: handleCheckDocs2 } = await import("./docs-FZOPM4GK.js");
|
|
3527
3748
|
const result = await handleCheckDocs2({ path: projectPath, scope: "coverage" });
|
|
3528
3749
|
const first = result.content[0];
|
|
3529
3750
|
const parsed = first ? JSON.parse(first.text) : {};
|
|
@@ -3550,7 +3771,7 @@ async function handleAssessProject(input) {
|
|
|
3550
3771
|
parallelChecks.push(
|
|
3551
3772
|
(async () => {
|
|
3552
3773
|
try {
|
|
3553
|
-
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-
|
|
3774
|
+
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-LVHJMFGH.js");
|
|
3554
3775
|
const result = await handleDetectEntropy2({ path: projectPath, type: "all" });
|
|
3555
3776
|
const first = result.content[0];
|
|
3556
3777
|
const parsed = first ? JSON.parse(first.text) : {};
|
|
@@ -3577,7 +3798,7 @@ async function handleAssessProject(input) {
|
|
|
3577
3798
|
parallelChecks.push(
|
|
3578
3799
|
(async () => {
|
|
3579
3800
|
try {
|
|
3580
|
-
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-
|
|
3801
|
+
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-FWQZF2IZ.js");
|
|
3581
3802
|
const result = await handleRunSecurityScan2({ path: projectPath });
|
|
3582
3803
|
const first = result.content[0];
|
|
3583
3804
|
const parsed = first ? JSON.parse(first.text) : {};
|
|
@@ -3609,7 +3830,7 @@ async function handleAssessProject(input) {
|
|
|
3609
3830
|
parallelChecks.push(
|
|
3610
3831
|
(async () => {
|
|
3611
3832
|
try {
|
|
3612
|
-
const { handleCheckPerformance: handleCheckPerformance2 } = await import("./performance-
|
|
3833
|
+
const { handleCheckPerformance: handleCheckPerformance2 } = await import("./performance-ZTVSUANN.js");
|
|
3613
3834
|
const result = await handleCheckPerformance2({ path: projectPath });
|
|
3614
3835
|
const first = result.content[0];
|
|
3615
3836
|
const parsed = first ? JSON.parse(first.text) : {};
|
|
@@ -3784,7 +4005,7 @@ async function handleReviewChanges(input) {
|
|
|
3784
4005
|
}
|
|
3785
4006
|
try {
|
|
3786
4007
|
if (effectiveDepth === "quick") {
|
|
3787
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-
|
|
4008
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-IHLVLMRD.js");
|
|
3788
4009
|
const result2 = await handleAnalyzeDiff2({ diff, path: projectPath });
|
|
3789
4010
|
const firstContent = result2.content[0];
|
|
3790
4011
|
if (!firstContent) throw new Error("Empty analyze_diff response");
|
|
@@ -3806,7 +4027,7 @@ async function handleReviewChanges(input) {
|
|
|
3806
4027
|
};
|
|
3807
4028
|
}
|
|
3808
4029
|
if (effectiveDepth === "standard") {
|
|
3809
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-
|
|
4030
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-IHLVLMRD.js");
|
|
3810
4031
|
const [diffResult, reviewResult] = await Promise.all([
|
|
3811
4032
|
handleAnalyzeDiff2({ diff, path: projectPath }),
|
|
3812
4033
|
handleCreateSelfReview2({ path: projectPath, diff })
|
|
@@ -3837,7 +4058,7 @@ async function handleReviewChanges(input) {
|
|
|
3837
4058
|
]
|
|
3838
4059
|
};
|
|
3839
4060
|
}
|
|
3840
|
-
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-
|
|
4061
|
+
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-76JHKGSV.js");
|
|
3841
4062
|
const result = await handleRunCodeReview2({ path: projectPath, diff });
|
|
3842
4063
|
const deepContent = result.content[0];
|
|
3843
4064
|
if (!deepContent) throw new Error("Empty code review response");
|
|
@@ -3914,7 +4135,7 @@ async function handleCheckTaskIndependence(input) {
|
|
|
3914
4135
|
try {
|
|
3915
4136
|
const projectPath = sanitizePath(input.path);
|
|
3916
4137
|
const store = await loadGraphStore(projectPath);
|
|
3917
|
-
const { TaskIndependenceAnalyzer } = await import("./dist-
|
|
4138
|
+
const { TaskIndependenceAnalyzer } = await import("./dist-HXHWB7SV.js");
|
|
3918
4139
|
const analyzer = new TaskIndependenceAnalyzer(store ?? void 0);
|
|
3919
4140
|
const result = analyzer.analyze({
|
|
3920
4141
|
tasks: input.tasks,
|
|
@@ -4002,7 +4223,7 @@ async function handlePredictConflicts(input) {
|
|
|
4002
4223
|
try {
|
|
4003
4224
|
const projectPath = sanitizePath(input.path);
|
|
4004
4225
|
const store = await loadGraphStore(projectPath);
|
|
4005
|
-
const { ConflictPredictor } = await import("./dist-
|
|
4226
|
+
const { ConflictPredictor } = await import("./dist-HXHWB7SV.js");
|
|
4006
4227
|
const predictor = new ConflictPredictor(store ?? void 0);
|
|
4007
4228
|
const result = predictor.predict({
|
|
4008
4229
|
tasks: input.tasks,
|
|
@@ -4108,7 +4329,7 @@ async function handleDetectStaleConstraints(input) {
|
|
|
4108
4329
|
isError: true
|
|
4109
4330
|
};
|
|
4110
4331
|
}
|
|
4111
|
-
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-
|
|
4332
|
+
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-GJZ4FN4Y.js");
|
|
4112
4333
|
const store = await loadGraphStore2(projectPath);
|
|
4113
4334
|
if (!store) {
|
|
4114
4335
|
return {
|
|
@@ -4129,7 +4350,7 @@ async function handleDetectStaleConstraints(input) {
|
|
|
4129
4350
|
]
|
|
4130
4351
|
};
|
|
4131
4352
|
}
|
|
4132
|
-
const { detectStaleConstraints } = await import("./dist-
|
|
4353
|
+
const { detectStaleConstraints } = await import("./dist-2B363XUH.js");
|
|
4133
4354
|
const result = detectStaleConstraints(
|
|
4134
4355
|
store,
|
|
4135
4356
|
windowDays,
|
|
@@ -4156,6 +4377,76 @@ async function handleDetectStaleConstraints(input) {
|
|
|
4156
4377
|
}
|
|
4157
4378
|
}
|
|
4158
4379
|
|
|
4380
|
+
// src/mcp/tools/search-skills.ts
|
|
4381
|
+
var searchSkillsDefinition = {
|
|
4382
|
+
name: "search_skills",
|
|
4383
|
+
description: "Search the skill catalog for domain-specific skills. Returns ranked results based on keyword and stack-signal matching. Use this to discover catalog skills that are not loaded as slash commands.",
|
|
4384
|
+
inputSchema: {
|
|
4385
|
+
type: "object",
|
|
4386
|
+
properties: {
|
|
4387
|
+
query: {
|
|
4388
|
+
type: "string",
|
|
4389
|
+
description: "Natural language or keyword query to search for skills"
|
|
4390
|
+
},
|
|
4391
|
+
path: {
|
|
4392
|
+
type: "string",
|
|
4393
|
+
description: "Project root path (defaults to cwd)"
|
|
4394
|
+
},
|
|
4395
|
+
platform: {
|
|
4396
|
+
type: "string",
|
|
4397
|
+
enum: ["claude-code", "gemini-cli"],
|
|
4398
|
+
description: "Target platform (defaults to claude-code)"
|
|
4399
|
+
}
|
|
4400
|
+
},
|
|
4401
|
+
required: ["query"]
|
|
4402
|
+
}
|
|
4403
|
+
};
|
|
4404
|
+
async function handleSearchSkills(input) {
|
|
4405
|
+
const query = input.query;
|
|
4406
|
+
const projectRoot = input.path || process.cwd();
|
|
4407
|
+
const platform = input.platform || "claude-code";
|
|
4408
|
+
const configResult = resolveConfig();
|
|
4409
|
+
const tierOverrides = configResult.ok ? configResult.value.skills?.tierOverrides : void 0;
|
|
4410
|
+
const index = loadOrRebuildIndex(platform, projectRoot, tierOverrides);
|
|
4411
|
+
const profile = loadOrGenerateProfile(projectRoot);
|
|
4412
|
+
const queryTerms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 2);
|
|
4413
|
+
const results = [];
|
|
4414
|
+
for (const [name, entry] of Object.entries(index.skills)) {
|
|
4415
|
+
const matchedKeywords = entry.keywords.filter(
|
|
4416
|
+
(kw) => queryTerms.some(
|
|
4417
|
+
(term) => kw.toLowerCase().includes(term.toLowerCase()) || term.toLowerCase().includes(kw.toLowerCase())
|
|
4418
|
+
)
|
|
4419
|
+
);
|
|
4420
|
+
const keywordScore = queryTerms.length > 0 ? matchedKeywords.length / queryTerms.length : 0;
|
|
4421
|
+
let stackScore = 0;
|
|
4422
|
+
if (entry.stackSignals.length > 0) {
|
|
4423
|
+
const matchedSignals = entry.stackSignals.filter((signal) => profile.signals[signal]);
|
|
4424
|
+
stackScore = matchedSignals.length / entry.stackSignals.length;
|
|
4425
|
+
}
|
|
4426
|
+
const score = 0.6 * keywordScore + 0.4 * stackScore;
|
|
4427
|
+
if (score > 0 || queryTerms.length === 0) {
|
|
4428
|
+
results.push({
|
|
4429
|
+
name,
|
|
4430
|
+
description: entry.description,
|
|
4431
|
+
keywords: entry.keywords,
|
|
4432
|
+
phases: entry.phases,
|
|
4433
|
+
score: Math.round(score * 100) / 100,
|
|
4434
|
+
source: entry.source
|
|
4435
|
+
});
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
results.sort((a, b) => b.score - a.score);
|
|
4439
|
+
const top5 = results.slice(0, 5);
|
|
4440
|
+
return {
|
|
4441
|
+
content: [
|
|
4442
|
+
{
|
|
4443
|
+
type: "text",
|
|
4444
|
+
text: JSON.stringify({ results: top5 }, null, 2)
|
|
4445
|
+
}
|
|
4446
|
+
]
|
|
4447
|
+
};
|
|
4448
|
+
}
|
|
4449
|
+
|
|
4159
4450
|
// src/mcp/server.ts
|
|
4160
4451
|
var TOOL_DEFINITIONS = [
|
|
4161
4452
|
validateToolDefinition,
|
|
@@ -4202,7 +4493,8 @@ var TOOL_DEFINITIONS = [
|
|
|
4202
4493
|
askGraphDefinition,
|
|
4203
4494
|
checkTaskIndependenceDefinition,
|
|
4204
4495
|
predictConflictsDefinition,
|
|
4205
|
-
detectStaleConstraintsDefinition
|
|
4496
|
+
detectStaleConstraintsDefinition,
|
|
4497
|
+
searchSkillsDefinition
|
|
4206
4498
|
];
|
|
4207
4499
|
var TOOL_HANDLERS = {
|
|
4208
4500
|
validate_project: handleValidateProject,
|
|
@@ -4249,7 +4541,8 @@ var TOOL_HANDLERS = {
|
|
|
4249
4541
|
ask_graph: handleAskGraph,
|
|
4250
4542
|
check_task_independence: handleCheckTaskIndependence,
|
|
4251
4543
|
predict_conflicts: handlePredictConflicts,
|
|
4252
|
-
detect_stale_constraints: handleDetectStaleConstraints
|
|
4544
|
+
detect_stale_constraints: handleDetectStaleConstraints,
|
|
4545
|
+
search_skills: handleSearchSkills
|
|
4253
4546
|
};
|
|
4254
4547
|
var RESOURCE_DEFINITIONS = [
|
|
4255
4548
|
{
|
|
@@ -4340,7 +4633,7 @@ function createHarnessServer(projectRoot) {
|
|
|
4340
4633
|
shouldRunCheck,
|
|
4341
4634
|
readCheckState,
|
|
4342
4635
|
spawnBackgroundCheck
|
|
4343
|
-
} = await import("./dist-
|
|
4636
|
+
} = await import("./dist-2B363XUH.js");
|
|
4344
4637
|
const { CLI_VERSION: version } = await import("./version-KFFPOQAX.js");
|
|
4345
4638
|
let CLI_VERSION = version;
|
|
4346
4639
|
let configInterval;
|