@cardor/agent-harness-kit 1.7.2 → 1.7.5
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/README.md +1 -1
- package/dist/cli.js +120 -65
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -174,7 +174,7 @@ Regenerates `AGENTS.md` and provider-specific files from your `agent-harness-kit
|
|
|
174
174
|
```bash
|
|
175
175
|
ahk build
|
|
176
176
|
ahk build --watch # watch mode: rebuilds automatically on config changes
|
|
177
|
-
ahk build --sync # sync tools: frontmatter in
|
|
177
|
+
ahk build --sync # sync tools: frontmatter in agent files to match current permission constants (claude-code only; no-op for opencode/codex-cli)
|
|
178
178
|
```
|
|
179
179
|
|
|
180
180
|
---
|
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import * as p from "@clack/prompts";
|
|
|
12
12
|
import pc from "picocolors";
|
|
13
13
|
|
|
14
14
|
// src/core/materializer/claude-code.ts
|
|
15
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
15
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
16
16
|
import { join as join4, resolve as resolve3 } from "path";
|
|
17
17
|
|
|
18
18
|
// src/utils/file.ts
|
|
@@ -672,38 +672,6 @@ function appendGitignore(cwd2) {
|
|
|
672
672
|
function slugify(title) {
|
|
673
673
|
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
674
674
|
}
|
|
675
|
-
var AGENT_TOOLS = {
|
|
676
|
-
lead: [...MCP_CLAUDE_PERMISSIONS_LEAD],
|
|
677
|
-
explorer: [...MCP_CLAUDE_PERMISSIONS_EXPLORER],
|
|
678
|
-
consultant: [...MCP_CLAUDE_PERMISSIONS_CONSULTANT],
|
|
679
|
-
builder: [...MCP_CLAUDE_PERMISSIONS_BUILDER],
|
|
680
|
-
reviewer: [...MCP_CLAUDE_PERMISSIONS_REVIEWER]
|
|
681
|
-
};
|
|
682
|
-
async function syncAgentPermissions(cwd2) {
|
|
683
|
-
for (const [agent, tools] of Object.entries(AGENT_TOOLS)) {
|
|
684
|
-
const filePath = join3(cwd2, ".claude", "agents", `${agent}.md`);
|
|
685
|
-
if (!existsSync2(filePath)) {
|
|
686
|
-
console.log(` ${agent}.md not found \u2014 skipping`);
|
|
687
|
-
continue;
|
|
688
|
-
}
|
|
689
|
-
const content = readFileSync3(filePath, "utf-8");
|
|
690
|
-
const updated = content.replace(
|
|
691
|
-
/(tools:\n)((?: - [^\n]+\n)*)/m,
|
|
692
|
-
(_match, header, toolsSection) => {
|
|
693
|
-
const nativeLines = toolsSection.split("\n").filter((line) => line.trim() && !line.includes("mcp__"));
|
|
694
|
-
const nativeSection = nativeLines.length ? nativeLines.join("\n") + "\n" : "";
|
|
695
|
-
const mcpSection = tools.map((t) => ` - ${t}`).join("\n") + "\n";
|
|
696
|
-
return header + nativeSection + mcpSection;
|
|
697
|
-
}
|
|
698
|
-
);
|
|
699
|
-
if (updated === content) {
|
|
700
|
-
console.log(` ${agent}.md already in sync`);
|
|
701
|
-
} else {
|
|
702
|
-
writeFileSync3(filePath, updated, "utf-8");
|
|
703
|
-
console.log(` ${agent}.md updated`);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
675
|
|
|
708
676
|
// src/core/materializer/claude-code.ts
|
|
709
677
|
var ClaudeCodeMaterializer = class {
|
|
@@ -765,6 +733,38 @@ No tasks in progress.
|
|
|
765
733
|
async migrate(config, _to, _cwd) {
|
|
766
734
|
void config;
|
|
767
735
|
}
|
|
736
|
+
async syncPermissions(cwd2) {
|
|
737
|
+
const AGENT_TOOLS = {
|
|
738
|
+
lead: [...MCP_CLAUDE_PERMISSIONS_LEAD],
|
|
739
|
+
explorer: [...MCP_CLAUDE_PERMISSIONS_EXPLORER],
|
|
740
|
+
consultant: [...MCP_CLAUDE_PERMISSIONS_CONSULTANT],
|
|
741
|
+
builder: [...MCP_CLAUDE_PERMISSIONS_BUILDER],
|
|
742
|
+
reviewer: [...MCP_CLAUDE_PERMISSIONS_REVIEWER]
|
|
743
|
+
};
|
|
744
|
+
for (const [agent, tools] of Object.entries(AGENT_TOOLS)) {
|
|
745
|
+
const filePath = join4(cwd2, ".claude", "agents", `${agent}.md`);
|
|
746
|
+
if (!existsSync3(filePath)) {
|
|
747
|
+
console.log(` ${agent}.md not found \u2014 skipping`);
|
|
748
|
+
continue;
|
|
749
|
+
}
|
|
750
|
+
const content = readFileSync4(filePath, "utf-8");
|
|
751
|
+
const updated = content.replace(
|
|
752
|
+
/(tools:\n)((?: - [^\n]+\n)*)/m,
|
|
753
|
+
(_match, header, toolsSection) => {
|
|
754
|
+
const nativeLines = toolsSection.split("\n").filter((line) => line.trim() && !line.includes("mcp__"));
|
|
755
|
+
const nativeSection = nativeLines.length ? nativeLines.join("\n") + "\n" : "";
|
|
756
|
+
const mcpSection = tools.map((t) => ` - ${t}`).join("\n") + "\n";
|
|
757
|
+
return header + nativeSection + mcpSection;
|
|
758
|
+
}
|
|
759
|
+
);
|
|
760
|
+
if (updated === content) {
|
|
761
|
+
console.log(` ${agent}.md already in sync`);
|
|
762
|
+
} else {
|
|
763
|
+
writeFileSync4(filePath, updated, "utf-8");
|
|
764
|
+
console.log(` ${agent}.md updated`);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
768
|
};
|
|
769
769
|
|
|
770
770
|
// src/core/materializer/codex-cli.ts
|
|
@@ -829,6 +829,9 @@ No tasks in progress.
|
|
|
829
829
|
async migrate(config, _to, _cwd) {
|
|
830
830
|
void config;
|
|
831
831
|
}
|
|
832
|
+
async syncPermissions(_cwd) {
|
|
833
|
+
console.log(" Permissions sync not needed for codex-cli \u2014 skipping");
|
|
834
|
+
}
|
|
832
835
|
};
|
|
833
836
|
|
|
834
837
|
// src/core/materializer/opencode.ts
|
|
@@ -891,6 +894,9 @@ No tasks in progress.
|
|
|
891
894
|
async migrate(config, _to, _cwd) {
|
|
892
895
|
void config;
|
|
893
896
|
}
|
|
897
|
+
async syncPermissions(_cwd) {
|
|
898
|
+
console.log(" Permissions sync not needed for opencode \u2014 skipping");
|
|
899
|
+
}
|
|
894
900
|
};
|
|
895
901
|
|
|
896
902
|
// src/core/materializer/index.ts
|
|
@@ -911,7 +917,10 @@ function getMaterializer(provider) {
|
|
|
911
917
|
async function runBuild(cwd2, opts) {
|
|
912
918
|
await buildOnce(cwd2);
|
|
913
919
|
if (opts.sync) {
|
|
914
|
-
|
|
920
|
+
p.log.step("Syncing agent permissions...");
|
|
921
|
+
const config = await loadConfig(cwd2);
|
|
922
|
+
const materializer = getMaterializer(config.provider);
|
|
923
|
+
await materializer.syncPermissions(cwd2);
|
|
915
924
|
}
|
|
916
925
|
if (opts.watch) {
|
|
917
926
|
p.log.info(`Watching agent-harness-kit.config.ts for changes...`);
|
|
@@ -951,7 +960,7 @@ import pc2 from "picocolors";
|
|
|
951
960
|
|
|
952
961
|
// src/core/dashboard-server.ts
|
|
953
962
|
import { watch as watch2 } from "fs";
|
|
954
|
-
import { existsSync as existsSync6, readFileSync as
|
|
963
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
955
964
|
import { extname, join as join7 } from "path";
|
|
956
965
|
import { serve } from "@hono/node-server";
|
|
957
966
|
import { Hono } from "hono";
|
|
@@ -994,7 +1003,7 @@ var MIME = {
|
|
|
994
1003
|
".ttf": "font/ttf"
|
|
995
1004
|
};
|
|
996
1005
|
function fileResponse(filePath) {
|
|
997
|
-
const content =
|
|
1006
|
+
const content = readFileSync5(filePath);
|
|
998
1007
|
const mime = MIME[extname(filePath)] ?? "application/octet-stream";
|
|
999
1008
|
return new Response(content, {
|
|
1000
1009
|
headers: { "Content-Type": mime, "Cache-Control": "no-cache" }
|
|
@@ -1978,14 +1987,14 @@ var cliFormWithRetry = async (formFn, schema) => {
|
|
|
1978
1987
|
};
|
|
1979
1988
|
|
|
1980
1989
|
// src/commands/init-helpers.ts
|
|
1981
|
-
import { existsSync as existsSync8, readFileSync as
|
|
1990
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
1982
1991
|
import { join as join11 } from "path";
|
|
1983
1992
|
import pc5 from "picocolors";
|
|
1984
1993
|
function readProjectNameFromPackageJson(cwd2) {
|
|
1985
1994
|
try {
|
|
1986
1995
|
const pkgPath2 = join11(cwd2, "package.json");
|
|
1987
1996
|
if (!existsSync8(pkgPath2)) return null;
|
|
1988
|
-
const content =
|
|
1997
|
+
const content = readFileSync6(pkgPath2, "utf8");
|
|
1989
1998
|
const pkg2 = JSON.parse(content);
|
|
1990
1999
|
const name = pkg2?.name;
|
|
1991
2000
|
if (typeof name === "string" && name.trim()) return name.trim();
|
|
@@ -1999,7 +2008,7 @@ function detectConfigExtension(cwd2) {
|
|
|
1999
2008
|
if (existsSync8(join11(cwd2, "tsconfig.json"))) return "ts";
|
|
2000
2009
|
const pkgPath2 = join11(cwd2, "package.json");
|
|
2001
2010
|
if (!existsSync8(pkgPath2)) return "mjs";
|
|
2002
|
-
const pkg2 = JSON.parse(
|
|
2011
|
+
const pkg2 = JSON.parse(readFileSync6(pkgPath2, "utf8"));
|
|
2003
2012
|
if (pkg2?.type === "module") return "mjs";
|
|
2004
2013
|
} catch {
|
|
2005
2014
|
}
|
|
@@ -2459,7 +2468,7 @@ async function runReset(cwd2, opts) {
|
|
|
2459
2468
|
}
|
|
2460
2469
|
|
|
2461
2470
|
// src/core/mcp-server.ts
|
|
2462
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readdirSync as readdirSync2, readFileSync as
|
|
2471
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync, writeFileSync as writeFileSync10 } from "fs";
|
|
2463
2472
|
import { join as join15, resolve as resolve10 } from "path";
|
|
2464
2473
|
import { Server } from "@modelcontextprotocol/sdk/server";
|
|
2465
2474
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -2469,7 +2478,7 @@ import {
|
|
|
2469
2478
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
2470
2479
|
|
|
2471
2480
|
// src/core/permissions-check.ts
|
|
2472
|
-
import { existsSync as existsSync10, readFileSync as
|
|
2481
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
2473
2482
|
import { join as join14 } from "path";
|
|
2474
2483
|
var CANONICAL = {
|
|
2475
2484
|
lead: [...MCP_CLAUDE_PERMISSIONS_LEAD],
|
|
@@ -2486,7 +2495,10 @@ function parseToolsFromFrontmatter(content) {
|
|
|
2486
2495
|
if (!toolsMatch) return [];
|
|
2487
2496
|
return toolsMatch[1].split("\n").map((l) => l.trim().replace(/^- /, "")).filter((l) => l.startsWith("mcp__"));
|
|
2488
2497
|
}
|
|
2489
|
-
function checkPermissionsSync(cwd2) {
|
|
2498
|
+
function checkPermissionsSync(cwd2, config) {
|
|
2499
|
+
if (config.provider !== "claude-code") {
|
|
2500
|
+
return { in_sync: true };
|
|
2501
|
+
}
|
|
2490
2502
|
const agents = {};
|
|
2491
2503
|
let in_sync = true;
|
|
2492
2504
|
for (const agent of ["lead", "explorer", "consultant", "builder", "reviewer"]) {
|
|
@@ -2497,7 +2509,7 @@ function checkPermissionsSync(cwd2) {
|
|
|
2497
2509
|
in_sync = false;
|
|
2498
2510
|
continue;
|
|
2499
2511
|
}
|
|
2500
|
-
const content =
|
|
2512
|
+
const content = readFileSync7(filePath, "utf-8");
|
|
2501
2513
|
const installed = parseToolsFromFrontmatter(content);
|
|
2502
2514
|
const canonical = CANONICAL[agent];
|
|
2503
2515
|
const missing = canonical.filter((t) => !installed.includes(t));
|
|
@@ -2646,7 +2658,10 @@ var TOOLS = [
|
|
|
2646
2658
|
inputSchema: {
|
|
2647
2659
|
type: "object",
|
|
2648
2660
|
properties: {
|
|
2649
|
-
criterionId: {
|
|
2661
|
+
criterionId: {
|
|
2662
|
+
type: "number",
|
|
2663
|
+
description: "The id of the acceptance criterion to mark as met"
|
|
2664
|
+
}
|
|
2650
2665
|
},
|
|
2651
2666
|
required: ["criterionId"]
|
|
2652
2667
|
}
|
|
@@ -2669,7 +2684,10 @@ var TOOLS = [
|
|
|
2669
2684
|
type: "object",
|
|
2670
2685
|
properties: {
|
|
2671
2686
|
title: { type: "string", description: "Short human-readable title for the task" },
|
|
2672
|
-
slug: {
|
|
2687
|
+
slug: {
|
|
2688
|
+
type: "string",
|
|
2689
|
+
description: "URL-safe identifier (lowercase, hyphens). Auto-derived from title if omitted."
|
|
2690
|
+
},
|
|
2673
2691
|
description: { type: "string", description: "Longer description of the task goal" },
|
|
2674
2692
|
acceptance: {
|
|
2675
2693
|
type: "array",
|
|
@@ -2687,8 +2705,14 @@ var TOOLS = [
|
|
|
2687
2705
|
type: "object",
|
|
2688
2706
|
properties: {
|
|
2689
2707
|
actionId: { type: "string", description: "UUID returned by actions.start" },
|
|
2690
|
-
toolName: {
|
|
2691
|
-
|
|
2708
|
+
toolName: {
|
|
2709
|
+
type: "string",
|
|
2710
|
+
description: "Name of the tool that was called (e.g. Read, Bash, Edit)"
|
|
2711
|
+
},
|
|
2712
|
+
argsJson: {
|
|
2713
|
+
type: "string",
|
|
2714
|
+
description: "Optional JSON string of the arguments passed to the tool"
|
|
2715
|
+
},
|
|
2692
2716
|
resultSummary: { type: "string", description: "Optional short summary of the tool result" }
|
|
2693
2717
|
},
|
|
2694
2718
|
required: ["actionId", "toolName"]
|
|
@@ -2762,7 +2786,7 @@ async function startMcpServer(config, cwd2) {
|
|
|
2762
2786
|
const { name, arguments: args } = request.params;
|
|
2763
2787
|
const a = args ?? {};
|
|
2764
2788
|
try {
|
|
2765
|
-
const result = await dispatch(name, a, db, docsPath, cwd2);
|
|
2789
|
+
const result = await dispatch(name, a, db, docsPath, cwd2, config);
|
|
2766
2790
|
return result;
|
|
2767
2791
|
} catch (err) {
|
|
2768
2792
|
return ok(`Error: ${err instanceof Error ? err.message : String(err)}`, true);
|
|
@@ -2771,7 +2795,7 @@ async function startMcpServer(config, cwd2) {
|
|
|
2771
2795
|
const transport = new StdioServerTransport();
|
|
2772
2796
|
await server.connect(transport);
|
|
2773
2797
|
}
|
|
2774
|
-
async function dispatch(name, args, db, docsPath, cwd2) {
|
|
2798
|
+
async function dispatch(name, args, db, docsPath, cwd2, config) {
|
|
2775
2799
|
switch (name) {
|
|
2776
2800
|
case "actions.start": {
|
|
2777
2801
|
const taskId = num(args, "taskId");
|
|
@@ -2790,7 +2814,9 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2790
2814
|
const actionId = str(args, "actionId");
|
|
2791
2815
|
const summary = str(args, "summary");
|
|
2792
2816
|
const action = await db.completeAction(actionId, summary);
|
|
2793
|
-
return ok(
|
|
2817
|
+
return ok(
|
|
2818
|
+
JSON.stringify({ actionId, status: action.status, completedAt: action.completed_at })
|
|
2819
|
+
);
|
|
2794
2820
|
}
|
|
2795
2821
|
case "actions.get": {
|
|
2796
2822
|
const taskId = num(args, "taskId");
|
|
@@ -2873,7 +2899,10 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2873
2899
|
const acceptance = args["acceptance"];
|
|
2874
2900
|
const task2 = await db.getTaskById(id);
|
|
2875
2901
|
if (!task2) return ok(JSON.stringify({ error: "Task not found", taskId: id }), true);
|
|
2876
|
-
await db.updateTask(id, {
|
|
2902
|
+
await db.updateTask(id, {
|
|
2903
|
+
title,
|
|
2904
|
+
description: description !== void 0 ? description : void 0
|
|
2905
|
+
});
|
|
2877
2906
|
if (acceptance !== void 0 && acceptance !== null) {
|
|
2878
2907
|
await db.updateTaskAcceptance(id, acceptance);
|
|
2879
2908
|
}
|
|
@@ -2891,7 +2920,7 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2891
2920
|
return ok(JSON.stringify(task2));
|
|
2892
2921
|
}
|
|
2893
2922
|
case "permissions.check": {
|
|
2894
|
-
const result = checkPermissionsSync(cwd2);
|
|
2923
|
+
const result = checkPermissionsSync(cwd2, config);
|
|
2895
2924
|
return ok(JSON.stringify(result, null, 2));
|
|
2896
2925
|
}
|
|
2897
2926
|
case "deps.snapshot": {
|
|
@@ -2899,7 +2928,7 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2899
2928
|
if (!existsSync11(pkgPath2)) {
|
|
2900
2929
|
return ok("package.json not found in project root", true);
|
|
2901
2930
|
}
|
|
2902
|
-
const pkg2 = JSON.parse(
|
|
2931
|
+
const pkg2 = JSON.parse(readFileSync8(pkgPath2, "utf8"));
|
|
2903
2932
|
const snapshot = {
|
|
2904
2933
|
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2905
2934
|
dependencies: pkg2.dependencies ?? {},
|
|
@@ -2908,7 +2937,12 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2908
2937
|
const harnessDir = join15(cwd2, ".harness");
|
|
2909
2938
|
mkdirSync9(harnessDir, { recursive: true });
|
|
2910
2939
|
writeFileSync10(join15(harnessDir, "deps-lock.json"), JSON.stringify(snapshot, null, 2), "utf8");
|
|
2911
|
-
return ok(
|
|
2940
|
+
return ok(
|
|
2941
|
+
JSON.stringify({
|
|
2942
|
+
message: "Snapshot saved to .harness/deps-lock.json",
|
|
2943
|
+
capturedAt: snapshot.capturedAt
|
|
2944
|
+
})
|
|
2945
|
+
);
|
|
2912
2946
|
}
|
|
2913
2947
|
case "deps.check": {
|
|
2914
2948
|
const pkgPath2 = join15(cwd2, "package.json");
|
|
@@ -2917,10 +2951,15 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2917
2951
|
return ok("package.json not found in project root", true);
|
|
2918
2952
|
}
|
|
2919
2953
|
if (!existsSync11(lockPath)) {
|
|
2920
|
-
return ok(
|
|
2954
|
+
return ok(
|
|
2955
|
+
JSON.stringify({
|
|
2956
|
+
status: "no-snapshot",
|
|
2957
|
+
message: "No deps-lock.json found. Run deps.snapshot first to establish a baseline."
|
|
2958
|
+
})
|
|
2959
|
+
);
|
|
2921
2960
|
}
|
|
2922
|
-
const pkg2 = JSON.parse(
|
|
2923
|
-
const lock = JSON.parse(
|
|
2961
|
+
const pkg2 = JSON.parse(readFileSync8(pkgPath2, "utf8"));
|
|
2962
|
+
const lock = JSON.parse(readFileSync8(lockPath, "utf8"));
|
|
2924
2963
|
const current = { ...pkg2.dependencies ?? {}, ...pkg2.devDependencies ?? {} };
|
|
2925
2964
|
const previous = { ...lock.dependencies ?? {}, ...lock.devDependencies ?? {} };
|
|
2926
2965
|
const added = [];
|
|
@@ -2930,7 +2969,10 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2930
2969
|
if (!(name2 in previous)) {
|
|
2931
2970
|
added.push(`${name2}@${version}`);
|
|
2932
2971
|
} else {
|
|
2933
|
-
const prevMajor = parseInt(
|
|
2972
|
+
const prevMajor = parseInt(
|
|
2973
|
+
previous[name2].replace(/^[\^~>=v]/, "").split(".")[0] ?? "0",
|
|
2974
|
+
10
|
|
2975
|
+
);
|
|
2934
2976
|
const curMajor = parseInt(version.replace(/^[\^~>=v]/, "").split(".")[0] ?? "0", 10);
|
|
2935
2977
|
if (!isNaN(prevMajor) && !isNaN(curMajor) && curMajor > prevMajor) {
|
|
2936
2978
|
majorBumps.push({ name: name2, from: previous[name2], to: version });
|
|
@@ -2944,7 +2986,16 @@ async function dispatch(name, args, db, docsPath, cwd2) {
|
|
|
2944
2986
|
}
|
|
2945
2987
|
const significant = added.length > 0 || removed.length > 0 || majorBumps.length > 0;
|
|
2946
2988
|
const advisory = significant ? "Significant dependency changes detected. Consider running `pnpx autoskills` (or `npx autoskills` if pnpm is unavailable) to refresh agent skills. Clearing stale skills before re-running is recommended." : "No significant dependency changes detected.";
|
|
2947
|
-
return ok(
|
|
2989
|
+
return ok(
|
|
2990
|
+
JSON.stringify({
|
|
2991
|
+
significant,
|
|
2992
|
+
added,
|
|
2993
|
+
removed,
|
|
2994
|
+
majorBumps,
|
|
2995
|
+
advisory,
|
|
2996
|
+
snapshotDate: lock.capturedAt
|
|
2997
|
+
})
|
|
2998
|
+
);
|
|
2948
2999
|
}
|
|
2949
3000
|
default:
|
|
2950
3001
|
return ok(`Unknown tool: ${name}`, true);
|
|
@@ -2958,12 +3009,16 @@ function searchDocs(docsPath, query, maxResults = 10) {
|
|
|
2958
3009
|
for (const file of files) {
|
|
2959
3010
|
if (results.length >= maxResults) break;
|
|
2960
3011
|
try {
|
|
2961
|
-
const content =
|
|
3012
|
+
const content = readFileSync8(file, "utf8");
|
|
2962
3013
|
const lines = content.split("\n");
|
|
2963
3014
|
for (let i = 0; i < lines.length; i++) {
|
|
2964
3015
|
const lower = lines[i].toLowerCase();
|
|
2965
3016
|
if (terms.every((t) => lower.includes(t))) {
|
|
2966
|
-
results.push({
|
|
3017
|
+
results.push({
|
|
3018
|
+
file: file.replace(docsPath + "/", ""),
|
|
3019
|
+
line: i + 1,
|
|
3020
|
+
text: lines[i].trim()
|
|
3021
|
+
});
|
|
2967
3022
|
if (results.length >= maxResults) break;
|
|
2968
3023
|
}
|
|
2969
3024
|
}
|
|
@@ -3013,8 +3068,8 @@ async function runServe(cwd2, opts) {
|
|
|
3013
3068
|
}
|
|
3014
3069
|
process.stderr.write(`[agent-harness-kit] MCP server starting (stdio)
|
|
3015
3070
|
`);
|
|
3016
|
-
const syncResult = checkPermissionsSync(cwd2);
|
|
3017
|
-
if (!syncResult.in_sync) {
|
|
3071
|
+
const syncResult = checkPermissionsSync(cwd2, config);
|
|
3072
|
+
if (!syncResult.in_sync && syncResult.agents) {
|
|
3018
3073
|
const affected = Object.entries(syncResult.agents).filter(([, r]) => !r.ok).map(([name, r]) => {
|
|
3019
3074
|
const parts = [];
|
|
3020
3075
|
if (r.missing.length) parts.push(`missing: ${r.missing.map((t) => t.replace("mcp__agent-harness-kit__", "")).join(", ")}`);
|
|
@@ -3103,7 +3158,7 @@ async function runStatus(cwd2, opts) {
|
|
|
3103
3158
|
}
|
|
3104
3159
|
|
|
3105
3160
|
// src/commands/sync.ts
|
|
3106
|
-
import { existsSync as existsSync12, readFileSync as
|
|
3161
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
3107
3162
|
import { join as join16, resolve as resolve11 } from "path";
|
|
3108
3163
|
import pc10 from "picocolors";
|
|
3109
3164
|
async function runSync(cwd2, opts) {
|
|
@@ -3129,7 +3184,7 @@ async function syncIn(featureListPath, db, dryRun) {
|
|
|
3129
3184
|
}
|
|
3130
3185
|
let seeds;
|
|
3131
3186
|
try {
|
|
3132
|
-
seeds = JSON.parse(
|
|
3187
|
+
seeds = JSON.parse(readFileSync9(featureListPath, "utf8"));
|
|
3133
3188
|
} catch (err) {
|
|
3134
3189
|
console.error(pc10.red(`Failed to parse feature_list.json: ${err}`));
|
|
3135
3190
|
process.exit(1);
|