@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.
Files changed (92) hide show
  1. package/dist/agents/skills/claude-code/cleanup-dead-code/SKILL.md +3 -3
  2. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +20 -3
  3. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +55 -5
  4. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +36 -15
  5. package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +1 -1
  6. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +70 -13
  7. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +41 -3
  8. package/dist/agents/skills/claude-code/harness-pre-commit-review/SKILL.md +28 -3
  9. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +14 -2
  10. package/dist/agents/skills/claude-code/harness-verification/SKILL.md +18 -2
  11. package/dist/agents/skills/gemini-cli/cleanup-dead-code/SKILL.md +3 -3
  12. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +20 -3
  13. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +55 -5
  14. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +36 -15
  15. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +1 -1
  16. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +70 -13
  17. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +41 -3
  18. package/dist/agents/skills/gemini-cli/harness-pre-commit-review/SKILL.md +28 -3
  19. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +14 -2
  20. package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +18 -2
  21. package/dist/agents-md-EMRFLNBC.js +8 -0
  22. package/dist/architecture-5JNN5L3M.js +13 -0
  23. package/dist/bin/harness-mcp.d.ts +1 -0
  24. package/dist/bin/harness-mcp.js +28 -0
  25. package/dist/bin/harness.js +42 -8
  26. package/dist/check-phase-gate-WOKIYGAM.js +12 -0
  27. package/dist/chunk-46YA6FI3.js +293 -0
  28. package/dist/chunk-4PFMY3H7.js +248 -0
  29. package/dist/{chunk-LB4GRDDV.js → chunk-72GHBOL2.js} +1 -1
  30. package/dist/chunk-7X7ZAYMY.js +373 -0
  31. package/dist/chunk-B7HFEHWP.js +35 -0
  32. package/dist/chunk-BM3PWGXQ.js +14 -0
  33. package/dist/chunk-C2ERUR3L.js +255 -0
  34. package/dist/chunk-CWZ4Y2PO.js +189 -0
  35. package/dist/{chunk-ULSRSP53.js → chunk-ECUJQS3B.js} +11 -112
  36. package/dist/chunk-EOLRW32Q.js +72 -0
  37. package/dist/chunk-F3YDAJFQ.js +125 -0
  38. package/dist/chunk-F4PTVZWA.js +116 -0
  39. package/dist/chunk-FPIPT36X.js +187 -0
  40. package/dist/chunk-FX7SQHGD.js +103 -0
  41. package/dist/chunk-HIOXKZYF.js +15 -0
  42. package/dist/chunk-IDZNPTYD.js +16 -0
  43. package/dist/chunk-JSTQ3AWB.js +31 -0
  44. package/dist/chunk-K6XAPGML.js +27 -0
  45. package/dist/chunk-KET4QQZB.js +8 -0
  46. package/dist/chunk-LXU5M77O.js +4028 -0
  47. package/dist/chunk-MDUK2J2O.js +67 -0
  48. package/dist/chunk-MHBMTPW7.js +29 -0
  49. package/dist/chunk-MO4YQOMB.js +85 -0
  50. package/dist/chunk-NKDM3FMH.js +52 -0
  51. package/dist/{chunk-SAB3VXOW.js → chunk-NX6DSZSM.js} +144 -111
  52. package/dist/chunk-OPXH4CQN.js +62 -0
  53. package/dist/{chunk-Y7U5AYAL.js → chunk-PAHHT2IK.js} +471 -2719
  54. package/dist/chunk-PMTFPOCT.js +122 -0
  55. package/dist/chunk-PSXF277V.js +89 -0
  56. package/dist/chunk-Q6AB7W5Z.js +135 -0
  57. package/dist/chunk-QPEH2QPG.js +347 -0
  58. package/dist/chunk-TEFCFC4H.js +15 -0
  59. package/dist/chunk-TRAPF4IX.js +185 -0
  60. package/dist/chunk-VUCPTQ6G.js +67 -0
  61. package/dist/chunk-W6Y7ZW3Y.js +13 -0
  62. package/dist/chunk-ZOAWBDWU.js +72 -0
  63. package/dist/ci-workflow-ZBBUNTHQ.js +8 -0
  64. package/dist/constants-5JGUXPEK.js +6 -0
  65. package/dist/create-skill-LUWO46WF.js +11 -0
  66. package/dist/dist-D4RYGUZE.js +14 -0
  67. package/dist/{dist-K6KTTN3I.js → dist-I7DB5VKB.js} +237 -0
  68. package/dist/dist-L7LAAQAS.js +18 -0
  69. package/dist/{dist-ZODQVGC4.js → dist-PBTNVK6K.js} +8 -6
  70. package/dist/docs-PTJGD6XI.js +12 -0
  71. package/dist/engine-SCMZ3G3E.js +8 -0
  72. package/dist/entropy-YIUBGKY7.js +12 -0
  73. package/dist/feedback-WEVQSLAA.js +18 -0
  74. package/dist/generate-agent-definitions-BU5LOJTI.js +15 -0
  75. package/dist/glob-helper-5OHBUQAI.js +52 -0
  76. package/dist/graph-loader-RLO3KRIX.js +8 -0
  77. package/dist/index.d.ts +11 -1
  78. package/dist/index.js +84 -33
  79. package/dist/loader-6S6PVGSF.js +10 -0
  80. package/dist/mcp-BNLBTCXZ.js +34 -0
  81. package/dist/performance-5TVW6SA6.js +24 -0
  82. package/dist/review-pipeline-4JTQAWKW.js +9 -0
  83. package/dist/runner-VMYLHWOC.js +6 -0
  84. package/dist/runtime-PXIM7UV6.js +9 -0
  85. package/dist/security-URYTKLGK.js +9 -0
  86. package/dist/skill-executor-KVS47DAU.js +8 -0
  87. package/dist/validate-KSDUUK2M.js +12 -0
  88. package/dist/validate-cross-check-WZAX357V.js +8 -0
  89. package/dist/version-KFFPOQAX.js +6 -0
  90. package/package.json +7 -5
  91. package/dist/create-skill-UZOHMXRU.js +0 -8
  92. package/dist/validate-cross-check-DLNK423G.js +0 -7
@@ -0,0 +1,189 @@
1
+ import {
2
+ resultToMcpResponse
3
+ } from "./chunk-IDZNPTYD.js";
4
+ import {
5
+ sanitizePath
6
+ } from "./chunk-W6Y7ZW3Y.js";
7
+ import {
8
+ Ok
9
+ } from "./chunk-MHBMTPW7.js";
10
+
11
+ // src/mcp/tools/entropy.ts
12
+ async function loadEntropyGraphOptions(projectPath) {
13
+ const { loadGraphStore } = await import("./graph-loader-RLO3KRIX.js");
14
+ const store = await loadGraphStore(projectPath);
15
+ if (!store) return void 0;
16
+ const { GraphEntropyAdapter } = await import("./dist-I7DB5VKB.js");
17
+ const adapter = new GraphEntropyAdapter(store);
18
+ const driftData = adapter.computeDriftData();
19
+ const deadCodeData = adapter.computeDeadCodeData();
20
+ return {
21
+ graphDriftData: {
22
+ staleEdges: driftData.staleEdges.map((e) => ({
23
+ docNodeId: e.docNodeId,
24
+ codeNodeId: e.codeNodeId,
25
+ edgeType: e.edgeType
26
+ })),
27
+ missingTargets: [...driftData.missingTargets]
28
+ },
29
+ graphDeadCodeData: {
30
+ reachableNodeIds: new Set(deadCodeData.reachableNodeIds),
31
+ unreachableNodes: deadCodeData.unreachableNodes.map((n) => ({
32
+ id: n.id,
33
+ type: n.type,
34
+ name: n.name,
35
+ ...n.path !== void 0 && { path: n.path }
36
+ }))
37
+ }
38
+ };
39
+ }
40
+ var detectEntropyDefinition = {
41
+ name: "detect_entropy",
42
+ description: "Detect documentation drift, dead code, and pattern violations. Optionally auto-fix detected issues.",
43
+ inputSchema: {
44
+ type: "object",
45
+ properties: {
46
+ path: { type: "string", description: "Path to project root" },
47
+ type: {
48
+ type: "string",
49
+ enum: ["drift", "dead-code", "patterns", "all"],
50
+ description: "Type of entropy to detect (default: all)"
51
+ },
52
+ autoFix: {
53
+ type: "boolean",
54
+ description: "When true, apply fixes after analysis. Default: false (analysis only)"
55
+ },
56
+ dryRun: {
57
+ type: "boolean",
58
+ description: "Preview fixes without applying (only used when autoFix is true)"
59
+ },
60
+ fixTypes: {
61
+ type: "array",
62
+ items: {
63
+ type: "string",
64
+ enum: [
65
+ "unused-imports",
66
+ "dead-files",
67
+ "dead-exports",
68
+ "commented-code",
69
+ "orphaned-deps",
70
+ "forbidden-import-replacement",
71
+ "import-ordering"
72
+ ]
73
+ },
74
+ description: "Specific fix types to apply (default: all safe types). Only used when autoFix is true."
75
+ },
76
+ mode: {
77
+ type: "string",
78
+ enum: ["summary", "detailed"],
79
+ description: "Response density: summary returns issue counts and top issues per category, detailed returns full findings. Default: detailed"
80
+ }
81
+ },
82
+ required: ["path"]
83
+ }
84
+ };
85
+ async function handleDetectEntropy(input) {
86
+ try {
87
+ const { EntropyAnalyzer } = await import("./dist-PBTNVK6K.js");
88
+ const typeFilter = input.type ?? "all";
89
+ const analyzer = new EntropyAnalyzer({
90
+ rootDir: sanitizePath(input.path),
91
+ analyze: {
92
+ drift: typeFilter === "all" || typeFilter === "drift",
93
+ deadCode: typeFilter === "all" || typeFilter === "dead-code",
94
+ patterns: typeFilter === "all" || typeFilter === "patterns"
95
+ }
96
+ });
97
+ const graphOptions = await loadEntropyGraphOptions(sanitizePath(input.path));
98
+ const result = await analyzer.analyze(graphOptions);
99
+ if (input.mode === "summary" && result.ok && !input.autoFix) {
100
+ const report2 = result.value;
101
+ const summary = {};
102
+ if (report2.drift) {
103
+ const driftIssues = (report2.drift.drifts ?? []).map(
104
+ (d) => `Drift: ${d.type}${d.file ? ` in ${d.file}` : ""}`
105
+ );
106
+ summary["drift"] = {
107
+ issueCount: driftIssues.length,
108
+ topIssues: driftIssues.slice(0, 3)
109
+ };
110
+ }
111
+ if (report2.deadCode) {
112
+ const deadIssues = [
113
+ ...(report2.deadCode.unusedImports ?? []).map(
114
+ (i) => `Unused import: ${i.specifiers.join(", ")} from ${i.source}`
115
+ ),
116
+ ...(report2.deadCode.deadExports ?? []).map((e) => `Dead export: ${e.name} in ${e.file}`),
117
+ ...(report2.deadCode.deadFiles ?? []).map((f) => `Dead file: ${f.path}`)
118
+ ];
119
+ summary["deadCode"] = {
120
+ issueCount: deadIssues.length,
121
+ topIssues: deadIssues.slice(0, 3)
122
+ };
123
+ }
124
+ if (report2.patterns) {
125
+ const patternIssues = (report2.patterns.violations ?? []).map(
126
+ (v) => `${v.pattern}: ${v.file}`
127
+ );
128
+ summary["patterns"] = {
129
+ issueCount: patternIssues.length,
130
+ topIssues: patternIssues.slice(0, 3)
131
+ };
132
+ }
133
+ const totalIssues = Object.values(summary).reduce((s, c) => s + c.issueCount, 0);
134
+ return {
135
+ content: [
136
+ {
137
+ type: "text",
138
+ text: JSON.stringify({ mode: "summary", totalIssues, categories: summary })
139
+ }
140
+ ]
141
+ };
142
+ }
143
+ if (!input.autoFix) {
144
+ return resultToMcpResponse(result);
145
+ }
146
+ if (!result.ok) return resultToMcpResponse(result);
147
+ const { createFixes, applyFixes, generateSuggestions } = await import("./dist-PBTNVK6K.js");
148
+ const report = result.value;
149
+ const deadCode = report.deadCode;
150
+ const fixTypesConfig = input.fixTypes ? { fixTypes: input.fixTypes } : void 0;
151
+ const fixes = deadCode ? createFixes(deadCode, fixTypesConfig) : [];
152
+ const suggestions = generateSuggestions(report.deadCode, report.drift, report.patterns);
153
+ if (input.dryRun) {
154
+ return {
155
+ content: [
156
+ { type: "text", text: JSON.stringify({ analysis: report, fixes, suggestions }) }
157
+ ]
158
+ };
159
+ }
160
+ if (fixes.length > 0) {
161
+ const applied = await applyFixes(fixes, {});
162
+ if (!applied.ok) return resultToMcpResponse(applied);
163
+ return {
164
+ content: [
165
+ {
166
+ type: "text",
167
+ text: JSON.stringify({ analysis: report, ...applied.value, suggestions })
168
+ }
169
+ ]
170
+ };
171
+ }
172
+ return resultToMcpResponse(Ok({ analysis: report, fixes: [], applied: 0, suggestions }));
173
+ } catch (error) {
174
+ return {
175
+ content: [
176
+ {
177
+ type: "text",
178
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`
179
+ }
180
+ ],
181
+ isError: true
182
+ };
183
+ }
184
+ }
185
+
186
+ export {
187
+ detectEntropyDefinition,
188
+ handleDetectEntropy
189
+ };
@@ -1,115 +1,19 @@
1
+ import {
2
+ logger
3
+ } from "./chunk-HIOXKZYF.js";
4
+ import {
5
+ CLIError,
6
+ ExitCode
7
+ } from "./chunk-B7HFEHWP.js";
8
+ import {
9
+ ALLOWED_COGNITIVE_MODES
10
+ } from "./chunk-MDUK2J2O.js";
11
+
1
12
  // src/commands/create-skill.ts
2
13
  import { Command } from "commander";
3
14
  import * as path from "path";
4
15
  import * as fs from "fs";
5
16
  import YAML from "yaml";
6
-
7
- // src/skill/schema.ts
8
- import { z } from "zod";
9
- var SkillPhaseSchema = z.object({
10
- name: z.string(),
11
- description: z.string(),
12
- required: z.boolean().default(true)
13
- });
14
- var SkillCliSchema = z.object({
15
- command: z.string(),
16
- args: z.array(
17
- z.object({
18
- name: z.string(),
19
- description: z.string(),
20
- required: z.boolean().default(false)
21
- })
22
- ).default([])
23
- });
24
- var SkillMcpSchema = z.object({
25
- tool: z.string(),
26
- input: z.record(z.string())
27
- });
28
- var SkillStateSchema = z.object({
29
- persistent: z.boolean().default(false),
30
- files: z.array(z.string()).default([])
31
- });
32
- var ALLOWED_TRIGGERS = [
33
- "manual",
34
- "on_pr",
35
- "on_commit",
36
- "on_new_feature",
37
- "on_bug_fix",
38
- "on_refactor",
39
- "on_project_init",
40
- "on_review",
41
- "on_milestone",
42
- "on_task_complete",
43
- "on_doc_check"
44
- ];
45
- var ALLOWED_PLATFORMS = ["claude-code", "gemini-cli"];
46
- var ALLOWED_COGNITIVE_MODES = [
47
- "adversarial-reviewer",
48
- "constructive-architect",
49
- "meticulous-implementer",
50
- "diagnostic-investigator",
51
- "advisory-guide",
52
- "meticulous-verifier"
53
- ];
54
- var SkillMetadataSchema = z.object({
55
- name: z.string().regex(/^[a-z][a-z0-9-]*$/, "Name must be lowercase with hyphens"),
56
- version: z.string().regex(/^\d+\.\d+\.\d+$/, "Version must be semver format"),
57
- description: z.string(),
58
- cognitive_mode: z.string().regex(/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, "Cognitive mode must be kebab-case").optional(),
59
- triggers: z.array(z.enum(ALLOWED_TRIGGERS)),
60
- platforms: z.array(z.enum(ALLOWED_PLATFORMS)),
61
- tools: z.array(z.string()),
62
- cli: SkillCliSchema.optional(),
63
- mcp: SkillMcpSchema.optional(),
64
- type: z.enum(["rigid", "flexible"]),
65
- phases: z.array(SkillPhaseSchema).optional(),
66
- state: SkillStateSchema.default({}),
67
- depends_on: z.array(z.string()).default([])
68
- });
69
-
70
- // src/output/logger.ts
71
- import chalk from "chalk";
72
- var logger = {
73
- info: (message) => console.log(chalk.blue("i"), message),
74
- success: (message) => console.log(chalk.green("v"), message),
75
- warn: (message) => console.log(chalk.yellow("!"), message),
76
- error: (message) => console.error(chalk.red("x"), message),
77
- dim: (message) => console.log(chalk.dim(message)),
78
- // For JSON output mode
79
- raw: (data) => console.log(JSON.stringify(data, null, 2))
80
- };
81
-
82
- // src/utils/errors.ts
83
- var ExitCode = {
84
- SUCCESS: 0,
85
- VALIDATION_FAILED: 1,
86
- ERROR: 2
87
- };
88
- var CLIError = class extends Error {
89
- exitCode;
90
- constructor(message, exitCode = ExitCode.ERROR) {
91
- super(message);
92
- this.name = "CLIError";
93
- this.exitCode = exitCode;
94
- }
95
- };
96
- function formatError(error) {
97
- if (error instanceof CLIError) {
98
- return `Error: ${error.message}`;
99
- }
100
- if (error instanceof Error) {
101
- return `Error: ${error.message}`;
102
- }
103
- return `Error: ${String(error)}`;
104
- }
105
- function handleError(error) {
106
- const message = formatError(error);
107
- console.error(message);
108
- const exitCode = error instanceof CLIError ? error.exitCode : ExitCode.ERROR;
109
- process.exit(exitCode);
110
- }
111
-
112
- // src/commands/create-skill.ts
113
17
  var KEBAB_CASE_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
114
18
  function buildSkillYaml(opts) {
115
19
  const doc = {
@@ -258,11 +162,6 @@ function createCreateSkillCommand() {
258
162
  }
259
163
 
260
164
  export {
261
- ExitCode,
262
- CLIError,
263
- handleError,
264
- logger,
265
- SkillMetadataSchema,
266
165
  generateSkillFiles,
267
166
  createCreateSkillCommand
268
167
  };
@@ -0,0 +1,72 @@
1
+ // src/utils/paths.ts
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import { fileURLToPath } from "url";
5
+ var __filename = fileURLToPath(import.meta.url);
6
+ var __dirname = path.dirname(__filename);
7
+ function findUpFrom(startDir, targetName, marker, maxLevels) {
8
+ let dir = startDir;
9
+ for (let i = 0; i < maxLevels; i++) {
10
+ const candidate = path.join(dir, targetName);
11
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
12
+ if (fs.existsSync(path.join(candidate, marker))) {
13
+ return candidate;
14
+ }
15
+ }
16
+ dir = path.dirname(dir);
17
+ }
18
+ return null;
19
+ }
20
+ function findUpDir(targetName, marker, maxLevels = 8) {
21
+ const fromModule = findUpFrom(__dirname, targetName, marker, maxLevels);
22
+ if (fromModule) return fromModule;
23
+ return findUpFrom(process.cwd(), targetName, marker, maxLevels);
24
+ }
25
+ function resolveTemplatesDir() {
26
+ return findUpDir("templates", "base") ?? path.join(__dirname, "templates");
27
+ }
28
+ function resolvePersonasDir() {
29
+ const agentsDir = findUpDir("agents", "personas");
30
+ if (agentsDir) {
31
+ return path.join(agentsDir, "personas");
32
+ }
33
+ return path.join(__dirname, "agents", "personas");
34
+ }
35
+ function resolveSkillsDir() {
36
+ const agentsDir = findUpDir("agents", "skills");
37
+ if (agentsDir) {
38
+ return path.join(agentsDir, "skills", "claude-code");
39
+ }
40
+ return path.join(__dirname, "agents", "skills", "claude-code");
41
+ }
42
+ function resolveProjectSkillsDir(cwd) {
43
+ let dir = cwd ?? process.cwd();
44
+ for (let i = 0; i < 8; i++) {
45
+ const candidate = path.join(dir, "agents", "skills", "claude-code");
46
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
47
+ const agentsDir = path.join(dir, "agents");
48
+ if (fs.existsSync(path.join(agentsDir, "skills"))) {
49
+ return candidate;
50
+ }
51
+ }
52
+ const parent = path.dirname(dir);
53
+ if (parent === dir) break;
54
+ dir = parent;
55
+ }
56
+ return null;
57
+ }
58
+ function resolveGlobalSkillsDir() {
59
+ const agentsDir = findUpDir("agents", "skills");
60
+ if (agentsDir) {
61
+ return path.join(agentsDir, "skills", "claude-code");
62
+ }
63
+ return path.join(__dirname, "agents", "skills", "claude-code");
64
+ }
65
+
66
+ export {
67
+ resolveTemplatesDir,
68
+ resolvePersonasDir,
69
+ resolveSkillsDir,
70
+ resolveProjectSkillsDir,
71
+ resolveGlobalSkillsDir
72
+ };
@@ -0,0 +1,125 @@
1
+ import {
2
+ resolveSkillsDir
3
+ } from "./chunk-EOLRW32Q.js";
4
+ import {
5
+ SkillMetadataSchema
6
+ } from "./chunk-MDUK2J2O.js";
7
+
8
+ // src/persona/skill-executor.ts
9
+ import * as fs from "fs";
10
+ import * as path from "path";
11
+ import { parse } from "yaml";
12
+ function resolveOutputMode(mode, trigger) {
13
+ if (mode !== "auto") return mode;
14
+ return trigger === "manual" ? "inline" : "artifact";
15
+ }
16
+ function buildArtifactPath(projectPath, headSha) {
17
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
18
+ const sha = headSha?.slice(0, 7) ?? "unknown";
19
+ return path.join(projectPath, ".harness", "reviews", `${date}-${sha}.md`);
20
+ }
21
+ function buildArtifactContent(skillName, trigger, headSha) {
22
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
23
+ return [
24
+ "---",
25
+ `skill: ${skillName}`,
26
+ `trigger: ${trigger}`,
27
+ `sha: ${headSha?.slice(0, 7) ?? "unknown"}`,
28
+ `date: ${date}`,
29
+ `assessment: pending`,
30
+ "---",
31
+ "",
32
+ `# Review by ${skillName}`,
33
+ "",
34
+ "## Strengths",
35
+ "",
36
+ "- (review pending)",
37
+ "",
38
+ "## Issues",
39
+ "",
40
+ "### Critical",
41
+ "",
42
+ "- None identified",
43
+ "",
44
+ "### Important",
45
+ "",
46
+ "- None identified",
47
+ "",
48
+ "### Suggestions",
49
+ "",
50
+ "- None identified",
51
+ "",
52
+ "## Assessment",
53
+ "",
54
+ "Pending \u2014 skill execution scaffolded.",
55
+ "",
56
+ "## Harness Checks",
57
+ "",
58
+ "- (run harness validate, check-deps, check-docs to populate)",
59
+ ""
60
+ ].join("\n");
61
+ }
62
+ async function executeSkill(skillName, context) {
63
+ const startTime = Date.now();
64
+ const skillsDir = resolveSkillsDir();
65
+ const skillDir = path.join(skillsDir, skillName);
66
+ if (!fs.existsSync(skillDir)) {
67
+ return {
68
+ status: "fail",
69
+ output: `Skill not found: ${skillName}`,
70
+ durationMs: Date.now() - startTime
71
+ };
72
+ }
73
+ const yamlPath = path.join(skillDir, "skill.yaml");
74
+ if (!fs.existsSync(yamlPath)) {
75
+ return {
76
+ status: "fail",
77
+ output: `skill.yaml not found for ${skillName}`,
78
+ durationMs: Date.now() - startTime
79
+ };
80
+ }
81
+ const raw = fs.readFileSync(yamlPath, "utf-8");
82
+ const parsed = parse(raw);
83
+ const metadataResult = SkillMetadataSchema.safeParse(parsed);
84
+ if (!metadataResult.success) {
85
+ return {
86
+ status: "fail",
87
+ output: `Invalid skill metadata: ${metadataResult.error.message}`,
88
+ durationMs: Date.now() - startTime
89
+ };
90
+ }
91
+ const skillMdPath = path.join(skillDir, "SKILL.md");
92
+ if (!fs.existsSync(skillMdPath)) {
93
+ return {
94
+ status: "fail",
95
+ output: `SKILL.md not found for ${skillName}`,
96
+ durationMs: Date.now() - startTime
97
+ };
98
+ }
99
+ const skillContent = fs.readFileSync(skillMdPath, "utf-8");
100
+ const metadata = metadataResult.data;
101
+ const resolvedMode = resolveOutputMode(context.outputMode, context.trigger);
102
+ const output = `Skill ${metadata.name} (${metadata.type}) loaded.
103
+ Cognitive mode: ${metadata.cognitive_mode ?? "default"}
104
+ Content length: ${skillContent.length} chars
105
+ Trigger: ${context.trigger}
106
+ `;
107
+ let artifactPath;
108
+ if (resolvedMode === "artifact") {
109
+ artifactPath = buildArtifactPath(context.projectPath, context.headSha);
110
+ const artifactContent = buildArtifactContent(skillName, context.trigger, context.headSha);
111
+ const dir = path.dirname(artifactPath);
112
+ fs.mkdirSync(dir, { recursive: true });
113
+ fs.writeFileSync(artifactPath, artifactContent, "utf-8");
114
+ }
115
+ return {
116
+ status: "pass",
117
+ output,
118
+ ...artifactPath ? { artifactPath } : {},
119
+ durationMs: Date.now() - startTime
120
+ };
121
+ }
122
+
123
+ export {
124
+ executeSkill
125
+ };
@@ -0,0 +1,116 @@
1
+ import {
2
+ resultToMcpResponse
3
+ } from "./chunk-IDZNPTYD.js";
4
+ import {
5
+ sanitizePath
6
+ } from "./chunk-W6Y7ZW3Y.js";
7
+ import {
8
+ Ok
9
+ } from "./chunk-MHBMTPW7.js";
10
+
11
+ // src/mcp/tools/docs.ts
12
+ import * as path from "path";
13
+ var checkDocsDefinition = {
14
+ name: "check_docs",
15
+ description: "Analyze documentation coverage and/or validate knowledge map integrity",
16
+ inputSchema: {
17
+ type: "object",
18
+ properties: {
19
+ path: { type: "string", description: "Path to project root" },
20
+ domain: { type: "string", description: "Domain/module to check" },
21
+ scope: {
22
+ type: "string",
23
+ enum: ["coverage", "integrity", "all"],
24
+ description: "Scope of check: 'coverage' (doc coverage), 'integrity' (knowledge map validation), 'all' (both). Default: 'coverage'"
25
+ }
26
+ },
27
+ required: ["path"]
28
+ }
29
+ };
30
+ async function handleCheckDocs(input) {
31
+ try {
32
+ const projectPath = sanitizePath(input.path);
33
+ const scope = input.scope ?? "coverage";
34
+ if (scope === "integrity") {
35
+ const { validateKnowledgeMap } = await import("./dist-PBTNVK6K.js");
36
+ const result2 = await validateKnowledgeMap(projectPath);
37
+ return resultToMcpResponse(result2);
38
+ }
39
+ if (scope === "all") {
40
+ const { checkDocCoverage: checkDocCoverage2, validateKnowledgeMap } = await import("./dist-PBTNVK6K.js");
41
+ const domain2 = input.domain ?? "src";
42
+ const { loadGraphStore: loadGraphStore2 } = await import("./graph-loader-RLO3KRIX.js");
43
+ const store2 = await loadGraphStore2(projectPath);
44
+ let graphCoverage2;
45
+ if (store2) {
46
+ const { Assembler } = await import("./dist-I7DB5VKB.js");
47
+ const assembler = new Assembler(store2);
48
+ const report = assembler.checkCoverage();
49
+ graphCoverage2 = {
50
+ documented: [...report.documented],
51
+ undocumented: [...report.undocumented],
52
+ coveragePercentage: report.coveragePercentage
53
+ };
54
+ }
55
+ const [coverageResult, integrityResult] = await Promise.allSettled([
56
+ checkDocCoverage2(domain2, {
57
+ sourceDir: path.resolve(projectPath, "src"),
58
+ docsDir: path.resolve(projectPath, "docs"),
59
+ ...graphCoverage2 !== void 0 && { graphCoverage: graphCoverage2 }
60
+ }),
61
+ validateKnowledgeMap(projectPath)
62
+ ]);
63
+ let coverage;
64
+ if (coverageResult.status === "fulfilled") {
65
+ const r = coverageResult.value;
66
+ coverage = r.ok ? r.value : { error: r.error };
67
+ } else {
68
+ coverage = { error: String(coverageResult.reason) };
69
+ }
70
+ let integrity;
71
+ if (integrityResult.status === "fulfilled") {
72
+ const r = integrityResult.value;
73
+ integrity = r.ok ? r.value : { error: r.error };
74
+ } else {
75
+ integrity = { error: String(integrityResult.reason) };
76
+ }
77
+ return resultToMcpResponse(Ok({ coverage, integrity }));
78
+ }
79
+ const { checkDocCoverage } = await import("./dist-PBTNVK6K.js");
80
+ const domain = input.domain ?? "src";
81
+ const { loadGraphStore } = await import("./graph-loader-RLO3KRIX.js");
82
+ const store = await loadGraphStore(projectPath);
83
+ let graphCoverage;
84
+ if (store) {
85
+ const { Assembler } = await import("./dist-I7DB5VKB.js");
86
+ const assembler = new Assembler(store);
87
+ const report = assembler.checkCoverage();
88
+ graphCoverage = {
89
+ documented: [...report.documented],
90
+ undocumented: [...report.undocumented],
91
+ coveragePercentage: report.coveragePercentage
92
+ };
93
+ }
94
+ const result = await checkDocCoverage(domain, {
95
+ sourceDir: path.resolve(projectPath, "src"),
96
+ docsDir: path.resolve(projectPath, "docs"),
97
+ ...graphCoverage !== void 0 && { graphCoverage }
98
+ });
99
+ return resultToMcpResponse(result);
100
+ } catch (error) {
101
+ return {
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`
106
+ }
107
+ ],
108
+ isError: true
109
+ };
110
+ }
111
+ }
112
+
113
+ export {
114
+ checkDocsDefinition,
115
+ handleCheckDocs
116
+ };