@harness-engineering/cli 2.7.0 → 2.7.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/naming-craft/SKILL.md +74 -2
- package/dist/agents/skills/codex/naming-craft/SKILL.md +74 -2
- package/dist/agents/skills/cursor/naming-craft/SKILL.md +74 -2
- package/dist/agents/skills/gemini-cli/naming-craft/SKILL.md +74 -2
- package/dist/{agents-md-267R2NUJ.js → agents-md-FKMKH6ZF.js} +3 -3
- package/dist/{analyzer-VY6DJVOU-WYKV3TTW.js → analyzer-H3AHBFSL-KPOPJYRB.js} +7 -7
- package/dist/{architecture-ZTEHGIHD.js → architecture-LUR2I67H.js} +4 -4
- package/dist/{assess-project-OKDW3YSK.js → assess-project-OJWECOP2.js} +1 -1
- package/dist/bin/harness-mcp.js +14 -14
- package/dist/bin/harness.js +23 -23
- package/dist/{check-phase-gate-YJWFDW66.js → check-phase-gate-HS5KYLRO.js} +4 -4
- package/dist/{chunk-MQG7FHXX.js → chunk-7AF6C5GE.js} +3 -3
- package/dist/{chunk-4EGPFB7V.js → chunk-7PLIWP7U.js} +961 -256
- package/dist/{chunk-WOXR6I3R.js → chunk-B2VAYLYI.js} +1 -1
- package/dist/{chunk-67RP7MLR.js → chunk-CZPOPMMI.js} +2 -2
- package/dist/{chunk-OLTVDPA2.js → chunk-FC4JPM6W.js} +2 -2
- package/dist/{chunk-CXAHK5PJ.js → chunk-FEKBXX2J.js} +6 -6
- package/dist/{chunk-B4OLYXZ4.js → chunk-FXZI6NJ2.js} +39 -4
- package/dist/{chunk-6T5AYG5S.js → chunk-GGSNWH7P.js} +2 -2
- package/dist/{chunk-ZKA3TGYS.js → chunk-INBTDBV2.js} +1 -1
- package/dist/{chunk-HMMSWRWR.js → chunk-KN3EMDZ5.js} +2 -2
- package/dist/{chunk-OQE6ME2Z.js → chunk-LECXPXS3.js} +1 -1
- package/dist/{chunk-HLPY3RHE.js → chunk-LGYXR2KZ.js} +799 -515
- package/dist/{chunk-QUPC37UB.js → chunk-LYIPI2SJ.js} +3 -3
- package/dist/{chunk-S7GEONXL.js → chunk-N5NSSLMU.js} +1 -1
- package/dist/{chunk-P7EO7USC.js → chunk-NIVWM7OW.js} +5 -5
- package/dist/{chunk-PARV3G2F.js → chunk-O2ASYKA6.js} +1 -1
- package/dist/{chunk-XTIPZUPR.js → chunk-PTHX545Q.js} +1 -1
- package/dist/{chunk-B3B64OPD.js → chunk-RJ2WEES5.js} +1 -1
- package/dist/{chunk-TIZ3L6CU.js → chunk-VI4IS55S.js} +6 -6
- package/dist/{chunk-VG6UK6G6.js → chunk-VSIRUZQP.js} +1 -1
- package/dist/{chunk-IY2TZLY5.js → chunk-WZY5U6NS.js} +4 -4
- package/dist/{chunk-W3PDVZ4I.js → chunk-Y4T6ENKQ.js} +8 -8
- package/dist/{chunk-Z2GUITAS.js → chunk-Z3TMCCZB.js} +3 -3
- package/dist/{ci-workflow-YGTQTNVC.js → ci-workflow-MDSTHJOY.js} +3 -3
- package/dist/{dist-XIJWWQ5N.js → dist-72ID44UE.js} +2 -2
- package/dist/{docs-KCTLXK2G.js → docs-2RFOJ6XY.js} +4 -4
- package/dist/{engine-J64WPH5K.js → engine-BSFKOGPN.js} +3 -3
- package/dist/{entropy-M27JUL3V.js → entropy-3UX6644G.js} +3 -3
- package/dist/{feedback-W25QO3OL.js → feedback-CVCFYND4.js} +1 -1
- package/dist/{generate-agent-definitions-RNMU5U5R.js → generate-agent-definitions-HZ3XENWO.js} +4 -4
- package/dist/index.d.ts +425 -6
- package/dist/index.js +23 -23
- package/dist/{loader-HZKJ5ABV.js → loader-6RHWU5FH.js} +3 -3
- package/dist/{mcp-NEAPIDTT.js → mcp-OYR26JDI.js} +14 -14
- package/dist/{performance-3AVQUDRG.js → performance-JJMIRXCH.js} +4 -4
- package/dist/{review-pipeline-KA7SGUXJ.js → review-pipeline-BHQZIXWZ.js} +3 -3
- package/dist/{runtime-IP6FVV5M.js → runtime-DALTAVTN.js} +3 -3
- package/dist/{security-EAR4FJWI.js → security-RMLMYFPB.js} +1 -1
- package/dist/{validate-EVH3UXIC.js → validate-R7DZRDFK.js} +4 -4
- package/dist/{validate-cross-check-SNE3SQOB.js → validate-cross-check-AUUZFNVL.js} +3 -3
- package/package.json +4 -4
|
@@ -3,20 +3,20 @@ import {
|
|
|
3
3
|
handleGetSecurityTrends,
|
|
4
4
|
handleRunSecurityScan,
|
|
5
5
|
runSecurityScanDefinition
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CZPOPMMI.js";
|
|
7
7
|
import {
|
|
8
8
|
handleRunCodeReview,
|
|
9
9
|
runCodeReviewDefinition,
|
|
10
10
|
sortFindingsBySeverity
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-KN3EMDZ5.js";
|
|
12
12
|
import {
|
|
13
13
|
assessProjectDefinition,
|
|
14
14
|
handleAssessProject
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VI4IS55S.js";
|
|
16
16
|
import {
|
|
17
17
|
detectEntropyDefinition,
|
|
18
18
|
handleDetectEntropy
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-LYIPI2SJ.js";
|
|
20
20
|
import {
|
|
21
21
|
checkPerformanceDefinition,
|
|
22
22
|
getCriticalPathsDefinition,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
handleGetPerfBaselines,
|
|
27
27
|
handleUpdatePerfBaselines,
|
|
28
28
|
updatePerfBaselinesDefinition
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-FEKBXX2J.js";
|
|
30
30
|
import {
|
|
31
31
|
getBusinessKnowledgeResource
|
|
32
32
|
} from "./chunk-IOW3MW2K.js";
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
handleCreateSelfReview,
|
|
38
38
|
handleRequestPeerReview,
|
|
39
39
|
requestPeerReviewDefinition
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-Z3TMCCZB.js";
|
|
41
41
|
import {
|
|
42
42
|
GENERATED_HEADER_CLAUDE,
|
|
43
43
|
GENERATED_HEADER_CODEX,
|
|
@@ -53,18 +53,18 @@ import {
|
|
|
53
53
|
import {
|
|
54
54
|
handleValidateProject,
|
|
55
55
|
validateToolDefinition
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-7AF6C5GE.js";
|
|
57
57
|
import {
|
|
58
58
|
checkDependenciesDefinition,
|
|
59
59
|
handleCheckDependencies
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-GGSNWH7P.js";
|
|
61
61
|
import {
|
|
62
62
|
resolveProjectConfig
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-VSIRUZQP.js";
|
|
64
64
|
import {
|
|
65
65
|
checkDocsDefinition,
|
|
66
66
|
handleCheckDocs
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-NIVWM7OW.js";
|
|
68
68
|
import {
|
|
69
69
|
resultToMcpResponse
|
|
70
70
|
} from "./chunk-RC3OI5NK.js";
|
|
@@ -87,8 +87,10 @@ import {
|
|
|
87
87
|
SkillMetadataSchema
|
|
88
88
|
} from "./chunk-HIK6OEUF.js";
|
|
89
89
|
import {
|
|
90
|
+
findConfigFile,
|
|
91
|
+
loadConfig,
|
|
90
92
|
resolveConfig
|
|
91
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-FXZI6NJ2.js";
|
|
92
94
|
import {
|
|
93
95
|
logger
|
|
94
96
|
} from "./chunk-EBJQ6N4M.js";
|
|
@@ -118,7 +120,7 @@ import {
|
|
|
118
120
|
scanForInjection,
|
|
119
121
|
serializeEnvelope,
|
|
120
122
|
writeTaint
|
|
121
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-WZY5U6NS.js";
|
|
122
124
|
import {
|
|
123
125
|
Err,
|
|
124
126
|
INDEXED_FILE_KINDS,
|
|
@@ -571,7 +573,7 @@ init_dist2();
|
|
|
571
573
|
init_dist();
|
|
572
574
|
var searchSessionsDefinition = {
|
|
573
575
|
name: "search_sessions",
|
|
574
|
-
description: "Full-text search over archived + live session content (
|
|
576
|
+
description: "Full-text search over archived + live session content (FTS5/BM25).",
|
|
575
577
|
inputSchema: {
|
|
576
578
|
type: "object",
|
|
577
579
|
properties: {
|
|
@@ -627,7 +629,7 @@ import * as fs2 from "fs";
|
|
|
627
629
|
import * as path2 from "path";
|
|
628
630
|
var summarizeSessionDefinition = {
|
|
629
631
|
name: "summarize_session",
|
|
630
|
-
description: "Generate or regenerate the LLM `llm-summary.md` for an archived session
|
|
632
|
+
description: "Generate or regenerate the LLM `llm-summary.md` for an archived session.",
|
|
631
633
|
inputSchema: {
|
|
632
634
|
type: "object",
|
|
633
635
|
properties: {
|
|
@@ -714,7 +716,7 @@ init_dist2();
|
|
|
714
716
|
init_dist();
|
|
715
717
|
var insightsSummaryDefinition = {
|
|
716
718
|
name: "insights_summary",
|
|
717
|
-
description: "Composite report combining health, entropy, decay, attention, and impact
|
|
719
|
+
description: "Composite report combining health, entropy, decay, attention, and impact.",
|
|
718
720
|
inputSchema: {
|
|
719
721
|
type: "object",
|
|
720
722
|
properties: {
|
|
@@ -735,7 +737,7 @@ async function handleInsightsSummary(input) {
|
|
|
735
737
|
const skip = Array.isArray(input.skip) ? input.skip.filter(
|
|
736
738
|
(k) => typeof k === "string" && INSIGHTS_KEYS.includes(k)
|
|
737
739
|
) : void 0;
|
|
738
|
-
const { composeInsights } = await import("./dist-
|
|
740
|
+
const { composeInsights } = await import("./dist-72ID44UE.js");
|
|
739
741
|
const report = await composeInsights(projectPath, {
|
|
740
742
|
...skip && skip.length > 0 && { skip }
|
|
741
743
|
});
|
|
@@ -911,7 +913,7 @@ ${skippedMsg}`
|
|
|
911
913
|
async function handleInitProject(input) {
|
|
912
914
|
const i = input;
|
|
913
915
|
try {
|
|
914
|
-
const { TemplateEngine } = await import("./engine-
|
|
916
|
+
const { TemplateEngine } = await import("./engine-BSFKOGPN.js");
|
|
915
917
|
const engine = new TemplateEngine(resolveTemplatesDir());
|
|
916
918
|
const safePath = sanitizePath(i.path);
|
|
917
919
|
const detected = tryDetectFramework(engine, safePath, i);
|
|
@@ -933,7 +935,7 @@ var listPersonasDefinition = {
|
|
|
933
935
|
inputSchema: { type: "object", properties: {} }
|
|
934
936
|
};
|
|
935
937
|
async function handleListPersonas() {
|
|
936
|
-
const { listPersonas } = await import("./loader-
|
|
938
|
+
const { listPersonas } = await import("./loader-6RHWU5FH.js");
|
|
937
939
|
const result = listPersonas(resolvePersonasDir());
|
|
938
940
|
return resultToMcpResponse(result);
|
|
939
941
|
}
|
|
@@ -957,10 +959,10 @@ async function handleGeneratePersonaArtifacts(input) {
|
|
|
957
959
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.name)) {
|
|
958
960
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.name}`)));
|
|
959
961
|
}
|
|
960
|
-
const { loadPersona } = await import("./loader-
|
|
961
|
-
const { generateRuntime } = await import("./runtime-
|
|
962
|
-
const { generateAgentsMd } = await import("./agents-md-
|
|
963
|
-
const { generateCIWorkflow } = await import("./ci-workflow-
|
|
962
|
+
const { loadPersona } = await import("./loader-6RHWU5FH.js");
|
|
963
|
+
const { generateRuntime } = await import("./runtime-DALTAVTN.js");
|
|
964
|
+
const { generateAgentsMd } = await import("./agents-md-FKMKH6ZF.js");
|
|
965
|
+
const { generateCIWorkflow } = await import("./ci-workflow-MDSTHJOY.js");
|
|
964
966
|
const personasDir = resolvePersonasDir();
|
|
965
967
|
const filePath = path4.join(personasDir, `${input.name}.yaml`);
|
|
966
968
|
if (!filePath.startsWith(personasDir)) {
|
|
@@ -1015,7 +1017,7 @@ async function handleRunPersona(input) {
|
|
|
1015
1017
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(input.persona)) {
|
|
1016
1018
|
return resultToMcpResponse(Err(new Error(`Invalid persona name: ${input.persona}`)));
|
|
1017
1019
|
}
|
|
1018
|
-
const { loadPersona } = await import("./loader-
|
|
1020
|
+
const { loadPersona } = await import("./loader-6RHWU5FH.js");
|
|
1019
1021
|
const { runPersona } = await import("./runner-AAEF2TXY.js");
|
|
1020
1022
|
const { executeSkill } = await import("./skill-executor-MOCUIAYS.js");
|
|
1021
1023
|
const personasDir = resolvePersonasDir();
|
|
@@ -1460,7 +1462,7 @@ function loadOrGenerateProfile(projectRoot) {
|
|
|
1460
1462
|
// src/mcp/tools/event-emitter.ts
|
|
1461
1463
|
async function emitSkillEvent(projectPath, event) {
|
|
1462
1464
|
try {
|
|
1463
|
-
const { emitEvent } = await import("./dist-
|
|
1465
|
+
const { emitEvent } = await import("./dist-72ID44UE.js");
|
|
1464
1466
|
await emitEvent(projectPath, event);
|
|
1465
1467
|
} catch {
|
|
1466
1468
|
}
|
|
@@ -1732,7 +1734,7 @@ async function autoSyncRoadmap(projectPath) {
|
|
|
1732
1734
|
try {
|
|
1733
1735
|
const roadmapFile = path11.join(projectPath, "docs", "roadmap.md");
|
|
1734
1736
|
if (!fs10.existsSync(roadmapFile)) return;
|
|
1735
|
-
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges } = await import("./dist-
|
|
1737
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges } = await import("./dist-72ID44UE.js");
|
|
1736
1738
|
const raw = fs10.readFileSync(roadmapFile, "utf-8");
|
|
1737
1739
|
const parseResult = parseRoadmap(raw);
|
|
1738
1740
|
if (!parseResult.ok) return;
|
|
@@ -1762,7 +1764,7 @@ async function triggerExternalSync(projectPath, roadmapFile) {
|
|
|
1762
1764
|
console.warn("[roadmap-sync] GITHUB_TOKEN not found \u2014 external sync skipped");
|
|
1763
1765
|
return;
|
|
1764
1766
|
}
|
|
1765
|
-
const { fullSync, GitHubIssuesSyncAdapter } = await import("./dist-
|
|
1767
|
+
const { fullSync, GitHubIssuesSyncAdapter } = await import("./dist-72ID44UE.js");
|
|
1766
1768
|
const adapter = new GitHubIssuesSyncAdapter({
|
|
1767
1769
|
token,
|
|
1768
1770
|
config: trackerConfig
|
|
@@ -1859,12 +1861,12 @@ var manageStateDefinition = {
|
|
|
1859
1861
|
}
|
|
1860
1862
|
};
|
|
1861
1863
|
async function handleShow(projectPath, input) {
|
|
1862
|
-
const { loadState } = await import("./dist-
|
|
1864
|
+
const { loadState } = await import("./dist-72ID44UE.js");
|
|
1863
1865
|
return resultToMcpResponse(await loadState(projectPath, input.stream, input.session));
|
|
1864
1866
|
}
|
|
1865
1867
|
async function handleLearn(projectPath, input) {
|
|
1866
1868
|
if (!input.learning) return mcpError("Error: learning is required for learn action");
|
|
1867
|
-
const { appendLearning } = await import("./dist-
|
|
1869
|
+
const { appendLearning } = await import("./dist-72ID44UE.js");
|
|
1868
1870
|
const result = await appendLearning(
|
|
1869
1871
|
projectPath,
|
|
1870
1872
|
input.learning,
|
|
@@ -1879,7 +1881,7 @@ async function handleLearn(projectPath, input) {
|
|
|
1879
1881
|
async function handleFailure(projectPath, input) {
|
|
1880
1882
|
if (!input.description) return mcpError("Error: description is required for failure action");
|
|
1881
1883
|
if (!input.failureType) return mcpError("Error: failureType is required for failure action");
|
|
1882
|
-
const { appendFailure } = await import("./dist-
|
|
1884
|
+
const { appendFailure } = await import("./dist-72ID44UE.js");
|
|
1883
1885
|
const result = await appendFailure(
|
|
1884
1886
|
projectPath,
|
|
1885
1887
|
input.description,
|
|
@@ -1898,19 +1900,19 @@ async function handleFailure(projectPath, input) {
|
|
|
1898
1900
|
return resultToMcpResponse(Ok({ recorded: true }));
|
|
1899
1901
|
}
|
|
1900
1902
|
async function handleArchive(projectPath, input) {
|
|
1901
|
-
const { archiveFailures } = await import("./dist-
|
|
1903
|
+
const { archiveFailures } = await import("./dist-72ID44UE.js");
|
|
1902
1904
|
const result = await archiveFailures(projectPath, input.stream, input.session);
|
|
1903
1905
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1904
1906
|
return resultToMcpResponse(Ok({ archived: true }));
|
|
1905
1907
|
}
|
|
1906
1908
|
async function handleReset(projectPath, input) {
|
|
1907
|
-
const { saveState, DEFAULT_STATE } = await import("./dist-
|
|
1909
|
+
const { saveState, DEFAULT_STATE } = await import("./dist-72ID44UE.js");
|
|
1908
1910
|
const result = await saveState(projectPath, { ...DEFAULT_STATE }, input.stream, input.session);
|
|
1909
1911
|
if (!result.ok) return resultToMcpResponse(result);
|
|
1910
1912
|
return resultToMcpResponse(Ok({ reset: true }));
|
|
1911
1913
|
}
|
|
1912
1914
|
async function handleGate(projectPath, input) {
|
|
1913
|
-
const { runMechanicalGate } = await import("./dist-
|
|
1915
|
+
const { runMechanicalGate } = await import("./dist-72ID44UE.js");
|
|
1914
1916
|
const result = await runMechanicalGate(projectPath);
|
|
1915
1917
|
if (result.ok) {
|
|
1916
1918
|
await emitSkillEvent(projectPath, {
|
|
@@ -1930,7 +1932,7 @@ async function handleGate(projectPath, input) {
|
|
|
1930
1932
|
}
|
|
1931
1933
|
async function handleSaveHandoff(projectPath, input) {
|
|
1932
1934
|
if (!input.handoff) return mcpError("Error: handoff is required for save-handoff action");
|
|
1933
|
-
const { saveHandoff } = await import("./dist-
|
|
1935
|
+
const { saveHandoff } = await import("./dist-72ID44UE.js");
|
|
1934
1936
|
const result = await saveHandoff(
|
|
1935
1937
|
projectPath,
|
|
1936
1938
|
input.handoff,
|
|
@@ -1952,7 +1954,7 @@ async function handleSaveHandoff(projectPath, input) {
|
|
|
1952
1954
|
return resultToMcpResponse(Ok({ saved: true }));
|
|
1953
1955
|
}
|
|
1954
1956
|
async function handleLoadHandoff(projectPath, input) {
|
|
1955
|
-
const { loadHandoff } = await import("./dist-
|
|
1957
|
+
const { loadHandoff } = await import("./dist-72ID44UE.js");
|
|
1956
1958
|
return resultToMcpResponse(await loadHandoff(projectPath, input.stream, input.session));
|
|
1957
1959
|
}
|
|
1958
1960
|
async function handleAppendEntry(projectPath, input) {
|
|
@@ -1960,7 +1962,7 @@ async function handleAppendEntry(projectPath, input) {
|
|
|
1960
1962
|
if (!input.authorSkill) return mcpError("Error: authorSkill is required for append_entry action");
|
|
1961
1963
|
if (!input.content) return mcpError("Error: content is required for append_entry action");
|
|
1962
1964
|
if (input.session) {
|
|
1963
|
-
const { appendSessionEntry } = await import("./dist-
|
|
1965
|
+
const { appendSessionEntry } = await import("./dist-72ID44UE.js");
|
|
1964
1966
|
const result = await appendSessionEntry(
|
|
1965
1967
|
projectPath,
|
|
1966
1968
|
input.session,
|
|
@@ -1973,7 +1975,7 @@ async function handleAppendEntry(projectPath, input) {
|
|
|
1973
1975
|
if (input.section !== "decisions") {
|
|
1974
1976
|
return mcpError("Error: session is required for non-decisions sections");
|
|
1975
1977
|
}
|
|
1976
|
-
const { loadState, saveState } = await import("./dist-
|
|
1978
|
+
const { loadState, saveState } = await import("./dist-72ID44UE.js");
|
|
1977
1979
|
const lr = await loadState(projectPath, input.stream);
|
|
1978
1980
|
if (!lr.ok) return resultToMcpResponse(lr);
|
|
1979
1981
|
lr.value.decisions.push({
|
|
@@ -1991,7 +1993,7 @@ async function handleUpdateEntryStatus(projectPath, input) {
|
|
|
1991
1993
|
if (!input.entryId) return mcpError("Error: entryId is required for update_entry_status action");
|
|
1992
1994
|
if (!input.newStatus)
|
|
1993
1995
|
return mcpError("Error: newStatus is required for update_entry_status action");
|
|
1994
|
-
const { updateSessionEntryStatus } = await import("./dist-
|
|
1996
|
+
const { updateSessionEntryStatus } = await import("./dist-72ID44UE.js");
|
|
1995
1997
|
const result = await updateSessionEntryStatus(
|
|
1996
1998
|
projectPath,
|
|
1997
1999
|
input.session,
|
|
@@ -2004,7 +2006,7 @@ async function handleUpdateEntryStatus(projectPath, input) {
|
|
|
2004
2006
|
async function handleReadSection(projectPath, input) {
|
|
2005
2007
|
if (!input.session) return mcpError("Error: session is required for read_section action");
|
|
2006
2008
|
if (!input.section) return mcpError("Error: section is required for read_section action");
|
|
2007
|
-
const { readSessionSection } = await import("./dist-
|
|
2009
|
+
const { readSessionSection } = await import("./dist-72ID44UE.js");
|
|
2008
2010
|
const result = await readSessionSection(
|
|
2009
2011
|
projectPath,
|
|
2010
2012
|
input.session,
|
|
@@ -2014,13 +2016,13 @@ async function handleReadSection(projectPath, input) {
|
|
|
2014
2016
|
}
|
|
2015
2017
|
async function handleReadSections(projectPath, input) {
|
|
2016
2018
|
if (!input.session) return mcpError("Error: session is required for read_sections action");
|
|
2017
|
-
const { readSessionSections } = await import("./dist-
|
|
2019
|
+
const { readSessionSections } = await import("./dist-72ID44UE.js");
|
|
2018
2020
|
const result = await readSessionSections(projectPath, input.session);
|
|
2019
2021
|
return resultToMcpResponse(result);
|
|
2020
2022
|
}
|
|
2021
2023
|
async function handleArchiveSession(projectPath, input) {
|
|
2022
2024
|
if (!input.session) return mcpError("Error: session is required for archive_session action");
|
|
2023
|
-
const { archiveSession } = await import("./dist-
|
|
2025
|
+
const { archiveSession } = await import("./dist-72ID44UE.js");
|
|
2024
2026
|
const { buildArchiveHooks } = await import("@harness-engineering/orchestrator");
|
|
2025
2027
|
const hooks = buildArchiveHooks({ projectPath });
|
|
2026
2028
|
const result = await archiveSession(projectPath, input.session, { hooks });
|
|
@@ -2102,7 +2104,7 @@ var listStreamsDefinition = {
|
|
|
2102
2104
|
};
|
|
2103
2105
|
async function handleListStreams(input) {
|
|
2104
2106
|
try {
|
|
2105
|
-
const { listStreams, loadStreamIndex } = await import("./dist-
|
|
2107
|
+
const { listStreams, loadStreamIndex } = await import("./dist-72ID44UE.js");
|
|
2106
2108
|
const projectPath = sanitizePath(input.path);
|
|
2107
2109
|
const indexResult = await loadStreamIndex(projectPath);
|
|
2108
2110
|
const streamsResult = await listStreams(projectPath);
|
|
@@ -2140,7 +2142,7 @@ var checkPhaseGateDefinition = {
|
|
|
2140
2142
|
};
|
|
2141
2143
|
async function handleCheckPhaseGate(input) {
|
|
2142
2144
|
try {
|
|
2143
|
-
const { runCheckPhaseGate } = await import("./check-phase-gate-
|
|
2145
|
+
const { runCheckPhaseGate } = await import("./check-phase-gate-HS5KYLRO.js");
|
|
2144
2146
|
const result = await runCheckPhaseGate({ cwd: sanitizePath(input.path) });
|
|
2145
2147
|
if (result.ok) {
|
|
2146
2148
|
return { content: [{ type: "text", text: JSON.stringify(result.value) }] };
|
|
@@ -2196,7 +2198,7 @@ async function handleValidateCrossCheck(input) {
|
|
|
2196
2198
|
};
|
|
2197
2199
|
}
|
|
2198
2200
|
try {
|
|
2199
|
-
const { runCrossCheck } = await import("./validate-cross-check-
|
|
2201
|
+
const { runCrossCheck } = await import("./validate-cross-check-AUUZFNVL.js");
|
|
2200
2202
|
const specsDir = path12.resolve(projectPath, input.specsDir ?? "docs/specs");
|
|
2201
2203
|
if (!specsDir.startsWith(projectPath)) {
|
|
2202
2204
|
return {
|
|
@@ -2705,11 +2707,11 @@ function resolveOutputDir(platform, opts) {
|
|
|
2705
2707
|
}
|
|
2706
2708
|
async function confirmDeletion(files) {
|
|
2707
2709
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2708
|
-
return new Promise((
|
|
2710
|
+
return new Promise((resolve5) => {
|
|
2709
2711
|
rl.question(`
|
|
2710
2712
|
Remove ${files.length} orphaned command(s)? (y/N) `, (answer) => {
|
|
2711
2713
|
rl.close();
|
|
2712
|
-
|
|
2714
|
+
resolve5(answer.toLowerCase() === "y");
|
|
2713
2715
|
});
|
|
2714
2716
|
});
|
|
2715
2717
|
}
|
|
@@ -3019,7 +3021,7 @@ async function handleGenerateSlashCommands(input) {
|
|
|
3019
3021
|
// src/mcp/resources/state.ts
|
|
3020
3022
|
async function getStateResource(projectRoot) {
|
|
3021
3023
|
try {
|
|
3022
|
-
const { loadState, migrateToStreams } = await import("./dist-
|
|
3024
|
+
const { loadState, migrateToStreams } = await import("./dist-72ID44UE.js");
|
|
3023
3025
|
await migrateToStreams(projectRoot);
|
|
3024
3026
|
const result = await loadState(projectRoot);
|
|
3025
3027
|
if (result.ok) {
|
|
@@ -3630,8 +3632,8 @@ async function handleIngestSource(input) {
|
|
|
3630
3632
|
const projectPath = sanitizePath(input.path);
|
|
3631
3633
|
const graphDir = path16.join(projectPath, ".harness", "graph");
|
|
3632
3634
|
const { GraphStore, CodeIngestor, TopologicalLinker, KnowledgeIngestor, GitIngestor } = await import("./dist-R3TOOPJ7.js");
|
|
3633
|
-
const
|
|
3634
|
-
await
|
|
3635
|
+
const fs44 = await import("fs/promises");
|
|
3636
|
+
await fs44.mkdir(graphDir, { recursive: true });
|
|
3635
3637
|
const store = new GraphStore();
|
|
3636
3638
|
await store.load(graphDir);
|
|
3637
3639
|
const results = [];
|
|
@@ -4039,7 +4041,7 @@ var generateAgentDefinitionsDefinition = {
|
|
|
4039
4041
|
}
|
|
4040
4042
|
};
|
|
4041
4043
|
async function handleGenerateAgentDefinitions(input) {
|
|
4042
|
-
const { generateAgentDefinitions } = await import("./generate-agent-definitions-
|
|
4044
|
+
const { generateAgentDefinitions } = await import("./generate-agent-definitions-HZ3XENWO.js");
|
|
4043
4045
|
const platforms = input.platform === "all" || !input.platform ? ["claude-code", "gemini-cli"] : [input.platform];
|
|
4044
4046
|
const results = generateAgentDefinitions({
|
|
4045
4047
|
platforms: [...platforms],
|
|
@@ -4533,7 +4535,7 @@ async function handleManageRoadmap(input) {
|
|
|
4533
4535
|
return handleManageRoadmapFileLess(input, clientResult.value);
|
|
4534
4536
|
}
|
|
4535
4537
|
try {
|
|
4536
|
-
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges, assignFeature } = await import("./dist-
|
|
4538
|
+
const { parseRoadmap, serializeRoadmap, syncRoadmap, applySyncChanges, assignFeature } = await import("./dist-72ID44UE.js");
|
|
4537
4539
|
const { Ok: Ok2 } = await import("./dist-E3SAAHCM.js");
|
|
4538
4540
|
const projectPath = projectPathPre;
|
|
4539
4541
|
const deps = {
|
|
@@ -4972,7 +4974,7 @@ async function handleTransition(validInput, projectPath, id) {
|
|
|
4972
4974
|
const transition = transitionResult.data;
|
|
4973
4975
|
const prompt = renderTransition(transition);
|
|
4974
4976
|
try {
|
|
4975
|
-
const { saveHandoff } = await import("./dist-
|
|
4977
|
+
const { saveHandoff } = await import("./dist-72ID44UE.js");
|
|
4976
4978
|
await saveHandoff(
|
|
4977
4979
|
projectPath,
|
|
4978
4980
|
{
|
|
@@ -5053,7 +5055,7 @@ async function handleEmitInteraction(input) {
|
|
|
5053
5055
|
}
|
|
5054
5056
|
async function recordInteraction(projectPath, id, type, decision, stream) {
|
|
5055
5057
|
try {
|
|
5056
|
-
const { loadState, saveState } = await import("./dist-
|
|
5058
|
+
const { loadState, saveState } = await import("./dist-72ID44UE.js");
|
|
5057
5059
|
const stateResult = await loadState(projectPath, stream);
|
|
5058
5060
|
if (stateResult.ok) {
|
|
5059
5061
|
const state = stateResult.value;
|
|
@@ -5214,10 +5216,10 @@ async function handleGatherContext(input) {
|
|
|
5214
5216
|
input.include ?? ["state", "learnings", "handoff", "graph", "validation", "businessKnowledge"]
|
|
5215
5217
|
);
|
|
5216
5218
|
const errors = [];
|
|
5217
|
-
const statePromise = includeSet.has("state") ? import("./dist-
|
|
5219
|
+
const statePromise = includeSet.has("state") ? import("./dist-72ID44UE.js").then(
|
|
5218
5220
|
(core) => core.loadState(projectPath, void 0, input.session)
|
|
5219
5221
|
) : Promise.resolve(null);
|
|
5220
|
-
const learningsPromise = includeSet.has("learnings") ? import("./dist-
|
|
5222
|
+
const learningsPromise = includeSet.has("learnings") ? import("./dist-72ID44UE.js").then(
|
|
5221
5223
|
(core) => core.loadBudgetedLearnings(projectPath, {
|
|
5222
5224
|
intent: input.intent,
|
|
5223
5225
|
tokenBudget: input.learningsBudget ?? 1e3,
|
|
@@ -5226,7 +5228,7 @@ async function handleGatherContext(input) {
|
|
|
5226
5228
|
...input.depth !== void 0 && { depth: input.depth }
|
|
5227
5229
|
})
|
|
5228
5230
|
) : Promise.resolve(null);
|
|
5229
|
-
const handoffPromise = includeSet.has("handoff") ? import("./dist-
|
|
5231
|
+
const handoffPromise = includeSet.has("handoff") ? import("./dist-72ID44UE.js").then(
|
|
5230
5232
|
(core) => core.loadHandoff(projectPath, void 0, input.session)
|
|
5231
5233
|
) : Promise.resolve(null);
|
|
5232
5234
|
const graphPromise = includeSet.has("graph") ? (async () => {
|
|
@@ -5270,11 +5272,11 @@ async function handleGatherContext(input) {
|
|
|
5270
5272
|
context: contextBlocks
|
|
5271
5273
|
};
|
|
5272
5274
|
})() : Promise.resolve(null);
|
|
5273
|
-
const sessionsPromise = includeSet.has("sessions") && input.session ? import("./dist-
|
|
5275
|
+
const sessionsPromise = includeSet.has("sessions") && input.session ? import("./dist-72ID44UE.js").then(
|
|
5274
5276
|
(core) => core.readSessionSections(projectPath, input.session)
|
|
5275
5277
|
) : Promise.resolve(null);
|
|
5276
5278
|
const shouldIncludeEvents = input.includeEvents !== void 0 ? input.includeEvents : includeSet.has("events") || !!input.session && !input.include;
|
|
5277
|
-
const eventsPromise = shouldIncludeEvents ? import("./dist-
|
|
5279
|
+
const eventsPromise = shouldIncludeEvents ? import("./dist-72ID44UE.js").then(async (core) => {
|
|
5278
5280
|
const result = await core.loadEvents(projectPath, {
|
|
5279
5281
|
session: input.session
|
|
5280
5282
|
});
|
|
@@ -5282,7 +5284,7 @@ async function handleGatherContext(input) {
|
|
|
5282
5284
|
return core.formatEventTimeline(result.value);
|
|
5283
5285
|
}) : Promise.resolve(null);
|
|
5284
5286
|
const validationPromise = includeSet.has("validation") ? (async () => {
|
|
5285
|
-
const { handleValidateProject: handleValidateProject2 } = await import("./validate-
|
|
5287
|
+
const { handleValidateProject: handleValidateProject2 } = await import("./validate-R7DZRDFK.js");
|
|
5286
5288
|
const result = await handleValidateProject2({ path: projectPath });
|
|
5287
5289
|
const first = result.content[0];
|
|
5288
5290
|
return first ? JSON.parse(first.text) : null;
|
|
@@ -5385,7 +5387,7 @@ async function handleGatherContext(input) {
|
|
|
5385
5387
|
};
|
|
5386
5388
|
if (input.session) {
|
|
5387
5389
|
try {
|
|
5388
|
-
const core = await import("./dist-
|
|
5390
|
+
const core = await import("./dist-72ID44UE.js");
|
|
5389
5391
|
core.updateSessionIndex(
|
|
5390
5392
|
projectPath,
|
|
5391
5393
|
input.session,
|
|
@@ -5537,7 +5539,7 @@ async function handleReviewChanges(input) {
|
|
|
5537
5539
|
}
|
|
5538
5540
|
}
|
|
5539
5541
|
async function runQuickReview(projectPath, diff, diffLines, downgraded, offset, limit) {
|
|
5540
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-
|
|
5542
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2 } = await import("./feedback-CVCFYND4.js");
|
|
5541
5543
|
const result = await handleAnalyzeDiff2({ diff, path: projectPath });
|
|
5542
5544
|
const firstContent = result.content[0];
|
|
5543
5545
|
if (!firstContent) throw new Error("Empty analyze_diff response");
|
|
@@ -5572,7 +5574,7 @@ function extractFileCount(diffParsed) {
|
|
|
5572
5574
|
return files?.length ?? 0;
|
|
5573
5575
|
}
|
|
5574
5576
|
async function runStandardReview(projectPath, diff, diffLines, downgraded, offset, limit) {
|
|
5575
|
-
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-
|
|
5577
|
+
const { handleAnalyzeDiff: handleAnalyzeDiff2, handleCreateSelfReview: handleCreateSelfReview2 } = await import("./feedback-CVCFYND4.js");
|
|
5576
5578
|
const [diffResult, reviewResult] = await Promise.all([
|
|
5577
5579
|
handleAnalyzeDiff2({ diff, path: projectPath }),
|
|
5578
5580
|
handleCreateSelfReview2({ path: projectPath, diff })
|
|
@@ -5607,7 +5609,7 @@ async function runStandardReview(projectPath, diff, diffLines, downgraded, offse
|
|
|
5607
5609
|
};
|
|
5608
5610
|
}
|
|
5609
5611
|
async function runDeepReview(projectPath, diff, diffLines, _downgraded, offset, limit) {
|
|
5610
|
-
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-
|
|
5612
|
+
const { handleRunCodeReview: handleRunCodeReview2 } = await import("./review-pipeline-BHQZIXWZ.js");
|
|
5611
5613
|
const result = await handleRunCodeReview2({
|
|
5612
5614
|
path: projectPath,
|
|
5613
5615
|
diff,
|
|
@@ -5901,7 +5903,7 @@ async function handleDetectStaleConstraints(input) {
|
|
|
5901
5903
|
]
|
|
5902
5904
|
};
|
|
5903
5905
|
}
|
|
5904
|
-
const { detectStaleConstraints } = await import("./dist-
|
|
5906
|
+
const { detectStaleConstraints } = await import("./dist-72ID44UE.js");
|
|
5905
5907
|
const result = detectStaleConstraints(
|
|
5906
5908
|
store,
|
|
5907
5909
|
windowDays,
|
|
@@ -5987,8 +5989,18 @@ function deriveSignals(checks, metrics) {
|
|
|
5987
5989
|
return [...signals];
|
|
5988
5990
|
}
|
|
5989
5991
|
var DEFAULT_CHECK = { passed: true, issueCount: 0 };
|
|
5990
|
-
function parseToolResult(result) {
|
|
5991
|
-
|
|
5992
|
+
function parseToolResult(result, toolName) {
|
|
5993
|
+
const text = result.content[0]?.text ?? "{}";
|
|
5994
|
+
if (result.isError) {
|
|
5995
|
+
logger.warn(`${toolName} reported an error: ${text}`);
|
|
5996
|
+
return {};
|
|
5997
|
+
}
|
|
5998
|
+
try {
|
|
5999
|
+
return JSON.parse(text);
|
|
6000
|
+
} catch {
|
|
6001
|
+
logger.warn(`${toolName} returned non-JSON output: ${text.slice(0, 120)}`);
|
|
6002
|
+
return {};
|
|
6003
|
+
}
|
|
5992
6004
|
}
|
|
5993
6005
|
function buildCheckMap(assessData) {
|
|
5994
6006
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -6021,10 +6033,10 @@ function countCriticalFindings(securityData) {
|
|
|
6021
6033
|
return findings.filter((f) => f.severity === "error").length;
|
|
6022
6034
|
}
|
|
6023
6035
|
async function runHealthChecks(projectPath) {
|
|
6024
|
-
const { handleAssessProject: handleAssessProject2 } = await import("./assess-project-
|
|
6025
|
-
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-
|
|
6026
|
-
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-
|
|
6027
|
-
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-
|
|
6036
|
+
const { handleAssessProject: handleAssessProject2 } = await import("./assess-project-OJWECOP2.js");
|
|
6037
|
+
const { handleCheckDependencies: handleCheckDependencies2 } = await import("./architecture-LUR2I67H.js");
|
|
6038
|
+
const { handleDetectEntropy: handleDetectEntropy2 } = await import("./entropy-3UX6644G.js");
|
|
6039
|
+
const { handleRunSecurityScan: handleRunSecurityScan2 } = await import("./security-RMLMYFPB.js");
|
|
6028
6040
|
const [assessResult, depsResult, entropyResult, securityResult] = await Promise.all([
|
|
6029
6041
|
handleAssessProject2({
|
|
6030
6042
|
path: projectPath,
|
|
@@ -6034,11 +6046,13 @@ async function runHealthChecks(projectPath) {
|
|
|
6034
6046
|
handleDetectEntropy2({ path: projectPath, type: "all" }),
|
|
6035
6047
|
handleRunSecurityScan2({ path: projectPath })
|
|
6036
6048
|
]);
|
|
6037
|
-
const assessData = parseToolResult(assessResult);
|
|
6049
|
+
const assessData = parseToolResult(assessResult, "assess_project");
|
|
6038
6050
|
const checkMap = buildCheckMap(assessData);
|
|
6039
|
-
const { circularDeps, layerViolations } = countViolations(
|
|
6040
|
-
|
|
6041
|
-
|
|
6051
|
+
const { circularDeps, layerViolations } = countViolations(
|
|
6052
|
+
parseToolResult(depsResult, "check_dependencies")
|
|
6053
|
+
);
|
|
6054
|
+
const entropyGranular = parseEntropyGranular(parseToolResult(entropyResult, "detect_entropy"));
|
|
6055
|
+
const criticalCount = countCriticalFindings(parseToolResult(securityResult, "run_security_scan"));
|
|
6042
6056
|
return assembleHealthChecks(
|
|
6043
6057
|
checkMap,
|
|
6044
6058
|
circularDeps,
|
|
@@ -6865,7 +6879,7 @@ async function handleGetDecayTrends(input) {
|
|
|
6865
6879
|
};
|
|
6866
6880
|
}
|
|
6867
6881
|
try {
|
|
6868
|
-
const core = await import("./dist-
|
|
6882
|
+
const core = await import("./dist-72ID44UE.js");
|
|
6869
6883
|
const { TimelineManager } = core;
|
|
6870
6884
|
const manager = new TimelineManager(projectPath);
|
|
6871
6885
|
const timeline = manager.load();
|
|
@@ -7000,7 +7014,7 @@ async function handleCodeOutline(input) {
|
|
|
7000
7014
|
};
|
|
7001
7015
|
}
|
|
7002
7016
|
try {
|
|
7003
|
-
const { getOutline, formatOutline, EXTENSION_MAP } = await import("./dist-
|
|
7017
|
+
const { getOutline, formatOutline, EXTENSION_MAP } = await import("./dist-72ID44UE.js");
|
|
7004
7018
|
const { stat } = await import("fs/promises");
|
|
7005
7019
|
const stats = await stat(targetPath).catch(() => null);
|
|
7006
7020
|
if (stats?.isFile()) {
|
|
@@ -7019,7 +7033,7 @@ async function handleCodeOutline(input) {
|
|
|
7019
7033
|
})
|
|
7020
7034
|
);
|
|
7021
7035
|
fileStats.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
7022
|
-
const { paginate: paginate2 } = await import("./dist-
|
|
7036
|
+
const { paginate: paginate2 } = await import("./dist-72ID44UE.js");
|
|
7023
7037
|
const paged = paginate2(fileStats, input.offset ?? 0, input.limit ?? 30);
|
|
7024
7038
|
const results = [];
|
|
7025
7039
|
for (const entry of paged.items) {
|
|
@@ -7092,7 +7106,7 @@ async function handleCodeSearch(input) {
|
|
|
7092
7106
|
};
|
|
7093
7107
|
}
|
|
7094
7108
|
try {
|
|
7095
|
-
const { searchSymbols } = await import("./dist-
|
|
7109
|
+
const { searchSymbols } = await import("./dist-72ID44UE.js");
|
|
7096
7110
|
const result = await searchSymbols(input.query, directory, input.glob);
|
|
7097
7111
|
const lines = [`Search: "${result.query}" \u2014 ${result.matches.length} matches`];
|
|
7098
7112
|
for (const match of result.matches) {
|
|
@@ -7161,7 +7175,7 @@ async function handleCodeUnfold(input) {
|
|
|
7161
7175
|
}
|
|
7162
7176
|
try {
|
|
7163
7177
|
if (input.symbol) {
|
|
7164
|
-
const { unfoldSymbol } = await import("./dist-
|
|
7178
|
+
const { unfoldSymbol } = await import("./dist-72ID44UE.js");
|
|
7165
7179
|
const result = await unfoldSymbol(filePath, input.symbol);
|
|
7166
7180
|
const header = result.warning ? `${result.file}:${result.startLine}-${result.endLine} ${result.warning}
|
|
7167
7181
|
` : `${result.file}:${result.startLine}-${result.endLine}
|
|
@@ -7169,7 +7183,7 @@ async function handleCodeUnfold(input) {
|
|
|
7169
7183
|
return { content: [{ type: "text", text: header + result.content }] };
|
|
7170
7184
|
}
|
|
7171
7185
|
if (input.startLine != null && input.endLine != null) {
|
|
7172
|
-
const { unfoldRange } = await import("./dist-
|
|
7186
|
+
const { unfoldRange } = await import("./dist-72ID44UE.js");
|
|
7173
7187
|
const result = await unfoldRange(filePath, input.startLine, input.endLine);
|
|
7174
7188
|
const header = `${result.file}:${result.startLine}-${result.endLine}
|
|
7175
7189
|
`;
|
|
@@ -7354,7 +7368,7 @@ async function handlePredictFailures(input) {
|
|
|
7354
7368
|
};
|
|
7355
7369
|
}
|
|
7356
7370
|
try {
|
|
7357
|
-
const core = await import("./dist-
|
|
7371
|
+
const core = await import("./dist-72ID44UE.js");
|
|
7358
7372
|
const { TimelineManager, PredictionEngine, SpecImpactEstimator } = core;
|
|
7359
7373
|
const manager = new TimelineManager(projectPath);
|
|
7360
7374
|
const includeRoadmap = input.includeRoadmap !== false;
|
|
@@ -8463,7 +8477,7 @@ async function handleDetectConstraintEmergence(input) {
|
|
|
8463
8477
|
}
|
|
8464
8478
|
const nodePath = await import("path");
|
|
8465
8479
|
const historyPath = nodePath.resolve(projectPath, ".harness/arch/violation-history.json");
|
|
8466
|
-
const { ViolationHistoryManager, detectEmergentConstraints } = await import("./dist-
|
|
8480
|
+
const { ViolationHistoryManager, detectEmergentConstraints } = await import("./dist-72ID44UE.js");
|
|
8467
8481
|
const manager = new ViolationHistoryManager(historyPath);
|
|
8468
8482
|
const history = manager.load();
|
|
8469
8483
|
const options = { windowWeeks, minOccurrences };
|
|
@@ -8551,7 +8565,7 @@ async function handleRunCIChecks(input) {
|
|
|
8551
8565
|
};
|
|
8552
8566
|
}
|
|
8553
8567
|
try {
|
|
8554
|
-
const { runCIChecks } = await import("./dist-
|
|
8568
|
+
const { runCIChecks } = await import("./dist-72ID44UE.js");
|
|
8555
8569
|
const skip = input.checks ? VALID_CHECKS.filter((c) => !input.checks.includes(c)) : [];
|
|
8556
8570
|
const result = await runCIChecks({
|
|
8557
8571
|
projectRoot: projectPath,
|
|
@@ -8613,7 +8627,7 @@ async function handleGenerateBlueprint(input) {
|
|
|
8613
8627
|
};
|
|
8614
8628
|
}
|
|
8615
8629
|
try {
|
|
8616
|
-
const { ProjectScanner } = await import("./dist-
|
|
8630
|
+
const { ProjectScanner } = await import("./dist-72ID44UE.js");
|
|
8617
8631
|
const scanner = new ProjectScanner(projectPath);
|
|
8618
8632
|
const data = await scanner.scan();
|
|
8619
8633
|
return {
|
|
@@ -8812,7 +8826,7 @@ async function handleEmitSkillProposal(input) {
|
|
|
8812
8826
|
let createProposal;
|
|
8813
8827
|
let ProposalConflictError;
|
|
8814
8828
|
try {
|
|
8815
|
-
const core = await import("./dist-
|
|
8829
|
+
const core = await import("./dist-72ID44UE.js");
|
|
8816
8830
|
createProposal = core.createProposal;
|
|
8817
8831
|
ProposalConflictError = core.ProposalConflictError;
|
|
8818
8832
|
} catch (err2) {
|
|
@@ -9481,6 +9495,234 @@ var hierarchyClarityRubric = {
|
|
|
9481
9495
|
}
|
|
9482
9496
|
};
|
|
9483
9497
|
|
|
9498
|
+
// src/shared/craft/llm/in-session.ts
|
|
9499
|
+
var PromptDeferredError = class extends Error {
|
|
9500
|
+
promptId;
|
|
9501
|
+
constructor(promptId) {
|
|
9502
|
+
super(`In-session prompt ${promptId} deferred to calling agent`);
|
|
9503
|
+
this.name = "PromptDeferredError";
|
|
9504
|
+
this.promptId = promptId;
|
|
9505
|
+
}
|
|
9506
|
+
};
|
|
9507
|
+
var InSessionLlmProvider = class {
|
|
9508
|
+
providerId = "in-session";
|
|
9509
|
+
model = "host-chat";
|
|
9510
|
+
deferred = [];
|
|
9511
|
+
costs = [];
|
|
9512
|
+
counter = 0;
|
|
9513
|
+
async callText(prompt, opts) {
|
|
9514
|
+
const promptId = `p${(++this.counter).toString(36)}`;
|
|
9515
|
+
this.deferred.push({
|
|
9516
|
+
promptId,
|
|
9517
|
+
systemPrompt: opts?.systemPrompt,
|
|
9518
|
+
userPrompt: prompt
|
|
9519
|
+
});
|
|
9520
|
+
throw new PromptDeferredError(promptId);
|
|
9521
|
+
}
|
|
9522
|
+
async callVision(_prompt, _image) {
|
|
9523
|
+
throw new Error(
|
|
9524
|
+
"InSessionLlmProvider.callVision is not implemented \u2014 vision flows must use a real provider."
|
|
9525
|
+
);
|
|
9526
|
+
}
|
|
9527
|
+
recordCost(cost) {
|
|
9528
|
+
this.costs.push(cost);
|
|
9529
|
+
}
|
|
9530
|
+
getCosts() {
|
|
9531
|
+
return this.costs;
|
|
9532
|
+
}
|
|
9533
|
+
/** Read out the queue of deferred prompts (in the order callText was invoked). */
|
|
9534
|
+
getDeferred() {
|
|
9535
|
+
return this.deferred;
|
|
9536
|
+
}
|
|
9537
|
+
};
|
|
9538
|
+
|
|
9539
|
+
// src/shared/craft/llm/adapters.ts
|
|
9540
|
+
import { z as z2 } from "zod";
|
|
9541
|
+
var RAW_SCHEMA = z2.object({ raw: z2.string() });
|
|
9542
|
+
var RAW_INSTRUCTIONS = 'Return a JSON object with a single field "raw" whose string value is the fenced JSON block you would normally emit. Do not add prose outside the JSON object.';
|
|
9543
|
+
var AnalysisProviderAdapter = class {
|
|
9544
|
+
providerId;
|
|
9545
|
+
model;
|
|
9546
|
+
inner;
|
|
9547
|
+
costs = [];
|
|
9548
|
+
constructor(opts) {
|
|
9549
|
+
this.providerId = opts.providerId;
|
|
9550
|
+
this.model = opts.model;
|
|
9551
|
+
this.inner = opts.inner;
|
|
9552
|
+
}
|
|
9553
|
+
async callText(prompt, opts) {
|
|
9554
|
+
const wrappedSystem = [opts?.systemPrompt, RAW_INSTRUCTIONS].filter(Boolean).join("\n\n");
|
|
9555
|
+
const response = await this.inner.analyze({
|
|
9556
|
+
prompt,
|
|
9557
|
+
systemPrompt: wrappedSystem,
|
|
9558
|
+
responseSchema: RAW_SCHEMA
|
|
9559
|
+
});
|
|
9560
|
+
this.recordCost({
|
|
9561
|
+
provider: this.providerId,
|
|
9562
|
+
model: response.model || this.model,
|
|
9563
|
+
inputTokens: response.tokenUsage.inputTokens,
|
|
9564
|
+
outputTokens: response.tokenUsage.outputTokens,
|
|
9565
|
+
costUsd: 0
|
|
9566
|
+
});
|
|
9567
|
+
return response.result.raw;
|
|
9568
|
+
}
|
|
9569
|
+
async callVision(_prompt, _image) {
|
|
9570
|
+
throw new Error(
|
|
9571
|
+
`${this.providerId} adapter does not implement callVision \u2014 wire vision when needed.`
|
|
9572
|
+
);
|
|
9573
|
+
}
|
|
9574
|
+
recordCost(cost) {
|
|
9575
|
+
this.costs.push(cost);
|
|
9576
|
+
}
|
|
9577
|
+
getCosts() {
|
|
9578
|
+
return this.costs;
|
|
9579
|
+
}
|
|
9580
|
+
};
|
|
9581
|
+
function adaptClaudeCli(inner, model) {
|
|
9582
|
+
return new AnalysisProviderAdapter({
|
|
9583
|
+
providerId: "claude-cli",
|
|
9584
|
+
model: model ?? "claude",
|
|
9585
|
+
inner
|
|
9586
|
+
});
|
|
9587
|
+
}
|
|
9588
|
+
function adaptAnthropic(inner, model) {
|
|
9589
|
+
return new AnalysisProviderAdapter({
|
|
9590
|
+
providerId: "anthropic",
|
|
9591
|
+
model: model ?? "claude-sonnet-4-20250514",
|
|
9592
|
+
inner
|
|
9593
|
+
});
|
|
9594
|
+
}
|
|
9595
|
+
function adaptOpenAICompatible(inner, model) {
|
|
9596
|
+
return new AnalysisProviderAdapter({
|
|
9597
|
+
providerId: "openai-compatible",
|
|
9598
|
+
model: model ?? "unknown",
|
|
9599
|
+
inner
|
|
9600
|
+
});
|
|
9601
|
+
}
|
|
9602
|
+
|
|
9603
|
+
// src/shared/craft/llm/lazy-local-adapter.ts
|
|
9604
|
+
import { OpenAICompatibleAnalysisProvider } from "@harness-engineering/intelligence";
|
|
9605
|
+
import { defaultFetchModels } from "@harness-engineering/orchestrator";
|
|
9606
|
+
var LazyLocalAdapter = class {
|
|
9607
|
+
providerId;
|
|
9608
|
+
model;
|
|
9609
|
+
opts;
|
|
9610
|
+
costs = [];
|
|
9611
|
+
/** Cached resolution. Populated on first probe; subsequent calls reuse. */
|
|
9612
|
+
resolved = null;
|
|
9613
|
+
resolvePromise = null;
|
|
9614
|
+
constructor(opts, providerId = "local") {
|
|
9615
|
+
this.opts = opts;
|
|
9616
|
+
this.providerId = providerId;
|
|
9617
|
+
this.model = opts.configured[0] ?? "unresolved";
|
|
9618
|
+
}
|
|
9619
|
+
async callText(prompt, callOpts) {
|
|
9620
|
+
const { provider } = await this.resolve();
|
|
9621
|
+
return provider.callText(prompt, callOpts);
|
|
9622
|
+
}
|
|
9623
|
+
async callVision(_prompt, _image) {
|
|
9624
|
+
throw new Error(`${this.providerId}: callVision is not wired for local backends.`);
|
|
9625
|
+
}
|
|
9626
|
+
recordCost(cost) {
|
|
9627
|
+
this.costs.push(cost);
|
|
9628
|
+
}
|
|
9629
|
+
getCosts() {
|
|
9630
|
+
return this.costs;
|
|
9631
|
+
}
|
|
9632
|
+
/** Test/debug surface — read the resolved model id (null before first probe). */
|
|
9633
|
+
getResolvedModel() {
|
|
9634
|
+
return this.resolved?.modelId ?? null;
|
|
9635
|
+
}
|
|
9636
|
+
async resolve() {
|
|
9637
|
+
if (this.resolved !== null) return this.resolved;
|
|
9638
|
+
if (this.resolvePromise !== null) return this.resolvePromise;
|
|
9639
|
+
const fetcher = this.opts.fetchModels ?? defaultFetchModels;
|
|
9640
|
+
this.resolvePromise = (async () => {
|
|
9641
|
+
let detected;
|
|
9642
|
+
try {
|
|
9643
|
+
detected = await fetcher(this.opts.endpoint, this.opts.apiKey);
|
|
9644
|
+
} catch (err2) {
|
|
9645
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
9646
|
+
throw new Error(
|
|
9647
|
+
`${this.providerId}: probe failed against ${this.opts.endpoint}: ${message}. Is the server running? (Ollama: \`ollama serve\`; LM Studio: enable the server.)`,
|
|
9648
|
+
{ cause: err2 }
|
|
9649
|
+
);
|
|
9650
|
+
}
|
|
9651
|
+
const match = this.opts.configured.find((id) => detected.includes(id));
|
|
9652
|
+
if (match === void 0) {
|
|
9653
|
+
throw new Error(
|
|
9654
|
+
`${this.providerId}: no configured model is loaded at ${this.opts.endpoint}. Configured: [${this.opts.configured.join(", ")}]. Detected: [${detected.join(", ")}]. Load one of the configured models or update agent.backends.<name>.model.`
|
|
9655
|
+
);
|
|
9656
|
+
}
|
|
9657
|
+
const inner = new OpenAICompatibleAnalysisProvider({
|
|
9658
|
+
apiKey: this.opts.apiKey,
|
|
9659
|
+
baseUrl: this.opts.endpoint,
|
|
9660
|
+
defaultModel: match
|
|
9661
|
+
});
|
|
9662
|
+
const provider = new AnalysisProviderAdapter({
|
|
9663
|
+
providerId: this.providerId,
|
|
9664
|
+
model: match,
|
|
9665
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9666
|
+
inner
|
|
9667
|
+
});
|
|
9668
|
+
const resolved = { provider, modelId: match };
|
|
9669
|
+
this.resolved = resolved;
|
|
9670
|
+
return resolved;
|
|
9671
|
+
})().finally(() => {
|
|
9672
|
+
this.resolvePromise = null;
|
|
9673
|
+
});
|
|
9674
|
+
return this.resolvePromise;
|
|
9675
|
+
}
|
|
9676
|
+
};
|
|
9677
|
+
|
|
9678
|
+
// src/shared/craft/llm/provider.ts
|
|
9679
|
+
import {
|
|
9680
|
+
AnthropicAnalysisProvider,
|
|
9681
|
+
ClaudeCliAnalysisProvider,
|
|
9682
|
+
OpenAICompatibleAnalysisProvider as OpenAICompatibleAnalysisProvider2
|
|
9683
|
+
} from "@harness-engineering/intelligence";
|
|
9684
|
+
|
|
9685
|
+
// src/shared/craft/llm/orchestrator-md.ts
|
|
9686
|
+
import * as fs21 from "fs";
|
|
9687
|
+
import * as path24 from "path";
|
|
9688
|
+
import { parse as parse4 } from "yaml";
|
|
9689
|
+
var FILENAME = "harness.orchestrator.md";
|
|
9690
|
+
function findOrchestratorMd(startDir) {
|
|
9691
|
+
let cur = path24.resolve(startDir);
|
|
9692
|
+
const root = path24.parse(cur).root;
|
|
9693
|
+
while (cur !== root) {
|
|
9694
|
+
const candidate = path24.join(cur, FILENAME);
|
|
9695
|
+
if (fs21.existsSync(candidate)) return candidate;
|
|
9696
|
+
cur = path24.dirname(cur);
|
|
9697
|
+
}
|
|
9698
|
+
return null;
|
|
9699
|
+
}
|
|
9700
|
+
function readBackendsFromOrchestratorMd(startDir) {
|
|
9701
|
+
const file = findOrchestratorMd(startDir);
|
|
9702
|
+
if (file === null) return null;
|
|
9703
|
+
let raw;
|
|
9704
|
+
try {
|
|
9705
|
+
raw = fs21.readFileSync(file, "utf-8");
|
|
9706
|
+
} catch {
|
|
9707
|
+
return null;
|
|
9708
|
+
}
|
|
9709
|
+
const parts = raw.split("---");
|
|
9710
|
+
if (parts.length < 3) return null;
|
|
9711
|
+
const yamlContent = parts[1].trim();
|
|
9712
|
+
let parsed;
|
|
9713
|
+
try {
|
|
9714
|
+
parsed = parse4(yamlContent);
|
|
9715
|
+
} catch {
|
|
9716
|
+
return null;
|
|
9717
|
+
}
|
|
9718
|
+
if (parsed === null || typeof parsed !== "object") return null;
|
|
9719
|
+
const agent = parsed.agent;
|
|
9720
|
+
if (agent === null || typeof agent !== "object") return null;
|
|
9721
|
+
const backends = agent.backends;
|
|
9722
|
+
if (backends === null || typeof backends !== "object") return null;
|
|
9723
|
+
return backends;
|
|
9724
|
+
}
|
|
9725
|
+
|
|
9484
9726
|
// src/shared/craft/llm/provider.ts
|
|
9485
9727
|
var MockLlmProvider = class {
|
|
9486
9728
|
constructor(responses = []) {
|
|
@@ -9528,8 +9770,206 @@ var MockLlmProvider = class {
|
|
|
9528
9770
|
return this.costs;
|
|
9529
9771
|
}
|
|
9530
9772
|
};
|
|
9531
|
-
function
|
|
9532
|
-
return
|
|
9773
|
+
function hasEnvValue(raw) {
|
|
9774
|
+
return raw.length > 0;
|
|
9775
|
+
}
|
|
9776
|
+
function resolveCraftLlmConfig(opts = {}) {
|
|
9777
|
+
const projectRoot = opts.projectRoot ?? process.cwd();
|
|
9778
|
+
const fileConfig = readCraftConfigFromFile(projectRoot);
|
|
9779
|
+
const envRaw = (process.env.HARNESS_CRAFT_LLM ?? "").trim();
|
|
9780
|
+
if (hasEnvValue(envRaw)) {
|
|
9781
|
+
if (envRaw === "in-session" || envRaw === "mock") {
|
|
9782
|
+
return { mode: envRaw };
|
|
9783
|
+
}
|
|
9784
|
+
const def = fileConfig?.backends?.[envRaw];
|
|
9785
|
+
if (def !== void 0 && typeof def === "object" && def !== null) {
|
|
9786
|
+
const backendDef = def;
|
|
9787
|
+
const type = backendDef.type;
|
|
9788
|
+
if (typeof type === "string" && isBackendType(type)) {
|
|
9789
|
+
return { mode: type, backendName: envRaw, backendDef };
|
|
9790
|
+
}
|
|
9791
|
+
}
|
|
9792
|
+
}
|
|
9793
|
+
const backendName = fileConfig?.craft?.backend;
|
|
9794
|
+
if (fileConfig !== null && typeof backendName === "string" && backendName.length > 0) {
|
|
9795
|
+
const def = fileConfig.backends?.[backendName];
|
|
9796
|
+
if (def === void 0 || typeof def !== "object" || def === null) {
|
|
9797
|
+
throw new Error(
|
|
9798
|
+
`craft.llm.backend="${backendName}" references an entry that is missing from agent.backends.`
|
|
9799
|
+
);
|
|
9800
|
+
}
|
|
9801
|
+
const backendDef = def;
|
|
9802
|
+
const type = backendDef.type;
|
|
9803
|
+
if (typeof type !== "string" || !isBackendType(type)) {
|
|
9804
|
+
throw new Error(
|
|
9805
|
+
`agent.backends["${backendName}"] has unsupported type "${String(type)}" for craft skills.`
|
|
9806
|
+
);
|
|
9807
|
+
}
|
|
9808
|
+
return { mode: type, backendName, backendDef };
|
|
9809
|
+
}
|
|
9810
|
+
const mode2 = fileConfig?.craft?.mode;
|
|
9811
|
+
if (mode2 === "in-session" || mode2 === "mock") return { mode: mode2 };
|
|
9812
|
+
return { mode: "in-session" };
|
|
9813
|
+
}
|
|
9814
|
+
function resolveCraftLlmMode(envValue) {
|
|
9815
|
+
if (envValue !== void 0) {
|
|
9816
|
+
const trimmed = envValue.trim();
|
|
9817
|
+
if (trimmed === "in-session" || trimmed === "mock") return trimmed;
|
|
9818
|
+
}
|
|
9819
|
+
return resolveCraftLlmConfig().mode;
|
|
9820
|
+
}
|
|
9821
|
+
var BACKEND_TYPES = ["claude", "anthropic", "openai", "gemini", "local", "pi", "mock"];
|
|
9822
|
+
function isBackendType(t) {
|
|
9823
|
+
return BACKEND_TYPES.includes(t);
|
|
9824
|
+
}
|
|
9825
|
+
function readJsonCraftView(startDir) {
|
|
9826
|
+
const view = {};
|
|
9827
|
+
const found = findConfigFile(startDir);
|
|
9828
|
+
if (!found.ok) return view;
|
|
9829
|
+
const loaded = loadConfig(found.value);
|
|
9830
|
+
if (!loaded.ok) return view;
|
|
9831
|
+
const craft = loaded.value.craft?.llm;
|
|
9832
|
+
if (craft !== void 0) {
|
|
9833
|
+
view.craft = {};
|
|
9834
|
+
if (craft.backend !== void 0) view.craft.backend = craft.backend;
|
|
9835
|
+
if (craft.mode !== void 0) view.craft.mode = craft.mode;
|
|
9836
|
+
}
|
|
9837
|
+
const backends = loaded.value.agent?.backends;
|
|
9838
|
+
if (backends !== void 0) view.backends = backends;
|
|
9839
|
+
return view;
|
|
9840
|
+
}
|
|
9841
|
+
function readCraftConfigFromFile(startDir) {
|
|
9842
|
+
const view = readJsonCraftView(startDir);
|
|
9843
|
+
if (view.backends === void 0) {
|
|
9844
|
+
const fromMd = readBackendsFromOrchestratorMd(startDir);
|
|
9845
|
+
if (fromMd !== null) {
|
|
9846
|
+
view.backends = fromMd;
|
|
9847
|
+
view.backendsFromOrchestratorMd = true;
|
|
9848
|
+
warnOrchestratorMdFallback();
|
|
9849
|
+
}
|
|
9850
|
+
}
|
|
9851
|
+
return view.craft !== void 0 || view.backends !== void 0 ? view : null;
|
|
9852
|
+
}
|
|
9853
|
+
var warnedOrchestratorMd = false;
|
|
9854
|
+
function warnOrchestratorMdFallback() {
|
|
9855
|
+
if (warnedOrchestratorMd) return;
|
|
9856
|
+
warnedOrchestratorMd = true;
|
|
9857
|
+
if (process.env.HARNESS_SUPPRESS_BACKEND_MIGRATION_WARNING) return;
|
|
9858
|
+
console.warn(
|
|
9859
|
+
"[craft] agent.backends read from harness.orchestrator.md. Run `harness migrate backends` to copy them into harness.config.json (single source of truth). Suppress with HARNESS_SUPPRESS_BACKEND_MIGRATION_WARNING=1."
|
|
9860
|
+
);
|
|
9861
|
+
}
|
|
9862
|
+
function getProvider(opts) {
|
|
9863
|
+
if (opts?.mode === "in-session") return new InSessionLlmProvider();
|
|
9864
|
+
if (opts?.mode === "mock") return new MockLlmProvider();
|
|
9865
|
+
const resolved = resolveCraftLlmConfig(
|
|
9866
|
+
opts?.projectRoot !== void 0 ? { projectRoot: opts.projectRoot } : {}
|
|
9867
|
+
);
|
|
9868
|
+
return providerForResolution(resolved);
|
|
9869
|
+
}
|
|
9870
|
+
function providerForResolution(resolved) {
|
|
9871
|
+
switch (resolved.mode) {
|
|
9872
|
+
case "in-session":
|
|
9873
|
+
return new InSessionLlmProvider();
|
|
9874
|
+
case "mock":
|
|
9875
|
+
return new MockLlmProvider();
|
|
9876
|
+
case "claude":
|
|
9877
|
+
return buildClaudeProvider(resolved);
|
|
9878
|
+
case "anthropic":
|
|
9879
|
+
return buildAnthropicProvider(resolved);
|
|
9880
|
+
case "openai":
|
|
9881
|
+
case "local":
|
|
9882
|
+
case "pi":
|
|
9883
|
+
return buildOpenAICompatibleProvider(resolved);
|
|
9884
|
+
case "gemini":
|
|
9885
|
+
throw new Error(
|
|
9886
|
+
`agent.backends["${resolved.backendName}"]: 'gemini' backend is not yet wired into the craft adapter.`
|
|
9887
|
+
);
|
|
9888
|
+
}
|
|
9889
|
+
}
|
|
9890
|
+
function buildClaudeProvider(resolved) {
|
|
9891
|
+
const def = resolved.backendDef ?? {};
|
|
9892
|
+
const command = stringField(def, "command");
|
|
9893
|
+
return adaptClaudeCli(new ClaudeCliAnalysisProvider(command !== void 0 ? { command } : {}));
|
|
9894
|
+
}
|
|
9895
|
+
function buildAnthropicProvider(resolved) {
|
|
9896
|
+
const def = resolved.backendDef ?? {};
|
|
9897
|
+
const model = stringField(def, "model");
|
|
9898
|
+
if (model === void 0) {
|
|
9899
|
+
throw new Error(
|
|
9900
|
+
`agent.backends["${resolved.backendName}"]: 'anthropic' backend requires a 'model'.`
|
|
9901
|
+
);
|
|
9902
|
+
}
|
|
9903
|
+
const apiKey = stringField(def, "apiKey") ?? process.env.ANTHROPIC_API_KEY;
|
|
9904
|
+
if (!apiKey) {
|
|
9905
|
+
throw new Error(
|
|
9906
|
+
`agent.backends["${resolved.backendName}"]: 'anthropic' backend requires apiKey or ANTHROPIC_API_KEY.`
|
|
9907
|
+
);
|
|
9908
|
+
}
|
|
9909
|
+
return adaptAnthropic(new AnthropicAnalysisProvider({ apiKey, defaultModel: model }), model);
|
|
9910
|
+
}
|
|
9911
|
+
function pickConfiguredModels(modelField) {
|
|
9912
|
+
if (typeof modelField === "string") return [modelField];
|
|
9913
|
+
if (Array.isArray(modelField)) {
|
|
9914
|
+
return modelField.filter((m) => typeof m === "string");
|
|
9915
|
+
}
|
|
9916
|
+
return [];
|
|
9917
|
+
}
|
|
9918
|
+
function resolveOpenAICompatibleEndpoint(resolved) {
|
|
9919
|
+
const def = resolved.backendDef ?? {};
|
|
9920
|
+
const fallback = resolved.mode === "openai" ? "https://api.openai.com/v1" : void 0;
|
|
9921
|
+
const endpoint = stringField(def, "endpoint") ?? fallback;
|
|
9922
|
+
if (endpoint === void 0) {
|
|
9923
|
+
throw new Error(
|
|
9924
|
+
`agent.backends["${resolved.backendName}"]: '${resolved.mode}' backend requires 'endpoint'.`
|
|
9925
|
+
);
|
|
9926
|
+
}
|
|
9927
|
+
return endpoint;
|
|
9928
|
+
}
|
|
9929
|
+
function resolveOpenAICompatibleApiKey(resolved) {
|
|
9930
|
+
const def = resolved.backendDef ?? {};
|
|
9931
|
+
const fallback = resolved.mode === "openai" ? void 0 : "local";
|
|
9932
|
+
const apiKey = stringField(def, "apiKey") ?? process.env.OPENAI_API_KEY ?? fallback;
|
|
9933
|
+
if (!apiKey) {
|
|
9934
|
+
throw new Error(
|
|
9935
|
+
`agent.backends["${resolved.backendName}"]: 'openai' backend requires apiKey or OPENAI_API_KEY.`
|
|
9936
|
+
);
|
|
9937
|
+
}
|
|
9938
|
+
return apiKey;
|
|
9939
|
+
}
|
|
9940
|
+
function resolveOpenAICompatibleInputs(resolved) {
|
|
9941
|
+
const configured = pickConfiguredModels(resolved.backendDef?.model);
|
|
9942
|
+
if (configured.length === 0) {
|
|
9943
|
+
throw new Error(
|
|
9944
|
+
`agent.backends["${resolved.backendName}"]: '${resolved.mode}' backend requires 'model' (string or non-empty array of strings).`
|
|
9945
|
+
);
|
|
9946
|
+
}
|
|
9947
|
+
return {
|
|
9948
|
+
endpoint: resolveOpenAICompatibleEndpoint(resolved),
|
|
9949
|
+
apiKey: resolveOpenAICompatibleApiKey(resolved),
|
|
9950
|
+
configured
|
|
9951
|
+
};
|
|
9952
|
+
}
|
|
9953
|
+
function buildOpenAICompatibleProvider(resolved) {
|
|
9954
|
+
const { endpoint, apiKey, configured } = resolveOpenAICompatibleInputs(resolved);
|
|
9955
|
+
if (configured.length === 1) {
|
|
9956
|
+
return adaptOpenAICompatible(
|
|
9957
|
+
new OpenAICompatibleAnalysisProvider2({
|
|
9958
|
+
apiKey,
|
|
9959
|
+
baseUrl: endpoint,
|
|
9960
|
+
defaultModel: configured[0]
|
|
9961
|
+
}),
|
|
9962
|
+
configured[0]
|
|
9963
|
+
);
|
|
9964
|
+
}
|
|
9965
|
+
return new LazyLocalAdapter(
|
|
9966
|
+
{ endpoint, apiKey, configured },
|
|
9967
|
+
resolved.mode === "pi" ? "pi" : "local"
|
|
9968
|
+
);
|
|
9969
|
+
}
|
|
9970
|
+
function stringField(obj, key) {
|
|
9971
|
+
const v = obj[key];
|
|
9972
|
+
return typeof v === "string" ? v : void 0;
|
|
9533
9973
|
}
|
|
9534
9974
|
|
|
9535
9975
|
// src/mcp/tools/design-craft.ts
|
|
@@ -9657,18 +10097,18 @@ async function handleDesignCraft(input) {
|
|
|
9657
10097
|
}
|
|
9658
10098
|
|
|
9659
10099
|
// src/drift/index.ts
|
|
9660
|
-
import * as
|
|
9661
|
-
import * as
|
|
10100
|
+
import * as fs24 from "fs";
|
|
10101
|
+
import * as path27 from "path";
|
|
9662
10102
|
|
|
9663
10103
|
// src/drift/resolvers/tokens.ts
|
|
9664
|
-
import * as
|
|
9665
|
-
import * as
|
|
10104
|
+
import * as fs22 from "fs";
|
|
10105
|
+
import * as path25 from "path";
|
|
9666
10106
|
function loadTokenSet(projectRoot) {
|
|
9667
|
-
const tokenPath =
|
|
9668
|
-
if (!
|
|
10107
|
+
const tokenPath = path25.join(projectRoot, "design-system", "tokens.json");
|
|
10108
|
+
if (!fs22.existsSync(tokenPath)) return null;
|
|
9669
10109
|
let raw;
|
|
9670
10110
|
try {
|
|
9671
|
-
raw =
|
|
10111
|
+
raw = fs22.readFileSync(tokenPath, "utf-8");
|
|
9672
10112
|
} catch {
|
|
9673
10113
|
return null;
|
|
9674
10114
|
}
|
|
@@ -9692,11 +10132,11 @@ function extractTokens(root) {
|
|
|
9692
10132
|
return set;
|
|
9693
10133
|
}
|
|
9694
10134
|
function loadTokenPathIndex(projectRoot) {
|
|
9695
|
-
const tokenPath =
|
|
9696
|
-
if (!
|
|
10135
|
+
const tokenPath = path25.join(projectRoot, "design-system", "tokens.json");
|
|
10136
|
+
if (!fs22.existsSync(tokenPath)) return null;
|
|
9697
10137
|
let raw;
|
|
9698
10138
|
try {
|
|
9699
|
-
raw =
|
|
10139
|
+
raw = fs22.readFileSync(tokenPath, "utf-8");
|
|
9700
10140
|
} catch {
|
|
9701
10141
|
return null;
|
|
9702
10142
|
}
|
|
@@ -9746,9 +10186,9 @@ function walkForPaths(node, breadcrumb, idx) {
|
|
|
9746
10186
|
}
|
|
9747
10187
|
}
|
|
9748
10188
|
}
|
|
9749
|
-
function pushPath(map, key,
|
|
10189
|
+
function pushPath(map, key, path47) {
|
|
9750
10190
|
const list = map.get(key) ?? [];
|
|
9751
|
-
list.push(
|
|
10191
|
+
list.push(path47);
|
|
9752
10192
|
map.set(key, list);
|
|
9753
10193
|
}
|
|
9754
10194
|
function walk(node, breadcrumb, set) {
|
|
@@ -9795,8 +10235,8 @@ function parsePxValue(s) {
|
|
|
9795
10235
|
}
|
|
9796
10236
|
|
|
9797
10237
|
// src/drift/resolvers/component-registry.ts
|
|
9798
|
-
import * as
|
|
9799
|
-
import * as
|
|
10238
|
+
import * as fs23 from "fs";
|
|
10239
|
+
import * as path26 from "path";
|
|
9800
10240
|
var HTML_PRIMITIVE_MAP = {
|
|
9801
10241
|
Button: "button",
|
|
9802
10242
|
Input: "input",
|
|
@@ -9805,11 +10245,11 @@ var HTML_PRIMITIVE_MAP = {
|
|
|
9805
10245
|
Anchor: "a"
|
|
9806
10246
|
};
|
|
9807
10247
|
function loadComponentRegistry(projectRoot) {
|
|
9808
|
-
const designMdPath =
|
|
9809
|
-
if (!
|
|
10248
|
+
const designMdPath = path26.join(projectRoot, "design-system", "DESIGN.md");
|
|
10249
|
+
if (!fs23.existsSync(designMdPath)) return null;
|
|
9810
10250
|
let raw;
|
|
9811
10251
|
try {
|
|
9812
|
-
raw =
|
|
10252
|
+
raw = fs23.readFileSync(designMdPath, "utf-8");
|
|
9813
10253
|
} catch {
|
|
9814
10254
|
return null;
|
|
9815
10255
|
}
|
|
@@ -10107,7 +10547,7 @@ async function runDetectDrift(input) {
|
|
|
10107
10547
|
for (const file of filesToScan) {
|
|
10108
10548
|
let source;
|
|
10109
10549
|
try {
|
|
10110
|
-
source =
|
|
10550
|
+
source = fs24.readFileSync(file, "utf-8");
|
|
10111
10551
|
} catch {
|
|
10112
10552
|
continue;
|
|
10113
10553
|
}
|
|
@@ -10142,7 +10582,7 @@ async function runDetectDrift(input) {
|
|
|
10142
10582
|
}
|
|
10143
10583
|
async function collectFiles(projectRoot, explicitFiles) {
|
|
10144
10584
|
if (explicitFiles !== void 0 && explicitFiles.length > 0) {
|
|
10145
|
-
return explicitFiles.map((f) =>
|
|
10585
|
+
return explicitFiles.map((f) => path27.isAbsolute(f) ? f : path27.join(projectRoot, f));
|
|
10146
10586
|
}
|
|
10147
10587
|
const out = [];
|
|
10148
10588
|
walk2(projectRoot, out, 0);
|
|
@@ -10152,7 +10592,7 @@ function walk2(dir, out, depth) {
|
|
|
10152
10592
|
if (depth > 8) return;
|
|
10153
10593
|
let entries;
|
|
10154
10594
|
try {
|
|
10155
|
-
entries =
|
|
10595
|
+
entries = fs24.readdirSync(dir, { withFileTypes: true });
|
|
10156
10596
|
} catch {
|
|
10157
10597
|
return;
|
|
10158
10598
|
}
|
|
@@ -10160,7 +10600,7 @@ function walk2(dir, out, depth) {
|
|
|
10160
10600
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
10161
10601
|
continue;
|
|
10162
10602
|
}
|
|
10163
|
-
const full =
|
|
10603
|
+
const full = path27.join(dir, entry.name);
|
|
10164
10604
|
if (entry.isDirectory()) {
|
|
10165
10605
|
walk2(full, out, depth + 1);
|
|
10166
10606
|
} else if (entry.isFile() && DEFAULT_GLOB_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
|
|
@@ -10228,8 +10668,8 @@ async function handleDetectDrift(input) {
|
|
|
10228
10668
|
}
|
|
10229
10669
|
|
|
10230
10670
|
// src/align/index.ts
|
|
10231
|
-
import * as
|
|
10232
|
-
import * as
|
|
10671
|
+
import * as fs25 from "fs";
|
|
10672
|
+
import * as path29 from "path";
|
|
10233
10673
|
|
|
10234
10674
|
// src/align/classifier/token-import.ts
|
|
10235
10675
|
var NAMED_IMPORT = /^\s*import\s*\{\s*tokens(?:\s+as\s+\w+)?\s*\}\s*from\s+['"][^'"]+['"];?\s*$/m;
|
|
@@ -10369,9 +10809,9 @@ function sourceLine(source, line) {
|
|
|
10369
10809
|
}
|
|
10370
10810
|
|
|
10371
10811
|
// src/align/codemods/common.ts
|
|
10372
|
-
import * as
|
|
10812
|
+
import * as path28 from "path";
|
|
10373
10813
|
function renderTokenReference(file, tokenPath) {
|
|
10374
|
-
const ext =
|
|
10814
|
+
const ext = path28.extname(file).toLowerCase();
|
|
10375
10815
|
if (ext === ".css" || ext === ".scss") {
|
|
10376
10816
|
return `var(--${tokenPath.replace(/\./g, "-")})`;
|
|
10377
10817
|
}
|
|
@@ -10563,10 +11003,10 @@ async function runAlignDesignSystem(input) {
|
|
|
10563
11003
|
}
|
|
10564
11004
|
async function loadFindings(projectRoot, input, mode2) {
|
|
10565
11005
|
if (mode2 === "pipeline") {
|
|
10566
|
-
const handoffPath =
|
|
10567
|
-
if (!
|
|
11006
|
+
const handoffPath = path29.join(projectRoot, HANDOFF_PATH);
|
|
11007
|
+
if (!fs25.existsSync(handoffPath)) return [];
|
|
10568
11008
|
try {
|
|
10569
|
-
const raw =
|
|
11009
|
+
const raw = fs25.readFileSync(handoffPath, "utf-8");
|
|
10570
11010
|
const parsed = JSON.parse(raw);
|
|
10571
11011
|
return parsed.pipeline?.driftFindings ?? [];
|
|
10572
11012
|
} catch {
|
|
@@ -10591,7 +11031,7 @@ async function processFinding(finding, tokenPaths, sourceCache, dryRun) {
|
|
|
10591
11031
|
}
|
|
10592
11032
|
let source;
|
|
10593
11033
|
try {
|
|
10594
|
-
source = sourceCache.get(finding.file) ??
|
|
11034
|
+
source = sourceCache.get(finding.file) ?? fs25.readFileSync(finding.file, "utf-8");
|
|
10595
11035
|
sourceCache.set(finding.file, source);
|
|
10596
11036
|
} catch (err2) {
|
|
10597
11037
|
return {
|
|
@@ -10619,7 +11059,7 @@ async function processFinding(finding, tokenPaths, sourceCache, dryRun) {
|
|
|
10619
11059
|
}
|
|
10620
11060
|
if (!dryRun) {
|
|
10621
11061
|
try {
|
|
10622
|
-
|
|
11062
|
+
fs25.writeFileSync(finding.file, result.newSource, "utf-8");
|
|
10623
11063
|
sourceCache.set(finding.file, result.newSource);
|
|
10624
11064
|
} catch (err2) {
|
|
10625
11065
|
return {
|
|
@@ -10680,19 +11120,19 @@ function aggregateOutput(outcomes, meta) {
|
|
|
10680
11120
|
};
|
|
10681
11121
|
}
|
|
10682
11122
|
function writePipelineFixesApplied(projectRoot, outcomes) {
|
|
10683
|
-
const handoffPath =
|
|
11123
|
+
const handoffPath = path29.join(projectRoot, HANDOFF_PATH);
|
|
10684
11124
|
let handoff = {};
|
|
10685
|
-
if (
|
|
11125
|
+
if (fs25.existsSync(handoffPath)) {
|
|
10686
11126
|
try {
|
|
10687
|
-
handoff = JSON.parse(
|
|
11127
|
+
handoff = JSON.parse(fs25.readFileSync(handoffPath, "utf-8"));
|
|
10688
11128
|
} catch {
|
|
10689
11129
|
handoff = {};
|
|
10690
11130
|
}
|
|
10691
11131
|
}
|
|
10692
11132
|
handoff.pipeline = handoff.pipeline ?? {};
|
|
10693
11133
|
handoff.pipeline.fixesApplied = outcomes;
|
|
10694
|
-
|
|
10695
|
-
|
|
11134
|
+
fs25.mkdirSync(path29.dirname(handoffPath), { recursive: true });
|
|
11135
|
+
fs25.writeFileSync(handoffPath, JSON.stringify(handoff, null, 2) + "\n", "utf-8");
|
|
10696
11136
|
}
|
|
10697
11137
|
function findingKey(finding) {
|
|
10698
11138
|
return `${finding.code}@${finding.file}:${finding.line ?? "?"}`;
|
|
@@ -10764,18 +11204,18 @@ async function handleAlignDesignSystem(input) {
|
|
|
10764
11204
|
}
|
|
10765
11205
|
|
|
10766
11206
|
// src/brand/index.ts
|
|
10767
|
-
import * as
|
|
10768
|
-
import * as
|
|
11207
|
+
import * as fs28 from "fs";
|
|
11208
|
+
import * as path32 from "path";
|
|
10769
11209
|
|
|
10770
11210
|
// src/brand/resolvers/design-md-brand.ts
|
|
10771
|
-
import * as
|
|
10772
|
-
import * as
|
|
11211
|
+
import * as fs26 from "fs";
|
|
11212
|
+
import * as path30 from "path";
|
|
10773
11213
|
function loadBrandRules(projectRoot) {
|
|
10774
|
-
const designMdPath =
|
|
10775
|
-
if (!
|
|
11214
|
+
const designMdPath = path30.join(projectRoot, "design-system", "DESIGN.md");
|
|
11215
|
+
if (!fs26.existsSync(designMdPath)) return null;
|
|
10776
11216
|
let raw;
|
|
10777
11217
|
try {
|
|
10778
|
-
raw =
|
|
11218
|
+
raw = fs26.readFileSync(designMdPath, "utf-8");
|
|
10779
11219
|
} catch {
|
|
10780
11220
|
return null;
|
|
10781
11221
|
}
|
|
@@ -10886,14 +11326,14 @@ function parseAssets(block) {
|
|
|
10886
11326
|
}
|
|
10887
11327
|
|
|
10888
11328
|
// src/brand/resolvers/token-extensions.ts
|
|
10889
|
-
import * as
|
|
10890
|
-
import * as
|
|
11329
|
+
import * as fs27 from "fs";
|
|
11330
|
+
import * as path31 from "path";
|
|
10891
11331
|
function loadBrandTokenIndex(projectRoot) {
|
|
10892
|
-
const tokenPath =
|
|
10893
|
-
if (!
|
|
11332
|
+
const tokenPath = path31.join(projectRoot, "design-system", "tokens.json");
|
|
11333
|
+
if (!fs27.existsSync(tokenPath)) return null;
|
|
10894
11334
|
let raw;
|
|
10895
11335
|
try {
|
|
10896
|
-
raw =
|
|
11336
|
+
raw = fs27.readFileSync(tokenPath, "utf-8");
|
|
10897
11337
|
} catch {
|
|
10898
11338
|
return null;
|
|
10899
11339
|
}
|
|
@@ -11142,7 +11582,7 @@ async function runAuditBrand(input) {
|
|
|
11142
11582
|
for (const file of filesToScan) {
|
|
11143
11583
|
let source;
|
|
11144
11584
|
try {
|
|
11145
|
-
source =
|
|
11585
|
+
source = fs28.readFileSync(file, "utf-8");
|
|
11146
11586
|
} catch {
|
|
11147
11587
|
continue;
|
|
11148
11588
|
}
|
|
@@ -11184,7 +11624,7 @@ async function runAuditBrand(input) {
|
|
|
11184
11624
|
}
|
|
11185
11625
|
function collectFiles2(projectRoot, explicitFiles) {
|
|
11186
11626
|
if (explicitFiles !== void 0 && explicitFiles.length > 0) {
|
|
11187
|
-
return explicitFiles.map((f) =>
|
|
11627
|
+
return explicitFiles.map((f) => path32.isAbsolute(f) ? f : path32.join(projectRoot, f));
|
|
11188
11628
|
}
|
|
11189
11629
|
const out = [];
|
|
11190
11630
|
walk4(projectRoot, out, 0);
|
|
@@ -11194,7 +11634,7 @@ function walk4(dir, out, depth) {
|
|
|
11194
11634
|
if (depth > 8) return;
|
|
11195
11635
|
let entries;
|
|
11196
11636
|
try {
|
|
11197
|
-
entries =
|
|
11637
|
+
entries = fs28.readdirSync(dir, { withFileTypes: true });
|
|
11198
11638
|
} catch {
|
|
11199
11639
|
return;
|
|
11200
11640
|
}
|
|
@@ -11202,7 +11642,7 @@ function walk4(dir, out, depth) {
|
|
|
11202
11642
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
11203
11643
|
continue;
|
|
11204
11644
|
}
|
|
11205
|
-
const full =
|
|
11645
|
+
const full = path32.join(dir, entry.name);
|
|
11206
11646
|
if (entry.isDirectory()) {
|
|
11207
11647
|
walk4(full, out, depth + 1);
|
|
11208
11648
|
} else if (entry.isFile() && DEFAULT_GLOB_EXTENSIONS2.some((ext) => entry.name.endsWith(ext))) {
|
|
@@ -11320,15 +11760,15 @@ var VerifierRegistry = class {
|
|
|
11320
11760
|
};
|
|
11321
11761
|
|
|
11322
11762
|
// src/design-pipeline/phases/freshen.ts
|
|
11323
|
-
import * as
|
|
11324
|
-
import * as
|
|
11763
|
+
import * as fs29 from "fs";
|
|
11764
|
+
import * as path33 from "path";
|
|
11325
11765
|
function runFreshen(input) {
|
|
11326
11766
|
const { projectRoot, context } = input;
|
|
11327
|
-
context.graphAvailable =
|
|
11328
|
-
const designMdPath =
|
|
11329
|
-
const tokensJsonPath =
|
|
11330
|
-
context.inputs.designMdExists =
|
|
11331
|
-
context.inputs.tokensJsonExists =
|
|
11767
|
+
context.graphAvailable = fs29.existsSync(path33.join(projectRoot, ".harness", "graph"));
|
|
11768
|
+
const designMdPath = path33.join(projectRoot, "design-system", "DESIGN.md");
|
|
11769
|
+
const tokensJsonPath = path33.join(projectRoot, "design-system", "tokens.json");
|
|
11770
|
+
context.inputs.designMdExists = fs29.existsSync(designMdPath);
|
|
11771
|
+
context.inputs.tokensJsonExists = fs29.existsSync(tokensJsonPath);
|
|
11332
11772
|
if (context.inputs.designMdExists) {
|
|
11333
11773
|
const content = readFileSafe(designMdPath);
|
|
11334
11774
|
context.inputs.componentRegistryExists = content !== null && /^##\s+component\s+registry\b/im.test(content);
|
|
@@ -11337,7 +11777,7 @@ function runFreshen(input) {
|
|
|
11337
11777
|
}
|
|
11338
11778
|
function readFileSafe(p) {
|
|
11339
11779
|
try {
|
|
11340
|
-
return
|
|
11780
|
+
return fs29.readFileSync(p, "utf-8");
|
|
11341
11781
|
} catch {
|
|
11342
11782
|
return null;
|
|
11343
11783
|
}
|
|
@@ -11364,8 +11804,8 @@ async function runDetect(input) {
|
|
|
11364
11804
|
}
|
|
11365
11805
|
|
|
11366
11806
|
// src/design-pipeline/phases/fix.ts
|
|
11367
|
-
import * as
|
|
11368
|
-
import * as
|
|
11807
|
+
import * as fs30 from "fs";
|
|
11808
|
+
import * as path34 from "path";
|
|
11369
11809
|
var MAX_ITERATIONS = 5;
|
|
11370
11810
|
async function runFix(input) {
|
|
11371
11811
|
const { projectRoot, context, mode: mode2, files, designStrictness } = input;
|
|
@@ -11414,11 +11854,11 @@ async function safelyRedetect(projectRoot, mode2, files, designStrictness) {
|
|
|
11414
11854
|
}
|
|
11415
11855
|
}
|
|
11416
11856
|
function writePipelineHandoff(projectRoot, context) {
|
|
11417
|
-
const handoffPath =
|
|
11857
|
+
const handoffPath = path34.join(projectRoot, ".harness", "handoff.json");
|
|
11418
11858
|
let handoff = {};
|
|
11419
|
-
if (
|
|
11859
|
+
if (fs30.existsSync(handoffPath)) {
|
|
11420
11860
|
try {
|
|
11421
|
-
handoff = JSON.parse(
|
|
11861
|
+
handoff = JSON.parse(fs30.readFileSync(handoffPath, "utf-8"));
|
|
11422
11862
|
} catch {
|
|
11423
11863
|
handoff = {};
|
|
11424
11864
|
}
|
|
@@ -11426,8 +11866,8 @@ function writePipelineHandoff(projectRoot, context) {
|
|
|
11426
11866
|
handoff.pipeline = {
|
|
11427
11867
|
driftFindings: context.driftFindings
|
|
11428
11868
|
};
|
|
11429
|
-
|
|
11430
|
-
|
|
11869
|
+
fs30.mkdirSync(path34.dirname(handoffPath), { recursive: true });
|
|
11870
|
+
fs30.writeFileSync(handoffPath, JSON.stringify(handoff, null, 2) + "\n");
|
|
11431
11871
|
}
|
|
11432
11872
|
|
|
11433
11873
|
// src/design-pipeline/phases/audit.ts
|
|
@@ -11457,8 +11897,8 @@ async function runAudit2(input) {
|
|
|
11457
11897
|
}
|
|
11458
11898
|
|
|
11459
11899
|
// src/design-pipeline/phases/fill.ts
|
|
11460
|
-
import * as
|
|
11461
|
-
import * as
|
|
11900
|
+
import * as fs31 from "fs";
|
|
11901
|
+
import * as path35 from "path";
|
|
11462
11902
|
var DESIGN_MD_STUB = `# Design System
|
|
11463
11903
|
|
|
11464
11904
|
<!-- TODO: author this file. See harness-design skill for guidance. -->
|
|
@@ -11518,11 +11958,11 @@ async function runFill(input) {
|
|
|
11518
11958
|
}
|
|
11519
11959
|
function bootstrapMissingInputs(input) {
|
|
11520
11960
|
const { projectRoot, context } = input;
|
|
11521
|
-
const designMdPath =
|
|
11522
|
-
const tokensJsonPath =
|
|
11523
|
-
if (!
|
|
11524
|
-
|
|
11525
|
-
|
|
11961
|
+
const designMdPath = path35.join(projectRoot, "design-system", "DESIGN.md");
|
|
11962
|
+
const tokensJsonPath = path35.join(projectRoot, "design-system", "tokens.json");
|
|
11963
|
+
if (!fs31.existsSync(designMdPath)) {
|
|
11964
|
+
fs31.mkdirSync(path35.dirname(designMdPath), { recursive: true });
|
|
11965
|
+
fs31.writeFileSync(designMdPath, DESIGN_MD_STUB);
|
|
11526
11966
|
context.bootstrapped.designMd = true;
|
|
11527
11967
|
context.inputs.designMdExists = true;
|
|
11528
11968
|
context.inputs.componentRegistryExists = true;
|
|
@@ -11542,16 +11982,16 @@ function bootstrapMissingInputs(input) {
|
|
|
11542
11982
|
}
|
|
11543
11983
|
}
|
|
11544
11984
|
}
|
|
11545
|
-
if (!
|
|
11546
|
-
|
|
11547
|
-
|
|
11985
|
+
if (!fs31.existsSync(tokensJsonPath)) {
|
|
11986
|
+
fs31.mkdirSync(path35.dirname(tokensJsonPath), { recursive: true });
|
|
11987
|
+
fs31.writeFileSync(tokensJsonPath, TOKENS_JSON_STUB);
|
|
11548
11988
|
context.bootstrapped.tokensJson = true;
|
|
11549
11989
|
context.inputs.tokensJsonExists = true;
|
|
11550
11990
|
}
|
|
11551
11991
|
}
|
|
11552
11992
|
function readFileSafe2(p) {
|
|
11553
11993
|
try {
|
|
11554
|
-
return
|
|
11994
|
+
return fs31.readFileSync(p, "utf-8");
|
|
11555
11995
|
} catch {
|
|
11556
11996
|
return null;
|
|
11557
11997
|
}
|
|
@@ -11586,10 +12026,10 @@ async function invokeCraftPolish(input) {
|
|
|
11586
12026
|
function appendToFile(p, content) {
|
|
11587
12027
|
let existing = "";
|
|
11588
12028
|
try {
|
|
11589
|
-
existing =
|
|
12029
|
+
existing = fs31.readFileSync(p, "utf-8");
|
|
11590
12030
|
} catch {
|
|
11591
12031
|
}
|
|
11592
|
-
|
|
12032
|
+
fs31.writeFileSync(p, existing + content);
|
|
11593
12033
|
}
|
|
11594
12034
|
|
|
11595
12035
|
// src/design-pipeline/phases/report.ts
|
|
@@ -11738,8 +12178,8 @@ async function handleDesignPipeline(input) {
|
|
|
11738
12178
|
}
|
|
11739
12179
|
|
|
11740
12180
|
// src/naming-craft/index.ts
|
|
11741
|
-
import * as
|
|
11742
|
-
import * as
|
|
12181
|
+
import * as fs33 from "fs";
|
|
12182
|
+
import * as path37 from "path";
|
|
11743
12183
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
11744
12184
|
|
|
11745
12185
|
// src/naming-craft/extract/identifiers.ts
|
|
@@ -11971,12 +12411,14 @@ var SEED_RUBRICS = [
|
|
|
11971
12411
|
];
|
|
11972
12412
|
|
|
11973
12413
|
// src/naming-craft/phases/critique.ts
|
|
12414
|
+
var CRITIQUE_SYSTEM_PROMPT = "You are a senior engineer critiquing identifier names against a single naming rubric. Respond ONLY with a fenced JSON block. If the rubric does not apply or the name is fine, return `null` (literally the word null inside the JSON block).";
|
|
11974
12415
|
async function critiqueOne(input) {
|
|
11975
12416
|
const { identifier, rubric, provider } = input;
|
|
11976
12417
|
const prompt = buildPrompt(input);
|
|
11977
|
-
const raw = await provider.callText(prompt, {
|
|
11978
|
-
|
|
11979
|
-
|
|
12418
|
+
const raw = await provider.callText(prompt, { systemPrompt: CRITIQUE_SYSTEM_PROMPT });
|
|
12419
|
+
return parseFindingFromRaw(raw, { identifier, rubric });
|
|
12420
|
+
}
|
|
12421
|
+
function parseFindingFromRaw(raw, ctx) {
|
|
11980
12422
|
const parsed = parseFencedJson(raw);
|
|
11981
12423
|
if (parsed === null) return null;
|
|
11982
12424
|
if (typeof parsed !== "object") return null;
|
|
@@ -11985,23 +12427,22 @@ async function critiqueOne(input) {
|
|
|
11985
12427
|
const confidence = parsed.confidence;
|
|
11986
12428
|
if (!isTier2(tier) || !isImpact2(impact) || !isConfidence2(confidence)) return null;
|
|
11987
12429
|
if (typeof parsed.message !== "string" || parsed.message.length === 0) return null;
|
|
11988
|
-
|
|
11989
|
-
code: rubric.id,
|
|
12430
|
+
return {
|
|
12431
|
+
code: ctx.rubric.id,
|
|
11990
12432
|
phase: "critique",
|
|
11991
12433
|
tier,
|
|
11992
12434
|
impact,
|
|
11993
12435
|
confidence,
|
|
11994
12436
|
target: {
|
|
11995
|
-
file: identifier.file,
|
|
11996
|
-
line: identifier.line,
|
|
11997
|
-
identifier: identifier.name,
|
|
11998
|
-
kind: identifier.kind
|
|
12437
|
+
file: ctx.identifier.file,
|
|
12438
|
+
line: ctx.identifier.line,
|
|
12439
|
+
identifier: ctx.identifier.name,
|
|
12440
|
+
kind: ctx.identifier.kind
|
|
11999
12441
|
},
|
|
12000
12442
|
message: parsed.message,
|
|
12001
|
-
cite: { rubricId: rubric.id, source: rubric.source },
|
|
12443
|
+
cite: { rubricId: ctx.rubric.id, source: ctx.rubric.source },
|
|
12002
12444
|
derived: { priority: derivePriority(tier, impact, confidence) }
|
|
12003
12445
|
};
|
|
12004
|
-
return finding;
|
|
12005
12446
|
}
|
|
12006
12447
|
function buildPrompt(input) {
|
|
12007
12448
|
const { identifier, rubric, convention } = input;
|
|
@@ -12061,23 +12502,74 @@ function isConfidence2(v) {
|
|
|
12061
12502
|
return v === "high" || v === "medium" || v === "low";
|
|
12062
12503
|
}
|
|
12063
12504
|
|
|
12505
|
+
// src/shared/craft/runs/store.ts
|
|
12506
|
+
import * as fs32 from "fs";
|
|
12507
|
+
import * as path36 from "path";
|
|
12508
|
+
var RUN_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
12509
|
+
function runsDir(projectRoot) {
|
|
12510
|
+
return path36.join(projectRoot, ".harness", "craft", "runs");
|
|
12511
|
+
}
|
|
12512
|
+
function runPath(projectRoot, runId) {
|
|
12513
|
+
return path36.join(runsDir(projectRoot), `${runId}.json`);
|
|
12514
|
+
}
|
|
12515
|
+
function saveRunState(projectRoot, state) {
|
|
12516
|
+
const dir = runsDir(projectRoot);
|
|
12517
|
+
fs32.mkdirSync(dir, { recursive: true });
|
|
12518
|
+
const file = runPath(projectRoot, state.runId);
|
|
12519
|
+
fs32.writeFileSync(file, JSON.stringify(state, null, 2));
|
|
12520
|
+
return { runFile: file };
|
|
12521
|
+
}
|
|
12522
|
+
function loadRunState(projectRoot, runId) {
|
|
12523
|
+
const file = runPath(projectRoot, runId);
|
|
12524
|
+
if (!fs32.existsSync(file)) return null;
|
|
12525
|
+
try {
|
|
12526
|
+
const raw = fs32.readFileSync(file, "utf-8");
|
|
12527
|
+
return JSON.parse(raw);
|
|
12528
|
+
} catch {
|
|
12529
|
+
return null;
|
|
12530
|
+
}
|
|
12531
|
+
}
|
|
12532
|
+
function deleteRunState(projectRoot, runId) {
|
|
12533
|
+
const file = runPath(projectRoot, runId);
|
|
12534
|
+
try {
|
|
12535
|
+
fs32.unlinkSync(file);
|
|
12536
|
+
} catch {
|
|
12537
|
+
}
|
|
12538
|
+
}
|
|
12539
|
+
function pruneOldRuns(projectRoot, now = Date.now()) {
|
|
12540
|
+
const dir = runsDir(projectRoot);
|
|
12541
|
+
let entries;
|
|
12542
|
+
try {
|
|
12543
|
+
entries = fs32.readdirSync(dir, { withFileTypes: true });
|
|
12544
|
+
} catch {
|
|
12545
|
+
return;
|
|
12546
|
+
}
|
|
12547
|
+
for (const entry of entries) {
|
|
12548
|
+
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
12549
|
+
const full = path36.join(dir, entry.name);
|
|
12550
|
+
try {
|
|
12551
|
+
const stat = fs32.statSync(full);
|
|
12552
|
+
if (now - stat.mtimeMs > RUN_TTL_MS) fs32.unlinkSync(full);
|
|
12553
|
+
} catch {
|
|
12554
|
+
}
|
|
12555
|
+
}
|
|
12556
|
+
}
|
|
12557
|
+
|
|
12064
12558
|
// src/naming-craft/index.ts
|
|
12559
|
+
var DEFAULT_PROMPT_BUDGET = 100;
|
|
12065
12560
|
var DEFAULT_MAX_FILES = 100;
|
|
12066
12561
|
var DEFAULT_MAX_IDENTIFIERS_PER_FILE = 15;
|
|
12067
12562
|
var EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
|
|
12068
|
-
|
|
12069
|
-
const startedAt = Date.now();
|
|
12563
|
+
function gatherProjectContext(input) {
|
|
12070
12564
|
const projectRoot = sanitizePath(input.path);
|
|
12071
12565
|
const maxFiles = input.maxFiles ?? DEFAULT_MAX_FILES;
|
|
12072
|
-
const maxIdentifiersPerFile = input.maxIdentifiersPerFile ?? DEFAULT_MAX_IDENTIFIERS_PER_FILE;
|
|
12073
|
-
const provider = input.__testProvider ?? getProvider();
|
|
12074
12566
|
const files = collectFiles3(projectRoot, input.files).slice(0, maxFiles);
|
|
12075
12567
|
const allIdentifiers = [];
|
|
12076
12568
|
const perFile = /* @__PURE__ */ new Map();
|
|
12077
12569
|
for (const file of files) {
|
|
12078
12570
|
let source;
|
|
12079
12571
|
try {
|
|
12080
|
-
source =
|
|
12572
|
+
source = fs33.readFileSync(file, "utf-8");
|
|
12081
12573
|
} catch {
|
|
12082
12574
|
continue;
|
|
12083
12575
|
}
|
|
@@ -12086,6 +12578,18 @@ async function runNamingCraft(input) {
|
|
|
12086
12578
|
allIdentifiers.push(...ids);
|
|
12087
12579
|
}
|
|
12088
12580
|
const convention = sampleConventions(allIdentifiers, files);
|
|
12581
|
+
return { projectRoot, files, perFile, convention };
|
|
12582
|
+
}
|
|
12583
|
+
async function runNamingCraft(input) {
|
|
12584
|
+
const startedAt = Date.now();
|
|
12585
|
+
const maxIdentifiersPerFile = input.maxIdentifiersPerFile ?? DEFAULT_MAX_IDENTIFIERS_PER_FILE;
|
|
12586
|
+
const provider = input.__testProvider ?? getProvider();
|
|
12587
|
+
if (provider instanceof InSessionLlmProvider) {
|
|
12588
|
+
throw new Error(
|
|
12589
|
+
"runNamingCraft is the inline entry point; the in-session provider requires the two-step flow. Call collectNamingCraftPrompts(...) and then finalizeNamingCraft(...), or set HARNESS_CRAFT_LLM=mock for tests."
|
|
12590
|
+
);
|
|
12591
|
+
}
|
|
12592
|
+
const { perFile, convention } = gatherProjectContext(input);
|
|
12089
12593
|
const rubrics = SEED_RUBRICS;
|
|
12090
12594
|
const findings = [];
|
|
12091
12595
|
for (const [, identifiers] of perFile) {
|
|
@@ -12120,9 +12624,109 @@ async function runNamingCraft(input) {
|
|
|
12120
12624
|
}
|
|
12121
12625
|
};
|
|
12122
12626
|
}
|
|
12627
|
+
async function collectNamingCraftPrompts(input) {
|
|
12628
|
+
const maxIdentifiersPerFile = input.maxIdentifiersPerFile ?? DEFAULT_MAX_IDENTIFIERS_PER_FILE;
|
|
12629
|
+
const budget = input.promptBudget ?? DEFAULT_PROMPT_BUDGET;
|
|
12630
|
+
const { projectRoot, perFile, convention } = gatherProjectContext(input);
|
|
12631
|
+
const rubrics = SEED_RUBRICS;
|
|
12632
|
+
const runId = randomUUID3();
|
|
12633
|
+
const promptRecords = [];
|
|
12634
|
+
const pending = [];
|
|
12635
|
+
outer: for (const [, identifiers] of perFile) {
|
|
12636
|
+
const sample = sampleIdentifiers(identifiers, maxIdentifiersPerFile, input.kinds);
|
|
12637
|
+
for (const identifier of sample) {
|
|
12638
|
+
for (const rubric of rubrics) {
|
|
12639
|
+
if (!rubric.appliesTo.includes(identifier.kind)) continue;
|
|
12640
|
+
const promptId = `p${promptRecords.length + 1}`;
|
|
12641
|
+
const userPrompt = buildPrompt({ identifier, rubric, convention });
|
|
12642
|
+
promptRecords.push({ promptId, identifier, rubricId: rubric.id });
|
|
12643
|
+
pending.push({ promptId, systemPrompt: CRITIQUE_SYSTEM_PROMPT, userPrompt });
|
|
12644
|
+
if (pending.length > budget) break outer;
|
|
12645
|
+
}
|
|
12646
|
+
}
|
|
12647
|
+
}
|
|
12648
|
+
if (pending.length > budget) {
|
|
12649
|
+
return {
|
|
12650
|
+
status: "budget-exceeded",
|
|
12651
|
+
runId,
|
|
12652
|
+
pendingPrompts: [],
|
|
12653
|
+
projection: { promptCount: pending.length, budget },
|
|
12654
|
+
hint: `Projected at least ${pending.length} LLM prompts (budget: ${budget}). Re-invoke with smaller maxFiles / maxIdentifiersPerFile, or pass promptBudget to raise the ceiling.`
|
|
12655
|
+
};
|
|
12656
|
+
}
|
|
12657
|
+
const meta = {
|
|
12658
|
+
projectRoot,
|
|
12659
|
+
startedAt: Date.now(),
|
|
12660
|
+
convention,
|
|
12661
|
+
rubricsApplied: rubrics.map((r) => r.id),
|
|
12662
|
+
prompts: promptRecords
|
|
12663
|
+
};
|
|
12664
|
+
pruneOldRuns(projectRoot);
|
|
12665
|
+
const { runFile } = saveRunState(projectRoot, {
|
|
12666
|
+
v: 1,
|
|
12667
|
+
runId,
|
|
12668
|
+
skill: "naming-craft",
|
|
12669
|
+
createdAt: Date.now(),
|
|
12670
|
+
meta
|
|
12671
|
+
});
|
|
12672
|
+
return {
|
|
12673
|
+
status: "collected",
|
|
12674
|
+
runId,
|
|
12675
|
+
pendingPrompts: pending,
|
|
12676
|
+
projection: { promptCount: pending.length, budget },
|
|
12677
|
+
runFile
|
|
12678
|
+
};
|
|
12679
|
+
}
|
|
12680
|
+
async function finalizeNamingCraft(input) {
|
|
12681
|
+
const startedAt = Date.now();
|
|
12682
|
+
const projectRoot = sanitizePath(input.path);
|
|
12683
|
+
const state = loadRunState(projectRoot, input.runId);
|
|
12684
|
+
if (state === null) {
|
|
12685
|
+
throw new Error(
|
|
12686
|
+
`naming-craft: no persisted run found for runId=${input.runId} under ${projectRoot}. Run collectNamingCraftPrompts first, or ensure the path matches the project root used at collection time.`
|
|
12687
|
+
);
|
|
12688
|
+
}
|
|
12689
|
+
if (state.skill !== "naming-craft") {
|
|
12690
|
+
throw new Error(
|
|
12691
|
+
`naming-craft: runId=${input.runId} belongs to skill ${state.skill}, not naming-craft.`
|
|
12692
|
+
);
|
|
12693
|
+
}
|
|
12694
|
+
const rubricById = new Map(SEED_RUBRICS.map((r) => [r.id, r]));
|
|
12695
|
+
const promptById = new Map(state.meta.prompts.map((p) => [p.promptId, p]));
|
|
12696
|
+
const findings = [];
|
|
12697
|
+
for (const response of input.responses) {
|
|
12698
|
+
const promptRecord = promptById.get(response.promptId);
|
|
12699
|
+
if (promptRecord === void 0) continue;
|
|
12700
|
+
const rubric = rubricById.get(promptRecord.rubricId);
|
|
12701
|
+
if (rubric === void 0) continue;
|
|
12702
|
+
const finding = parseFindingFromRaw(response.raw, {
|
|
12703
|
+
identifier: promptRecord.identifier,
|
|
12704
|
+
rubric
|
|
12705
|
+
});
|
|
12706
|
+
if (finding !== null) findings.push(finding);
|
|
12707
|
+
}
|
|
12708
|
+
deleteRunState(projectRoot, input.runId);
|
|
12709
|
+
return {
|
|
12710
|
+
findings,
|
|
12711
|
+
summary: {
|
|
12712
|
+
phaseRun: ["critique"],
|
|
12713
|
+
mode: "fast",
|
|
12714
|
+
durationMs: Date.now() - startedAt,
|
|
12715
|
+
llmCalls: {
|
|
12716
|
+
provider: "in-session",
|
|
12717
|
+
model: "host-chat",
|
|
12718
|
+
count: input.responses.length,
|
|
12719
|
+
costUsd: 0
|
|
12720
|
+
},
|
|
12721
|
+
catalog: { rubricsApplied: state.meta.rubricsApplied },
|
|
12722
|
+
convention: state.meta.convention,
|
|
12723
|
+
runId: input.runId
|
|
12724
|
+
}
|
|
12725
|
+
};
|
|
12726
|
+
}
|
|
12123
12727
|
function collectFiles3(projectRoot, explicitFiles) {
|
|
12124
12728
|
if (explicitFiles !== void 0 && explicitFiles.length > 0) {
|
|
12125
|
-
return explicitFiles.map((f) =>
|
|
12729
|
+
return explicitFiles.map((f) => path37.isAbsolute(f) ? f : path37.join(projectRoot, f));
|
|
12126
12730
|
}
|
|
12127
12731
|
const out = [];
|
|
12128
12732
|
walk5(projectRoot, out, 0);
|
|
@@ -12132,7 +12736,7 @@ function walk5(dir, out, depth) {
|
|
|
12132
12736
|
if (depth > 8) return;
|
|
12133
12737
|
let entries;
|
|
12134
12738
|
try {
|
|
12135
|
-
entries =
|
|
12739
|
+
entries = fs33.readdirSync(dir, { withFileTypes: true });
|
|
12136
12740
|
} catch {
|
|
12137
12741
|
return;
|
|
12138
12742
|
}
|
|
@@ -12140,7 +12744,7 @@ function walk5(dir, out, depth) {
|
|
|
12140
12744
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
12141
12745
|
continue;
|
|
12142
12746
|
}
|
|
12143
|
-
const full =
|
|
12747
|
+
const full = path37.join(dir, entry.name);
|
|
12144
12748
|
if (entry.isDirectory()) walk5(full, out, depth + 1);
|
|
12145
12749
|
else if (entry.isFile() && EXTENSIONS.some((ext) => entry.name.endsWith(ext))) out.push(full);
|
|
12146
12750
|
}
|
|
@@ -12179,7 +12783,7 @@ function sumCosts(provider) {
|
|
|
12179
12783
|
// src/mcp/tools/naming-craft.ts
|
|
12180
12784
|
var namingCraftDefinition = {
|
|
12181
12785
|
name: "naming_craft",
|
|
12182
|
-
description: "LLM-judgment critique of identifier names (variables, functions, types, files). First craft-pipeline ceiling skill; uses a curated rubric catalog seeded from Martin / Beck / Karlton. Emits 3-axis findings (tier x impact x confidence per ADR 0019).",
|
|
12786
|
+
description: "LLM-judgment critique of identifier names (variables, functions, types, files). First craft-pipeline ceiling skill; uses a curated rubric catalog seeded from Martin / Beck / Karlton. Emits 3-axis findings (tier x impact x confidence per ADR 0019). In-session mode (default in Claude Code) returns prompts for the calling agent to answer; call naming_craft_finalize with the responses to get findings.",
|
|
12183
12787
|
inputSchema: {
|
|
12184
12788
|
type: "object",
|
|
12185
12789
|
properties: {
|
|
@@ -12198,11 +12802,52 @@ var namingCraftDefinition = {
|
|
|
12198
12802
|
maxIdentifiersPerFile: {
|
|
12199
12803
|
type: "number",
|
|
12200
12804
|
description: "Cap per-file identifier sampling (default: 15)"
|
|
12805
|
+
},
|
|
12806
|
+
mode: {
|
|
12807
|
+
type: "string",
|
|
12808
|
+
enum: ["inline", "in-session"],
|
|
12809
|
+
description: "'in-session' (default): return prompts for the calling agent to answer, then call naming_craft_finalize. 'inline': run end-to-end via the configured provider (HARNESS_CRAFT_LLM)."
|
|
12810
|
+
},
|
|
12811
|
+
promptBudget: {
|
|
12812
|
+
type: "number",
|
|
12813
|
+
description: "Cap prompt count in in-session mode (default: 100)"
|
|
12201
12814
|
}
|
|
12202
12815
|
},
|
|
12203
12816
|
required: ["path"]
|
|
12204
12817
|
}
|
|
12205
12818
|
};
|
|
12819
|
+
var namingCraftFinalizeDefinition = {
|
|
12820
|
+
name: "naming_craft_finalize",
|
|
12821
|
+
description: "Finalize a naming_craft in-session run by submitting the calling agent's responses to the prompts collected by naming_craft. Returns the standard NamingCraftOutput with findings.",
|
|
12822
|
+
inputSchema: {
|
|
12823
|
+
type: "object",
|
|
12824
|
+
properties: {
|
|
12825
|
+
path: {
|
|
12826
|
+
type: "string",
|
|
12827
|
+
description: "Project root path used in the collect call (must match)"
|
|
12828
|
+
},
|
|
12829
|
+
runId: { type: "string", description: "runId returned by the naming_craft collect call" },
|
|
12830
|
+
responses: {
|
|
12831
|
+
type: "array",
|
|
12832
|
+
description: "Per-prompt responses. `raw` is the fenced JSON block the calling agent produced.",
|
|
12833
|
+
items: {
|
|
12834
|
+
type: "object",
|
|
12835
|
+
properties: {
|
|
12836
|
+
promptId: { type: "string" },
|
|
12837
|
+
raw: { type: "string" }
|
|
12838
|
+
},
|
|
12839
|
+
required: ["promptId", "raw"]
|
|
12840
|
+
}
|
|
12841
|
+
}
|
|
12842
|
+
},
|
|
12843
|
+
required: ["path", "runId", "responses"]
|
|
12844
|
+
}
|
|
12845
|
+
};
|
|
12846
|
+
function effectiveMode(input) {
|
|
12847
|
+
if (input.mode !== void 0) return input.mode;
|
|
12848
|
+
const envMode = resolveCraftLlmMode();
|
|
12849
|
+
return envMode === "in-session" ? "in-session" : "inline";
|
|
12850
|
+
}
|
|
12206
12851
|
async function handleNamingCraft(input) {
|
|
12207
12852
|
if (typeof input?.path !== "string" || input.path.length === 0) {
|
|
12208
12853
|
return {
|
|
@@ -12213,6 +12858,10 @@ async function handleNamingCraft(input) {
|
|
|
12213
12858
|
};
|
|
12214
12859
|
}
|
|
12215
12860
|
try {
|
|
12861
|
+
if (effectiveMode(input) === "in-session") {
|
|
12862
|
+
const result2 = await collectNamingCraftPrompts(input);
|
|
12863
|
+
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
12864
|
+
}
|
|
12216
12865
|
const result = await runNamingCraft(input);
|
|
12217
12866
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
12218
12867
|
} catch (err2) {
|
|
@@ -12225,34 +12874,86 @@ async function handleNamingCraft(input) {
|
|
|
12225
12874
|
};
|
|
12226
12875
|
}
|
|
12227
12876
|
}
|
|
12877
|
+
async function handleNamingCraftFinalize(input) {
|
|
12878
|
+
if (typeof input?.path !== "string" || input.path.length === 0) {
|
|
12879
|
+
return {
|
|
12880
|
+
content: [
|
|
12881
|
+
{
|
|
12882
|
+
type: "text",
|
|
12883
|
+
text: JSON.stringify({ error: "naming_craft_finalize: `path` is required" })
|
|
12884
|
+
}
|
|
12885
|
+
],
|
|
12886
|
+
isError: true
|
|
12887
|
+
};
|
|
12888
|
+
}
|
|
12889
|
+
if (typeof input?.runId !== "string" || input.runId.length === 0) {
|
|
12890
|
+
return {
|
|
12891
|
+
content: [
|
|
12892
|
+
{
|
|
12893
|
+
type: "text",
|
|
12894
|
+
text: JSON.stringify({ error: "naming_craft_finalize: `runId` is required" })
|
|
12895
|
+
}
|
|
12896
|
+
],
|
|
12897
|
+
isError: true
|
|
12898
|
+
};
|
|
12899
|
+
}
|
|
12900
|
+
if (!Array.isArray(input?.responses)) {
|
|
12901
|
+
return {
|
|
12902
|
+
content: [
|
|
12903
|
+
{
|
|
12904
|
+
type: "text",
|
|
12905
|
+
text: JSON.stringify({
|
|
12906
|
+
error: "naming_craft_finalize: `responses` must be an array"
|
|
12907
|
+
})
|
|
12908
|
+
}
|
|
12909
|
+
],
|
|
12910
|
+
isError: true
|
|
12911
|
+
};
|
|
12912
|
+
}
|
|
12913
|
+
try {
|
|
12914
|
+
const result = await finalizeNamingCraft(input);
|
|
12915
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
12916
|
+
} catch (err2) {
|
|
12917
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
12918
|
+
return {
|
|
12919
|
+
content: [
|
|
12920
|
+
{
|
|
12921
|
+
type: "text",
|
|
12922
|
+
text: JSON.stringify({ error: `naming_craft_finalize failed: ${message}` })
|
|
12923
|
+
}
|
|
12924
|
+
],
|
|
12925
|
+
isError: true
|
|
12926
|
+
};
|
|
12927
|
+
}
|
|
12928
|
+
}
|
|
12228
12929
|
|
|
12229
12930
|
// src/spec-craft/index.ts
|
|
12230
|
-
import * as
|
|
12931
|
+
import * as fs35 from "fs";
|
|
12231
12932
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
12232
12933
|
|
|
12233
12934
|
// src/spec-craft/extract/discover.ts
|
|
12234
|
-
import * as
|
|
12235
|
-
import * as
|
|
12935
|
+
import * as fs34 from "fs";
|
|
12936
|
+
import * as path38 from "path";
|
|
12236
12937
|
function discoverSpecs(projectRoot, kindsFilter) {
|
|
12237
12938
|
const wantProposal = kindsFilter === void 0 || kindsFilter.includes("proposal");
|
|
12238
12939
|
const wantADR = kindsFilter === void 0 || kindsFilter.includes("adr");
|
|
12239
12940
|
const out = [];
|
|
12240
12941
|
if (wantProposal) {
|
|
12241
|
-
const changesDir =
|
|
12242
|
-
if (
|
|
12243
|
-
for (const entry of
|
|
12942
|
+
const changesDir = path38.join(projectRoot, "docs", "changes");
|
|
12943
|
+
if (fs34.existsSync(changesDir)) {
|
|
12944
|
+
for (const entry of fs34.readdirSync(changesDir, { withFileTypes: true })) {
|
|
12244
12945
|
if (!entry.isDirectory()) continue;
|
|
12245
12946
|
if (entry.name.startsWith(".")) continue;
|
|
12246
|
-
const topicDir =
|
|
12247
|
-
const direct =
|
|
12248
|
-
if (
|
|
12947
|
+
const topicDir = path38.join(changesDir, entry.name);
|
|
12948
|
+
const direct = path38.join(topicDir, "proposal.md");
|
|
12949
|
+
if (fs34.existsSync(direct)) {
|
|
12249
12950
|
out.push({ file: direct, kind: "proposal" });
|
|
12250
12951
|
}
|
|
12251
|
-
for (const sub of
|
|
12952
|
+
for (const sub of fs34.readdirSync(topicDir, { withFileTypes: true })) {
|
|
12252
12953
|
if (!sub.isDirectory()) continue;
|
|
12253
12954
|
if (sub.name.startsWith(".")) continue;
|
|
12254
|
-
const subProposal =
|
|
12255
|
-
if (
|
|
12955
|
+
const subProposal = path38.join(topicDir, sub.name, "proposal.md");
|
|
12956
|
+
if (fs34.existsSync(subProposal)) {
|
|
12256
12957
|
out.push({ file: subProposal, kind: "proposal" });
|
|
12257
12958
|
}
|
|
12258
12959
|
}
|
|
@@ -12260,13 +12961,13 @@ function discoverSpecs(projectRoot, kindsFilter) {
|
|
|
12260
12961
|
}
|
|
12261
12962
|
}
|
|
12262
12963
|
if (wantADR) {
|
|
12263
|
-
const decisionsDir =
|
|
12264
|
-
if (
|
|
12265
|
-
for (const entry of
|
|
12964
|
+
const decisionsDir = path38.join(projectRoot, "docs", "knowledge", "decisions");
|
|
12965
|
+
if (fs34.existsSync(decisionsDir)) {
|
|
12966
|
+
for (const entry of fs34.readdirSync(decisionsDir, { withFileTypes: true })) {
|
|
12266
12967
|
if (!entry.isFile()) continue;
|
|
12267
12968
|
if (!entry.name.endsWith(".md")) continue;
|
|
12268
12969
|
if (entry.name.startsWith(".") || entry.name.toUpperCase() === "README.MD") continue;
|
|
12269
|
-
out.push({ file:
|
|
12970
|
+
out.push({ file: path38.join(decisionsDir, entry.name), kind: "adr" });
|
|
12270
12971
|
}
|
|
12271
12972
|
}
|
|
12272
12973
|
}
|
|
@@ -12514,7 +13215,7 @@ async function runSpecCraft(input) {
|
|
|
12514
13215
|
for (const spec of specs) {
|
|
12515
13216
|
let source;
|
|
12516
13217
|
try {
|
|
12517
|
-
source =
|
|
13218
|
+
source = fs35.readFileSync(spec.file, "utf-8");
|
|
12518
13219
|
} catch {
|
|
12519
13220
|
continue;
|
|
12520
13221
|
}
|
|
@@ -12634,13 +13335,13 @@ async function handleSpecCraft(input) {
|
|
|
12634
13335
|
}
|
|
12635
13336
|
|
|
12636
13337
|
// src/copy-craft/index.ts
|
|
12637
|
-
import * as
|
|
12638
|
-
import * as
|
|
13338
|
+
import * as fs37 from "fs";
|
|
13339
|
+
import * as path41 from "path";
|
|
12639
13340
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
12640
13341
|
|
|
12641
13342
|
// src/copy-craft/extract/source.ts
|
|
12642
13343
|
import ts5 from "typescript";
|
|
12643
|
-
import * as
|
|
13344
|
+
import * as path39 from "path";
|
|
12644
13345
|
var LOG_LEVELS = ["log", "info", "warn", "warning", "error", "debug", "trace", "fatal"];
|
|
12645
13346
|
function extractFromSource(input) {
|
|
12646
13347
|
if (!/\.(?:ts|tsx|js|jsx)$/i.test(input.file)) return [];
|
|
@@ -12780,7 +13481,7 @@ function isLikelyLogger(name) {
|
|
|
12780
13481
|
}
|
|
12781
13482
|
function fileMatchesCliPaths(file, cliPaths) {
|
|
12782
13483
|
const paths = cliPaths ?? defaultCliOutputPaths();
|
|
12783
|
-
const normalized = file.split(
|
|
13484
|
+
const normalized = file.split(path39.sep).join("/");
|
|
12784
13485
|
return paths.some((p) => normalized.includes(p));
|
|
12785
13486
|
}
|
|
12786
13487
|
function defaultCliOutputPaths() {
|
|
@@ -12800,8 +13501,8 @@ function cleanCommentText(raw) {
|
|
|
12800
13501
|
|
|
12801
13502
|
// src/copy-craft/extract/commits.ts
|
|
12802
13503
|
import { spawnSync } from "child_process";
|
|
12803
|
-
import * as
|
|
12804
|
-
import * as
|
|
13504
|
+
import * as fs36 from "fs";
|
|
13505
|
+
import * as path40 from "path";
|
|
12805
13506
|
var GIT_TIMEOUT_MS = 1e4;
|
|
12806
13507
|
function extractCommits(input) {
|
|
12807
13508
|
const { projectRoot, since = "1 month ago", limit = 100 } = input;
|
|
@@ -12840,8 +13541,8 @@ function extractCommits(input) {
|
|
|
12840
13541
|
function isGitRepo(projectRoot) {
|
|
12841
13542
|
let dir = projectRoot;
|
|
12842
13543
|
for (let i = 0; i < 10; i++) {
|
|
12843
|
-
if (
|
|
12844
|
-
const parent =
|
|
13544
|
+
if (fs36.existsSync(path40.join(dir, ".git"))) return true;
|
|
13545
|
+
const parent = path40.dirname(dir);
|
|
12845
13546
|
if (parent === dir) break;
|
|
12846
13547
|
dir = parent;
|
|
12847
13548
|
}
|
|
@@ -13147,7 +13848,7 @@ async function runCopyCraft(input) {
|
|
|
13147
13848
|
for (const file of files) {
|
|
13148
13849
|
let source;
|
|
13149
13850
|
try {
|
|
13150
|
-
source =
|
|
13851
|
+
source = fs37.readFileSync(file, "utf-8");
|
|
13151
13852
|
} catch {
|
|
13152
13853
|
continue;
|
|
13153
13854
|
}
|
|
@@ -13231,7 +13932,7 @@ async function runCopyCraft(input) {
|
|
|
13231
13932
|
}
|
|
13232
13933
|
function collectSourceFiles(projectRoot, explicitFiles) {
|
|
13233
13934
|
if (explicitFiles !== void 0 && explicitFiles.length > 0) {
|
|
13234
|
-
return explicitFiles.map((f) =>
|
|
13935
|
+
return explicitFiles.map((f) => path41.isAbsolute(f) ? f : path41.join(projectRoot, f));
|
|
13235
13936
|
}
|
|
13236
13937
|
const out = [];
|
|
13237
13938
|
walk6(projectRoot, out, 0);
|
|
@@ -13241,7 +13942,7 @@ function walk6(dir, out, depth) {
|
|
|
13241
13942
|
if (depth > 8) return;
|
|
13242
13943
|
let entries;
|
|
13243
13944
|
try {
|
|
13244
|
-
entries =
|
|
13945
|
+
entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
13245
13946
|
} catch {
|
|
13246
13947
|
return;
|
|
13247
13948
|
}
|
|
@@ -13249,7 +13950,7 @@ function walk6(dir, out, depth) {
|
|
|
13249
13950
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
13250
13951
|
continue;
|
|
13251
13952
|
}
|
|
13252
|
-
const full =
|
|
13953
|
+
const full = path41.join(dir, entry.name);
|
|
13253
13954
|
if (entry.isDirectory()) walk6(full, out, depth + 1);
|
|
13254
13955
|
else if (entry.isFile() && SOURCE_EXTENSIONS.some((ext) => entry.name.endsWith(ext)))
|
|
13255
13956
|
out.push(full);
|
|
@@ -13319,8 +14020,8 @@ async function handleCopyCraft(input) {
|
|
|
13319
14020
|
}
|
|
13320
14021
|
|
|
13321
14022
|
// src/test-craft/index.ts
|
|
13322
|
-
import * as
|
|
13323
|
-
import * as
|
|
14023
|
+
import * as fs39 from "fs";
|
|
14024
|
+
import * as path43 from "path";
|
|
13324
14025
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
13325
14026
|
|
|
13326
14027
|
// src/test-craft/extract/framework.ts
|
|
@@ -13426,25 +14127,25 @@ function extractCallbackText(node, fullSource) {
|
|
|
13426
14127
|
}
|
|
13427
14128
|
|
|
13428
14129
|
// src/test-craft/extract/source-pair.ts
|
|
13429
|
-
import * as
|
|
13430
|
-
import * as
|
|
14130
|
+
import * as fs38 from "fs";
|
|
14131
|
+
import * as path42 from "path";
|
|
13431
14132
|
var MAX_SOURCE_CHARS = 2e3;
|
|
13432
14133
|
function resolveSourceFile(testFile) {
|
|
13433
|
-
const dir =
|
|
14134
|
+
const dir = path42.dirname(testFile);
|
|
13434
14135
|
const ext = /\.tsx$/.test(testFile) ? ".tsx" : ".ts";
|
|
13435
|
-
const base =
|
|
14136
|
+
const base = path42.basename(testFile).replace(/\.(?:test|spec)\.(?:tsx?|jsx?)$/, "");
|
|
13436
14137
|
const candidates = [
|
|
13437
14138
|
// Sibling (most common in co-located setups)
|
|
13438
|
-
|
|
14139
|
+
path42.join(dir, base + ext),
|
|
13439
14140
|
// tests/ peer to src/
|
|
13440
|
-
|
|
14141
|
+
path42.join(dir, "..", "src", base + ext),
|
|
13441
14142
|
// tests/ one level deeper than src/
|
|
13442
|
-
|
|
14143
|
+
path42.join(dir, "..", "..", "src", base + ext)
|
|
13443
14144
|
];
|
|
13444
14145
|
for (const candidate of candidates) {
|
|
13445
|
-
if (
|
|
14146
|
+
if (fs38.existsSync(candidate)) {
|
|
13446
14147
|
try {
|
|
13447
|
-
const raw =
|
|
14148
|
+
const raw = fs38.readFileSync(candidate, "utf-8");
|
|
13448
14149
|
const content = raw.length > MAX_SOURCE_CHARS ? raw.slice(0, MAX_SOURCE_CHARS) + "\n[\u2026truncated for prompt cost\u2026]" : raw;
|
|
13449
14150
|
return { file: candidate, content };
|
|
13450
14151
|
} catch {
|
|
@@ -13680,7 +14381,7 @@ async function runTestCraft(input) {
|
|
|
13680
14381
|
for (const file of files) {
|
|
13681
14382
|
let source;
|
|
13682
14383
|
try {
|
|
13683
|
-
source =
|
|
14384
|
+
source = fs39.readFileSync(file, "utf-8");
|
|
13684
14385
|
} catch {
|
|
13685
14386
|
continue;
|
|
13686
14387
|
}
|
|
@@ -13745,7 +14446,7 @@ async function runTestCraft(input) {
|
|
|
13745
14446
|
}
|
|
13746
14447
|
function collectTestFiles(projectRoot, explicitFiles) {
|
|
13747
14448
|
if (explicitFiles !== void 0 && explicitFiles.length > 0) {
|
|
13748
|
-
return explicitFiles.map((f) =>
|
|
14449
|
+
return explicitFiles.map((f) => path43.isAbsolute(f) ? f : path43.join(projectRoot, f));
|
|
13749
14450
|
}
|
|
13750
14451
|
const out = [];
|
|
13751
14452
|
walk7(projectRoot, out, 0);
|
|
@@ -13755,7 +14456,7 @@ function walk7(dir, out, depth) {
|
|
|
13755
14456
|
if (depth > 10) return;
|
|
13756
14457
|
let entries;
|
|
13757
14458
|
try {
|
|
13758
|
-
entries =
|
|
14459
|
+
entries = fs39.readdirSync(dir, { withFileTypes: true });
|
|
13759
14460
|
} catch {
|
|
13760
14461
|
return;
|
|
13761
14462
|
}
|
|
@@ -13763,7 +14464,7 @@ function walk7(dir, out, depth) {
|
|
|
13763
14464
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
13764
14465
|
continue;
|
|
13765
14466
|
}
|
|
13766
|
-
const full =
|
|
14467
|
+
const full = path43.join(dir, entry.name);
|
|
13767
14468
|
if (entry.isDirectory()) walk7(full, out, depth + 1);
|
|
13768
14469
|
else if (entry.isFile() && TEST_FILE_EXTS.some((ext) => entry.name.endsWith(ext))) {
|
|
13769
14470
|
out.push(full);
|
|
@@ -13836,18 +14537,18 @@ async function handleTestCraft(input) {
|
|
|
13836
14537
|
}
|
|
13837
14538
|
|
|
13838
14539
|
// src/knowledge-craft/index.ts
|
|
13839
|
-
import * as
|
|
13840
|
-
import * as
|
|
14540
|
+
import * as fs41 from "fs";
|
|
14541
|
+
import * as path45 from "path";
|
|
13841
14542
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
13842
14543
|
|
|
13843
14544
|
// src/knowledge-craft/extract/discover.ts
|
|
13844
|
-
import * as
|
|
13845
|
-
import * as
|
|
14545
|
+
import * as fs40 from "fs";
|
|
14546
|
+
import * as path44 from "path";
|
|
13846
14547
|
var KNOWLEDGE_ROOT = "docs/knowledge";
|
|
13847
14548
|
var DEFAULT_EXCLUDED_DIRS = ["decisions"];
|
|
13848
14549
|
function discoverKnowledgeEntries(projectRoot, extraExcludeDirs) {
|
|
13849
|
-
const root =
|
|
13850
|
-
if (!
|
|
14550
|
+
const root = path44.join(projectRoot, KNOWLEDGE_ROOT);
|
|
14551
|
+
if (!fs40.existsSync(root)) return [];
|
|
13851
14552
|
const exclude = /* @__PURE__ */ new Set([...DEFAULT_EXCLUDED_DIRS, ...extraExcludeDirs ?? []]);
|
|
13852
14553
|
const out = [];
|
|
13853
14554
|
walk8(root, root, out, exclude);
|
|
@@ -13856,13 +14557,13 @@ function discoverKnowledgeEntries(projectRoot, extraExcludeDirs) {
|
|
|
13856
14557
|
function walk8(dir, root, out, exclude) {
|
|
13857
14558
|
let entries;
|
|
13858
14559
|
try {
|
|
13859
|
-
entries =
|
|
14560
|
+
entries = fs40.readdirSync(dir, { withFileTypes: true });
|
|
13860
14561
|
} catch {
|
|
13861
14562
|
return;
|
|
13862
14563
|
}
|
|
13863
14564
|
for (const entry of entries) {
|
|
13864
14565
|
if (entry.name.startsWith(".")) continue;
|
|
13865
|
-
const full =
|
|
14566
|
+
const full = path44.join(dir, entry.name);
|
|
13866
14567
|
if (entry.isDirectory()) {
|
|
13867
14568
|
if (exclude.has(entry.name)) continue;
|
|
13868
14569
|
walk8(full, root, out, exclude);
|
|
@@ -13871,7 +14572,7 @@ function walk8(dir, root, out, exclude) {
|
|
|
13871
14572
|
if (!entry.isFile()) continue;
|
|
13872
14573
|
if (!entry.name.endsWith(".md")) continue;
|
|
13873
14574
|
if (entry.name.toLowerCase() === "readme.md") continue;
|
|
13874
|
-
const rel =
|
|
14575
|
+
const rel = path44.relative(root, full).replaceAll("\\", "/");
|
|
13875
14576
|
out.push({ file: full, relative: rel });
|
|
13876
14577
|
}
|
|
13877
14578
|
}
|
|
@@ -14051,7 +14752,7 @@ async function runKnowledgeCraft(input) {
|
|
|
14051
14752
|
for (const entry of entries) {
|
|
14052
14753
|
let content;
|
|
14053
14754
|
try {
|
|
14054
|
-
content =
|
|
14755
|
+
content = fs41.readFileSync(entry.file, "utf-8");
|
|
14055
14756
|
} catch {
|
|
14056
14757
|
filesSkipped++;
|
|
14057
14758
|
continue;
|
|
@@ -14092,10 +14793,10 @@ async function runKnowledgeCraft(input) {
|
|
|
14092
14793
|
}
|
|
14093
14794
|
function collectEntries(projectRoot, input) {
|
|
14094
14795
|
if (input.files !== void 0 && input.files.length > 0) {
|
|
14095
|
-
const root =
|
|
14796
|
+
const root = path45.join(projectRoot, KNOWLEDGE_ROOT);
|
|
14096
14797
|
return input.files.map((f) => ({
|
|
14097
14798
|
file: f,
|
|
14098
|
-
relative:
|
|
14799
|
+
relative: path45.relative(root, f).replaceAll("\\", "/")
|
|
14099
14800
|
}));
|
|
14100
14801
|
}
|
|
14101
14802
|
return discoverKnowledgeEntries(projectRoot, input.excludeDirs);
|
|
@@ -14157,12 +14858,12 @@ async function handleKnowledgeCraft(input) {
|
|
|
14157
14858
|
}
|
|
14158
14859
|
|
|
14159
14860
|
// src/security-craft/index.ts
|
|
14160
|
-
import * as
|
|
14861
|
+
import * as fs43 from "fs";
|
|
14161
14862
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
14162
14863
|
|
|
14163
14864
|
// src/security-craft/extract/discover.ts
|
|
14164
|
-
import * as
|
|
14165
|
-
import * as
|
|
14865
|
+
import * as fs42 from "fs";
|
|
14866
|
+
import * as path46 from "path";
|
|
14166
14867
|
var SOURCE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
14167
14868
|
var EXCLUDED_DIRS = /* @__PURE__ */ new Set([
|
|
14168
14869
|
"node_modules",
|
|
@@ -14182,12 +14883,12 @@ var EXCLUDED_DIRS = /* @__PURE__ */ new Set([
|
|
|
14182
14883
|
]);
|
|
14183
14884
|
var TEST_FILE_PATTERN = /\.(test|spec)\.(ts|tsx|js|jsx|mjs|cjs)$/i;
|
|
14184
14885
|
function discoverSourceFiles(projectRoot, packagesFilter) {
|
|
14185
|
-
const packagesDir =
|
|
14186
|
-
if (!
|
|
14886
|
+
const packagesDir = path46.join(projectRoot, "packages");
|
|
14887
|
+
if (!fs42.existsSync(packagesDir)) return [];
|
|
14187
14888
|
const out = [];
|
|
14188
14889
|
let entries;
|
|
14189
14890
|
try {
|
|
14190
|
-
entries =
|
|
14891
|
+
entries = fs42.readdirSync(packagesDir, { withFileTypes: true });
|
|
14191
14892
|
} catch {
|
|
14192
14893
|
return [];
|
|
14193
14894
|
}
|
|
@@ -14195,8 +14896,8 @@ function discoverSourceFiles(projectRoot, packagesFilter) {
|
|
|
14195
14896
|
if (!entry.isDirectory()) continue;
|
|
14196
14897
|
if (entry.name.startsWith(".")) continue;
|
|
14197
14898
|
if (packagesFilter !== void 0 && !packagesFilter.includes(entry.name)) continue;
|
|
14198
|
-
const srcDir =
|
|
14199
|
-
if (!
|
|
14899
|
+
const srcDir = path46.join(packagesDir, entry.name, "src");
|
|
14900
|
+
if (!fs42.existsSync(srcDir)) continue;
|
|
14200
14901
|
walk9(srcDir, out);
|
|
14201
14902
|
}
|
|
14202
14903
|
return out;
|
|
@@ -14204,13 +14905,13 @@ function discoverSourceFiles(projectRoot, packagesFilter) {
|
|
|
14204
14905
|
function walk9(dir, out) {
|
|
14205
14906
|
let entries;
|
|
14206
14907
|
try {
|
|
14207
|
-
entries =
|
|
14908
|
+
entries = fs42.readdirSync(dir, { withFileTypes: true });
|
|
14208
14909
|
} catch {
|
|
14209
14910
|
return;
|
|
14210
14911
|
}
|
|
14211
14912
|
for (const entry of entries) {
|
|
14212
14913
|
if (entry.name.startsWith(".")) continue;
|
|
14213
|
-
const full =
|
|
14914
|
+
const full = path46.join(dir, entry.name);
|
|
14214
14915
|
if (entry.isDirectory()) {
|
|
14215
14916
|
if (EXCLUDED_DIRS.has(entry.name)) continue;
|
|
14216
14917
|
walk9(full, out);
|
|
@@ -14218,7 +14919,7 @@ function walk9(dir, out) {
|
|
|
14218
14919
|
}
|
|
14219
14920
|
if (!entry.isFile()) continue;
|
|
14220
14921
|
if (TEST_FILE_PATTERN.test(entry.name)) continue;
|
|
14221
|
-
const ext =
|
|
14922
|
+
const ext = path46.extname(entry.name);
|
|
14222
14923
|
if (!SOURCE_EXTENSIONS2.has(ext)) continue;
|
|
14223
14924
|
out.push(full);
|
|
14224
14925
|
}
|
|
@@ -14715,7 +15416,7 @@ async function runSecurityCraft(input) {
|
|
|
14715
15416
|
for (const file of candidateFiles) {
|
|
14716
15417
|
let source;
|
|
14717
15418
|
try {
|
|
14718
|
-
source =
|
|
15419
|
+
source = fs43.readFileSync(file, "utf-8");
|
|
14719
15420
|
} catch {
|
|
14720
15421
|
continue;
|
|
14721
15422
|
}
|
|
@@ -14900,6 +15601,7 @@ var TOOL_DEFINITIONS = [
|
|
|
14900
15601
|
auditBrandDefinition,
|
|
14901
15602
|
designPipelineDefinition,
|
|
14902
15603
|
namingCraftDefinition,
|
|
15604
|
+
namingCraftFinalizeDefinition,
|
|
14903
15605
|
specCraftDefinition,
|
|
14904
15606
|
copyCraftDefinition,
|
|
14905
15607
|
testCraftDefinition,
|
|
@@ -14982,6 +15684,7 @@ var TOOL_HANDLERS = {
|
|
|
14982
15684
|
audit_brand: handleAuditBrand,
|
|
14983
15685
|
run_design_pipeline: handleDesignPipeline,
|
|
14984
15686
|
naming_craft: handleNamingCraft,
|
|
15687
|
+
naming_craft_finalize: handleNamingCraftFinalize,
|
|
14985
15688
|
spec_craft: handleSpecCraft,
|
|
14986
15689
|
copy_craft: handleCopyCraft,
|
|
14987
15690
|
test_craft: handleTestCraft,
|
|
@@ -15088,7 +15791,7 @@ async function appendUpdateNotification(result, resolvedRoot) {
|
|
|
15088
15791
|
shouldRunCheck,
|
|
15089
15792
|
readCheckState,
|
|
15090
15793
|
spawnBackgroundCheck
|
|
15091
|
-
} = await import("./dist-
|
|
15794
|
+
} = await import("./dist-72ID44UE.js");
|
|
15092
15795
|
const { CLI_VERSION } = await import("./version-CUI434OP.js");
|
|
15093
15796
|
const configInterval = readConfigInterval(resolvedRoot);
|
|
15094
15797
|
const DEFAULT_INTERVAL = 864e5;
|
|
@@ -15186,6 +15889,8 @@ export {
|
|
|
15186
15889
|
runDetectDrift,
|
|
15187
15890
|
runAlignDesignSystem,
|
|
15188
15891
|
runAudit,
|
|
15892
|
+
findOrchestratorMd,
|
|
15893
|
+
readBackendsFromOrchestratorMd,
|
|
15189
15894
|
runDesignCraft,
|
|
15190
15895
|
runAuditBrand,
|
|
15191
15896
|
runCopyCraft,
|