@harness-engineering/cli 2.4.3 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents-md-KAD3L2NO.js +13 -0
- package/dist/analyzer-VY6DJVOU-NI56JRFK.js +26 -0
- package/dist/{architecture-TUJ2FWM7.js → architecture-OC7TFCFF.js} +7 -4
- package/dist/{assess-project-SIG4QAZA.js → assess-project-ZGMRPTS3.js} +1 -1
- package/dist/bin/harness-mcp.js +20 -17
- package/dist/bin/harness.js +38 -35
- package/dist/{check-phase-gate-JX522QQH.js → check-phase-gate-PD5MVEZT.js} +8 -5
- package/dist/{chunk-O63AAPIZ.js → chunk-2LPUIBVH.js} +75 -1
- package/dist/{chunk-NDTH6MGG.js → chunk-2RNGLYOG.js} +2 -2
- package/dist/{chunk-OOXNZABU.js → chunk-4CWFVEVV.js} +1 -1
- package/dist/{chunk-LA3VGBU6.js → chunk-57TS3UGN.js} +2 -2
- package/dist/{chunk-IWUKWHXV.js → chunk-65MJPWFN.js} +6 -6
- package/dist/{chunk-O7ZZ3FN4.js → chunk-6SRKI77C.js} +3 -3
- package/dist/{chunk-MTJ2LOXB.js → chunk-7DOGGXQU.js} +2 -2
- package/dist/{chunk-54S2MJZI.js → chunk-A3EBWI7U.js} +2 -2
- package/dist/{chunk-JAS63FFQ.js → chunk-DOUS4ULX.js} +6 -6
- package/dist/{chunk-Y2ZVBLOR.js → chunk-ELMV6QU2.js} +2 -2
- package/dist/{chunk-GNZABDPB.js → chunk-HIZXUWWC.js} +8 -6
- package/dist/{chunk-52ATJ5JD.js → chunk-IGBQIXPS.js} +2 -2
- package/dist/chunk-IWRYCUDO.js +3337 -0
- package/dist/{chunk-P542RBCL.js → chunk-IXKGMPMT.js} +2 -2
- package/dist/{chunk-TW4NGPAW.js → chunk-JE5GQVCQ.js} +2 -2
- package/dist/{chunk-5O3PNHUQ.js → chunk-KQ6TDRPS.js} +3932 -7323
- package/dist/{chunk-NDS6XSHS.js → chunk-LT244Y6E.js} +497 -300
- package/dist/{chunk-IPFGVYNC.js → chunk-N6VWCISQ.js} +2 -2
- package/dist/{chunk-URHLDRYH.js → chunk-NOOPJD5R.js} +3 -3
- package/dist/chunk-QCLOIUMX.js +395 -0
- package/dist/{chunk-GDGEFHXV.js → chunk-TCSNO7YW.js} +2 -2
- package/dist/{chunk-AK7T7NG7.js → chunk-UCL3UZIC.js} +779 -274
- package/dist/{chunk-AP73KZP6.js → chunk-UF7BKRH4.js} +4 -4
- package/dist/chunk-XARGEOJV.js +21 -0
- package/dist/{chunk-JDOL6YP7.js → chunk-XIW24BJY.js} +7 -7
- package/dist/{chunk-LZXZQQKP.js → chunk-XSI3RDH6.js} +7 -7
- package/dist/ci-workflow-WAG4TOV6.js +13 -0
- package/dist/{dist-O733ZU6I.js → dist-HVJUGPSY.js} +23 -1
- package/dist/{dist-RYZFURLL.js → dist-TKHVYUWZ.js} +79 -48
- package/dist/{docs-VVCOB35D.js → docs-4WPBYSCF.js} +8 -5
- package/dist/engine-5BXDQT5T.js +13 -0
- package/dist/{entropy-TNA7IRJY.js → entropy-7FIUFACI.js} +6 -3
- package/dist/{feedback-BAVIWDHH.js → feedback-ER2HRTFD.js} +1 -1
- package/dist/{generate-agent-definitions-6UTHCELR.js → generate-agent-definitions-5PV4O3BD.js} +8 -5
- package/dist/index.js +49 -46
- package/dist/loader-6RTEYN5Q.js +15 -0
- package/dist/{mcp-BMCVFQJG.js → mcp-QWSDEYMN.js} +20 -17
- package/dist/{performance-HH7SQOTB.js → performance-AZJAT35R.js} +8 -5
- package/dist/{review-pipeline-QB3AND3K.js → review-pipeline-4VF73V4V.js} +6 -3
- package/dist/runtime-SAZGLILX.js +14 -0
- package/dist/{security-UISVYDES.js → security-ZWRABJNE.js} +1 -1
- package/dist/timeline-manager-FPYKJRHR-VVX7CSGW.js +24 -0
- package/dist/{tool-tiers-QVWKAZX4.js → tool-tiers-LTQNNAFU.js} +7 -2
- package/dist/{validate-QWQMHJFD.js → validate-AFJVI4OX.js} +7 -4
- package/dist/validate-cross-check-7PO7CBVT.js +13 -0
- package/package.json +6 -6
- package/dist/agents-md-WN2DOL7N.js +0 -10
- package/dist/ci-workflow-TIFZJZNY.js +0 -10
- package/dist/engine-AAJLFT45.js +0 -10
- package/dist/loader-TMZCNQWN.js +0 -12
- package/dist/runtime-RITOSII6.js +0 -11
- package/dist/validate-cross-check-3QIA7O4F.js +0 -10
|
@@ -1,12 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getSecurityTrendsDefinition,
|
|
3
|
+
handleGetSecurityTrends,
|
|
4
|
+
handleRunSecurityScan,
|
|
5
|
+
runSecurityScanDefinition
|
|
6
|
+
} from "./chunk-TCSNO7YW.js";
|
|
1
7
|
import {
|
|
2
8
|
handleRunCodeReview,
|
|
3
9
|
runCodeReviewDefinition,
|
|
4
10
|
sortFindingsBySeverity
|
|
5
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-JE5GQVCQ.js";
|
|
6
12
|
import {
|
|
7
13
|
assessProjectDefinition,
|
|
8
14
|
handleAssessProject
|
|
9
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-65MJPWFN.js";
|
|
16
|
+
import {
|
|
17
|
+
detectEntropyDefinition,
|
|
18
|
+
handleDetectEntropy
|
|
19
|
+
} from "./chunk-UF7BKRH4.js";
|
|
20
|
+
import {
|
|
21
|
+
checkPerformanceDefinition,
|
|
22
|
+
getCriticalPathsDefinition,
|
|
23
|
+
getPerfBaselinesDefinition,
|
|
24
|
+
handleCheckPerformance,
|
|
25
|
+
handleGetCriticalPaths,
|
|
26
|
+
handleGetPerfBaselines,
|
|
27
|
+
handleUpdatePerfBaselines,
|
|
28
|
+
updatePerfBaselinesDefinition
|
|
29
|
+
} from "./chunk-XSI3RDH6.js";
|
|
10
30
|
import {
|
|
11
31
|
getBusinessKnowledgeResource
|
|
12
32
|
} from "./chunk-IOW3MW2K.js";
|
|
@@ -17,45 +37,34 @@ import {
|
|
|
17
37
|
handleCreateSelfReview,
|
|
18
38
|
handleRequestPeerReview,
|
|
19
39
|
requestPeerReviewDefinition
|
|
20
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-6SRKI77C.js";
|
|
21
41
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
42
|
+
GENERATED_HEADER_CLAUDE,
|
|
43
|
+
GENERATED_HEADER_CODEX,
|
|
44
|
+
GENERATED_HEADER_CURSOR,
|
|
45
|
+
GENERATED_HEADER_GEMINI,
|
|
46
|
+
VALID_PLATFORMS,
|
|
47
|
+
applySyncPlan,
|
|
48
|
+
computeSyncPlan
|
|
49
|
+
} from "./chunk-3ISINLYT.js";
|
|
27
50
|
import {
|
|
28
51
|
loadGraphStore
|
|
29
52
|
} from "./chunk-5FDBXUFW.js";
|
|
30
53
|
import {
|
|
31
54
|
handleValidateProject,
|
|
32
55
|
validateToolDefinition
|
|
33
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-NOOPJD5R.js";
|
|
34
57
|
import {
|
|
35
58
|
checkDependenciesDefinition,
|
|
36
59
|
handleCheckDependencies
|
|
37
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-2RNGLYOG.js";
|
|
38
61
|
import {
|
|
39
62
|
resolveProjectConfig
|
|
40
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-7DOGGXQU.js";
|
|
41
64
|
import {
|
|
42
65
|
checkDocsDefinition,
|
|
43
66
|
handleCheckDocs
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import {
|
|
46
|
-
detectEntropyDefinition,
|
|
47
|
-
handleDetectEntropy
|
|
48
|
-
} from "./chunk-AP73KZP6.js";
|
|
49
|
-
import {
|
|
50
|
-
checkPerformanceDefinition,
|
|
51
|
-
getCriticalPathsDefinition,
|
|
52
|
-
getPerfBaselinesDefinition,
|
|
53
|
-
handleCheckPerformance,
|
|
54
|
-
handleGetCriticalPaths,
|
|
55
|
-
handleGetPerfBaselines,
|
|
56
|
-
handleUpdatePerfBaselines,
|
|
57
|
-
updatePerfBaselinesDefinition
|
|
58
|
-
} from "./chunk-LZXZQQKP.js";
|
|
67
|
+
} from "./chunk-DOUS4ULX.js";
|
|
59
68
|
import {
|
|
60
69
|
resultToMcpResponse
|
|
61
70
|
} from "./chunk-EPUKTTJZ.js";
|
|
@@ -65,18 +74,6 @@ import {
|
|
|
65
74
|
import {
|
|
66
75
|
loadOrRebuildIndex
|
|
67
76
|
} from "./chunk-27AJKSQY.js";
|
|
68
|
-
import {
|
|
69
|
-
resolveConfig
|
|
70
|
-
} from "./chunk-GNZABDPB.js";
|
|
71
|
-
import {
|
|
72
|
-
GENERATED_HEADER_CLAUDE,
|
|
73
|
-
GENERATED_HEADER_CODEX,
|
|
74
|
-
GENERATED_HEADER_CURSOR,
|
|
75
|
-
GENERATED_HEADER_GEMINI,
|
|
76
|
-
VALID_PLATFORMS,
|
|
77
|
-
applySyncPlan,
|
|
78
|
-
computeSyncPlan
|
|
79
|
-
} from "./chunk-3ISINLYT.js";
|
|
80
77
|
import {
|
|
81
78
|
resolveCommunitySkillsDir,
|
|
82
79
|
resolveGlobalCommunitySkillsDir,
|
|
@@ -86,6 +83,20 @@ import {
|
|
|
86
83
|
resolveSkillsDir,
|
|
87
84
|
resolveTemplatesDir
|
|
88
85
|
} from "./chunk-6B6UN6SG.js";
|
|
86
|
+
import {
|
|
87
|
+
SkillMetadataSchema
|
|
88
|
+
} from "./chunk-HIK6OEUF.js";
|
|
89
|
+
import {
|
|
90
|
+
resolveConfig
|
|
91
|
+
} from "./chunk-HIZXUWWC.js";
|
|
92
|
+
import {
|
|
93
|
+
logger
|
|
94
|
+
} from "./chunk-EBJQ6N4M.js";
|
|
95
|
+
import {
|
|
96
|
+
CLIError,
|
|
97
|
+
ExitCode,
|
|
98
|
+
handleError
|
|
99
|
+
} from "./chunk-3WGJMBKH.js";
|
|
89
100
|
import {
|
|
90
101
|
CompactionPipeline,
|
|
91
102
|
ConflictError,
|
|
@@ -99,7 +110,7 @@ import {
|
|
|
99
110
|
detectChangeType,
|
|
100
111
|
estimateTokens,
|
|
101
112
|
extractLevel,
|
|
102
|
-
init_dist,
|
|
113
|
+
init_dist as init_dist2,
|
|
103
114
|
loadProjectRoadmapMode,
|
|
104
115
|
loadTrackerClientConfigFromProject,
|
|
105
116
|
loadTrackerSyncConfig,
|
|
@@ -107,22 +118,14 @@ import {
|
|
|
107
118
|
scanForInjection,
|
|
108
119
|
serializeEnvelope,
|
|
109
120
|
writeTaint
|
|
110
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-KQ6TDRPS.js";
|
|
111
122
|
import {
|
|
112
123
|
Err,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
} from "./chunk-
|
|
118
|
-
import {
|
|
119
|
-
logger
|
|
120
|
-
} from "./chunk-EBJQ6N4M.js";
|
|
121
|
-
import {
|
|
122
|
-
CLIError,
|
|
123
|
-
ExitCode,
|
|
124
|
-
handleError
|
|
125
|
-
} from "./chunk-3WGJMBKH.js";
|
|
124
|
+
INDEXED_FILE_KINDS,
|
|
125
|
+
INSIGHTS_KEYS,
|
|
126
|
+
Ok,
|
|
127
|
+
init_dist
|
|
128
|
+
} from "./chunk-2LPUIBVH.js";
|
|
126
129
|
|
|
127
130
|
// src/mcp/server.ts
|
|
128
131
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -316,6 +319,13 @@ events.jsonl
|
|
|
316
319
|
telemetry.json
|
|
317
320
|
.telemetry-notice-shown
|
|
318
321
|
|
|
322
|
+
# Phase 3 webhook delivery queue \u2014 SQLite runtime DB (and WAL/SHM sidecars)
|
|
323
|
+
webhook-queue.sqlite
|
|
324
|
+
webhook-queue.sqlite-wal
|
|
325
|
+
webhook-queue.sqlite-shm
|
|
326
|
+
# Maintenance task run history (regenerated each tick)
|
|
327
|
+
maintenance/
|
|
328
|
+
|
|
319
329
|
# security/: track timeline.json (trend ledger), ignore everything else
|
|
320
330
|
security/*
|
|
321
331
|
!security/timeline.json
|
|
@@ -338,7 +348,7 @@ function appendFrameworkAgents(targetDir, framework, language) {
|
|
|
338
348
|
}
|
|
339
349
|
|
|
340
350
|
// src/mcp/middleware/injection-guard.ts
|
|
341
|
-
|
|
351
|
+
init_dist2();
|
|
342
352
|
import { realpathSync } from "fs";
|
|
343
353
|
import { resolve } from "path";
|
|
344
354
|
function isDestructiveBash(command) {
|
|
@@ -459,7 +469,7 @@ function applyInjectionGuard(handlers, options = {}) {
|
|
|
459
469
|
}
|
|
460
470
|
|
|
461
471
|
// src/mcp/middleware/compaction.ts
|
|
462
|
-
|
|
472
|
+
init_dist2();
|
|
463
473
|
var DEFAULT_PIPELINE = new CompactionPipeline([
|
|
464
474
|
new StructuralStrategy(),
|
|
465
475
|
new TruncationStrategy()
|
|
@@ -546,6 +556,185 @@ function applyCompaction(handlers) {
|
|
|
546
556
|
return wrapped;
|
|
547
557
|
}
|
|
548
558
|
|
|
559
|
+
// src/mcp/tools/search-sessions.ts
|
|
560
|
+
init_dist2();
|
|
561
|
+
init_dist();
|
|
562
|
+
var searchSessionsDefinition = {
|
|
563
|
+
name: "search_sessions",
|
|
564
|
+
description: "Full-text search over archived + live session content (Hermes Phase 1, FTS5/BM25).",
|
|
565
|
+
inputSchema: {
|
|
566
|
+
type: "object",
|
|
567
|
+
properties: {
|
|
568
|
+
path: { type: "string", description: "Path to project root" },
|
|
569
|
+
query: { type: "string", description: "FTS5 query (bare words AND-joined)" },
|
|
570
|
+
limit: { type: "number", description: "Max results (default 20)" },
|
|
571
|
+
archivedOnly: {
|
|
572
|
+
type: "boolean",
|
|
573
|
+
description: "Only search archived sessions (skip live)."
|
|
574
|
+
},
|
|
575
|
+
fileKinds: {
|
|
576
|
+
type: "array",
|
|
577
|
+
items: { type: "string", enum: INDEXED_FILE_KINDS },
|
|
578
|
+
description: "Subset of file kinds to search."
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
required: ["path", "query"]
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
async function handleSearchSessions(input) {
|
|
585
|
+
try {
|
|
586
|
+
const pathInput = typeof input.path === "string" ? input.path : "";
|
|
587
|
+
const projectPath = sanitizePath(pathInput);
|
|
588
|
+
const query = typeof input.query === "string" ? input.query : "";
|
|
589
|
+
if (!query || query.trim() === "") {
|
|
590
|
+
return resultToMcpResponse(Err({ message: "query is required" }));
|
|
591
|
+
}
|
|
592
|
+
const limit = typeof input.limit === "number" ? input.limit : void 0;
|
|
593
|
+
const archivedOnly = input.archivedOnly === true;
|
|
594
|
+
const fileKinds = Array.isArray(input.fileKinds) ? input.fileKinds.filter(
|
|
595
|
+
(k) => typeof k === "string" && INDEXED_FILE_KINDS.includes(k)
|
|
596
|
+
) : void 0;
|
|
597
|
+
const orchestrator = await import("@harness-engineering/orchestrator");
|
|
598
|
+
const idx = orchestrator.openSearchIndex(projectPath);
|
|
599
|
+
try {
|
|
600
|
+
const result = idx.search(query, {
|
|
601
|
+
...limit !== void 0 && { limit },
|
|
602
|
+
...archivedOnly && { archivedOnly },
|
|
603
|
+
...fileKinds && fileKinds.length > 0 && { fileKinds }
|
|
604
|
+
});
|
|
605
|
+
return resultToMcpResponse(Ok(result));
|
|
606
|
+
} finally {
|
|
607
|
+
idx.close();
|
|
608
|
+
}
|
|
609
|
+
} catch (e) {
|
|
610
|
+
return resultToMcpResponse(Err({ message: e instanceof Error ? e.message : String(e) }));
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// src/mcp/tools/summarize-session.ts
|
|
615
|
+
init_dist2();
|
|
616
|
+
import * as fs2 from "fs";
|
|
617
|
+
import * as path2 from "path";
|
|
618
|
+
var summarizeSessionDefinition = {
|
|
619
|
+
name: "summarize_session",
|
|
620
|
+
description: "Generate or regenerate the LLM `llm-summary.md` for an archived session (Hermes Phase 1).",
|
|
621
|
+
inputSchema: {
|
|
622
|
+
type: "object",
|
|
623
|
+
properties: {
|
|
624
|
+
path: { type: "string", description: "Path to project root" },
|
|
625
|
+
sessionId: {
|
|
626
|
+
type: "string",
|
|
627
|
+
description: "Archived session id (basename of the directory inside .harness/archive/sessions/)"
|
|
628
|
+
},
|
|
629
|
+
force: {
|
|
630
|
+
type: "boolean",
|
|
631
|
+
description: "If true, overwrite an existing llm-summary.md. Default: false (no-op when present)."
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
required: ["path", "sessionId"]
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
async function resolveAnthropicProvider() {
|
|
638
|
+
try {
|
|
639
|
+
const intelligence = await import("@harness-engineering/intelligence");
|
|
640
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
641
|
+
if (!apiKey) return null;
|
|
642
|
+
const Provider = intelligence.AnthropicAnalysisProvider;
|
|
643
|
+
if (typeof Provider !== "function") return null;
|
|
644
|
+
return new Provider({ apiKey });
|
|
645
|
+
} catch {
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
async function handleSummarizeSession(input) {
|
|
650
|
+
try {
|
|
651
|
+
const pathInput = typeof input.path === "string" ? input.path : "";
|
|
652
|
+
const projectPath = sanitizePath(pathInput);
|
|
653
|
+
const sessionId = typeof input.sessionId === "string" ? input.sessionId : "";
|
|
654
|
+
if (!sessionId) {
|
|
655
|
+
return resultToMcpResponse(Err({ message: "sessionId is required" }));
|
|
656
|
+
}
|
|
657
|
+
const force = input.force === true;
|
|
658
|
+
const archiveDir = path2.join(projectPath, ".harness", "archive", "sessions", sessionId);
|
|
659
|
+
if (!fs2.existsSync(archiveDir)) {
|
|
660
|
+
return resultToMcpResponse(Err({ message: `archived session not found: ${sessionId}` }));
|
|
661
|
+
}
|
|
662
|
+
const llmSummary = path2.join(archiveDir, "llm-summary.md");
|
|
663
|
+
if (fs2.existsSync(llmSummary) && !force) {
|
|
664
|
+
return resultToMcpResponse(
|
|
665
|
+
Ok({
|
|
666
|
+
sessionId,
|
|
667
|
+
status: "exists",
|
|
668
|
+
filePath: llmSummary
|
|
669
|
+
})
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
const provider = await resolveAnthropicProvider();
|
|
673
|
+
if (!provider) {
|
|
674
|
+
return resultToMcpResponse(
|
|
675
|
+
Err({
|
|
676
|
+
message: "No analysis provider configured. Set ANTHROPIC_API_KEY to enable session summarization."
|
|
677
|
+
})
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
const { summarizeArchivedSession } = await import("@harness-engineering/orchestrator");
|
|
681
|
+
const result = await summarizeArchivedSession({
|
|
682
|
+
archiveDir,
|
|
683
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
684
|
+
provider
|
|
685
|
+
});
|
|
686
|
+
if (!result.ok) {
|
|
687
|
+
return resultToMcpResponse(Err({ message: result.error.message }));
|
|
688
|
+
}
|
|
689
|
+
return resultToMcpResponse(
|
|
690
|
+
Ok({
|
|
691
|
+
sessionId,
|
|
692
|
+
status: "wrote",
|
|
693
|
+
filePath: result.value.filePath,
|
|
694
|
+
meta: result.value.meta
|
|
695
|
+
})
|
|
696
|
+
);
|
|
697
|
+
} catch (e) {
|
|
698
|
+
return resultToMcpResponse(Err({ message: e instanceof Error ? e.message : String(e) }));
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/mcp/tools/insights-summary.ts
|
|
703
|
+
init_dist2();
|
|
704
|
+
init_dist();
|
|
705
|
+
var insightsSummaryDefinition = {
|
|
706
|
+
name: "insights_summary",
|
|
707
|
+
description: "Composite report combining health, entropy, decay, attention, and impact (Hermes Phase 1).",
|
|
708
|
+
inputSchema: {
|
|
709
|
+
type: "object",
|
|
710
|
+
properties: {
|
|
711
|
+
path: { type: "string", description: "Path to project root" },
|
|
712
|
+
skip: {
|
|
713
|
+
type: "array",
|
|
714
|
+
items: { type: "string", enum: INSIGHTS_KEYS },
|
|
715
|
+
description: "Top-level keys to skip."
|
|
716
|
+
}
|
|
717
|
+
},
|
|
718
|
+
required: ["path"]
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
async function handleInsightsSummary(input) {
|
|
722
|
+
try {
|
|
723
|
+
const pathInput = typeof input.path === "string" ? input.path : "";
|
|
724
|
+
const projectPath = sanitizePath(pathInput);
|
|
725
|
+
const skip = Array.isArray(input.skip) ? input.skip.filter(
|
|
726
|
+
(k) => typeof k === "string" && INSIGHTS_KEYS.includes(k)
|
|
727
|
+
) : void 0;
|
|
728
|
+
const { composeInsights } = await import("./dist-TKHVYUWZ.js");
|
|
729
|
+
const report = await composeInsights(projectPath, {
|
|
730
|
+
...skip && skip.length > 0 && { skip }
|
|
731
|
+
});
|
|
732
|
+
return resultToMcpResponse(Ok(report));
|
|
733
|
+
} catch (e) {
|
|
734
|
+
return resultToMcpResponse(Err({ message: e instanceof Error ? e.message : String(e) }));
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
549
738
|
// src/mcp/tools/linter.ts
|
|
550
739
|
var generateLinterDefinition = {
|
|
551
740
|
name: "generate_linter",
|
|
@@ -615,8 +804,8 @@ async function handleValidateLinterConfig(input) {
|
|
|
615
804
|
}
|
|
616
805
|
|
|
617
806
|
// src/mcp/tools/init.ts
|
|
618
|
-
import * as
|
|
619
|
-
import * as
|
|
807
|
+
import * as path3 from "path";
|
|
808
|
+
import * as fs3 from "fs";
|
|
620
809
|
var initProjectDefinition = {
|
|
621
810
|
name: "init_project",
|
|
622
811
|
description: "Scaffold a new harness engineering project from a template",
|
|
@@ -649,7 +838,7 @@ function findFrameworkLanguage(engine, framework) {
|
|
|
649
838
|
return templates.value.find((t) => t.framework === framework)?.language;
|
|
650
839
|
}
|
|
651
840
|
function tryDetectFramework(engine, safePath, input) {
|
|
652
|
-
if (input.framework || input.language || !
|
|
841
|
+
if (input.framework || input.language || !fs3.existsSync(safePath)) return null;
|
|
653
842
|
const result = engine.detectFramework(safePath);
|
|
654
843
|
if (!result.ok || !result.value || result.value.length === 0) return null;
|
|
655
844
|
const candidates = result.value.map((c) => `${c.framework} (${c.language}, score: ${c.score})`).join(", ");
|
|
@@ -681,7 +870,7 @@ function scaffoldMcp(engine, safePath, i, language) {
|
|
|
681
870
|
const resolveResult = engine.resolveTemplate(level, i.framework, language);
|
|
682
871
|
if (!resolveResult.ok) return resultToMcpResponse(resolveResult);
|
|
683
872
|
const renderResult = engine.render(resolveResult.value, {
|
|
684
|
-
projectName: i.name ??
|
|
873
|
+
projectName: i.name ?? path3.basename(safePath),
|
|
685
874
|
level: level ?? "",
|
|
686
875
|
...i.framework !== void 0 && { framework: i.framework },
|
|
687
876
|
...language !== void 0 && { language }
|
|
@@ -712,7 +901,7 @@ ${skippedMsg}`
|
|
|
712
901
|
async function handleInitProject(input) {
|
|
713
902
|
const i = input;
|
|
714
903
|
try {
|
|
715
|
-
const { TemplateEngine } = await import("./engine-
|
|
904
|
+
const { TemplateEngine } = await import("./engine-5BXDQT5T.js");
|
|
716
905
|
const engine = new TemplateEngine(resolveTemplatesDir());
|
|
717
906
|
const safePath = sanitizePath(i.path);
|
|
718
907
|
const detected = tryDetectFramework(engine, safePath, i);
|
|
@@ -726,15 +915,15 @@ async function handleInitProject(input) {
|
|
|
726
915
|
}
|
|
727
916
|
|
|
728
917
|
// src/mcp/tools/persona.ts
|
|
729
|
-
|
|
730
|
-
import * as
|
|
918
|
+
init_dist2();
|
|
919
|
+
import * as path4 from "path";
|
|
731
920
|
var listPersonasDefinition = {
|
|
732
921
|
name: "list_personas",
|
|
733
922
|
description: "List available agent personas",
|
|
734
923
|
inputSchema: { type: "object", properties: {} }
|
|
735
924
|
};
|
|
736
925
|
async function handleListPersonas() {
|
|
737
|
-
const { listPersonas } = await import("./loader-
|
|
926
|
+
const { listPersonas } = await import("./loader-6RTEYN5Q.js");
|
|
738
927
|
const result = listPersonas(resolvePersonasDir());
|
|
739
928
|
return resultToMcpResponse(result);
|
|
740
929
|
}
|
|
@@ -758,12 +947,12 @@ async function handleGeneratePersonaArtifacts(input) {
|
|
|
758
947
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.name)) {
|
|
759
948
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.name}`)));
|
|
760
949
|
}
|
|
761
|
-
const { loadPersona } = await import("./loader-
|
|
762
|
-
const { generateRuntime } = await import("./runtime-
|
|
763
|
-
const { generateAgentsMd } = await import("./agents-md-
|
|
764
|
-
const { generateCIWorkflow } = await import("./ci-workflow-
|
|
950
|
+
const { loadPersona } = await import("./loader-6RTEYN5Q.js");
|
|
951
|
+
const { generateRuntime } = await import("./runtime-SAZGLILX.js");
|
|
952
|
+
const { generateAgentsMd } = await import("./agents-md-KAD3L2NO.js");
|
|
953
|
+
const { generateCIWorkflow } = await import("./ci-workflow-WAG4TOV6.js");
|
|
765
954
|
const personasDir = resolvePersonasDir();
|
|
766
|
-
const filePath =
|
|
955
|
+
const filePath = path4.join(personasDir, `${input.name}.yaml`);
|
|
767
956
|
if (!filePath.startsWith(personasDir)) {
|
|
768
957
|
return resultToMcpResponse(Err(new Error(`Invalid persona path: ${input.name}`)));
|
|
769
958
|
}
|
|
@@ -816,11 +1005,11 @@ async function handleRunPersona(input) {
|
|
|
816
1005
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.persona)) {
|
|
817
1006
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.persona}`)));
|
|
818
1007
|
}
|
|
819
|
-
const { loadPersona } = await import("./loader-
|
|
1008
|
+
const { loadPersona } = await import("./loader-6RTEYN5Q.js");
|
|
820
1009
|
const { runPersona } = await import("./runner-AAEF2TXY.js");
|
|
821
1010
|
const { executeSkill } = await import("./skill-executor-MOCUIAYS.js");
|
|
822
1011
|
const personasDir = resolvePersonasDir();
|
|
823
|
-
const filePath =
|
|
1012
|
+
const filePath = path4.join(personasDir, `${input.persona}.yaml`);
|
|
824
1013
|
if (!filePath.startsWith(personasDir)) {
|
|
825
1014
|
return resultToMcpResponse(Err(new Error(`Invalid persona path: ${input.persona}`)));
|
|
826
1015
|
}
|
|
@@ -982,9 +1171,9 @@ async function handleRunAgentTask(input) {
|
|
|
982
1171
|
}
|
|
983
1172
|
|
|
984
1173
|
// src/mcp/tools/skill.ts
|
|
985
|
-
|
|
986
|
-
import * as
|
|
987
|
-
import * as
|
|
1174
|
+
init_dist2();
|
|
1175
|
+
import * as fs5 from "fs";
|
|
1176
|
+
import * as path6 from "path";
|
|
988
1177
|
import { parse as parseYaml } from "yaml";
|
|
989
1178
|
|
|
990
1179
|
// src/skill/dispatcher.ts
|
|
@@ -1171,8 +1360,8 @@ function formatSuggestions(suggestions) {
|
|
|
1171
1360
|
}
|
|
1172
1361
|
|
|
1173
1362
|
// src/skill/stack-profile.ts
|
|
1174
|
-
import
|
|
1175
|
-
import
|
|
1363
|
+
import fs4 from "fs";
|
|
1364
|
+
import path5 from "path";
|
|
1176
1365
|
var SIGNAL_DOMAIN_MAP = {
|
|
1177
1366
|
"prisma/schema.prisma": ["database"],
|
|
1178
1367
|
"drizzle.config.ts": ["database"],
|
|
@@ -1231,8 +1420,8 @@ function generateStackProfile(projectRoot) {
|
|
|
1231
1420
|
const signals = {};
|
|
1232
1421
|
const domainSet = /* @__PURE__ */ new Set();
|
|
1233
1422
|
for (const [pattern, domains] of Object.entries(SIGNAL_DOMAIN_MAP)) {
|
|
1234
|
-
const fullPath =
|
|
1235
|
-
const exists =
|
|
1423
|
+
const fullPath = path5.join(projectRoot, pattern);
|
|
1424
|
+
const exists = fs4.existsSync(fullPath);
|
|
1236
1425
|
signals[pattern] = exists;
|
|
1237
1426
|
if (exists) {
|
|
1238
1427
|
for (const domain of domains) domainSet.add(domain);
|
|
@@ -1245,23 +1434,23 @@ function generateStackProfile(projectRoot) {
|
|
|
1245
1434
|
};
|
|
1246
1435
|
}
|
|
1247
1436
|
function loadOrGenerateProfile(projectRoot) {
|
|
1248
|
-
const profilePath =
|
|
1249
|
-
if (
|
|
1437
|
+
const profilePath = path5.join(projectRoot, ".harness", "stack-profile.json");
|
|
1438
|
+
if (fs4.existsSync(profilePath)) {
|
|
1250
1439
|
try {
|
|
1251
|
-
return JSON.parse(
|
|
1440
|
+
return JSON.parse(fs4.readFileSync(profilePath, "utf-8"));
|
|
1252
1441
|
} catch {
|
|
1253
1442
|
}
|
|
1254
1443
|
}
|
|
1255
1444
|
const profile = generateStackProfile(projectRoot);
|
|
1256
|
-
|
|
1257
|
-
|
|
1445
|
+
fs4.mkdirSync(path5.dirname(profilePath), { recursive: true });
|
|
1446
|
+
fs4.writeFileSync(profilePath, JSON.stringify(profile, null, 2));
|
|
1258
1447
|
return profile;
|
|
1259
1448
|
}
|
|
1260
1449
|
|
|
1261
1450
|
// src/mcp/tools/event-emitter.ts
|
|
1262
1451
|
async function emitSkillEvent(projectPath, event) {
|
|
1263
1452
|
try {
|
|
1264
|
-
const { emitEvent } = await import("./dist-
|
|
1453
|
+
const { emitEvent } = await import("./dist-TKHVYUWZ.js");
|
|
1265
1454
|
await emitEvent(projectPath, event);
|
|
1266
1455
|
} catch {
|
|
1267
1456
|
}
|
|
@@ -1296,18 +1485,18 @@ async function handleRunSkill(input) {
|
|
|
1296
1485
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.skill)) {
|
|
1297
1486
|
return resultToMcpResponse(Err(new Error(`Invalid skill name: ${input.skill}`)));
|
|
1298
1487
|
}
|
|
1299
|
-
const skillDir =
|
|
1488
|
+
const skillDir = path6.join(skillsDir, input.skill);
|
|
1300
1489
|
if (!skillDir.startsWith(skillsDir)) {
|
|
1301
1490
|
return resultToMcpResponse(Err(new Error(`Invalid skill path: ${input.skill}`)));
|
|
1302
1491
|
}
|
|
1303
|
-
if (!
|
|
1492
|
+
if (!fs5.existsSync(skillDir)) {
|
|
1304
1493
|
return resultToMcpResponse(Err(new Error(`Skill not found: ${input.skill}`)));
|
|
1305
1494
|
}
|
|
1306
|
-
const skillMdPath =
|
|
1307
|
-
if (!
|
|
1495
|
+
const skillMdPath = path6.join(skillDir, "SKILL.md");
|
|
1496
|
+
if (!fs5.existsSync(skillMdPath)) {
|
|
1308
1497
|
return resultToMcpResponse(Err(new Error(`SKILL.md not found for skill: ${input.skill}`)));
|
|
1309
1498
|
}
|
|
1310
|
-
let content =
|
|
1499
|
+
let content = fs5.readFileSync(skillMdPath, "utf-8");
|
|
1311
1500
|
const projectRoot = input.path ? sanitizePath(input.path) : process.cwd();
|
|
1312
1501
|
const configResult = resolveConfig();
|
|
1313
1502
|
const skillsConfig = configResult.ok ? configResult.value.skills : void 0;
|
|
@@ -1334,9 +1523,9 @@ async function handleRunSkill(input) {
|
|
|
1334
1523
|
}
|
|
1335
1524
|
if (input.path) {
|
|
1336
1525
|
const projectPath = sanitizePath(input.path);
|
|
1337
|
-
const stateFile =
|
|
1338
|
-
if (
|
|
1339
|
-
const stateContent =
|
|
1526
|
+
const stateFile = path6.join(projectPath, ".harness", "state.json");
|
|
1527
|
+
if (fs5.existsSync(stateFile)) {
|
|
1528
|
+
const stateContent = fs5.readFileSync(stateFile, "utf-8");
|
|
1340
1529
|
content += `
|
|
1341
1530
|
|
|
1342
1531
|
---
|
|
@@ -1347,10 +1536,10 @@ ${stateContent}
|
|
|
1347
1536
|
`;
|
|
1348
1537
|
}
|
|
1349
1538
|
}
|
|
1350
|
-
const skillYamlPath =
|
|
1351
|
-
if (
|
|
1539
|
+
const skillYamlPath = path6.join(skillDir, "skill.yaml");
|
|
1540
|
+
if (fs5.existsSync(skillYamlPath)) {
|
|
1352
1541
|
try {
|
|
1353
|
-
const rawYaml =
|
|
1542
|
+
const rawYaml = fs5.readFileSync(skillYamlPath, "utf-8");
|
|
1354
1543
|
const skillMeta = parseYaml(rawYaml);
|
|
1355
1544
|
if (skillMeta.type === "knowledge") {
|
|
1356
1545
|
const boundary = content.indexOf("\n## Details");
|
|
@@ -1433,22 +1622,22 @@ async function handleCreateSkill(input) {
|
|
|
1433
1622
|
}
|
|
1434
1623
|
|
|
1435
1624
|
// src/mcp/resources/skills.ts
|
|
1436
|
-
import * as
|
|
1437
|
-
import * as
|
|
1625
|
+
import * as fs6 from "fs";
|
|
1626
|
+
import * as path7 from "path";
|
|
1438
1627
|
import * as yaml from "yaml";
|
|
1439
1628
|
async function getSkillsResource(projectRoot) {
|
|
1440
|
-
const skillsDir =
|
|
1629
|
+
const skillsDir = path7.join(projectRoot, "agents", "skills", "claude-code");
|
|
1441
1630
|
const skills = [];
|
|
1442
|
-
if (!
|
|
1631
|
+
if (!fs6.existsSync(skillsDir)) {
|
|
1443
1632
|
return JSON.stringify(skills, null, 2);
|
|
1444
1633
|
}
|
|
1445
|
-
const entries =
|
|
1634
|
+
const entries = fs6.readdirSync(skillsDir, { withFileTypes: true });
|
|
1446
1635
|
for (const entry of entries) {
|
|
1447
1636
|
if (!entry.isDirectory()) continue;
|
|
1448
|
-
const skillYamlPath =
|
|
1449
|
-
if (!
|
|
1637
|
+
const skillYamlPath = path7.join(skillsDir, entry.name, "skill.yaml");
|
|
1638
|
+
if (!fs6.existsSync(skillYamlPath)) continue;
|
|
1450
1639
|
try {
|
|
1451
|
-
const content =
|
|
1640
|
+
const content = fs6.readFileSync(skillYamlPath, "utf-8");
|
|
1452
1641
|
const parsed = yaml.parse(content);
|
|
1453
1642
|
skills.push({
|
|
1454
1643
|
name: parsed.name,
|
|
@@ -1464,14 +1653,14 @@ async function getSkillsResource(projectRoot) {
|
|
|
1464
1653
|
}
|
|
1465
1654
|
|
|
1466
1655
|
// src/mcp/resources/rules.ts
|
|
1467
|
-
import * as
|
|
1468
|
-
import * as
|
|
1656
|
+
import * as fs7 from "fs";
|
|
1657
|
+
import * as path8 from "path";
|
|
1469
1658
|
async function getRulesResource(projectRoot) {
|
|
1470
1659
|
const rules = [];
|
|
1471
|
-
const configPath =
|
|
1472
|
-
if (
|
|
1660
|
+
const configPath = path8.join(projectRoot, "harness.config.json");
|
|
1661
|
+
if (fs7.existsSync(configPath)) {
|
|
1473
1662
|
try {
|
|
1474
|
-
const config = JSON.parse(
|
|
1663
|
+
const config = JSON.parse(fs7.readFileSync(configPath, "utf-8"));
|
|
1475
1664
|
if (config.layers) {
|
|
1476
1665
|
rules.push({ type: "layer-enforcement", config: config.layers });
|
|
1477
1666
|
}
|
|
@@ -1484,10 +1673,10 @@ async function getRulesResource(projectRoot) {
|
|
|
1484
1673
|
} catch {
|
|
1485
1674
|
}
|
|
1486
1675
|
}
|
|
1487
|
-
const linterPath =
|
|
1488
|
-
if (
|
|
1676
|
+
const linterPath = path8.join(projectRoot, ".harness", "linter.json");
|
|
1677
|
+
if (fs7.existsSync(linterPath)) {
|
|
1489
1678
|
try {
|
|
1490
|
-
const linterConfig = JSON.parse(
|
|
1679
|
+
const linterConfig = JSON.parse(fs7.readFileSync(linterPath, "utf-8"));
|
|
1491
1680
|
rules.push({ type: "linter", config: linterConfig });
|
|
1492
1681
|
} catch {
|
|
1493
1682
|
}
|
|
@@ -1496,45 +1685,45 @@ async function getRulesResource(projectRoot) {
|
|
|
1496
1685
|
}
|
|
1497
1686
|
|
|
1498
1687
|
// src/mcp/resources/project.ts
|
|
1499
|
-
import * as
|
|
1500
|
-
import * as
|
|
1688
|
+
import * as fs8 from "fs";
|
|
1689
|
+
import * as path9 from "path";
|
|
1501
1690
|
async function getProjectResource(projectRoot) {
|
|
1502
|
-
const agentsPath =
|
|
1503
|
-
if (
|
|
1504
|
-
return
|
|
1691
|
+
const agentsPath = path9.join(projectRoot, "AGENTS.md");
|
|
1692
|
+
if (fs8.existsSync(agentsPath)) {
|
|
1693
|
+
return fs8.readFileSync(agentsPath, "utf-8");
|
|
1505
1694
|
}
|
|
1506
1695
|
return "# No AGENTS.md found";
|
|
1507
1696
|
}
|
|
1508
1697
|
|
|
1509
1698
|
// src/mcp/resources/learnings.ts
|
|
1510
|
-
import * as
|
|
1511
|
-
import * as
|
|
1699
|
+
import * as fs9 from "fs";
|
|
1700
|
+
import * as path10 from "path";
|
|
1512
1701
|
async function getLearningsResource(projectRoot) {
|
|
1513
1702
|
const sections = [];
|
|
1514
|
-
const reviewPath =
|
|
1515
|
-
if (
|
|
1516
|
-
sections.push("## Review Learnings\n\n" +
|
|
1703
|
+
const reviewPath = path10.join(projectRoot, ".harness", "review-learnings.md");
|
|
1704
|
+
if (fs9.existsSync(reviewPath)) {
|
|
1705
|
+
sections.push("## Review Learnings\n\n" + fs9.readFileSync(reviewPath, "utf-8"));
|
|
1517
1706
|
}
|
|
1518
|
-
const antiPath =
|
|
1519
|
-
if (
|
|
1520
|
-
sections.push("## Anti-Pattern Log\n\n" +
|
|
1707
|
+
const antiPath = path10.join(projectRoot, ".harness", "anti-patterns.md");
|
|
1708
|
+
if (fs9.existsSync(antiPath)) {
|
|
1709
|
+
sections.push("## Anti-Pattern Log\n\n" + fs9.readFileSync(antiPath, "utf-8"));
|
|
1521
1710
|
}
|
|
1522
1711
|
return sections.length > 0 ? sections.join("\n\n---\n\n") : "No learnings files found.";
|
|
1523
1712
|
}
|
|
1524
1713
|
|
|
1525
1714
|
// src/mcp/tools/state.ts
|
|
1526
|
-
|
|
1715
|
+
init_dist2();
|
|
1527
1716
|
|
|
1528
1717
|
// src/mcp/tools/roadmap-auto-sync.ts
|
|
1529
|
-
|
|
1530
|
-
import * as
|
|
1531
|
-
import * as
|
|
1718
|
+
init_dist2();
|
|
1719
|
+
import * as fs10 from "fs";
|
|
1720
|
+
import * as path11 from "path";
|
|
1532
1721
|
async function autoSyncRoadmap(projectPath) {
|
|
1533
1722
|
try {
|
|
1534
|
-
const roadmapFile =
|
|
1535
|
-
if (!
|
|
1536
|
-
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges } = await import("./dist-
|
|
1537
|
-
const raw =
|
|
1723
|
+
const roadmapFile = path11.join(projectPath, "docs", "roadmap.md");
|
|
1724
|
+
if (!fs10.existsSync(roadmapFile)) return;
|
|
1725
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges } = await import("./dist-TKHVYUWZ.js");
|
|
1726
|
+
const raw = fs10.readFileSync(roadmapFile, "utf-8");
|
|
1538
1727
|
const parseResult = parseRoadmap(raw);
|
|
1539
1728
|
if (!parseResult.ok) return;
|
|
1540
1729
|
const roadmap = parseResult.value;
|
|
@@ -1544,7 +1733,7 @@ async function autoSyncRoadmap(projectPath) {
|
|
|
1544
1733
|
return;
|
|
1545
1734
|
}
|
|
1546
1735
|
applySyncChanges(roadmap, syncResult.value);
|
|
1547
|
-
|
|
1736
|
+
fs10.writeFileSync(roadmapFile, serializeRoadmap(roadmap), "utf-8");
|
|
1548
1737
|
await triggerExternalSync(projectPath, roadmapFile);
|
|
1549
1738
|
} catch {
|
|
1550
1739
|
}
|
|
@@ -1553,8 +1742,8 @@ async function triggerExternalSync(projectPath, roadmapFile) {
|
|
|
1553
1742
|
try {
|
|
1554
1743
|
const trackerConfig = loadTrackerSyncConfig(projectPath);
|
|
1555
1744
|
if (!trackerConfig) return;
|
|
1556
|
-
const projectEnvPath =
|
|
1557
|
-
if (
|
|
1745
|
+
const projectEnvPath = path11.join(projectPath, ".env");
|
|
1746
|
+
if (fs10.existsSync(projectEnvPath) && !process.env.GITHUB_TOKEN) {
|
|
1558
1747
|
const { config: loadDotenv } = await import("dotenv");
|
|
1559
1748
|
loadDotenv({ path: projectEnvPath });
|
|
1560
1749
|
}
|
|
@@ -1563,7 +1752,7 @@ async function triggerExternalSync(projectPath, roadmapFile) {
|
|
|
1563
1752
|
console.warn("[roadmap-sync] GITHUB_TOKEN not found \u2014 external sync skipped");
|
|
1564
1753
|
return;
|
|
1565
1754
|
}
|
|
1566
|
-
const { fullSync, GitHubIssuesSyncAdapter } = await import("./dist-
|
|
1755
|
+
const { fullSync, GitHubIssuesSyncAdapter } = await import("./dist-TKHVYUWZ.js");
|
|
1567
1756
|
const adapter = new GitHubIssuesSyncAdapter({
|
|
1568
1757
|
token,
|
|
1569
1758
|
config: trackerConfig
|
|
@@ -1660,12 +1849,12 @@ var manageStateDefinition = {
|
|
|
1660
1849
|
}
|
|
1661
1850
|
};
|
|
1662
1851
|
async function handleShow(projectPath, input) {
|
|
1663
|
-
const { loadState } = await import("./dist-
|
|
1852
|
+
const { loadState } = await import("./dist-TKHVYUWZ.js");
|
|
1664
1853
|
return resultToMcpResponse(await loadState(projectPath, input.stream, input.session));
|
|
1665
1854
|
}
|
|
1666
1855
|
async function handleLearn(projectPath, input) {
|
|
1667
1856
|
if (!input.learning) return mcpError("Error: learning is required for learn action");
|
|
1668
|
-
const { appendLearning } = await import("./dist-
|
|
1857
|
+
const { appendLearning } = await import("./dist-TKHVYUWZ.js");
|
|
1669
1858
|
const result = await appendLearning(
|
|
1670
1859
|
projectPath,
|
|
1671
1860
|
input.learning,
|
|
@@ -1680,7 +1869,7 @@ async function handleLearn(projectPath, input) {
|
|
|
1680
1869
|
async function handleFailure(projectPath, input) {
|
|
1681
1870
|
if (!input.description) return mcpError("Error: description is required for failure action");
|
|
1682
1871
|
if (!input.failureType) return mcpError("Error: failureType is required for failure action");
|
|
1683
|
-
const { appendFailure } = await import("./dist-
|
|
1872
|
+
const { appendFailure } = await import("./dist-TKHVYUWZ.js");
|
|
1684
1873
|
const result = await appendFailure(
|
|
1685
1874
|
projectPath,
|
|
1686
1875
|
input.description,
|
|
@@ -1699,19 +1888,19 @@ async function handleFailure(projectPath, input) {
|
|
|
1699
1888
|
return resultToMcpResponse(Ok({ recorded: true }));
|
|
1700
1889
|
}
|
|
1701
1890
|
async function handleArchive(projectPath, input) {
|
|
1702
|
-
const { archiveFailures } = await import("./dist-
|
|
1891
|
+
const { archiveFailures } = await import("./dist-TKHVYUWZ.js");
|
|
1703
1892
|
const result = await archiveFailures(projectPath, input.stream, input.session);
|
|
1704
1893
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1705
1894
|
return resultToMcpResponse(Ok({ archived: true }));
|
|
1706
1895
|
}
|
|
1707
1896
|
async function handleReset(projectPath, input) {
|
|
1708
|
-
const { saveState, DEFAULT_STATE } = await import("./dist-
|
|
1897
|
+
const { saveState, DEFAULT_STATE } = await import("./dist-TKHVYUWZ.js");
|
|
1709
1898
|
const result = await saveState(projectPath, { ...DEFAULT_STATE }, input.stream, input.session);
|
|
1710
1899
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1711
1900
|
return resultToMcpResponse(Ok({ reset: true }));
|
|
1712
1901
|
}
|
|
1713
1902
|
async function handleGate(projectPath, input) {
|
|
1714
|
-
const { runMechanicalGate } = await import("./dist-
|
|
1903
|
+
const { runMechanicalGate } = await import("./dist-TKHVYUWZ.js");
|
|
1715
1904
|
const result = await runMechanicalGate(projectPath);
|
|
1716
1905
|
if (result.ok) {
|
|
1717
1906
|
await emitSkillEvent(projectPath, {
|
|
@@ -1731,7 +1920,7 @@ async function handleGate(projectPath, input) {
|
|
|
1731
1920
|
}
|
|
1732
1921
|
async function handleSaveHandoff(projectPath, input) {
|
|
1733
1922
|
if (!input.handoff) return mcpError("Error: handoff is required for save-handoff action");
|
|
1734
|
-
const { saveHandoff } = await import("./dist-
|
|
1923
|
+
const { saveHandoff } = await import("./dist-TKHVYUWZ.js");
|
|
1735
1924
|
const result = await saveHandoff(
|
|
1736
1925
|
projectPath,
|
|
1737
1926
|
input.handoff,
|
|
@@ -1753,7 +1942,7 @@ async function handleSaveHandoff(projectPath, input) {
|
|
|
1753
1942
|
return resultToMcpResponse(Ok({ saved: true }));
|
|
1754
1943
|
}
|
|
1755
1944
|
async function handleLoadHandoff(projectPath, input) {
|
|
1756
|
-
const { loadHandoff } = await import("./dist-
|
|
1945
|
+
const { loadHandoff } = await import("./dist-TKHVYUWZ.js");
|
|
1757
1946
|
return resultToMcpResponse(await loadHandoff(projectPath, input.stream, input.session));
|
|
1758
1947
|
}
|
|
1759
1948
|
async function handleAppendEntry(projectPath, input) {
|
|
@@ -1761,7 +1950,7 @@ async function handleAppendEntry(projectPath, input) {
|
|
|
1761
1950
|
if (!input.authorSkill) return mcpError("Error: authorSkill is required for append_entry action");
|
|
1762
1951
|
if (!input.content) return mcpError("Error: content is required for append_entry action");
|
|
1763
1952
|
if (input.session) {
|
|
1764
|
-
const { appendSessionEntry } = await import("./dist-
|
|
1953
|
+
const { appendSessionEntry } = await import("./dist-TKHVYUWZ.js");
|
|
1765
1954
|
const result = await appendSessionEntry(
|
|
1766
1955
|
projectPath,
|
|
1767
1956
|
input.session,
|
|
@@ -1774,7 +1963,7 @@ async function handleAppendEntry(projectPath, input) {
|
|
|
1774
1963
|
if (input.section !== "decisions") {
|
|
1775
1964
|
return mcpError("Error: session is required for non-decisions sections");
|
|
1776
1965
|
}
|
|
1777
|
-
const { loadState, saveState } = await import("./dist-
|
|
1966
|
+
const { loadState, saveState } = await import("./dist-TKHVYUWZ.js");
|
|
1778
1967
|
const lr = await loadState(projectPath, input.stream);
|
|
1779
1968
|
if (!lr.ok) return resultToMcpResponse(lr);
|
|
1780
1969
|
lr.value.decisions.push({
|
|
@@ -1792,7 +1981,7 @@ async function handleUpdateEntryStatus(projectPath, input) {
|
|
|
1792
1981
|
if (!input.entryId) return mcpError("Error: entryId is required for update_entry_status action");
|
|
1793
1982
|
if (!input.newStatus)
|
|
1794
1983
|
return mcpError("Error: newStatus is required for update_entry_status action");
|
|
1795
|
-
const { updateSessionEntryStatus } = await import("./dist-
|
|
1984
|
+
const { updateSessionEntryStatus } = await import("./dist-TKHVYUWZ.js");
|
|
1796
1985
|
const result = await updateSessionEntryStatus(
|
|
1797
1986
|
projectPath,
|
|
1798
1987
|
input.session,
|
|
@@ -1805,7 +1994,7 @@ async function handleUpdateEntryStatus(projectPath, input) {
|
|
|
1805
1994
|
async function handleReadSection(projectPath, input) {
|
|
1806
1995
|
if (!input.session) return mcpError("Error: session is required for read_section action");
|
|
1807
1996
|
if (!input.section) return mcpError("Error: section is required for read_section action");
|
|
1808
|
-
const { readSessionSection } = await import("./dist-
|
|
1997
|
+
const { readSessionSection } = await import("./dist-TKHVYUWZ.js");
|
|
1809
1998
|
const result = await readSessionSection(
|
|
1810
1999
|
projectPath,
|
|
1811
2000
|
input.session,
|
|
@@ -1815,14 +2004,16 @@ async function handleReadSection(projectPath, input) {
|
|
|
1815
2004
|
}
|
|
1816
2005
|
async function handleReadSections(projectPath, input) {
|
|
1817
2006
|
if (!input.session) return mcpError("Error: session is required for read_sections action");
|
|
1818
|
-
const { readSessionSections } = await import("./dist-
|
|
2007
|
+
const { readSessionSections } = await import("./dist-TKHVYUWZ.js");
|
|
1819
2008
|
const result = await readSessionSections(projectPath, input.session);
|
|
1820
2009
|
return resultToMcpResponse(result);
|
|
1821
2010
|
}
|
|
1822
2011
|
async function handleArchiveSession(projectPath, input) {
|
|
1823
2012
|
if (!input.session) return mcpError("Error: session is required for archive_session action");
|
|
1824
|
-
const { archiveSession } = await import("./dist-
|
|
1825
|
-
const
|
|
2013
|
+
const { archiveSession } = await import("./dist-TKHVYUWZ.js");
|
|
2014
|
+
const { buildArchiveHooks } = await import("@harness-engineering/orchestrator");
|
|
2015
|
+
const hooks = buildArchiveHooks({ projectPath });
|
|
2016
|
+
const result = await archiveSession(projectPath, input.session, { hooks });
|
|
1826
2017
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1827
2018
|
await autoSyncRoadmap(projectPath);
|
|
1828
2019
|
return resultToMcpResponse(Ok({ archived: true }));
|
|
@@ -1901,7 +2092,7 @@ var listStreamsDefinition = {
|
|
|
1901
2092
|
};
|
|
1902
2093
|
async function handleListStreams(input) {
|
|
1903
2094
|
try {
|
|
1904
|
-
const { listStreams, loadStreamIndex } = await import("./dist-
|
|
2095
|
+
const { listStreams, loadStreamIndex } = await import("./dist-TKHVYUWZ.js");
|
|
1905
2096
|
const projectPath = sanitizePath(input.path);
|
|
1906
2097
|
const indexResult = await loadStreamIndex(projectPath);
|
|
1907
2098
|
const streamsResult = await listStreams(projectPath);
|
|
@@ -1939,7 +2130,7 @@ var checkPhaseGateDefinition = {
|
|
|
1939
2130
|
};
|
|
1940
2131
|
async function handleCheckPhaseGate(input) {
|
|
1941
2132
|
try {
|
|
1942
|
-
const { runCheckPhaseGate } = await import("./check-phase-gate-
|
|
2133
|
+
const { runCheckPhaseGate } = await import("./check-phase-gate-PD5MVEZT.js");
|
|
1943
2134
|
const result = await runCheckPhaseGate({ cwd: sanitizePath(input.path) });
|
|
1944
2135
|
if (result.ok) {
|
|
1945
2136
|
return { content: [{ type: "text", text: JSON.stringify(result.value) }] };
|
|
@@ -1959,7 +2150,7 @@ async function handleCheckPhaseGate(input) {
|
|
|
1959
2150
|
}
|
|
1960
2151
|
|
|
1961
2152
|
// src/mcp/tools/cross-check.ts
|
|
1962
|
-
import * as
|
|
2153
|
+
import * as path12 from "path";
|
|
1963
2154
|
var validateCrossCheckDefinition = {
|
|
1964
2155
|
name: "validate_cross_check",
|
|
1965
2156
|
description: "Validate plan-to-implementation coverage: checks that specs have plans and plans have implementations, detects staleness",
|
|
@@ -1995,15 +2186,15 @@ async function handleValidateCrossCheck(input) {
|
|
|
1995
2186
|
};
|
|
1996
2187
|
}
|
|
1997
2188
|
try {
|
|
1998
|
-
const { runCrossCheck } = await import("./validate-cross-check-
|
|
1999
|
-
const specsDir =
|
|
2189
|
+
const { runCrossCheck } = await import("./validate-cross-check-7PO7CBVT.js");
|
|
2190
|
+
const specsDir = path12.resolve(projectPath, input.specsDir ?? "docs/specs");
|
|
2000
2191
|
if (!specsDir.startsWith(projectPath)) {
|
|
2001
2192
|
return {
|
|
2002
2193
|
content: [{ type: "text", text: "Error: specsDir escapes project root" }],
|
|
2003
2194
|
isError: true
|
|
2004
2195
|
};
|
|
2005
2196
|
}
|
|
2006
|
-
const plansDir =
|
|
2197
|
+
const plansDir = path12.resolve(projectPath, input.plansDir ?? "docs/plans");
|
|
2007
2198
|
if (!plansDir.startsWith(projectPath)) {
|
|
2008
2199
|
return {
|
|
2009
2200
|
content: [{ type: "text", text: "Error: plansDir escapes project root" }],
|
|
@@ -2033,18 +2224,18 @@ async function handleValidateCrossCheck(input) {
|
|
|
2033
2224
|
}
|
|
2034
2225
|
|
|
2035
2226
|
// src/mcp/tools/generate-slash-commands.ts
|
|
2036
|
-
|
|
2227
|
+
init_dist2();
|
|
2037
2228
|
|
|
2038
2229
|
// src/commands/generate-slash-commands.ts
|
|
2039
2230
|
import { Command } from "commander";
|
|
2040
|
-
import
|
|
2041
|
-
import
|
|
2231
|
+
import fs13 from "fs";
|
|
2232
|
+
import path15 from "path";
|
|
2042
2233
|
import os from "os";
|
|
2043
2234
|
import readline from "readline";
|
|
2044
2235
|
|
|
2045
2236
|
// src/slash-commands/normalize.ts
|
|
2046
|
-
import
|
|
2047
|
-
import
|
|
2237
|
+
import fs11 from "fs";
|
|
2238
|
+
import path13 from "path";
|
|
2048
2239
|
import { parse as parse2 } from "yaml";
|
|
2049
2240
|
|
|
2050
2241
|
// src/slash-commands/normalize-name.ts
|
|
@@ -2064,7 +2255,7 @@ function normalizeName(skillName) {
|
|
|
2064
2255
|
function readSkillYaml(yamlPath) {
|
|
2065
2256
|
let raw;
|
|
2066
2257
|
try {
|
|
2067
|
-
raw =
|
|
2258
|
+
raw = fs11.readFileSync(yamlPath, "utf-8");
|
|
2068
2259
|
} catch {
|
|
2069
2260
|
return null;
|
|
2070
2261
|
}
|
|
@@ -2128,10 +2319,10 @@ function buildProcessLines(meta) {
|
|
|
2128
2319
|
];
|
|
2129
2320
|
}
|
|
2130
2321
|
function buildSpec(meta, normalized, entry, skillsDir, source) {
|
|
2131
|
-
const skillMdPath =
|
|
2132
|
-
const skillMdContent =
|
|
2133
|
-
const skillMdRelative =
|
|
2134
|
-
const skillYamlRelative =
|
|
2322
|
+
const skillMdPath = path13.join(skillsDir, entry.name, "SKILL.md");
|
|
2323
|
+
const skillMdContent = fs11.existsSync(skillMdPath) ? fs11.readFileSync(skillMdPath, "utf-8") : "";
|
|
2324
|
+
const skillMdRelative = path13.relative(process.cwd(), skillMdPath).replaceAll("\\", "/");
|
|
2325
|
+
const skillYamlRelative = path13.relative(process.cwd(), path13.join(skillsDir, entry.name, "skill.yaml")).replaceAll("\\", "/");
|
|
2135
2326
|
const args = (meta.cli?.args ?? []).map((a) => ({
|
|
2136
2327
|
name: a.name,
|
|
2137
2328
|
description: a.description ?? "",
|
|
@@ -2186,11 +2377,11 @@ function normalizeSkills(skillSources, platforms) {
|
|
|
2186
2377
|
const specs = [];
|
|
2187
2378
|
const nameMap = /* @__PURE__ */ new Map();
|
|
2188
2379
|
for (const { dir: skillsDir, source } of skillSources) {
|
|
2189
|
-
if (!
|
|
2190
|
-
const entries =
|
|
2380
|
+
if (!fs11.existsSync(skillsDir)) continue;
|
|
2381
|
+
const entries = fs11.readdirSync(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
2191
2382
|
for (const entry of entries) {
|
|
2192
|
-
const yamlPath =
|
|
2193
|
-
if (!
|
|
2383
|
+
const yamlPath = path13.join(skillsDir, entry.name, "skill.yaml");
|
|
2384
|
+
if (!fs11.existsSync(yamlPath)) continue;
|
|
2194
2385
|
const result = readSkillYaml(yamlPath);
|
|
2195
2386
|
if (!result) continue;
|
|
2196
2387
|
if (!result.success) {
|
|
@@ -2390,27 +2581,27 @@ function renderCodexAgentsMd(specs) {
|
|
|
2390
2581
|
}
|
|
2391
2582
|
|
|
2392
2583
|
// src/slash-commands/sync-codex.ts
|
|
2393
|
-
import
|
|
2394
|
-
import
|
|
2584
|
+
import fs12 from "fs";
|
|
2585
|
+
import path14 from "path";
|
|
2395
2586
|
function computeCodexSync(outputDir, specs, dryRun) {
|
|
2396
2587
|
const added = [];
|
|
2397
2588
|
const updated = [];
|
|
2398
2589
|
const unchanged = [];
|
|
2399
2590
|
const specSkillNames = /* @__PURE__ */ new Set();
|
|
2400
2591
|
for (const spec of specs) {
|
|
2401
|
-
const mdPath =
|
|
2402
|
-
const skillMd =
|
|
2403
|
-
const skillDir =
|
|
2592
|
+
const mdPath = path14.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
|
|
2593
|
+
const skillMd = fs12.existsSync(mdPath) ? fs12.readFileSync(mdPath, "utf-8") : "";
|
|
2594
|
+
const skillDir = path14.join(outputDir, spec.skillYamlName);
|
|
2404
2595
|
specSkillNames.add(spec.skillYamlName);
|
|
2405
2596
|
const renderedSkillMd = renderCodexSkill(skillMd);
|
|
2406
2597
|
const renderedOpenaiYaml = renderCodexOpenaiYaml(spec);
|
|
2407
|
-
const existingSkillMdPath =
|
|
2408
|
-
const existingOpenaiYamlPath =
|
|
2409
|
-
if (!
|
|
2598
|
+
const existingSkillMdPath = path14.join(skillDir, "SKILL.md");
|
|
2599
|
+
const existingOpenaiYamlPath = path14.join(skillDir, "agents", "openai.yaml");
|
|
2600
|
+
if (!fs12.existsSync(skillDir)) {
|
|
2410
2601
|
added.push(spec.skillYamlName);
|
|
2411
2602
|
} else {
|
|
2412
|
-
const existingSkillMd =
|
|
2413
|
-
const existingOpenaiYaml =
|
|
2603
|
+
const existingSkillMd = fs12.existsSync(existingSkillMdPath) ? fs12.readFileSync(existingSkillMdPath, "utf-8") : "";
|
|
2604
|
+
const existingOpenaiYaml = fs12.existsSync(existingOpenaiYamlPath) ? fs12.readFileSync(existingOpenaiYamlPath, "utf-8") : "";
|
|
2414
2605
|
if (existingSkillMd === renderedSkillMd && existingOpenaiYaml === renderedOpenaiYaml) {
|
|
2415
2606
|
unchanged.push(spec.skillYamlName);
|
|
2416
2607
|
} else {
|
|
@@ -2418,10 +2609,10 @@ function computeCodexSync(outputDir, specs, dryRun) {
|
|
|
2418
2609
|
}
|
|
2419
2610
|
}
|
|
2420
2611
|
if (!dryRun && !unchanged.includes(spec.skillYamlName)) {
|
|
2421
|
-
const agentsSubDir =
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2612
|
+
const agentsSubDir = path14.join(skillDir, "agents");
|
|
2613
|
+
fs12.mkdirSync(agentsSubDir, { recursive: true });
|
|
2614
|
+
fs12.writeFileSync(existingSkillMdPath, renderedSkillMd, "utf-8");
|
|
2615
|
+
fs12.writeFileSync(existingOpenaiYamlPath, renderedOpenaiYaml, "utf-8");
|
|
2425
2616
|
}
|
|
2426
2617
|
}
|
|
2427
2618
|
const removed = detectCodexOrphans(outputDir, specSkillNames);
|
|
@@ -2429,13 +2620,13 @@ function computeCodexSync(outputDir, specs, dryRun) {
|
|
|
2429
2620
|
}
|
|
2430
2621
|
function detectCodexOrphans(outputDir, specSkillNames) {
|
|
2431
2622
|
const removed = [];
|
|
2432
|
-
if (!
|
|
2433
|
-
const existingDirs =
|
|
2623
|
+
if (!fs12.existsSync(outputDir)) return removed;
|
|
2624
|
+
const existingDirs = fs12.readdirSync(outputDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
2434
2625
|
for (const dirName of existingDirs) {
|
|
2435
2626
|
if (specSkillNames.has(dirName)) continue;
|
|
2436
|
-
const skillMdPath =
|
|
2437
|
-
if (
|
|
2438
|
-
const content =
|
|
2627
|
+
const skillMdPath = path14.join(outputDir, dirName, "SKILL.md");
|
|
2628
|
+
if (fs12.existsSync(skillMdPath)) {
|
|
2629
|
+
const content = fs12.readFileSync(skillMdPath, "utf-8");
|
|
2439
2630
|
if (content.includes(GENERATED_HEADER_CODEX)) {
|
|
2440
2631
|
removed.push(dirName);
|
|
2441
2632
|
}
|
|
@@ -2447,19 +2638,19 @@ function detectCodexOrphans(outputDir, specSkillNames) {
|
|
|
2447
2638
|
// src/commands/generate-slash-commands.ts
|
|
2448
2639
|
function resolveOutputDir(platform, opts) {
|
|
2449
2640
|
if (opts.output) {
|
|
2450
|
-
return
|
|
2641
|
+
return path15.join(opts.output, "harness");
|
|
2451
2642
|
}
|
|
2452
2643
|
if (opts.global) {
|
|
2453
2644
|
const home = os.homedir();
|
|
2454
|
-
if (platform === "claude-code") return
|
|
2455
|
-
if (platform === "gemini-cli") return
|
|
2456
|
-
if (platform === "cursor") return
|
|
2457
|
-
return
|
|
2645
|
+
if (platform === "claude-code") return path15.join(home, ".claude", "commands", "harness");
|
|
2646
|
+
if (platform === "gemini-cli") return path15.join(home, ".gemini", "commands", "harness");
|
|
2647
|
+
if (platform === "cursor") return path15.join(home, ".cursor", "rules", "harness");
|
|
2648
|
+
return path15.join(home, ".codex", "harness");
|
|
2458
2649
|
}
|
|
2459
|
-
if (platform === "claude-code") return
|
|
2460
|
-
if (platform === "gemini-cli") return
|
|
2461
|
-
if (platform === "cursor") return
|
|
2462
|
-
return
|
|
2650
|
+
if (platform === "claude-code") return path15.join("agents", "commands", "claude-code", "harness");
|
|
2651
|
+
if (platform === "gemini-cli") return path15.join("agents", "commands", "gemini-cli", "harness");
|
|
2652
|
+
if (platform === "cursor") return path15.join("agents", "commands", "cursor", "harness");
|
|
2653
|
+
return path15.join("agents", "commands", "codex", "harness");
|
|
2463
2654
|
}
|
|
2464
2655
|
async function confirmDeletion(files) {
|
|
2465
2656
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -2475,8 +2666,8 @@ function resolveSkillSources(opts) {
|
|
|
2475
2666
|
const sources = [];
|
|
2476
2667
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
2477
2668
|
function addSource(dir, source) {
|
|
2478
|
-
const resolved =
|
|
2479
|
-
if (!seenPaths.has(resolved) &&
|
|
2669
|
+
const resolved = path15.resolve(dir);
|
|
2670
|
+
if (!seenPaths.has(resolved) && fs13.existsSync(dir)) {
|
|
2480
2671
|
seenPaths.add(resolved);
|
|
2481
2672
|
sources.push({ dir, source });
|
|
2482
2673
|
}
|
|
@@ -2503,7 +2694,7 @@ function resolveAbsoluteExecutionContext(spec) {
|
|
|
2503
2694
|
...spec,
|
|
2504
2695
|
prompt: {
|
|
2505
2696
|
...spec.prompt,
|
|
2506
|
-
executionContext: spec.prompt.executionContext.split("\n").map((line) => line.startsWith("@") ? `@${
|
|
2697
|
+
executionContext: spec.prompt.executionContext.split("\n").map((line) => line.startsWith("@") ? `@${path15.resolve(line.slice(1))}` : line).join("\n")
|
|
2507
2698
|
}
|
|
2508
2699
|
};
|
|
2509
2700
|
}
|
|
@@ -2512,26 +2703,26 @@ function renderSpec(platform, spec, useAbsolutePaths, cursorMode = "rules") {
|
|
|
2512
2703
|
if (cursorMode === "commands") {
|
|
2513
2704
|
return [`${spec.name}.md`, renderCursorCommand(spec)];
|
|
2514
2705
|
}
|
|
2515
|
-
const mdPath2 =
|
|
2516
|
-
const skillMd =
|
|
2706
|
+
const mdPath2 = path15.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
|
|
2707
|
+
const skillMd = fs13.existsSync(mdPath2) ? fs13.readFileSync(mdPath2, "utf-8") : "";
|
|
2517
2708
|
return [`${spec.skillYamlName}.mdc`, renderCursor(spec, skillMd, spec.cursor)];
|
|
2518
2709
|
}
|
|
2519
2710
|
if (platform === "claude-code") {
|
|
2520
2711
|
const renderSpecValue = useAbsolutePaths ? resolveAbsoluteExecutionContext(spec) : spec;
|
|
2521
2712
|
return [`${spec.name}.md`, renderClaudeCode(renderSpecValue)];
|
|
2522
2713
|
}
|
|
2523
|
-
const mdPath =
|
|
2524
|
-
const yamlPath =
|
|
2525
|
-
const mdContent =
|
|
2526
|
-
const yamlContent =
|
|
2714
|
+
const mdPath = path15.join(spec.skillsBaseDir, spec.sourceDir, "SKILL.md");
|
|
2715
|
+
const yamlPath = path15.join(spec.skillsBaseDir, spec.sourceDir, "skill.yaml");
|
|
2716
|
+
const mdContent = fs13.existsSync(mdPath) ? fs13.readFileSync(mdPath, "utf-8") : "";
|
|
2717
|
+
const yamlContent = fs13.existsSync(yamlPath) ? fs13.readFileSync(yamlPath, "utf-8") : "";
|
|
2527
2718
|
return [`${spec.name}.toml`, renderGemini(spec, mdContent, yamlContent)];
|
|
2528
2719
|
}
|
|
2529
2720
|
function generateForCodex(platform, outputDir, specs, dryRun) {
|
|
2530
2721
|
const codexSync = computeCodexSync(outputDir, specs, dryRun);
|
|
2531
|
-
const codexRoot =
|
|
2722
|
+
const codexRoot = path15.dirname(outputDir);
|
|
2532
2723
|
if (!dryRun) {
|
|
2533
|
-
|
|
2534
|
-
|
|
2724
|
+
fs13.mkdirSync(codexRoot, { recursive: true });
|
|
2725
|
+
fs13.writeFileSync(path15.join(codexRoot, "AGENTS.md"), renderCodexAgentsMd(specs), "utf-8");
|
|
2535
2726
|
}
|
|
2536
2727
|
return { platform, ...codexSync, outputDir };
|
|
2537
2728
|
}
|
|
@@ -2562,9 +2753,9 @@ function generateForPlatform(platform, outputDir, specs, opts) {
|
|
|
2562
2753
|
const allUpdated = [...plan.updated];
|
|
2563
2754
|
const allRemoved = [...plan.removed];
|
|
2564
2755
|
const allUnchanged = [...plan.unchanged];
|
|
2565
|
-
const parentDir =
|
|
2756
|
+
const parentDir = path15.dirname(outputDir);
|
|
2566
2757
|
for (const [ns, nsRendered] of customNamespaceRendered) {
|
|
2567
|
-
const nsDir =
|
|
2758
|
+
const nsDir = path15.join(parentDir, ns);
|
|
2568
2759
|
const nsPlan = computeSyncPlan(nsDir, nsRendered);
|
|
2569
2760
|
if (!opts.dryRun) {
|
|
2570
2761
|
applySyncPlan(nsDir, nsRendered, nsPlan, false);
|
|
@@ -2614,13 +2805,13 @@ async function handleOrphanDeletion(results, opts) {
|
|
|
2614
2805
|
const shouldDelete = opts.yes || await confirmDeletion(result.removed);
|
|
2615
2806
|
if (!shouldDelete) continue;
|
|
2616
2807
|
for (const filename of result.removed) {
|
|
2617
|
-
const filePath =
|
|
2618
|
-
if (!
|
|
2619
|
-
const stat =
|
|
2808
|
+
const filePath = path15.join(result.outputDir, filename);
|
|
2809
|
+
if (!fs13.existsSync(filePath)) continue;
|
|
2810
|
+
const stat = fs13.statSync(filePath);
|
|
2620
2811
|
if (stat.isDirectory()) {
|
|
2621
|
-
|
|
2812
|
+
fs13.rmSync(filePath, { recursive: true, force: true });
|
|
2622
2813
|
} else {
|
|
2623
|
-
|
|
2814
|
+
fs13.unlinkSync(filePath);
|
|
2624
2815
|
}
|
|
2625
2816
|
}
|
|
2626
2817
|
}
|
|
@@ -2762,7 +2953,7 @@ async function handleGenerateSlashCommands(input) {
|
|
|
2762
2953
|
// src/mcp/resources/state.ts
|
|
2763
2954
|
async function getStateResource(projectRoot) {
|
|
2764
2955
|
try {
|
|
2765
|
-
const { loadState, migrateToStreams } = await import("./dist-
|
|
2956
|
+
const { loadState, migrateToStreams } = await import("./dist-TKHVYUWZ.js");
|
|
2766
2957
|
await migrateToStreams(projectRoot);
|
|
2767
2958
|
const result = await loadState(projectRoot);
|
|
2768
2959
|
if (result.ok) {
|
|
@@ -2787,7 +2978,7 @@ async function getStateResource(projectRoot) {
|
|
|
2787
2978
|
}
|
|
2788
2979
|
|
|
2789
2980
|
// src/mcp/tools/graph/query-graph.ts
|
|
2790
|
-
|
|
2981
|
+
init_dist2();
|
|
2791
2982
|
|
|
2792
2983
|
// src/mcp/tools/graph/shared.ts
|
|
2793
2984
|
function graphNotFoundError() {
|
|
@@ -3085,7 +3276,7 @@ async function handleFindContextFor(input) {
|
|
|
3085
3276
|
}
|
|
3086
3277
|
|
|
3087
3278
|
// src/mcp/tools/graph/get-relationships.ts
|
|
3088
|
-
|
|
3279
|
+
init_dist2();
|
|
3089
3280
|
var getRelationshipsDefinition = {
|
|
3090
3281
|
name: "get_relationships",
|
|
3091
3282
|
description: "Get relationships for a specific node in the knowledge graph, with configurable direction and depth.",
|
|
@@ -3351,7 +3542,7 @@ async function handleGetImpact(input) {
|
|
|
3351
3542
|
}
|
|
3352
3543
|
|
|
3353
3544
|
// src/mcp/tools/graph/ingest-source.ts
|
|
3354
|
-
import * as
|
|
3545
|
+
import * as path16 from "path";
|
|
3355
3546
|
var ingestSourceDefinition = {
|
|
3356
3547
|
name: "ingest_source",
|
|
3357
3548
|
description: "Ingest sources into the project knowledge graph. Supports code analysis, knowledge documents, git history, or all at once.",
|
|
@@ -3371,10 +3562,10 @@ var ingestSourceDefinition = {
|
|
|
3371
3562
|
async function handleIngestSource(input) {
|
|
3372
3563
|
try {
|
|
3373
3564
|
const projectPath = sanitizePath(input.path);
|
|
3374
|
-
const graphDir =
|
|
3565
|
+
const graphDir = path16.join(projectPath, ".harness", "graph");
|
|
3375
3566
|
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-QPWXPCPL.js");
|
|
3376
|
-
const
|
|
3377
|
-
await
|
|
3567
|
+
const fs18 = await import("fs/promises");
|
|
3568
|
+
await fs18.mkdir(graphDir, { recursive: true });
|
|
3378
3569
|
const store = new GraphStore();
|
|
3379
3570
|
await store.load(graphDir);
|
|
3380
3571
|
const results = [];
|
|
@@ -3397,7 +3588,7 @@ async function handleIngestSource(input) {
|
|
|
3397
3588
|
}
|
|
3398
3589
|
if (input.source === "business-signals" || input.source === "all") {
|
|
3399
3590
|
const { createExtractionRunner } = await import("./dist-QPWXPCPL.js");
|
|
3400
|
-
const extractedDir =
|
|
3591
|
+
const extractedDir = path16.join(projectPath, ".harness", "knowledge", "extracted");
|
|
3401
3592
|
const signalsResult = await createExtractionRunner().run(projectPath, store, extractedDir);
|
|
3402
3593
|
results.push(signalsResult);
|
|
3403
3594
|
}
|
|
@@ -3437,7 +3628,7 @@ async function handleIngestSource(input) {
|
|
|
3437
3628
|
}
|
|
3438
3629
|
|
|
3439
3630
|
// src/mcp/tools/graph/detect-anomalies.ts
|
|
3440
|
-
|
|
3631
|
+
init_dist2();
|
|
3441
3632
|
var detectAnomaliesDefinition = {
|
|
3442
3633
|
name: "detect_anomalies",
|
|
3443
3634
|
description: "Detect structural anomalies \u2014 statistical outliers across code metrics and topological single points of failure in the import graph",
|
|
@@ -3668,8 +3859,8 @@ async function handleComputeBlastRadius(input) {
|
|
|
3668
3859
|
}
|
|
3669
3860
|
|
|
3670
3861
|
// src/mcp/resources/graph.ts
|
|
3671
|
-
import * as
|
|
3672
|
-
import * as
|
|
3862
|
+
import * as fs14 from "fs/promises";
|
|
3863
|
+
import * as path17 from "path";
|
|
3673
3864
|
var MAX_ITEMS = 5e3;
|
|
3674
3865
|
function formatStaleness(isoTimestamp) {
|
|
3675
3866
|
const then = new Date(isoTimestamp).getTime();
|
|
@@ -3692,9 +3883,9 @@ function countByType(items) {
|
|
|
3692
3883
|
return counts;
|
|
3693
3884
|
}
|
|
3694
3885
|
async function readLastScanTimestamp(projectRoot) {
|
|
3695
|
-
const metadataPath =
|
|
3886
|
+
const metadataPath = path17.join(projectRoot, ".harness", "graph", "metadata.json");
|
|
3696
3887
|
try {
|
|
3697
|
-
const raw = JSON.parse(await
|
|
3888
|
+
const raw = JSON.parse(await fs14.readFile(metadataPath, "utf-8"));
|
|
3698
3889
|
return raw.lastScanTimestamp ?? null;
|
|
3699
3890
|
} catch {
|
|
3700
3891
|
return null;
|
|
@@ -3764,7 +3955,7 @@ async function getRelationshipsResource(projectRoot) {
|
|
|
3764
3955
|
}
|
|
3765
3956
|
|
|
3766
3957
|
// src/mcp/tools/agent-definitions.ts
|
|
3767
|
-
|
|
3958
|
+
init_dist2();
|
|
3768
3959
|
var generateAgentDefinitionsDefinition = {
|
|
3769
3960
|
name: "generate_agent_definitions",
|
|
3770
3961
|
description: "Generate agent definition files from personas for Claude Code and Gemini CLI",
|
|
@@ -3782,7 +3973,7 @@ var generateAgentDefinitionsDefinition = {
|
|
|
3782
3973
|
}
|
|
3783
3974
|
};
|
|
3784
3975
|
async function handleGenerateAgentDefinitions(input) {
|
|
3785
|
-
const { generateAgentDefinitions } = await import("./generate-agent-definitions-
|
|
3976
|
+
const { generateAgentDefinitions } = await import("./generate-agent-definitions-5PV4O3BD.js");
|
|
3786
3977
|
const platforms = input.platform === "all" || !input.platform ? ["claude-code", "gemini-cli"] : [input.platform];
|
|
3787
3978
|
const results = generateAgentDefinitions({
|
|
3788
3979
|
platforms: [...platforms],
|
|
@@ -3793,12 +3984,12 @@ async function handleGenerateAgentDefinitions(input) {
|
|
|
3793
3984
|
}
|
|
3794
3985
|
|
|
3795
3986
|
// src/mcp/tools/roadmap.ts
|
|
3796
|
-
|
|
3797
|
-
import * as
|
|
3798
|
-
import * as
|
|
3987
|
+
init_dist2();
|
|
3988
|
+
import * as fs15 from "fs";
|
|
3989
|
+
import * as path18 from "path";
|
|
3799
3990
|
|
|
3800
3991
|
// src/mcp/tools/roadmap-file-less.ts
|
|
3801
|
-
|
|
3992
|
+
init_dist2();
|
|
3802
3993
|
var ok = (text) => ({ content: [{ type: "text", text }] });
|
|
3803
3994
|
var err = (text) => ({ content: [{ type: "text", text }], isError: true });
|
|
3804
3995
|
async function handleManageRoadmapFileLess(input, client) {
|
|
@@ -3996,21 +4187,21 @@ var manageRoadmapDefinition = {
|
|
|
3996
4187
|
}
|
|
3997
4188
|
};
|
|
3998
4189
|
function roadmapPath(projectRoot) {
|
|
3999
|
-
return
|
|
4190
|
+
return path18.join(projectRoot, "docs", "roadmap.md");
|
|
4000
4191
|
}
|
|
4001
4192
|
function readRoadmapFile(projectRoot) {
|
|
4002
4193
|
const filePath = roadmapPath(projectRoot);
|
|
4003
4194
|
try {
|
|
4004
|
-
return
|
|
4195
|
+
return fs15.readFileSync(filePath, "utf-8");
|
|
4005
4196
|
} catch {
|
|
4006
4197
|
return null;
|
|
4007
4198
|
}
|
|
4008
4199
|
}
|
|
4009
4200
|
function writeRoadmapFile(projectRoot, content) {
|
|
4010
4201
|
const filePath = roadmapPath(projectRoot);
|
|
4011
|
-
const dir =
|
|
4012
|
-
|
|
4013
|
-
|
|
4202
|
+
const dir = path18.dirname(filePath);
|
|
4203
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
4204
|
+
fs15.writeFileSync(filePath, content, "utf-8");
|
|
4014
4205
|
}
|
|
4015
4206
|
function roadmapNotFoundError() {
|
|
4016
4207
|
return {
|
|
@@ -4276,8 +4467,8 @@ async function handleManageRoadmap(input) {
|
|
|
4276
4467
|
return handleManageRoadmapFileLess(input, clientResult.value);
|
|
4277
4468
|
}
|
|
4278
4469
|
try {
|
|
4279
|
-
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges, assignFeature } = await import("./dist-
|
|
4280
|
-
const { Ok: Ok2 } = await import("./dist-
|
|
4470
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges, assignFeature } = await import("./dist-TKHVYUWZ.js");
|
|
4471
|
+
const { Ok: Ok2 } = await import("./dist-HVJUGPSY.js");
|
|
4281
4472
|
const projectPath = projectPathPre;
|
|
4282
4473
|
const deps = {
|
|
4283
4474
|
parseRoadmap,
|
|
@@ -4715,7 +4906,7 @@ async function handleTransition(validInput, projectPath, id) {
|
|
|
4715
4906
|
const transition = transitionResult.data;
|
|
4716
4907
|
const prompt = renderTransition(transition);
|
|
4717
4908
|
try {
|
|
4718
|
-
const { saveHandoff } = await import("./dist-
|
|
4909
|
+
const { saveHandoff } = await import("./dist-TKHVYUWZ.js");
|
|
4719
4910
|
await saveHandoff(
|
|
4720
4911
|
projectPath,
|
|
4721
4912
|
{
|
|
@@ -4796,7 +4987,7 @@ async function handleEmitInteraction(input) {
|
|
|
4796
4987
|
}
|
|
4797
4988
|
async function recordInteraction(projectPath, id, type, decision, stream) {
|
|
4798
4989
|
try {
|
|
4799
|
-
const { loadState, saveState } = await import("./dist-
|
|
4990
|
+
const { loadState, saveState } = await import("./dist-TKHVYUWZ.js");
|
|
4800
4991
|
const stateResult = await loadState(projectPath, stream);
|
|
4801
4992
|
if (stateResult.ok) {
|
|
4802
4993
|
const state = stateResult.value;
|
|
@@ -4812,7 +5003,7 @@ async function recordInteraction(projectPath, id, type, decision, stream) {
|
|
|
4812
5003
|
}
|
|
4813
5004
|
|
|
4814
5005
|
// src/mcp/tools/gather-context.ts
|
|
4815
|
-
|
|
5006
|
+
init_dist2();
|
|
4816
5007
|
function flattenSessionSections(sections) {
|
|
4817
5008
|
if (!sections) return [];
|
|
4818
5009
|
return Object.entries(sections).flatMap(
|
|
@@ -4957,10 +5148,10 @@ async function handleGatherContext(input) {
|
|
|
4957
5148
|
input.include ?? ["state", "learnings", "handoff", "graph", "validation", "businessKnowledge"]
|
|
4958
5149
|
);
|
|
4959
5150
|
const errors = [];
|
|
4960
|
-
const statePromise = includeSet.has("state") ? import("./dist-
|
|
5151
|
+
const statePromise = includeSet.has("state") ? import("./dist-TKHVYUWZ.js").then(
|
|
4961
5152
|
(core) => core.loadState(projectPath, void 0, input.session)
|
|
4962
5153
|
) : Promise.resolve(null);
|
|
4963
|
-
const learningsPromise = includeSet.has("learnings") ? import("./dist-
|
|
5154
|
+
const learningsPromise = includeSet.has("learnings") ? import("./dist-TKHVYUWZ.js").then(
|
|
4964
5155
|
(core) => core.loadBudgetedLearnings(projectPath, {
|
|
4965
5156
|
intent: input.intent,
|
|
4966
5157
|
tokenBudget: input.learningsBudget ?? 1e3,
|
|
@@ -4969,7 +5160,7 @@ async function handleGatherContext(input) {
|
|
|
4969
5160
|
...input.depth !== void 0 && { depth: input.depth }
|
|
4970
5161
|
})
|
|
4971
5162
|
) : Promise.resolve(null);
|
|
4972
|
-
const handoffPromise = includeSet.has("handoff") ? import("./dist-
|
|
5163
|
+
const handoffPromise = includeSet.has("handoff") ? import("./dist-TKHVYUWZ.js").then(
|
|
4973
5164
|
(core) => core.loadHandoff(projectPath, void 0, input.session)
|
|
4974
5165
|
) : Promise.resolve(null);
|
|
4975
5166
|
const graphPromise = includeSet.has("graph") ? (async () => {
|
|
@@ -5013,11 +5204,11 @@ async function handleGatherContext(input) {
|
|
|
5013
5204
|
context: contextBlocks
|
|
5014
5205
|
};
|
|
5015
5206
|
})() : Promise.resolve(null);
|
|
5016
|
-
const sessionsPromise = includeSet.has("sessions") && input.session ? import("./dist-
|
|
5207
|
+
const sessionsPromise = includeSet.has("sessions") && input.session ? import("./dist-TKHVYUWZ.js").then(
|
|
5017
5208
|
(core) => core.readSessionSections(projectPath, input.session)
|
|
5018
5209
|
) : Promise.resolve(null);
|
|
5019
5210
|
const shouldIncludeEvents = input.includeEvents !== void 0 ? input.includeEvents : includeSet.has("events") || !!input.session && !input.include;
|
|
5020
|
-
const eventsPromise = shouldIncludeEvents ? import("./dist-
|
|
5211
|
+
const eventsPromise = shouldIncludeEvents ? import("./dist-TKHVYUWZ.js").then(async (core) => {
|
|
5021
5212
|
const result = await core.loadEvents(projectPath, {
|
|
5022
5213
|
session: input.session
|
|
5023
5214
|
});
|
|
@@ -5025,7 +5216,7 @@ async function handleGatherContext(input) {
|
|
|
5025
5216
|
return core.formatEventTimeline(result.value);
|
|
5026
5217
|
}) : Promise.resolve(null);
|
|
5027
5218
|
const validationPromise = includeSet.has("validation") ? (async () => {
|
|
5028
|
-
const { handleValidateProject: handleValidateProject2 } = await import("./validate-
|
|
5219
|
+
const { handleValidateProject: handleValidateProject2 } = await import("./validate-AFJVI4OX.js");
|
|
5029
5220
|
const result = await handleValidateProject2({ path: projectPath });
|
|
5030
5221
|
const first = result.content[0];
|
|
5031
5222
|
return first ? JSON.parse(first.text) : null;
|
|
@@ -5128,7 +5319,7 @@ async function handleGatherContext(input) {
|
|
|
5128
5319
|
};
|
|
5129
5320
|
if (input.session) {
|
|
5130
5321
|
try {
|
|
5131
|
-
const core = await import("./dist-
|
|
5322
|
+
const core = await import("./dist-TKHVYUWZ.js");
|
|
5132
5323
|
core.updateSessionIndex(
|
|
5133
5324
|
projectPath,
|
|
5134
5325
|
input.session,
|
|
@@ -5168,7 +5359,7 @@ async function handleGatherContext(input) {
|
|
|
5168
5359
|
}
|
|
5169
5360
|
|
|
5170
5361
|
// src/mcp/tools/review-changes.ts
|
|
5171
|
-
|
|
5362
|
+
init_dist2();
|
|
5172
5363
|
var SIZE_GATE_LINES = 1e4;
|
|
5173
5364
|
var reviewChangesDefinition = {
|
|
5174
5365
|
name: "review_changes",
|
|
@@ -5280,7 +5471,7 @@ async function handleReviewChanges(input) {
|
|
|
5280
5471
|
}
|
|
5281
5472
|
}
|
|
5282
5473
|
async function runQuickReview(projectPath, diff, diffLines, downgraded, offset, limit) {
|
|
5283
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-
|
|
5474
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-ER2HRTFD.js");
|
|
5284
5475
|
const result = await handleAnalyzeDiff2({ diff, path: projectPath });
|
|
5285
5476
|
const firstContent = result.content[0];
|
|
5286
5477
|
if (!firstContent) throw new Error("Empty analyze_diff response");
|
|
@@ -5315,7 +5506,7 @@ function extractFileCount(diffParsed) {
|
|
|
5315
5506
|
return files?.length ?? 0;
|
|
5316
5507
|
}
|
|
5317
5508
|
async function runStandardReview(projectPath, diff, diffLines, downgraded, offset, limit) {
|
|
5318
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-
|
|
5509
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-ER2HRTFD.js");
|
|
5319
5510
|
const [diffResult, reviewResult] = await Promise.all([
|
|
5320
5511
|
handleAnalyzeDiff2({ diff, path: projectPath }),
|
|
5321
5512
|
handleCreateSelfReview2({ path: projectPath, diff })
|
|
@@ -5350,7 +5541,7 @@ async function runStandardReview(projectPath, diff, diffLines, downgraded, offse
|
|
|
5350
5541
|
};
|
|
5351
5542
|
}
|
|
5352
5543
|
async function runDeepReview(projectPath, diff, diffLines, _downgraded, offset, limit) {
|
|
5353
|
-
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-
|
|
5544
|
+
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-4VF73V4V.js");
|
|
5354
5545
|
const result = await handleRunCodeReview2({
|
|
5355
5546
|
path: projectPath,
|
|
5356
5547
|
diff,
|
|
@@ -5644,7 +5835,7 @@ async function handleDetectStaleConstraints(input) {
|
|
|
5644
5835
|
]
|
|
5645
5836
|
};
|
|
5646
5837
|
}
|
|
5647
|
-
const { detectStaleConstraints } = await import("./dist-
|
|
5838
|
+
const { detectStaleConstraints } = await import("./dist-TKHVYUWZ.js");
|
|
5648
5839
|
const result = detectStaleConstraints(
|
|
5649
5840
|
store,
|
|
5650
5841
|
windowDays,
|
|
@@ -5672,12 +5863,12 @@ async function handleDetectStaleConstraints(input) {
|
|
|
5672
5863
|
}
|
|
5673
5864
|
|
|
5674
5865
|
// src/mcp/tools/search-skills.ts
|
|
5675
|
-
|
|
5866
|
+
init_dist2();
|
|
5676
5867
|
|
|
5677
5868
|
// src/skill/health-snapshot.ts
|
|
5678
5869
|
import { execSync } from "child_process";
|
|
5679
|
-
import * as
|
|
5680
|
-
import * as
|
|
5870
|
+
import * as fs16 from "fs";
|
|
5871
|
+
import * as path19 from "path";
|
|
5681
5872
|
var CACHE_FILE = "health-snapshot.json";
|
|
5682
5873
|
var STALENESS_MS = 36e5;
|
|
5683
5874
|
function isSnapshotFresh(snapshot, projectPath) {
|
|
@@ -5694,19 +5885,19 @@ function isSnapshotFresh(snapshot, projectPath) {
|
|
|
5694
5885
|
return age < STALENESS_MS;
|
|
5695
5886
|
}
|
|
5696
5887
|
function loadCachedSnapshot(projectPath) {
|
|
5697
|
-
const filePath =
|
|
5888
|
+
const filePath = path19.join(projectPath, ".harness", CACHE_FILE);
|
|
5698
5889
|
try {
|
|
5699
|
-
const raw =
|
|
5890
|
+
const raw = fs16.readFileSync(filePath, "utf-8");
|
|
5700
5891
|
return JSON.parse(raw);
|
|
5701
5892
|
} catch {
|
|
5702
5893
|
return null;
|
|
5703
5894
|
}
|
|
5704
5895
|
}
|
|
5705
5896
|
function saveCachedSnapshot(snapshot, projectPath) {
|
|
5706
|
-
const dir =
|
|
5707
|
-
|
|
5708
|
-
const filePath =
|
|
5709
|
-
|
|
5897
|
+
const dir = path19.join(projectPath, ".harness");
|
|
5898
|
+
fs16.mkdirSync(dir, { recursive: true });
|
|
5899
|
+
const filePath = path19.join(dir, CACHE_FILE);
|
|
5900
|
+
fs16.writeFileSync(filePath, JSON.stringify(snapshot, null, 2));
|
|
5710
5901
|
}
|
|
5711
5902
|
var SIGNAL_RULES = [
|
|
5712
5903
|
["circular-deps", (c) => c.deps.circularDeps > 0],
|
|
@@ -5764,10 +5955,10 @@ function countCriticalFindings(securityData) {
|
|
|
5764
5955
|
return findings.filter((f) => f.severity === "error").length;
|
|
5765
5956
|
}
|
|
5766
5957
|
async function runHealthChecks(projectPath) {
|
|
5767
|
-
const { handleAssessProject: handleAssessProject2 } = await import("./assess-project-
|
|
5768
|
-
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-
|
|
5769
|
-
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-
|
|
5770
|
-
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-
|
|
5958
|
+
const { handleAssessProject: handleAssessProject2 } = await import("./assess-project-ZGMRPTS3.js");
|
|
5959
|
+
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-OC7TFCFF.js");
|
|
5960
|
+
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-7FIUFACI.js");
|
|
5961
|
+
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-ZWRABJNE.js");
|
|
5771
5962
|
const [assessResult, depsResult, entropyResult, securityResult] = await Promise.all([
|
|
5772
5963
|
handleAssessProject2({
|
|
5773
5964
|
path: projectPath,
|
|
@@ -5956,7 +6147,7 @@ async function handleSearchSkills(input) {
|
|
|
5956
6147
|
}
|
|
5957
6148
|
|
|
5958
6149
|
// src/skill/dispatch-engine.ts
|
|
5959
|
-
|
|
6150
|
+
init_dist2();
|
|
5960
6151
|
import { execSync as execSync2 } from "child_process";
|
|
5961
6152
|
|
|
5962
6153
|
// src/skill/recommendation-rules.ts
|
|
@@ -6551,7 +6742,7 @@ async function handleDispatchSkills(input) {
|
|
|
6551
6742
|
}
|
|
6552
6743
|
|
|
6553
6744
|
// src/mcp/tools/decay-trends.ts
|
|
6554
|
-
|
|
6745
|
+
init_dist2();
|
|
6555
6746
|
var getDecayTrendsDefinition = {
|
|
6556
6747
|
name: "get_decay_trends",
|
|
6557
6748
|
description: 'Get architecture decay trends over time. Returns stability score history and per-category trend analysis from timeline snapshots. Use to answer questions like "is the architecture decaying?" or "which metrics are getting worse?"',
|
|
@@ -6608,7 +6799,7 @@ async function handleGetDecayTrends(input) {
|
|
|
6608
6799
|
};
|
|
6609
6800
|
}
|
|
6610
6801
|
try {
|
|
6611
|
-
const core = await import("./dist-
|
|
6802
|
+
const core = await import("./dist-TKHVYUWZ.js");
|
|
6612
6803
|
const { TimelineManager } = core;
|
|
6613
6804
|
const manager = new TimelineManager(projectPath);
|
|
6614
6805
|
const timeline = manager.load();
|
|
@@ -6743,7 +6934,7 @@ async function handleCodeOutline(input) {
|
|
|
6743
6934
|
};
|
|
6744
6935
|
}
|
|
6745
6936
|
try {
|
|
6746
|
-
const { getOutline, formatOutline, EXTENSION_MAP } = await import("./dist-
|
|
6937
|
+
const { getOutline, formatOutline, EXTENSION_MAP } = await import("./dist-TKHVYUWZ.js");
|
|
6747
6938
|
const { stat } = await import("fs/promises");
|
|
6748
6939
|
const stats = await stat(targetPath).catch(() => null);
|
|
6749
6940
|
if (stats?.isFile()) {
|
|
@@ -6762,7 +6953,7 @@ async function handleCodeOutline(input) {
|
|
|
6762
6953
|
})
|
|
6763
6954
|
);
|
|
6764
6955
|
fileStats.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
6765
|
-
const { paginate: paginate2 } = await import("./dist-
|
|
6956
|
+
const { paginate: paginate2 } = await import("./dist-TKHVYUWZ.js");
|
|
6766
6957
|
const paged = paginate2(fileStats, input.offset ?? 0, input.limit ?? 30);
|
|
6767
6958
|
const results = [];
|
|
6768
6959
|
for (const entry of paged.items) {
|
|
@@ -6835,7 +7026,7 @@ async function handleCodeSearch(input) {
|
|
|
6835
7026
|
};
|
|
6836
7027
|
}
|
|
6837
7028
|
try {
|
|
6838
|
-
const { searchSymbols } = await import("./dist-
|
|
7029
|
+
const { searchSymbols } = await import("./dist-TKHVYUWZ.js");
|
|
6839
7030
|
const result = await searchSymbols(input.query, directory, input.glob);
|
|
6840
7031
|
const lines = [`Search: "${result.query}" \u2014 ${result.matches.length} matches`];
|
|
6841
7032
|
for (const match of result.matches) {
|
|
@@ -6904,7 +7095,7 @@ async function handleCodeUnfold(input) {
|
|
|
6904
7095
|
}
|
|
6905
7096
|
try {
|
|
6906
7097
|
if (input.symbol) {
|
|
6907
|
-
const { unfoldSymbol } = await import("./dist-
|
|
7098
|
+
const { unfoldSymbol } = await import("./dist-TKHVYUWZ.js");
|
|
6908
7099
|
const result = await unfoldSymbol(filePath, input.symbol);
|
|
6909
7100
|
const header = result.warning ? `${result.file}:${result.startLine}-${result.endLine} ${result.warning}
|
|
6910
7101
|
` : `${result.file}:${result.startLine}-${result.endLine}
|
|
@@ -6912,7 +7103,7 @@ async function handleCodeUnfold(input) {
|
|
|
6912
7103
|
return { content: [{ type: "text", text: header + result.content }] };
|
|
6913
7104
|
}
|
|
6914
7105
|
if (input.startLine != null && input.endLine != null) {
|
|
6915
|
-
const { unfoldRange } = await import("./dist-
|
|
7106
|
+
const { unfoldRange } = await import("./dist-TKHVYUWZ.js");
|
|
6916
7107
|
const result = await unfoldRange(filePath, input.startLine, input.endLine);
|
|
6917
7108
|
const header = `${result.file}:${result.startLine}-${result.endLine}
|
|
6918
7109
|
`;
|
|
@@ -7097,7 +7288,7 @@ async function handlePredictFailures(input) {
|
|
|
7097
7288
|
};
|
|
7098
7289
|
}
|
|
7099
7290
|
try {
|
|
7100
|
-
const core = await import("./dist-
|
|
7291
|
+
const core = await import("./dist-TKHVYUWZ.js");
|
|
7101
7292
|
const { TimelineManager, PredictionEngine, SpecImpactEstimator } = core;
|
|
7102
7293
|
const manager = new TimelineManager(projectPath);
|
|
7103
7294
|
const includeRoadmap = input.includeRoadmap !== false;
|
|
@@ -7200,12 +7391,12 @@ async function handleRecommendSkills(input) {
|
|
|
7200
7391
|
}
|
|
7201
7392
|
|
|
7202
7393
|
// src/mcp/tools/advise-skills.ts
|
|
7203
|
-
import
|
|
7394
|
+
import path21 from "path";
|
|
7204
7395
|
|
|
7205
7396
|
// src/commands/advise-skills.ts
|
|
7206
7397
|
import { Command as Command2 } from "commander";
|
|
7207
|
-
import
|
|
7208
|
-
import
|
|
7398
|
+
import fs17 from "fs";
|
|
7399
|
+
import path20 from "path";
|
|
7209
7400
|
import chalk from "chalk";
|
|
7210
7401
|
|
|
7211
7402
|
// src/skill/content-matcher-types.ts
|
|
@@ -7724,10 +7915,10 @@ function renderTable(matches) {
|
|
|
7724
7915
|
|
|
7725
7916
|
// src/commands/advise-skills.ts
|
|
7726
7917
|
function readPackageDeps(cwd) {
|
|
7727
|
-
const pkgPath =
|
|
7728
|
-
if (!
|
|
7918
|
+
const pkgPath = path20.join(cwd, "package.json");
|
|
7919
|
+
if (!fs17.existsSync(pkgPath)) return { deps: {}, devDeps: {} };
|
|
7729
7920
|
try {
|
|
7730
|
-
const pkg = JSON.parse(
|
|
7921
|
+
const pkg = JSON.parse(fs17.readFileSync(pkgPath, "utf-8"));
|
|
7731
7922
|
const deps = typeof pkg.dependencies === "object" && pkg.dependencies !== null ? pkg.dependencies : {};
|
|
7732
7923
|
const devDeps = typeof pkg.devDependencies === "object" && pkg.devDependencies !== null ? pkg.devDependencies : {};
|
|
7733
7924
|
return { deps, devDeps };
|
|
@@ -7736,10 +7927,10 @@ function readPackageDeps(cwd) {
|
|
|
7736
7927
|
}
|
|
7737
7928
|
}
|
|
7738
7929
|
function readSpecText(specPath) {
|
|
7739
|
-
if (!
|
|
7930
|
+
if (!fs17.existsSync(specPath)) {
|
|
7740
7931
|
throw new Error(`Spec not found: ${specPath}`);
|
|
7741
7932
|
}
|
|
7742
|
-
return
|
|
7933
|
+
return fs17.readFileSync(specPath, "utf-8");
|
|
7743
7934
|
}
|
|
7744
7935
|
function filterMatchesByTier(result, top, thorough) {
|
|
7745
7936
|
const applySkills = result.matches.filter((m) => m.tier === "apply").slice(0, top);
|
|
@@ -7749,11 +7940,11 @@ function filterMatchesByTier(result, top, thorough) {
|
|
|
7749
7940
|
}
|
|
7750
7941
|
function extractFeatureName(specText, specPath) {
|
|
7751
7942
|
const titleMatch = specText.match(/^#\s+(.+)/m);
|
|
7752
|
-
return titleMatch?.[1] ??
|
|
7943
|
+
return titleMatch?.[1] ?? path20.basename(path20.dirname(specPath));
|
|
7753
7944
|
}
|
|
7754
7945
|
async function runAdviseSkills(options) {
|
|
7755
7946
|
const cwd = options.cwd ?? process.cwd();
|
|
7756
|
-
const specPath =
|
|
7947
|
+
const specPath = path20.resolve(cwd, options.specPath);
|
|
7757
7948
|
const specText = readSpecText(specPath);
|
|
7758
7949
|
const { deps, devDeps } = readPackageDeps(cwd);
|
|
7759
7950
|
const signals = extractSignals(specText, deps, devDeps);
|
|
@@ -7764,9 +7955,9 @@ async function runAdviseSkills(options) {
|
|
|
7764
7955
|
const result = matchContent(index, signals);
|
|
7765
7956
|
const filteredResult = filterMatchesByTier(result, options.top ?? 5, !!options.thorough);
|
|
7766
7957
|
const featureName = extractFeatureName(specText, specPath);
|
|
7767
|
-
const skillsMdPath =
|
|
7958
|
+
const skillsMdPath = path20.join(path20.dirname(specPath), "SKILLS.md");
|
|
7768
7959
|
const md = generateSkillsMd(featureName, filteredResult, totalSkills);
|
|
7769
|
-
|
|
7960
|
+
fs17.writeFileSync(skillsMdPath, md, "utf-8");
|
|
7770
7961
|
return { result: filteredResult, skillsMdPath, featureName, totalSkills };
|
|
7771
7962
|
}
|
|
7772
7963
|
function formatOutput(featureName, result, skillsMdPath, totalSkills) {
|
|
@@ -7860,7 +8051,7 @@ async function handleAdviseSkills(input) {
|
|
|
7860
8051
|
});
|
|
7861
8052
|
const response = {
|
|
7862
8053
|
featureName,
|
|
7863
|
-
skillsPath:
|
|
8054
|
+
skillsPath: path21.relative(projectRoot, skillsMdPath).replaceAll("\\", "/"),
|
|
7864
8055
|
totalScanned: totalSkills,
|
|
7865
8056
|
scanDuration: result.scanDuration,
|
|
7866
8057
|
apply: result.matches.filter((m) => m.tier === "apply").map((m) => ({
|
|
@@ -7893,7 +8084,7 @@ async function handleAdviseSkills(input) {
|
|
|
7893
8084
|
}
|
|
7894
8085
|
|
|
7895
8086
|
// src/mcp/tools/compact.ts
|
|
7896
|
-
|
|
8087
|
+
init_dist2();
|
|
7897
8088
|
var COMPACT_TOOL_DEFAULT_BUDGET = 2e3;
|
|
7898
8089
|
var compactToolDefinition = {
|
|
7899
8090
|
name: "compact",
|
|
@@ -8206,7 +8397,7 @@ async function handleDetectConstraintEmergence(input) {
|
|
|
8206
8397
|
}
|
|
8207
8398
|
const nodePath = await import("path");
|
|
8208
8399
|
const historyPath = nodePath.resolve(projectPath, ".harness/arch/violation-history.json");
|
|
8209
|
-
const { ViolationHistoryManager, detectEmergentConstraints } = await import("./dist-
|
|
8400
|
+
const { ViolationHistoryManager, detectEmergentConstraints } = await import("./dist-TKHVYUWZ.js");
|
|
8210
8401
|
const manager = new ViolationHistoryManager(historyPath);
|
|
8211
8402
|
const history = manager.load();
|
|
8212
8403
|
const options = { windowWeeks, minOccurrences };
|
|
@@ -8294,7 +8485,7 @@ async function handleRunCIChecks(input) {
|
|
|
8294
8485
|
};
|
|
8295
8486
|
}
|
|
8296
8487
|
try {
|
|
8297
|
-
const { runCIChecks } = await import("./dist-
|
|
8488
|
+
const { runCIChecks } = await import("./dist-TKHVYUWZ.js");
|
|
8298
8489
|
const skip = input.checks ? VALID_CHECKS.filter((c) => !input.checks.includes(c)) : [];
|
|
8299
8490
|
const result = await runCIChecks({
|
|
8300
8491
|
projectRoot: projectPath,
|
|
@@ -8356,7 +8547,7 @@ async function handleGenerateBlueprint(input) {
|
|
|
8356
8547
|
};
|
|
8357
8548
|
}
|
|
8358
8549
|
try {
|
|
8359
|
-
const { ProjectScanner } = await import("./dist-
|
|
8550
|
+
const { ProjectScanner } = await import("./dist-TKHVYUWZ.js");
|
|
8360
8551
|
const scanner = new ProjectScanner(projectPath);
|
|
8361
8552
|
const data = await scanner.scan();
|
|
8362
8553
|
return {
|
|
@@ -8543,7 +8734,10 @@ var TOOL_DEFINITIONS = [
|
|
|
8543
8734
|
generateBlueprintDefinition,
|
|
8544
8735
|
triggerMaintenanceJobDefinition,
|
|
8545
8736
|
listGatewayTokensDefinition,
|
|
8546
|
-
subscribeWebhookDefinition
|
|
8737
|
+
subscribeWebhookDefinition,
|
|
8738
|
+
searchSessionsDefinition,
|
|
8739
|
+
summarizeSessionDefinition,
|
|
8740
|
+
insightsSummaryDefinition
|
|
8547
8741
|
].map((def) => ({ ...def, trustedOutput: true }));
|
|
8548
8742
|
var TOOL_HANDLERS = {
|
|
8549
8743
|
validate_project: handleValidateProject,
|
|
@@ -8609,7 +8803,10 @@ var TOOL_HANDLERS = {
|
|
|
8609
8803
|
generate_blueprint: handleGenerateBlueprint,
|
|
8610
8804
|
trigger_maintenance_job: handleTriggerMaintenanceJob,
|
|
8611
8805
|
list_gateway_tokens: handleListGatewayTokens,
|
|
8612
|
-
subscribe_webhook: handleSubscribeWebhook
|
|
8806
|
+
subscribe_webhook: handleSubscribeWebhook,
|
|
8807
|
+
search_sessions: handleSearchSessions,
|
|
8808
|
+
summarize_session: handleSummarizeSession,
|
|
8809
|
+
insights_summary: handleInsightsSummary
|
|
8613
8810
|
};
|
|
8614
8811
|
var RESOURCE_DEFINITIONS = [
|
|
8615
8812
|
{
|
|
@@ -8711,7 +8908,7 @@ async function appendUpdateNotification(result, resolvedRoot) {
|
|
|
8711
8908
|
shouldRunCheck,
|
|
8712
8909
|
readCheckState,
|
|
8713
8910
|
spawnBackgroundCheck
|
|
8714
|
-
} = await import("./dist-
|
|
8911
|
+
} = await import("./dist-TKHVYUWZ.js");
|
|
8715
8912
|
const { CLI_VERSION } = await import("./version-CUI434OP.js");
|
|
8716
8913
|
const configInterval = readConfigInterval(resolvedRoot);
|
|
8717
8914
|
const DEFAULT_INTERVAL = 864e5;
|