@cardor/agent-harness-kit 1.6.0 → 1.6.3
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 +47 -7
- package/dist/agent-templates/builder.md +27 -6
- package/dist/agent-templates/consultant.md +77 -0
- package/dist/agent-templates/lead.md +23 -1
- package/dist/agent-templates/reviewer.md +2 -0
- package/dist/cli.js +196 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/{sqlite-XBEJJ5T2.js → sqlite-KWYK4IJW.js} +2 -2
- package/dist/sqlite-KWYK4IJW.js.map +1 -0
- package/package.json +2 -2
- package/dist/sqlite-XBEJJ5T2.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -131,12 +131,24 @@ var MCP_CLAUDE_PERMISSIONS_REVIEWER = [
|
|
|
131
131
|
"mcp__agent-harness-kit__tasks_acceptance_get",
|
|
132
132
|
"mcp__agent-harness-kit__docs_search"
|
|
133
133
|
];
|
|
134
|
+
var MCP_CLAUDE_PERMISSIONS_CONSULTANT = [
|
|
135
|
+
"mcp__agent-harness-kit__actions_start",
|
|
136
|
+
"mcp__agent-harness-kit__actions_write",
|
|
137
|
+
"mcp__agent-harness-kit__actions_complete",
|
|
138
|
+
"mcp__agent-harness-kit__actions_get",
|
|
139
|
+
"mcp__agent-harness-kit__actions_record_file",
|
|
140
|
+
"mcp__agent-harness-kit__actions_record_tool",
|
|
141
|
+
"mcp__agent-harness-kit__tasks_get",
|
|
142
|
+
"mcp__agent-harness-kit__deps_snapshot",
|
|
143
|
+
"mcp__agent-harness-kit__deps_check"
|
|
144
|
+
];
|
|
134
145
|
var MCP_CLAUDE_PERMISSIONS = [
|
|
135
146
|
.../* @__PURE__ */ new Set([
|
|
136
147
|
...MCP_CLAUDE_PERMISSIONS_LEAD,
|
|
137
148
|
...MCP_CLAUDE_PERMISSIONS_EXPLORER,
|
|
138
149
|
...MCP_CLAUDE_PERMISSIONS_BUILDER,
|
|
139
|
-
...MCP_CLAUDE_PERMISSIONS_REVIEWER
|
|
150
|
+
...MCP_CLAUDE_PERMISSIONS_REVIEWER,
|
|
151
|
+
...MCP_CLAUDE_PERMISSIONS_CONSULTANT
|
|
140
152
|
])
|
|
141
153
|
];
|
|
142
154
|
function mergeClaudeSettingsLocalJson(filePath) {
|
|
@@ -491,6 +503,9 @@ function agentExplorer(vars) {
|
|
|
491
503
|
function agentBuilder(vars) {
|
|
492
504
|
return loadAgentTemplate("builder", vars);
|
|
493
505
|
}
|
|
506
|
+
function agentConsultant(vars) {
|
|
507
|
+
return loadAgentTemplate("consultant", vars);
|
|
508
|
+
}
|
|
494
509
|
function agentReviewer(vars) {
|
|
495
510
|
return loadAgentTemplate("reviewer", vars);
|
|
496
511
|
}
|
|
@@ -548,10 +563,11 @@ function agentReviewerToml(vars) {
|
|
|
548
563
|
}
|
|
549
564
|
function translateFrontmatterForClaudeCode(md, agentName) {
|
|
550
565
|
const permissionsMap = {
|
|
551
|
-
lead: MCP_CLAUDE_PERMISSIONS_LEAD,
|
|
552
|
-
explorer: MCP_CLAUDE_PERMISSIONS_EXPLORER,
|
|
553
|
-
|
|
554
|
-
|
|
566
|
+
lead: [...MCP_CLAUDE_PERMISSIONS_LEAD],
|
|
567
|
+
explorer: [...MCP_CLAUDE_PERMISSIONS_EXPLORER],
|
|
568
|
+
consultant: [...MCP_CLAUDE_PERMISSIONS_CONSULTANT],
|
|
569
|
+
builder: [...MCP_CLAUDE_PERMISSIONS_BUILDER],
|
|
570
|
+
reviewer: [...MCP_CLAUDE_PERMISSIONS_REVIEWER]
|
|
555
571
|
};
|
|
556
572
|
const permissions = permissionsMap[agentName] ?? MCP_CLAUDE_PERMISSIONS;
|
|
557
573
|
const mcpLines = permissions.map((t) => ` - ${t}`).join("\n");
|
|
@@ -589,6 +605,33 @@ function appendGitignore(cwd2) {
|
|
|
589
605
|
function slugify(title) {
|
|
590
606
|
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
591
607
|
}
|
|
608
|
+
var AGENT_TOOLS = {
|
|
609
|
+
lead: [...MCP_CLAUDE_PERMISSIONS_LEAD],
|
|
610
|
+
explorer: [...MCP_CLAUDE_PERMISSIONS_EXPLORER],
|
|
611
|
+
consultant: [...MCP_CLAUDE_PERMISSIONS_CONSULTANT],
|
|
612
|
+
builder: [...MCP_CLAUDE_PERMISSIONS_BUILDER],
|
|
613
|
+
reviewer: [...MCP_CLAUDE_PERMISSIONS_REVIEWER]
|
|
614
|
+
};
|
|
615
|
+
async function syncAgentPermissions(cwd2) {
|
|
616
|
+
for (const [agent, tools] of Object.entries(AGENT_TOOLS)) {
|
|
617
|
+
const filePath = join3(cwd2, ".claude", "agents", `${agent}.md`);
|
|
618
|
+
if (!existsSync2(filePath)) {
|
|
619
|
+
console.log(` ${agent}.md not found \u2014 skipping`);
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
623
|
+
const toolsBlock = `tools:
|
|
624
|
+
${tools.map((t) => ` - ${t}`).join("\n")}
|
|
625
|
+
`;
|
|
626
|
+
const updated = content.replace(/tools:\n(?: - [^\n]+\n)*/m, toolsBlock);
|
|
627
|
+
if (updated === content) {
|
|
628
|
+
console.log(` ${agent}.md already in sync`);
|
|
629
|
+
} else {
|
|
630
|
+
writeFileSync3(filePath, updated, "utf-8");
|
|
631
|
+
console.log(` ${agent}.md updated`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
592
635
|
|
|
593
636
|
// src/core/materializer/claude-code.ts
|
|
594
637
|
var ClaudeCodeMaterializer = class {
|
|
@@ -619,6 +662,7 @@ No tasks in progress.
|
|
|
619
662
|
const writablePaths = (config.agents.builder.writablePaths ?? []).join(", ");
|
|
620
663
|
writeAgentFile(cwd2, ".claude/agents/lead.md", translateFrontmatterForClaudeCode(agentLead({ projectName }), "lead"));
|
|
621
664
|
writeAgentFile(cwd2, ".claude/agents/explorer.md", translateFrontmatterForClaudeCode(agentExplorer({ projectName, allowedPaths }), "explorer"));
|
|
665
|
+
writeAgentFile(cwd2, ".claude/agents/consultant.md", translateFrontmatterForClaudeCode(agentConsultant({ projectName }), "consultant"));
|
|
622
666
|
writeAgentFile(cwd2, ".claude/agents/builder.md", translateFrontmatterForClaudeCode(agentBuilder({ projectName, writablePaths }), "builder"));
|
|
623
667
|
writeAgentFile(cwd2, ".claude/agents/reviewer.md", translateFrontmatterForClaudeCode(agentReviewer({ projectName }), "reviewer"));
|
|
624
668
|
mergeClaudeMcpJson(join4(cwd2, ".mcp.json"), config.tools.mcp.port);
|
|
@@ -639,6 +683,7 @@ No tasks in progress.
|
|
|
639
683
|
const writablePaths = (config.agents.builder.writablePaths ?? []).join(", ");
|
|
640
684
|
writeAgentFile(cwd2, ".claude/agents/lead.md", translateFrontmatterForClaudeCode(agentLead({ projectName }), "lead"));
|
|
641
685
|
writeAgentFile(cwd2, ".claude/agents/explorer.md", translateFrontmatterForClaudeCode(agentExplorer({ projectName, allowedPaths }), "explorer"));
|
|
686
|
+
writeAgentFile(cwd2, ".claude/agents/consultant.md", translateFrontmatterForClaudeCode(agentConsultant({ projectName }), "consultant"));
|
|
642
687
|
writeAgentFile(cwd2, ".claude/agents/builder.md", translateFrontmatterForClaudeCode(agentBuilder({ projectName, writablePaths }), "builder"));
|
|
643
688
|
writeAgentFile(cwd2, ".claude/agents/reviewer.md", translateFrontmatterForClaudeCode(agentReviewer({ projectName }), "reviewer"));
|
|
644
689
|
mergeClaudeMcpJson(join4(cwd2, ".mcp.json"), config.tools.mcp.port);
|
|
@@ -789,6 +834,9 @@ function getMaterializer(provider) {
|
|
|
789
834
|
// src/commands/build.ts
|
|
790
835
|
async function runBuild(cwd2, opts) {
|
|
791
836
|
await buildOnce(cwd2);
|
|
837
|
+
if (opts.sync) {
|
|
838
|
+
await syncAgentPermissions(cwd2);
|
|
839
|
+
}
|
|
792
840
|
if (opts.watch) {
|
|
793
841
|
p.log.info(`Watching agent-harness-kit.config.ts for changes...`);
|
|
794
842
|
watch(cwd2, { recursive: false }, async (_, filename) => {
|
|
@@ -1642,7 +1690,7 @@ async function openDB(config, cwd2) {
|
|
|
1642
1690
|
const { MySQLDriver } = await import("./mysql-THKQOXIS.js");
|
|
1643
1691
|
driver = new MySQLDriver(dbConfig);
|
|
1644
1692
|
} else {
|
|
1645
|
-
const { SQLiteDriver } = await import("./sqlite-
|
|
1693
|
+
const { SQLiteDriver } = await import("./sqlite-KWYK4IJW.js");
|
|
1646
1694
|
if (dbConfig.type !== "sqlite") {
|
|
1647
1695
|
throw new Error("Invalid database type");
|
|
1648
1696
|
}
|
|
@@ -2324,14 +2372,57 @@ async function runReset(cwd2, opts) {
|
|
|
2324
2372
|
}
|
|
2325
2373
|
|
|
2326
2374
|
// src/core/mcp-server.ts
|
|
2327
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
2328
|
-
import { join as
|
|
2375
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync, writeFileSync as writeFileSync10 } from "fs";
|
|
2376
|
+
import { join as join15, resolve as resolve10 } from "path";
|
|
2329
2377
|
import { Server } from "@modelcontextprotocol/sdk/server";
|
|
2330
2378
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2331
2379
|
import {
|
|
2332
2380
|
CallToolRequestSchema,
|
|
2333
2381
|
ListToolsRequestSchema
|
|
2334
2382
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
2383
|
+
|
|
2384
|
+
// src/core/permissions-check.ts
|
|
2385
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
|
|
2386
|
+
import { join as join14 } from "path";
|
|
2387
|
+
var CANONICAL = {
|
|
2388
|
+
lead: [...MCP_CLAUDE_PERMISSIONS_LEAD],
|
|
2389
|
+
explorer: [...MCP_CLAUDE_PERMISSIONS_EXPLORER],
|
|
2390
|
+
consultant: [...MCP_CLAUDE_PERMISSIONS_CONSULTANT],
|
|
2391
|
+
builder: [...MCP_CLAUDE_PERMISSIONS_BUILDER],
|
|
2392
|
+
reviewer: [...MCP_CLAUDE_PERMISSIONS_REVIEWER]
|
|
2393
|
+
};
|
|
2394
|
+
function parseToolsFromFrontmatter(content) {
|
|
2395
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/m);
|
|
2396
|
+
if (!match) return [];
|
|
2397
|
+
const fm = match[1];
|
|
2398
|
+
const toolsMatch = fm.match(/^tools:\n((?: - [^\n]+\n?)*)/m);
|
|
2399
|
+
if (!toolsMatch) return [];
|
|
2400
|
+
return toolsMatch[1].split("\n").map((l) => l.trim().replace(/^- /, "")).filter((l) => l.startsWith("mcp__"));
|
|
2401
|
+
}
|
|
2402
|
+
function checkPermissionsSync(cwd2) {
|
|
2403
|
+
const agents = {};
|
|
2404
|
+
let in_sync = true;
|
|
2405
|
+
for (const agent of ["lead", "explorer", "consultant", "builder", "reviewer"]) {
|
|
2406
|
+
const filePath = join14(cwd2, ".claude", "agents", `${agent}.md`);
|
|
2407
|
+
if (!existsSync10(filePath)) {
|
|
2408
|
+
const missing2 = CANONICAL[agent];
|
|
2409
|
+
agents[agent] = { ok: false, missing: missing2, extra: [] };
|
|
2410
|
+
in_sync = false;
|
|
2411
|
+
continue;
|
|
2412
|
+
}
|
|
2413
|
+
const content = readFileSync6(filePath, "utf-8");
|
|
2414
|
+
const installed = parseToolsFromFrontmatter(content);
|
|
2415
|
+
const canonical = CANONICAL[agent];
|
|
2416
|
+
const missing = canonical.filter((t) => !installed.includes(t));
|
|
2417
|
+
const extra = installed.filter((t) => !canonical.includes(t));
|
|
2418
|
+
const ok2 = missing.length === 0 && extra.length === 0;
|
|
2419
|
+
if (!ok2) in_sync = false;
|
|
2420
|
+
agents[agent] = { ok: ok2, missing, extra };
|
|
2421
|
+
}
|
|
2422
|
+
return { in_sync, agents };
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
// src/core/mcp-server.ts
|
|
2335
2426
|
var VERSION = "0.1.0";
|
|
2336
2427
|
var TOOLS = [
|
|
2337
2428
|
{
|
|
@@ -2555,6 +2646,21 @@ var TOOLS = [
|
|
|
2555
2646
|
},
|
|
2556
2647
|
required: ["id"]
|
|
2557
2648
|
}
|
|
2649
|
+
},
|
|
2650
|
+
{
|
|
2651
|
+
name: "permissions.check",
|
|
2652
|
+
description: "Check whether the .claude/agents/*.md tool permission lists are in sync with the current canonical permission constants. Returns per-agent diff with missing and extra tools. Call this at session start to detect outdated agent files after an ahk upgrade.",
|
|
2653
|
+
inputSchema: { type: "object", properties: {}, required: [] }
|
|
2654
|
+
},
|
|
2655
|
+
{
|
|
2656
|
+
name: "deps.snapshot",
|
|
2657
|
+
description: "Snapshot current package.json dependencies to .harness/deps-lock.json",
|
|
2658
|
+
inputSchema: { type: "object", properties: {}, required: [] }
|
|
2659
|
+
},
|
|
2660
|
+
{
|
|
2661
|
+
name: "deps.check",
|
|
2662
|
+
description: "Compare current package.json against .harness/deps-lock.json and report changes",
|
|
2663
|
+
inputSchema: { type: "object", properties: {}, required: [] }
|
|
2558
2664
|
}
|
|
2559
2665
|
];
|
|
2560
2666
|
async function startMcpServer(config, cwd2) {
|
|
@@ -2569,7 +2675,7 @@ async function startMcpServer(config, cwd2) {
|
|
|
2569
2675
|
const { name, arguments: args } = request.params;
|
|
2570
2676
|
const a = args ?? {};
|
|
2571
2677
|
try {
|
|
2572
|
-
const result = await dispatch(name, a, db, docsPath);
|
|
2678
|
+
const result = await dispatch(name, a, db, docsPath, cwd2);
|
|
2573
2679
|
return result;
|
|
2574
2680
|
} catch (err) {
|
|
2575
2681
|
return ok(`Error: ${err instanceof Error ? err.message : String(err)}`, true);
|
|
@@ -2578,7 +2684,7 @@ async function startMcpServer(config, cwd2) {
|
|
|
2578
2684
|
const transport = new StdioServerTransport();
|
|
2579
2685
|
await server.connect(transport);
|
|
2580
2686
|
}
|
|
2581
|
-
async function dispatch(name, args, db, docsPath) {
|
|
2687
|
+
async function dispatch(name, args, db, docsPath, cwd2) {
|
|
2582
2688
|
switch (name) {
|
|
2583
2689
|
case "actions.start": {
|
|
2584
2690
|
const taskId = num(args, "taskId");
|
|
@@ -2697,6 +2803,62 @@ async function dispatch(name, args, db, docsPath) {
|
|
|
2697
2803
|
const task2 = await db.unarchiveTask(id);
|
|
2698
2804
|
return ok(JSON.stringify(task2));
|
|
2699
2805
|
}
|
|
2806
|
+
case "permissions.check": {
|
|
2807
|
+
const result = checkPermissionsSync(cwd2);
|
|
2808
|
+
return ok(JSON.stringify(result, null, 2));
|
|
2809
|
+
}
|
|
2810
|
+
case "deps.snapshot": {
|
|
2811
|
+
const pkgPath2 = join15(cwd2, "package.json");
|
|
2812
|
+
if (!existsSync11(pkgPath2)) {
|
|
2813
|
+
return ok("package.json not found in project root", true);
|
|
2814
|
+
}
|
|
2815
|
+
const pkg2 = JSON.parse(readFileSync7(pkgPath2, "utf8"));
|
|
2816
|
+
const snapshot = {
|
|
2817
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2818
|
+
dependencies: pkg2.dependencies ?? {},
|
|
2819
|
+
devDependencies: pkg2.devDependencies ?? {}
|
|
2820
|
+
};
|
|
2821
|
+
const harnessDir = join15(cwd2, ".harness");
|
|
2822
|
+
mkdirSync9(harnessDir, { recursive: true });
|
|
2823
|
+
writeFileSync10(join15(harnessDir, "deps-lock.json"), JSON.stringify(snapshot, null, 2), "utf8");
|
|
2824
|
+
return ok(JSON.stringify({ message: "Snapshot saved to .harness/deps-lock.json", capturedAt: snapshot.capturedAt }));
|
|
2825
|
+
}
|
|
2826
|
+
case "deps.check": {
|
|
2827
|
+
const pkgPath2 = join15(cwd2, "package.json");
|
|
2828
|
+
const lockPath = join15(cwd2, ".harness", "deps-lock.json");
|
|
2829
|
+
if (!existsSync11(pkgPath2)) {
|
|
2830
|
+
return ok("package.json not found in project root", true);
|
|
2831
|
+
}
|
|
2832
|
+
if (!existsSync11(lockPath)) {
|
|
2833
|
+
return ok(JSON.stringify({ status: "no-snapshot", message: "No deps-lock.json found. Run deps.snapshot first to establish a baseline." }));
|
|
2834
|
+
}
|
|
2835
|
+
const pkg2 = JSON.parse(readFileSync7(pkgPath2, "utf8"));
|
|
2836
|
+
const lock = JSON.parse(readFileSync7(lockPath, "utf8"));
|
|
2837
|
+
const current = { ...pkg2.dependencies ?? {}, ...pkg2.devDependencies ?? {} };
|
|
2838
|
+
const previous = { ...lock.dependencies ?? {}, ...lock.devDependencies ?? {} };
|
|
2839
|
+
const added = [];
|
|
2840
|
+
const removed = [];
|
|
2841
|
+
const majorBumps = [];
|
|
2842
|
+
for (const [name2, version] of Object.entries(current)) {
|
|
2843
|
+
if (!(name2 in previous)) {
|
|
2844
|
+
added.push(`${name2}@${version}`);
|
|
2845
|
+
} else {
|
|
2846
|
+
const prevMajor = parseInt(previous[name2].replace(/^[\^~>=v]/, "").split(".")[0] ?? "0", 10);
|
|
2847
|
+
const curMajor = parseInt(version.replace(/^[\^~>=v]/, "").split(".")[0] ?? "0", 10);
|
|
2848
|
+
if (!isNaN(prevMajor) && !isNaN(curMajor) && curMajor > prevMajor) {
|
|
2849
|
+
majorBumps.push({ name: name2, from: previous[name2], to: version });
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
for (const depName of Object.keys(previous)) {
|
|
2854
|
+
if (!(depName in current)) {
|
|
2855
|
+
removed.push(depName);
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
const significant = added.length > 0 || removed.length > 0 || majorBumps.length > 0;
|
|
2859
|
+
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.";
|
|
2860
|
+
return ok(JSON.stringify({ significant, added, removed, majorBumps, advisory, snapshotDate: lock.capturedAt }));
|
|
2861
|
+
}
|
|
2700
2862
|
default:
|
|
2701
2863
|
return ok(`Unknown tool: ${name}`, true);
|
|
2702
2864
|
}
|
|
@@ -2709,7 +2871,7 @@ function searchDocs(docsPath, query, maxResults = 10) {
|
|
|
2709
2871
|
for (const file of files) {
|
|
2710
2872
|
if (results.length >= maxResults) break;
|
|
2711
2873
|
try {
|
|
2712
|
-
const content =
|
|
2874
|
+
const content = readFileSync7(file, "utf8");
|
|
2713
2875
|
const lines = content.split("\n");
|
|
2714
2876
|
for (let i = 0; i < lines.length; i++) {
|
|
2715
2877
|
const lower = lines[i].toLowerCase();
|
|
@@ -2730,7 +2892,7 @@ function collectMarkdownFiles(dir) {
|
|
|
2730
2892
|
const files = [];
|
|
2731
2893
|
try {
|
|
2732
2894
|
for (const entry of readdirSync2(dir)) {
|
|
2733
|
-
const full =
|
|
2895
|
+
const full = join15(dir, entry);
|
|
2734
2896
|
const stat = statSync(full);
|
|
2735
2897
|
if (stat.isDirectory()) {
|
|
2736
2898
|
files.push(...collectMarkdownFiles(full));
|
|
@@ -2764,6 +2926,18 @@ async function runServe(cwd2, opts) {
|
|
|
2764
2926
|
}
|
|
2765
2927
|
process.stderr.write(`[agent-harness-kit] MCP server starting (stdio)
|
|
2766
2928
|
`);
|
|
2929
|
+
const syncResult = checkPermissionsSync(cwd2);
|
|
2930
|
+
if (!syncResult.in_sync) {
|
|
2931
|
+
const affected = Object.entries(syncResult.agents).filter(([, r]) => !r.ok).map(([name, r]) => {
|
|
2932
|
+
const parts = [];
|
|
2933
|
+
if (r.missing.length) parts.push(`missing: ${r.missing.map((t) => t.replace("mcp__agent-harness-kit__", "")).join(", ")}`);
|
|
2934
|
+
if (r.extra.length) parts.push(`extra: ${r.extra.map((t) => t.replace("mcp__agent-harness-kit__", "")).join(", ")}`);
|
|
2935
|
+
return `${name} (${parts.join("; ")})`;
|
|
2936
|
+
}).join("\n ");
|
|
2937
|
+
process.stderr.write(`[agent-harness-kit] Agent permissions out of sync. Run: ahk build --sync
|
|
2938
|
+
${affected}
|
|
2939
|
+
`);
|
|
2940
|
+
}
|
|
2767
2941
|
await startMcpServer(config, cwd2);
|
|
2768
2942
|
}
|
|
2769
2943
|
|
|
@@ -2842,13 +3016,13 @@ async function runStatus(cwd2, opts) {
|
|
|
2842
3016
|
}
|
|
2843
3017
|
|
|
2844
3018
|
// src/commands/sync.ts
|
|
2845
|
-
import { existsSync as
|
|
2846
|
-
import { join as
|
|
3019
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
|
|
3020
|
+
import { join as join16, resolve as resolve11 } from "path";
|
|
2847
3021
|
import pc10 from "picocolors";
|
|
2848
3022
|
async function runSync(cwd2, opts) {
|
|
2849
3023
|
const config = await loadConfig(cwd2);
|
|
2850
3024
|
const direction = opts.direction ?? "both";
|
|
2851
|
-
const featureListPath = resolve11(
|
|
3025
|
+
const featureListPath = resolve11(join16(cwd2, config.storage.dir, "feature_list.json"));
|
|
2852
3026
|
const db = await openDB(config, cwd2);
|
|
2853
3027
|
try {
|
|
2854
3028
|
if (direction === "in" || direction === "both") {
|
|
@@ -2862,13 +3036,13 @@ async function runSync(cwd2, opts) {
|
|
|
2862
3036
|
}
|
|
2863
3037
|
}
|
|
2864
3038
|
async function syncIn(featureListPath, db, dryRun) {
|
|
2865
|
-
if (!
|
|
3039
|
+
if (!existsSync12(featureListPath)) {
|
|
2866
3040
|
console.log(pc10.dim(`feature_list.json not found at ${featureListPath} \u2014 skipping in-sync`));
|
|
2867
3041
|
return;
|
|
2868
3042
|
}
|
|
2869
3043
|
let seeds;
|
|
2870
3044
|
try {
|
|
2871
|
-
seeds = JSON.parse(
|
|
3045
|
+
seeds = JSON.parse(readFileSync8(featureListPath, "utf8"));
|
|
2872
3046
|
} catch (err) {
|
|
2873
3047
|
console.error(pc10.red(`Failed to parse feature_list.json: ${err}`));
|
|
2874
3048
|
process.exit(1);
|
|
@@ -2953,14 +3127,14 @@ async function runTaskAdd(cwd2) {
|
|
|
2953
3127
|
|
|
2954
3128
|
// src/commands/task/done.ts
|
|
2955
3129
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
2956
|
-
import { existsSync as
|
|
3130
|
+
import { existsSync as existsSync13 } from "fs";
|
|
2957
3131
|
import { resolve as resolve12 } from "path";
|
|
2958
3132
|
import pc12 from "picocolors";
|
|
2959
3133
|
async function runTaskDone(cwd2, idOrSlug) {
|
|
2960
3134
|
const config = await loadConfig(cwd2);
|
|
2961
3135
|
if (config.health.required) {
|
|
2962
3136
|
const scriptPath = resolve12(cwd2, config.health.scriptPath);
|
|
2963
|
-
if (
|
|
3137
|
+
if (existsSync13(scriptPath)) {
|
|
2964
3138
|
const result = spawnSync2("bash", [scriptPath], { cwd: cwd2, stdio: "pipe", encoding: "utf8" });
|
|
2965
3139
|
if (result.status !== 0) {
|
|
2966
3140
|
console.error(pc12.red("\u2717 Health check failed \u2014 cannot mark task as done."));
|
|
@@ -3133,10 +3307,10 @@ async function runTaskList(cwd2, opts) {
|
|
|
3133
3307
|
|
|
3134
3308
|
// src/core/package-data.ts
|
|
3135
3309
|
import { createRequire } from "module";
|
|
3136
|
-
import { dirname as dirname5, join as
|
|
3310
|
+
import { dirname as dirname5, join as join17 } from "path";
|
|
3137
3311
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3138
3312
|
var require2 = createRequire(import.meta.url);
|
|
3139
|
-
var pkgPath =
|
|
3313
|
+
var pkgPath = join17(dirname5(fileURLToPath3(import.meta.url)), "..", "package.json");
|
|
3140
3314
|
var pkg = require2(pkgPath);
|
|
3141
3315
|
|
|
3142
3316
|
// src/core/update-check.ts
|
|
@@ -3180,7 +3354,7 @@ program.name("ahk").description("agent-harness-kit \u2014 CLI scaffolding for mu
|
|
|
3180
3354
|
program.command("init").description("Scaffold a harness interactively in the current directory").option("--name <name>", "Project name (skip prompt)").option("--provider <provider>", "AI provider: claude-code | opencode (skip prompt)").option("--docs <path>", "Docs folder path (skip prompt)").option("--tasks <adapter>", "Task adapter: local | jira | linear (skip prompt)").action(async (opts) => {
|
|
3181
3355
|
await runInit(cwd, opts);
|
|
3182
3356
|
});
|
|
3183
|
-
program.command("build").description("Regenerate AGENTS.md and provider files from agent-harness-kit.config.ts").option("--watch", "Rebuild on config changes").action(async (opts) => {
|
|
3357
|
+
program.command("build").description("Regenerate AGENTS.md and provider files from agent-harness-kit.config.ts").option("--watch", "Rebuild on config changes").option("--sync", "Sync tools: frontmatter in existing .claude/agents/*.md to match current permission constants").action(async (opts) => {
|
|
3184
3358
|
await runBuild(cwd, opts);
|
|
3185
3359
|
});
|
|
3186
3360
|
program.command("health").description("Run health.sh and report result").action(async () => {
|