@harness-engineering/cli 1.28.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/skills/claude-code/harness-compound/SKILL.md +153 -0
- package/dist/agents/skills/claude-code/harness-compound/skill.yaml +60 -0
- package/dist/agents/skills/claude-code/harness-knowledge-pipeline/SKILL.md +12 -1
- package/dist/agents/skills/claude-code/harness-observability/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +138 -0
- package/dist/agents/skills/claude-code/harness-pulse/references/interview.md +77 -0
- package/dist/agents/skills/claude-code/harness-pulse/skill.yaml +61 -0
- package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +25 -1
- package/dist/agents/skills/codex/harness-compound/SKILL.md +153 -0
- package/dist/agents/skills/codex/harness-compound/skill.yaml +60 -0
- package/dist/agents/skills/codex/harness-knowledge-pipeline/SKILL.md +12 -1
- package/dist/agents/skills/codex/harness-observability/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-pulse/SKILL.md +138 -0
- package/dist/agents/skills/codex/harness-pulse/references/interview.md +77 -0
- package/dist/agents/skills/codex/harness-pulse/skill.yaml +61 -0
- package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +25 -1
- package/dist/agents/skills/cursor/harness-compound/SKILL.md +153 -0
- package/dist/agents/skills/cursor/harness-compound/skill.yaml +60 -0
- package/dist/agents/skills/cursor/harness-knowledge-pipeline/SKILL.md +12 -1
- package/dist/agents/skills/cursor/harness-observability/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-pulse/SKILL.md +138 -0
- package/dist/agents/skills/cursor/harness-pulse/references/interview.md +77 -0
- package/dist/agents/skills/cursor/harness-pulse/skill.yaml +61 -0
- package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +25 -1
- package/dist/agents/skills/gemini-cli/harness-compound/SKILL.md +153 -0
- package/dist/agents/skills/gemini-cli/harness-compound/skill.yaml +60 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-pipeline/SKILL.md +12 -1
- package/dist/agents/skills/gemini-cli/harness-observability/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +138 -0
- package/dist/agents/skills/gemini-cli/harness-pulse/references/interview.md +77 -0
- package/dist/agents/skills/gemini-cli/harness-pulse/skill.yaml +61 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +25 -1
- package/dist/agents/skills/package.json +1 -0
- package/dist/agents/skills/tests/fixtures/harness-compound/bug-track-fixture/input.json +10 -0
- package/dist/agents/skills/tests/fixtures/harness-compound/duplicate-detection-fixture/docs/solutions/bug-track/integration-issues/stalled-lease-cleanup.md +28 -0
- package/dist/agents/skills/tests/fixtures/harness-compound/duplicate-detection-fixture/expected.json +4 -0
- package/dist/agents/skills/tests/fixtures/harness-compound/duplicate-detection-fixture/input.json +10 -0
- package/dist/agents/skills/tests/fixtures/harness-compound/knowledge-track-fixture/input.json +10 -0
- package/dist/agents/skills/tests/harness-compound.test.ts +86 -0
- package/dist/{agents-md-6SAMHE7H.js → agents-md-XCAWON2D.js} +3 -3
- package/dist/{architecture-5YR52NSV.js → architecture-KERHEEQZ.js} +4 -4
- package/dist/{assess-project-5X7TYQFM.js → assess-project-NPYA3UVI.js} +1 -1
- package/dist/bin/harness-mcp.js +16 -15
- package/dist/bin/harness.js +26 -25
- package/dist/{check-phase-gate-PLV2VDOL.js → check-phase-gate-GE5ALEEU.js} +5 -4
- package/dist/{chunk-KJD4J54I.js → chunk-4FVHBBPY.js} +6 -1
- package/dist/{chunk-PFM3BVVU.js → chunk-AEFZJ543.js} +1 -1
- package/dist/{chunk-S2WB4LE7.js → chunk-BMM3GXV6.js} +384 -28
- package/dist/{chunk-RYDPFIJY.js → chunk-D5FE4L2O.js} +1 -1
- package/dist/{chunk-HT7HYYGT.js → chunk-DRD7LLFC.js} +1 -1
- package/dist/{chunk-2IBXUG6J.js → chunk-EFA4OEEN.js} +2 -2
- package/dist/{chunk-JZST2WZS.js → chunk-FBQYKH7R.js} +3 -3
- package/dist/{chunk-MTPHNOJW.js → chunk-FQAJAM54.js} +506 -242
- package/dist/{chunk-R2CBBZA6.js → chunk-GCYGGQFM.js} +1 -1
- package/dist/{chunk-7JQ7HLM4.js → chunk-GHPWBWUW.js} +8 -8
- package/dist/{chunk-6L2BU4BP.js → chunk-HBQ3BK2E.js} +1 -1
- package/dist/{chunk-ZYLBIDLE.js → chunk-IIX5OJES.js} +1 -1
- package/dist/{chunk-DXGI7DL3.js → chunk-KTWKW6KJ.js} +1 -1
- package/dist/{chunk-6GXSJGSW.js → chunk-LY2TY6NE.js} +3 -3
- package/dist/{chunk-JNKALGRM.js → chunk-M4C3ZIGL.js} +5 -5
- package/dist/{chunk-RFYF7TJS.js → chunk-MAFI6UWT.js} +1701 -769
- package/dist/{chunk-BYS3TQOO.js → chunk-OXFFN3FD.js} +1 -1
- package/dist/{chunk-XHOGGZS7.js → chunk-PCX4GPNT.js} +1 -1
- package/dist/{chunk-BFBZK6BC.js → chunk-RCHXBL2M.js} +6 -6
- package/dist/{chunk-74YADB7T.js → chunk-T7MNLCUD.js} +92 -92
- package/dist/{chunk-SITVRO7K.js → chunk-URLDPALI.js} +9 -9
- package/dist/{chunk-ELJ2MXMO.js → chunk-UWIOBHZL.js} +9 -9
- package/dist/{chunk-QDRBWVVY.js → chunk-WW6AUOA3.js} +2 -2
- package/dist/{chunk-5ME3WG3G.js → chunk-YBGVZQQE.js} +5 -5
- package/dist/{chunk-YJE23GRZ.js → chunk-YG4ZBGEH.js} +39 -5
- package/dist/chunk-ZCZD7FHU.js +16 -0
- package/dist/{ci-workflow-7T2XKB3P.js → ci-workflow-A2E2RTOP.js} +3 -3
- package/dist/{dist-42AYXCAK.js → dist-D27LJR2T.js} +7 -1
- package/dist/{dist-77VNTHWV.js → dist-K22DQUYY.js} +78 -2
- package/dist/{docs-MSIJ6SDO.js → docs-GXJOFVCF.js} +5 -4
- package/dist/{engine-F4P5RBE4.js → engine-JBUIA2XO.js} +3 -3
- package/dist/{entropy-GSUTIORR.js → entropy-Y7LUT4BZ.js} +3 -3
- package/dist/{feedback-NST6T4HI.js → feedback-BHOBVKI3.js} +1 -1
- package/dist/{generate-agent-definitions-BOUGQIPA.js → generate-agent-definitions-VL3ZVR32.js} +4 -4
- package/dist/glob-helper-FZPPTGJN.js +62 -0
- package/dist/{graph-loader-IAUPGLRV.js → graph-loader-5MKHAJJF.js} +1 -1
- package/dist/index.d.ts +44 -6
- package/dist/index.js +26 -25
- package/dist/{loader-6QTJC7IN.js → loader-WCKVMDYR.js} +3 -3
- package/dist/{mcp-QFBGTUX6.js → mcp-FA2CKHFY.js} +16 -15
- package/dist/{performance-B2NAAIE5.js → performance-NISUL5AA.js} +5 -4
- package/dist/{review-pipeline-6EYMBS6B.js → review-pipeline-CHE5LJ5D.js} +3 -3
- package/dist/{runtime-VFZK6BCZ.js → runtime-3SKKEVPF.js} +3 -3
- package/dist/{scan-DB6FNYGG.js → scan-BIJYHOE7.js} +2 -1
- package/dist/{security-HRNTYHPM.js → security-MF54MY3P.js} +1 -1
- package/dist/templates/orchestrator/harness.orchestrator.md +31 -8
- package/dist/{validate-YEMAFWJE.js → validate-SIWFNTXI.js} +4 -4
- package/dist/{validate-cross-check-DGHTJFVH.js → validate-cross-check-GBX7B7CQ.js} +3 -3
- package/package.json +8 -7
- package/dist/glob-helper-VCQXK5XY.js +0 -54
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateRuntime
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AEFZJ543.js";
|
|
4
4
|
import {
|
|
5
5
|
generateAgentsMd
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HBQ3BK2E.js";
|
|
7
7
|
import {
|
|
8
8
|
generateCIWorkflow
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-D5FE4L2O.js";
|
|
10
10
|
import {
|
|
11
11
|
TemplateEngine
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IIX5OJES.js";
|
|
13
13
|
import {
|
|
14
14
|
generate,
|
|
15
15
|
validate
|
|
@@ -28,21 +28,22 @@ import {
|
|
|
28
28
|
OutputMode,
|
|
29
29
|
createCheckPhaseGateCommand,
|
|
30
30
|
findFiles
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-WW6AUOA3.js";
|
|
32
32
|
import {
|
|
33
33
|
createGenerateAgentDefinitionsCommand,
|
|
34
34
|
generateAgentDefinitions
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-GCYGGQFM.js";
|
|
36
36
|
import {
|
|
37
37
|
toKebabCase
|
|
38
38
|
} from "./chunk-KET4QQZB.js";
|
|
39
39
|
import {
|
|
40
40
|
listPersonas,
|
|
41
41
|
loadPersona
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-DRD7LLFC.js";
|
|
43
43
|
import {
|
|
44
|
-
createScanCommand
|
|
45
|
-
|
|
44
|
+
createScanCommand,
|
|
45
|
+
loadIngestOptions
|
|
46
|
+
} from "./chunk-YG4ZBGEH.js";
|
|
46
47
|
import {
|
|
47
48
|
appendFrameworkAgents,
|
|
48
49
|
captureHealthSnapshot,
|
|
@@ -56,17 +57,17 @@ import {
|
|
|
56
57
|
loadCachedSnapshot,
|
|
57
58
|
persistToolingConfig,
|
|
58
59
|
recommend
|
|
59
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-T7MNLCUD.js";
|
|
60
61
|
import {
|
|
61
62
|
loadGraphStore
|
|
62
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-KTWKW6KJ.js";
|
|
63
64
|
import {
|
|
64
65
|
loadOrRebuildIndex
|
|
65
66
|
} from "./chunk-27AJKSQY.js";
|
|
66
67
|
import {
|
|
67
68
|
findConfigFile,
|
|
68
69
|
resolveConfig
|
|
69
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-4FVHBBPY.js";
|
|
70
71
|
import {
|
|
71
72
|
VALID_PLATFORMS
|
|
72
73
|
} from "./chunk-3ISINLYT.js";
|
|
@@ -102,14 +103,19 @@ import {
|
|
|
102
103
|
appendLearning,
|
|
103
104
|
applyFixes,
|
|
104
105
|
archiveStream,
|
|
106
|
+
assembleCandidateReport,
|
|
107
|
+
assembleReport,
|
|
105
108
|
buildSnapshot,
|
|
106
109
|
checkDocCoverage,
|
|
107
110
|
checkTaint,
|
|
108
111
|
clearTaint,
|
|
112
|
+
computeHotspots,
|
|
109
113
|
computeOverallSeverity,
|
|
110
114
|
computeScanExitCode,
|
|
115
|
+
computeWindow,
|
|
111
116
|
createFixes,
|
|
112
117
|
createStream,
|
|
118
|
+
crossReferenceUndocumentedFixes,
|
|
113
119
|
deepMergeConstraints,
|
|
114
120
|
defineLayer,
|
|
115
121
|
detectCircularDepsInFiles,
|
|
@@ -118,9 +124,13 @@ import {
|
|
|
118
124
|
diff,
|
|
119
125
|
dist_exports,
|
|
120
126
|
extractBundle,
|
|
127
|
+
extractHeadlines,
|
|
128
|
+
formatIsoWeek,
|
|
121
129
|
generateSuggestions,
|
|
122
130
|
getOrCreateInstallId,
|
|
131
|
+
gitScan,
|
|
123
132
|
init_dist,
|
|
133
|
+
isoWeek,
|
|
124
134
|
listStreams,
|
|
125
135
|
listTaintedSessions,
|
|
126
136
|
loadState,
|
|
@@ -142,6 +152,7 @@ import {
|
|
|
142
152
|
resolveStreamPath,
|
|
143
153
|
runAll,
|
|
144
154
|
runCIChecks,
|
|
155
|
+
runPulse,
|
|
145
156
|
runReviewPipeline,
|
|
146
157
|
scanForInjection,
|
|
147
158
|
setActiveStream,
|
|
@@ -149,9 +160,11 @@ import {
|
|
|
149
160
|
validateAgentsMap,
|
|
150
161
|
validateDependencies,
|
|
151
162
|
validateKnowledgeMap,
|
|
163
|
+
validatePulseConfig,
|
|
164
|
+
validateSolutionsDir,
|
|
152
165
|
writeConfig,
|
|
153
166
|
writeLockfile
|
|
154
|
-
} from "./chunk-
|
|
167
|
+
} from "./chunk-MAFI6UWT.js";
|
|
155
168
|
import {
|
|
156
169
|
Err,
|
|
157
170
|
Ok
|
|
@@ -176,7 +189,7 @@ import {
|
|
|
176
189
|
} from "./chunk-KFQGP6VL.js";
|
|
177
190
|
|
|
178
191
|
// src/index.ts
|
|
179
|
-
import { Command as
|
|
192
|
+
import { Command as Command90 } from "commander";
|
|
180
193
|
|
|
181
194
|
// src/commands/add.ts
|
|
182
195
|
init_dist();
|
|
@@ -365,7 +378,7 @@ function registerSkillsCommand(adoption) {
|
|
|
365
378
|
const globalOpts = cmd.optsWithGlobals();
|
|
366
379
|
const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
|
|
367
380
|
const cwd = process.cwd();
|
|
368
|
-
const { readAdoptionRecords, aggregateBySkill } = await import("./dist-
|
|
381
|
+
const { readAdoptionRecords, aggregateBySkill } = await import("./dist-K22DQUYY.js");
|
|
369
382
|
const records = readAdoptionRecords(cwd);
|
|
370
383
|
if (records.length === 0) {
|
|
371
384
|
if (globalOpts.json) {
|
|
@@ -401,7 +414,7 @@ function registerRecentCommand(adoption) {
|
|
|
401
414
|
const globalOpts = cmd.optsWithGlobals();
|
|
402
415
|
const limit = Math.max(parseInt(opts.limit, 10) || 20, 1);
|
|
403
416
|
const cwd = process.cwd();
|
|
404
|
-
const { readAdoptionRecords } = await import("./dist-
|
|
417
|
+
const { readAdoptionRecords } = await import("./dist-K22DQUYY.js");
|
|
405
418
|
const records = readAdoptionRecords(cwd);
|
|
406
419
|
if (records.length === 0) {
|
|
407
420
|
if (globalOpts.json) {
|
|
@@ -479,7 +492,7 @@ function registerSkillCommand(adoption) {
|
|
|
479
492
|
adoption.command("skill <name>").description("Show detail for a specific skill").action(async (name, _opts, cmd) => {
|
|
480
493
|
const globalOpts = cmd.optsWithGlobals();
|
|
481
494
|
const cwd = process.cwd();
|
|
482
|
-
const { readAdoptionRecords, aggregateBySkill } = await import("./dist-
|
|
495
|
+
const { readAdoptionRecords, aggregateBySkill } = await import("./dist-K22DQUYY.js");
|
|
483
496
|
const records = readAdoptionRecords(cwd);
|
|
484
497
|
const skillRecords = records.filter((r) => r.skill === name);
|
|
485
498
|
if (skillRecords.length === 0) {
|
|
@@ -2101,16 +2114,108 @@ function createCleanupSessionsCommand() {
|
|
|
2101
2114
|
return command;
|
|
2102
2115
|
}
|
|
2103
2116
|
|
|
2104
|
-
// src/commands/
|
|
2117
|
+
// src/commands/compound/index.ts
|
|
2118
|
+
import { Command as Command20 } from "commander";
|
|
2119
|
+
|
|
2120
|
+
// src/commands/compound/scan-candidates.ts
|
|
2121
|
+
init_dist();
|
|
2122
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
2123
|
+
import { dirname as dirname2, join as join6, resolve as resolve11 } from "path";
|
|
2105
2124
|
import { Command as Command19 } from "commander";
|
|
2125
|
+
var HOTSPOT_THRESHOLD = 7;
|
|
2126
|
+
var DEFAULT_LOOKBACK = "7d";
|
|
2127
|
+
async function runCompoundScanCandidatesCommand(opts) {
|
|
2128
|
+
const startedAt = Date.now();
|
|
2129
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
2130
|
+
const lookback = opts.lookback ?? DEFAULT_LOOKBACK;
|
|
2131
|
+
let undocumented;
|
|
2132
|
+
let hotspots;
|
|
2133
|
+
try {
|
|
2134
|
+
const fixes = await gitScan({ since: lookback, cwd });
|
|
2135
|
+
undocumented = await crossReferenceUndocumentedFixes(fixes, opts.solutionsDir);
|
|
2136
|
+
hotspots = await computeHotspots({ since: lookback, cwd, threshold: HOTSPOT_THRESHOLD });
|
|
2137
|
+
} catch (err) {
|
|
2138
|
+
return emit(
|
|
2139
|
+
{ status: "failure", reason: err instanceof Error ? err.message : String(err), lookback },
|
|
2140
|
+
opts.nonInteractive
|
|
2141
|
+
);
|
|
2142
|
+
}
|
|
2143
|
+
const week = isoWeek(/* @__PURE__ */ new Date());
|
|
2144
|
+
const report = assembleCandidateReport({
|
|
2145
|
+
undocumentedFixes: undocumented,
|
|
2146
|
+
hotspotCandidates: hotspots,
|
|
2147
|
+
isoWeek: week,
|
|
2148
|
+
lookback
|
|
2149
|
+
});
|
|
2150
|
+
const outputPath = opts.outputPath ?? join6(cwd, "docs/solutions/.candidates", `${formatIsoWeek(week)}.md`);
|
|
2151
|
+
mkdirSync3(dirname2(outputPath), { recursive: true });
|
|
2152
|
+
writeFileSync3(outputPath, report);
|
|
2153
|
+
const candidatesFound = undocumented.length + hotspots.length;
|
|
2154
|
+
const status = {
|
|
2155
|
+
status: candidatesFound === 0 ? "no-issues" : "success",
|
|
2156
|
+
path: outputPath,
|
|
2157
|
+
candidatesFound,
|
|
2158
|
+
lookback,
|
|
2159
|
+
durationMs: Date.now() - startedAt
|
|
2160
|
+
};
|
|
2161
|
+
return emit(status, opts.nonInteractive);
|
|
2162
|
+
}
|
|
2163
|
+
function emit(status, nonInteractive) {
|
|
2164
|
+
if (nonInteractive) {
|
|
2165
|
+
process.stdout.write(JSON.stringify(status) + "\n");
|
|
2166
|
+
} else if (status.status === "failure") {
|
|
2167
|
+
process.stderr.write(`scan-candidates failed: ${status.reason}
|
|
2168
|
+
`);
|
|
2169
|
+
} else {
|
|
2170
|
+
process.stdout.write(
|
|
2171
|
+
`${status.candidatesFound} candidate(s) over ${status.lookback}
|
|
2172
|
+
\u2192 ${status.path}
|
|
2173
|
+
`
|
|
2174
|
+
);
|
|
2175
|
+
}
|
|
2176
|
+
return status;
|
|
2177
|
+
}
|
|
2178
|
+
function createScanCandidatesCommand() {
|
|
2179
|
+
return new Command19("scan-candidates").description(
|
|
2180
|
+
"Scan recent fixes and hotspots for undocumented learnings; write candidate prompts"
|
|
2181
|
+
).option("--lookback <window>", "Lookback window (e.g. 7d, 14d).", DEFAULT_LOOKBACK).option(
|
|
2182
|
+
"--non-interactive",
|
|
2183
|
+
"Emit single-line JSON status on stdout. Auto-detected when stdout is not a TTY."
|
|
2184
|
+
).option("--config <path>", "Path to harness.config.json", "harness.config.json").option(
|
|
2185
|
+
"--output-path <path>",
|
|
2186
|
+
"Override output file path (default: docs/solutions/.candidates/{YYYY-WW}.md)"
|
|
2187
|
+
).option("--solutions-dir <path>", "Solutions directory to cross-reference", "docs/solutions").action(
|
|
2188
|
+
async (options) => {
|
|
2189
|
+
const nonInteractive = options.nonInteractive === true || !process.stdout.isTTY;
|
|
2190
|
+
const status = await runCompoundScanCandidatesCommand({
|
|
2191
|
+
lookback: options.lookback,
|
|
2192
|
+
configPath: resolve11(process.cwd(), options.config),
|
|
2193
|
+
outputPath: options.outputPath ? resolve11(process.cwd(), options.outputPath) : void 0,
|
|
2194
|
+
solutionsDir: resolve11(process.cwd(), options.solutionsDir),
|
|
2195
|
+
nonInteractive
|
|
2196
|
+
});
|
|
2197
|
+
if (status.status === "failure") process.exitCode = 1;
|
|
2198
|
+
}
|
|
2199
|
+
);
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
// src/commands/compound/index.ts
|
|
2203
|
+
function createCompoundCommand() {
|
|
2204
|
+
const command = new Command20("compound").description("Compound (post-mortem playbook) commands");
|
|
2205
|
+
command.addCommand(createScanCandidatesCommand());
|
|
2206
|
+
return command;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
// src/commands/dashboard.ts
|
|
2210
|
+
import { Command as Command21 } from "commander";
|
|
2106
2211
|
import { spawn } from "child_process";
|
|
2107
2212
|
import { existsSync as existsSync4 } from "fs";
|
|
2108
2213
|
import { createRequire } from "module";
|
|
2109
|
-
import { dirname as
|
|
2214
|
+
import { dirname as dirname3, join as join7, resolve as resolve12 } from "path";
|
|
2110
2215
|
import { setTimeout } from "timers";
|
|
2111
2216
|
import { fileURLToPath } from "url";
|
|
2112
2217
|
var __filename = fileURLToPath(import.meta.url);
|
|
2113
|
-
var __dirname =
|
|
2218
|
+
var __dirname = dirname3(__filename);
|
|
2114
2219
|
var require2 = createRequire(import.meta.url);
|
|
2115
2220
|
var DEFAULT_CLIENT_PORT = 3700;
|
|
2116
2221
|
var DEFAULT_API_PORT = 3701;
|
|
@@ -2121,21 +2226,21 @@ function openBrowser(url) {
|
|
|
2121
2226
|
function resolveServerScript() {
|
|
2122
2227
|
try {
|
|
2123
2228
|
const pkgPath = require2.resolve("@harness-engineering/dashboard/package.json");
|
|
2124
|
-
const pkgDir =
|
|
2125
|
-
const built2 =
|
|
2229
|
+
const pkgDir = dirname3(pkgPath);
|
|
2230
|
+
const built2 = join7(pkgDir, "dist", "server", "serve.js");
|
|
2126
2231
|
if (existsSync4(built2)) return { script: built2, dev: false };
|
|
2127
|
-
const dev2 =
|
|
2232
|
+
const dev2 = join7(pkgDir, "src", "server", "serve.ts");
|
|
2128
2233
|
if (existsSync4(dev2)) return { script: dev2, dev: true };
|
|
2129
2234
|
} catch {
|
|
2130
2235
|
}
|
|
2131
2236
|
const built = [
|
|
2132
|
-
|
|
2133
|
-
|
|
2237
|
+
join7(__dirname, "..", "..", "..", "dashboard", "dist", "server", "serve.js"),
|
|
2238
|
+
join7(__dirname, "..", "..", "..", "..", "packages", "dashboard", "dist", "server", "serve.js")
|
|
2134
2239
|
].find((p) => existsSync4(p));
|
|
2135
2240
|
if (built) return { script: built, dev: false };
|
|
2136
2241
|
const dev = [
|
|
2137
|
-
|
|
2138
|
-
|
|
2242
|
+
join7(__dirname, "..", "..", "..", "dashboard", "src", "server", "serve.ts"),
|
|
2243
|
+
join7(__dirname, "..", "..", "..", "..", "packages", "dashboard", "src", "server", "serve.ts")
|
|
2139
2244
|
].find((p) => existsSync4(p));
|
|
2140
2245
|
return dev ? { script: dev, dev: true } : null;
|
|
2141
2246
|
}
|
|
@@ -2170,7 +2275,7 @@ function buildDashboardEnv(opts, clientPort, apiPort, projectPath) {
|
|
|
2170
2275
|
function runDashboard(opts) {
|
|
2171
2276
|
const clientPort = Number(opts.port ?? DEFAULT_CLIENT_PORT);
|
|
2172
2277
|
const apiPort = Number(opts.apiPort ?? DEFAULT_API_PORT);
|
|
2173
|
-
const projectPath =
|
|
2278
|
+
const projectPath = resolve12(opts.cwd ?? process.cwd());
|
|
2174
2279
|
const url = `http://localhost:${apiPort}`;
|
|
2175
2280
|
const server = resolveServerScript();
|
|
2176
2281
|
if (!server) {
|
|
@@ -2186,11 +2291,11 @@ function runDashboard(opts) {
|
|
|
2186
2291
|
}
|
|
2187
2292
|
}
|
|
2188
2293
|
function createDashboardCommand() {
|
|
2189
|
-
return new
|
|
2294
|
+
return new Command21("dashboard").description("Start the Harness local web dashboard").option("--port <port>", "Client dev server port", String(DEFAULT_CLIENT_PORT)).option("--api-port <port>", "API server port", String(DEFAULT_API_PORT)).option("--orchestrator-url <url>", "Orchestrator URL (default: http://localhost:8080)").option("--no-open", "Do not automatically open browser").option("--cwd <path>", "Project directory (defaults to cwd)").action((opts) => runDashboard(opts));
|
|
2190
2295
|
}
|
|
2191
2296
|
|
|
2192
2297
|
// src/commands/doctor.ts
|
|
2193
|
-
import { Command as
|
|
2298
|
+
import { Command as Command22 } from "commander";
|
|
2194
2299
|
import * as fs7 from "fs";
|
|
2195
2300
|
import * as os from "os";
|
|
2196
2301
|
import * as path13 from "path";
|
|
@@ -2508,7 +2613,7 @@ function formatCheck(check) {
|
|
|
2508
2613
|
return line;
|
|
2509
2614
|
}
|
|
2510
2615
|
function createDoctorCommand() {
|
|
2511
|
-
return new
|
|
2616
|
+
return new Command22("doctor").description("Check environment health: Node version, slash commands, MCP configuration").action((_opts, cmd) => {
|
|
2512
2617
|
const globalOpts = cmd.optsWithGlobals();
|
|
2513
2618
|
const cwd = process.cwd();
|
|
2514
2619
|
const useJson = globalOpts.json;
|
|
@@ -2534,7 +2639,7 @@ function createDoctorCommand() {
|
|
|
2534
2639
|
|
|
2535
2640
|
// src/commands/fix-drift.ts
|
|
2536
2641
|
init_dist();
|
|
2537
|
-
import { Command as
|
|
2642
|
+
import { Command as Command23 } from "commander";
|
|
2538
2643
|
import * as path14 from "path";
|
|
2539
2644
|
async function runFixDrift(options) {
|
|
2540
2645
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -2667,7 +2772,7 @@ function printFixDriftResult(value, mode, formatter) {
|
|
|
2667
2772
|
}
|
|
2668
2773
|
}
|
|
2669
2774
|
function createFixDriftCommand() {
|
|
2670
|
-
const command = new
|
|
2775
|
+
const command = new Command23("fix-drift").description("Auto-fix entropy issues (doc drift, dead code)").option("--no-dry-run", "Actually apply fixes (default is dry-run mode)").action(async (opts, cmd) => {
|
|
2671
2776
|
const globalOpts = cmd.optsWithGlobals();
|
|
2672
2777
|
const mode = resolveOutputMode(globalOpts);
|
|
2673
2778
|
const formatter = new OutputFormatter(mode);
|
|
@@ -2697,7 +2802,7 @@ function createFixDriftCommand() {
|
|
|
2697
2802
|
}
|
|
2698
2803
|
|
|
2699
2804
|
// src/commands/generate.ts
|
|
2700
|
-
import { Command as
|
|
2805
|
+
import { Command as Command24 } from "commander";
|
|
2701
2806
|
function validatePlatforms(platforms) {
|
|
2702
2807
|
for (const p of platforms) {
|
|
2703
2808
|
if (!VALID_PLATFORMS.includes(p)) {
|
|
@@ -2757,50 +2862,75 @@ async function runGenerateAction(opts, globalOpts) {
|
|
|
2757
2862
|
}
|
|
2758
2863
|
}
|
|
2759
2864
|
function createGenerateCommand() {
|
|
2760
|
-
return new
|
|
2865
|
+
return new Command24("generate").description("Generate all platform integrations (slash commands + agent definitions)").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global directories", false).option("--include-global", "Include built-in global skills", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).option("--yes", "Skip deletion confirmation prompts", false).action(async (opts, cmd) => {
|
|
2761
2866
|
await runGenerateAction(opts, cmd.optsWithGlobals());
|
|
2762
2867
|
});
|
|
2763
2868
|
}
|
|
2764
2869
|
|
|
2765
2870
|
// src/commands/graph/index.ts
|
|
2766
|
-
import { Command as
|
|
2871
|
+
import { Command as Command27 } from "commander";
|
|
2767
2872
|
|
|
2768
2873
|
// src/commands/graph/status.ts
|
|
2769
2874
|
import * as path15 from "path";
|
|
2770
|
-
async function
|
|
2771
|
-
const { GraphStore } = await import("./dist-42AYXCAK.js");
|
|
2772
|
-
const graphDir = path15.join(projectPath, ".harness", "graph");
|
|
2773
|
-
const store = new GraphStore();
|
|
2774
|
-
const loaded = await store.load(graphDir);
|
|
2775
|
-
if (!loaded) return { status: "no_graph", message: "No graph found. Run `harness scan` first." };
|
|
2875
|
+
async function readConnectorSyncStatus(graphDir) {
|
|
2776
2876
|
const fs42 = await import("fs/promises");
|
|
2777
|
-
const
|
|
2778
|
-
let lastScan = "unknown";
|
|
2779
|
-
try {
|
|
2780
|
-
const meta = JSON.parse(await fs42.readFile(metaPath, "utf-8"));
|
|
2781
|
-
lastScan = meta.lastScanTimestamp;
|
|
2782
|
-
} catch {
|
|
2783
|
-
}
|
|
2784
|
-
const allNodes = store.findNodes({});
|
|
2785
|
-
const nodesByType = {};
|
|
2786
|
-
for (const node of allNodes) {
|
|
2787
|
-
nodesByType[node.type] = (nodesByType[node.type] ?? 0) + 1;
|
|
2788
|
-
}
|
|
2789
|
-
let connectorSyncStatus = {};
|
|
2877
|
+
const result = {};
|
|
2790
2878
|
try {
|
|
2791
2879
|
const syncMetaPath = path15.join(graphDir, "sync-metadata.json");
|
|
2792
2880
|
const syncMeta = JSON.parse(await fs42.readFile(syncMetaPath, "utf-8"));
|
|
2793
2881
|
for (const [name, data] of Object.entries(syncMeta.connectors ?? {})) {
|
|
2794
|
-
|
|
2882
|
+
result[name] = data.lastSyncTimestamp;
|
|
2795
2883
|
}
|
|
2796
2884
|
} catch {
|
|
2797
2885
|
}
|
|
2886
|
+
return result;
|
|
2887
|
+
}
|
|
2888
|
+
async function runGraphStatus(projectPath) {
|
|
2889
|
+
const { GraphStore, loadGraphMetadata } = await import("./dist-D27LJR2T.js");
|
|
2890
|
+
const graphDir = path15.join(projectPath, ".harness", "graph");
|
|
2891
|
+
const metaResult = await loadGraphMetadata(graphDir);
|
|
2892
|
+
if (metaResult.status === "not_found") {
|
|
2893
|
+
return { status: "no_graph", message: "No graph found. Run `harness scan` first." };
|
|
2894
|
+
}
|
|
2895
|
+
if (metaResult.status === "schema_mismatch") {
|
|
2896
|
+
return {
|
|
2897
|
+
status: "schema_mismatch",
|
|
2898
|
+
message: `Graph schema version mismatch: file is v${metaResult.found}, CLI expects v${metaResult.expected}. Run \`harness scan\` to rebuild.`
|
|
2899
|
+
};
|
|
2900
|
+
}
|
|
2901
|
+
const meta = metaResult.metadata;
|
|
2902
|
+
const connectorSyncStatus = await readConnectorSyncStatus(graphDir);
|
|
2903
|
+
if (meta.nodesByType) {
|
|
2904
|
+
return {
|
|
2905
|
+
status: "ok",
|
|
2906
|
+
nodeCount: meta.nodeCount,
|
|
2907
|
+
edgeCount: meta.edgeCount,
|
|
2908
|
+
nodesByType: { ...meta.nodesByType },
|
|
2909
|
+
lastScanTimestamp: meta.lastScanTimestamp,
|
|
2910
|
+
...Object.keys(connectorSyncStatus).length > 0 ? { connectorSyncStatus } : {}
|
|
2911
|
+
};
|
|
2912
|
+
}
|
|
2913
|
+
const store = new GraphStore();
|
|
2914
|
+
const loaded = await store.load(graphDir);
|
|
2915
|
+
if (!loaded) {
|
|
2916
|
+
return {
|
|
2917
|
+
status: "ok",
|
|
2918
|
+
nodeCount: meta.nodeCount,
|
|
2919
|
+
edgeCount: meta.edgeCount,
|
|
2920
|
+
lastScanTimestamp: meta.lastScanTimestamp,
|
|
2921
|
+
...Object.keys(connectorSyncStatus).length > 0 ? { connectorSyncStatus } : {}
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
const nodesByType = {};
|
|
2925
|
+
for (const node of store.findNodes({})) {
|
|
2926
|
+
nodesByType[node.type] = (nodesByType[node.type] ?? 0) + 1;
|
|
2927
|
+
}
|
|
2798
2928
|
return {
|
|
2799
2929
|
status: "ok",
|
|
2800
2930
|
nodeCount: store.nodeCount,
|
|
2801
2931
|
edgeCount: store.edgeCount,
|
|
2802
2932
|
nodesByType,
|
|
2803
|
-
lastScanTimestamp:
|
|
2933
|
+
lastScanTimestamp: meta.lastScanTimestamp,
|
|
2804
2934
|
...Object.keys(connectorSyncStatus).length > 0 ? { connectorSyncStatus } : {}
|
|
2805
2935
|
};
|
|
2806
2936
|
}
|
|
@@ -2808,7 +2938,7 @@ async function runGraphStatus(projectPath) {
|
|
|
2808
2938
|
// src/commands/graph/export.ts
|
|
2809
2939
|
import * as path16 from "path";
|
|
2810
2940
|
async function runGraphExport(projectPath, format) {
|
|
2811
|
-
const { GraphStore } = await import("./dist-
|
|
2941
|
+
const { GraphStore } = await import("./dist-D27LJR2T.js");
|
|
2812
2942
|
const graphDir = path16.join(projectPath, ".harness", "graph");
|
|
2813
2943
|
const store = new GraphStore();
|
|
2814
2944
|
const loaded = await store.load(graphDir);
|
|
@@ -2841,10 +2971,10 @@ async function runGraphExport(projectPath, format) {
|
|
|
2841
2971
|
import * as path19 from "path";
|
|
2842
2972
|
|
|
2843
2973
|
// src/commands/graph/query.ts
|
|
2844
|
-
import { Command as
|
|
2974
|
+
import { Command as Command25 } from "commander";
|
|
2845
2975
|
import * as path17 from "path";
|
|
2846
2976
|
async function runQuery(projectPath, rootNodeId, opts) {
|
|
2847
|
-
const { GraphStore, ContextQL } = await import("./dist-
|
|
2977
|
+
const { GraphStore, ContextQL } = await import("./dist-D27LJR2T.js");
|
|
2848
2978
|
const store = new GraphStore();
|
|
2849
2979
|
const graphDir = path17.join(projectPath, ".harness", "graph");
|
|
2850
2980
|
const loaded = await store.load(graphDir);
|
|
@@ -2887,13 +3017,13 @@ async function runQueryAction(rootNodeId, opts, globalOpts) {
|
|
|
2887
3017
|
}
|
|
2888
3018
|
}
|
|
2889
3019
|
function createQueryCommand() {
|
|
2890
|
-
return new
|
|
3020
|
+
return new Command25("query").description("Query the knowledge graph").argument("<rootNodeId>", "Starting node ID").option("--depth <n>", "Max traversal depth", "3").option("--types <types>", "Comma-separated node types to include").option("--edges <edges>", "Comma-separated edge types to include").option("--bidirectional", "Traverse both directions").action(async (rootNodeId, opts, cmd) => {
|
|
2891
3021
|
await runQueryAction(rootNodeId, opts, cmd.optsWithGlobals());
|
|
2892
3022
|
});
|
|
2893
3023
|
}
|
|
2894
3024
|
|
|
2895
3025
|
// src/commands/graph/ingest.ts
|
|
2896
|
-
import { Command as
|
|
3026
|
+
import { Command as Command26 } from "commander";
|
|
2897
3027
|
import * as path18 from "path";
|
|
2898
3028
|
async function loadConnectorConfig(projectPath, source) {
|
|
2899
3029
|
try {
|
|
@@ -2941,20 +3071,21 @@ async function runIngest(projectPath, source, opts) {
|
|
|
2941
3071
|
ConfluenceConnector,
|
|
2942
3072
|
FigmaConnector,
|
|
2943
3073
|
MiroConnector
|
|
2944
|
-
} = await import("./dist-
|
|
3074
|
+
} = await import("./dist-D27LJR2T.js");
|
|
2945
3075
|
const graphDir = path18.join(projectPath, ".harness", "graph");
|
|
2946
3076
|
const store = new GraphStore();
|
|
2947
3077
|
await store.load(graphDir);
|
|
3078
|
+
const ingestOptions = loadIngestOptions(projectPath);
|
|
2948
3079
|
if (opts?.all) {
|
|
2949
3080
|
const startMs = Date.now();
|
|
2950
|
-
const codeResult = await new CodeIngestor(store).ingest(projectPath);
|
|
3081
|
+
const codeResult = await new CodeIngestor(store, ingestOptions).ingest(projectPath);
|
|
2951
3082
|
new TopologicalLinker(store).link();
|
|
2952
3083
|
const knowledgeResult = await new KnowledgeIngestor(store).ingestAll(projectPath);
|
|
2953
3084
|
const reqResult = await new RequirementIngestor(store).ingestSpecs(
|
|
2954
3085
|
path18.join(projectPath, "docs", "changes")
|
|
2955
3086
|
);
|
|
2956
3087
|
const gitResult = await new GitIngestor(store).ingest(projectPath);
|
|
2957
|
-
const { createExtractionRunner } = await import("./dist-
|
|
3088
|
+
const { createExtractionRunner } = await import("./dist-D27LJR2T.js");
|
|
2958
3089
|
const extractedDir = path18.join(projectPath, ".harness", "knowledge", "extracted");
|
|
2959
3090
|
const signalsResult = await createExtractionRunner().run(projectPath, store, extractedDir);
|
|
2960
3091
|
const syncManager = new SyncManager(store, graphDir);
|
|
@@ -2985,7 +3116,7 @@ async function runIngest(projectPath, source, opts) {
|
|
|
2985
3116
|
let result;
|
|
2986
3117
|
switch (source) {
|
|
2987
3118
|
case "code":
|
|
2988
|
-
result = await new CodeIngestor(store).ingest(projectPath);
|
|
3119
|
+
result = await new CodeIngestor(store, ingestOptions).ingest(projectPath);
|
|
2989
3120
|
new TopologicalLinker(store).link();
|
|
2990
3121
|
break;
|
|
2991
3122
|
case "knowledge":
|
|
@@ -3000,7 +3131,7 @@ async function runIngest(projectPath, source, opts) {
|
|
|
3000
3131
|
);
|
|
3001
3132
|
break;
|
|
3002
3133
|
case "business-signals": {
|
|
3003
|
-
const { createExtractionRunner } = await import("./dist-
|
|
3134
|
+
const { createExtractionRunner } = await import("./dist-D27LJR2T.js");
|
|
3004
3135
|
const extractedDir = path18.join(projectPath, ".harness", "knowledge", "extracted");
|
|
3005
3136
|
result = await createExtractionRunner().run(projectPath, store, extractedDir);
|
|
3006
3137
|
break;
|
|
@@ -3037,7 +3168,7 @@ async function runIngest(projectPath, source, opts) {
|
|
|
3037
3168
|
return result;
|
|
3038
3169
|
}
|
|
3039
3170
|
function createIngestCommand() {
|
|
3040
|
-
return new
|
|
3171
|
+
return new Command26("ingest").description("Ingest data into the knowledge graph").option(
|
|
3041
3172
|
"--source <name>",
|
|
3042
3173
|
"Source to ingest (code, knowledge, git, requirements, business-signals, jira, slack, ci, confluence, figma, miro)"
|
|
3043
3174
|
).option("--all", "Run all sources (code, knowledge, git, and configured connectors)").option("--full", "Force full re-ingestion").action(async (opts, cmd) => {
|
|
@@ -3072,15 +3203,17 @@ function resolveProjectPath(globalOpts) {
|
|
|
3072
3203
|
return path19.resolve(globalOpts.config ? path19.dirname(globalOpts.config) : ".");
|
|
3073
3204
|
}
|
|
3074
3205
|
function printGraphStatus(result) {
|
|
3075
|
-
if (result.status === "no_graph") {
|
|
3206
|
+
if (result.status === "no_graph" || result.status === "schema_mismatch") {
|
|
3076
3207
|
console.log(result.message);
|
|
3077
3208
|
return;
|
|
3078
3209
|
}
|
|
3079
3210
|
console.log(`Graph: ${result.nodeCount} nodes, ${result.edgeCount} edges`);
|
|
3080
3211
|
console.log(`Last scan: ${result.lastScanTimestamp}`);
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3212
|
+
if (result.nodesByType) {
|
|
3213
|
+
console.log("Nodes by type:");
|
|
3214
|
+
for (const [type, count] of Object.entries(result.nodesByType)) {
|
|
3215
|
+
console.log(` ${type}: ${count}`);
|
|
3216
|
+
}
|
|
3084
3217
|
}
|
|
3085
3218
|
if (!result.connectorSyncStatus) return;
|
|
3086
3219
|
console.log("Connector sync status:");
|
|
@@ -3113,17 +3246,17 @@ async function runExportAction(opts, cmd) {
|
|
|
3113
3246
|
}
|
|
3114
3247
|
}
|
|
3115
3248
|
function createGraphCommand() {
|
|
3116
|
-
const graph = new
|
|
3249
|
+
const graph = new Command27("graph").description("Knowledge graph management");
|
|
3117
3250
|
graph.command("status").description("Show graph statistics").action(runStatusAction);
|
|
3118
3251
|
graph.command("export").description("Export graph").requiredOption("--format <format>", "Output format (json, mermaid)").action(runExportAction);
|
|
3119
3252
|
return graph;
|
|
3120
3253
|
}
|
|
3121
3254
|
|
|
3122
3255
|
// src/commands/hooks/index.ts
|
|
3123
|
-
import { Command as
|
|
3256
|
+
import { Command as Command32 } from "commander";
|
|
3124
3257
|
|
|
3125
3258
|
// src/commands/hooks/init.ts
|
|
3126
|
-
import { Command as
|
|
3259
|
+
import { Command as Command28 } from "commander";
|
|
3127
3260
|
import * as fs8 from "fs";
|
|
3128
3261
|
import * as path20 from "path";
|
|
3129
3262
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -3245,7 +3378,7 @@ function initHooks(options) {
|
|
|
3245
3378
|
return { copiedScripts, settingsPath, profilePath };
|
|
3246
3379
|
}
|
|
3247
3380
|
function createInitCommand2() {
|
|
3248
|
-
return new
|
|
3381
|
+
return new Command28("init").description("Install Claude Code hook configurations into the current project").option("--profile <profile>", "Hook profile: minimal, standard, or strict", "standard").action(async (opts, cmd) => {
|
|
3249
3382
|
const globalOpts = cmd.optsWithGlobals();
|
|
3250
3383
|
const profile = opts.profile;
|
|
3251
3384
|
if (!VALID_PROFILES.includes(profile)) {
|
|
@@ -3283,7 +3416,7 @@ function createInitCommand2() {
|
|
|
3283
3416
|
}
|
|
3284
3417
|
|
|
3285
3418
|
// src/commands/hooks/list.ts
|
|
3286
|
-
import { Command as
|
|
3419
|
+
import { Command as Command29 } from "commander";
|
|
3287
3420
|
import * as fs9 from "fs";
|
|
3288
3421
|
import * as path21 from "path";
|
|
3289
3422
|
function listHooks(projectDir) {
|
|
@@ -3316,7 +3449,7 @@ function listHooks(projectDir) {
|
|
|
3316
3449
|
return result;
|
|
3317
3450
|
}
|
|
3318
3451
|
function createListCommand() {
|
|
3319
|
-
return new
|
|
3452
|
+
return new Command29("list").description("Show installed hooks and active profile").action(async (_opts, cmd) => {
|
|
3320
3453
|
const globalOpts = cmd.optsWithGlobals();
|
|
3321
3454
|
const projectDir = process.cwd();
|
|
3322
3455
|
const result = listHooks(projectDir);
|
|
@@ -3337,7 +3470,7 @@ function createListCommand() {
|
|
|
3337
3470
|
}
|
|
3338
3471
|
|
|
3339
3472
|
// src/commands/hooks/remove.ts
|
|
3340
|
-
import { Command as
|
|
3473
|
+
import { Command as Command30 } from "commander";
|
|
3341
3474
|
import * as fs10 from "fs";
|
|
3342
3475
|
import * as path22 from "path";
|
|
3343
3476
|
function removeHooks(projectDir) {
|
|
@@ -3367,7 +3500,7 @@ function removeHooks(projectDir) {
|
|
|
3367
3500
|
return { removed, hooksDir, settingsCleaned };
|
|
3368
3501
|
}
|
|
3369
3502
|
function createRemoveCommand() {
|
|
3370
|
-
return new
|
|
3503
|
+
return new Command30("remove").description("Remove harness-managed hooks from the current project").action(async (_opts, cmd) => {
|
|
3371
3504
|
const globalOpts = cmd.optsWithGlobals();
|
|
3372
3505
|
const projectDir = process.cwd();
|
|
3373
3506
|
const result = removeHooks(projectDir);
|
|
@@ -3389,7 +3522,7 @@ function createRemoveCommand() {
|
|
|
3389
3522
|
}
|
|
3390
3523
|
|
|
3391
3524
|
// src/commands/hooks/add.ts
|
|
3392
|
-
import { Command as
|
|
3525
|
+
import { Command as Command31 } from "commander";
|
|
3393
3526
|
import * as fs11 from "fs";
|
|
3394
3527
|
import * as path23 from "path";
|
|
3395
3528
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -3446,7 +3579,7 @@ function addHooks(hookName, projectDir) {
|
|
|
3446
3579
|
return result;
|
|
3447
3580
|
}
|
|
3448
3581
|
function createAddCommand2() {
|
|
3449
|
-
return new
|
|
3582
|
+
return new Command31("add").argument("<hook-name>", "Hook name or alias (e.g., sentinel)").description("Add a hook without changing the profile").action(async (hookName, _opts, cmd) => {
|
|
3450
3583
|
const projectDir = process.cwd();
|
|
3451
3584
|
try {
|
|
3452
3585
|
const res = addHooks(hookName, projectDir);
|
|
@@ -3471,7 +3604,7 @@ function createAddCommand2() {
|
|
|
3471
3604
|
|
|
3472
3605
|
// src/commands/hooks/index.ts
|
|
3473
3606
|
function createHooksCommand() {
|
|
3474
|
-
const command = new
|
|
3607
|
+
const command = new Command32("hooks").description("Manage Claude Code hook configurations");
|
|
3475
3608
|
command.addCommand(createInitCommand2());
|
|
3476
3609
|
command.addCommand(createListCommand());
|
|
3477
3610
|
command.addCommand(createRemoveCommand());
|
|
@@ -3480,7 +3613,7 @@ function createHooksCommand() {
|
|
|
3480
3613
|
}
|
|
3481
3614
|
|
|
3482
3615
|
// src/commands/impact-preview.ts
|
|
3483
|
-
import { Command as
|
|
3616
|
+
import { Command as Command33 } from "commander";
|
|
3484
3617
|
import { execSync as execSync4 } from "child_process";
|
|
3485
3618
|
import * as path24 from "path";
|
|
3486
3619
|
import * as fs12 from "fs";
|
|
@@ -3679,7 +3812,7 @@ async function runImpactPreview(options) {
|
|
|
3679
3812
|
return formatImpactOutput(stagedFiles, acc, options);
|
|
3680
3813
|
}
|
|
3681
3814
|
function createImpactPreviewCommand() {
|
|
3682
|
-
const command = new
|
|
3815
|
+
const command = new Command33("impact-preview").description("Show blast radius of staged changes using the knowledge graph").option("--detailed", "Show all affected files instead of top items").option("--per-file", "Show impact per staged file instead of aggregate").option("--path <dir>", "Project root (default: cwd)").action(async (opts) => {
|
|
3683
3816
|
const output = await runImpactPreview({
|
|
3684
3817
|
detailed: opts.detailed,
|
|
3685
3818
|
perFile: opts.perFile,
|
|
@@ -3693,13 +3826,13 @@ function createImpactPreviewCommand() {
|
|
|
3693
3826
|
|
|
3694
3827
|
// src/commands/init.ts
|
|
3695
3828
|
init_dist();
|
|
3696
|
-
import { Command as
|
|
3829
|
+
import { Command as Command35 } from "commander";
|
|
3697
3830
|
import chalk3 from "chalk";
|
|
3698
3831
|
import * as fs15 from "fs";
|
|
3699
3832
|
import * as path27 from "path";
|
|
3700
3833
|
|
|
3701
3834
|
// src/commands/setup-mcp.ts
|
|
3702
|
-
import { Command as
|
|
3835
|
+
import { Command as Command34 } from "commander";
|
|
3703
3836
|
import * as fs14 from "fs";
|
|
3704
3837
|
import * as path26 from "path";
|
|
3705
3838
|
import * as os2 from "os";
|
|
@@ -4023,7 +4156,7 @@ function printMcpResult(configured, skipped, trustedFolder) {
|
|
|
4023
4156
|
console.log("");
|
|
4024
4157
|
}
|
|
4025
4158
|
function createSetupMcpCommand() {
|
|
4026
|
-
return new
|
|
4159
|
+
return new Command34("setup-mcp").description("Configure MCP server for AI agent integration").option("--client <client>", "Client to configure (claude, gemini, codex, cursor, all)", "all").option("--pick", "Launch interactive tool picker (Cursor only)").option("--yes", "Bypass interactive picker and use curated 25-tool set (Cursor only)").action(async (opts, cmd) => {
|
|
4027
4160
|
const globalOpts = cmd.optsWithGlobals();
|
|
4028
4161
|
const cwd = process.cwd();
|
|
4029
4162
|
let configured;
|
|
@@ -4165,7 +4298,7 @@ async function runInitAction2(opts) {
|
|
|
4165
4298
|
process.exit(ExitCode.SUCCESS);
|
|
4166
4299
|
}
|
|
4167
4300
|
function createInitCommand3() {
|
|
4168
|
-
const command = new
|
|
4301
|
+
const command = new Command35("init").description("Initialize a new harness-engineering project").option("-n, --name <name>", "Project name").option("-l, --level <level>", "Adoption level (basic, intermediate, advanced)", "basic").option("-t, --template <template>", "Specific template name (e.g. orchestrator)").option("--framework <framework>", "Framework overlay (nextjs)").option("--language <language>", "Target language (typescript, python, go, rust, java)").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Use defaults without prompting").action(async (opts, cmd) => {
|
|
4169
4302
|
const globalOpts = cmd.optsWithGlobals();
|
|
4170
4303
|
await runInitAction2({
|
|
4171
4304
|
name: opts.name,
|
|
@@ -4184,7 +4317,7 @@ import * as fs20 from "fs";
|
|
|
4184
4317
|
import * as os5 from "os";
|
|
4185
4318
|
import * as path32 from "path";
|
|
4186
4319
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
4187
|
-
import { Command as
|
|
4320
|
+
import { Command as Command36 } from "commander";
|
|
4188
4321
|
import { parse as yamlParse } from "yaml";
|
|
4189
4322
|
|
|
4190
4323
|
// src/registry/npm-client.ts
|
|
@@ -4744,7 +4877,7 @@ async function runInstall(skillName, options) {
|
|
|
4744
4877
|
return result;
|
|
4745
4878
|
}
|
|
4746
4879
|
function createInstallCommand() {
|
|
4747
|
-
const cmd = new
|
|
4880
|
+
const cmd = new Command36("install");
|
|
4748
4881
|
cmd.description("Install skills from npm registry, local directory, or GitHub repository").argument("<skill>", 'Skill name, @harness-skills/scoped package, or "." for bulk install').option("--version <range>", "Semver range or exact version to install").option("--force", "Force reinstall even if same version is already installed").option(
|
|
4749
4882
|
"--from <source>",
|
|
4750
4883
|
"Install from local path, directory, or GitHub (github:owner/repo, https://github.com/owner/repo)"
|
|
@@ -4780,7 +4913,7 @@ function createInstallCommand() {
|
|
|
4780
4913
|
init_dist();
|
|
4781
4914
|
import * as fs21 from "fs/promises";
|
|
4782
4915
|
import * as path33 from "path";
|
|
4783
|
-
import { Command as
|
|
4916
|
+
import { Command as Command37 } from "commander";
|
|
4784
4917
|
import semver3 from "semver";
|
|
4785
4918
|
async function runInstallConstraints(options) {
|
|
4786
4919
|
const { source, configPath, lockfilePath } = options;
|
|
@@ -5034,17 +5167,17 @@ async function handleInstallConstraints(source, opts) {
|
|
|
5034
5167
|
logInstallResult(result.value, opts);
|
|
5035
5168
|
}
|
|
5036
5169
|
function createInstallConstraintsCommand() {
|
|
5037
|
-
const cmd = new
|
|
5170
|
+
const cmd = new Command37("install-constraints");
|
|
5038
5171
|
cmd.description("Install a constraints bundle into the local harness config").argument("<source>", "Path to a .harness-constraints.json bundle file").option("--force-local", "Resolve all conflicts by keeping local values").option("--force-package", "Resolve all conflicts by using package values").option("--dry-run", "Show what would change without writing files").option("-c, --config <path>", "Path to harness.config.json").action(handleInstallConstraints);
|
|
5039
5172
|
return cmd;
|
|
5040
5173
|
}
|
|
5041
5174
|
|
|
5042
5175
|
// src/commands/integrations/index.ts
|
|
5043
|
-
import { Command as
|
|
5176
|
+
import { Command as Command42 } from "commander";
|
|
5044
5177
|
|
|
5045
5178
|
// src/commands/integrations/add.ts
|
|
5046
5179
|
init_dist();
|
|
5047
|
-
import { Command as
|
|
5180
|
+
import { Command as Command38 } from "commander";
|
|
5048
5181
|
import * as fs22 from "fs";
|
|
5049
5182
|
import * as path34 from "path";
|
|
5050
5183
|
import chalk4 from "chalk";
|
|
@@ -5108,7 +5241,7 @@ function printAddSuccess(value) {
|
|
|
5108
5241
|
}
|
|
5109
5242
|
}
|
|
5110
5243
|
function createAddIntegrationCommand() {
|
|
5111
|
-
return new
|
|
5244
|
+
return new Command38("add").description("Enable an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
|
|
5112
5245
|
const globalOpts = cmd.optsWithGlobals();
|
|
5113
5246
|
const result = addIntegration(process.cwd(), name);
|
|
5114
5247
|
if (!result.ok) {
|
|
@@ -5122,7 +5255,7 @@ function createAddIntegrationCommand() {
|
|
|
5122
5255
|
}
|
|
5123
5256
|
|
|
5124
5257
|
// src/commands/integrations/list.ts
|
|
5125
|
-
import { Command as
|
|
5258
|
+
import { Command as Command39 } from "commander";
|
|
5126
5259
|
import * as path35 from "path";
|
|
5127
5260
|
import chalk5 from "chalk";
|
|
5128
5261
|
function printTier0Integrations(tier0, mcpServers) {
|
|
@@ -5179,12 +5312,12 @@ async function runListIntegrations(globalOpts) {
|
|
|
5179
5312
|
process.exit(ExitCode.SUCCESS);
|
|
5180
5313
|
}
|
|
5181
5314
|
function createListIntegrationsCommand() {
|
|
5182
|
-
return new
|
|
5315
|
+
return new Command39("list").description("Show all MCP integrations with status").action(async (_opts, cmd) => runListIntegrations(cmd.optsWithGlobals()));
|
|
5183
5316
|
}
|
|
5184
5317
|
|
|
5185
5318
|
// src/commands/integrations/remove.ts
|
|
5186
5319
|
init_dist();
|
|
5187
|
-
import { Command as
|
|
5320
|
+
import { Command as Command40 } from "commander";
|
|
5188
5321
|
import * as fs23 from "fs";
|
|
5189
5322
|
import * as path36 from "path";
|
|
5190
5323
|
function removeIntegration(cwd, name) {
|
|
@@ -5211,7 +5344,7 @@ function removeIntegration(cwd, name) {
|
|
|
5211
5344
|
return Ok(def.displayName);
|
|
5212
5345
|
}
|
|
5213
5346
|
function createRemoveIntegrationCommand() {
|
|
5214
|
-
return new
|
|
5347
|
+
return new Command40("remove").description("Remove an MCP integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
|
|
5215
5348
|
const globalOpts = cmd.optsWithGlobals();
|
|
5216
5349
|
const cwd = process.cwd();
|
|
5217
5350
|
const result = removeIntegration(cwd, name);
|
|
@@ -5233,7 +5366,7 @@ function createRemoveIntegrationCommand() {
|
|
|
5233
5366
|
|
|
5234
5367
|
// src/commands/integrations/dismiss.ts
|
|
5235
5368
|
init_dist();
|
|
5236
|
-
import { Command as
|
|
5369
|
+
import { Command as Command41 } from "commander";
|
|
5237
5370
|
import * as path37 from "path";
|
|
5238
5371
|
function dismissIntegration(cwd, name) {
|
|
5239
5372
|
const def = INTEGRATION_REGISTRY.find((i) => i.name === name);
|
|
@@ -5255,7 +5388,7 @@ function dismissIntegration(cwd, name) {
|
|
|
5255
5388
|
return Ok(def.displayName);
|
|
5256
5389
|
}
|
|
5257
5390
|
function createDismissIntegrationCommand() {
|
|
5258
|
-
return new
|
|
5391
|
+
return new Command41("dismiss").description("Suppress doctor recommendations for an integration").argument("<name>", "Integration name (e.g. perplexity, augment-code)").action(async (name, _opts, cmd) => {
|
|
5259
5392
|
const globalOpts = cmd.optsWithGlobals();
|
|
5260
5393
|
const cwd = process.cwd();
|
|
5261
5394
|
const result = dismissIntegration(cwd, name);
|
|
@@ -5279,7 +5412,7 @@ function createDismissIntegrationCommand() {
|
|
|
5279
5412
|
|
|
5280
5413
|
// src/commands/integrations/index.ts
|
|
5281
5414
|
function createIntegrationsCommand() {
|
|
5282
|
-
const command = new
|
|
5415
|
+
const command = new Command42("integrations").description(
|
|
5283
5416
|
"Manage MCP peer integrations (add, list, remove, dismiss)"
|
|
5284
5417
|
);
|
|
5285
5418
|
command.addCommand(createListIntegrationsCommand());
|
|
@@ -5290,18 +5423,18 @@ function createIntegrationsCommand() {
|
|
|
5290
5423
|
}
|
|
5291
5424
|
|
|
5292
5425
|
// src/commands/knowledge-pipeline.ts
|
|
5293
|
-
import { Command as
|
|
5426
|
+
import { Command as Command43 } from "commander";
|
|
5294
5427
|
import * as path38 from "path";
|
|
5295
5428
|
import chalk6 from "chalk";
|
|
5296
5429
|
function createKnowledgePipelineCommand() {
|
|
5297
|
-
return new
|
|
5430
|
+
return new Command43("knowledge-pipeline").description("Run knowledge extraction, drift detection, and gap analysis").option("--fix", "Enable convergence-based auto-remediation (default: detect-only)").option("--ci", "Non-interactive mode \u2014 apply safe fixes only, report everything else").option("--domain <name>", "Limit pipeline to a specific knowledge domain").option("--drift-check", "Exit 1 if unresolved drift exists (CI gate mode)").option("--analyze-images", "Enable vision model analysis of image files").option("--image-paths <paths>", "Comma-separated image file paths for analysis").option("--coverage", "Display per-domain coverage report").option("--check-contradictions", "Display cross-source contradiction report").action(async (opts, cmd) => {
|
|
5298
5431
|
const globalOpts = cmd.optsWithGlobals();
|
|
5299
5432
|
const projectDir = process.cwd();
|
|
5300
5433
|
try {
|
|
5301
5434
|
const graphDir = path38.join(projectDir, ".harness", "graph");
|
|
5302
5435
|
const fs42 = await import("fs/promises");
|
|
5303
5436
|
await fs42.mkdir(graphDir, { recursive: true });
|
|
5304
|
-
const { GraphStore, KnowledgePipelineRunner } = await import("./dist-
|
|
5437
|
+
const { GraphStore, KnowledgePipelineRunner } = await import("./dist-D27LJR2T.js");
|
|
5305
5438
|
const store = new GraphStore();
|
|
5306
5439
|
try {
|
|
5307
5440
|
await store.load(graphDir);
|
|
@@ -5458,11 +5591,11 @@ function createKnowledgePipelineCommand() {
|
|
|
5458
5591
|
}
|
|
5459
5592
|
|
|
5460
5593
|
// src/commands/learnings/index.ts
|
|
5461
|
-
import { Command as
|
|
5594
|
+
import { Command as Command45 } from "commander";
|
|
5462
5595
|
|
|
5463
5596
|
// src/commands/learnings/prune.ts
|
|
5464
5597
|
init_dist();
|
|
5465
|
-
import { Command as
|
|
5598
|
+
import { Command as Command44 } from "commander";
|
|
5466
5599
|
import * as path39 from "path";
|
|
5467
5600
|
async function handlePrune(opts) {
|
|
5468
5601
|
const projectPath = path39.resolve(opts.path);
|
|
@@ -5504,23 +5637,23 @@ function printPatternProposals(patterns) {
|
|
|
5504
5637
|
);
|
|
5505
5638
|
}
|
|
5506
5639
|
function createPruneCommand() {
|
|
5507
|
-
return new
|
|
5640
|
+
return new Command44("prune").description(
|
|
5508
5641
|
"Analyze global learnings for patterns, present improvement proposals, and archive old entries"
|
|
5509
5642
|
).option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(handlePrune);
|
|
5510
5643
|
}
|
|
5511
5644
|
|
|
5512
5645
|
// src/commands/learnings/index.ts
|
|
5513
5646
|
function createLearningsCommand() {
|
|
5514
|
-
const command = new
|
|
5647
|
+
const command = new Command45("learnings").description("Learnings management commands");
|
|
5515
5648
|
command.addCommand(createPruneCommand());
|
|
5516
5649
|
return command;
|
|
5517
5650
|
}
|
|
5518
5651
|
|
|
5519
5652
|
// src/commands/linter/index.ts
|
|
5520
|
-
import { Command as
|
|
5653
|
+
import { Command as Command48 } from "commander";
|
|
5521
5654
|
|
|
5522
5655
|
// src/commands/linter/generate.ts
|
|
5523
|
-
import { Command as
|
|
5656
|
+
import { Command as Command46 } from "commander";
|
|
5524
5657
|
function formatGenerateError(e) {
|
|
5525
5658
|
switch (e.type) {
|
|
5526
5659
|
case "parse":
|
|
@@ -5564,7 +5697,7 @@ function handleSuccess(result, useJson) {
|
|
|
5564
5697
|
Generated ${result.rulesGenerated.length} rules to ${result.outputDir}`);
|
|
5565
5698
|
}
|
|
5566
5699
|
function createGenerateCommand2() {
|
|
5567
|
-
return new
|
|
5700
|
+
return new Command46("generate").description("Generate ESLint rules from harness-linter.yml").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("-o, --output <dir>", "Override output directory").option("--clean", "Remove existing files before generating").option("--dry-run", "Preview without writing files").option("--json", "Output as JSON").option("--verbose", "Show detailed output").action(async (options) => {
|
|
5568
5701
|
try {
|
|
5569
5702
|
if (options.verbose) logger.info(`Parsing config: ${options.config}`);
|
|
5570
5703
|
const result = await generate({
|
|
@@ -5586,9 +5719,9 @@ function createGenerateCommand2() {
|
|
|
5586
5719
|
}
|
|
5587
5720
|
|
|
5588
5721
|
// src/commands/linter/validate.ts
|
|
5589
|
-
import { Command as
|
|
5722
|
+
import { Command as Command47 } from "commander";
|
|
5590
5723
|
function createValidateCommand() {
|
|
5591
|
-
return new
|
|
5724
|
+
return new Command47("validate").description("Validate harness-linter.yml config").option("-c, --config <path>", "Path to harness-linter.yml", "./harness-linter.yml").option("--json", "Output as JSON").action(async (options) => {
|
|
5592
5725
|
try {
|
|
5593
5726
|
const result = await validate({ configPath: options.config });
|
|
5594
5727
|
if (options.json) {
|
|
@@ -5607,7 +5740,7 @@ function createValidateCommand() {
|
|
|
5607
5740
|
|
|
5608
5741
|
// src/commands/linter/index.ts
|
|
5609
5742
|
function createLinterCommand() {
|
|
5610
|
-
const linter = new
|
|
5743
|
+
const linter = new Command48("linter").description(
|
|
5611
5744
|
"Generate and validate ESLint rules from YAML config"
|
|
5612
5745
|
);
|
|
5613
5746
|
linter.addCommand(createGenerateCommand2());
|
|
@@ -5616,7 +5749,7 @@ function createLinterCommand() {
|
|
|
5616
5749
|
}
|
|
5617
5750
|
|
|
5618
5751
|
// src/commands/mcp.ts
|
|
5619
|
-
import { Command as
|
|
5752
|
+
import { Command as Command49 } from "commander";
|
|
5620
5753
|
var VALID_TIERS = /* @__PURE__ */ new Set(["core", "standard", "full"]);
|
|
5621
5754
|
function parseTier(value) {
|
|
5622
5755
|
const lower = value.toLowerCase();
|
|
@@ -5633,7 +5766,7 @@ function parseBudget(value) {
|
|
|
5633
5766
|
return n;
|
|
5634
5767
|
}
|
|
5635
5768
|
function createMcpCommand() {
|
|
5636
|
-
return new
|
|
5769
|
+
return new Command49("mcp").description("Start the MCP (Model Context Protocol) server on stdio").option("--tools <tools...>", "Only register the specified tools (used by Cursor integration)").option(
|
|
5637
5770
|
"--tier <core|standard|full>",
|
|
5638
5771
|
"Load a preset tool tier instead of all tools",
|
|
5639
5772
|
parseTier
|
|
@@ -5643,7 +5776,7 @@ function createMcpCommand() {
|
|
|
5643
5776
|
parseBudget
|
|
5644
5777
|
).action(async (opts) => {
|
|
5645
5778
|
const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
|
|
5646
|
-
import("./mcp-
|
|
5779
|
+
import("./mcp-FA2CKHFY.js"),
|
|
5647
5780
|
import("./tool-tiers-7QGZ3FKY.js")
|
|
5648
5781
|
]);
|
|
5649
5782
|
if (opts.tools && opts.tools.length > 0) {
|
|
@@ -5665,7 +5798,7 @@ function createMcpCommand() {
|
|
|
5665
5798
|
|
|
5666
5799
|
// src/commands/migrate.ts
|
|
5667
5800
|
init_dist();
|
|
5668
|
-
import { Command as
|
|
5801
|
+
import { Command as Command50 } from "commander";
|
|
5669
5802
|
import * as fs24 from "fs";
|
|
5670
5803
|
import * as path40 from "path";
|
|
5671
5804
|
import * as readline from "readline";
|
|
@@ -5906,7 +6039,7 @@ function updateReferences(plan) {
|
|
|
5906
6039
|
}
|
|
5907
6040
|
async function prompt(question, def = "n") {
|
|
5908
6041
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
5909
|
-
const answer = await new Promise((
|
|
6042
|
+
const answer = await new Promise((resolve39) => rl.question(question, resolve39));
|
|
5910
6043
|
rl.close();
|
|
5911
6044
|
return (answer.trim() || def).toLowerCase();
|
|
5912
6045
|
}
|
|
@@ -6067,7 +6200,7 @@ async function runMigrate(opts) {
|
|
|
6067
6200
|
});
|
|
6068
6201
|
}
|
|
6069
6202
|
function createMigrateCommand() {
|
|
6070
|
-
return new
|
|
6203
|
+
return new Command50("migrate").description("Migrate legacy harness artifact locations to current layout").option("--dry-run", "Show the migration plan without moving files", false).option("--yes", "Skip confirmation prompt", false).option(
|
|
6071
6204
|
"--skip-references",
|
|
6072
6205
|
"Do not update path references in docs/sessions after moves",
|
|
6073
6206
|
false
|
|
@@ -6089,11 +6222,11 @@ function createMigrateCommand() {
|
|
|
6089
6222
|
}
|
|
6090
6223
|
|
|
6091
6224
|
// src/commands/orchestrator.ts
|
|
6092
|
-
import { Command as
|
|
6225
|
+
import { Command as Command51 } from "commander";
|
|
6093
6226
|
import * as path41 from "path";
|
|
6094
6227
|
import { Orchestrator, WorkflowLoader, launchTUI } from "@harness-engineering/orchestrator";
|
|
6095
6228
|
function createOrchestratorCommand() {
|
|
6096
|
-
const orchestrator = new
|
|
6229
|
+
const orchestrator = new Command51("orchestrator");
|
|
6097
6230
|
orchestrator.command("run").description("Run the orchestrator daemon").option("-w, --workflow <path>", "Path to harness.orchestrator.md", "harness.orchestrator.md").option("--headless", "Run without TUI (server-only mode for use with web dashboard)").action(async (opts) => {
|
|
6098
6231
|
const workflowPath = path41.resolve(process.cwd(), opts.workflow);
|
|
6099
6232
|
const loader = new WorkflowLoader();
|
|
@@ -6128,13 +6261,13 @@ function createOrchestratorCommand() {
|
|
|
6128
6261
|
|
|
6129
6262
|
// src/commands/perf.ts
|
|
6130
6263
|
init_dist();
|
|
6131
|
-
import { Command as
|
|
6264
|
+
import { Command as Command52 } from "commander";
|
|
6132
6265
|
import * as path42 from "path";
|
|
6133
6266
|
function registerBenchCommand(perf) {
|
|
6134
6267
|
perf.command("bench [glob]").description("Run benchmarks via vitest bench").action(async (glob2, _opts, cmd) => {
|
|
6135
6268
|
const globalOpts = cmd.optsWithGlobals();
|
|
6136
6269
|
const cwd = process.cwd();
|
|
6137
|
-
const { BenchmarkRunner } = await import("./dist-
|
|
6270
|
+
const { BenchmarkRunner } = await import("./dist-K22DQUYY.js");
|
|
6138
6271
|
const runner = new BenchmarkRunner();
|
|
6139
6272
|
const benchFiles = runner.discover(cwd, glob2);
|
|
6140
6273
|
if (benchFiles.length === 0) {
|
|
@@ -6198,7 +6331,7 @@ async function runBaselinesShow(globalOpts) {
|
|
|
6198
6331
|
}
|
|
6199
6332
|
async function runBaselinesUpdate(globalOpts) {
|
|
6200
6333
|
const cwd = process.cwd();
|
|
6201
|
-
const { BenchmarkRunner } = await import("./dist-
|
|
6334
|
+
const { BenchmarkRunner } = await import("./dist-K22DQUYY.js");
|
|
6202
6335
|
const runner = new BenchmarkRunner();
|
|
6203
6336
|
const manager = new BaselineManager(cwd);
|
|
6204
6337
|
logger.info("Running benchmarks to update baselines...");
|
|
@@ -6239,7 +6372,7 @@ function registerReportCommand(perf) {
|
|
|
6239
6372
|
perf.command("report").description("Full performance report with metrics, trends, and hotspots").action(async (_opts, cmd) => {
|
|
6240
6373
|
const globalOpts = cmd.optsWithGlobals();
|
|
6241
6374
|
const cwd = process.cwd();
|
|
6242
|
-
const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-
|
|
6375
|
+
const { EntropyAnalyzer: EntropyAnalyzer2 } = await import("./dist-K22DQUYY.js");
|
|
6243
6376
|
const analyzer = new EntropyAnalyzer2({
|
|
6244
6377
|
rootDir: path42.resolve(cwd),
|
|
6245
6378
|
analyze: { complexity: true, coupling: true }
|
|
@@ -6300,7 +6433,7 @@ function registerCriticalPathsCommand(perf) {
|
|
|
6300
6433
|
});
|
|
6301
6434
|
}
|
|
6302
6435
|
function createPerfCommand() {
|
|
6303
|
-
const perf = new
|
|
6436
|
+
const perf = new Command52("perf").description("Performance benchmark and baseline management");
|
|
6304
6437
|
registerBenchCommand(perf);
|
|
6305
6438
|
registerBaselinesCommands(perf);
|
|
6306
6439
|
registerReportCommand(perf);
|
|
@@ -6309,10 +6442,10 @@ function createPerfCommand() {
|
|
|
6309
6442
|
}
|
|
6310
6443
|
|
|
6311
6444
|
// src/commands/persona/index.ts
|
|
6312
|
-
import { Command as
|
|
6445
|
+
import { Command as Command55 } from "commander";
|
|
6313
6446
|
|
|
6314
6447
|
// src/commands/persona/list.ts
|
|
6315
|
-
import { Command as
|
|
6448
|
+
import { Command as Command53 } from "commander";
|
|
6316
6449
|
function printPersonaList(personas) {
|
|
6317
6450
|
if (personas.length === 0) {
|
|
6318
6451
|
logger.info("No personas found.");
|
|
@@ -6326,7 +6459,7 @@ function printPersonaList(personas) {
|
|
|
6326
6459
|
}
|
|
6327
6460
|
}
|
|
6328
6461
|
function createListCommand2() {
|
|
6329
|
-
return new
|
|
6462
|
+
return new Command53("list").description("List available agent personas").action(async (_opts, cmd) => {
|
|
6330
6463
|
const globalOpts = cmd.optsWithGlobals();
|
|
6331
6464
|
const personasDir = resolvePersonasDir();
|
|
6332
6465
|
const result = listPersonas(personasDir);
|
|
@@ -6346,7 +6479,7 @@ function createListCommand2() {
|
|
|
6346
6479
|
}
|
|
6347
6480
|
|
|
6348
6481
|
// src/commands/persona/generate.ts
|
|
6349
|
-
import { Command as
|
|
6482
|
+
import { Command as Command54 } from "commander";
|
|
6350
6483
|
import * as fs25 from "fs";
|
|
6351
6484
|
import * as path43 from "path";
|
|
6352
6485
|
function generatePersonaArtifacts(persona, outputDir, only) {
|
|
@@ -6381,7 +6514,7 @@ function generatePersonaArtifacts(persona, outputDir, only) {
|
|
|
6381
6514
|
return generated;
|
|
6382
6515
|
}
|
|
6383
6516
|
function createGenerateCommand3() {
|
|
6384
|
-
return new
|
|
6517
|
+
return new Command54("generate").description("Generate artifacts from a persona config").argument("<name>", "Persona name (e.g., architecture-enforcer)").option("--output-dir <dir>", "Output directory", ".").option("--only <type>", "Generate only: ci, agents-md, runtime").action(async (name, opts, cmd) => {
|
|
6385
6518
|
const globalOpts = cmd.optsWithGlobals();
|
|
6386
6519
|
const personaResult = loadPersona(path43.join(resolvePersonasDir(), `${name}.yaml`));
|
|
6387
6520
|
if (!personaResult.ok) {
|
|
@@ -6403,7 +6536,7 @@ function createGenerateCommand3() {
|
|
|
6403
6536
|
|
|
6404
6537
|
// src/commands/persona/index.ts
|
|
6405
6538
|
function createPersonaCommand() {
|
|
6406
|
-
const command = new
|
|
6539
|
+
const command = new Command55("persona").description("Agent persona management commands");
|
|
6407
6540
|
command.addCommand(createListCommand2());
|
|
6408
6541
|
command.addCommand(createGenerateCommand3());
|
|
6409
6542
|
return command;
|
|
@@ -6411,7 +6544,7 @@ function createPersonaCommand() {
|
|
|
6411
6544
|
|
|
6412
6545
|
// src/commands/predict.ts
|
|
6413
6546
|
init_dist();
|
|
6414
|
-
import { Command as
|
|
6547
|
+
import { Command as Command56 } from "commander";
|
|
6415
6548
|
import chalk8 from "chalk";
|
|
6416
6549
|
var CATEGORY_ORDER = [
|
|
6417
6550
|
"circular-deps",
|
|
@@ -6517,7 +6650,7 @@ function handlePredictError(err, mode) {
|
|
|
6517
6650
|
process.exit(ExitCode.ERROR);
|
|
6518
6651
|
}
|
|
6519
6652
|
function createPredictCommand() {
|
|
6520
|
-
const command = new
|
|
6653
|
+
const command = new Command56("predict").description("Predict which architectural constraints will break and when").option("--category <name>", "Filter to a single metric category").option("--no-roadmap", "Baseline only \u2014 skip roadmap spec impact").option("--horizon <weeks>", "Forecast horizon in weeks (default: 12)", "12").action(async (opts, cmd) => {
|
|
6521
6654
|
const globalOpts = cmd.optsWithGlobals();
|
|
6522
6655
|
const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
|
|
6523
6656
|
try {
|
|
@@ -6542,7 +6675,7 @@ function createPredictCommand() {
|
|
|
6542
6675
|
// src/commands/publish-analyses.ts
|
|
6543
6676
|
import * as fs26 from "fs";
|
|
6544
6677
|
import * as path44 from "path";
|
|
6545
|
-
import { Command as
|
|
6678
|
+
import { Command as Command57 } from "commander";
|
|
6546
6679
|
init_dist();
|
|
6547
6680
|
import {
|
|
6548
6681
|
renderAnalysisComment,
|
|
@@ -6630,7 +6763,7 @@ async function runPublishAnalyses(opts) {
|
|
|
6630
6763
|
const nameToExternalId = buildNameToExternalIdMap(projectPath);
|
|
6631
6764
|
if (!nameToExternalId) return process.exit(1);
|
|
6632
6765
|
const { AnalysisArchive } = await import("@harness-engineering/orchestrator");
|
|
6633
|
-
const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-
|
|
6766
|
+
const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-K22DQUYY.js");
|
|
6634
6767
|
const archive = new AnalysisArchive(path44.join(projectPath, ".harness", "analyses"));
|
|
6635
6768
|
const analyses = await archive.list();
|
|
6636
6769
|
if (analyses.length === 0) {
|
|
@@ -6653,7 +6786,7 @@ async function runPublishAnalyses(opts) {
|
|
|
6653
6786
|
}
|
|
6654
6787
|
}
|
|
6655
6788
|
function createPublishAnalysesCommand() {
|
|
6656
|
-
const command = new
|
|
6789
|
+
const command = new Command57("publish-analyses").description(
|
|
6657
6790
|
"Publishes locally generated intelligence analyses to the external issue tracker (e.g., GitHub)"
|
|
6658
6791
|
).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
|
|
6659
6792
|
try {
|
|
@@ -6668,8 +6801,109 @@ function createPublishAnalysesCommand() {
|
|
|
6668
6801
|
return command;
|
|
6669
6802
|
}
|
|
6670
6803
|
|
|
6804
|
+
// src/commands/pulse/index.ts
|
|
6805
|
+
import { Command as Command59 } from "commander";
|
|
6806
|
+
|
|
6807
|
+
// src/commands/pulse/run.ts
|
|
6808
|
+
init_dist();
|
|
6809
|
+
import { readFileSync as readFileSync15, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14 } from "fs";
|
|
6810
|
+
import { dirname as dirname17, join as join33, resolve as resolve28 } from "path";
|
|
6811
|
+
import { Command as Command58 } from "commander";
|
|
6812
|
+
async function runPulseRunCommand(opts) {
|
|
6813
|
+
const startedAt = Date.now();
|
|
6814
|
+
let raw;
|
|
6815
|
+
try {
|
|
6816
|
+
raw = JSON.parse(readFileSync15(opts.configPath, "utf-8"));
|
|
6817
|
+
} catch (err) {
|
|
6818
|
+
return emit2(
|
|
6819
|
+
{
|
|
6820
|
+
status: "failure",
|
|
6821
|
+
reason: `cannot read ${opts.configPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
6822
|
+
},
|
|
6823
|
+
opts.nonInteractive
|
|
6824
|
+
);
|
|
6825
|
+
}
|
|
6826
|
+
if (!raw.pulse?.enabled) {
|
|
6827
|
+
return emit2(
|
|
6828
|
+
{ status: "skipped", reason: "pulse.enabled is false or missing" },
|
|
6829
|
+
opts.nonInteractive
|
|
6830
|
+
);
|
|
6831
|
+
}
|
|
6832
|
+
const lookback = opts.lookback ?? raw.pulse.lookbackDefault ?? "24h";
|
|
6833
|
+
const window = computeWindow(/* @__PURE__ */ new Date(), lookback);
|
|
6834
|
+
const result = await runPulse(raw.pulse, window);
|
|
6835
|
+
if (result.sourcesQueried.length === 0 && result.sourcesSkipped.length === 0) {
|
|
6836
|
+
return emit2({ status: "skipped", reason: "no sources configured" }, opts.nonInteractive);
|
|
6837
|
+
}
|
|
6838
|
+
const productName = typeof raw.name === "string" ? raw.name : "Project";
|
|
6839
|
+
const report = assembleReport(result, productName, lookback);
|
|
6840
|
+
const now = /* @__PURE__ */ new Date();
|
|
6841
|
+
const ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}_${String(now.getHours()).padStart(2, "0")}-${String(now.getMinutes()).padStart(2, "0")}`;
|
|
6842
|
+
const filePath = join33(opts.outputDir, `${ts}.md`);
|
|
6843
|
+
mkdirSync13(dirname17(filePath), { recursive: true });
|
|
6844
|
+
writeFileSync14(filePath, report);
|
|
6845
|
+
const headlines = extractHeadlines(report);
|
|
6846
|
+
return emit2(
|
|
6847
|
+
{
|
|
6848
|
+
status: "success",
|
|
6849
|
+
path: filePath,
|
|
6850
|
+
headlinesSummary: headlines,
|
|
6851
|
+
durationMs: Date.now() - startedAt,
|
|
6852
|
+
sourcesQueried: result.sourcesQueried,
|
|
6853
|
+
sourcesSkipped: result.sourcesSkipped
|
|
6854
|
+
},
|
|
6855
|
+
opts.nonInteractive
|
|
6856
|
+
);
|
|
6857
|
+
}
|
|
6858
|
+
function emit2(status, nonInteractive) {
|
|
6859
|
+
if (nonInteractive) {
|
|
6860
|
+
process.stdout.write(JSON.stringify(status) + "\n");
|
|
6861
|
+
} else if (status.status === "success") {
|
|
6862
|
+
process.stdout.write(`${status.headlinesSummary ?? ""}
|
|
6863
|
+
|
|
6864
|
+
\u2192 ${status.path}
|
|
6865
|
+
`);
|
|
6866
|
+
} else if (status.status === "skipped") {
|
|
6867
|
+
process.stdout.write(`pulse skipped: ${status.reason}
|
|
6868
|
+
`);
|
|
6869
|
+
} else {
|
|
6870
|
+
process.stderr.write(`pulse failed: ${status.reason}
|
|
6871
|
+
`);
|
|
6872
|
+
}
|
|
6873
|
+
return status;
|
|
6874
|
+
}
|
|
6875
|
+
function createRunCommand2() {
|
|
6876
|
+
return new Command58("run").description("Run a pulse: query configured adapters, sanitize, assemble single-page report").option(
|
|
6877
|
+
"--lookback <window>",
|
|
6878
|
+
"Lookback window (e.g. 24h, 7d). Defaults to pulse.lookbackDefault."
|
|
6879
|
+
).option(
|
|
6880
|
+
"--non-interactive",
|
|
6881
|
+
"Emit single-line JSON status on stdout instead of headlines+path. Auto-detected when stdout is not a TTY."
|
|
6882
|
+
).option("--config <path>", "Path to harness.config.json", "harness.config.json").option("--output-dir <dir>", "Directory to write the report into", "docs/pulse-reports").action(
|
|
6883
|
+
async (options) => {
|
|
6884
|
+
const nonInteractive = options.nonInteractive === true || !process.stdout.isTTY;
|
|
6885
|
+
const status = await runPulseRunCommand({
|
|
6886
|
+
configPath: resolve28(process.cwd(), options.config),
|
|
6887
|
+
outputDir: resolve28(process.cwd(), options.outputDir),
|
|
6888
|
+
nonInteractive,
|
|
6889
|
+
lookback: options.lookback
|
|
6890
|
+
});
|
|
6891
|
+
if (status.status === "failure") {
|
|
6892
|
+
process.exitCode = 1;
|
|
6893
|
+
}
|
|
6894
|
+
}
|
|
6895
|
+
);
|
|
6896
|
+
}
|
|
6897
|
+
|
|
6898
|
+
// src/commands/pulse/index.ts
|
|
6899
|
+
function createPulseCommand() {
|
|
6900
|
+
const command = new Command59("pulse").description("Pulse (read-side observability) commands");
|
|
6901
|
+
command.addCommand(createRunCommand2());
|
|
6902
|
+
return command;
|
|
6903
|
+
}
|
|
6904
|
+
|
|
6671
6905
|
// src/commands/recommend.ts
|
|
6672
|
-
import { Command as
|
|
6906
|
+
import { Command as Command60 } from "commander";
|
|
6673
6907
|
import chalk9 from "chalk";
|
|
6674
6908
|
async function resolveSnapshot(cwd, noCache) {
|
|
6675
6909
|
if (!noCache) {
|
|
@@ -6733,7 +6967,7 @@ function printRecommendations(result) {
|
|
|
6733
6967
|
console.log("");
|
|
6734
6968
|
}
|
|
6735
6969
|
function createRecommendCommand() {
|
|
6736
|
-
const command = new
|
|
6970
|
+
const command = new Command60("recommend").description("Recommend skills based on codebase health analysis").option("--no-cache", "Force fresh health snapshot").option("--top <n>", "Max recommendations (default 5)", "5").action(async (opts, cmd) => {
|
|
6737
6971
|
const globalOpts = cmd.optsWithGlobals();
|
|
6738
6972
|
const mode = globalOpts.json ? OutputMode.JSON : OutputMode.TEXT;
|
|
6739
6973
|
try {
|
|
@@ -6770,9 +7004,9 @@ function createRecommendCommand() {
|
|
|
6770
7004
|
|
|
6771
7005
|
// src/commands/scan-config.ts
|
|
6772
7006
|
init_dist();
|
|
6773
|
-
import { Command as
|
|
6774
|
-
import { existsSync as existsSync23, readFileSync as
|
|
6775
|
-
import { join as
|
|
7007
|
+
import { Command as Command61 } from "commander";
|
|
7008
|
+
import { existsSync as existsSync23, readFileSync as readFileSync16, writeFileSync as writeFileSync15 } from "fs";
|
|
7009
|
+
import { join as join34, relative as relative3 } from "path";
|
|
6776
7010
|
var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".gemini/settings.json", "skill.yaml"];
|
|
6777
7011
|
function stripHighSeverityPatterns(content, injectionFindings) {
|
|
6778
7012
|
const highLines = /* @__PURE__ */ new Set();
|
|
@@ -6798,7 +7032,7 @@ function applyFix(filePath, targetDir, content, injectionFindings) {
|
|
|
6798
7032
|
if (!hasHighSeverity) return;
|
|
6799
7033
|
const { cleaned, linesStripped } = stripHighSeverityPatterns(content, injectionFindings);
|
|
6800
7034
|
if (linesStripped > 0) {
|
|
6801
|
-
|
|
7035
|
+
writeFileSync15(filePath, cleaned);
|
|
6802
7036
|
logger.info(
|
|
6803
7037
|
`scan-config --fix: stripped ${linesStripped} high-severity line(s) from ${relative3(targetDir, filePath).replaceAll("\\", "/")}`
|
|
6804
7038
|
);
|
|
@@ -6808,7 +7042,7 @@ function scanSingleFile(filePath, targetDir, scanner, options) {
|
|
|
6808
7042
|
if (!existsSync23(filePath)) return null;
|
|
6809
7043
|
let content;
|
|
6810
7044
|
try {
|
|
6811
|
-
content =
|
|
7045
|
+
content = readFileSync16(filePath, "utf8");
|
|
6812
7046
|
} catch {
|
|
6813
7047
|
return null;
|
|
6814
7048
|
}
|
|
@@ -6829,7 +7063,7 @@ async function runScanConfig(targetDir, options) {
|
|
|
6829
7063
|
const scanner = new SecurityScanner(parseSecurityConfig({}));
|
|
6830
7064
|
const results = [];
|
|
6831
7065
|
for (const configFile of CONFIG_FILES) {
|
|
6832
|
-
const result = scanSingleFile(
|
|
7066
|
+
const result = scanSingleFile(join34(targetDir, configFile), targetDir, scanner, options);
|
|
6833
7067
|
if (result) results.push(result);
|
|
6834
7068
|
}
|
|
6835
7069
|
return { exitCode: computeScanExitCode(results), results };
|
|
@@ -6859,7 +7093,7 @@ function formatTextOutput(result) {
|
|
|
6859
7093
|
}
|
|
6860
7094
|
}
|
|
6861
7095
|
function createScanConfigCommand() {
|
|
6862
|
-
const command = new
|
|
7096
|
+
const command = new Command61("scan-config").description(
|
|
6863
7097
|
"Scan CLAUDE.md, AGENTS.md, .gemini/settings.json, and skill.yaml for prompt injection patterns"
|
|
6864
7098
|
).option("--path <dir>", "Target directory to scan (default: cwd)").option("--fix", "Strip high-severity patterns from files in-place").action(async (opts, cmd) => {
|
|
6865
7099
|
const globalOpts = cmd.optsWithGlobals();
|
|
@@ -6876,7 +7110,7 @@ function createScanConfigCommand() {
|
|
|
6876
7110
|
}
|
|
6877
7111
|
|
|
6878
7112
|
// src/commands/setup.ts
|
|
6879
|
-
import { Command as
|
|
7113
|
+
import { Command as Command62 } from "commander";
|
|
6880
7114
|
import * as fs29 from "fs";
|
|
6881
7115
|
import * as os7 from "os";
|
|
6882
7116
|
import * as path47 from "path";
|
|
@@ -6915,10 +7149,10 @@ function prompt2(question) {
|
|
|
6915
7149
|
input: process.stdin,
|
|
6916
7150
|
output: process.stdout
|
|
6917
7151
|
});
|
|
6918
|
-
return new Promise((
|
|
7152
|
+
return new Promise((resolve39) => {
|
|
6919
7153
|
rl.question(question, (answer) => {
|
|
6920
7154
|
rl.close();
|
|
6921
|
-
|
|
7155
|
+
resolve39(answer.trim().toLowerCase());
|
|
6922
7156
|
});
|
|
6923
7157
|
});
|
|
6924
7158
|
}
|
|
@@ -6927,10 +7161,10 @@ function promptRaw(question) {
|
|
|
6927
7161
|
input: process.stdin,
|
|
6928
7162
|
output: process.stdout
|
|
6929
7163
|
});
|
|
6930
|
-
return new Promise((
|
|
7164
|
+
return new Promise((resolve39) => {
|
|
6931
7165
|
rl.question(question, (answer) => {
|
|
6932
7166
|
rl.close();
|
|
6933
|
-
|
|
7167
|
+
resolve39(answer.trim());
|
|
6934
7168
|
});
|
|
6935
7169
|
});
|
|
6936
7170
|
}
|
|
@@ -7169,7 +7403,7 @@ async function detectLegacyLayout(cwd) {
|
|
|
7169
7403
|
}
|
|
7170
7404
|
async function runInitialGraphScan(cwd) {
|
|
7171
7405
|
try {
|
|
7172
|
-
const { runScan: runScan2 } = await import("./scan-
|
|
7406
|
+
const { runScan: runScan2 } = await import("./scan-BIJYHOE7.js");
|
|
7173
7407
|
const result = await runScan2(cwd);
|
|
7174
7408
|
return {
|
|
7175
7409
|
status: "pass",
|
|
@@ -7208,7 +7442,7 @@ async function runSetup(cwd) {
|
|
|
7208
7442
|
return { steps, success };
|
|
7209
7443
|
}
|
|
7210
7444
|
function createSetupCommand() {
|
|
7211
|
-
return new
|
|
7445
|
+
return new Command62("setup").description("Configure harness environment: slash commands, MCP, and more").action(async () => {
|
|
7212
7446
|
const cwd = process.cwd();
|
|
7213
7447
|
console.log("");
|
|
7214
7448
|
console.log(` ${chalk11.bold("harness setup")}`);
|
|
@@ -7231,7 +7465,7 @@ function createSetupCommand() {
|
|
|
7231
7465
|
|
|
7232
7466
|
// src/commands/share.ts
|
|
7233
7467
|
init_dist();
|
|
7234
|
-
import { Command as
|
|
7468
|
+
import { Command as Command63 } from "commander";
|
|
7235
7469
|
import * as fs30 from "fs";
|
|
7236
7470
|
import * as path48 from "path";
|
|
7237
7471
|
import { parse as parseYaml } from "yaml";
|
|
@@ -7290,16 +7524,16 @@ Create a constraints.yaml in your project root to define what to share.`
|
|
|
7290
7524
|
logger.success(`Bundle written to ${outputPath}`);
|
|
7291
7525
|
}
|
|
7292
7526
|
function createShareCommand() {
|
|
7293
|
-
return new
|
|
7527
|
+
return new Command63("share").description("Extract and publish a constraints bundle from constraints.yaml").argument("[path]", "Path to the project root", ".").option("-o, --output <dir>", "Output directory for the bundle", ".").action(async (projectPath, options) => {
|
|
7294
7528
|
await runShareAction(projectPath, options);
|
|
7295
7529
|
});
|
|
7296
7530
|
}
|
|
7297
7531
|
|
|
7298
7532
|
// src/commands/skill/index.ts
|
|
7299
|
-
import { Command as
|
|
7533
|
+
import { Command as Command71 } from "commander";
|
|
7300
7534
|
|
|
7301
7535
|
// src/commands/skill/list.ts
|
|
7302
|
-
import { Command as
|
|
7536
|
+
import { Command as Command64 } from "commander";
|
|
7303
7537
|
import * as fs31 from "fs";
|
|
7304
7538
|
import * as path49 from "path";
|
|
7305
7539
|
import { parse } from "yaml";
|
|
@@ -7402,7 +7636,7 @@ function printSkillsVerbose(skills) {
|
|
|
7402
7636
|
for (const s of skills) printSkillEntry(s);
|
|
7403
7637
|
}
|
|
7404
7638
|
function createListCommand3() {
|
|
7405
|
-
return new
|
|
7639
|
+
return new Command64("list").description("List available skills").option("--installed", "Show only community-installed skills").option("--local", "Show only project-local skills").option("--all", "Show all skills (default)").action(async (opts, cmd) => {
|
|
7406
7640
|
const globalOpts = cmd.optsWithGlobals();
|
|
7407
7641
|
const skills = collectSkills({ filter: resolveFilter(opts) });
|
|
7408
7642
|
if (globalOpts.json) {
|
|
@@ -7417,7 +7651,7 @@ function createListCommand3() {
|
|
|
7417
7651
|
}
|
|
7418
7652
|
|
|
7419
7653
|
// src/commands/skill/run.ts
|
|
7420
|
-
import { Command as
|
|
7654
|
+
import { Command as Command65 } from "commander";
|
|
7421
7655
|
import * as fs32 from "fs";
|
|
7422
7656
|
import * as path50 from "path";
|
|
7423
7657
|
import { parse as parse2 } from "yaml";
|
|
@@ -7628,12 +7862,12 @@ async function runSkill(name, opts) {
|
|
|
7628
7862
|
process.stdout.write(preamble + content);
|
|
7629
7863
|
process.exit(ExitCode.SUCCESS);
|
|
7630
7864
|
}
|
|
7631
|
-
function
|
|
7632
|
-
return new
|
|
7865
|
+
function createRunCommand3() {
|
|
7866
|
+
return new Command65("run").description("Run a skill (outputs SKILL.md content with context preamble)").argument("<name>", "Skill name (e.g., harness-tdd)").option("--path <path>", "Project root path for context injection").option("--complexity <level>", "Rigor level: fast, standard, thorough", "standard").option("--phase <name>", "Start at a specific phase (for re-entry)").option("--party", "Enable multi-perspective evaluation").action(async (name, opts) => runSkill(name, opts));
|
|
7633
7867
|
}
|
|
7634
7868
|
|
|
7635
7869
|
// src/commands/skill/validate.ts
|
|
7636
|
-
import { Command as
|
|
7870
|
+
import { Command as Command66 } from "commander";
|
|
7637
7871
|
import * as fs33 from "fs";
|
|
7638
7872
|
import * as path51 from "path";
|
|
7639
7873
|
import { parse as parse3 } from "yaml";
|
|
@@ -7697,7 +7931,7 @@ function validateSkillEntry(name, skillsDir, errors) {
|
|
|
7697
7931
|
}
|
|
7698
7932
|
}
|
|
7699
7933
|
function createValidateCommand2() {
|
|
7700
|
-
return new
|
|
7934
|
+
return new Command66("validate").description("Validate all skill.yaml files and SKILL.md structure").action(async (_opts, cmd) => {
|
|
7701
7935
|
const globalOpts = cmd.optsWithGlobals();
|
|
7702
7936
|
const skillsDir = resolveSkillsDir();
|
|
7703
7937
|
if (!fs33.existsSync(skillsDir)) {
|
|
@@ -7727,7 +7961,7 @@ function createValidateCommand2() {
|
|
|
7727
7961
|
}
|
|
7728
7962
|
|
|
7729
7963
|
// src/commands/skill/info.ts
|
|
7730
|
-
import { Command as
|
|
7964
|
+
import { Command as Command67 } from "commander";
|
|
7731
7965
|
import * as fs34 from "fs";
|
|
7732
7966
|
import * as path52 from "path";
|
|
7733
7967
|
import { parse as parse4 } from "yaml";
|
|
@@ -7773,7 +8007,7 @@ function printSkillInfo(skill) {
|
|
|
7773
8007
|
console.log(`Persistent: ${skill.state.persistent}`);
|
|
7774
8008
|
}
|
|
7775
8009
|
function createInfoCommand() {
|
|
7776
|
-
return new
|
|
8010
|
+
return new Command67("info").description("Show metadata for a skill").argument("<name>", "Skill name (e.g., harness-tdd)").action(async (name, _opts, cmd) => {
|
|
7777
8011
|
const globalOpts = cmd.optsWithGlobals();
|
|
7778
8012
|
const loaded = loadSkillMetadata2(name);
|
|
7779
8013
|
if (!loaded.ok) {
|
|
@@ -7790,7 +8024,7 @@ function createInfoCommand() {
|
|
|
7790
8024
|
}
|
|
7791
8025
|
|
|
7792
8026
|
// src/commands/skill/search.ts
|
|
7793
|
-
import { Command as
|
|
8027
|
+
import { Command as Command68 } from "commander";
|
|
7794
8028
|
async function runSearch(query, opts) {
|
|
7795
8029
|
const results = await searchNpmRegistry(query, opts.registry);
|
|
7796
8030
|
return results.filter((r) => {
|
|
@@ -7835,13 +8069,13 @@ async function runSearchAction(query, opts, globalOpts) {
|
|
|
7835
8069
|
}
|
|
7836
8070
|
}
|
|
7837
8071
|
function createSearchCommand() {
|
|
7838
|
-
return new
|
|
8072
|
+
return new Command68("search").description("Search for community skills on the @harness-skills registry").argument("<query>", "Search query").option("--platform <platform>", "Filter by platform (e.g., claude-code)").option("--trigger <trigger>", "Filter by trigger type (e.g., manual, automatic)").option("--registry <url>", "Use a custom npm registry URL").action(async (query, opts, cmd) => {
|
|
7839
8073
|
await runSearchAction(query, opts, cmd.optsWithGlobals());
|
|
7840
8074
|
});
|
|
7841
8075
|
}
|
|
7842
8076
|
|
|
7843
8077
|
// src/commands/skill/create.ts
|
|
7844
|
-
import { Command as
|
|
8078
|
+
import { Command as Command69 } from "commander";
|
|
7845
8079
|
import * as path53 from "path";
|
|
7846
8080
|
import * as fs35 from "fs";
|
|
7847
8081
|
import YAML from "yaml";
|
|
@@ -7961,7 +8195,7 @@ Next steps:`);
|
|
|
7961
8195
|
logger.info(` 3. Run: harness skills publish`);
|
|
7962
8196
|
}
|
|
7963
8197
|
function createCreateCommand() {
|
|
7964
|
-
return new
|
|
8198
|
+
return new Command69("create").description("Scaffold a new community skill").argument("<name>", "Skill name (kebab-case)").option("--description <desc>", "Skill description").option("--type <type>", "Skill type: rigid or flexible", "flexible").option("--platforms <platforms>", "Comma-separated platforms (default: claude-code)").option("--triggers <triggers>", "Comma-separated triggers (default: manual)").option("--output-dir <dir>", "Output directory (default: agents/skills/claude-code/)").action(async (name, opts, cmd) => {
|
|
7965
8199
|
const globalOpts = cmd.optsWithGlobals();
|
|
7966
8200
|
try {
|
|
7967
8201
|
const result = runCreate(name, {
|
|
@@ -7984,7 +8218,7 @@ function createCreateCommand() {
|
|
|
7984
8218
|
}
|
|
7985
8219
|
|
|
7986
8220
|
// src/commands/skill/publish.ts
|
|
7987
|
-
import { Command as
|
|
8221
|
+
import { Command as Command70 } from "commander";
|
|
7988
8222
|
import * as fs37 from "fs";
|
|
7989
8223
|
import * as path55 from "path";
|
|
7990
8224
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
@@ -8153,7 +8387,7 @@ ${skillMdContent}`;
|
|
|
8153
8387
|
};
|
|
8154
8388
|
}
|
|
8155
8389
|
function createPublishCommand() {
|
|
8156
|
-
return new
|
|
8390
|
+
return new Command70("publish").description("Validate and publish a skill to @harness-skills on npm").option("--dry-run", "Run validation and generate package.json without publishing").option("--dir <dir>", "Skill directory (default: current directory)").option("--registry <url>", "Use a custom npm registry URL").action(async (opts, cmd) => {
|
|
8157
8391
|
const globalOpts = cmd.optsWithGlobals();
|
|
8158
8392
|
const skillDir = opts.dir || process.cwd();
|
|
8159
8393
|
try {
|
|
@@ -8178,9 +8412,9 @@ function createPublishCommand() {
|
|
|
8178
8412
|
|
|
8179
8413
|
// src/commands/skill/index.ts
|
|
8180
8414
|
function createSkillCommand() {
|
|
8181
|
-
const command = new
|
|
8415
|
+
const command = new Command71("skill").description("Skill management commands");
|
|
8182
8416
|
command.addCommand(createListCommand3());
|
|
8183
|
-
command.addCommand(
|
|
8417
|
+
command.addCommand(createRunCommand3());
|
|
8184
8418
|
command.addCommand(createValidateCommand2());
|
|
8185
8419
|
command.addCommand(createInfoCommand());
|
|
8186
8420
|
command.addCommand(createSearchCommand());
|
|
@@ -8191,7 +8425,7 @@ function createSkillCommand() {
|
|
|
8191
8425
|
|
|
8192
8426
|
// src/commands/snapshot.ts
|
|
8193
8427
|
init_dist();
|
|
8194
|
-
import { Command as
|
|
8428
|
+
import { Command as Command72 } from "commander";
|
|
8195
8429
|
import { execSync as execSync5 } from "child_process";
|
|
8196
8430
|
import chalk12 from "chalk";
|
|
8197
8431
|
function getCommitHash3(cwd) {
|
|
@@ -8373,7 +8607,7 @@ function registerListCommand(parent) {
|
|
|
8373
8607
|
});
|
|
8374
8608
|
}
|
|
8375
8609
|
function createSnapshotCommand() {
|
|
8376
|
-
const command = new
|
|
8610
|
+
const command = new Command72("snapshot").description("Architecture timeline snapshot commands");
|
|
8377
8611
|
registerCaptureCommand(command);
|
|
8378
8612
|
registerTrendsCommand(command);
|
|
8379
8613
|
registerListCommand(command);
|
|
@@ -8381,11 +8615,11 @@ function createSnapshotCommand() {
|
|
|
8381
8615
|
}
|
|
8382
8616
|
|
|
8383
8617
|
// src/commands/state/index.ts
|
|
8384
|
-
import { Command as
|
|
8618
|
+
import { Command as Command77 } from "commander";
|
|
8385
8619
|
|
|
8386
8620
|
// src/commands/state/show.ts
|
|
8387
8621
|
init_dist();
|
|
8388
|
-
import { Command as
|
|
8622
|
+
import { Command as Command73 } from "commander";
|
|
8389
8623
|
import * as path56 from "path";
|
|
8390
8624
|
function printStateText(state, stream) {
|
|
8391
8625
|
if (stream) console.log(`Stream: ${stream}`);
|
|
@@ -8410,7 +8644,7 @@ function printStateProgress(progress) {
|
|
|
8410
8644
|
}
|
|
8411
8645
|
}
|
|
8412
8646
|
function createShowCommand() {
|
|
8413
|
-
return new
|
|
8647
|
+
return new Command73("show").description("Show current project state").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (opts, cmd) => {
|
|
8414
8648
|
const globalOpts = cmd.optsWithGlobals();
|
|
8415
8649
|
const result = await loadState(path56.resolve(opts.path), opts.stream);
|
|
8416
8650
|
if (!result.ok) {
|
|
@@ -8428,7 +8662,7 @@ function createShowCommand() {
|
|
|
8428
8662
|
|
|
8429
8663
|
// src/commands/state/reset.ts
|
|
8430
8664
|
init_dist();
|
|
8431
|
-
import { Command as
|
|
8665
|
+
import { Command as Command74 } from "commander";
|
|
8432
8666
|
import * as fs38 from "fs";
|
|
8433
8667
|
import * as path57 from "path";
|
|
8434
8668
|
import * as readline3 from "readline";
|
|
@@ -8445,8 +8679,8 @@ async function resolveStatePath(projectPath, stream) {
|
|
|
8445
8679
|
}
|
|
8446
8680
|
async function confirmReset() {
|
|
8447
8681
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
8448
|
-
const answer = await new Promise((
|
|
8449
|
-
rl.question("Reset project state? This cannot be undone. [y/N] ",
|
|
8682
|
+
const answer = await new Promise((resolve39) => {
|
|
8683
|
+
rl.question("Reset project state? This cannot be undone. [y/N] ", resolve39);
|
|
8450
8684
|
});
|
|
8451
8685
|
rl.close();
|
|
8452
8686
|
return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
|
|
@@ -8472,15 +8706,15 @@ async function runReset(opts) {
|
|
|
8472
8706
|
process.exit(ExitCode.SUCCESS);
|
|
8473
8707
|
}
|
|
8474
8708
|
function createResetCommand() {
|
|
8475
|
-
return new
|
|
8709
|
+
return new Command74("reset").description("Reset project state (deletes .harness/state.json)").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").option("--yes", "Skip confirmation prompt").action(async (opts) => runReset(opts));
|
|
8476
8710
|
}
|
|
8477
8711
|
|
|
8478
8712
|
// src/commands/state/learn.ts
|
|
8479
8713
|
init_dist();
|
|
8480
|
-
import { Command as
|
|
8714
|
+
import { Command as Command75 } from "commander";
|
|
8481
8715
|
import * as path58 from "path";
|
|
8482
8716
|
function createLearnCommand() {
|
|
8483
|
-
return new
|
|
8717
|
+
return new Command75("learn").description("Append a learning to .harness/learnings.md").argument("<message>", "The learning to record").option("--path <path>", "Project root path", ".").option("--stream <name>", "Target a specific stream").action(async (message, opts, _cmd) => {
|
|
8484
8718
|
const projectPath = path58.resolve(opts.path);
|
|
8485
8719
|
const result = await appendLearning(projectPath, message, void 0, void 0, opts.stream);
|
|
8486
8720
|
if (!result.ok) {
|
|
@@ -8495,7 +8729,7 @@ function createLearnCommand() {
|
|
|
8495
8729
|
|
|
8496
8730
|
// src/commands/state/streams.ts
|
|
8497
8731
|
init_dist();
|
|
8498
|
-
import { Command as
|
|
8732
|
+
import { Command as Command76 } from "commander";
|
|
8499
8733
|
import * as path59 from "path";
|
|
8500
8734
|
async function runListStreams(opts, globalOpts) {
|
|
8501
8735
|
const projectPath = path59.resolve(opts.path);
|
|
@@ -8546,7 +8780,7 @@ async function runActivateStream(name, opts) {
|
|
|
8546
8780
|
process.exit(ExitCode.SUCCESS);
|
|
8547
8781
|
}
|
|
8548
8782
|
function createStreamsCommand() {
|
|
8549
|
-
const command = new
|
|
8783
|
+
const command = new Command76("streams").description("Manage state streams");
|
|
8550
8784
|
command.command("list").description("List all known streams").option("--path <path>", "Project root path", ".").action(async (opts, cmd) => runListStreams(opts, cmd.optsWithGlobals()));
|
|
8551
8785
|
command.command("create <name>").description("Create a new stream").option("--path <path>", "Project root path", ".").option("--branch <branch>", "Associate with a git branch").action(async (name, opts) => runCreateStream(name, opts));
|
|
8552
8786
|
command.command("archive <name>").description("Archive a stream").option("--path <path>", "Project root path", ".").action(async (name, opts) => runArchiveStream(name, opts));
|
|
@@ -8556,7 +8790,7 @@ function createStreamsCommand() {
|
|
|
8556
8790
|
|
|
8557
8791
|
// src/commands/state/index.ts
|
|
8558
8792
|
function createStateCommand() {
|
|
8559
|
-
const command = new
|
|
8793
|
+
const command = new Command77("state").description("Project state management commands");
|
|
8560
8794
|
command.addCommand(createShowCommand());
|
|
8561
8795
|
command.addCommand(createResetCommand());
|
|
8562
8796
|
command.addCommand(createLearnCommand());
|
|
@@ -8567,7 +8801,7 @@ function createStateCommand() {
|
|
|
8567
8801
|
// src/commands/sync-analyses.ts
|
|
8568
8802
|
import * as fs39 from "fs";
|
|
8569
8803
|
import * as path60 from "path";
|
|
8570
|
-
import { Command as
|
|
8804
|
+
import { Command as Command78 } from "commander";
|
|
8571
8805
|
init_dist();
|
|
8572
8806
|
function isValidRecord(record) {
|
|
8573
8807
|
return typeof record.issueId === "string" && !!record.issueId && typeof record.identifier === "string" && !!record.identifier && typeof record.analyzedAt === "string" && !/[/\\]/.test(record.issueId);
|
|
@@ -8674,7 +8908,7 @@ async function runSyncAnalyses(opts) {
|
|
|
8674
8908
|
return;
|
|
8675
8909
|
}
|
|
8676
8910
|
const { AnalysisArchive, loadPublishedIndex: loadPublishedIndex2, savePublishedIndex: savePublishedIndex2 } = await import("@harness-engineering/orchestrator");
|
|
8677
|
-
const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-
|
|
8911
|
+
const { GitHubIssuesSyncAdapter: GitHubIssuesSyncAdapter2 } = await import("./dist-K22DQUYY.js");
|
|
8678
8912
|
const adapter = new GitHubIssuesSyncAdapter2({ token, config: trackerConfig });
|
|
8679
8913
|
const archive = new AnalysisArchive(path60.join(projectPath, ".harness", "analyses"));
|
|
8680
8914
|
const publishedIndex = loadPublishedIndex2(projectPath);
|
|
@@ -8696,7 +8930,7 @@ async function runSyncAnalyses(opts) {
|
|
|
8696
8930
|
}
|
|
8697
8931
|
}
|
|
8698
8932
|
function createSyncAnalysesCommand() {
|
|
8699
|
-
const command = new
|
|
8933
|
+
const command = new Command78("sync-analyses").description(
|
|
8700
8934
|
"Pull published intelligence analyses from the external issue tracker into the local .harness/analyses/ directory"
|
|
8701
8935
|
).option("-d, --dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
|
|
8702
8936
|
try {
|
|
@@ -8711,7 +8945,7 @@ function createSyncAnalysesCommand() {
|
|
|
8711
8945
|
|
|
8712
8946
|
// src/commands/taint.ts
|
|
8713
8947
|
init_dist();
|
|
8714
|
-
import { Command as
|
|
8948
|
+
import { Command as Command79 } from "commander";
|
|
8715
8949
|
function getProjectRoot() {
|
|
8716
8950
|
return process.cwd();
|
|
8717
8951
|
}
|
|
@@ -8783,18 +9017,18 @@ function registerStatusCommand(taint) {
|
|
|
8783
9017
|
});
|
|
8784
9018
|
}
|
|
8785
9019
|
function createTaintCommand() {
|
|
8786
|
-
const taint = new
|
|
9020
|
+
const taint = new Command79("taint").description("Manage sentinel session taint state");
|
|
8787
9021
|
registerClearCommand(taint);
|
|
8788
9022
|
registerStatusCommand(taint);
|
|
8789
9023
|
return taint;
|
|
8790
9024
|
}
|
|
8791
9025
|
|
|
8792
9026
|
// src/commands/telemetry/index.ts
|
|
8793
|
-
import { Command as
|
|
9027
|
+
import { Command as Command83 } from "commander";
|
|
8794
9028
|
|
|
8795
9029
|
// src/commands/telemetry/identify.ts
|
|
8796
9030
|
init_dist();
|
|
8797
|
-
import { Command as
|
|
9031
|
+
import { Command as Command80 } from "commander";
|
|
8798
9032
|
import * as fs40 from "fs";
|
|
8799
9033
|
import * as path61 from "path";
|
|
8800
9034
|
function telemetryFilePath(cwd) {
|
|
@@ -8818,7 +9052,7 @@ function printIdentity(identity) {
|
|
|
8818
9052
|
}
|
|
8819
9053
|
}
|
|
8820
9054
|
function createIdentifyCommand() {
|
|
8821
|
-
const cmd = new
|
|
9055
|
+
const cmd = new Command80("identify").description("Set or clear telemetry identity fields in .harness/telemetry.json").option("--project <name>", "Project name").option("--team <name>", "Team name").option("--alias <name>", "User alias").option("--clear", "Remove all identity fields").action((opts) => {
|
|
8822
9056
|
const cwd = process.cwd();
|
|
8823
9057
|
if (opts.clear) {
|
|
8824
9058
|
writeTelemetryFile(cwd, { identity: {} });
|
|
@@ -8843,7 +9077,7 @@ function createIdentifyCommand() {
|
|
|
8843
9077
|
|
|
8844
9078
|
// src/commands/telemetry/status.ts
|
|
8845
9079
|
init_dist();
|
|
8846
|
-
import { Command as
|
|
9080
|
+
import { Command as Command81 } from "commander";
|
|
8847
9081
|
function gatherEnvOverrides() {
|
|
8848
9082
|
const overrides = {};
|
|
8849
9083
|
if (process.env.DO_NOT_TRACK) overrides.DO_NOT_TRACK = process.env.DO_NOT_TRACK;
|
|
@@ -8885,7 +9119,7 @@ function printHumanStatus(result) {
|
|
|
8885
9119
|
printEnvOverrides(result.envOverrides);
|
|
8886
9120
|
}
|
|
8887
9121
|
function createStatusCommand() {
|
|
8888
|
-
const cmd = new
|
|
9122
|
+
const cmd = new Command81("status").description("Show current telemetry consent state, install ID, and identity").option("--json", "Output as JSON").action((opts) => {
|
|
8889
9123
|
const cwd = process.cwd();
|
|
8890
9124
|
const envOverrides = gatherEnvOverrides();
|
|
8891
9125
|
const consent = resolveConsent(cwd, void 0);
|
|
@@ -8918,20 +9152,20 @@ function createStatusCommand() {
|
|
|
8918
9152
|
|
|
8919
9153
|
// src/commands/telemetry/test.ts
|
|
8920
9154
|
init_dist();
|
|
8921
|
-
import { Command as
|
|
9155
|
+
import { Command as Command82 } from "commander";
|
|
8922
9156
|
|
|
8923
9157
|
// src/bin/command-telemetry.ts
|
|
8924
|
-
import { existsSync as existsSync37, readFileSync as
|
|
8925
|
-
import { join as
|
|
9158
|
+
import { existsSync as existsSync37, readFileSync as readFileSync27, mkdirSync as mkdirSync18, appendFileSync, writeFileSync as writeFileSync21 } from "fs";
|
|
9159
|
+
import { join as join49, parse as parsePath, resolve as resolve36 } from "path";
|
|
8926
9160
|
import { spawn as spawn2 } from "child_process";
|
|
8927
9161
|
var POSTHOG_API_KEY = "phc_wNTdCMcfJXZPgdNeDociZW6vwoGGo4nb7vqEfWThFfsG";
|
|
8928
9162
|
var EXCLUDED_COMMANDS = /* @__PURE__ */ new Set(["help", "completion"]);
|
|
8929
9163
|
function findProjectRoot(cwd) {
|
|
8930
|
-
let dir =
|
|
9164
|
+
let dir = resolve36(cwd);
|
|
8931
9165
|
const { root } = parsePath(dir);
|
|
8932
9166
|
while (dir !== root) {
|
|
8933
|
-
if (existsSync37(
|
|
8934
|
-
dir =
|
|
9167
|
+
if (existsSync37(join49(dir, "harness.config.json"))) return dir;
|
|
9168
|
+
dir = resolve36(dir, "..");
|
|
8935
9169
|
}
|
|
8936
9170
|
return cwd;
|
|
8937
9171
|
}
|
|
@@ -8968,8 +9202,8 @@ function resolveCommandName(cmd) {
|
|
|
8968
9202
|
}
|
|
8969
9203
|
function writeCommandRecordSync(cwd, command, duration, outcome) {
|
|
8970
9204
|
try {
|
|
8971
|
-
const metricsDir =
|
|
8972
|
-
|
|
9205
|
+
const metricsDir = join49(cwd, ".harness", "metrics");
|
|
9206
|
+
mkdirSync18(metricsDir, { recursive: true });
|
|
8973
9207
|
const record = {
|
|
8974
9208
|
skill: command,
|
|
8975
9209
|
session: `cli-${Date.now()}`,
|
|
@@ -8978,16 +9212,16 @@ function writeCommandRecordSync(cwd, command, duration, outcome) {
|
|
|
8978
9212
|
outcome,
|
|
8979
9213
|
phasesReached: []
|
|
8980
9214
|
};
|
|
8981
|
-
const adoptionFile =
|
|
9215
|
+
const adoptionFile = join49(metricsDir, "adoption.jsonl");
|
|
8982
9216
|
appendFileSync(adoptionFile, JSON.stringify(record) + "\n");
|
|
8983
9217
|
} catch {
|
|
8984
9218
|
}
|
|
8985
9219
|
}
|
|
8986
9220
|
function isTelemetryDisabledByConfig(cwd) {
|
|
8987
|
-
const configPath =
|
|
9221
|
+
const configPath = join49(cwd, "harness.config.json");
|
|
8988
9222
|
if (!existsSync37(configPath)) return false;
|
|
8989
9223
|
try {
|
|
8990
|
-
const config = JSON.parse(
|
|
9224
|
+
const config = JSON.parse(readFileSync27(configPath, "utf-8"));
|
|
8991
9225
|
return config?.telemetry?.enabled === false;
|
|
8992
9226
|
} catch {
|
|
8993
9227
|
return false;
|
|
@@ -8999,10 +9233,10 @@ function isTelemetryOptedOut(cwd) {
|
|
|
8999
9233
|
}
|
|
9000
9234
|
function flushTelemetryBackground(cwd) {
|
|
9001
9235
|
try {
|
|
9002
|
-
const adoptionFile =
|
|
9236
|
+
const adoptionFile = join49(cwd, ".harness", "metrics", "adoption.jsonl");
|
|
9003
9237
|
if (!existsSync37(adoptionFile)) return;
|
|
9004
9238
|
if (isTelemetryOptedOut(cwd)) return;
|
|
9005
|
-
const reporterPath =
|
|
9239
|
+
const reporterPath = join49(cwd, ".harness", "hooks", "telemetry-reporter.js");
|
|
9006
9240
|
if (!existsSync37(reporterPath)) return;
|
|
9007
9241
|
const child = spawn2(process.execPath, [reporterPath], {
|
|
9008
9242
|
cwd,
|
|
@@ -9040,7 +9274,7 @@ function reportTestSuccess(status, distinctId, identity) {
|
|
|
9040
9274
|
if (identity.team) logger.info(` team: ${identity.team}`);
|
|
9041
9275
|
}
|
|
9042
9276
|
function createTestCommand() {
|
|
9043
|
-
return new
|
|
9277
|
+
return new Command82("test").description("Send a test event to PostHog and verify connectivity").action(async () => {
|
|
9044
9278
|
const cwd = process.cwd();
|
|
9045
9279
|
const consent = resolveConsent(cwd, void 0);
|
|
9046
9280
|
if (!consent.allowed) {
|
|
@@ -9077,7 +9311,7 @@ function createTestCommand() {
|
|
|
9077
9311
|
|
|
9078
9312
|
// src/commands/telemetry/index.ts
|
|
9079
9313
|
function createTelemetryCommand() {
|
|
9080
|
-
const command = new
|
|
9314
|
+
const command = new Command83("telemetry").description("Telemetry identity and status management");
|
|
9081
9315
|
command.addCommand(createIdentifyCommand());
|
|
9082
9316
|
command.addCommand(createStatusCommand());
|
|
9083
9317
|
command.addCommand(createTestCommand());
|
|
@@ -9085,7 +9319,7 @@ function createTelemetryCommand() {
|
|
|
9085
9319
|
}
|
|
9086
9320
|
|
|
9087
9321
|
// src/commands/traceability.ts
|
|
9088
|
-
import { Command as
|
|
9322
|
+
import { Command as Command84 } from "commander";
|
|
9089
9323
|
import chalk13 from "chalk";
|
|
9090
9324
|
function confidenceLabel(maxConfidence) {
|
|
9091
9325
|
if (maxConfidence >= 0.8) return "explicit";
|
|
@@ -9206,7 +9440,7 @@ async function runTraceability(options) {
|
|
|
9206
9440
|
const projectPath = process.cwd();
|
|
9207
9441
|
const store = await loadGraphStore(projectPath);
|
|
9208
9442
|
if (!store) handleNoStore(mode);
|
|
9209
|
-
const graphModule = await import("./dist-
|
|
9443
|
+
const graphModule = await import("./dist-D27LJR2T.js");
|
|
9210
9444
|
const filterOptions = buildFilterOptions(options);
|
|
9211
9445
|
const results = graphModule.queryTraceability(store, filterOptions);
|
|
9212
9446
|
if (results.length === 0) handleEmptyResults(mode);
|
|
@@ -9221,7 +9455,7 @@ async function runTraceability(options) {
|
|
|
9221
9455
|
process.exit(ExitCode.SUCCESS);
|
|
9222
9456
|
}
|
|
9223
9457
|
function createTraceabilityCommand() {
|
|
9224
|
-
return new
|
|
9458
|
+
return new Command84("traceability").description("Show spec-to-implementation traceability from the knowledge graph").option("--spec <path>", "Filter by spec file path").option("--feature <name>", "Filter by feature name").action(async (opts, cmd) => {
|
|
9225
9459
|
const globalOpts = cmd.optsWithGlobals();
|
|
9226
9460
|
await runTraceability({
|
|
9227
9461
|
spec: opts.spec,
|
|
@@ -9235,7 +9469,7 @@ function createTraceabilityCommand() {
|
|
|
9235
9469
|
|
|
9236
9470
|
// src/commands/uninstall.ts
|
|
9237
9471
|
import * as path62 from "path";
|
|
9238
|
-
import { Command as
|
|
9472
|
+
import { Command as Command85 } from "commander";
|
|
9239
9473
|
async function runUninstall(skillName, options) {
|
|
9240
9474
|
const packageName = resolvePackageName(skillName);
|
|
9241
9475
|
const shortName = extractSkillName(packageName);
|
|
@@ -9272,7 +9506,7 @@ async function runUninstall(skillName, options) {
|
|
|
9272
9506
|
return result;
|
|
9273
9507
|
}
|
|
9274
9508
|
function createUninstallCommand() {
|
|
9275
|
-
const cmd = new
|
|
9509
|
+
const cmd = new Command85("uninstall");
|
|
9276
9510
|
cmd.description("Uninstall a community skill").argument("<skill>", "Skill name or @harness-skills/scoped package name").option("--force", "Remove even if other skills depend on this one").action(async (skill, opts) => {
|
|
9277
9511
|
try {
|
|
9278
9512
|
const result = await runUninstall(skill, opts);
|
|
@@ -9294,7 +9528,7 @@ function createUninstallCommand() {
|
|
|
9294
9528
|
init_dist();
|
|
9295
9529
|
import * as fs41 from "fs/promises";
|
|
9296
9530
|
import * as path63 from "path";
|
|
9297
|
-
import { Command as
|
|
9531
|
+
import { Command as Command86 } from "commander";
|
|
9298
9532
|
async function runUninstallConstraints(options) {
|
|
9299
9533
|
const { packageName, configPath, lockfilePath } = options;
|
|
9300
9534
|
const lockfileResult = await readLockfile(lockfilePath);
|
|
@@ -9351,7 +9585,7 @@ async function runUninstallConstraints(options) {
|
|
|
9351
9585
|
};
|
|
9352
9586
|
}
|
|
9353
9587
|
function createUninstallConstraintsCommand() {
|
|
9354
|
-
const cmd = new
|
|
9588
|
+
const cmd = new Command86("uninstall-constraints");
|
|
9355
9589
|
cmd.description("Remove a previously installed constraints package").argument("<name>", "Name of the constraint package to uninstall").option("-c, --config <path>", "Path to harness.config.json").action(async (name, opts) => {
|
|
9356
9590
|
let configPath;
|
|
9357
9591
|
if (opts.config) {
|
|
@@ -9390,10 +9624,10 @@ function createUninstallConstraintsCommand() {
|
|
|
9390
9624
|
}
|
|
9391
9625
|
|
|
9392
9626
|
// src/commands/update.ts
|
|
9393
|
-
import { Command as
|
|
9627
|
+
import { Command as Command87 } from "commander";
|
|
9394
9628
|
import { execFile, execFileSync as execFileSync7 } from "child_process";
|
|
9395
|
-
import { realpathSync, existsSync as existsSync38, readFileSync as
|
|
9396
|
-
import { join as
|
|
9629
|
+
import { realpathSync, existsSync as existsSync38, readFileSync as readFileSync28 } from "fs";
|
|
9630
|
+
import { join as join52 } from "path";
|
|
9397
9631
|
import { promisify } from "util";
|
|
9398
9632
|
import readline4 from "readline";
|
|
9399
9633
|
import chalk14 from "chalk";
|
|
@@ -9459,10 +9693,10 @@ function prompt3(question) {
|
|
|
9459
9693
|
input: process.stdin,
|
|
9460
9694
|
output: process.stdout
|
|
9461
9695
|
});
|
|
9462
|
-
return new Promise((
|
|
9696
|
+
return new Promise((resolve39) => {
|
|
9463
9697
|
rl.question(question, (answer) => {
|
|
9464
9698
|
rl.close();
|
|
9465
|
-
|
|
9699
|
+
resolve39(answer.trim().toLowerCase());
|
|
9466
9700
|
});
|
|
9467
9701
|
});
|
|
9468
9702
|
}
|
|
@@ -9477,12 +9711,12 @@ async function ensureTelemetryIfNeeded() {
|
|
|
9477
9711
|
}
|
|
9478
9712
|
function refreshHooks() {
|
|
9479
9713
|
const cwd = process.cwd();
|
|
9480
|
-
const configPath =
|
|
9714
|
+
const configPath = join52(cwd, "harness.config.json");
|
|
9481
9715
|
if (!existsSync38(configPath)) return;
|
|
9482
9716
|
let profile = "standard";
|
|
9483
|
-
const profilePath =
|
|
9717
|
+
const profilePath = join52(cwd, ".harness", "hooks", "profile.json");
|
|
9484
9718
|
try {
|
|
9485
|
-
const data = JSON.parse(
|
|
9719
|
+
const data = JSON.parse(readFileSync28(profilePath, "utf-8"));
|
|
9486
9720
|
if (data.profile && ["minimal", "standard", "strict"].includes(data.profile)) {
|
|
9487
9721
|
profile = data.profile;
|
|
9488
9722
|
}
|
|
@@ -9608,7 +9842,7 @@ async function runUpdateAction(opts, globalOpts) {
|
|
|
9608
9842
|
process.exit(ExitCode.SUCCESS);
|
|
9609
9843
|
}
|
|
9610
9844
|
function createUpdateCommand() {
|
|
9611
|
-
return new
|
|
9845
|
+
return new Command87("update").description("Update all @harness-engineering packages to the latest version").option("--version <semver>", "Pin @harness-engineering/cli to a specific version").option("--force", "Force update even if versions match").option(
|
|
9612
9846
|
"--regenerate",
|
|
9613
9847
|
"Only regenerate slash commands and agent definitions (skip package updates)"
|
|
9614
9848
|
).action(async (opts, cmd) => {
|
|
@@ -9618,9 +9852,9 @@ function createUpdateCommand() {
|
|
|
9618
9852
|
}
|
|
9619
9853
|
|
|
9620
9854
|
// src/commands/usage.ts
|
|
9621
|
-
import { Command as
|
|
9855
|
+
import { Command as Command88 } from "commander";
|
|
9622
9856
|
async function loadAndPriceRecords(cwd, includeClaudeSessions = false) {
|
|
9623
|
-
const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-
|
|
9857
|
+
const { readCostRecords, loadPricingData, calculateCost, parseCCRecords } = await import("./dist-K22DQUYY.js");
|
|
9624
9858
|
const records = readCostRecords(cwd);
|
|
9625
9859
|
if (includeClaudeSessions) {
|
|
9626
9860
|
const ccRecords = parseCCRecords();
|
|
@@ -9713,7 +9947,7 @@ function registerDailyCommand(usage) {
|
|
|
9713
9947
|
else logger.info("No usage data found. Run some harness sessions first.");
|
|
9714
9948
|
return;
|
|
9715
9949
|
}
|
|
9716
|
-
const { aggregateByDay } = await import("./dist-
|
|
9950
|
+
const { aggregateByDay } = await import("./dist-K22DQUYY.js");
|
|
9717
9951
|
const limited = aggregateByDay(records).slice(0, days);
|
|
9718
9952
|
if (globalOpts.json) {
|
|
9719
9953
|
console.log(
|
|
@@ -9742,7 +9976,7 @@ function registerSessionsCommand(usage) {
|
|
|
9742
9976
|
}
|
|
9743
9977
|
return;
|
|
9744
9978
|
}
|
|
9745
|
-
const { aggregateBySession } = await import("./dist-
|
|
9979
|
+
const { aggregateBySession } = await import("./dist-K22DQUYY.js");
|
|
9746
9980
|
const sessionData = aggregateBySession(records);
|
|
9747
9981
|
const limited = sessionData.slice(0, limit);
|
|
9748
9982
|
if (globalOpts.json) {
|
|
@@ -9822,7 +10056,7 @@ function registerSessionCommand(usage) {
|
|
|
9822
10056
|
cwd,
|
|
9823
10057
|
globalOpts.includeClaudeSessions
|
|
9824
10058
|
);
|
|
9825
|
-
const { aggregateBySession } = await import("./dist-
|
|
10059
|
+
const { aggregateBySession } = await import("./dist-K22DQUYY.js");
|
|
9826
10060
|
const sessionData = aggregateBySession(records);
|
|
9827
10061
|
const match = sessionData.find((s) => s.sessionId === id);
|
|
9828
10062
|
if (!match) {
|
|
@@ -9857,7 +10091,7 @@ function registerLatestCommand(usage) {
|
|
|
9857
10091
|
}
|
|
9858
10092
|
return;
|
|
9859
10093
|
}
|
|
9860
|
-
const { aggregateBySession } = await import("./dist-
|
|
10094
|
+
const { aggregateBySession } = await import("./dist-K22DQUYY.js");
|
|
9861
10095
|
const sessionData = aggregateBySession(records);
|
|
9862
10096
|
const latest = sessionData[0];
|
|
9863
10097
|
if (!latest) {
|
|
@@ -9883,7 +10117,7 @@ function registerLatestCommand(usage) {
|
|
|
9883
10117
|
});
|
|
9884
10118
|
}
|
|
9885
10119
|
function createUsageCommand() {
|
|
9886
|
-
const usage = new
|
|
10120
|
+
const usage = new Command88("usage").description("Token usage and cost tracking");
|
|
9887
10121
|
usage.option(
|
|
9888
10122
|
"--include-claude-sessions",
|
|
9889
10123
|
"Include Claude Code session data from ~/.claude/projects/"
|
|
@@ -9898,7 +10132,7 @@ function createUsageCommand() {
|
|
|
9898
10132
|
// src/commands/validate.ts
|
|
9899
10133
|
init_dist();
|
|
9900
10134
|
init_dist();
|
|
9901
|
-
import { Command as
|
|
10135
|
+
import { Command as Command89 } from "commander";
|
|
9902
10136
|
import * as path64 from "path";
|
|
9903
10137
|
async function runValidate(options) {
|
|
9904
10138
|
const configResult = resolveConfig(options.configPath);
|
|
@@ -9952,6 +10186,34 @@ async function runValidate(options) {
|
|
|
9952
10186
|
});
|
|
9953
10187
|
}
|
|
9954
10188
|
result.checks.fileStructure = true;
|
|
10189
|
+
const pulseResult = await validatePulseConfig(cwd);
|
|
10190
|
+
if (pulseResult.ok) {
|
|
10191
|
+
result.checks.pulseConfig = true;
|
|
10192
|
+
} else {
|
|
10193
|
+
result.valid = false;
|
|
10194
|
+
result.checks.pulseConfig = false;
|
|
10195
|
+
result.issues.push({
|
|
10196
|
+
check: "pulseConfig",
|
|
10197
|
+
file: "harness.config.json",
|
|
10198
|
+
message: pulseResult.error.message,
|
|
10199
|
+
...pulseResult.error.suggestions?.[0] !== void 0 && {
|
|
10200
|
+
suggestion: pulseResult.error.suggestions[0]
|
|
10201
|
+
}
|
|
10202
|
+
});
|
|
10203
|
+
}
|
|
10204
|
+
const solutionsResult = await validateSolutionsDir(cwd);
|
|
10205
|
+
if (solutionsResult.ok) {
|
|
10206
|
+
result.checks.solutionsDir = true;
|
|
10207
|
+
} else {
|
|
10208
|
+
result.valid = false;
|
|
10209
|
+
result.checks.solutionsDir = false;
|
|
10210
|
+
const detail = solutionsResult.error.details;
|
|
10211
|
+
for (const issue of detail.issues ?? [
|
|
10212
|
+
{ file: "docs/solutions", message: solutionsResult.error.message }
|
|
10213
|
+
]) {
|
|
10214
|
+
result.issues.push({ check: "solutionsDir", file: issue.file, message: issue.message });
|
|
10215
|
+
}
|
|
10216
|
+
}
|
|
9955
10217
|
if (options.agentConfigs) {
|
|
9956
10218
|
const agentCfg = await validateAgentConfigs(cwd, {
|
|
9957
10219
|
strict: options.strict === true,
|
|
@@ -9981,7 +10243,7 @@ function resolveValidateMode(globalOpts) {
|
|
|
9981
10243
|
return OutputMode.TEXT;
|
|
9982
10244
|
}
|
|
9983
10245
|
async function printCrossCheckWarnings(mode) {
|
|
9984
|
-
const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-
|
|
10246
|
+
const { runCrossCheck: runCrossCheck2 } = await import("./validate-cross-check-GBX7B7CQ.js");
|
|
9985
10247
|
const cwd = process.cwd();
|
|
9986
10248
|
const crossResult = await runCrossCheck2({
|
|
9987
10249
|
specsDir: path64.join(cwd, "docs", "specs"),
|
|
@@ -9997,7 +10259,7 @@ async function printCrossCheckWarnings(mode) {
|
|
|
9997
10259
|
${crossResult.value.warnings} warnings`);
|
|
9998
10260
|
}
|
|
9999
10261
|
function createValidateCommand3() {
|
|
10000
|
-
const command = new
|
|
10262
|
+
const command = new Command89("validate").description("Run all validation checks").option("--cross-check", "Run cross-artifact consistency validation").option(
|
|
10001
10263
|
"--agent-configs",
|
|
10002
10264
|
"Validate agent configs (CLAUDE.md, hooks, skills) via agnix or built-in fallback rules"
|
|
10003
10265
|
).option("--strict", "Treat warnings as errors (applies to --agent-configs)").option("--agnix-bin <path>", "Override the agnix binary path discovered on PATH").action(async (opts, cmd) => runValidateAction(opts, cmd.optsWithGlobals()));
|
|
@@ -10061,6 +10323,7 @@ var commandCreators = [
|
|
|
10061
10323
|
createCICommand,
|
|
10062
10324
|
createCleanupCommand,
|
|
10063
10325
|
createCleanupSessionsCommand,
|
|
10326
|
+
createCompoundCommand,
|
|
10064
10327
|
createCreateSkillCommand,
|
|
10065
10328
|
createDashboardCommand,
|
|
10066
10329
|
createDoctorCommand,
|
|
@@ -10086,6 +10349,7 @@ var commandCreators = [
|
|
|
10086
10349
|
createPersonaCommand,
|
|
10087
10350
|
createPredictCommand,
|
|
10088
10351
|
createPublishAnalysesCommand,
|
|
10352
|
+
createPulseCommand,
|
|
10089
10353
|
createQueryCommand,
|
|
10090
10354
|
createRecommendCommand,
|
|
10091
10355
|
createScanCommand,
|
|
@@ -10109,7 +10373,7 @@ var commandCreators = [
|
|
|
10109
10373
|
|
|
10110
10374
|
// src/index.ts
|
|
10111
10375
|
function createProgram() {
|
|
10112
|
-
const program = new
|
|
10376
|
+
const program = new Command90();
|
|
10113
10377
|
program.name("harness").description("CLI for Harness Engineering toolkit").version(CLI_VERSION).option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--verbose", "Verbose output").option("--quiet", "Minimal output");
|
|
10114
10378
|
for (const creator of commandCreators) {
|
|
10115
10379
|
program.addCommand(creator());
|