@cardor/agent-harness-kit 1.6.3 → 1.6.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 +41 -39
- package/dist/cli.js +18 -9
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ npx ahk init
|
|
|
46
46
|
- [`ahk export`](#ahk-export)
|
|
47
47
|
- [Files created by `ahk init`](#files-created-by-ahk-init)
|
|
48
48
|
- [What each file does](#what-each-file-does)
|
|
49
|
+
- [Tasks schema](#tasks-schema)
|
|
49
50
|
- [What you can customize](#what-you-can-customize)
|
|
50
51
|
- [`agent-harness-kit.config.ts`](#agent-harness-kitconfigts)
|
|
51
52
|
- [`health.sh`](#healthsh)
|
|
@@ -53,6 +54,7 @@ npx ahk init
|
|
|
53
54
|
- [`.harness/feature_list.json`](#harnessfeature_listjson)
|
|
54
55
|
- [MCP tools (for agents)](#mcp-tools-for-agents)
|
|
55
56
|
- [Agent roles](#agent-roles)
|
|
57
|
+
- [MCP tool permissions by role](#mcp-tool-permissions-by-role)
|
|
56
58
|
- [What to commit](#what-to-commit)
|
|
57
59
|
- [Runtime compatibility](#runtime-compatibility)
|
|
58
60
|
- [Contributing \& local development](#contributing--local-development)
|
|
@@ -577,55 +579,55 @@ Good acceptance criteria make the difference — the reviewer agent uses them to
|
|
|
577
579
|
|
|
578
580
|
The harness exposes these tools via MCP. Agents use them instead of reading files directly.
|
|
579
581
|
|
|
580
|
-
| Tool | Parameters | Description
|
|
581
|
-
| ------------------------- | ----------------------------------------------- |
|
|
582
|
-
| `tasks.get` | `status?` | List tasks, optionally filtered by `pending \| in_progress \| done \| blocked`
|
|
583
|
-
| `tasks.claim` | `id, agent` | Atomically claim a pending task. Returns `task_already_claimed` if another agent got it first
|
|
584
|
-
| `tasks.update` | `id, status` | Change task status
|
|
585
|
-
| `tasks.add` | `title, slug?, description?, acceptance?` | Create a new task directly from MCP (agents can queue work on the fly)
|
|
586
|
-
| `tasks.acceptance.update` | `criterionId` | Mark an acceptance criterion as met. Criterion IDs come from `tasks.acceptance_get`
|
|
587
|
-
| `actions.start` | `taskId, agent` | Start a new action, returns `actionId`
|
|
588
|
-
| `actions.write` | `actionId, sectionType, content` | Record a text section: `result \| tools_used \| blockers \| next_steps`. Does **not** populate the Files dashboard — use `actions.record_file` for that
|
|
589
|
-
| `actions.complete` | `actionId, summary` | Close an action with a one-line summary
|
|
590
|
-
| `actions.get` | `taskId` | Full action history for a task (all agents, all sections)
|
|
591
|
-
| `actions.record_file` | `actionId, filePath, operation, notes?` | Register a file touch. The **only** way to populate the Files dashboard. `operation`: `read \| created \| modified \| deleted`
|
|
592
|
-
| `actions.record_tool` | `actionId, toolName, argsJson?, resultSummary?` | Register a tool call. The **only** way to populate the Tools dashboard
|
|
593
|
-
| `docs.search` | `query` | Search the `docsPath` folder for content matching the query
|
|
594
|
-
| `tasks.acceptance_get` | `taskId`
|
|
595
|
-
| `deps.snapshot` | _(none)_ | Snapshot current `package.json` dependencies to `.harness/deps-lock.json`
|
|
596
|
-
| `deps.check` | _(none)_ | Compare current `package.json` against `.harness/deps-lock.json`. Returns `{ significant, added, removed, majorBumps, advisory }`
|
|
582
|
+
| Tool | Parameters | Description |
|
|
583
|
+
| ------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
584
|
+
| `tasks.get` | `status?` | List tasks, optionally filtered by `pending \| in_progress \| done \| blocked` |
|
|
585
|
+
| `tasks.claim` | `id, agent` | Atomically claim a pending task. Returns `task_already_claimed` if another agent got it first |
|
|
586
|
+
| `tasks.update` | `id, status` | Change task status |
|
|
587
|
+
| `tasks.add` | `title, slug?, description?, acceptance?` | Create a new task directly from MCP (agents can queue work on the fly) |
|
|
588
|
+
| `tasks.acceptance.update` | `criterionId` | Mark an acceptance criterion as met. Criterion IDs come from `tasks.acceptance_get` |
|
|
589
|
+
| `actions.start` | `taskId, agent` | Start a new action, returns `actionId` |
|
|
590
|
+
| `actions.write` | `actionId, sectionType, content` | Record a text section: `result \| tools_used \| blockers \| next_steps`. Does **not** populate the Files dashboard — use `actions.record_file` for that |
|
|
591
|
+
| `actions.complete` | `actionId, summary` | Close an action with a one-line summary |
|
|
592
|
+
| `actions.get` | `taskId` | Full action history for a task (all agents, all sections) |
|
|
593
|
+
| `actions.record_file` | `actionId, filePath, operation, notes?` | Register a file touch. The **only** way to populate the Files dashboard. `operation`: `read \| created \| modified \| deleted` |
|
|
594
|
+
| `actions.record_tool` | `actionId, toolName, argsJson?, resultSummary?` | Register a tool call. The **only** way to populate the Tools dashboard |
|
|
595
|
+
| `docs.search` | `query` | Search the `docsPath` folder for content matching the query |
|
|
596
|
+
| `tasks.acceptance_get` | `taskId` | Returns all acceptance criteria for a task with their `id`, `task_id`, `criterion` text, and `met` status. Use the returned `id` values with `tasks.acceptance.update` |
|
|
597
|
+
| `deps.snapshot` | _(none)_ | Snapshot current `package.json` dependencies to `.harness/deps-lock.json` |
|
|
598
|
+
| `deps.check` | _(none)_ | Compare current `package.json` against `.harness/deps-lock.json`. Returns `{ significant, added, removed, majorBumps, advisory }` |
|
|
597
599
|
|
|
598
600
|
---
|
|
599
601
|
|
|
600
602
|
## Agent roles
|
|
601
603
|
|
|
602
|
-
| Role
|
|
603
|
-
|
|
|
604
|
-
| **lead**
|
|
605
|
-
| **explorer**
|
|
606
|
-
| **consultant**
|
|
607
|
-
| **builder**
|
|
608
|
-
| **reviewer**
|
|
604
|
+
| Role | Responsibility |
|
|
605
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
606
|
+
| **lead** | Decomposes the task into a plan, assigns sub-agents. Does not write code or read source files. |
|
|
607
|
+
| **explorer** | Reads and maps the codebase. Never writes files. Records every file read. |
|
|
608
|
+
| **consultant** | Provides structured technical advisory after explorer. Runs conditionally. Never writes code. Writes advisory to harness via actions.write. |
|
|
609
|
+
| **builder** | Implements the plan. Only writes to `writablePaths`. Records every file modified. |
|
|
610
|
+
| **reviewer** | Verifies all acceptance criteria are met. Approves or blocks. Runs health check before approving. |
|
|
609
611
|
|
|
610
612
|
### MCP tool permissions by role
|
|
611
613
|
|
|
612
614
|
Each agent role has a scoped set of MCP tools enforced through the agent definition files.
|
|
613
615
|
|
|
614
|
-
| Tool
|
|
615
|
-
|
|
616
|
-
| `tasks.get`
|
|
617
|
-
| `tasks.claim`
|
|
618
|
-
| `tasks.add`
|
|
619
|
-
| `tasks.update`
|
|
620
|
-
| `tasks.edit`
|
|
621
|
-
| `tasks.archive` / `unarchive` |
|
|
622
|
-
| `tasks.acceptance_get`
|
|
623
|
-
| `tasks.acceptance.update`
|
|
624
|
-
| `actions.*` (all 6)
|
|
625
|
-
| `docs.search`
|
|
626
|
-
| `permissions.check`
|
|
627
|
-
| `deps.snapshot`
|
|
628
|
-
| `deps.check`
|
|
616
|
+
| Tool | lead | explorer | consultant | builder | reviewer |
|
|
617
|
+
| ----------------------------- | :--: | :------: | :--------: | :-----: | :------: |
|
|
618
|
+
| `tasks.get` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
619
|
+
| `tasks.claim` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
620
|
+
| `tasks.add` | ✅ | ❌ | ❌ | ✅ | ✅ |
|
|
621
|
+
| `tasks.update` | ✅ | ❌ | ❌ | ✅ | ✅ |
|
|
622
|
+
| `tasks.edit` | ✅ | ❌ | ❌ | ✅ | ✅ |
|
|
623
|
+
| `tasks.archive` / `unarchive` | ✅ | ❌ | ❌ | ✅ | ✅ |
|
|
624
|
+
| `tasks.acceptance_get` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
625
|
+
| `tasks.acceptance.update` | ❌ | ❌ | ❌ | ❌ | ✅ |
|
|
626
|
+
| `actions.*` (all 6) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
627
|
+
| `docs.search` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
628
|
+
| `permissions.check` | ✅ | ✅ | ❌ | ✅ | ✅ |
|
|
629
|
+
| `deps.snapshot` | ❌ | ❌ | ✅ | ❌ | ❌ |
|
|
630
|
+
| `deps.check` | ❌ | ❌ | ✅ | ❌ | ❌ |
|
|
629
631
|
|
|
630
632
|
**explorer** is read-only for task state — can query but cannot mutate status or mark criteria.
|
|
631
633
|
**reviewer** is the only role that can mark acceptance criteria as met (`tasks.acceptance.update`).
|
package/dist/cli.js
CHANGED
|
@@ -139,8 +139,11 @@ var MCP_CLAUDE_PERMISSIONS_CONSULTANT = [
|
|
|
139
139
|
"mcp__agent-harness-kit__actions_record_file",
|
|
140
140
|
"mcp__agent-harness-kit__actions_record_tool",
|
|
141
141
|
"mcp__agent-harness-kit__tasks_get",
|
|
142
|
+
"mcp__agent-harness-kit__tasks_claim",
|
|
143
|
+
"mcp__agent-harness-kit__tasks_acceptance_get",
|
|
142
144
|
"mcp__agent-harness-kit__deps_snapshot",
|
|
143
|
-
"mcp__agent-harness-kit__deps_check"
|
|
145
|
+
"mcp__agent-harness-kit__deps_check",
|
|
146
|
+
"mcp__agent-harness-kit__docs_search"
|
|
144
147
|
];
|
|
145
148
|
var MCP_CLAUDE_PERMISSIONS = [
|
|
146
149
|
.../* @__PURE__ */ new Set([
|
|
@@ -579,6 +582,12 @@ ${mcpLines}
|
|
|
579
582
|
`;
|
|
580
583
|
});
|
|
581
584
|
}
|
|
585
|
+
function translateFrontmatterForOpenCode(md) {
|
|
586
|
+
return md.replace(/(tools:\n(?: - [^\n]+\n)+)/, (match) => {
|
|
587
|
+
const tools = [...match.matchAll(/ - ([^\n]+)/g)].map((m) => m[1].trim());
|
|
588
|
+
return "tools:\n" + tools.map((t) => ` ${t.toLocaleLowerCase()}: true`).join("\n") + "\n";
|
|
589
|
+
});
|
|
590
|
+
}
|
|
582
591
|
var GITIGNORE_ENTRIES = `
|
|
583
592
|
# agent-harness-kit
|
|
584
593
|
.harness/harness.db
|
|
@@ -789,10 +798,10 @@ No tasks in progress.
|
|
|
789
798
|
const projectName = config.project.name;
|
|
790
799
|
const allowedPaths = (config.agents.explorer.allowedPaths ?? []).join(", ");
|
|
791
800
|
const writablePaths = (config.agents.builder.writablePaths ?? []).join(", ");
|
|
792
|
-
writeAgentFile(cwd2, ".opencode/agents/lead.md", agentLead({ projectName }));
|
|
793
|
-
writeAgentFile(cwd2, ".opencode/agents/explorer.md", agentExplorer({ projectName, allowedPaths }));
|
|
794
|
-
writeAgentFile(cwd2, ".opencode/agents/builder.md", agentBuilder({ projectName, writablePaths }));
|
|
795
|
-
writeAgentFile(cwd2, ".opencode/agents/reviewer.md", agentReviewer({ projectName }));
|
|
801
|
+
writeAgentFile(cwd2, ".opencode/agents/lead.md", translateFrontmatterForOpenCode(agentLead({ projectName })));
|
|
802
|
+
writeAgentFile(cwd2, ".opencode/agents/explorer.md", translateFrontmatterForOpenCode(agentExplorer({ projectName, allowedPaths })));
|
|
803
|
+
writeAgentFile(cwd2, ".opencode/agents/builder.md", translateFrontmatterForOpenCode(agentBuilder({ projectName, writablePaths })));
|
|
804
|
+
writeAgentFile(cwd2, ".opencode/agents/reviewer.md", translateFrontmatterForOpenCode(agentReviewer({ projectName })));
|
|
796
805
|
mergeOpencodeJson(join6(cwd2, "opencode.json"), config.tools.mcp.port);
|
|
797
806
|
appendGitignore(cwd2);
|
|
798
807
|
}
|
|
@@ -806,10 +815,10 @@ No tasks in progress.
|
|
|
806
815
|
const projectName = config.project.name;
|
|
807
816
|
const allowedPaths = (config.agents.explorer.allowedPaths ?? []).join(", ");
|
|
808
817
|
const writablePaths = (config.agents.builder.writablePaths ?? []).join(", ");
|
|
809
|
-
writeAgentFile(cwd2, ".opencode/agents/lead.md", agentLead({ projectName }));
|
|
810
|
-
writeAgentFile(cwd2, ".opencode/agents/explorer.md", agentExplorer({ projectName, allowedPaths }));
|
|
811
|
-
writeAgentFile(cwd2, ".opencode/agents/builder.md", agentBuilder({ projectName, writablePaths }));
|
|
812
|
-
writeAgentFile(cwd2, ".opencode/agents/reviewer.md", agentReviewer({ projectName }));
|
|
818
|
+
writeAgentFile(cwd2, ".opencode/agents/lead.md", translateFrontmatterForOpenCode(agentLead({ projectName })));
|
|
819
|
+
writeAgentFile(cwd2, ".opencode/agents/explorer.md", translateFrontmatterForOpenCode(agentExplorer({ projectName, allowedPaths })));
|
|
820
|
+
writeAgentFile(cwd2, ".opencode/agents/builder.md", translateFrontmatterForOpenCode(agentBuilder({ projectName, writablePaths })));
|
|
821
|
+
writeAgentFile(cwd2, ".opencode/agents/reviewer.md", translateFrontmatterForOpenCode(agentReviewer({ projectName })));
|
|
813
822
|
mergeOpencodeJson(join6(cwd2, "opencode.json"), config.tools.mcp.port);
|
|
814
823
|
}
|
|
815
824
|
async migrate(config, _to, _cwd) {
|