@harness-engineering/cli 1.8.2 → 1.10.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/cleanup-dead-code/SKILL.md +3 -3
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +20 -3
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +55 -5
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +36 -15
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +1 -1
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +70 -13
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +41 -3
- package/dist/agents/skills/claude-code/harness-pre-commit-review/SKILL.md +28 -3
- package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +14 -2
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +18 -2
- package/dist/agents/skills/gemini-cli/cleanup-dead-code/SKILL.md +3 -3
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +20 -3
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +55 -5
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +36 -15
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +1 -1
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +70 -13
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +41 -3
- package/dist/agents/skills/gemini-cli/harness-pre-commit-review/SKILL.md +28 -3
- package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +14 -2
- package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +18 -2
- package/dist/agents-md-EMRFLNBC.js +8 -0
- package/dist/architecture-5JNN5L3M.js +13 -0
- package/dist/bin/harness-mcp.d.ts +1 -0
- package/dist/bin/harness-mcp.js +28 -0
- package/dist/bin/harness.js +42 -8
- package/dist/check-phase-gate-WOKIYGAM.js +12 -0
- package/dist/chunk-46YA6FI3.js +293 -0
- package/dist/chunk-4PFMY3H7.js +248 -0
- package/dist/{chunk-LB4GRDDV.js → chunk-72GHBOL2.js} +1 -1
- package/dist/chunk-7X7ZAYMY.js +373 -0
- package/dist/chunk-B7HFEHWP.js +35 -0
- package/dist/chunk-BM3PWGXQ.js +14 -0
- package/dist/chunk-C2ERUR3L.js +255 -0
- package/dist/chunk-CWZ4Y2PO.js +189 -0
- package/dist/{chunk-ULSRSP53.js → chunk-ECUJQS3B.js} +11 -112
- package/dist/chunk-EOLRW32Q.js +72 -0
- package/dist/chunk-F3YDAJFQ.js +125 -0
- package/dist/chunk-F4PTVZWA.js +116 -0
- package/dist/chunk-FPIPT36X.js +187 -0
- package/dist/chunk-FX7SQHGD.js +103 -0
- package/dist/chunk-HIOXKZYF.js +15 -0
- package/dist/chunk-IDZNPTYD.js +16 -0
- package/dist/chunk-JSTQ3AWB.js +31 -0
- package/dist/chunk-K6XAPGML.js +27 -0
- package/dist/chunk-KET4QQZB.js +8 -0
- package/dist/chunk-LXU5M77O.js +4028 -0
- package/dist/chunk-MDUK2J2O.js +67 -0
- package/dist/chunk-MHBMTPW7.js +29 -0
- package/dist/chunk-MO4YQOMB.js +85 -0
- package/dist/chunk-NKDM3FMH.js +52 -0
- package/dist/{chunk-SAB3VXOW.js → chunk-NX6DSZSM.js} +144 -111
- package/dist/chunk-OPXH4CQN.js +62 -0
- package/dist/{chunk-Y7U5AYAL.js → chunk-PAHHT2IK.js} +471 -2719
- package/dist/chunk-PMTFPOCT.js +122 -0
- package/dist/chunk-PSXF277V.js +89 -0
- package/dist/chunk-Q6AB7W5Z.js +135 -0
- package/dist/chunk-QPEH2QPG.js +347 -0
- package/dist/chunk-TEFCFC4H.js +15 -0
- package/dist/chunk-TRAPF4IX.js +185 -0
- package/dist/chunk-VUCPTQ6G.js +67 -0
- package/dist/chunk-W6Y7ZW3Y.js +13 -0
- package/dist/chunk-ZOAWBDWU.js +72 -0
- package/dist/ci-workflow-ZBBUNTHQ.js +8 -0
- package/dist/constants-5JGUXPEK.js +6 -0
- package/dist/create-skill-LUWO46WF.js +11 -0
- package/dist/dist-D4RYGUZE.js +14 -0
- package/dist/{dist-K6KTTN3I.js → dist-I7DB5VKB.js} +237 -0
- package/dist/dist-L7LAAQAS.js +18 -0
- package/dist/{dist-ZODQVGC4.js → dist-PBTNVK6K.js} +8 -6
- package/dist/docs-PTJGD6XI.js +12 -0
- package/dist/engine-SCMZ3G3E.js +8 -0
- package/dist/entropy-YIUBGKY7.js +12 -0
- package/dist/feedback-WEVQSLAA.js +18 -0
- package/dist/generate-agent-definitions-BU5LOJTI.js +15 -0
- package/dist/glob-helper-5OHBUQAI.js +52 -0
- package/dist/graph-loader-RLO3KRIX.js +8 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.js +84 -33
- package/dist/loader-6S6PVGSF.js +10 -0
- package/dist/mcp-BNLBTCXZ.js +34 -0
- package/dist/performance-5TVW6SA6.js +24 -0
- package/dist/review-pipeline-4JTQAWKW.js +9 -0
- package/dist/runner-VMYLHWOC.js +6 -0
- package/dist/runtime-PXIM7UV6.js +9 -0
- package/dist/security-URYTKLGK.js +9 -0
- package/dist/skill-executor-KVS47DAU.js +8 -0
- package/dist/validate-KSDUUK2M.js +12 -0
- package/dist/validate-cross-check-WZAX357V.js +8 -0
- package/dist/version-KFFPOQAX.js +6 -0
- package/package.json +7 -5
- package/dist/create-skill-UZOHMXRU.js +0 -8
- package/dist/validate-cross-check-DLNK423G.js +0 -7
package/dist/bin/harness.js
CHANGED
|
@@ -1,21 +1,55 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
createProgram
|
|
4
|
+
} from "../chunk-PAHHT2IK.js";
|
|
5
|
+
import "../chunk-VUCPTQ6G.js";
|
|
6
|
+
import {
|
|
5
7
|
findConfigFile,
|
|
6
8
|
loadConfig
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
+
} from "../chunk-7X7ZAYMY.js";
|
|
10
|
+
import "../chunk-46YA6FI3.js";
|
|
11
|
+
import "../chunk-Q6AB7W5Z.js";
|
|
12
|
+
import "../chunk-TRAPF4IX.js";
|
|
13
|
+
import "../chunk-F3YDAJFQ.js";
|
|
14
|
+
import "../chunk-TEFCFC4H.js";
|
|
15
|
+
import "../chunk-ECUJQS3B.js";
|
|
16
|
+
import "../chunk-HIOXKZYF.js";
|
|
17
|
+
import "../chunk-QPEH2QPG.js";
|
|
18
|
+
import "../chunk-JSTQ3AWB.js";
|
|
19
|
+
import "../chunk-KET4QQZB.js";
|
|
20
|
+
import "../chunk-NKDM3FMH.js";
|
|
21
|
+
import "../chunk-LXU5M77O.js";
|
|
22
|
+
import "../chunk-CWZ4Y2PO.js";
|
|
23
|
+
import "../chunk-FPIPT36X.js";
|
|
24
|
+
import "../chunk-4PFMY3H7.js";
|
|
25
|
+
import "../chunk-PSXF277V.js";
|
|
26
|
+
import "../chunk-PMTFPOCT.js";
|
|
27
|
+
import "../chunk-ZOAWBDWU.js";
|
|
28
|
+
import "../chunk-FX7SQHGD.js";
|
|
29
|
+
import "../chunk-OPXH4CQN.js";
|
|
30
|
+
import "../chunk-MO4YQOMB.js";
|
|
31
|
+
import "../chunk-K6XAPGML.js";
|
|
32
|
+
import "../chunk-F4PTVZWA.js";
|
|
33
|
+
import "../chunk-IDZNPTYD.js";
|
|
34
|
+
import "../chunk-W6Y7ZW3Y.js";
|
|
35
|
+
import "../chunk-EOLRW32Q.js";
|
|
36
|
+
import {
|
|
37
|
+
handleError
|
|
38
|
+
} from "../chunk-B7HFEHWP.js";
|
|
39
|
+
import "../chunk-MDUK2J2O.js";
|
|
40
|
+
import {
|
|
41
|
+
CLI_VERSION
|
|
42
|
+
} from "../chunk-BM3PWGXQ.js";
|
|
43
|
+
import "../chunk-72GHBOL2.js";
|
|
44
|
+
import "../chunk-C2ERUR3L.js";
|
|
9
45
|
import {
|
|
10
46
|
getUpdateNotification,
|
|
11
47
|
isUpdateCheckEnabled,
|
|
12
48
|
readCheckState,
|
|
13
49
|
shouldRunCheck,
|
|
14
50
|
spawnBackgroundCheck
|
|
15
|
-
} from "../chunk-
|
|
16
|
-
import
|
|
17
|
-
handleError
|
|
18
|
-
} from "../chunk-ULSRSP53.js";
|
|
51
|
+
} from "../chunk-NX6DSZSM.js";
|
|
52
|
+
import "../chunk-MHBMTPW7.js";
|
|
19
53
|
|
|
20
54
|
// src/bin/update-check-hooks.ts
|
|
21
55
|
var DEFAULT_INTERVAL_MS = 864e5;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCheckPhaseGateCommand,
|
|
3
|
+
runCheckPhaseGate
|
|
4
|
+
} from "./chunk-7X7ZAYMY.js";
|
|
5
|
+
import "./chunk-HIOXKZYF.js";
|
|
6
|
+
import "./chunk-B7HFEHWP.js";
|
|
7
|
+
import "./chunk-NX6DSZSM.js";
|
|
8
|
+
import "./chunk-MHBMTPW7.js";
|
|
9
|
+
export {
|
|
10
|
+
createCheckPhaseGateCommand,
|
|
11
|
+
runCheckPhaseGate
|
|
12
|
+
};
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listPersonas,
|
|
3
|
+
loadPersona
|
|
4
|
+
} from "./chunk-Q6AB7W5Z.js";
|
|
5
|
+
import {
|
|
6
|
+
toKebabCase
|
|
7
|
+
} from "./chunk-KET4QQZB.js";
|
|
8
|
+
import {
|
|
9
|
+
GENERATED_HEADER_AGENT,
|
|
10
|
+
VALID_PLATFORMS,
|
|
11
|
+
applySyncPlan,
|
|
12
|
+
computeSyncPlan
|
|
13
|
+
} from "./chunk-ZOAWBDWU.js";
|
|
14
|
+
import {
|
|
15
|
+
resolvePersonasDir,
|
|
16
|
+
resolveSkillsDir
|
|
17
|
+
} from "./chunk-EOLRW32Q.js";
|
|
18
|
+
import {
|
|
19
|
+
CLIError,
|
|
20
|
+
ExitCode,
|
|
21
|
+
handleError
|
|
22
|
+
} from "./chunk-B7HFEHWP.js";
|
|
23
|
+
|
|
24
|
+
// src/commands/generate-agent-definitions.ts
|
|
25
|
+
import { Command } from "commander";
|
|
26
|
+
import * as fs from "fs";
|
|
27
|
+
import * as path from "path";
|
|
28
|
+
import * as os from "os";
|
|
29
|
+
|
|
30
|
+
// src/agent-definitions/generator.ts
|
|
31
|
+
var AGENT_DESCRIPTIONS = {
|
|
32
|
+
"code-reviewer": "Perform code review and address review findings using harness methodology. Use when reviewing code, fixing review findings, responding to review feedback, or when a code review has produced issues that need to be addressed.",
|
|
33
|
+
"task-executor": "Execute implementation plans task-by-task with state tracking, TDD, and verification. Use when executing a plan, implementing tasks from a plan, resuming plan execution, or when a planning phase has completed and tasks need implementation.",
|
|
34
|
+
"parallel-coordinator": "Dispatch independent tasks across isolated agents for parallel execution. Use when multiple independent tasks need to run concurrently, splitting work across agents, or coordinating parallel implementation.",
|
|
35
|
+
"architecture-enforcer": "Validate architectural constraints and dependency rules. Use when checking layer boundaries, detecting circular dependencies, or verifying import direction compliance.",
|
|
36
|
+
"documentation-maintainer": "Keep documentation in sync with source code. Use when detecting documentation drift, validating doc coverage, or aligning docs with code changes.",
|
|
37
|
+
"entropy-cleaner": "Detect and fix codebase entropy including drift, dead code, and pattern violations. Use when running cleanup, detecting dead code, or fixing pattern violations.",
|
|
38
|
+
planner: "Create detailed implementation plans from specs with task breakdown, dependency ordering, and checkpoint placement. Use when planning a phase, breaking a spec into tasks, or creating an execution plan.",
|
|
39
|
+
verifier: "Verify implementation completeness against spec and plan at three tiers (EXISTS, SUBSTANTIVE, WIRED). Use when checking if built code matches what was planned, validating phase completion, or auditing implementation quality."
|
|
40
|
+
};
|
|
41
|
+
var DEFAULT_TOOLS = ["Bash", "Read", "Write", "Edit", "Glob", "Grep"];
|
|
42
|
+
var GEMINI_TOOL_MAP = {
|
|
43
|
+
Bash: "run_shell_command",
|
|
44
|
+
Read: "read_file",
|
|
45
|
+
Write: "write_file",
|
|
46
|
+
Edit: "replace",
|
|
47
|
+
Glob: "glob",
|
|
48
|
+
Grep: "search_file_content"
|
|
49
|
+
};
|
|
50
|
+
function generateAgentDefinition(persona, skillContents) {
|
|
51
|
+
const kebabName = toKebabCase(persona.name);
|
|
52
|
+
const name = `harness-${kebabName}`;
|
|
53
|
+
const description = AGENT_DESCRIPTIONS[kebabName] ?? persona.description;
|
|
54
|
+
const methodologyParts = [];
|
|
55
|
+
for (const skillName of persona.skills) {
|
|
56
|
+
const content = skillContents.get(skillName);
|
|
57
|
+
if (content) {
|
|
58
|
+
methodologyParts.push(content);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
name,
|
|
63
|
+
description,
|
|
64
|
+
tools: [...DEFAULT_TOOLS],
|
|
65
|
+
role: persona.role,
|
|
66
|
+
skills: persona.skills,
|
|
67
|
+
steps: persona.steps,
|
|
68
|
+
methodology: methodologyParts.join("\n\n---\n\n")
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/agent-definitions/render-claude-code.ts
|
|
73
|
+
function formatStep(step, index) {
|
|
74
|
+
if ("command" in step && step.command) {
|
|
75
|
+
const cmd = step.command;
|
|
76
|
+
const when = step.when ?? "always";
|
|
77
|
+
return `${index + 1}. Run \`harness ${cmd}\` (${when})`;
|
|
78
|
+
}
|
|
79
|
+
if ("skill" in step && step.skill) {
|
|
80
|
+
const skill = step.skill;
|
|
81
|
+
const when = step.when ?? "always";
|
|
82
|
+
return `${index + 1}. Execute ${skill} skill (${when})`;
|
|
83
|
+
}
|
|
84
|
+
return `${index + 1}. Unknown step`;
|
|
85
|
+
}
|
|
86
|
+
function renderClaudeCodeAgent(def) {
|
|
87
|
+
const lines = ["---"];
|
|
88
|
+
lines.push(`name: ${def.name}`);
|
|
89
|
+
lines.push(`description: >`);
|
|
90
|
+
lines.push(` ${def.description}`);
|
|
91
|
+
lines.push(`tools: ${def.tools.join(", ")}`);
|
|
92
|
+
lines.push("---");
|
|
93
|
+
lines.push("");
|
|
94
|
+
lines.push(GENERATED_HEADER_AGENT);
|
|
95
|
+
lines.push("");
|
|
96
|
+
lines.push("## Role");
|
|
97
|
+
lines.push("");
|
|
98
|
+
lines.push(def.role);
|
|
99
|
+
lines.push("");
|
|
100
|
+
lines.push("## Skills");
|
|
101
|
+
lines.push("");
|
|
102
|
+
for (const skill of def.skills) {
|
|
103
|
+
lines.push(`- ${skill}`);
|
|
104
|
+
}
|
|
105
|
+
lines.push("");
|
|
106
|
+
lines.push("## Steps");
|
|
107
|
+
lines.push("");
|
|
108
|
+
def.steps.forEach((step, i) => {
|
|
109
|
+
lines.push(formatStep(step, i));
|
|
110
|
+
});
|
|
111
|
+
lines.push("");
|
|
112
|
+
if (def.methodology) {
|
|
113
|
+
lines.push("## Methodology");
|
|
114
|
+
lines.push("");
|
|
115
|
+
lines.push(def.methodology);
|
|
116
|
+
lines.push("");
|
|
117
|
+
}
|
|
118
|
+
return lines.join("\n");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/agent-definitions/render-gemini-cli.ts
|
|
122
|
+
function toGeminiToolName(tool) {
|
|
123
|
+
return GEMINI_TOOL_MAP[tool] ?? tool;
|
|
124
|
+
}
|
|
125
|
+
function formatStep2(step, index) {
|
|
126
|
+
if ("command" in step && step.command) {
|
|
127
|
+
const cmd = step.command;
|
|
128
|
+
const when = step.when ?? "always";
|
|
129
|
+
return `${index + 1}. Run \`harness ${cmd}\` (${when})`;
|
|
130
|
+
}
|
|
131
|
+
if ("skill" in step && step.skill) {
|
|
132
|
+
const skill = step.skill;
|
|
133
|
+
const when = step.when ?? "always";
|
|
134
|
+
return `${index + 1}. Execute ${skill} skill (${when})`;
|
|
135
|
+
}
|
|
136
|
+
return `${index + 1}. Unknown step`;
|
|
137
|
+
}
|
|
138
|
+
function renderGeminiAgent(def) {
|
|
139
|
+
const lines = ["---"];
|
|
140
|
+
lines.push(`name: ${def.name}`);
|
|
141
|
+
lines.push(`description: >`);
|
|
142
|
+
lines.push(` ${def.description}`);
|
|
143
|
+
if (def.tools.length > 0) {
|
|
144
|
+
lines.push("tools:");
|
|
145
|
+
for (const tool of def.tools) {
|
|
146
|
+
lines.push(` - ${toGeminiToolName(tool)}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
lines.push("---");
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push(GENERATED_HEADER_AGENT);
|
|
152
|
+
lines.push("");
|
|
153
|
+
lines.push("## Role");
|
|
154
|
+
lines.push("");
|
|
155
|
+
lines.push(def.role);
|
|
156
|
+
lines.push("");
|
|
157
|
+
lines.push("## Skills");
|
|
158
|
+
lines.push("");
|
|
159
|
+
for (const skill of def.skills) {
|
|
160
|
+
lines.push(`- ${skill}`);
|
|
161
|
+
}
|
|
162
|
+
lines.push("");
|
|
163
|
+
lines.push("## Steps");
|
|
164
|
+
lines.push("");
|
|
165
|
+
def.steps.forEach((step, i) => {
|
|
166
|
+
lines.push(formatStep2(step, i));
|
|
167
|
+
});
|
|
168
|
+
lines.push("");
|
|
169
|
+
if (def.methodology) {
|
|
170
|
+
lines.push("## Methodology");
|
|
171
|
+
lines.push("");
|
|
172
|
+
lines.push(def.methodology);
|
|
173
|
+
lines.push("");
|
|
174
|
+
}
|
|
175
|
+
return lines.join("\n");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/commands/generate-agent-definitions.ts
|
|
179
|
+
function resolveOutputDir(platform, opts) {
|
|
180
|
+
if (opts.output) {
|
|
181
|
+
return platform === "claude-code" ? path.join(opts.output, "claude-code") : path.join(opts.output, "gemini-cli");
|
|
182
|
+
}
|
|
183
|
+
if (opts.global) {
|
|
184
|
+
const home = os.homedir();
|
|
185
|
+
return platform === "claude-code" ? path.join(home, ".claude", "agents") : path.join(home, ".gemini", "agents");
|
|
186
|
+
}
|
|
187
|
+
return platform === "claude-code" ? path.join("agents", "agents", "claude-code") : path.join("agents", "agents", "gemini-cli");
|
|
188
|
+
}
|
|
189
|
+
function loadSkillContent(skillName) {
|
|
190
|
+
const skillsDir = resolveSkillsDir();
|
|
191
|
+
const skillMdPath = path.join(skillsDir, skillName, "SKILL.md");
|
|
192
|
+
if (!fs.existsSync(skillMdPath)) return null;
|
|
193
|
+
return fs.readFileSync(skillMdPath, "utf-8");
|
|
194
|
+
}
|
|
195
|
+
function getRenderer(platform) {
|
|
196
|
+
return platform === "claude-code" ? renderClaudeCodeAgent : renderGeminiAgent;
|
|
197
|
+
}
|
|
198
|
+
function generateAgentDefinitions(opts) {
|
|
199
|
+
const personasDir = resolvePersonasDir();
|
|
200
|
+
const personaList = listPersonas(personasDir);
|
|
201
|
+
if (!personaList.ok) return [];
|
|
202
|
+
const personas = personaList.value.map((meta) => loadPersona(meta.filePath)).filter((r) => r.ok).map((r) => r.value);
|
|
203
|
+
const allSkillNames = new Set(personas.flatMap((p) => p.skills));
|
|
204
|
+
const skillContents = /* @__PURE__ */ new Map();
|
|
205
|
+
for (const skillName of allSkillNames) {
|
|
206
|
+
const content = loadSkillContent(skillName);
|
|
207
|
+
if (content) {
|
|
208
|
+
skillContents.set(skillName, content);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const definitions = personas.map((p) => generateAgentDefinition(p, skillContents));
|
|
212
|
+
const results = [];
|
|
213
|
+
for (const platform of opts.platforms) {
|
|
214
|
+
const outputDir = resolveOutputDir(platform, opts);
|
|
215
|
+
const renderer = getRenderer(platform);
|
|
216
|
+
const rendered = /* @__PURE__ */ new Map();
|
|
217
|
+
for (const def of definitions) {
|
|
218
|
+
const filename = `${def.name}.md`;
|
|
219
|
+
rendered.set(filename, renderer(def));
|
|
220
|
+
}
|
|
221
|
+
const plan = computeSyncPlan(outputDir, rendered);
|
|
222
|
+
if (!opts.dryRun) {
|
|
223
|
+
applySyncPlan(outputDir, rendered, plan, false);
|
|
224
|
+
}
|
|
225
|
+
results.push({
|
|
226
|
+
platform,
|
|
227
|
+
added: plan.added,
|
|
228
|
+
updated: plan.updated,
|
|
229
|
+
removed: plan.removed,
|
|
230
|
+
unchanged: plan.unchanged,
|
|
231
|
+
outputDir
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return results;
|
|
235
|
+
}
|
|
236
|
+
function createGenerateAgentDefinitionsCommand() {
|
|
237
|
+
return new Command("generate-agent-definitions").description("Generate agent definition files from personas for Claude Code and Gemini CLI").option("--platforms <list>", "Target platforms (comma-separated)", "claude-code,gemini-cli").option("--global", "Write to global agent directories", false).option("--output <dir>", "Custom output directory").option("--dry-run", "Show what would change without writing", false).action(async (opts, cmd) => {
|
|
238
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
239
|
+
const platforms = opts.platforms.split(",").map((p) => p.trim());
|
|
240
|
+
for (const p of platforms) {
|
|
241
|
+
if (!VALID_PLATFORMS.includes(p)) {
|
|
242
|
+
throw new CLIError(
|
|
243
|
+
`Invalid platform "${p}". Valid platforms: ${VALID_PLATFORMS.join(", ")}`,
|
|
244
|
+
ExitCode.VALIDATION_FAILED
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
const results = generateAgentDefinitions({
|
|
250
|
+
platforms,
|
|
251
|
+
global: opts.global,
|
|
252
|
+
output: opts.output,
|
|
253
|
+
dryRun: opts.dryRun
|
|
254
|
+
});
|
|
255
|
+
if (globalOpts.json) {
|
|
256
|
+
console.log(JSON.stringify(results, null, 2));
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
for (const result of results) {
|
|
260
|
+
console.log(`
|
|
261
|
+
${result.platform} \u2192 ${result.outputDir}`);
|
|
262
|
+
if (result.added.length > 0) {
|
|
263
|
+
console.log(` + ${result.added.length} new: ${result.added.join(", ")}`);
|
|
264
|
+
}
|
|
265
|
+
if (result.updated.length > 0) {
|
|
266
|
+
console.log(` ~ ${result.updated.length} updated: ${result.updated.join(", ")}`);
|
|
267
|
+
}
|
|
268
|
+
if (result.removed.length > 0) {
|
|
269
|
+
console.log(` - ${result.removed.length} removed: ${result.removed.join(", ")}`);
|
|
270
|
+
}
|
|
271
|
+
if (result.unchanged.length > 0) {
|
|
272
|
+
console.log(` = ${result.unchanged.length} unchanged`);
|
|
273
|
+
}
|
|
274
|
+
if (opts.dryRun) {
|
|
275
|
+
console.log(" (dry run \u2014 no files written)");
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
handleError(error);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export {
|
|
285
|
+
AGENT_DESCRIPTIONS,
|
|
286
|
+
DEFAULT_TOOLS,
|
|
287
|
+
GEMINI_TOOL_MAP,
|
|
288
|
+
generateAgentDefinition,
|
|
289
|
+
renderClaudeCodeAgent,
|
|
290
|
+
renderGeminiAgent,
|
|
291
|
+
generateAgentDefinitions,
|
|
292
|
+
createGenerateAgentDefinitionsCommand
|
|
293
|
+
};
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resultToMcpResponse
|
|
3
|
+
} from "./chunk-IDZNPTYD.js";
|
|
4
|
+
import {
|
|
5
|
+
sanitizePath
|
|
6
|
+
} from "./chunk-W6Y7ZW3Y.js";
|
|
7
|
+
|
|
8
|
+
// src/mcp/tools/feedback.ts
|
|
9
|
+
var createSelfReviewDefinition = {
|
|
10
|
+
name: "create_self_review",
|
|
11
|
+
description: "Generate a checklist-based code review from a git diff, checking harness constraints, custom rules, and diff patterns",
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: "object",
|
|
14
|
+
properties: {
|
|
15
|
+
path: { type: "string", description: "Path to project root" },
|
|
16
|
+
diff: { type: "string", description: "Git diff string to review" },
|
|
17
|
+
customRules: {
|
|
18
|
+
type: "array",
|
|
19
|
+
items: { type: "object" },
|
|
20
|
+
description: "Optional custom rules to apply during review"
|
|
21
|
+
},
|
|
22
|
+
maxFileSize: {
|
|
23
|
+
type: "number",
|
|
24
|
+
description: "Maximum number of lines changed per file before flagging"
|
|
25
|
+
},
|
|
26
|
+
maxFileCount: {
|
|
27
|
+
type: "number",
|
|
28
|
+
description: "Maximum number of changed files before flagging"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
required: ["path", "diff"]
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
async function handleCreateSelfReview(input) {
|
|
35
|
+
try {
|
|
36
|
+
const { parseDiff, createSelfReview } = await import("./dist-PBTNVK6K.js");
|
|
37
|
+
const parseResult = parseDiff(input.diff);
|
|
38
|
+
if (!parseResult.ok) {
|
|
39
|
+
return resultToMcpResponse(parseResult);
|
|
40
|
+
}
|
|
41
|
+
const projectPath = sanitizePath(input.path);
|
|
42
|
+
const config = {
|
|
43
|
+
rootDir: projectPath,
|
|
44
|
+
harness: {
|
|
45
|
+
context: true,
|
|
46
|
+
constraints: true,
|
|
47
|
+
entropy: true
|
|
48
|
+
},
|
|
49
|
+
...input.customRules ? { customRules: input.customRules } : {},
|
|
50
|
+
diffAnalysis: {
|
|
51
|
+
enabled: true,
|
|
52
|
+
...input.maxFileSize !== void 0 ? { maxFileSize: input.maxFileSize } : {},
|
|
53
|
+
...input.maxFileCount !== void 0 ? { maxChangedFiles: input.maxFileCount } : {}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const { loadGraphStore } = await import("./graph-loader-RLO3KRIX.js");
|
|
57
|
+
const store = await loadGraphStore(projectPath);
|
|
58
|
+
let graphData;
|
|
59
|
+
if (store) {
|
|
60
|
+
const { GraphFeedbackAdapter } = await import("./dist-I7DB5VKB.js");
|
|
61
|
+
const adapter = new GraphFeedbackAdapter(store);
|
|
62
|
+
const changedFiles = parseResult.value.files.map((f) => f.path);
|
|
63
|
+
const impact = adapter.computeImpactData(changedFiles);
|
|
64
|
+
const harness = adapter.computeHarnessCheckData();
|
|
65
|
+
graphData = {
|
|
66
|
+
impact: {
|
|
67
|
+
affectedTests: [...impact.affectedTests],
|
|
68
|
+
affectedDocs: [...impact.affectedDocs],
|
|
69
|
+
impactScope: impact.impactScope
|
|
70
|
+
},
|
|
71
|
+
harness: { ...harness }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const result = await createSelfReview(
|
|
75
|
+
parseResult.value,
|
|
76
|
+
config,
|
|
77
|
+
graphData
|
|
78
|
+
);
|
|
79
|
+
return resultToMcpResponse(result);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text",
|
|
85
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
isError: true
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
var analyzeDiffDefinition = {
|
|
93
|
+
name: "analyze_diff",
|
|
94
|
+
description: "Parse a git diff and check for forbidden patterns, oversized files, and missing test coverage",
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: "object",
|
|
97
|
+
properties: {
|
|
98
|
+
diff: { type: "string", description: "Git diff string to analyze" },
|
|
99
|
+
path: {
|
|
100
|
+
type: "string",
|
|
101
|
+
description: "Path to project root (enables graph-enhanced analysis)"
|
|
102
|
+
},
|
|
103
|
+
forbiddenPatterns: {
|
|
104
|
+
type: "array",
|
|
105
|
+
items: { type: "string" },
|
|
106
|
+
description: "List of regex patterns that are forbidden in the diff"
|
|
107
|
+
},
|
|
108
|
+
maxFileSize: {
|
|
109
|
+
type: "number",
|
|
110
|
+
description: "Maximum number of lines changed per file before flagging"
|
|
111
|
+
},
|
|
112
|
+
maxFileCount: {
|
|
113
|
+
type: "number",
|
|
114
|
+
description: "Maximum number of changed files before flagging"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
required: ["diff"]
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
async function handleAnalyzeDiff(input) {
|
|
121
|
+
try {
|
|
122
|
+
const { parseDiff, analyzeDiff } = await import("./dist-PBTNVK6K.js");
|
|
123
|
+
const parseResult = parseDiff(input.diff);
|
|
124
|
+
if (!parseResult.ok) {
|
|
125
|
+
return resultToMcpResponse(parseResult);
|
|
126
|
+
}
|
|
127
|
+
const options = {
|
|
128
|
+
enabled: true,
|
|
129
|
+
...input.forbiddenPatterns ? {
|
|
130
|
+
forbiddenPatterns: input.forbiddenPatterns.map((pattern) => ({
|
|
131
|
+
pattern,
|
|
132
|
+
message: `Forbidden pattern matched: ${pattern}`,
|
|
133
|
+
severity: "warning"
|
|
134
|
+
}))
|
|
135
|
+
} : {},
|
|
136
|
+
...input.maxFileSize !== void 0 ? { maxFileSize: input.maxFileSize } : {},
|
|
137
|
+
...input.maxFileCount !== void 0 ? { maxChangedFiles: input.maxFileCount } : {}
|
|
138
|
+
};
|
|
139
|
+
let graphImpactData;
|
|
140
|
+
if (input.path) {
|
|
141
|
+
try {
|
|
142
|
+
const { loadGraphStore } = await import("./graph-loader-RLO3KRIX.js");
|
|
143
|
+
const store = await loadGraphStore(sanitizePath(input.path));
|
|
144
|
+
if (store) {
|
|
145
|
+
const { GraphFeedbackAdapter } = await import("./dist-I7DB5VKB.js");
|
|
146
|
+
const adapter = new GraphFeedbackAdapter(store);
|
|
147
|
+
const changedFiles = parseResult.value.files.map((f) => f.path);
|
|
148
|
+
const impact = adapter.computeImpactData(changedFiles);
|
|
149
|
+
graphImpactData = {
|
|
150
|
+
affectedTests: [...impact.affectedTests],
|
|
151
|
+
affectedDocs: [...impact.affectedDocs],
|
|
152
|
+
impactScope: impact.impactScope
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const result = await analyzeDiff(parseResult.value, options, graphImpactData);
|
|
159
|
+
return resultToMcpResponse(result);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{
|
|
164
|
+
type: "text",
|
|
165
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
166
|
+
}
|
|
167
|
+
],
|
|
168
|
+
isError: true
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
var requestPeerReviewDefinition = {
|
|
173
|
+
name: "request_peer_review",
|
|
174
|
+
description: "Spawn an agent subprocess to perform code review. Returns structured feedback with approval status. Timeout: 120 seconds.",
|
|
175
|
+
inputSchema: {
|
|
176
|
+
type: "object",
|
|
177
|
+
properties: {
|
|
178
|
+
path: { type: "string", description: "Path to project root" },
|
|
179
|
+
agentType: {
|
|
180
|
+
type: "string",
|
|
181
|
+
enum: [
|
|
182
|
+
"architecture-enforcer",
|
|
183
|
+
"documentation-maintainer",
|
|
184
|
+
"test-reviewer",
|
|
185
|
+
"entropy-cleaner",
|
|
186
|
+
"custom"
|
|
187
|
+
],
|
|
188
|
+
description: "Type of agent to use for the peer review"
|
|
189
|
+
},
|
|
190
|
+
diff: { type: "string", description: "Git diff string to review" },
|
|
191
|
+
context: { type: "string", description: "Optional additional context for the reviewer" }
|
|
192
|
+
},
|
|
193
|
+
required: ["path", "agentType", "diff"]
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
async function handleRequestPeerReview(input) {
|
|
197
|
+
try {
|
|
198
|
+
const { parseDiff, requestPeerReview } = await import("./dist-PBTNVK6K.js");
|
|
199
|
+
const parseResult = parseDiff(input.diff);
|
|
200
|
+
if (!parseResult.ok) {
|
|
201
|
+
return resultToMcpResponse(parseResult);
|
|
202
|
+
}
|
|
203
|
+
const reviewContext = {
|
|
204
|
+
files: parseResult.value.files.map((f) => f.path),
|
|
205
|
+
diff: input.diff,
|
|
206
|
+
...input.context ? { metadata: { context: input.context } } : {}
|
|
207
|
+
};
|
|
208
|
+
try {
|
|
209
|
+
const { loadGraphStore } = await import("./graph-loader-RLO3KRIX.js");
|
|
210
|
+
const store = await loadGraphStore(sanitizePath(input.path));
|
|
211
|
+
if (store) {
|
|
212
|
+
const { GraphFeedbackAdapter } = await import("./dist-I7DB5VKB.js");
|
|
213
|
+
const adapter = new GraphFeedbackAdapter(store);
|
|
214
|
+
const changedFiles = parseResult.value.files.map((f) => f.path);
|
|
215
|
+
const impactData = adapter.computeImpactData(changedFiles);
|
|
216
|
+
reviewContext.metadata = {
|
|
217
|
+
...reviewContext.metadata,
|
|
218
|
+
graphContext: impactData
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
}
|
|
223
|
+
const result = await requestPeerReview(input.agentType, reviewContext, {
|
|
224
|
+
timeout: 12e4,
|
|
225
|
+
wait: true
|
|
226
|
+
});
|
|
227
|
+
return resultToMcpResponse(result);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
return {
|
|
230
|
+
content: [
|
|
231
|
+
{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
isError: true
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export {
|
|
242
|
+
createSelfReviewDefinition,
|
|
243
|
+
handleCreateSelfReview,
|
|
244
|
+
analyzeDiffDefinition,
|
|
245
|
+
handleAnalyzeDiff,
|
|
246
|
+
requestPeerReviewDefinition,
|
|
247
|
+
handleRequestPeerReview
|
|
248
|
+
};
|