@harness-engineering/cli 1.26.1 → 1.27.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/cleanup-dead-code/SKILL.md +3 -1
- package/dist/agents/skills/claude-code/detect-doc-drift/SKILL.md +3 -1
- package/dist/agents/skills/claude-code/harness-architecture-advisor/SKILL.md +4 -0
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +55 -24
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +16 -5
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +21 -6
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-debugging/SKILL.md +13 -1
- package/dist/agents/skills/claude-code/harness-dependency-health/SKILL.md +4 -0
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +16 -6
- package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-integration/SKILL.md +560 -0
- package/dist/agents/skills/claude-code/harness-integration/skill.yaml +65 -0
- package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +4 -0
- package/dist/agents/skills/claude-code/harness-perf/SKILL.md +9 -7
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +77 -10
- package/dist/agents/skills/claude-code/harness-refactoring/SKILL.md +13 -4
- package/dist/agents/skills/claude-code/harness-security-scan/SKILL.md +3 -1
- package/dist/agents/skills/claude-code/harness-soundness-review/SKILL.md +4 -0
- package/dist/agents/skills/claude-code/harness-tdd/SKILL.md +5 -2
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +4 -0
- package/dist/agents/skills/codex/cleanup-dead-code/SKILL.md +3 -1
- package/dist/agents/skills/codex/detect-doc-drift/SKILL.md +3 -1
- package/dist/agents/skills/codex/harness-architecture-advisor/SKILL.md +4 -0
- package/dist/agents/skills/codex/harness-autopilot/SKILL.md +55 -24
- package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +16 -5
- package/dist/agents/skills/codex/harness-code-review/SKILL.md +21 -6
- package/dist/agents/skills/codex/harness-codebase-cleanup/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-debugging/SKILL.md +13 -1
- package/dist/agents/skills/codex/harness-dependency-health/SKILL.md +4 -0
- package/dist/agents/skills/codex/harness-execution/SKILL.md +16 -6
- package/dist/agents/skills/codex/harness-impact-analysis/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-integration/SKILL.md +560 -0
- package/dist/agents/skills/codex/harness-integration/skill.yaml +65 -0
- package/dist/agents/skills/codex/harness-integrity/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-onboarding/SKILL.md +4 -0
- package/dist/agents/skills/codex/harness-perf/SKILL.md +9 -7
- package/dist/agents/skills/codex/harness-planning/SKILL.md +77 -10
- package/dist/agents/skills/codex/harness-refactoring/SKILL.md +13 -4
- package/dist/agents/skills/codex/harness-security-scan/SKILL.md +3 -1
- package/dist/agents/skills/codex/harness-soundness-review/SKILL.md +4 -0
- package/dist/agents/skills/codex/harness-tdd/SKILL.md +5 -2
- package/dist/agents/skills/codex/harness-verification/SKILL.md +4 -0
- package/dist/agents/skills/cursor/cleanup-dead-code/SKILL.md +3 -1
- package/dist/agents/skills/cursor/detect-doc-drift/SKILL.md +3 -1
- package/dist/agents/skills/cursor/harness-architecture-advisor/SKILL.md +4 -0
- package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +55 -24
- package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +16 -5
- package/dist/agents/skills/cursor/harness-code-review/SKILL.md +21 -6
- package/dist/agents/skills/cursor/harness-codebase-cleanup/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-debugging/SKILL.md +13 -1
- package/dist/agents/skills/cursor/harness-dependency-health/SKILL.md +4 -0
- package/dist/agents/skills/cursor/harness-execution/SKILL.md +16 -6
- package/dist/agents/skills/cursor/harness-impact-analysis/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-integration/SKILL.md +560 -0
- package/dist/agents/skills/cursor/harness-integration/skill.yaml +65 -0
- package/dist/agents/skills/cursor/harness-integrity/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-onboarding/SKILL.md +4 -0
- package/dist/agents/skills/cursor/harness-perf/SKILL.md +9 -7
- package/dist/agents/skills/cursor/harness-planning/SKILL.md +77 -10
- package/dist/agents/skills/cursor/harness-refactoring/SKILL.md +13 -4
- package/dist/agents/skills/cursor/harness-security-scan/SKILL.md +3 -1
- package/dist/agents/skills/cursor/harness-soundness-review/SKILL.md +4 -0
- package/dist/agents/skills/cursor/harness-tdd/SKILL.md +5 -2
- package/dist/agents/skills/cursor/harness-verification/SKILL.md +4 -0
- package/dist/agents/skills/gemini-cli/cleanup-dead-code/SKILL.md +3 -1
- package/dist/agents/skills/gemini-cli/detect-doc-drift/SKILL.md +3 -1
- package/dist/agents/skills/gemini-cli/harness-architecture-advisor/SKILL.md +4 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +55 -24
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +16 -5
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +21 -6
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-debugging/SKILL.md +13 -1
- package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +4 -0
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +16 -6
- package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-integration/SKILL.md +560 -0
- package/dist/agents/skills/gemini-cli/harness-integration/skill.yaml +65 -0
- package/dist/agents/skills/gemini-cli/harness-integrity/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/SKILL.md +4 -0
- package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +9 -7
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +77 -10
- package/dist/agents/skills/gemini-cli/harness-refactoring/SKILL.md +13 -4
- package/dist/agents/skills/gemini-cli/harness-security-scan/SKILL.md +3 -1
- package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +4 -0
- package/dist/agents/skills/gemini-cli/harness-tdd/SKILL.md +5 -2
- package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +4 -0
- package/dist/{agents-md-VI3HLR7E.js → agents-md-2RN666DE.js} +3 -3
- package/dist/{architecture-ZDDKEVID.js → architecture-ZR33YKJB.js} +4 -4
- package/dist/{assess-project-Y6W7YDUA.js → assess-project-LLWWEQEV.js} +1 -1
- package/dist/bin/harness-mcp.js +17 -16
- package/dist/bin/harness.js +27 -26
- package/dist/{business-knowledge-6RHYJOB3.js → business-knowledge-EISPR7FU.js} +1 -1
- package/dist/{check-phase-gate-CXR3VM22.js → check-phase-gate-ZVG56NT2.js} +4 -4
- package/dist/chunk-27AJKSQY.js +107 -0
- package/dist/{chunk-DBIX3X4H.js → chunk-2FOLD76X.js} +2 -2
- package/dist/{chunk-3AMQYWGT.js → chunk-3AJW7VQ3.js} +2 -2
- package/dist/{chunk-FUND5WJR.js → chunk-3XMOWLK3.js} +2 -2
- package/dist/{chunk-OLW7BJ5N.js → chunk-776JFSPK.js} +1 -1
- package/dist/{chunk-VKS3F46M.js → chunk-A4ETL34H.js} +7 -2
- package/dist/{chunk-JV4Y2U5F.js → chunk-BO4AJZRE.js} +1 -1
- package/dist/{chunk-WZ7UHPT3.js → chunk-BZZNYHRY.js} +9 -9
- package/dist/{chunk-ZN6ROTYP.js → chunk-C7RPQWBG.js} +1 -1
- package/dist/{chunk-RAVD7QLY.js → chunk-CJYNZMOP.js} +8 -8
- package/dist/{chunk-PNNFCVW4.js → chunk-EGRQHLDM.js} +5 -5
- package/dist/{chunk-2BPPS6YQ.js → chunk-EHTUWULH.js} +458 -363
- package/dist/{chunk-N6B6RKQQ.js → chunk-EICASBYP.js} +1 -1
- package/dist/{chunk-K56DTX7G.js → chunk-F3Y64VNF.js} +6 -6
- package/dist/{chunk-ORNEK65Y.js → chunk-FUS4OOGC.js} +1 -1
- package/dist/{chunk-2FPUPRCY.js → chunk-GAIOIINV.js} +594 -127
- package/dist/{chunk-YC4EYIER.js → chunk-IBTHD2UA.js} +132 -77
- package/dist/{chunk-RC5ZY3EV.js → chunk-IOW3MW2K.js} +2 -2
- package/dist/{chunk-B66LRB5M.js → chunk-L3Y7L4EG.js} +1 -1
- package/dist/{chunk-BK4DJIIY.js → chunk-MGPVA2EM.js} +27 -4
- package/dist/{chunk-NY7DTZ6K.js → chunk-Q5DKIL46.js} +3 -3
- package/dist/{chunk-TY2ESLVL.js → chunk-SDDQPMZK.js} +1 -1
- package/dist/{chunk-7GY6WNEI.js → chunk-SDPHFDQS.js} +1 -1
- package/dist/{chunk-56A6OXVA.js → chunk-T7UZOJF4.js} +9 -9
- package/dist/{chunk-AMRC4FU2.js → chunk-VCC47EXU.js} +109 -57
- package/dist/{chunk-Q3ZLVMQM.js → chunk-XKU37HGH.js} +10 -1
- package/dist/{chunk-TSVYBDDE.js → chunk-YZH4I4JO.js} +1 -1
- package/dist/{ci-workflow-EW37KVPS.js → ci-workflow-JFOL4YWW.js} +3 -3
- package/dist/{dist-NCNAXUFD.js → dist-BZS2XRLG.js} +5 -1
- package/dist/{dist-CJDGASPP.js → dist-CPKL5Y2R.js} +2 -2
- package/dist/{docs-4XI2FQW2.js → docs-FUTRJQHA.js} +4 -4
- package/dist/{engine-4L4CDTHU.js → engine-FB3HCNVT.js} +3 -3
- package/dist/{entropy-PBYSIQYS.js → entropy-FIEE4YDA.js} +3 -3
- package/dist/{feedback-OTIFW5MK.js → feedback-7EC4T6XG.js} +1 -1
- package/dist/{generate-agent-definitions-CZGUXIIN.js → generate-agent-definitions-FOSFADNR.js} +4 -4
- package/dist/{graph-loader-RDXSEBD7.js → graph-loader-QEI7SYOQ.js} +1 -1
- package/dist/hooks/adoption-tracker.js +36 -8
- package/dist/hooks/sentinel-pre.js +3 -2
- package/dist/hooks/telemetry-reporter.js +34 -15
- package/dist/index-builder-3AOQ3ZII.js +13 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +29 -28
- package/dist/{loader-UZOXCWFC.js → loader-HXUOBTYA.js} +3 -3
- package/dist/{mcp-GWVVV6LH.js → mcp-NUG4BMKJ.js} +17 -16
- package/dist/{performance-5UQPP3XX.js → performance-TYXBCTR7.js} +4 -4
- package/dist/{review-pipeline-65V4EO6O.js → review-pipeline-B4WPU6BQ.js} +3 -3
- package/dist/{runtime-PXX7HNB3.js → runtime-HQQNOARD.js} +3 -3
- package/dist/{scan-WM7XDUF7.js → scan-M4EGDAQ2.js} +1 -1
- package/dist/{security-CAYDRZIZ.js → security-25VFLIAO.js} +1 -1
- package/dist/templates/orchestrator/harness.orchestrator.md +18 -8
- package/dist/{validate-CWGXR7QM.js → validate-EAVGKZQB.js} +4 -4
- package/dist/{validate-cross-check-BKCNLZYG.js → validate-cross-check-SPL3H4O5.js} +3 -3
- package/package.json +13 -5
- package/dist/hooks/profiles.ts +0 -48
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleRunCodeReview,
|
|
3
|
+
runCodeReviewDefinition,
|
|
4
|
+
sortFindingsBySeverity
|
|
5
|
+
} from "./chunk-2FOLD76X.js";
|
|
1
6
|
import {
|
|
2
7
|
assessProjectDefinition,
|
|
3
8
|
handleAssessProject
|
|
4
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-F3Y64VNF.js";
|
|
5
10
|
import {
|
|
6
11
|
getBusinessKnowledgeResource
|
|
7
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IOW3MW2K.js";
|
|
8
13
|
import {
|
|
9
14
|
analyzeDiffDefinition,
|
|
10
15
|
createSelfReviewDefinition,
|
|
@@ -12,37 +17,35 @@ import {
|
|
|
12
17
|
handleCreateSelfReview,
|
|
13
18
|
handleRequestPeerReview,
|
|
14
19
|
requestPeerReviewDefinition
|
|
15
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-BZZNYHRY.js";
|
|
16
21
|
import {
|
|
17
22
|
getSecurityTrendsDefinition,
|
|
18
23
|
handleGetSecurityTrends,
|
|
19
24
|
handleRunSecurityScan,
|
|
20
25
|
runSecurityScanDefinition
|
|
21
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-3AJW7VQ3.js";
|
|
22
27
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
sortFindingsBySeverity
|
|
26
|
-
} from "./chunk-DBIX3X4H.js";
|
|
28
|
+
loadGraphStore
|
|
29
|
+
} from "./chunk-776JFSPK.js";
|
|
27
30
|
import {
|
|
28
31
|
handleValidateProject,
|
|
29
32
|
validateToolDefinition
|
|
30
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-Q5DKIL46.js";
|
|
31
34
|
import {
|
|
32
35
|
checkDependenciesDefinition,
|
|
33
36
|
handleCheckDependencies
|
|
34
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-MGPVA2EM.js";
|
|
35
38
|
import {
|
|
36
39
|
resolveProjectConfig
|
|
37
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-YZH4I4JO.js";
|
|
38
41
|
import {
|
|
39
42
|
checkDocsDefinition,
|
|
40
43
|
handleCheckDocs
|
|
41
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-T7UZOJF4.js";
|
|
42
45
|
import {
|
|
43
46
|
detectEntropyDefinition,
|
|
44
47
|
handleDetectEntropy
|
|
45
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-EGRQHLDM.js";
|
|
46
49
|
import {
|
|
47
50
|
checkPerformanceDefinition,
|
|
48
51
|
getCriticalPathsDefinition,
|
|
@@ -52,16 +55,19 @@ import {
|
|
|
52
55
|
handleGetPerfBaselines,
|
|
53
56
|
handleUpdatePerfBaselines,
|
|
54
57
|
updatePerfBaselinesDefinition
|
|
55
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-CJYNZMOP.js";
|
|
56
59
|
import {
|
|
57
60
|
resultToMcpResponse
|
|
58
61
|
} from "./chunk-EPUKTTJZ.js";
|
|
59
62
|
import {
|
|
60
63
|
sanitizePath
|
|
61
64
|
} from "./chunk-W6Y7ZW3Y.js";
|
|
65
|
+
import {
|
|
66
|
+
loadOrRebuildIndex
|
|
67
|
+
} from "./chunk-27AJKSQY.js";
|
|
62
68
|
import {
|
|
63
69
|
resolveConfig
|
|
64
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-A4ETL34H.js";
|
|
65
71
|
import {
|
|
66
72
|
GENERATED_HEADER_CLAUDE,
|
|
67
73
|
GENERATED_HEADER_CODEX,
|
|
@@ -72,7 +78,6 @@ import {
|
|
|
72
78
|
computeSyncPlan
|
|
73
79
|
} from "./chunk-3ISINLYT.js";
|
|
74
80
|
import {
|
|
75
|
-
resolveAllSkillsDirs,
|
|
76
81
|
resolveCommunitySkillsDir,
|
|
77
82
|
resolveGlobalCommunitySkillsDir,
|
|
78
83
|
resolveGlobalSkillsDir,
|
|
@@ -81,9 +86,6 @@ import {
|
|
|
81
86
|
resolveSkillsDir,
|
|
82
87
|
resolveTemplatesDir
|
|
83
88
|
} from "./chunk-6B6UN6SG.js";
|
|
84
|
-
import {
|
|
85
|
-
loadGraphStore
|
|
86
|
-
} from "./chunk-OLW7BJ5N.js";
|
|
87
89
|
import {
|
|
88
90
|
CompactionPipeline,
|
|
89
91
|
DEFAULT_TOKEN_BUDGET,
|
|
@@ -101,7 +103,7 @@ import {
|
|
|
101
103
|
scanForInjection,
|
|
102
104
|
serializeEnvelope,
|
|
103
105
|
writeTaint
|
|
104
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-IBTHD2UA.js";
|
|
105
107
|
import {
|
|
106
108
|
Err,
|
|
107
109
|
Ok
|
|
@@ -704,7 +706,7 @@ ${skippedMsg}`
|
|
|
704
706
|
async function handleInitProject(input) {
|
|
705
707
|
const i = input;
|
|
706
708
|
try {
|
|
707
|
-
const { TemplateEngine } = await import("./engine-
|
|
709
|
+
const { TemplateEngine } = await import("./engine-FB3HCNVT.js");
|
|
708
710
|
const engine = new TemplateEngine(resolveTemplatesDir());
|
|
709
711
|
const safePath = sanitizePath(i.path);
|
|
710
712
|
const detected = tryDetectFramework(engine, safePath, i);
|
|
@@ -726,7 +728,7 @@ var listPersonasDefinition = {
|
|
|
726
728
|
inputSchema: { type: "object", properties: {} }
|
|
727
729
|
};
|
|
728
730
|
async function handleListPersonas() {
|
|
729
|
-
const { listPersonas } = await import("./loader-
|
|
731
|
+
const { listPersonas } = await import("./loader-HXUOBTYA.js");
|
|
730
732
|
const result = listPersonas(resolvePersonasDir());
|
|
731
733
|
return resultToMcpResponse(result);
|
|
732
734
|
}
|
|
@@ -750,10 +752,10 @@ async function handleGeneratePersonaArtifacts(input) {
|
|
|
750
752
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.name)) {
|
|
751
753
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.name}`)));
|
|
752
754
|
}
|
|
753
|
-
const { loadPersona } = await import("./loader-
|
|
754
|
-
const { generateRuntime } = await import("./runtime-
|
|
755
|
-
const { generateAgentsMd } = await import("./agents-md-
|
|
756
|
-
const { generateCIWorkflow } = await import("./ci-workflow-
|
|
755
|
+
const { loadPersona } = await import("./loader-HXUOBTYA.js");
|
|
756
|
+
const { generateRuntime } = await import("./runtime-HQQNOARD.js");
|
|
757
|
+
const { generateAgentsMd } = await import("./agents-md-2RN666DE.js");
|
|
758
|
+
const { generateCIWorkflow } = await import("./ci-workflow-JFOL4YWW.js");
|
|
757
759
|
const personasDir = resolvePersonasDir();
|
|
758
760
|
const filePath = path3.join(personasDir, `${input.name}.yaml`);
|
|
759
761
|
if (!filePath.startsWith(personasDir)) {
|
|
@@ -808,7 +810,7 @@ async function handleRunPersona(input) {
|
|
|
808
810
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.persona)) {
|
|
809
811
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.persona}`)));
|
|
810
812
|
}
|
|
811
|
-
const { loadPersona } = await import("./loader-
|
|
813
|
+
const { loadPersona } = await import("./loader-HXUOBTYA.js");
|
|
812
814
|
const { runPersona } = await import("./runner-AAEF2TXY.js");
|
|
813
815
|
const { executeSkill } = await import("./skill-executor-MOCUIAYS.js");
|
|
814
816
|
const personasDir = resolvePersonasDir();
|
|
@@ -975,8 +977,8 @@ async function handleRunAgentTask(input) {
|
|
|
975
977
|
|
|
976
978
|
// src/mcp/tools/skill.ts
|
|
977
979
|
init_dist();
|
|
978
|
-
import * as
|
|
979
|
-
import * as
|
|
980
|
+
import * as fs4 from "fs";
|
|
981
|
+
import * as path5 from "path";
|
|
980
982
|
import { parse as parseYaml } from "yaml";
|
|
981
983
|
|
|
982
984
|
// src/skill/dispatcher.ts
|
|
@@ -1162,103 +1164,9 @@ function formatSuggestions(suggestions) {
|
|
|
1162
1164
|
].join("\n");
|
|
1163
1165
|
}
|
|
1164
1166
|
|
|
1165
|
-
// src/skill/
|
|
1167
|
+
// src/skill/stack-profile.ts
|
|
1166
1168
|
import fs3 from "fs";
|
|
1167
1169
|
import path4 from "path";
|
|
1168
|
-
import crypto from "crypto";
|
|
1169
|
-
import { parse } from "yaml";
|
|
1170
|
-
function computeSkillsDirHash(skillsDirs) {
|
|
1171
|
-
const hash = crypto.createHash("sha256");
|
|
1172
|
-
for (const dir of skillsDirs) {
|
|
1173
|
-
if (!fs3.existsSync(dir)) continue;
|
|
1174
|
-
for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
1175
|
-
if (!entry.isDirectory()) continue;
|
|
1176
|
-
const yamlPath = path4.join(dir, entry.name, "skill.yaml");
|
|
1177
|
-
if (!fs3.existsSync(yamlPath)) continue;
|
|
1178
|
-
const stat = fs3.statSync(yamlPath);
|
|
1179
|
-
hash.update(`${yamlPath}:${stat.mtimeMs}`);
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
return hash.digest("hex");
|
|
1183
|
-
}
|
|
1184
|
-
function parseSkillEntry(yamlPath, source, tierOverrides) {
|
|
1185
|
-
const raw = fs3.readFileSync(yamlPath, "utf-8");
|
|
1186
|
-
const parsed = parse(raw);
|
|
1187
|
-
const result = SkillMetadataSchema.safeParse(parsed);
|
|
1188
|
-
if (!result.success) return null;
|
|
1189
|
-
const meta = result.data;
|
|
1190
|
-
const effectiveTier = tierOverrides?.[meta.name] ?? meta.tier;
|
|
1191
|
-
if (meta.internal) return null;
|
|
1192
|
-
return {
|
|
1193
|
-
tier: effectiveTier ?? 3,
|
|
1194
|
-
type: meta.type,
|
|
1195
|
-
description: meta.description,
|
|
1196
|
-
keywords: meta.keywords ?? [],
|
|
1197
|
-
stackSignals: meta.stack_signals ?? [],
|
|
1198
|
-
cognitiveMode: meta.cognitive_mode,
|
|
1199
|
-
phases: (meta.phases ?? []).map((p) => p.name),
|
|
1200
|
-
paths: meta.paths ?? [],
|
|
1201
|
-
relatedSkills: meta.related_skills ?? [],
|
|
1202
|
-
source,
|
|
1203
|
-
addresses: meta.addresses ?? [],
|
|
1204
|
-
dependsOn: meta.depends_on ?? [],
|
|
1205
|
-
...meta.context_budget && {
|
|
1206
|
-
contextBudget: {
|
|
1207
|
-
maxTokens: meta.context_budget.max_tokens,
|
|
1208
|
-
priority: meta.context_budget.priority
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
};
|
|
1212
|
-
}
|
|
1213
|
-
function scanDirectory(dir, source, index, tierOverrides) {
|
|
1214
|
-
if (!fs3.existsSync(dir)) return;
|
|
1215
|
-
for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
1216
|
-
if (!entry.isDirectory()) continue;
|
|
1217
|
-
if (index.skills[entry.name]) continue;
|
|
1218
|
-
const yamlPath = path4.join(dir, entry.name, "skill.yaml");
|
|
1219
|
-
if (!fs3.existsSync(yamlPath)) continue;
|
|
1220
|
-
try {
|
|
1221
|
-
const parsed = parseSkillEntry(yamlPath, source, tierOverrides);
|
|
1222
|
-
if (parsed) index.skills[entry.name] = parsed;
|
|
1223
|
-
} catch {
|
|
1224
|
-
continue;
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
function buildIndex(platform, _projectRoot, tierOverrides) {
|
|
1229
|
-
const skillsDirs = resolveAllSkillsDirs(platform);
|
|
1230
|
-
const sourceMap = ["project", "community", "bundled"];
|
|
1231
|
-
const index = {
|
|
1232
|
-
version: 1,
|
|
1233
|
-
hash: computeSkillsDirHash(skillsDirs),
|
|
1234
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1235
|
-
skills: {}
|
|
1236
|
-
};
|
|
1237
|
-
for (let i = 0; i < skillsDirs.length; i++) {
|
|
1238
|
-
scanDirectory(skillsDirs[i], sourceMap[i] ?? "bundled", index, tierOverrides);
|
|
1239
|
-
}
|
|
1240
|
-
return index;
|
|
1241
|
-
}
|
|
1242
|
-
function loadOrRebuildIndex(platform, projectRoot, tierOverrides) {
|
|
1243
|
-
const indexPath = path4.join(projectRoot, ".harness", "skills-index.json");
|
|
1244
|
-
const skillsDirs = resolveAllSkillsDirs(platform);
|
|
1245
|
-
const currentHash = computeSkillsDirHash(skillsDirs);
|
|
1246
|
-
if (fs3.existsSync(indexPath)) {
|
|
1247
|
-
try {
|
|
1248
|
-
const existing = JSON.parse(fs3.readFileSync(indexPath, "utf-8"));
|
|
1249
|
-
if (existing.hash === currentHash) return existing;
|
|
1250
|
-
} catch {
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
const index = buildIndex(platform, projectRoot, tierOverrides);
|
|
1254
|
-
fs3.mkdirSync(path4.dirname(indexPath), { recursive: true });
|
|
1255
|
-
fs3.writeFileSync(indexPath, JSON.stringify(index, null, 2));
|
|
1256
|
-
return index;
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
// src/skill/stack-profile.ts
|
|
1260
|
-
import fs4 from "fs";
|
|
1261
|
-
import path5 from "path";
|
|
1262
1170
|
var SIGNAL_DOMAIN_MAP = {
|
|
1263
1171
|
"prisma/schema.prisma": ["database"],
|
|
1264
1172
|
"drizzle.config.ts": ["database"],
|
|
@@ -1317,8 +1225,8 @@ function generateStackProfile(projectRoot) {
|
|
|
1317
1225
|
const signals = {};
|
|
1318
1226
|
const domainSet = /* @__PURE__ */ new Set();
|
|
1319
1227
|
for (const [pattern, domains] of Object.entries(SIGNAL_DOMAIN_MAP)) {
|
|
1320
|
-
const fullPath =
|
|
1321
|
-
const exists =
|
|
1228
|
+
const fullPath = path4.join(projectRoot, pattern);
|
|
1229
|
+
const exists = fs3.existsSync(fullPath);
|
|
1322
1230
|
signals[pattern] = exists;
|
|
1323
1231
|
if (exists) {
|
|
1324
1232
|
for (const domain of domains) domainSet.add(domain);
|
|
@@ -1331,23 +1239,23 @@ function generateStackProfile(projectRoot) {
|
|
|
1331
1239
|
};
|
|
1332
1240
|
}
|
|
1333
1241
|
function loadOrGenerateProfile(projectRoot) {
|
|
1334
|
-
const profilePath =
|
|
1335
|
-
if (
|
|
1242
|
+
const profilePath = path4.join(projectRoot, ".harness", "stack-profile.json");
|
|
1243
|
+
if (fs3.existsSync(profilePath)) {
|
|
1336
1244
|
try {
|
|
1337
|
-
return JSON.parse(
|
|
1245
|
+
return JSON.parse(fs3.readFileSync(profilePath, "utf-8"));
|
|
1338
1246
|
} catch {
|
|
1339
1247
|
}
|
|
1340
1248
|
}
|
|
1341
1249
|
const profile = generateStackProfile(projectRoot);
|
|
1342
|
-
|
|
1343
|
-
|
|
1250
|
+
fs3.mkdirSync(path4.dirname(profilePath), { recursive: true });
|
|
1251
|
+
fs3.writeFileSync(profilePath, JSON.stringify(profile, null, 2));
|
|
1344
1252
|
return profile;
|
|
1345
1253
|
}
|
|
1346
1254
|
|
|
1347
1255
|
// src/mcp/tools/event-emitter.ts
|
|
1348
1256
|
async function emitSkillEvent(projectPath, event) {
|
|
1349
1257
|
try {
|
|
1350
|
-
const { emitEvent } = await import("./dist-
|
|
1258
|
+
const { emitEvent } = await import("./dist-CPKL5Y2R.js");
|
|
1351
1259
|
await emitEvent(projectPath, event);
|
|
1352
1260
|
} catch {
|
|
1353
1261
|
}
|
|
@@ -1382,18 +1290,18 @@ async function handleRunSkill(input) {
|
|
|
1382
1290
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.skill)) {
|
|
1383
1291
|
return resultToMcpResponse(Err(new Error(`Invalid skill name: ${input.skill}`)));
|
|
1384
1292
|
}
|
|
1385
|
-
const skillDir =
|
|
1293
|
+
const skillDir = path5.join(skillsDir, input.skill);
|
|
1386
1294
|
if (!skillDir.startsWith(skillsDir)) {
|
|
1387
1295
|
return resultToMcpResponse(Err(new Error(`Invalid skill path: ${input.skill}`)));
|
|
1388
1296
|
}
|
|
1389
|
-
if (!
|
|
1297
|
+
if (!fs4.existsSync(skillDir)) {
|
|
1390
1298
|
return resultToMcpResponse(Err(new Error(`Skill not found: ${input.skill}`)));
|
|
1391
1299
|
}
|
|
1392
|
-
const skillMdPath =
|
|
1393
|
-
if (!
|
|
1300
|
+
const skillMdPath = path5.join(skillDir, "SKILL.md");
|
|
1301
|
+
if (!fs4.existsSync(skillMdPath)) {
|
|
1394
1302
|
return resultToMcpResponse(Err(new Error(`SKILL.md not found for skill: ${input.skill}`)));
|
|
1395
1303
|
}
|
|
1396
|
-
let content =
|
|
1304
|
+
let content = fs4.readFileSync(skillMdPath, "utf-8");
|
|
1397
1305
|
const projectRoot = input.path ? sanitizePath(input.path) : process.cwd();
|
|
1398
1306
|
const configResult = resolveConfig();
|
|
1399
1307
|
const skillsConfig = configResult.ok ? configResult.value.skills : void 0;
|
|
@@ -1420,9 +1328,9 @@ async function handleRunSkill(input) {
|
|
|
1420
1328
|
}
|
|
1421
1329
|
if (input.path) {
|
|
1422
1330
|
const projectPath = sanitizePath(input.path);
|
|
1423
|
-
const stateFile =
|
|
1424
|
-
if (
|
|
1425
|
-
const stateContent =
|
|
1331
|
+
const stateFile = path5.join(projectPath, ".harness", "state.json");
|
|
1332
|
+
if (fs4.existsSync(stateFile)) {
|
|
1333
|
+
const stateContent = fs4.readFileSync(stateFile, "utf-8");
|
|
1426
1334
|
content += `
|
|
1427
1335
|
|
|
1428
1336
|
---
|
|
@@ -1433,10 +1341,10 @@ ${stateContent}
|
|
|
1433
1341
|
`;
|
|
1434
1342
|
}
|
|
1435
1343
|
}
|
|
1436
|
-
const skillYamlPath =
|
|
1437
|
-
if (
|
|
1344
|
+
const skillYamlPath = path5.join(skillDir, "skill.yaml");
|
|
1345
|
+
if (fs4.existsSync(skillYamlPath)) {
|
|
1438
1346
|
try {
|
|
1439
|
-
const rawYaml =
|
|
1347
|
+
const rawYaml = fs4.readFileSync(skillYamlPath, "utf-8");
|
|
1440
1348
|
const skillMeta = parseYaml(rawYaml);
|
|
1441
1349
|
if (skillMeta.type === "knowledge") {
|
|
1442
1350
|
const boundary = content.indexOf("\n## Details");
|
|
@@ -1519,22 +1427,22 @@ async function handleCreateSkill(input) {
|
|
|
1519
1427
|
}
|
|
1520
1428
|
|
|
1521
1429
|
// src/mcp/resources/skills.ts
|
|
1522
|
-
import * as
|
|
1523
|
-
import * as
|
|
1430
|
+
import * as fs5 from "fs";
|
|
1431
|
+
import * as path6 from "path";
|
|
1524
1432
|
import * as yaml from "yaml";
|
|
1525
1433
|
async function getSkillsResource(projectRoot) {
|
|
1526
|
-
const skillsDir =
|
|
1434
|
+
const skillsDir = path6.join(projectRoot, "agents", "skills", "claude-code");
|
|
1527
1435
|
const skills = [];
|
|
1528
|
-
if (!
|
|
1436
|
+
if (!fs5.existsSync(skillsDir)) {
|
|
1529
1437
|
return JSON.stringify(skills, null, 2);
|
|
1530
1438
|
}
|
|
1531
|
-
const entries =
|
|
1439
|
+
const entries = fs5.readdirSync(skillsDir, { withFileTypes: true });
|
|
1532
1440
|
for (const entry of entries) {
|
|
1533
1441
|
if (!entry.isDirectory()) continue;
|
|
1534
|
-
const skillYamlPath =
|
|
1535
|
-
if (!
|
|
1442
|
+
const skillYamlPath = path6.join(skillsDir, entry.name, "skill.yaml");
|
|
1443
|
+
if (!fs5.existsSync(skillYamlPath)) continue;
|
|
1536
1444
|
try {
|
|
1537
|
-
const content =
|
|
1445
|
+
const content = fs5.readFileSync(skillYamlPath, "utf-8");
|
|
1538
1446
|
const parsed = yaml.parse(content);
|
|
1539
1447
|
skills.push({
|
|
1540
1448
|
name: parsed.name,
|
|
@@ -1550,14 +1458,14 @@ async function getSkillsResource(projectRoot) {
|
|
|
1550
1458
|
}
|
|
1551
1459
|
|
|
1552
1460
|
// src/mcp/resources/rules.ts
|
|
1553
|
-
import * as
|
|
1554
|
-
import * as
|
|
1461
|
+
import * as fs6 from "fs";
|
|
1462
|
+
import * as path7 from "path";
|
|
1555
1463
|
async function getRulesResource(projectRoot) {
|
|
1556
1464
|
const rules = [];
|
|
1557
|
-
const configPath =
|
|
1558
|
-
if (
|
|
1465
|
+
const configPath = path7.join(projectRoot, "harness.config.json");
|
|
1466
|
+
if (fs6.existsSync(configPath)) {
|
|
1559
1467
|
try {
|
|
1560
|
-
const config = JSON.parse(
|
|
1468
|
+
const config = JSON.parse(fs6.readFileSync(configPath, "utf-8"));
|
|
1561
1469
|
if (config.layers) {
|
|
1562
1470
|
rules.push({ type: "layer-enforcement", config: config.layers });
|
|
1563
1471
|
}
|
|
@@ -1570,10 +1478,10 @@ async function getRulesResource(projectRoot) {
|
|
|
1570
1478
|
} catch {
|
|
1571
1479
|
}
|
|
1572
1480
|
}
|
|
1573
|
-
const linterPath =
|
|
1574
|
-
if (
|
|
1481
|
+
const linterPath = path7.join(projectRoot, ".harness", "linter.json");
|
|
1482
|
+
if (fs6.existsSync(linterPath)) {
|
|
1575
1483
|
try {
|
|
1576
|
-
const linterConfig = JSON.parse(
|
|
1484
|
+
const linterConfig = JSON.parse(fs6.readFileSync(linterPath, "utf-8"));
|
|
1577
1485
|
rules.push({ type: "linter", config: linterConfig });
|
|
1578
1486
|
} catch {
|
|
1579
1487
|
}
|
|
@@ -1582,28 +1490,28 @@ async function getRulesResource(projectRoot) {
|
|
|
1582
1490
|
}
|
|
1583
1491
|
|
|
1584
1492
|
// src/mcp/resources/project.ts
|
|
1585
|
-
import * as
|
|
1586
|
-
import * as
|
|
1493
|
+
import * as fs7 from "fs";
|
|
1494
|
+
import * as path8 from "path";
|
|
1587
1495
|
async function getProjectResource(projectRoot) {
|
|
1588
|
-
const agentsPath =
|
|
1589
|
-
if (
|
|
1590
|
-
return
|
|
1496
|
+
const agentsPath = path8.join(projectRoot, "AGENTS.md");
|
|
1497
|
+
if (fs7.existsSync(agentsPath)) {
|
|
1498
|
+
return fs7.readFileSync(agentsPath, "utf-8");
|
|
1591
1499
|
}
|
|
1592
1500
|
return "# No AGENTS.md found";
|
|
1593
1501
|
}
|
|
1594
1502
|
|
|
1595
1503
|
// src/mcp/resources/learnings.ts
|
|
1596
|
-
import * as
|
|
1597
|
-
import * as
|
|
1504
|
+
import * as fs8 from "fs";
|
|
1505
|
+
import * as path9 from "path";
|
|
1598
1506
|
async function getLearningsResource(projectRoot) {
|
|
1599
1507
|
const sections = [];
|
|
1600
|
-
const reviewPath =
|
|
1601
|
-
if (
|
|
1602
|
-
sections.push("## Review Learnings\n\n" +
|
|
1508
|
+
const reviewPath = path9.join(projectRoot, ".harness", "review-learnings.md");
|
|
1509
|
+
if (fs8.existsSync(reviewPath)) {
|
|
1510
|
+
sections.push("## Review Learnings\n\n" + fs8.readFileSync(reviewPath, "utf-8"));
|
|
1603
1511
|
}
|
|
1604
|
-
const antiPath =
|
|
1605
|
-
if (
|
|
1606
|
-
sections.push("## Anti-Pattern Log\n\n" +
|
|
1512
|
+
const antiPath = path9.join(projectRoot, ".harness", "anti-patterns.md");
|
|
1513
|
+
if (fs8.existsSync(antiPath)) {
|
|
1514
|
+
sections.push("## Anti-Pattern Log\n\n" + fs8.readFileSync(antiPath, "utf-8"));
|
|
1607
1515
|
}
|
|
1608
1516
|
return sections.length > 0 ? sections.join("\n\n---\n\n") : "No learnings files found.";
|
|
1609
1517
|
}
|
|
@@ -1613,14 +1521,14 @@ init_dist();
|
|
|
1613
1521
|
|
|
1614
1522
|
// src/mcp/tools/roadmap-auto-sync.ts
|
|
1615
1523
|
init_dist();
|
|
1616
|
-
import * as
|
|
1617
|
-
import * as
|
|
1524
|
+
import * as fs9 from "fs";
|
|
1525
|
+
import * as path10 from "path";
|
|
1618
1526
|
async function autoSyncRoadmap(projectPath) {
|
|
1619
1527
|
try {
|
|
1620
|
-
const roadmapFile =
|
|
1621
|
-
if (!
|
|
1622
|
-
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges } = await import("./dist-
|
|
1623
|
-
const raw =
|
|
1528
|
+
const roadmapFile = path10.join(projectPath, "docs", "roadmap.md");
|
|
1529
|
+
if (!fs9.existsSync(roadmapFile)) return;
|
|
1530
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges } = await import("./dist-CPKL5Y2R.js");
|
|
1531
|
+
const raw = fs9.readFileSync(roadmapFile, "utf-8");
|
|
1624
1532
|
const parseResult = parseRoadmap(raw);
|
|
1625
1533
|
if (!parseResult.ok) return;
|
|
1626
1534
|
const roadmap = parseResult.value;
|
|
@@ -1630,7 +1538,7 @@ async function autoSyncRoadmap(projectPath) {
|
|
|
1630
1538
|
return;
|
|
1631
1539
|
}
|
|
1632
1540
|
applySyncChanges(roadmap, syncResult.value);
|
|
1633
|
-
|
|
1541
|
+
fs9.writeFileSync(roadmapFile, serializeRoadmap(roadmap), "utf-8");
|
|
1634
1542
|
await triggerExternalSync(projectPath, roadmapFile);
|
|
1635
1543
|
} catch {
|
|
1636
1544
|
}
|
|
@@ -1639,8 +1547,8 @@ async function triggerExternalSync(projectPath, roadmapFile) {
|
|
|
1639
1547
|
try {
|
|
1640
1548
|
const trackerConfig = loadTrackerSyncConfig(projectPath);
|
|
1641
1549
|
if (!trackerConfig) return;
|
|
1642
|
-
const projectEnvPath =
|
|
1643
|
-
if (
|
|
1550
|
+
const projectEnvPath = path10.join(projectPath, ".env");
|
|
1551
|
+
if (fs9.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
|
|
1644
1552
|
const { config: loadDotenv } = await import("dotenv");
|
|
1645
1553
|
loadDotenv({ path: projectEnvPath });
|
|
1646
1554
|
}
|
|
@@ -1649,7 +1557,7 @@ async function triggerExternalSync(projectPath, roadmapFile) {
|
|
|
1649
1557
|
console.warn("[roadmap-sync] GITHUB_TOKEN not found \u2014 external sync skipped");
|
|
1650
1558
|
return;
|
|
1651
1559
|
}
|
|
1652
|
-
const { fullSync, GitHubIssuesSyncAdapter } = await import("./dist-
|
|
1560
|
+
const { fullSync, GitHubIssuesSyncAdapter } = await import("./dist-CPKL5Y2R.js");
|
|
1653
1561
|
const adapter = new GitHubIssuesSyncAdapter({
|
|
1654
1562
|
token,
|
|
1655
1563
|
config: trackerConfig
|
|
@@ -1746,12 +1654,12 @@ var manageStateDefinition = {
|
|
|
1746
1654
|
}
|
|
1747
1655
|
};
|
|
1748
1656
|
async function handleShow(projectPath, input) {
|
|
1749
|
-
const { loadState } = await import("./dist-
|
|
1657
|
+
const { loadState } = await import("./dist-CPKL5Y2R.js");
|
|
1750
1658
|
return resultToMcpResponse(await loadState(projectPath, input.stream, input.session));
|
|
1751
1659
|
}
|
|
1752
1660
|
async function handleLearn(projectPath, input) {
|
|
1753
1661
|
if (!input.learning) return mcpError("Error: learning is required for learn action");
|
|
1754
|
-
const { appendLearning } = await import("./dist-
|
|
1662
|
+
const { appendLearning } = await import("./dist-CPKL5Y2R.js");
|
|
1755
1663
|
const result = await appendLearning(
|
|
1756
1664
|
projectPath,
|
|
1757
1665
|
input.learning,
|
|
@@ -1766,7 +1674,7 @@ async function handleLearn(projectPath, input) {
|
|
|
1766
1674
|
async function handleFailure(projectPath, input) {
|
|
1767
1675
|
if (!input.description) return mcpError("Error: description is required for failure action");
|
|
1768
1676
|
if (!input.failureType) return mcpError("Error: failureType is required for failure action");
|
|
1769
|
-
const { appendFailure } = await import("./dist-
|
|
1677
|
+
const { appendFailure } = await import("./dist-CPKL5Y2R.js");
|
|
1770
1678
|
const result = await appendFailure(
|
|
1771
1679
|
projectPath,
|
|
1772
1680
|
input.description,
|
|
@@ -1785,19 +1693,19 @@ async function handleFailure(projectPath, input) {
|
|
|
1785
1693
|
return resultToMcpResponse(Ok({ recorded: true }));
|
|
1786
1694
|
}
|
|
1787
1695
|
async function handleArchive(projectPath, input) {
|
|
1788
|
-
const { archiveFailures } = await import("./dist-
|
|
1696
|
+
const { archiveFailures } = await import("./dist-CPKL5Y2R.js");
|
|
1789
1697
|
const result = await archiveFailures(projectPath, input.stream, input.session);
|
|
1790
1698
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1791
1699
|
return resultToMcpResponse(Ok({ archived: true }));
|
|
1792
1700
|
}
|
|
1793
1701
|
async function handleReset(projectPath, input) {
|
|
1794
|
-
const { saveState, DEFAULT_STATE } = await import("./dist-
|
|
1702
|
+
const { saveState, DEFAULT_STATE } = await import("./dist-CPKL5Y2R.js");
|
|
1795
1703
|
const result = await saveState(projectPath, { ...DEFAULT_STATE }, input.stream, input.session);
|
|
1796
1704
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1797
1705
|
return resultToMcpResponse(Ok({ reset: true }));
|
|
1798
1706
|
}
|
|
1799
1707
|
async function handleGate(projectPath, input) {
|
|
1800
|
-
const { runMechanicalGate } = await import("./dist-
|
|
1708
|
+
const { runMechanicalGate } = await import("./dist-CPKL5Y2R.js");
|
|
1801
1709
|
const result = await runMechanicalGate(projectPath);
|
|
1802
1710
|
if (result.ok) {
|
|
1803
1711
|
await emitSkillEvent(projectPath, {
|
|
@@ -1817,7 +1725,7 @@ async function handleGate(projectPath, input) {
|
|
|
1817
1725
|
}
|
|
1818
1726
|
async function handleSaveHandoff(projectPath, input) {
|
|
1819
1727
|
if (!input.handoff) return mcpError("Error: handoff is required for save-handoff action");
|
|
1820
|
-
const { saveHandoff } = await import("./dist-
|
|
1728
|
+
const { saveHandoff } = await import("./dist-CPKL5Y2R.js");
|
|
1821
1729
|
const result = await saveHandoff(
|
|
1822
1730
|
projectPath,
|
|
1823
1731
|
input.handoff,
|
|
@@ -1839,7 +1747,7 @@ async function handleSaveHandoff(projectPath, input) {
|
|
|
1839
1747
|
return resultToMcpResponse(Ok({ saved: true }));
|
|
1840
1748
|
}
|
|
1841
1749
|
async function handleLoadHandoff(projectPath, input) {
|
|
1842
|
-
const { loadHandoff } = await import("./dist-
|
|
1750
|
+
const { loadHandoff } = await import("./dist-CPKL5Y2R.js");
|
|
1843
1751
|
return resultToMcpResponse(await loadHandoff(projectPath, input.stream, input.session));
|
|
1844
1752
|
}
|
|
1845
1753
|
async function handleAppendEntry(projectPath, input) {
|
|
@@ -1847,7 +1755,7 @@ async function handleAppendEntry(projectPath, input) {
|
|
|
1847
1755
|
if (!input.authorSkill) return mcpError("Error: authorSkill is required for append_entry action");
|
|
1848
1756
|
if (!input.content) return mcpError("Error: content is required for append_entry action");
|
|
1849
1757
|
if (input.session) {
|
|
1850
|
-
const { appendSessionEntry } = await import("./dist-
|
|
1758
|
+
const { appendSessionEntry } = await import("./dist-CPKL5Y2R.js");
|
|
1851
1759
|
const result = await appendSessionEntry(
|
|
1852
1760
|
projectPath,
|
|
1853
1761
|
input.session,
|
|
@@ -1860,7 +1768,7 @@ async function handleAppendEntry(projectPath, input) {
|
|
|
1860
1768
|
if (input.section !== "decisions") {
|
|
1861
1769
|
return mcpError("Error: session is required for non-decisions sections");
|
|
1862
1770
|
}
|
|
1863
|
-
const { loadState, saveState } = await import("./dist-
|
|
1771
|
+
const { loadState, saveState } = await import("./dist-CPKL5Y2R.js");
|
|
1864
1772
|
const lr = await loadState(projectPath, input.stream);
|
|
1865
1773
|
if (!lr.ok) return resultToMcpResponse(lr);
|
|
1866
1774
|
lr.value.decisions.push({
|
|
@@ -1878,7 +1786,7 @@ async function handleUpdateEntryStatus(projectPath, input) {
|
|
|
1878
1786
|
if (!input.entryId) return mcpError("Error: entryId is required for update_entry_status action");
|
|
1879
1787
|
if (!input.newStatus)
|
|
1880
1788
|
return mcpError("Error: newStatus is required for update_entry_status action");
|
|
1881
|
-
const { updateSessionEntryStatus } = await import("./dist-
|
|
1789
|
+
const { updateSessionEntryStatus } = await import("./dist-CPKL5Y2R.js");
|
|
1882
1790
|
const result = await updateSessionEntryStatus(
|
|
1883
1791
|
projectPath,
|
|
1884
1792
|
input.session,
|
|
@@ -1891,7 +1799,7 @@ async function handleUpdateEntryStatus(projectPath, input) {
|
|
|
1891
1799
|
async function handleReadSection(projectPath, input) {
|
|
1892
1800
|
if (!input.session) return mcpError("Error: session is required for read_section action");
|
|
1893
1801
|
if (!input.section) return mcpError("Error: section is required for read_section action");
|
|
1894
|
-
const { readSessionSection } = await import("./dist-
|
|
1802
|
+
const { readSessionSection } = await import("./dist-CPKL5Y2R.js");
|
|
1895
1803
|
const result = await readSessionSection(
|
|
1896
1804
|
projectPath,
|
|
1897
1805
|
input.session,
|
|
@@ -1901,13 +1809,13 @@ async function handleReadSection(projectPath, input) {
|
|
|
1901
1809
|
}
|
|
1902
1810
|
async function handleReadSections(projectPath, input) {
|
|
1903
1811
|
if (!input.session) return mcpError("Error: session is required for read_sections action");
|
|
1904
|
-
const { readSessionSections } = await import("./dist-
|
|
1812
|
+
const { readSessionSections } = await import("./dist-CPKL5Y2R.js");
|
|
1905
1813
|
const result = await readSessionSections(projectPath, input.session);
|
|
1906
1814
|
return resultToMcpResponse(result);
|
|
1907
1815
|
}
|
|
1908
1816
|
async function handleArchiveSession(projectPath, input) {
|
|
1909
1817
|
if (!input.session) return mcpError("Error: session is required for archive_session action");
|
|
1910
|
-
const { archiveSession } = await import("./dist-
|
|
1818
|
+
const { archiveSession } = await import("./dist-CPKL5Y2R.js");
|
|
1911
1819
|
const result = await archiveSession(projectPath, input.session);
|
|
1912
1820
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1913
1821
|
await autoSyncRoadmap(projectPath);
|
|
@@ -1987,7 +1895,7 @@ var listStreamsDefinition = {
|
|
|
1987
1895
|
};
|
|
1988
1896
|
async function handleListStreams(input) {
|
|
1989
1897
|
try {
|
|
1990
|
-
const { listStreams, loadStreamIndex } = await import("./dist-
|
|
1898
|
+
const { listStreams, loadStreamIndex } = await import("./dist-CPKL5Y2R.js");
|
|
1991
1899
|
const projectPath = sanitizePath(input.path);
|
|
1992
1900
|
const indexResult = await loadStreamIndex(projectPath);
|
|
1993
1901
|
const streamsResult = await listStreams(projectPath);
|
|
@@ -2025,7 +1933,7 @@ var checkPhaseGateDefinition = {
|
|
|
2025
1933
|
};
|
|
2026
1934
|
async function handleCheckPhaseGate(input) {
|
|
2027
1935
|
try {
|
|
2028
|
-
const { runCheckPhaseGate } = await import("./check-phase-gate-
|
|
1936
|
+
const { runCheckPhaseGate } = await import("./check-phase-gate-ZVG56NT2.js");
|
|
2029
1937
|
const result = await runCheckPhaseGate({ cwd: sanitizePath(input.path) });
|
|
2030
1938
|
if (result.ok) {
|
|
2031
1939
|
return { content: [{ type: "text", text: JSON.stringify(result.value) }] };
|
|
@@ -2045,7 +1953,7 @@ async function handleCheckPhaseGate(input) {
|
|
|
2045
1953
|
}
|
|
2046
1954
|
|
|
2047
1955
|
// src/mcp/tools/cross-check.ts
|
|
2048
|
-
import * as
|
|
1956
|
+
import * as path11 from "path";
|
|
2049
1957
|
var validateCrossCheckDefinition = {
|
|
2050
1958
|
name: "validate_cross_check",
|
|
2051
1959
|
description: "Validate plan-to-implementation coverage: checks that specs have plans and plans have implementations, detects staleness",
|
|
@@ -2081,15 +1989,15 @@ async function handleValidateCrossCheck(input) {
|
|
|
2081
1989
|
};
|
|
2082
1990
|
}
|
|
2083
1991
|
try {
|
|
2084
|
-
const { runCrossCheck } = await import("./validate-cross-check-
|
|
2085
|
-
const specsDir =
|
|
1992
|
+
const { runCrossCheck } = await import("./validate-cross-check-SPL3H4O5.js");
|
|
1993
|
+
const specsDir = path11.resolve(projectPath, input.specsDir ?? "docs/specs");
|
|
2086
1994
|
if (!specsDir.startsWith(projectPath)) {
|
|
2087
1995
|
return {
|
|
2088
1996
|
content: [{ type: "text", text: "Error: specsDir escapes project root" }],
|
|
2089
1997
|
isError: true
|
|
2090
1998
|
};
|
|
2091
1999
|
}
|
|
2092
|
-
const plansDir =
|
|
2000
|
+
const plansDir = path11.resolve(projectPath, input.plansDir ?? "docs/plans");
|
|
2093
2001
|
if (!plansDir.startsWith(projectPath)) {
|
|
2094
2002
|
return {
|
|
2095
2003
|
content: [{ type: "text", text: "Error: plansDir escapes project root" }],
|
|
@@ -2123,15 +2031,15 @@ init_dist();
|
|
|
2123
2031
|
|
|
2124
2032
|
// src/commands/generate-slash-commands.ts
|
|
2125
2033
|
import { Command } from "commander";
|
|
2126
|
-
import
|
|
2127
|
-
import
|
|
2034
|
+
import fs12 from "fs";
|
|
2035
|
+
import path14 from "path";
|
|
2128
2036
|
import os from "os";
|
|
2129
2037
|
import readline from "readline";
|
|
2130
2038
|
|
|
2131
2039
|
// src/slash-commands/normalize.ts
|
|
2132
|
-
import
|
|
2133
|
-
import
|
|
2134
|
-
import { parse as
|
|
2040
|
+
import fs10 from "fs";
|
|
2041
|
+
import path12 from "path";
|
|
2042
|
+
import { parse as parse2 } from "yaml";
|
|
2135
2043
|
|
|
2136
2044
|
// src/slash-commands/normalize-name.ts
|
|
2137
2045
|
function normalizeName(skillName) {
|
|
@@ -2150,11 +2058,11 @@ function normalizeName(skillName) {
|
|
|
2150
2058
|
function readSkillYaml(yamlPath) {
|
|
2151
2059
|
let raw;
|
|
2152
2060
|
try {
|
|
2153
|
-
raw =
|
|
2061
|
+
raw = fs10.readFileSync(yamlPath, "utf-8");
|
|
2154
2062
|
} catch {
|
|
2155
2063
|
return null;
|
|
2156
2064
|
}
|
|
2157
|
-
return SkillMetadataSchema.safeParse(
|
|
2065
|
+
return SkillMetadataSchema.safeParse(parse2(raw));
|
|
2158
2066
|
}
|
|
2159
2067
|
var DERIVED_FROM_CLAUDE_CODE = ["cursor", "codex"];
|
|
2160
2068
|
function shouldSkipSkill(meta, platforms) {
|
|
@@ -2214,10 +2122,10 @@ function buildProcessLines(meta) {
|
|
|
2214
2122
|
];
|
|
2215
2123
|
}
|
|
2216
2124
|
function buildSpec(meta, normalized, entry, skillsDir, source) {
|
|
2217
|
-
const skillMdPath =
|
|
2218
|
-
const skillMdContent =
|
|
2219
|
-
const skillMdRelative =
|
|
2220
|
-
const skillYamlRelative =
|
|
2125
|
+
const skillMdPath = path12.join(skillsDir, entry.name, "SKILL.md");
|
|
2126
|
+
const skillMdContent = fs10.existsSync(skillMdPath) ? fs10.readFileSync(skillMdPath, "utf-8") : "";
|
|
2127
|
+
const skillMdRelative = path12.relative(process.cwd(), skillMdPath).replaceAll("\\", "/");
|
|
2128
|
+
const skillYamlRelative = path12.relative(process.cwd(), path12.join(skillsDir, entry.name, "skill.yaml")).replaceAll("\\", "/");
|
|
2221
2129
|
const args = (meta.cli?.args ?? []).map((a) => ({
|
|
2222
2130
|
name: a.name,
|
|
2223
2131
|
description: a.description ?? "",
|
|
@@ -2272,11 +2180,11 @@ function normalizeSkills(skillSources, platforms) {
|
|
|
2272
2180
|
const specs = [];
|
|
2273
2181
|
const nameMap = /* @__PURE__ */ new Map();
|
|
2274
2182
|
for (const { dir: skillsDir, source } of skillSources) {
|
|
2275
|
-
if (!
|
|
2276
|
-
const entries =
|
|
2183
|
+
if (!fs10.existsSync(skillsDir)) continue;
|
|
2184
|
+
const entries = fs10.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
2277
2185
|
for (const entry of entries) {
|
|
2278
|
-
const yamlPath =
|
|
2279
|
-
if (!
|
|
2186
|
+
const yamlPath = path12.join(skillsDir, entry.name, "skill.yaml");
|
|
2187
|
+
if (!fs10.existsSync(yamlPath)) continue;
|
|
2280
2188
|
const result = readSkillYaml(yamlPath);
|
|
2281
2189
|
if (!result) continue;
|
|
2282
2190
|
if (!result.success) {
|
|
@@ -2446,27 +2354,27 @@ function renderCodexAgentsMd(specs) {
|
|
|
2446
2354
|
}
|
|
2447
2355
|
|
|
2448
2356
|
// src/slash-commands/sync-codex.ts
|
|
2449
|
-
import
|
|
2450
|
-
import
|
|
2357
|
+
import fs11 from "fs";
|
|
2358
|
+
import path13 from "path";
|
|
2451
2359
|
function computeCodexSync(outputDir, specs, dryRun) {
|
|
2452
2360
|
const added = [];
|
|
2453
2361
|
const updated = [];
|
|
2454
2362
|
const unchanged = [];
|
|
2455
2363
|
const specSkillNames = /* @__PURE__ */ new Set();
|
|
2456
2364
|
for (const spec of specs) {
|
|
2457
|
-
const mdPath =
|
|
2458
|
-
const skillMd =
|
|
2459
|
-
const skillDir =
|
|
2365
|
+
const mdPath = path13.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
|
|
2366
|
+
const skillMd = fs11.existsSync(mdPath) ? fs11.readFileSync(mdPath, "utf-8") : "";
|
|
2367
|
+
const skillDir = path13.join(outputDir, spec.skillYamlName);
|
|
2460
2368
|
specSkillNames.add(spec.skillYamlName);
|
|
2461
2369
|
const renderedSkillMd = renderCodexSkill(skillMd);
|
|
2462
2370
|
const renderedOpenaiYaml = renderCodexOpenaiYaml(spec);
|
|
2463
|
-
const existingSkillMdPath =
|
|
2464
|
-
const existingOpenaiYamlPath =
|
|
2465
|
-
if (!
|
|
2371
|
+
const existingSkillMdPath = path13.join(skillDir, "SKILL.md");
|
|
2372
|
+
const existingOpenaiYamlPath = path13.join(skillDir, "agents", "openai.yaml");
|
|
2373
|
+
if (!fs11.existsSync(skillDir)) {
|
|
2466
2374
|
added.push(spec.skillYamlName);
|
|
2467
2375
|
} else {
|
|
2468
|
-
const existingSkillMd =
|
|
2469
|
-
const existingOpenaiYaml =
|
|
2376
|
+
const existingSkillMd = fs11.existsSync(existingSkillMdPath) ? fs11.readFileSync(existingSkillMdPath, "utf-8") : "";
|
|
2377
|
+
const existingOpenaiYaml = fs11.existsSync(existingOpenaiYamlPath) ? fs11.readFileSync(existingOpenaiYamlPath, "utf-8") : "";
|
|
2470
2378
|
if (existingSkillMd === renderedSkillMd && existingOpenaiYaml === renderedOpenaiYaml) {
|
|
2471
2379
|
unchanged.push(spec.skillYamlName);
|
|
2472
2380
|
} else {
|
|
@@ -2474,10 +2382,10 @@ function computeCodexSync(outputDir, specs, dryRun) {
|
|
|
2474
2382
|
}
|
|
2475
2383
|
}
|
|
2476
2384
|
if (!dryRun && !unchanged.includes(spec.skillYamlName)) {
|
|
2477
|
-
const agentsSubDir =
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2385
|
+
const agentsSubDir = path13.join(skillDir, "agents");
|
|
2386
|
+
fs11.mkdirSync(agentsSubDir, { recursive: true });
|
|
2387
|
+
fs11.writeFileSync(existingSkillMdPath, renderedSkillMd, "utf-8");
|
|
2388
|
+
fs11.writeFileSync(existingOpenaiYamlPath, renderedOpenaiYaml, "utf-8");
|
|
2481
2389
|
}
|
|
2482
2390
|
}
|
|
2483
2391
|
const removed = detectCodexOrphans(outputDir, specSkillNames);
|
|
@@ -2485,13 +2393,13 @@ function computeCodexSync(outputDir, specs, dryRun) {
|
|
|
2485
2393
|
}
|
|
2486
2394
|
function detectCodexOrphans(outputDir, specSkillNames) {
|
|
2487
2395
|
const removed = [];
|
|
2488
|
-
if (!
|
|
2489
|
-
const existingDirs =
|
|
2396
|
+
if (!fs11.existsSync(outputDir)) return removed;
|
|
2397
|
+
const existingDirs = fs11.readdirSync(outputDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
2490
2398
|
for (const dirName of existingDirs) {
|
|
2491
2399
|
if (specSkillNames.has(dirName)) continue;
|
|
2492
|
-
const skillMdPath =
|
|
2493
|
-
if (
|
|
2494
|
-
const content =
|
|
2400
|
+
const skillMdPath = path13.join(outputDir, dirName, "SKILL.md");
|
|
2401
|
+
if (fs11.existsSync(skillMdPath)) {
|
|
2402
|
+
const content = fs11.readFileSync(skillMdPath, "utf-8");
|
|
2495
2403
|
if (content.includes(GENERATED_HEADER_CODEX)) {
|
|
2496
2404
|
removed.push(dirName);
|
|
2497
2405
|
}
|
|
@@ -2503,19 +2411,19 @@ function detectCodexOrphans(outputDir, specSkillNames) {
|
|
|
2503
2411
|
// src/commands/generate-slash-commands.ts
|
|
2504
2412
|
function resolveOutputDir(platform, opts) {
|
|
2505
2413
|
if (opts.output) {
|
|
2506
|
-
return
|
|
2414
|
+
return path14.join(opts.output, "harness");
|
|
2507
2415
|
}
|
|
2508
2416
|
if (opts.global) {
|
|
2509
2417
|
const home = os.homedir();
|
|
2510
|
-
if (platform === "claude-code") return
|
|
2511
|
-
if (platform === "gemini-cli") return
|
|
2512
|
-
if (platform === "cursor") return
|
|
2513
|
-
return
|
|
2418
|
+
if (platform === "claude-code") return path14.join(home, ".claude", "commands", "harness");
|
|
2419
|
+
if (platform === "gemini-cli") return path14.join(home, ".gemini", "commands", "harness");
|
|
2420
|
+
if (platform === "cursor") return path14.join(home, ".cursor", "rules", "harness");
|
|
2421
|
+
return path14.join(home, ".codex", "harness");
|
|
2514
2422
|
}
|
|
2515
|
-
if (platform === "claude-code") return
|
|
2516
|
-
if (platform === "gemini-cli") return
|
|
2517
|
-
if (platform === "cursor") return
|
|
2518
|
-
return
|
|
2423
|
+
if (platform === "claude-code") return path14.join("agents", "commands", "claude-code", "harness");
|
|
2424
|
+
if (platform === "gemini-cli") return path14.join("agents", "commands", "gemini-cli", "harness");
|
|
2425
|
+
if (platform === "cursor") return path14.join("agents", "commands", "cursor", "harness");
|
|
2426
|
+
return path14.join("agents", "commands", "codex", "harness");
|
|
2519
2427
|
}
|
|
2520
2428
|
async function confirmDeletion(files) {
|
|
2521
2429
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -2531,8 +2439,8 @@ function resolveSkillSources(opts) {
|
|
|
2531
2439
|
const sources = [];
|
|
2532
2440
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
2533
2441
|
function addSource(dir, source) {
|
|
2534
|
-
const resolved =
|
|
2535
|
-
if (!seenPaths.has(resolved) &&
|
|
2442
|
+
const resolved = path14.resolve(dir);
|
|
2443
|
+
if (!seenPaths.has(resolved) && fs12.existsSync(dir)) {
|
|
2536
2444
|
seenPaths.add(resolved);
|
|
2537
2445
|
sources.push({ dir, source });
|
|
2538
2446
|
}
|
|
@@ -2559,32 +2467,32 @@ function resolveAbsoluteExecutionContext(spec) {
|
|
|
2559
2467
|
...spec,
|
|
2560
2468
|
prompt: {
|
|
2561
2469
|
...spec.prompt,
|
|
2562
|
-
executionContext: spec.prompt.executionContext.split("\n").map((line) => line.startsWith("@") ? `@${
|
|
2470
|
+
executionContext: spec.prompt.executionContext.split("\n").map((line) => line.startsWith("@") ? `@${path14.resolve(line.slice(1))}` : line).join("\n")
|
|
2563
2471
|
}
|
|
2564
2472
|
};
|
|
2565
2473
|
}
|
|
2566
2474
|
function renderSpec(platform, spec, useAbsolutePaths) {
|
|
2567
2475
|
if (platform === "cursor") {
|
|
2568
|
-
const mdPath2 =
|
|
2569
|
-
const skillMd =
|
|
2476
|
+
const mdPath2 = path14.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
|
|
2477
|
+
const skillMd = fs12.existsSync(mdPath2) ? fs12.readFileSync(mdPath2, "utf-8") : "";
|
|
2570
2478
|
return [`${spec.skillYamlName}.mdc`, renderCursor(spec, skillMd, spec.cursor)];
|
|
2571
2479
|
}
|
|
2572
2480
|
if (platform === "claude-code") {
|
|
2573
2481
|
const renderSpecValue = useAbsolutePaths ? resolveAbsoluteExecutionContext(spec) : spec;
|
|
2574
2482
|
return [`${spec.name}.md`, renderClaudeCode(renderSpecValue)];
|
|
2575
2483
|
}
|
|
2576
|
-
const mdPath =
|
|
2577
|
-
const yamlPath =
|
|
2578
|
-
const mdContent =
|
|
2579
|
-
const yamlContent =
|
|
2484
|
+
const mdPath = path14.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
|
|
2485
|
+
const yamlPath = path14.join(spec.skillsBaseDir, spec.sourceDir, "skill.yaml");
|
|
2486
|
+
const mdContent = fs12.existsSync(mdPath) ? fs12.readFileSync(mdPath, "utf-8") : "";
|
|
2487
|
+
const yamlContent = fs12.existsSync(yamlPath) ? fs12.readFileSync(yamlPath, "utf-8") : "";
|
|
2580
2488
|
return [`${spec.name}.toml`, renderGemini(spec, mdContent, yamlContent)];
|
|
2581
2489
|
}
|
|
2582
2490
|
function generateForCodex(platform, outputDir, specs, dryRun) {
|
|
2583
2491
|
const codexSync = computeCodexSync(outputDir, specs, dryRun);
|
|
2584
|
-
const codexRoot =
|
|
2492
|
+
const codexRoot = path14.dirname(outputDir);
|
|
2585
2493
|
if (!dryRun) {
|
|
2586
|
-
|
|
2587
|
-
|
|
2494
|
+
fs12.mkdirSync(codexRoot, { recursive: true });
|
|
2495
|
+
fs12.writeFileSync(path14.join(codexRoot, "AGENTS.md"), renderCodexAgentsMd(specs), "utf-8");
|
|
2588
2496
|
}
|
|
2589
2497
|
return { platform, ...codexSync, outputDir };
|
|
2590
2498
|
}
|
|
@@ -2615,9 +2523,9 @@ function generateForPlatform(platform, outputDir, specs, opts) {
|
|
|
2615
2523
|
const allUpdated = [...plan.updated];
|
|
2616
2524
|
const allRemoved = [...plan.removed];
|
|
2617
2525
|
const allUnchanged = [...plan.unchanged];
|
|
2618
|
-
const parentDir =
|
|
2526
|
+
const parentDir = path14.dirname(outputDir);
|
|
2619
2527
|
for (const [ns, nsRendered] of customNamespaceRendered) {
|
|
2620
|
-
const nsDir =
|
|
2528
|
+
const nsDir = path14.join(parentDir, ns);
|
|
2621
2529
|
const nsPlan = computeSyncPlan(nsDir, nsRendered);
|
|
2622
2530
|
if (!opts.dryRun) {
|
|
2623
2531
|
applySyncPlan(nsDir, nsRendered, nsPlan, false);
|
|
@@ -2667,13 +2575,13 @@ async function handleOrphanDeletion(results, opts) {
|
|
|
2667
2575
|
const shouldDelete = opts.yes || await confirmDeletion(result.removed);
|
|
2668
2576
|
if (!shouldDelete) continue;
|
|
2669
2577
|
for (const filename of result.removed) {
|
|
2670
|
-
const filePath =
|
|
2671
|
-
if (!
|
|
2672
|
-
const stat =
|
|
2578
|
+
const filePath = path14.join(result.outputDir, filename);
|
|
2579
|
+
if (!fs12.existsSync(filePath)) continue;
|
|
2580
|
+
const stat = fs12.statSync(filePath);
|
|
2673
2581
|
if (stat.isDirectory()) {
|
|
2674
|
-
|
|
2582
|
+
fs12.rmSync(filePath, { recursive: true, force: true });
|
|
2675
2583
|
} else {
|
|
2676
|
-
|
|
2584
|
+
fs12.unlinkSync(filePath);
|
|
2677
2585
|
}
|
|
2678
2586
|
}
|
|
2679
2587
|
}
|
|
@@ -2804,7 +2712,7 @@ async function handleGenerateSlashCommands(input) {
|
|
|
2804
2712
|
// src/mcp/resources/state.ts
|
|
2805
2713
|
async function getStateResource(projectRoot) {
|
|
2806
2714
|
try {
|
|
2807
|
-
const { loadState, migrateToStreams } = await import("./dist-
|
|
2715
|
+
const { loadState, migrateToStreams } = await import("./dist-CPKL5Y2R.js");
|
|
2808
2716
|
await migrateToStreams(projectRoot);
|
|
2809
2717
|
const result = await loadState(projectRoot);
|
|
2810
2718
|
if (result.ok) {
|
|
@@ -2922,7 +2830,7 @@ async function handleQueryGraph(input) {
|
|
|
2922
2830
|
const projectPath = sanitizePath(input.path);
|
|
2923
2831
|
const store = await loadGraphStore(projectPath);
|
|
2924
2832
|
if (!store) return graphNotFoundError();
|
|
2925
|
-
const { ContextQL } = await import("./dist-
|
|
2833
|
+
const { ContextQL } = await import("./dist-BZS2XRLG.js");
|
|
2926
2834
|
const cql = new ContextQL(store);
|
|
2927
2835
|
const result = cql.execute({
|
|
2928
2836
|
rootNodeIds: input.rootNodeIds,
|
|
@@ -3004,7 +2912,7 @@ async function handleSearchSimilar(input) {
|
|
|
3004
2912
|
const projectPath = sanitizePath(input.path);
|
|
3005
2913
|
const store = await loadGraphStore(projectPath);
|
|
3006
2914
|
if (!store) return graphNotFoundError();
|
|
3007
|
-
const { FusionLayer } = await import("./dist-
|
|
2915
|
+
const { FusionLayer } = await import("./dist-BZS2XRLG.js");
|
|
3008
2916
|
const fusion = new FusionLayer(store);
|
|
3009
2917
|
const results = fusion.search(input.query, input.topK ?? 10);
|
|
3010
2918
|
if (input.mode === "summary") {
|
|
@@ -3059,7 +2967,7 @@ async function handleFindContextFor(input) {
|
|
|
3059
2967
|
const projectPath = sanitizePath(input.path);
|
|
3060
2968
|
const store = await loadGraphStore(projectPath);
|
|
3061
2969
|
if (!store) return graphNotFoundError();
|
|
3062
|
-
const { FusionLayer, ContextQL } = await import("./dist-
|
|
2970
|
+
const { FusionLayer, ContextQL } = await import("./dist-BZS2XRLG.js");
|
|
3063
2971
|
const fusion = new FusionLayer(store);
|
|
3064
2972
|
const cql = new ContextQL(store);
|
|
3065
2973
|
const tokenBudget = input.tokenBudget ?? 4e3;
|
|
@@ -3164,7 +3072,7 @@ async function handleGetRelationships(input) {
|
|
|
3164
3072
|
const projectPath = sanitizePath(input.path);
|
|
3165
3073
|
const store = await loadGraphStore(projectPath);
|
|
3166
3074
|
if (!store) return graphNotFoundError();
|
|
3167
|
-
const { ContextQL } = await import("./dist-
|
|
3075
|
+
const { ContextQL } = await import("./dist-BZS2XRLG.js");
|
|
3168
3076
|
const cql = new ContextQL(store);
|
|
3169
3077
|
const direction = input.direction ?? "both";
|
|
3170
3078
|
const bidirectional = direction === "both" || direction === "inbound";
|
|
@@ -3282,7 +3190,7 @@ async function handleGetImpact(input) {
|
|
|
3282
3190
|
const projectPath = sanitizePath(input.path);
|
|
3283
3191
|
const store = await loadGraphStore(projectPath);
|
|
3284
3192
|
if (!store) return graphNotFoundError();
|
|
3285
|
-
const { ContextQL } = await import("./dist-
|
|
3193
|
+
const { ContextQL } = await import("./dist-BZS2XRLG.js");
|
|
3286
3194
|
let targetNodeId = input.nodeId;
|
|
3287
3195
|
if (!targetNodeId && input.filePath) {
|
|
3288
3196
|
const fileNodes = store.findNodes({ type: "file" });
|
|
@@ -3393,7 +3301,7 @@ async function handleGetImpact(input) {
|
|
|
3393
3301
|
}
|
|
3394
3302
|
|
|
3395
3303
|
// src/mcp/tools/graph/ingest-source.ts
|
|
3396
|
-
import * as
|
|
3304
|
+
import * as path15 from "path";
|
|
3397
3305
|
var ingestSourceDefinition = {
|
|
3398
3306
|
name: "ingest_source",
|
|
3399
3307
|
description: "Ingest sources into the project knowledge graph. Supports code analysis, knowledge documents, git history, or all at once.",
|
|
@@ -3413,10 +3321,10 @@ var ingestSourceDefinition = {
|
|
|
3413
3321
|
async function handleIngestSource(input) {
|
|
3414
3322
|
try {
|
|
3415
3323
|
const projectPath = sanitizePath(input.path);
|
|
3416
|
-
const graphDir =
|
|
3417
|
-
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-
|
|
3418
|
-
const
|
|
3419
|
-
await
|
|
3324
|
+
const graphDir = path15.join(projectPath, ".harness", "graph");
|
|
3325
|
+
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-BZS2XRLG.js");
|
|
3326
|
+
const fs17 = await import("fs/promises");
|
|
3327
|
+
await fs17.mkdir(graphDir, { recursive: true });
|
|
3420
3328
|
const store = new GraphStore();
|
|
3421
3329
|
await store.load(graphDir);
|
|
3422
3330
|
const results = [];
|
|
@@ -3438,13 +3346,13 @@ async function handleIngestSource(input) {
|
|
|
3438
3346
|
results.push(gitResult);
|
|
3439
3347
|
}
|
|
3440
3348
|
if (input.source === "business-signals" || input.source === "all") {
|
|
3441
|
-
const { createExtractionRunner } = await import("./dist-
|
|
3442
|
-
const extractedDir =
|
|
3349
|
+
const { createExtractionRunner } = await import("./dist-BZS2XRLG.js");
|
|
3350
|
+
const extractedDir = path15.join(projectPath, ".harness", "knowledge", "extracted");
|
|
3443
3351
|
const signalsResult = await createExtractionRunner().run(projectPath, store, extractedDir);
|
|
3444
3352
|
results.push(signalsResult);
|
|
3445
3353
|
}
|
|
3446
3354
|
if (input.source === "diagrams" || input.source === "all") {
|
|
3447
|
-
const { DiagramParser } = await import("./dist-
|
|
3355
|
+
const { DiagramParser } = await import("./dist-BZS2XRLG.js");
|
|
3448
3356
|
const diagramParser = new DiagramParser(store);
|
|
3449
3357
|
const diagramResult = await diagramParser.ingest(projectPath);
|
|
3450
3358
|
results.push(diagramResult);
|
|
@@ -3510,7 +3418,7 @@ async function handleDetectAnomalies(input) {
|
|
|
3510
3418
|
const projectPath = sanitizePath(input.path);
|
|
3511
3419
|
const store = await loadGraphStore(projectPath);
|
|
3512
3420
|
if (!store) return graphNotFoundError();
|
|
3513
|
-
const { GraphAnomalyAdapter } = await import("./dist-
|
|
3421
|
+
const { GraphAnomalyAdapter } = await import("./dist-BZS2XRLG.js");
|
|
3514
3422
|
const adapter = new GraphAnomalyAdapter(store);
|
|
3515
3423
|
const report = adapter.detect({
|
|
3516
3424
|
...input.threshold !== void 0 && { threshold: input.threshold },
|
|
@@ -3559,7 +3467,7 @@ async function handleAskGraph(input) {
|
|
|
3559
3467
|
const projectPath = sanitizePath(input.path);
|
|
3560
3468
|
const store = await loadGraphStore(projectPath);
|
|
3561
3469
|
if (!store) return graphNotFoundError();
|
|
3562
|
-
const { askGraph } = await import("./dist-
|
|
3470
|
+
const { askGraph } = await import("./dist-BZS2XRLG.js");
|
|
3563
3471
|
const result = await askGraph(store, input.question);
|
|
3564
3472
|
return {
|
|
3565
3473
|
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
@@ -3623,7 +3531,7 @@ async function handleComputeBlastRadius(input) {
|
|
|
3623
3531
|
const projectPath = sanitizePath(input.path);
|
|
3624
3532
|
const store = await loadGraphStore(projectPath);
|
|
3625
3533
|
if (!store) return graphNotFoundError();
|
|
3626
|
-
const { CascadeSimulator } = await import("./dist-
|
|
3534
|
+
const { CascadeSimulator } = await import("./dist-BZS2XRLG.js");
|
|
3627
3535
|
let targetNodeId = input.nodeId;
|
|
3628
3536
|
if (!targetNodeId && input.file) {
|
|
3629
3537
|
const fileNodes = store.findNodes({ type: "file" });
|
|
@@ -3710,8 +3618,8 @@ async function handleComputeBlastRadius(input) {
|
|
|
3710
3618
|
}
|
|
3711
3619
|
|
|
3712
3620
|
// src/mcp/resources/graph.ts
|
|
3713
|
-
import * as
|
|
3714
|
-
import * as
|
|
3621
|
+
import * as fs13 from "fs/promises";
|
|
3622
|
+
import * as path16 from "path";
|
|
3715
3623
|
var MAX_ITEMS = 5e3;
|
|
3716
3624
|
function formatStaleness(isoTimestamp) {
|
|
3717
3625
|
const then = new Date(isoTimestamp).getTime();
|
|
@@ -3734,9 +3642,9 @@ function countByType(items) {
|
|
|
3734
3642
|
return counts;
|
|
3735
3643
|
}
|
|
3736
3644
|
async function readLastScanTimestamp(projectRoot) {
|
|
3737
|
-
const metadataPath =
|
|
3645
|
+
const metadataPath = path16.join(projectRoot, ".harness", "graph", "metadata.json");
|
|
3738
3646
|
try {
|
|
3739
|
-
const raw = JSON.parse(await
|
|
3647
|
+
const raw = JSON.parse(await fs13.readFile(metadataPath, "utf-8"));
|
|
3740
3648
|
return raw.lastScanTimestamp ?? null;
|
|
3741
3649
|
} catch {
|
|
3742
3650
|
return null;
|
|
@@ -3824,7 +3732,7 @@ var generateAgentDefinitionsDefinition = {
|
|
|
3824
3732
|
}
|
|
3825
3733
|
};
|
|
3826
3734
|
async function handleGenerateAgentDefinitions(input) {
|
|
3827
|
-
const { generateAgentDefinitions } = await import("./generate-agent-definitions-
|
|
3735
|
+
const { generateAgentDefinitions } = await import("./generate-agent-definitions-FOSFADNR.js");
|
|
3828
3736
|
const platforms = input.platform === "all" || !input.platform ? ["claude-code", "gemini-cli"] : [input.platform];
|
|
3829
3737
|
const results = generateAgentDefinitions({
|
|
3830
3738
|
platforms: [...platforms],
|
|
@@ -3835,8 +3743,8 @@ async function handleGenerateAgentDefinitions(input) {
|
|
|
3835
3743
|
}
|
|
3836
3744
|
|
|
3837
3745
|
// src/mcp/tools/roadmap.ts
|
|
3838
|
-
import * as
|
|
3839
|
-
import * as
|
|
3746
|
+
import * as fs14 from "fs";
|
|
3747
|
+
import * as path17 from "path";
|
|
3840
3748
|
var manageRoadmapDefinition = {
|
|
3841
3749
|
name: "manage_roadmap",
|
|
3842
3750
|
description: "Manage the project roadmap: show, add, update, remove, sync features, or query by filter. Reads and writes docs/roadmap.md.",
|
|
@@ -3895,21 +3803,21 @@ var manageRoadmapDefinition = {
|
|
|
3895
3803
|
}
|
|
3896
3804
|
};
|
|
3897
3805
|
function roadmapPath(projectRoot) {
|
|
3898
|
-
return
|
|
3806
|
+
return path17.join(projectRoot, "docs", "roadmap.md");
|
|
3899
3807
|
}
|
|
3900
3808
|
function readRoadmapFile(projectRoot) {
|
|
3901
3809
|
const filePath = roadmapPath(projectRoot);
|
|
3902
3810
|
try {
|
|
3903
|
-
return
|
|
3811
|
+
return fs14.readFileSync(filePath, "utf-8");
|
|
3904
3812
|
} catch {
|
|
3905
3813
|
return null;
|
|
3906
3814
|
}
|
|
3907
3815
|
}
|
|
3908
3816
|
function writeRoadmapFile(projectRoot, content) {
|
|
3909
3817
|
const filePath = roadmapPath(projectRoot);
|
|
3910
|
-
const dir =
|
|
3911
|
-
|
|
3912
|
-
|
|
3818
|
+
const dir = path17.dirname(filePath);
|
|
3819
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
3820
|
+
fs14.writeFileSync(filePath, content, "utf-8");
|
|
3913
3821
|
}
|
|
3914
3822
|
function roadmapNotFoundError() {
|
|
3915
3823
|
return {
|
|
@@ -4152,7 +4060,7 @@ function shouldTriggerExternalSync(input, response) {
|
|
|
4152
4060
|
}
|
|
4153
4061
|
async function handleManageRoadmap(input) {
|
|
4154
4062
|
try {
|
|
4155
|
-
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges, assignFeature } = await import("./dist-
|
|
4063
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges, assignFeature } = await import("./dist-CPKL5Y2R.js");
|
|
4156
4064
|
const { Ok: Ok2 } = await import("./dist-3EWNRFFQ.js");
|
|
4157
4065
|
const projectPath = sanitizePath(input.path);
|
|
4158
4066
|
const deps = {
|
|
@@ -4591,7 +4499,7 @@ async function handleTransition(validInput, projectPath, id) {
|
|
|
4591
4499
|
const transition = transitionResult.data;
|
|
4592
4500
|
const prompt = renderTransition(transition);
|
|
4593
4501
|
try {
|
|
4594
|
-
const { saveHandoff } = await import("./dist-
|
|
4502
|
+
const { saveHandoff } = await import("./dist-CPKL5Y2R.js");
|
|
4595
4503
|
await saveHandoff(
|
|
4596
4504
|
projectPath,
|
|
4597
4505
|
{
|
|
@@ -4672,7 +4580,7 @@ async function handleEmitInteraction(input) {
|
|
|
4672
4580
|
}
|
|
4673
4581
|
async function recordInteraction(projectPath, id, type, decision, stream) {
|
|
4674
4582
|
try {
|
|
4675
|
-
const { loadState, saveState } = await import("./dist-
|
|
4583
|
+
const { loadState, saveState } = await import("./dist-CPKL5Y2R.js");
|
|
4676
4584
|
const stateResult = await loadState(projectPath, stream);
|
|
4677
4585
|
if (stateResult.ok) {
|
|
4678
4586
|
const state = stateResult.value;
|
|
@@ -4830,13 +4738,13 @@ async function handleGatherContext(input) {
|
|
|
4830
4738
|
};
|
|
4831
4739
|
}
|
|
4832
4740
|
const includeSet = new Set(
|
|
4833
|
-
input.include ?? ["state", "learnings", "handoff", "graph", "validation"]
|
|
4741
|
+
input.include ?? ["state", "learnings", "handoff", "graph", "validation", "businessKnowledge"]
|
|
4834
4742
|
);
|
|
4835
4743
|
const errors = [];
|
|
4836
|
-
const statePromise = includeSet.has("state") ? import("./dist-
|
|
4744
|
+
const statePromise = includeSet.has("state") ? import("./dist-CPKL5Y2R.js").then(
|
|
4837
4745
|
(core) => core.loadState(projectPath, void 0, input.session)
|
|
4838
4746
|
) : Promise.resolve(null);
|
|
4839
|
-
const learningsPromise = includeSet.has("learnings") ? import("./dist-
|
|
4747
|
+
const learningsPromise = includeSet.has("learnings") ? import("./dist-CPKL5Y2R.js").then(
|
|
4840
4748
|
(core) => core.loadBudgetedLearnings(projectPath, {
|
|
4841
4749
|
intent: input.intent,
|
|
4842
4750
|
tokenBudget: input.learningsBudget ?? 1e3,
|
|
@@ -4845,14 +4753,14 @@ async function handleGatherContext(input) {
|
|
|
4845
4753
|
...input.depth !== void 0 && { depth: input.depth }
|
|
4846
4754
|
})
|
|
4847
4755
|
) : Promise.resolve(null);
|
|
4848
|
-
const handoffPromise = includeSet.has("handoff") ? import("./dist-
|
|
4756
|
+
const handoffPromise = includeSet.has("handoff") ? import("./dist-CPKL5Y2R.js").then(
|
|
4849
4757
|
(core) => core.loadHandoff(projectPath, void 0, input.session)
|
|
4850
4758
|
) : Promise.resolve(null);
|
|
4851
4759
|
const graphPromise = includeSet.has("graph") ? (async () => {
|
|
4852
|
-
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-
|
|
4760
|
+
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-QEI7SYOQ.js");
|
|
4853
4761
|
const store = await loadGraphStore2(projectPath);
|
|
4854
4762
|
if (!store) return null;
|
|
4855
|
-
const { FusionLayer, ContextQL } = await import("./dist-
|
|
4763
|
+
const { FusionLayer, ContextQL } = await import("./dist-BZS2XRLG.js");
|
|
4856
4764
|
const fusion = new FusionLayer(store);
|
|
4857
4765
|
const cql = new ContextQL(store);
|
|
4858
4766
|
const tokenBudget = input.tokenBudget ?? 4e3;
|
|
@@ -4889,11 +4797,11 @@ async function handleGatherContext(input) {
|
|
|
4889
4797
|
context: contextBlocks
|
|
4890
4798
|
};
|
|
4891
4799
|
})() : Promise.resolve(null);
|
|
4892
|
-
const sessionsPromise = includeSet.has("sessions") && input.session ? import("./dist-
|
|
4800
|
+
const sessionsPromise = includeSet.has("sessions") && input.session ? import("./dist-CPKL5Y2R.js").then(
|
|
4893
4801
|
(core) => core.readSessionSections(projectPath, input.session)
|
|
4894
4802
|
) : Promise.resolve(null);
|
|
4895
4803
|
const shouldIncludeEvents = input.includeEvents !== void 0 ? input.includeEvents : includeSet.has("events") || !!input.session && !input.include;
|
|
4896
|
-
const eventsPromise = shouldIncludeEvents ? import("./dist-
|
|
4804
|
+
const eventsPromise = shouldIncludeEvents ? import("./dist-CPKL5Y2R.js").then(async (core) => {
|
|
4897
4805
|
const result = await core.loadEvents(projectPath, {
|
|
4898
4806
|
session: input.session
|
|
4899
4807
|
});
|
|
@@ -4901,13 +4809,13 @@ async function handleGatherContext(input) {
|
|
|
4901
4809
|
return core.formatEventTimeline(result.value);
|
|
4902
4810
|
}) : Promise.resolve(null);
|
|
4903
4811
|
const validationPromise = includeSet.has("validation") ? (async () => {
|
|
4904
|
-
const { handleValidateProject: handleValidateProject2 } = await import("./validate-
|
|
4812
|
+
const { handleValidateProject: handleValidateProject2 } = await import("./validate-EAVGKZQB.js");
|
|
4905
4813
|
const result = await handleValidateProject2({ path: projectPath });
|
|
4906
4814
|
const first = result.content[0];
|
|
4907
4815
|
return first ? JSON.parse(first.text) : null;
|
|
4908
4816
|
})() : Promise.resolve(null);
|
|
4909
4817
|
const businessKnowledgePromise = includeSet.has("businessKnowledge") ? (async () => {
|
|
4910
|
-
const { getBusinessKnowledgeResource: getBusinessKnowledgeResource2 } = await import("./business-knowledge-
|
|
4818
|
+
const { getBusinessKnowledgeResource: getBusinessKnowledgeResource2 } = await import("./business-knowledge-EISPR7FU.js");
|
|
4911
4819
|
const raw = await getBusinessKnowledgeResource2(projectPath);
|
|
4912
4820
|
return JSON.parse(raw);
|
|
4913
4821
|
})() : Promise.resolve(null);
|
|
@@ -5004,7 +4912,7 @@ async function handleGatherContext(input) {
|
|
|
5004
4912
|
};
|
|
5005
4913
|
if (input.session) {
|
|
5006
4914
|
try {
|
|
5007
|
-
const core = await import("./dist-
|
|
4915
|
+
const core = await import("./dist-CPKL5Y2R.js");
|
|
5008
4916
|
core.updateSessionIndex(
|
|
5009
4917
|
projectPath,
|
|
5010
4918
|
input.session,
|
|
@@ -5156,7 +5064,7 @@ async function handleReviewChanges(input) {
|
|
|
5156
5064
|
}
|
|
5157
5065
|
}
|
|
5158
5066
|
async function runQuickReview(projectPath, diff, diffLines, downgraded, offset, limit) {
|
|
5159
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-
|
|
5067
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-7EC4T6XG.js");
|
|
5160
5068
|
const result = await handleAnalyzeDiff2({ diff, path: projectPath });
|
|
5161
5069
|
const firstContent = result.content[0];
|
|
5162
5070
|
if (!firstContent) throw new Error("Empty analyze_diff response");
|
|
@@ -5191,7 +5099,7 @@ function extractFileCount(diffParsed) {
|
|
|
5191
5099
|
return files?.length ?? 0;
|
|
5192
5100
|
}
|
|
5193
5101
|
async function runStandardReview(projectPath, diff, diffLines, downgraded, offset, limit) {
|
|
5194
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-
|
|
5102
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-7EC4T6XG.js");
|
|
5195
5103
|
const [diffResult, reviewResult] = await Promise.all([
|
|
5196
5104
|
handleAnalyzeDiff2({ diff, path: projectPath }),
|
|
5197
5105
|
handleCreateSelfReview2({ path: projectPath, diff })
|
|
@@ -5226,7 +5134,7 @@ async function runStandardReview(projectPath, diff, diffLines, downgraded, offse
|
|
|
5226
5134
|
};
|
|
5227
5135
|
}
|
|
5228
5136
|
async function runDeepReview(projectPath, diff, diffLines, _downgraded, offset, limit) {
|
|
5229
|
-
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-
|
|
5137
|
+
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-B4WPU6BQ.js");
|
|
5230
5138
|
const result = await handleRunCodeReview2({
|
|
5231
5139
|
path: projectPath,
|
|
5232
5140
|
diff,
|
|
@@ -5305,7 +5213,7 @@ async function handleCheckTaskIndependence(input) {
|
|
|
5305
5213
|
try {
|
|
5306
5214
|
const projectPath = sanitizePath(input.path);
|
|
5307
5215
|
const store = await loadGraphStore(projectPath);
|
|
5308
|
-
const { TaskIndependenceAnalyzer } = await import("./dist-
|
|
5216
|
+
const { TaskIndependenceAnalyzer } = await import("./dist-BZS2XRLG.js");
|
|
5309
5217
|
const analyzer = new TaskIndependenceAnalyzer(store ?? void 0);
|
|
5310
5218
|
const result = analyzer.analyze({
|
|
5311
5219
|
tasks: input.tasks,
|
|
@@ -5393,7 +5301,7 @@ async function handlePredictConflicts(input) {
|
|
|
5393
5301
|
try {
|
|
5394
5302
|
const projectPath = sanitizePath(input.path);
|
|
5395
5303
|
const store = await loadGraphStore(projectPath);
|
|
5396
|
-
const { ConflictPredictor } = await import("./dist-
|
|
5304
|
+
const { ConflictPredictor } = await import("./dist-BZS2XRLG.js");
|
|
5397
5305
|
const predictor = new ConflictPredictor(store ?? void 0);
|
|
5398
5306
|
const result = predictor.predict({
|
|
5399
5307
|
tasks: input.tasks,
|
|
@@ -5499,7 +5407,7 @@ async function handleDetectStaleConstraints(input) {
|
|
|
5499
5407
|
isError: true
|
|
5500
5408
|
};
|
|
5501
5409
|
}
|
|
5502
|
-
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-
|
|
5410
|
+
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-QEI7SYOQ.js");
|
|
5503
5411
|
const store = await loadGraphStore2(projectPath);
|
|
5504
5412
|
if (!store) {
|
|
5505
5413
|
return {
|
|
@@ -5520,7 +5428,7 @@ async function handleDetectStaleConstraints(input) {
|
|
|
5520
5428
|
]
|
|
5521
5429
|
};
|
|
5522
5430
|
}
|
|
5523
|
-
const { detectStaleConstraints } = await import("./dist-
|
|
5431
|
+
const { detectStaleConstraints } = await import("./dist-CPKL5Y2R.js");
|
|
5524
5432
|
const result = detectStaleConstraints(
|
|
5525
5433
|
store,
|
|
5526
5434
|
windowDays,
|
|
@@ -5552,8 +5460,8 @@ init_dist();
|
|
|
5552
5460
|
|
|
5553
5461
|
// src/skill/health-snapshot.ts
|
|
5554
5462
|
import { execSync } from "child_process";
|
|
5555
|
-
import * as
|
|
5556
|
-
import * as
|
|
5463
|
+
import * as fs15 from "fs";
|
|
5464
|
+
import * as path18 from "path";
|
|
5557
5465
|
var CACHE_FILE = "health-snapshot.json";
|
|
5558
5466
|
var STALENESS_MS = 36e5;
|
|
5559
5467
|
function isSnapshotFresh(snapshot, projectPath) {
|
|
@@ -5570,19 +5478,19 @@ function isSnapshotFresh(snapshot, projectPath) {
|
|
|
5570
5478
|
return age < STALENESS_MS;
|
|
5571
5479
|
}
|
|
5572
5480
|
function loadCachedSnapshot(projectPath) {
|
|
5573
|
-
const filePath =
|
|
5481
|
+
const filePath = path18.join(projectPath, ".harness", CACHE_FILE);
|
|
5574
5482
|
try {
|
|
5575
|
-
const raw =
|
|
5483
|
+
const raw = fs15.readFileSync(filePath, "utf-8");
|
|
5576
5484
|
return JSON.parse(raw);
|
|
5577
5485
|
} catch {
|
|
5578
5486
|
return null;
|
|
5579
5487
|
}
|
|
5580
5488
|
}
|
|
5581
5489
|
function saveCachedSnapshot(snapshot, projectPath) {
|
|
5582
|
-
const dir =
|
|
5583
|
-
|
|
5584
|
-
const filePath =
|
|
5585
|
-
|
|
5490
|
+
const dir = path18.join(projectPath, ".harness");
|
|
5491
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
5492
|
+
const filePath = path18.join(dir, CACHE_FILE);
|
|
5493
|
+
fs15.writeFileSync(filePath, JSON.stringify(snapshot, null, 2));
|
|
5586
5494
|
}
|
|
5587
5495
|
var SIGNAL_RULES = [
|
|
5588
5496
|
["circular-deps", (c) => c.deps.circularDeps > 0],
|
|
@@ -5640,10 +5548,10 @@ function countCriticalFindings(securityData) {
|
|
|
5640
5548
|
return findings.filter((f) => f.severity === "error").length;
|
|
5641
5549
|
}
|
|
5642
5550
|
async function runHealthChecks(projectPath) {
|
|
5643
|
-
const { handleAssessProject: handleAssessProject2 } = await import("./assess-project-
|
|
5644
|
-
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-
|
|
5645
|
-
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-
|
|
5646
|
-
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-
|
|
5551
|
+
const { handleAssessProject: handleAssessProject2 } = await import("./assess-project-LLWWEQEV.js");
|
|
5552
|
+
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-ZR33YKJB.js");
|
|
5553
|
+
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-FIEE4YDA.js");
|
|
5554
|
+
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-25VFLIAO.js");
|
|
5647
5555
|
const [assessResult, depsResult, entropyResult, securityResult] = await Promise.all([
|
|
5648
5556
|
handleAssessProject2({
|
|
5649
5557
|
path: projectPath,
|
|
@@ -5698,10 +5606,10 @@ function avg(values) {
|
|
|
5698
5606
|
}
|
|
5699
5607
|
async function runGraphMetrics(projectPath) {
|
|
5700
5608
|
try {
|
|
5701
|
-
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-
|
|
5609
|
+
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-QEI7SYOQ.js");
|
|
5702
5610
|
const store = await loadGraphStore2(projectPath);
|
|
5703
5611
|
if (!store) return ZERO_METRICS;
|
|
5704
|
-
const { GraphCouplingAdapter, GraphComplexityAdapter, GraphAnomalyAdapter } = await import("./dist-
|
|
5612
|
+
const { GraphCouplingAdapter, GraphComplexityAdapter, GraphAnomalyAdapter } = await import("./dist-BZS2XRLG.js");
|
|
5705
5613
|
const couplingAdapter = new GraphCouplingAdapter(store);
|
|
5706
5614
|
const couplingData = couplingAdapter.computeCouplingData();
|
|
5707
5615
|
const files = couplingData.files;
|
|
@@ -5930,7 +5838,8 @@ function resolveMetricValue(metrics, metricName) {
|
|
|
5930
5838
|
function buildSkillAddressIndex(skills) {
|
|
5931
5839
|
const index = /* @__PURE__ */ new Map();
|
|
5932
5840
|
for (const [name, entry] of Object.entries(skills)) {
|
|
5933
|
-
const
|
|
5841
|
+
const canonicalName = name.replace(/^harness-/, "");
|
|
5842
|
+
const addresses = entry.addresses.length > 0 ? entry.addresses : FALLBACK_RULES[name] ?? FALLBACK_RULES[canonicalName] ?? [];
|
|
5934
5843
|
index.set(name, { addresses, dependsOn: entry.dependsOn });
|
|
5935
5844
|
}
|
|
5936
5845
|
for (const [name, addresses] of Object.entries(FALLBACK_RULES)) {
|
|
@@ -6090,7 +5999,14 @@ function recommend(snapshot, skills, options = {}) {
|
|
|
6090
5999
|
const hardRecs = matchHardRules(snapshot, addressIndex);
|
|
6091
6000
|
const softRecs = scoreByHealth(snapshot, addressIndex);
|
|
6092
6001
|
const hardSkills = new Set(hardRecs.map((r) => r.skillName));
|
|
6093
|
-
|
|
6002
|
+
let merged = [...hardRecs, ...softRecs.filter((r) => !hardSkills.has(r.skillName))];
|
|
6003
|
+
const { trigger, skillTriggers } = options;
|
|
6004
|
+
if (trigger && skillTriggers) {
|
|
6005
|
+
merged = merged.filter((r) => {
|
|
6006
|
+
const triggers = skillTriggers.get(r.skillName);
|
|
6007
|
+
return triggers ? triggers.includes(trigger) : true;
|
|
6008
|
+
});
|
|
6009
|
+
}
|
|
6094
6010
|
merged.sort((a, b) => b.score - a.score);
|
|
6095
6011
|
const limited = merged.slice(0, top);
|
|
6096
6012
|
const depMap = /* @__PURE__ */ new Map();
|
|
@@ -6255,7 +6171,12 @@ function dispatchSkills(context, options = {}) {
|
|
|
6255
6171
|
const { snapshot, changeType, domains, allSignals } = context;
|
|
6256
6172
|
const limit = options.limit ?? 5;
|
|
6257
6173
|
const enrichedSnapshot = { ...snapshot, signals: allSignals };
|
|
6258
|
-
const
|
|
6174
|
+
const recOpts = {
|
|
6175
|
+
top: limit
|
|
6176
|
+
};
|
|
6177
|
+
if (options.trigger) recOpts.trigger = options.trigger;
|
|
6178
|
+
if (options.skillTriggers) recOpts.skillTriggers = options.skillTriggers;
|
|
6179
|
+
const recResult = recommend(enrichedSnapshot, {}, recOpts);
|
|
6259
6180
|
const addressIndex = buildSkillAddressIndex({});
|
|
6260
6181
|
const skills = recResult.recommendations.map((rec, i) => {
|
|
6261
6182
|
const prevRec = i > 0 ? recResult.recommendations[i - 1] : null;
|
|
@@ -6306,6 +6227,8 @@ async function dispatchSkillsFromGit(projectPath, options = {}) {
|
|
|
6306
6227
|
const ctx = await enrichSnapshotForDispatch(projectPath, enrichOpts);
|
|
6307
6228
|
const dispatchOpts = {};
|
|
6308
6229
|
if (options.limit !== void 0) dispatchOpts.limit = options.limit;
|
|
6230
|
+
if (options.trigger) dispatchOpts.trigger = options.trigger;
|
|
6231
|
+
if (options.skillTriggers) dispatchOpts.skillTriggers = options.skillTriggers;
|
|
6309
6232
|
return dispatchSkills(ctx, dispatchOpts);
|
|
6310
6233
|
}
|
|
6311
6234
|
|
|
@@ -6336,6 +6259,10 @@ var dispatchSkillsDefinition = {
|
|
|
6336
6259
|
limit: {
|
|
6337
6260
|
type: "number",
|
|
6338
6261
|
description: "Maximum number of skills to return (default: 5)"
|
|
6262
|
+
},
|
|
6263
|
+
trigger: {
|
|
6264
|
+
type: "string",
|
|
6265
|
+
description: "Filter to skills declaring this trigger (e.g. on_pr, on_commit, on_milestone, on_task_complete, on_refactor, on_review). Only skills whose triggers array includes this value are returned."
|
|
6339
6266
|
}
|
|
6340
6267
|
},
|
|
6341
6268
|
required: []
|
|
@@ -6348,19 +6275,23 @@ function buildEnrichOpts(files, commitMessage, fresh) {
|
|
|
6348
6275
|
if (fresh) opts.fresh = fresh;
|
|
6349
6276
|
return opts;
|
|
6350
6277
|
}
|
|
6351
|
-
async function dispatchWithExplicitInput(projectRoot, files, commitMessage, fresh, limit) {
|
|
6278
|
+
async function dispatchWithExplicitInput(projectRoot, files, commitMessage, fresh, limit, trigger, skillTriggers) {
|
|
6352
6279
|
const ctx = await enrichSnapshotForDispatch(
|
|
6353
6280
|
projectRoot,
|
|
6354
6281
|
buildEnrichOpts(files, commitMessage, fresh)
|
|
6355
6282
|
);
|
|
6356
6283
|
const dispatchOpts = {};
|
|
6357
6284
|
if (limit !== 5) dispatchOpts.limit = limit;
|
|
6285
|
+
if (trigger) dispatchOpts.trigger = trigger;
|
|
6286
|
+
if (skillTriggers) dispatchOpts.skillTriggers = skillTriggers;
|
|
6358
6287
|
return dispatchSkills(ctx, dispatchOpts);
|
|
6359
6288
|
}
|
|
6360
|
-
async function dispatchFromGit(projectRoot, fresh, limit) {
|
|
6289
|
+
async function dispatchFromGit(projectRoot, fresh, limit, trigger, skillTriggers) {
|
|
6361
6290
|
const opts = {};
|
|
6362
6291
|
if (fresh) opts.fresh = fresh;
|
|
6363
6292
|
if (limit !== 5) opts.limit = limit;
|
|
6293
|
+
if (trigger) opts.trigger = trigger;
|
|
6294
|
+
if (skillTriggers) opts.skillTriggers = skillTriggers;
|
|
6364
6295
|
return dispatchSkillsFromGit(projectRoot, opts);
|
|
6365
6296
|
}
|
|
6366
6297
|
async function handleDispatchSkills(input) {
|
|
@@ -6369,9 +6300,30 @@ async function handleDispatchSkills(input) {
|
|
|
6369
6300
|
const commitMessage = input.commitMessage;
|
|
6370
6301
|
const fresh = input.fresh ?? false;
|
|
6371
6302
|
const limit = input.limit ?? 5;
|
|
6303
|
+
const trigger = input.trigger;
|
|
6372
6304
|
try {
|
|
6305
|
+
let skillTriggers;
|
|
6306
|
+
if (trigger) {
|
|
6307
|
+
try {
|
|
6308
|
+
const { loadOrRebuildIndex: loadOrRebuildIndex2 } = await import("./index-builder-3AOQ3ZII.js");
|
|
6309
|
+
const index = loadOrRebuildIndex2("claude-code", projectRoot);
|
|
6310
|
+
skillTriggers = /* @__PURE__ */ new Map();
|
|
6311
|
+
for (const [name, entry] of Object.entries(index.skills)) {
|
|
6312
|
+
skillTriggers.set(name, entry.triggers ?? ["manual"]);
|
|
6313
|
+
}
|
|
6314
|
+
} catch {
|
|
6315
|
+
}
|
|
6316
|
+
}
|
|
6373
6317
|
const hasExplicitInput = files !== void 0 || commitMessage !== void 0;
|
|
6374
|
-
const result = hasExplicitInput ? await dispatchWithExplicitInput(
|
|
6318
|
+
const result = hasExplicitInput ? await dispatchWithExplicitInput(
|
|
6319
|
+
projectRoot,
|
|
6320
|
+
files,
|
|
6321
|
+
commitMessage,
|
|
6322
|
+
fresh,
|
|
6323
|
+
limit,
|
|
6324
|
+
trigger,
|
|
6325
|
+
skillTriggers
|
|
6326
|
+
) : await dispatchFromGit(projectRoot, fresh, limit, trigger, skillTriggers);
|
|
6375
6327
|
if (result.skills.length > limit) {
|
|
6376
6328
|
result.skills = result.skills.slice(0, limit);
|
|
6377
6329
|
}
|
|
@@ -6440,7 +6392,7 @@ async function handleGetDecayTrends(input) {
|
|
|
6440
6392
|
};
|
|
6441
6393
|
}
|
|
6442
6394
|
try {
|
|
6443
|
-
const core = await import("./dist-
|
|
6395
|
+
const core = await import("./dist-CPKL5Y2R.js");
|
|
6444
6396
|
const { TimelineManager } = core;
|
|
6445
6397
|
const manager = new TimelineManager(projectPath);
|
|
6446
6398
|
const timeline = manager.load();
|
|
@@ -6575,7 +6527,7 @@ async function handleCodeOutline(input) {
|
|
|
6575
6527
|
};
|
|
6576
6528
|
}
|
|
6577
6529
|
try {
|
|
6578
|
-
const { getOutline, formatOutline, EXTENSION_MAP } = await import("./dist-
|
|
6530
|
+
const { getOutline, formatOutline, EXTENSION_MAP } = await import("./dist-CPKL5Y2R.js");
|
|
6579
6531
|
const { stat } = await import("fs/promises");
|
|
6580
6532
|
const stats = await stat(targetPath).catch(() => null);
|
|
6581
6533
|
if (stats?.isFile()) {
|
|
@@ -6594,7 +6546,7 @@ async function handleCodeOutline(input) {
|
|
|
6594
6546
|
})
|
|
6595
6547
|
);
|
|
6596
6548
|
fileStats.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
6597
|
-
const { paginate: paginate2 } = await import("./dist-
|
|
6549
|
+
const { paginate: paginate2 } = await import("./dist-CPKL5Y2R.js");
|
|
6598
6550
|
const paged = paginate2(fileStats, input.offset ?? 0, input.limit ?? 30);
|
|
6599
6551
|
const results = [];
|
|
6600
6552
|
for (const entry of paged.items) {
|
|
@@ -6667,7 +6619,7 @@ async function handleCodeSearch(input) {
|
|
|
6667
6619
|
};
|
|
6668
6620
|
}
|
|
6669
6621
|
try {
|
|
6670
|
-
const { searchSymbols } = await import("./dist-
|
|
6622
|
+
const { searchSymbols } = await import("./dist-CPKL5Y2R.js");
|
|
6671
6623
|
const result = await searchSymbols(input.query, directory, input.glob);
|
|
6672
6624
|
const lines = [`Search: "${result.query}" \u2014 ${result.matches.length} matches`];
|
|
6673
6625
|
for (const match of result.matches) {
|
|
@@ -6736,7 +6688,7 @@ async function handleCodeUnfold(input) {
|
|
|
6736
6688
|
}
|
|
6737
6689
|
try {
|
|
6738
6690
|
if (input.symbol) {
|
|
6739
|
-
const { unfoldSymbol } = await import("./dist-
|
|
6691
|
+
const { unfoldSymbol } = await import("./dist-CPKL5Y2R.js");
|
|
6740
6692
|
const result = await unfoldSymbol(filePath, input.symbol);
|
|
6741
6693
|
const header = result.warning ? `${result.file}:${result.startLine}-${result.endLine} ${result.warning}
|
|
6742
6694
|
` : `${result.file}:${result.startLine}-${result.endLine}
|
|
@@ -6744,7 +6696,7 @@ async function handleCodeUnfold(input) {
|
|
|
6744
6696
|
return { content: [{ type: "text", text: header + result.content }] };
|
|
6745
6697
|
}
|
|
6746
6698
|
if (input.startLine != null && input.endLine != null) {
|
|
6747
|
-
const { unfoldRange } = await import("./dist-
|
|
6699
|
+
const { unfoldRange } = await import("./dist-CPKL5Y2R.js");
|
|
6748
6700
|
const result = await unfoldRange(filePath, input.startLine, input.endLine);
|
|
6749
6701
|
const header = `${result.file}:${result.startLine}-${result.endLine}
|
|
6750
6702
|
`;
|
|
@@ -6806,7 +6758,7 @@ async function handleCheckTraceability(input) {
|
|
|
6806
6758
|
isError: true
|
|
6807
6759
|
};
|
|
6808
6760
|
}
|
|
6809
|
-
const { queryTraceability } = await import("./dist-
|
|
6761
|
+
const { queryTraceability } = await import("./dist-BZS2XRLG.js");
|
|
6810
6762
|
const options = {};
|
|
6811
6763
|
if (input.spec) options.specPath = input.spec;
|
|
6812
6764
|
if (input.feature) options.featureName = input.feature;
|
|
@@ -6818,7 +6770,7 @@ async function handleCheckTraceability(input) {
|
|
|
6818
6770
|
type: "text",
|
|
6819
6771
|
text: JSON.stringify({
|
|
6820
6772
|
status: "no-requirements",
|
|
6821
|
-
message: "No requirement nodes found in graph.
|
|
6773
|
+
message: "No requirement nodes found in graph. Run `harness scan` to ingest spec requirements."
|
|
6822
6774
|
})
|
|
6823
6775
|
}
|
|
6824
6776
|
]
|
|
@@ -6929,7 +6881,7 @@ async function handlePredictFailures(input) {
|
|
|
6929
6881
|
};
|
|
6930
6882
|
}
|
|
6931
6883
|
try {
|
|
6932
|
-
const core = await import("./dist-
|
|
6884
|
+
const core = await import("./dist-CPKL5Y2R.js");
|
|
6933
6885
|
const { TimelineManager, PredictionEngine, SpecImpactEstimator } = core;
|
|
6934
6886
|
const manager = new TimelineManager(projectPath);
|
|
6935
6887
|
const includeRoadmap = input.includeRoadmap !== false;
|
|
@@ -7032,12 +6984,12 @@ async function handleRecommendSkills(input) {
|
|
|
7032
6984
|
}
|
|
7033
6985
|
|
|
7034
6986
|
// src/mcp/tools/advise-skills.ts
|
|
7035
|
-
import
|
|
6987
|
+
import path20 from "path";
|
|
7036
6988
|
|
|
7037
6989
|
// src/commands/advise-skills.ts
|
|
7038
6990
|
import { Command as Command2 } from "commander";
|
|
7039
|
-
import
|
|
7040
|
-
import
|
|
6991
|
+
import fs16 from "fs";
|
|
6992
|
+
import path19 from "path";
|
|
7041
6993
|
import chalk from "chalk";
|
|
7042
6994
|
|
|
7043
6995
|
// src/skill/content-matcher-types.ts
|
|
@@ -7556,10 +7508,10 @@ function renderTable(matches) {
|
|
|
7556
7508
|
|
|
7557
7509
|
// src/commands/advise-skills.ts
|
|
7558
7510
|
function readPackageDeps(cwd) {
|
|
7559
|
-
const pkgPath =
|
|
7560
|
-
if (!
|
|
7511
|
+
const pkgPath = path19.join(cwd, "package.json");
|
|
7512
|
+
if (!fs16.existsSync(pkgPath)) return { deps: {}, devDeps: {} };
|
|
7561
7513
|
try {
|
|
7562
|
-
const pkg = JSON.parse(
|
|
7514
|
+
const pkg = JSON.parse(fs16.readFileSync(pkgPath, "utf-8"));
|
|
7563
7515
|
const deps = typeof pkg.dependencies === "object" && pkg.dependencies !== null ? pkg.dependencies : {};
|
|
7564
7516
|
const devDeps = typeof pkg.devDependencies === "object" && pkg.devDependencies !== null ? pkg.devDependencies : {};
|
|
7565
7517
|
return { deps, devDeps };
|
|
@@ -7568,10 +7520,10 @@ function readPackageDeps(cwd) {
|
|
|
7568
7520
|
}
|
|
7569
7521
|
}
|
|
7570
7522
|
function readSpecText(specPath) {
|
|
7571
|
-
if (!
|
|
7523
|
+
if (!fs16.existsSync(specPath)) {
|
|
7572
7524
|
throw new Error(`Spec not found: ${specPath}`);
|
|
7573
7525
|
}
|
|
7574
|
-
return
|
|
7526
|
+
return fs16.readFileSync(specPath, "utf-8");
|
|
7575
7527
|
}
|
|
7576
7528
|
function filterMatchesByTier(result, top, thorough) {
|
|
7577
7529
|
const applySkills = result.matches.filter((m) => m.tier === "apply").slice(0, top);
|
|
@@ -7581,11 +7533,11 @@ function filterMatchesByTier(result, top, thorough) {
|
|
|
7581
7533
|
}
|
|
7582
7534
|
function extractFeatureName(specText, specPath) {
|
|
7583
7535
|
const titleMatch = specText.match(/^#\s+(.+)/m);
|
|
7584
|
-
return titleMatch?.[1] ??
|
|
7536
|
+
return titleMatch?.[1] ?? path19.basename(path19.dirname(specPath));
|
|
7585
7537
|
}
|
|
7586
7538
|
async function runAdviseSkills(options) {
|
|
7587
7539
|
const cwd = options.cwd ?? process.cwd();
|
|
7588
|
-
const specPath =
|
|
7540
|
+
const specPath = path19.resolve(cwd, options.specPath);
|
|
7589
7541
|
const specText = readSpecText(specPath);
|
|
7590
7542
|
const { deps, devDeps } = readPackageDeps(cwd);
|
|
7591
7543
|
const signals = extractSignals(specText, deps, devDeps);
|
|
@@ -7596,9 +7548,9 @@ async function runAdviseSkills(options) {
|
|
|
7596
7548
|
const result = matchContent(index, signals);
|
|
7597
7549
|
const filteredResult = filterMatchesByTier(result, options.top ?? 5, !!options.thorough);
|
|
7598
7550
|
const featureName = extractFeatureName(specText, specPath);
|
|
7599
|
-
const skillsMdPath =
|
|
7551
|
+
const skillsMdPath = path19.join(path19.dirname(specPath), "SKILLS.md");
|
|
7600
7552
|
const md = generateSkillsMd(featureName, filteredResult, totalSkills);
|
|
7601
|
-
|
|
7553
|
+
fs16.writeFileSync(skillsMdPath, md, "utf-8");
|
|
7602
7554
|
return { result: filteredResult, skillsMdPath, featureName, totalSkills };
|
|
7603
7555
|
}
|
|
7604
7556
|
function formatOutput(featureName, result, skillsMdPath, totalSkills) {
|
|
@@ -7692,7 +7644,7 @@ async function handleAdviseSkills(input) {
|
|
|
7692
7644
|
});
|
|
7693
7645
|
const response = {
|
|
7694
7646
|
featureName,
|
|
7695
|
-
skillsPath:
|
|
7647
|
+
skillsPath: path20.relative(projectRoot, skillsMdPath).replaceAll("\\", "/"),
|
|
7696
7648
|
totalScanned: totalSkills,
|
|
7697
7649
|
scanDuration: result.scanDuration,
|
|
7698
7650
|
apply: result.matches.filter((m) => m.tier === "apply").map((m) => ({
|
|
@@ -7812,7 +7764,7 @@ function handleContentMode(content, pipeline, budget, source) {
|
|
|
7812
7764
|
};
|
|
7813
7765
|
}
|
|
7814
7766
|
async function handleIntentMode(projectPath, intent, pipeline, budget, filterContent) {
|
|
7815
|
-
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-
|
|
7767
|
+
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-QEI7SYOQ.js");
|
|
7816
7768
|
const store = await loadGraphStore2(projectPath);
|
|
7817
7769
|
if (!store) {
|
|
7818
7770
|
return {
|
|
@@ -7825,7 +7777,7 @@ async function handleIntentMode(projectPath, intent, pipeline, budget, filterCon
|
|
|
7825
7777
|
isError: true
|
|
7826
7778
|
};
|
|
7827
7779
|
}
|
|
7828
|
-
const { PackedSummaryCache, FusionLayer, ContextQL } = await import("./dist-
|
|
7780
|
+
const { PackedSummaryCache, FusionLayer, ContextQL } = await import("./dist-BZS2XRLG.js");
|
|
7829
7781
|
const cache = new PackedSummaryCache(store);
|
|
7830
7782
|
const cachedEnvelope = cache.get(intent);
|
|
7831
7783
|
if (cachedEnvelope) {
|
|
@@ -8038,7 +7990,7 @@ async function handleDetectConstraintEmergence(input) {
|
|
|
8038
7990
|
}
|
|
8039
7991
|
const nodePath = await import("path");
|
|
8040
7992
|
const historyPath = nodePath.resolve(projectPath, ".harness/arch/violation-history.json");
|
|
8041
|
-
const { ViolationHistoryManager, detectEmergentConstraints } = await import("./dist-
|
|
7993
|
+
const { ViolationHistoryManager, detectEmergentConstraints } = await import("./dist-CPKL5Y2R.js");
|
|
8042
7994
|
const manager = new ViolationHistoryManager(historyPath);
|
|
8043
7995
|
const history = manager.load();
|
|
8044
7996
|
const options = { windowWeeks, minOccurrences };
|
|
@@ -8067,6 +8019,146 @@ async function handleDetectConstraintEmergence(input) {
|
|
|
8067
8019
|
}
|
|
8068
8020
|
}
|
|
8069
8021
|
|
|
8022
|
+
// src/mcp/tools/ci.ts
|
|
8023
|
+
var VALID_CHECKS = [
|
|
8024
|
+
"validate",
|
|
8025
|
+
"deps",
|
|
8026
|
+
"docs",
|
|
8027
|
+
"entropy",
|
|
8028
|
+
"security",
|
|
8029
|
+
"perf",
|
|
8030
|
+
"phase-gate",
|
|
8031
|
+
"arch",
|
|
8032
|
+
"traceability"
|
|
8033
|
+
];
|
|
8034
|
+
var runCIChecksDefinition = {
|
|
8035
|
+
name: "run_ci_checks",
|
|
8036
|
+
description: "Run CI/CD validation checks on a harness project. Returns pass/fail results per check with issues. Checks: validate, deps, docs, entropy, security, perf, phase-gate, arch, traceability.",
|
|
8037
|
+
inputSchema: {
|
|
8038
|
+
type: "object",
|
|
8039
|
+
properties: {
|
|
8040
|
+
path: { type: "string", description: "Path to project root directory" },
|
|
8041
|
+
checks: {
|
|
8042
|
+
type: "array",
|
|
8043
|
+
items: {
|
|
8044
|
+
type: "string",
|
|
8045
|
+
enum: VALID_CHECKS
|
|
8046
|
+
},
|
|
8047
|
+
description: "Subset of checks to run (default: all)"
|
|
8048
|
+
}
|
|
8049
|
+
},
|
|
8050
|
+
required: ["path"]
|
|
8051
|
+
}
|
|
8052
|
+
};
|
|
8053
|
+
async function handleRunCIChecks(input) {
|
|
8054
|
+
let projectPath;
|
|
8055
|
+
try {
|
|
8056
|
+
projectPath = sanitizePath(input.path);
|
|
8057
|
+
} catch (error) {
|
|
8058
|
+
return {
|
|
8059
|
+
content: [
|
|
8060
|
+
{
|
|
8061
|
+
type: "text",
|
|
8062
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
8063
|
+
}
|
|
8064
|
+
],
|
|
8065
|
+
isError: true
|
|
8066
|
+
};
|
|
8067
|
+
}
|
|
8068
|
+
const configResult = resolveProjectConfig(projectPath);
|
|
8069
|
+
if (!configResult.ok) {
|
|
8070
|
+
return {
|
|
8071
|
+
content: [
|
|
8072
|
+
{
|
|
8073
|
+
type: "text",
|
|
8074
|
+
text: `Error: ${configResult.error.message}`
|
|
8075
|
+
}
|
|
8076
|
+
],
|
|
8077
|
+
isError: true
|
|
8078
|
+
};
|
|
8079
|
+
}
|
|
8080
|
+
try {
|
|
8081
|
+
const { runCIChecks } = await import("./dist-CPKL5Y2R.js");
|
|
8082
|
+
const skip = input.checks ? VALID_CHECKS.filter((c) => !input.checks.includes(c)) : [];
|
|
8083
|
+
const result = await runCIChecks({
|
|
8084
|
+
projectRoot: projectPath,
|
|
8085
|
+
config: configResult.value,
|
|
8086
|
+
...skip.length > 0 ? { skip } : {}
|
|
8087
|
+
});
|
|
8088
|
+
if (!result.ok) {
|
|
8089
|
+
return {
|
|
8090
|
+
content: [
|
|
8091
|
+
{
|
|
8092
|
+
type: "text",
|
|
8093
|
+
text: `Error: ${result.error.message}`
|
|
8094
|
+
}
|
|
8095
|
+
],
|
|
8096
|
+
isError: true
|
|
8097
|
+
};
|
|
8098
|
+
}
|
|
8099
|
+
return {
|
|
8100
|
+
content: [{ type: "text", text: JSON.stringify(result.value) }]
|
|
8101
|
+
};
|
|
8102
|
+
} catch (error) {
|
|
8103
|
+
return {
|
|
8104
|
+
content: [
|
|
8105
|
+
{
|
|
8106
|
+
type: "text",
|
|
8107
|
+
text: `Error running CI checks: ${error instanceof Error ? error.message : String(error)}`
|
|
8108
|
+
}
|
|
8109
|
+
],
|
|
8110
|
+
isError: true
|
|
8111
|
+
};
|
|
8112
|
+
}
|
|
8113
|
+
}
|
|
8114
|
+
|
|
8115
|
+
// src/mcp/tools/blueprint.ts
|
|
8116
|
+
var generateBlueprintDefinition = {
|
|
8117
|
+
name: "generate_blueprint",
|
|
8118
|
+
description: "Scan a project and return its blueprint data (modules, hotspots, dependencies). Returns the scan results as JSON without writing files.",
|
|
8119
|
+
inputSchema: {
|
|
8120
|
+
type: "object",
|
|
8121
|
+
properties: {
|
|
8122
|
+
path: { type: "string", description: "Path to project root directory" }
|
|
8123
|
+
},
|
|
8124
|
+
required: ["path"]
|
|
8125
|
+
}
|
|
8126
|
+
};
|
|
8127
|
+
async function handleGenerateBlueprint(input) {
|
|
8128
|
+
let projectPath;
|
|
8129
|
+
try {
|
|
8130
|
+
projectPath = sanitizePath(input.path);
|
|
8131
|
+
} catch (error) {
|
|
8132
|
+
return {
|
|
8133
|
+
content: [
|
|
8134
|
+
{
|
|
8135
|
+
type: "text",
|
|
8136
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
8137
|
+
}
|
|
8138
|
+
],
|
|
8139
|
+
isError: true
|
|
8140
|
+
};
|
|
8141
|
+
}
|
|
8142
|
+
try {
|
|
8143
|
+
const { ProjectScanner } = await import("./dist-CPKL5Y2R.js");
|
|
8144
|
+
const scanner = new ProjectScanner(projectPath);
|
|
8145
|
+
const data = await scanner.scan();
|
|
8146
|
+
return {
|
|
8147
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
8148
|
+
};
|
|
8149
|
+
} catch (error) {
|
|
8150
|
+
return {
|
|
8151
|
+
content: [
|
|
8152
|
+
{
|
|
8153
|
+
type: "text",
|
|
8154
|
+
text: `Error generating blueprint: ${error instanceof Error ? error.message : String(error)}`
|
|
8155
|
+
}
|
|
8156
|
+
],
|
|
8157
|
+
isError: true
|
|
8158
|
+
};
|
|
8159
|
+
}
|
|
8160
|
+
}
|
|
8161
|
+
|
|
8070
8162
|
// src/mcp/server.ts
|
|
8071
8163
|
var TOOL_DEFINITIONS = [
|
|
8072
8164
|
validateToolDefinition,
|
|
@@ -8127,7 +8219,9 @@ var TOOL_DEFINITIONS = [
|
|
|
8127
8219
|
computeBlastRadiusDefinition,
|
|
8128
8220
|
dispatchSkillsDefinition,
|
|
8129
8221
|
compactToolDefinition,
|
|
8130
|
-
detectConstraintEmergenceDefinition
|
|
8222
|
+
detectConstraintEmergenceDefinition,
|
|
8223
|
+
runCIChecksDefinition,
|
|
8224
|
+
generateBlueprintDefinition
|
|
8131
8225
|
].map((def) => ({ ...def, trustedOutput: true }));
|
|
8132
8226
|
var TOOL_HANDLERS = {
|
|
8133
8227
|
validate_project: handleValidateProject,
|
|
@@ -8188,7 +8282,9 @@ var TOOL_HANDLERS = {
|
|
|
8188
8282
|
compute_blast_radius: handleComputeBlastRadius,
|
|
8189
8283
|
dispatch_skills: handleDispatchSkills,
|
|
8190
8284
|
compact: handleCompact,
|
|
8191
|
-
detect_constraint_emergence: handleDetectConstraintEmergence
|
|
8285
|
+
detect_constraint_emergence: handleDetectConstraintEmergence,
|
|
8286
|
+
run_ci_checks: handleRunCIChecks,
|
|
8287
|
+
generate_blueprint: handleGenerateBlueprint
|
|
8192
8288
|
};
|
|
8193
8289
|
var RESOURCE_DEFINITIONS = [
|
|
8194
8290
|
{
|
|
@@ -8290,7 +8386,7 @@ async function appendUpdateNotification(result, resolvedRoot) {
|
|
|
8290
8386
|
shouldRunCheck,
|
|
8291
8387
|
readCheckState,
|
|
8292
8388
|
spawnBackgroundCheck
|
|
8293
|
-
} = await import("./dist-
|
|
8389
|
+
} = await import("./dist-CPKL5Y2R.js");
|
|
8294
8390
|
const { CLI_VERSION } = await import("./version-CUI434OP.js");
|
|
8295
8391
|
const configInterval = readConfigInterval(resolvedRoot);
|
|
8296
8392
|
const DEFAULT_INTERVAL = 864e5;
|
|
@@ -8384,7 +8480,6 @@ async function startServer(toolFilter) {
|
|
|
8384
8480
|
}
|
|
8385
8481
|
|
|
8386
8482
|
export {
|
|
8387
|
-
loadOrRebuildIndex,
|
|
8388
8483
|
createAdviseSkillsCommand,
|
|
8389
8484
|
generateSlashCommands,
|
|
8390
8485
|
handleOrphanDeletion,
|