@harness-engineering/cli 1.10.0 → 1.12.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/enforce-architecture/SKILL.md +4 -0
- package/dist/agents/skills/claude-code/harness-parallel-agents/SKILL.md +105 -20
- package/dist/agents/skills/claude-code/harness-pre-commit-review/SKILL.md +37 -0
- package/dist/agents/skills/gemini-cli/enforce-architecture/SKILL.md +4 -0
- package/dist/agents/skills/gemini-cli/harness-parallel-agents/SKILL.md +105 -20
- package/dist/agents/skills/gemini-cli/harness-pre-commit-review/SKILL.md +37 -0
- package/dist/{agents-md-EMRFLNBC.js → agents-md-KIS2RSMG.js} +1 -1
- package/dist/{architecture-5JNN5L3M.js → architecture-AJAUDRQQ.js} +2 -2
- package/dist/bin/harness-mcp.js +14 -14
- package/dist/bin/harness.js +20 -20
- package/dist/{check-phase-gate-WOKIYGAM.js → check-phase-gate-K7QCSYRJ.js} +4 -4
- package/dist/{chunk-FPIPT36X.js → chunk-2SWJ4VO7.js} +6 -6
- package/dist/{chunk-OPXH4CQN.js → chunk-2YPZKGAG.js} +1 -1
- package/dist/{chunk-B7HFEHWP.js → chunk-3WGJMBKH.js} +10 -0
- package/dist/{chunk-ECUJQS3B.js → chunk-6N4R6FVX.js} +3 -3
- package/dist/{chunk-LXU5M77O.js → chunk-747VBPA4.js} +390 -57
- package/dist/{chunk-NX6DSZSM.js → chunk-AE2OWWDH.js} +4497 -2640
- package/dist/{chunk-PAHHT2IK.js → chunk-B5SBNH4S.js} +2833 -918
- package/dist/{chunk-F4PTVZWA.js → chunk-CTTFXXKJ.js} +7 -7
- package/dist/{chunk-PSXF277V.js → chunk-EAURF4LH.js} +1 -1
- package/dist/chunk-EBJQ6N4M.js +39 -0
- package/dist/{chunk-4PFMY3H7.js → chunk-FLOEMHDF.js} +9 -9
- package/dist/{chunk-46YA6FI3.js → chunk-GNGELAXY.js} +2 -2
- package/dist/{chunk-EOLRW32Q.js → chunk-HD4IBGLA.js} +9 -1
- package/dist/{chunk-CWZ4Y2PO.js → chunk-JLXOEO5C.js} +4 -4
- package/dist/{chunk-F3YDAJFQ.js → chunk-L2KLU56K.js} +2 -2
- package/dist/{chunk-MO4YQOMB.js → chunk-OIGVQF5V.js} +3 -3
- package/dist/{chunk-PMTFPOCT.js → chunk-TJVVU3HB.js} +1 -1
- package/dist/{chunk-MDUK2J2O.js → chunk-VRFZWGMS.js} +2 -1
- package/dist/{chunk-FX7SQHGD.js → chunk-YXOG2277.js} +2 -2
- package/dist/{chunk-7X7ZAYMY.js → chunk-ZU2UBYBY.js} +102 -5
- package/dist/{ci-workflow-ZBBUNTHQ.js → ci-workflow-NBL4OT4A.js} +1 -1
- package/dist/create-skill-WPXHSLX2.js +11 -0
- package/dist/{dist-PBTNVK6K.js → dist-IJ4J4C5G.js} +103 -1
- package/dist/{dist-I7DB5VKB.js → dist-M6BQODWC.js} +1145 -0
- package/dist/{docs-PTJGD6XI.js → docs-CPTMH3VY.js} +2 -2
- package/dist/{engine-SCMZ3G3E.js → engine-BUWPAAGD.js} +1 -1
- package/dist/{entropy-YIUBGKY7.js → entropy-Z4FYVQ7L.js} +2 -2
- package/dist/{feedback-WEVQSLAA.js → feedback-TT6WF5YX.js} +1 -1
- package/dist/{generate-agent-definitions-BU5LOJTI.js → generate-agent-definitions-J5HANRNR.js} +4 -4
- package/dist/{graph-loader-RLO3KRIX.js → graph-loader-KO4GJ5N2.js} +1 -1
- package/dist/index.d.ts +355 -12
- package/dist/index.js +33 -21
- package/dist/{loader-6S6PVGSF.js → loader-PCU5YWRH.js} +1 -1
- package/dist/mcp-YM6QLHLZ.js +34 -0
- package/dist/{performance-5TVW6SA6.js → performance-YJVXOKIB.js} +2 -2
- package/dist/{review-pipeline-4JTQAWKW.js → review-pipeline-KGMIMLIE.js} +1 -1
- package/dist/{runtime-PXIM7UV6.js → runtime-F6R27LD6.js} +1 -1
- package/dist/{security-URYTKLGK.js → security-MX5VVXBC.js} +1 -1
- package/dist/skill-executor-RG45LUO5.js +8 -0
- package/dist/templates/orchestrator/WORKFLOW.md +48 -0
- package/dist/templates/orchestrator/template.json +6 -0
- package/dist/{validate-KSDUUK2M.js → validate-EFNMSFKD.js} +2 -2
- package/dist/{validate-cross-check-WZAX357V.js → validate-cross-check-LJX65SBS.js} +1 -1
- package/package.json +10 -6
- package/dist/chunk-HIOXKZYF.js +0 -15
- package/dist/create-skill-LUWO46WF.js +0 -11
- package/dist/mcp-BNLBTCXZ.js +0 -34
- package/dist/skill-executor-KVS47DAU.js +0 -8
|
@@ -32,18 +32,18 @@ async function handleCheckDocs(input) {
|
|
|
32
32
|
const projectPath = sanitizePath(input.path);
|
|
33
33
|
const scope = input.scope ?? "coverage";
|
|
34
34
|
if (scope === "integrity") {
|
|
35
|
-
const { validateKnowledgeMap } = await import("./dist-
|
|
35
|
+
const { validateKnowledgeMap } = await import("./dist-IJ4J4C5G.js");
|
|
36
36
|
const result2 = await validateKnowledgeMap(projectPath);
|
|
37
37
|
return resultToMcpResponse(result2);
|
|
38
38
|
}
|
|
39
39
|
if (scope === "all") {
|
|
40
|
-
const { checkDocCoverage: checkDocCoverage2, validateKnowledgeMap } = await import("./dist-
|
|
40
|
+
const { checkDocCoverage: checkDocCoverage2, validateKnowledgeMap } = await import("./dist-IJ4J4C5G.js");
|
|
41
41
|
const domain2 = input.domain ?? "src";
|
|
42
|
-
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-
|
|
42
|
+
const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-KO4GJ5N2.js");
|
|
43
43
|
const store2 = await loadGraphStore2(projectPath);
|
|
44
44
|
let graphCoverage2;
|
|
45
45
|
if (store2) {
|
|
46
|
-
const { Assembler } = await import("./dist-
|
|
46
|
+
const { Assembler } = await import("./dist-M6BQODWC.js");
|
|
47
47
|
const assembler = new Assembler(store2);
|
|
48
48
|
const report = assembler.checkCoverage();
|
|
49
49
|
graphCoverage2 = {
|
|
@@ -76,13 +76,13 @@ async function handleCheckDocs(input) {
|
|
|
76
76
|
}
|
|
77
77
|
return resultToMcpResponse(Ok({ coverage, integrity }));
|
|
78
78
|
}
|
|
79
|
-
const { checkDocCoverage } = await import("./dist-
|
|
79
|
+
const { checkDocCoverage } = await import("./dist-IJ4J4C5G.js");
|
|
80
80
|
const domain = input.domain ?? "src";
|
|
81
|
-
const { loadGraphStore } = await import("./graph-loader-
|
|
81
|
+
const { loadGraphStore } = await import("./graph-loader-KO4GJ5N2.js");
|
|
82
82
|
const store = await loadGraphStore(projectPath);
|
|
83
83
|
let graphCoverage;
|
|
84
84
|
if (store) {
|
|
85
|
-
const { Assembler } = await import("./dist-
|
|
85
|
+
const { Assembler } = await import("./dist-M6BQODWC.js");
|
|
86
86
|
const assembler = new Assembler(store);
|
|
87
87
|
const report = assembler.checkCoverage();
|
|
88
88
|
graphCoverage = {
|
|
@@ -26,7 +26,7 @@ var runSecurityScanDefinition = {
|
|
|
26
26
|
};
|
|
27
27
|
async function handleRunSecurityScan(input) {
|
|
28
28
|
try {
|
|
29
|
-
const core = await import("./dist-
|
|
29
|
+
const core = await import("./dist-IJ4J4C5G.js");
|
|
30
30
|
const projectRoot = sanitizePath(input.path);
|
|
31
31
|
let configData = {};
|
|
32
32
|
try {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/output/logger.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
var logger = {
|
|
4
|
+
/**
|
|
5
|
+
* Logs an informational message with a blue 'i' icon.
|
|
6
|
+
* @param message - The message to log.
|
|
7
|
+
*/
|
|
8
|
+
info: (message) => console.log(chalk.blue("i"), message),
|
|
9
|
+
/**
|
|
10
|
+
* Logs a success message with a green 'v' icon.
|
|
11
|
+
* @param message - The message to log.
|
|
12
|
+
*/
|
|
13
|
+
success: (message) => console.log(chalk.green("v"), message),
|
|
14
|
+
/**
|
|
15
|
+
* Logs a warning message with a yellow '!' icon.
|
|
16
|
+
* @param message - The message to log.
|
|
17
|
+
*/
|
|
18
|
+
warn: (message) => console.log(chalk.yellow("!"), message),
|
|
19
|
+
/**
|
|
20
|
+
* Logs an error message with a red 'x' icon to stderr.
|
|
21
|
+
* @param message - The message to log.
|
|
22
|
+
*/
|
|
23
|
+
error: (message) => console.error(chalk.red("x"), message),
|
|
24
|
+
/**
|
|
25
|
+
* Logs a dimmed message.
|
|
26
|
+
* @param message - The message to log.
|
|
27
|
+
*/
|
|
28
|
+
dim: (message) => console.log(chalk.dim(message)),
|
|
29
|
+
/**
|
|
30
|
+
* Logs raw data as a formatted JSON string.
|
|
31
|
+
* Useful for JSON output mode.
|
|
32
|
+
* @param data - The data to log.
|
|
33
|
+
*/
|
|
34
|
+
raw: (data) => console.log(JSON.stringify(data, null, 2))
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
logger
|
|
39
|
+
};
|
|
@@ -33,7 +33,7 @@ var createSelfReviewDefinition = {
|
|
|
33
33
|
};
|
|
34
34
|
async function handleCreateSelfReview(input) {
|
|
35
35
|
try {
|
|
36
|
-
const { parseDiff, createSelfReview } = await import("./dist-
|
|
36
|
+
const { parseDiff, createSelfReview } = await import("./dist-IJ4J4C5G.js");
|
|
37
37
|
const parseResult = parseDiff(input.diff);
|
|
38
38
|
if (!parseResult.ok) {
|
|
39
39
|
return resultToMcpResponse(parseResult);
|
|
@@ -53,11 +53,11 @@ async function handleCreateSelfReview(input) {
|
|
|
53
53
|
...input.maxFileCount !== void 0 ? { maxChangedFiles: input.maxFileCount } : {}
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
-
const { loadGraphStore } = await import("./graph-loader-
|
|
56
|
+
const { loadGraphStore } = await import("./graph-loader-KO4GJ5N2.js");
|
|
57
57
|
const store = await loadGraphStore(projectPath);
|
|
58
58
|
let graphData;
|
|
59
59
|
if (store) {
|
|
60
|
-
const { GraphFeedbackAdapter } = await import("./dist-
|
|
60
|
+
const { GraphFeedbackAdapter } = await import("./dist-M6BQODWC.js");
|
|
61
61
|
const adapter = new GraphFeedbackAdapter(store);
|
|
62
62
|
const changedFiles = parseResult.value.files.map((f) => f.path);
|
|
63
63
|
const impact = adapter.computeImpactData(changedFiles);
|
|
@@ -119,7 +119,7 @@ var analyzeDiffDefinition = {
|
|
|
119
119
|
};
|
|
120
120
|
async function handleAnalyzeDiff(input) {
|
|
121
121
|
try {
|
|
122
|
-
const { parseDiff, analyzeDiff } = await import("./dist-
|
|
122
|
+
const { parseDiff, analyzeDiff } = await import("./dist-IJ4J4C5G.js");
|
|
123
123
|
const parseResult = parseDiff(input.diff);
|
|
124
124
|
if (!parseResult.ok) {
|
|
125
125
|
return resultToMcpResponse(parseResult);
|
|
@@ -139,10 +139,10 @@ async function handleAnalyzeDiff(input) {
|
|
|
139
139
|
let graphImpactData;
|
|
140
140
|
if (input.path) {
|
|
141
141
|
try {
|
|
142
|
-
const { loadGraphStore } = await import("./graph-loader-
|
|
142
|
+
const { loadGraphStore } = await import("./graph-loader-KO4GJ5N2.js");
|
|
143
143
|
const store = await loadGraphStore(sanitizePath(input.path));
|
|
144
144
|
if (store) {
|
|
145
|
-
const { GraphFeedbackAdapter } = await import("./dist-
|
|
145
|
+
const { GraphFeedbackAdapter } = await import("./dist-M6BQODWC.js");
|
|
146
146
|
const adapter = new GraphFeedbackAdapter(store);
|
|
147
147
|
const changedFiles = parseResult.value.files.map((f) => f.path);
|
|
148
148
|
const impact = adapter.computeImpactData(changedFiles);
|
|
@@ -195,7 +195,7 @@ var requestPeerReviewDefinition = {
|
|
|
195
195
|
};
|
|
196
196
|
async function handleRequestPeerReview(input) {
|
|
197
197
|
try {
|
|
198
|
-
const { parseDiff, requestPeerReview } = await import("./dist-
|
|
198
|
+
const { parseDiff, requestPeerReview } = await import("./dist-IJ4J4C5G.js");
|
|
199
199
|
const parseResult = parseDiff(input.diff);
|
|
200
200
|
if (!parseResult.ok) {
|
|
201
201
|
return resultToMcpResponse(parseResult);
|
|
@@ -206,10 +206,10 @@ async function handleRequestPeerReview(input) {
|
|
|
206
206
|
...input.context ? { metadata: { context: input.context } } : {}
|
|
207
207
|
};
|
|
208
208
|
try {
|
|
209
|
-
const { loadGraphStore } = await import("./graph-loader-
|
|
209
|
+
const { loadGraphStore } = await import("./graph-loader-KO4GJ5N2.js");
|
|
210
210
|
const store = await loadGraphStore(sanitizePath(input.path));
|
|
211
211
|
if (store) {
|
|
212
|
-
const { GraphFeedbackAdapter } = await import("./dist-
|
|
212
|
+
const { GraphFeedbackAdapter } = await import("./dist-M6BQODWC.js");
|
|
213
213
|
const adapter = new GraphFeedbackAdapter(store);
|
|
214
214
|
const changedFiles = parseResult.value.files.map((f) => f.path);
|
|
215
215
|
const impactData = adapter.computeImpactData(changedFiles);
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
resolvePersonasDir,
|
|
16
16
|
resolveSkillsDir
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-HD4IBGLA.js";
|
|
18
18
|
import {
|
|
19
19
|
CLIError,
|
|
20
20
|
ExitCode,
|
|
21
21
|
handleError
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-3WGJMBKH.js";
|
|
23
23
|
|
|
24
24
|
// src/commands/generate-agent-definitions.ts
|
|
25
25
|
import { Command } from "commander";
|
|
@@ -62,11 +62,19 @@ function resolveGlobalSkillsDir() {
|
|
|
62
62
|
}
|
|
63
63
|
return path.join(__dirname, "agents", "skills", "claude-code");
|
|
64
64
|
}
|
|
65
|
+
function resolveCommunitySkillsDir(platform = "claude-code") {
|
|
66
|
+
const agentsDir = findUpDir("agents", "skills");
|
|
67
|
+
if (agentsDir) {
|
|
68
|
+
return path.join(agentsDir, "skills", "community", platform);
|
|
69
|
+
}
|
|
70
|
+
return path.join(__dirname, "agents", "skills", "community", platform);
|
|
71
|
+
}
|
|
65
72
|
|
|
66
73
|
export {
|
|
67
74
|
resolveTemplatesDir,
|
|
68
75
|
resolvePersonasDir,
|
|
69
76
|
resolveSkillsDir,
|
|
70
77
|
resolveProjectSkillsDir,
|
|
71
|
-
resolveGlobalSkillsDir
|
|
78
|
+
resolveGlobalSkillsDir,
|
|
79
|
+
resolveCommunitySkillsDir
|
|
72
80
|
};
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
|
|
11
11
|
// src/mcp/tools/entropy.ts
|
|
12
12
|
async function loadEntropyGraphOptions(projectPath) {
|
|
13
|
-
const { loadGraphStore } = await import("./graph-loader-
|
|
13
|
+
const { loadGraphStore } = await import("./graph-loader-KO4GJ5N2.js");
|
|
14
14
|
const store = await loadGraphStore(projectPath);
|
|
15
15
|
if (!store) return void 0;
|
|
16
|
-
const { GraphEntropyAdapter } = await import("./dist-
|
|
16
|
+
const { GraphEntropyAdapter } = await import("./dist-M6BQODWC.js");
|
|
17
17
|
const adapter = new GraphEntropyAdapter(store);
|
|
18
18
|
const driftData = adapter.computeDriftData();
|
|
19
19
|
const deadCodeData = adapter.computeDeadCodeData();
|
|
@@ -84,7 +84,7 @@ var detectEntropyDefinition = {
|
|
|
84
84
|
};
|
|
85
85
|
async function handleDetectEntropy(input) {
|
|
86
86
|
try {
|
|
87
|
-
const { EntropyAnalyzer } = await import("./dist-
|
|
87
|
+
const { EntropyAnalyzer } = await import("./dist-IJ4J4C5G.js");
|
|
88
88
|
const typeFilter = input.type ?? "all";
|
|
89
89
|
const analyzer = new EntropyAnalyzer({
|
|
90
90
|
rootDir: sanitizePath(input.path),
|
|
@@ -144,7 +144,7 @@ async function handleDetectEntropy(input) {
|
|
|
144
144
|
return resultToMcpResponse(result);
|
|
145
145
|
}
|
|
146
146
|
if (!result.ok) return resultToMcpResponse(result);
|
|
147
|
-
const { createFixes, applyFixes, generateSuggestions } = await import("./dist-
|
|
147
|
+
const { createFixes, applyFixes, generateSuggestions } = await import("./dist-IJ4J4C5G.js");
|
|
148
148
|
const report = result.value;
|
|
149
149
|
const deadCode = report.deadCode;
|
|
150
150
|
const fixTypesConfig = input.fixTypes ? { fixTypes: input.fixTypes } : void 0;
|
|
@@ -38,7 +38,7 @@ async function handleCheckDependencies(input) {
|
|
|
38
38
|
const configResult = resolveProjectConfig(projectPath);
|
|
39
39
|
if (!configResult.ok) return resultToMcpResponse(configResult);
|
|
40
40
|
try {
|
|
41
|
-
const { validateDependencies, TypeScriptParser } = await import("./dist-
|
|
41
|
+
const { validateDependencies, TypeScriptParser } = await import("./dist-IJ4J4C5G.js");
|
|
42
42
|
const config = configResult.value;
|
|
43
43
|
const rawLayers = Array.isArray(config.layers) ? config.layers : [];
|
|
44
44
|
const layers = rawLayers.map((l) => ({
|
|
@@ -47,11 +47,11 @@ async function handleCheckDependencies(input) {
|
|
|
47
47
|
allowedDependencies: l.allowedDependencies
|
|
48
48
|
}));
|
|
49
49
|
const parser = new TypeScriptParser();
|
|
50
|
-
const { loadGraphStore } = await import("./graph-loader-
|
|
50
|
+
const { loadGraphStore } = await import("./graph-loader-KO4GJ5N2.js");
|
|
51
51
|
const store = await loadGraphStore(projectPath);
|
|
52
52
|
let graphDependencyData;
|
|
53
53
|
if (store) {
|
|
54
|
-
const { GraphConstraintAdapter } = await import("./dist-
|
|
54
|
+
const { GraphConstraintAdapter } = await import("./dist-M6BQODWC.js");
|
|
55
55
|
const adapter = new GraphConstraintAdapter(store);
|
|
56
56
|
const graphData = adapter.computeDependencyGraph();
|
|
57
57
|
graphDependencyData = {
|
|
@@ -45,7 +45,7 @@ var runCodeReviewDefinition = {
|
|
|
45
45
|
};
|
|
46
46
|
async function handleRunCodeReview(input) {
|
|
47
47
|
try {
|
|
48
|
-
const { parseDiff, runReviewPipeline } = await import("./dist-
|
|
48
|
+
const { parseDiff, runReviewPipeline } = await import("./dist-IJ4J4C5G.js");
|
|
49
49
|
const parseResult = parseDiff(input.diff);
|
|
50
50
|
if (!parseResult.ok) {
|
|
51
51
|
return {
|
|
@@ -58,7 +58,8 @@ var SkillMetadataSchema = z.object({
|
|
|
58
58
|
type: z.enum(["rigid", "flexible"]),
|
|
59
59
|
phases: z.array(SkillPhaseSchema).optional(),
|
|
60
60
|
state: SkillStateSchema.default({}),
|
|
61
|
-
depends_on: z.array(z.string()).default([])
|
|
61
|
+
depends_on: z.array(z.string()).default([]),
|
|
62
|
+
repository: z.string().url().optional()
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
export {
|
|
@@ -49,7 +49,7 @@ async function handleValidateProject(input) {
|
|
|
49
49
|
checks.config = "pass";
|
|
50
50
|
const config = configResult.value;
|
|
51
51
|
try {
|
|
52
|
-
const core = await import("./dist-
|
|
52
|
+
const core = await import("./dist-IJ4J4C5G.js");
|
|
53
53
|
if (typeof core.validateFileStructure === "function" && Array.isArray(config.conventions)) {
|
|
54
54
|
const conventions = config.conventions;
|
|
55
55
|
const structureResult = await core.validateFileStructure(projectPath, conventions);
|
|
@@ -68,7 +68,7 @@ async function handleValidateProject(input) {
|
|
|
68
68
|
} catch {
|
|
69
69
|
}
|
|
70
70
|
try {
|
|
71
|
-
const core = await import("./dist-
|
|
71
|
+
const core = await import("./dist-IJ4J4C5G.js");
|
|
72
72
|
if (typeof core.validateAgentsMap === "function") {
|
|
73
73
|
const agentsMapPath = path.join(projectPath, "AGENTS.md");
|
|
74
74
|
const agentsResult = await core.validateAgentsMap(agentsMapPath);
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
logger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EBJQ6N4M.js";
|
|
4
4
|
import {
|
|
5
5
|
CLIError,
|
|
6
6
|
ExitCode
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3WGJMBKH.js";
|
|
8
|
+
import {
|
|
9
|
+
ArchConfigSchema
|
|
10
|
+
} from "./chunk-AE2OWWDH.js";
|
|
8
11
|
import {
|
|
9
12
|
Err,
|
|
10
13
|
Ok
|
|
@@ -22,67 +25,105 @@ import * as path from "path";
|
|
|
22
25
|
// src/config/schema.ts
|
|
23
26
|
import { z } from "zod";
|
|
24
27
|
var LayerSchema = z.object({
|
|
28
|
+
/** Human-readable name of the layer */
|
|
25
29
|
name: z.string(),
|
|
30
|
+
/** Glob pattern matching files in this layer */
|
|
26
31
|
pattern: z.string(),
|
|
32
|
+
/** Names of other layers this layer is allowed to import from */
|
|
27
33
|
allowedDependencies: z.array(z.string())
|
|
28
34
|
});
|
|
29
35
|
var ForbiddenImportSchema = z.object({
|
|
36
|
+
/** Glob pattern matching source files this rule applies to */
|
|
30
37
|
from: z.string(),
|
|
38
|
+
/** List of modules or patterns that are not allowed to be imported */
|
|
31
39
|
disallow: z.array(z.string()),
|
|
40
|
+
/** Optional custom message to display on violation */
|
|
32
41
|
message: z.string().optional()
|
|
33
42
|
});
|
|
34
43
|
var BoundaryConfigSchema = z.object({
|
|
44
|
+
/** List of globs where files MUST have a corresponding schema/definition */
|
|
35
45
|
requireSchema: z.array(z.string())
|
|
36
46
|
});
|
|
37
47
|
var AgentConfigSchema = z.object({
|
|
48
|
+
/** The execution environment for agents */
|
|
38
49
|
executor: z.enum(["subprocess", "cloud", "noop"]).default("subprocess"),
|
|
50
|
+
/** Maximum execution time in milliseconds */
|
|
39
51
|
timeout: z.number().default(3e5),
|
|
52
|
+
/** Optional list of skill IDs pre-authorized for the agent */
|
|
40
53
|
skills: z.array(z.string()).optional()
|
|
41
54
|
});
|
|
42
55
|
var EntropyConfigSchema = z.object({
|
|
56
|
+
/** Patterns to exclude from entropy analysis */
|
|
43
57
|
excludePatterns: z.array(z.string()).default(["**/node_modules/**", "**/*.test.ts"]),
|
|
58
|
+
/** Whether to automatically attempt to fix simple entropy issues */
|
|
44
59
|
autoFix: z.boolean().default(false)
|
|
45
60
|
});
|
|
46
61
|
var PhaseGateMappingSchema = z.object({
|
|
62
|
+
/** Pattern for implementation files */
|
|
47
63
|
implPattern: z.string(),
|
|
64
|
+
/** Pattern for corresponding specification files */
|
|
48
65
|
specPattern: z.string()
|
|
49
66
|
});
|
|
50
67
|
var PhaseGatesConfigSchema = z.object({
|
|
68
|
+
/** Whether phase gate checks are enabled */
|
|
51
69
|
enabled: z.boolean().default(false),
|
|
70
|
+
/** Severity level when a phase gate check fails */
|
|
52
71
|
severity: z.enum(["error", "warning"]).default("error"),
|
|
72
|
+
/** List of implementation-to-spec mappings */
|
|
53
73
|
mappings: z.array(PhaseGateMappingSchema).default([{ implPattern: "src/**/*.ts", specPattern: "docs/changes/{feature}/proposal.md" }])
|
|
54
74
|
});
|
|
55
75
|
var SecurityConfigSchema = z.object({
|
|
76
|
+
/** Whether security scanning is enabled */
|
|
56
77
|
enabled: z.boolean().default(true),
|
|
78
|
+
/** Whether to fail on any security warning */
|
|
57
79
|
strict: z.boolean().default(false),
|
|
80
|
+
/** Rule-specific severity overrides */
|
|
58
81
|
rules: z.record(z.string(), z.enum(["off", "error", "warning", "info"])).optional(),
|
|
82
|
+
/** Patterns to exclude from security scans */
|
|
59
83
|
exclude: z.array(z.string()).optional()
|
|
60
84
|
}).passthrough();
|
|
61
85
|
var PerformanceConfigSchema = z.object({
|
|
86
|
+
/** Complexity thresholds per module or pattern */
|
|
62
87
|
complexity: z.record(z.unknown()).optional(),
|
|
88
|
+
/** Coupling limits between modules */
|
|
63
89
|
coupling: z.record(z.unknown()).optional(),
|
|
90
|
+
/** Size budget for bundles or directories */
|
|
64
91
|
sizeBudget: z.record(z.unknown()).optional()
|
|
65
92
|
}).passthrough();
|
|
66
93
|
var DesignConfigSchema = z.object({
|
|
94
|
+
/** Strictness of design system enforcement */
|
|
67
95
|
strictness: z.enum(["strict", "standard", "permissive"]).default("standard"),
|
|
96
|
+
/** Supported target platforms */
|
|
68
97
|
platforms: z.array(z.enum(["web", "mobile"])).default([]),
|
|
98
|
+
/** Path to design tokens (e.g. JSON or CSS) */
|
|
69
99
|
tokenPath: z.string().optional(),
|
|
100
|
+
/** Brief description of the intended aesthetic direction */
|
|
70
101
|
aestheticIntent: z.string().optional()
|
|
71
102
|
});
|
|
72
103
|
var I18nCoverageConfigSchema = z.object({
|
|
104
|
+
/** Minimum required translation percentage */
|
|
73
105
|
minimumPercent: z.number().min(0).max(100).default(100),
|
|
106
|
+
/** Whether plural forms are required for all keys */
|
|
74
107
|
requirePlurals: z.boolean().default(true),
|
|
108
|
+
/** Whether to detect untranslated strings in source code */
|
|
75
109
|
detectUntranslated: z.boolean().default(true)
|
|
76
110
|
});
|
|
77
111
|
var I18nMcpConfigSchema = z.object({
|
|
112
|
+
/** Name or URL of the MCP server */
|
|
78
113
|
server: z.string(),
|
|
114
|
+
/** Project ID on the remote i18n platform */
|
|
79
115
|
projectId: z.string().optional()
|
|
80
116
|
});
|
|
81
117
|
var I18nConfigSchema = z.object({
|
|
118
|
+
/** Whether i18n management is enabled */
|
|
82
119
|
enabled: z.boolean().default(false),
|
|
120
|
+
/** Strictness of i18n rule enforcement */
|
|
83
121
|
strictness: z.enum(["strict", "standard", "permissive"]).default("standard"),
|
|
122
|
+
/** The primary language used for development */
|
|
84
123
|
sourceLocale: z.string().default("en"),
|
|
124
|
+
/** List of locales that translations are required for */
|
|
85
125
|
targetLocales: z.array(z.string()).default([]),
|
|
126
|
+
/** The i18n framework in use */
|
|
86
127
|
framework: z.enum([
|
|
87
128
|
"auto",
|
|
88
129
|
"i18next",
|
|
@@ -93,46 +134,82 @@ var I18nConfigSchema = z.object({
|
|
|
93
134
|
"android",
|
|
94
135
|
"custom"
|
|
95
136
|
]).default("auto"),
|
|
137
|
+
/** Storage format for translation files */
|
|
96
138
|
format: z.string().default("json"),
|
|
139
|
+
/** Syntax used for message formatting */
|
|
97
140
|
messageFormat: z.enum(["icu", "i18next", "custom"]).default("icu"),
|
|
141
|
+
/** Convention for translation keys */
|
|
98
142
|
keyConvention: z.enum(["dot-notation", "snake_case", "camelCase", "custom"]).default("dot-notation"),
|
|
143
|
+
/** Mapping of locales to their file paths */
|
|
99
144
|
translationPaths: z.record(z.string(), z.string()).optional(),
|
|
145
|
+
/** Platforms targeted by this configuration */
|
|
100
146
|
platforms: z.array(z.enum(["web", "mobile", "backend"])).default([]),
|
|
147
|
+
/** Industry vertical (for contextual translations) */
|
|
101
148
|
industry: z.string().optional(),
|
|
149
|
+
/** Translation coverage requirements */
|
|
102
150
|
coverage: I18nCoverageConfigSchema.optional(),
|
|
151
|
+
/** Locale used for pseudo-localization testing */
|
|
103
152
|
pseudoLocale: z.string().optional(),
|
|
153
|
+
/** MCP server for AI-assisted translation */
|
|
104
154
|
mcp: I18nMcpConfigSchema.optional()
|
|
105
155
|
});
|
|
106
156
|
var ModelTierConfigSchema = z.object({
|
|
157
|
+
/** Model ID to use for fast/cheap operations */
|
|
107
158
|
fast: z.string().optional(),
|
|
159
|
+
/** Model ID to use for standard reasoning tasks */
|
|
108
160
|
standard: z.string().optional(),
|
|
161
|
+
/** Model ID to use for complex/critical analysis */
|
|
109
162
|
strong: z.string().optional()
|
|
110
163
|
});
|
|
111
164
|
var ReviewConfigSchema = z.object({
|
|
165
|
+
/** Custom model tier mappings for reviewers */
|
|
112
166
|
model_tiers: ModelTierConfigSchema.optional()
|
|
113
167
|
});
|
|
114
168
|
var HarnessConfigSchema = z.object({
|
|
169
|
+
/** Configuration schema version */
|
|
115
170
|
version: z.literal(1),
|
|
171
|
+
/** Human-readable name of the project */
|
|
116
172
|
name: z.string().optional(),
|
|
173
|
+
/** Root directory of the project, relative to the config file */
|
|
117
174
|
rootDir: z.string().default("."),
|
|
175
|
+
/** Layered architecture definitions */
|
|
118
176
|
layers: z.array(LayerSchema).optional(),
|
|
177
|
+
/** Rules for forbidden cross-module imports */
|
|
119
178
|
forbiddenImports: z.array(ForbiddenImportSchema).optional(),
|
|
179
|
+
/** Boundary enforcement settings */
|
|
120
180
|
boundaries: BoundaryConfigSchema.optional(),
|
|
181
|
+
/** Path to the project's knowledge map (AGENTS.md) */
|
|
121
182
|
agentsMapPath: z.string().default("./AGENTS.md"),
|
|
183
|
+
/** Directory containing project documentation */
|
|
122
184
|
docsDir: z.string().default("./docs"),
|
|
185
|
+
/** Agent orchestration settings */
|
|
123
186
|
agent: AgentConfigSchema.optional(),
|
|
187
|
+
/** Drift and stale code management settings */
|
|
124
188
|
entropy: EntropyConfigSchema.optional(),
|
|
189
|
+
/** Security scanning configuration */
|
|
125
190
|
security: SecurityConfigSchema.optional(),
|
|
191
|
+
/** Performance and complexity budget settings */
|
|
126
192
|
performance: PerformanceConfigSchema.optional(),
|
|
193
|
+
/** Project template settings (used by 'harness init') */
|
|
127
194
|
template: z.object({
|
|
195
|
+
/** Complexity level of the template */
|
|
128
196
|
level: z.enum(["basic", "intermediate", "advanced"]),
|
|
197
|
+
/** Primary technology framework */
|
|
129
198
|
framework: z.string().optional(),
|
|
199
|
+
/** Template version */
|
|
130
200
|
version: z.number()
|
|
131
201
|
}).optional(),
|
|
202
|
+
/** Phase gate and readiness check configuration */
|
|
132
203
|
phaseGates: PhaseGatesConfigSchema.optional(),
|
|
204
|
+
/** Design system consistency settings */
|
|
133
205
|
design: DesignConfigSchema.optional(),
|
|
206
|
+
/** Internationalization (i18n) settings */
|
|
134
207
|
i18n: I18nConfigSchema.optional(),
|
|
208
|
+
/** Code review settings */
|
|
135
209
|
review: ReviewConfigSchema.optional(),
|
|
210
|
+
/** General architectural enforcement settings */
|
|
211
|
+
architecture: ArchConfigSchema.optional(),
|
|
212
|
+
/** How often (in ms) to check for CLI updates */
|
|
136
213
|
updateCheckInterval: z.number().int().min(0).optional()
|
|
137
214
|
});
|
|
138
215
|
|
|
@@ -198,17 +275,29 @@ async function findFiles(pattern, cwd = process.cwd()) {
|
|
|
198
275
|
// src/output/formatter.ts
|
|
199
276
|
import chalk from "chalk";
|
|
200
277
|
var OutputMode = {
|
|
278
|
+
/** Output as formatted JSON */
|
|
201
279
|
JSON: "json",
|
|
280
|
+
/** Output as human-readable text */
|
|
202
281
|
TEXT: "text",
|
|
282
|
+
/** Minimal output, only errors and successes */
|
|
203
283
|
QUIET: "quiet",
|
|
284
|
+
/** Full output with detailed context and suggestions */
|
|
204
285
|
VERBOSE: "verbose"
|
|
205
286
|
};
|
|
206
287
|
var OutputFormatter = class {
|
|
288
|
+
/**
|
|
289
|
+
* Creates a new OutputFormatter.
|
|
290
|
+
*
|
|
291
|
+
* @param mode - The output mode to use. Defaults to TEXT.
|
|
292
|
+
*/
|
|
207
293
|
constructor(mode = OutputMode.TEXT) {
|
|
208
294
|
this.mode = mode;
|
|
209
295
|
}
|
|
210
296
|
/**
|
|
211
|
-
*
|
|
297
|
+
* Formats raw data for output.
|
|
298
|
+
*
|
|
299
|
+
* @param data - The data to format.
|
|
300
|
+
* @returns A string representation of the data based on the current mode.
|
|
212
301
|
*/
|
|
213
302
|
format(data) {
|
|
214
303
|
if (this.mode === OutputMode.JSON) {
|
|
@@ -217,7 +306,10 @@ var OutputFormatter = class {
|
|
|
217
306
|
return String(data);
|
|
218
307
|
}
|
|
219
308
|
/**
|
|
220
|
-
*
|
|
309
|
+
* Formats a validation result into a user-friendly string.
|
|
310
|
+
*
|
|
311
|
+
* @param result - The validation result to format.
|
|
312
|
+
* @returns A formatted string containing the validation status and any issues.
|
|
221
313
|
*/
|
|
222
314
|
formatValidation(result) {
|
|
223
315
|
if (this.mode === OutputMode.JSON) {
|
|
@@ -245,7 +337,12 @@ var OutputFormatter = class {
|
|
|
245
337
|
return lines.join("\n");
|
|
246
338
|
}
|
|
247
339
|
/**
|
|
248
|
-
*
|
|
340
|
+
* Formats a summary line with a success/failure icon and label.
|
|
341
|
+
*
|
|
342
|
+
* @param label - The name of the field to summarize.
|
|
343
|
+
* @param value - The value to display.
|
|
344
|
+
* @param success - Whether the summary represents a success or failure state.
|
|
345
|
+
* @returns A formatted summary string, or an empty string in JSON or QUIET modes.
|
|
249
346
|
*/
|
|
250
347
|
formatSummary(label, value, success) {
|
|
251
348
|
if (this.mode === OutputMode.JSON || this.mode === OutputMode.QUIET) {
|