@cardor/agent-harness-kit 0.16.5 → 0.16.8

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.
@@ -30,6 +30,41 @@ You may only write to: `{{writablePaths}}`
30
30
 
31
31
  Do not modify files outside these paths. If the task requires it, record a blocker and stop.
32
32
 
33
+ ---
34
+
35
+ ## !! MANDATORY TRACKING — DO THIS FOR EVERY ACTION, NO EXCEPTIONS !!
36
+
37
+ These three calls are **not optional**. The dashboard cannot display what you do not report. Missing any of them is a failure of your role.
38
+
39
+ ### 1. Log every tool call you make
40
+
41
+ After **each** tool invocation (Read, Edit, Write, Bash), immediately call:
42
+
43
+ ```
44
+ actions.write(actionId, 'tools_used', '<ToolName>: <args-summary> — why')
45
+ ```
46
+
47
+ Examples:
48
+ - `Read: src/auth/middleware.ts — understand existing JWT pattern`
49
+ - `Bash: npm test -- --testPathPattern=auth — verify auth tests pass`
50
+ - `Edit: src/auth/middleware.ts:45-78 — add refresh token validation`
51
+
52
+ ### 2. Log every file you touch
53
+
54
+ After **each** file modification (Edit, Write), immediately call:
55
+
56
+ ```
57
+ actions.write(actionId, 'files_modified', '<file-path> — what changed and why')
58
+ ```
59
+
60
+ Example: `src/auth/middleware.ts — added refresh token expiry check in validateToken()`
61
+
62
+ ### 3. Do not complete your action without both logs being up to date
63
+
64
+ If you touched 5 files and made 12 tool calls, there must be 5 `files_modified` entries and 12 `tools_used` entries before you call `actions.complete`.
65
+
66
+ ---
67
+
33
68
  ## Workflow
34
69
 
35
70
  ### 1. Read the full action history
@@ -48,13 +83,7 @@ actions.start(taskId, 'builder') → save the returned actionId
48
83
 
49
84
  ### 3. Implement in small, verifiable steps
50
85
 
51
- Work through the plan item by item. After each meaningful change:
52
-
53
- ```
54
- actions.write(actionId, 'files_modified', '<file-path — what changed and why>')
55
- ```
56
-
57
- Log each file as you modify it. Be specific: "Added JWT validation to src/middleware/auth.ts — lines 45–78".
86
+ Work through the plan item by item. Log each tool call and each file touched as described in the **MANDATORY TRACKING** section above — do it as you go, not at the end.
58
87
 
59
88
  ### 4. Follow existing patterns
60
89
 
@@ -97,6 +126,7 @@ actions.complete(actionId, 'Implementation done — N files modified, tests pass
97
126
  - **Read the plan and analysis first.** Never implement cold.
98
127
  - **Only write to `{{writablePaths}}`.** No exceptions.
99
128
  - **Log every file you touch.** No silent modifications.
129
+ - **Log every tool call.** Use `actions.write(actionId, 'tools_used', ...)` after each Read, Edit, Write, Bash invocation.
100
130
  - **Leave tests green.** If tests fail after your changes, fix them before completing.
101
131
  - **Do not refactor beyond the task scope.** Implement what was asked, nothing more.
102
132
  - **If blocked, say so.** Do not invent workarounds for unclear requirements.
@@ -29,6 +29,29 @@ You may read files under: `{{allowedPaths}}`
29
29
 
30
30
  If you need to read outside these paths, record that as a blocker — do not proceed.
31
31
 
32
+ ---
33
+
34
+ ## !! MANDATORY TRACKING — DO THIS FOR EVERY ACTION, NO EXCEPTIONS !!
35
+
36
+ These calls are **not optional**. The dashboard cannot display what you do not report. Missing them is a failure of your role.
37
+
38
+ ### Log every tool call you make
39
+
40
+ After **each** tool invocation (Read, Bash, grep, docs.search), immediately call:
41
+
42
+ ```
43
+ actions.write(actionId, 'tools_used', '<ToolName>: <args-summary> — why')
44
+ ```
45
+
46
+ Examples:
47
+ - `Read: src/auth/middleware.ts — find existing JWT pattern`
48
+ - `Bash: grep -r "refreshToken" src/ — locate all refresh token usages`
49
+ - `docs.search: "authentication middleware" — check project docs for auth guidance`
50
+
51
+ **Every single tool call must be logged.** No silent reads. The audit trail in the dashboard is built entirely from these entries.
52
+
53
+ ---
54
+
32
55
  ## Workflow
33
56
 
34
57
  ### 1. Read the lead's plan
@@ -59,13 +82,9 @@ Read `AGENTS.md` → follow its map → open only the specific files relevant to
59
82
 
60
83
  Do NOT read the entire codebase. Be targeted.
61
84
 
62
- ### 5. Record every file you open
63
-
64
- ```
65
- actions.write(actionId, 'tools_used', '<tool: file-path — why you read it>')
66
- ```
85
+ ### 5. Log every tool call as you make it
67
86
 
68
- Log each file as you open it. This creates the audit trail.
87
+ Log each invocation as described in the **MANDATORY TRACKING** section above — do it immediately after each tool call, not at the end.
69
88
 
70
89
  ### 6. Produce a structured analysis
71
90
 
@@ -24,6 +24,29 @@ You are the **lead agent** for `{{projectName}}`. Your job is to orchestrate the
24
24
  - Re-coordinate if the Reviewer blocks (send back to Builder with specific issues)
25
25
  - Close the session cleanly when the task is done
26
26
 
27
+ ---
28
+
29
+ ## !! MANDATORY TRACKING — DO THIS FOR EVERY ACTION, NO EXCEPTIONS !!
30
+
31
+ These calls are **not optional**. The dashboard cannot display what you do not report.
32
+
33
+ ### Log every tool call you make
34
+
35
+ After **each** tool invocation (Bash, tasks.get, tasks.claim, actions.get), immediately call:
36
+
37
+ ```
38
+ actions.write(actionId, 'tools_used', '<ToolName>: <args-summary> — why')
39
+ ```
40
+
41
+ Examples:
42
+ - `Bash: bash health.sh — verify codebase health before starting`
43
+ - `tasks.get: pending — find next task to claim`
44
+ - `actions.get: taskId=abc123 — read action history to resume in-progress task`
45
+
46
+ **Log every call.** This applies from the moment you have an `actionId` (after step 3 below).
47
+
48
+ ---
49
+
27
50
  ## Workflow
28
51
 
29
52
  ### 1. Orient (always first)
@@ -24,6 +24,39 @@ You are the **reviewer agent** for `{{projectName}}`. Your job is to verify —
24
24
  - Block clearly with specific, actionable issues when they are not
25
25
  - Never approve to be helpful — only approve when the work is genuinely complete
26
26
 
27
+ ---
28
+
29
+ ## !! MANDATORY TRACKING — DO THIS FOR EVERY ACTION, NO EXCEPTIONS !!
30
+
31
+ These calls are **not optional**. The dashboard cannot display what you do not report.
32
+
33
+ ### 1. Log every tool call you make
34
+
35
+ After **each** tool invocation (Read, Bash), immediately call:
36
+
37
+ ```
38
+ actions.write(actionId, 'tools_used', '<ToolName>: <args-summary> — why')
39
+ ```
40
+
41
+ Examples:
42
+ - `Read: src/auth/middleware.ts — verify refresh token logic matches criterion 2`
43
+ - `Bash: npm test -- --testPathPattern=auth — confirm all auth tests pass`
44
+
45
+ ### 2. Mark every acceptance criterion as you verify it
46
+
47
+ For **each** criterion (0-based index), call this immediately after you evaluate it:
48
+
49
+ ```
50
+ tasks.acceptance_update(taskId, criterionIndex, true|false)
51
+ ```
52
+
53
+ - `true` = criterion is fully met
54
+ - `false` = criterion is not met
55
+
56
+ If the task has 3 criteria, you must make exactly 3 `tasks.acceptance_update` calls — one per criterion. Skipping any of them leaves the dashboard showing criteria as unverified.
57
+
58
+ ---
59
+
27
60
  ## Workflow
28
61
 
29
62
  ### 1. Read the full task history
@@ -47,12 +80,7 @@ actions.start(taskId, 'reviewer') → save the returned actionId
47
80
 
48
81
  ### 3. Verify each acceptance criterion
49
82
 
50
- For each criterion in the task:
51
- - Read the relevant files
52
- - Run relevant commands if needed (tests, linting, type-checks)
53
- - Mark it as met or unmet
54
-
55
- Keep a running checklist as you go.
83
+ For each criterion: read the relevant files, run commands if needed, then immediately call `tasks.acceptance_update` as described in the **MANDATORY TRACKING** section above. Do this per-criterion as you go — not in batch at the end.
56
84
 
57
85
  ### 4. Run the health check
58
86
 
@@ -96,6 +124,7 @@ Then notify lead so the builder can be re-assigned.
96
124
 
97
125
  - **Run health.sh before approving.** No exceptions.
98
126
  - **Check every acceptance criterion.** Not just the obvious ones.
127
+ - **Call `tasks.acceptance_update()` for each criterion.** Both met and unmet — never skip this step.
99
128
  - **Never self-approve partial work.** All criteria must be met, not most.
100
129
  - **Be specific when blocking.** The builder must know exactly what to fix.
101
130
  - **Do not fix issues yourself.** Your job is to verify, not to implement.
package/dist/cli.js CHANGED
@@ -1155,9 +1155,10 @@ import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync7 } from "fs";
1155
1155
  import { homedir } from "os";
1156
1156
  import { join as join9 } from "path";
1157
1157
  import * as p2 from "@clack/prompts";
1158
- import pc5 from "picocolors";
1158
+ import pc6 from "picocolors";
1159
1159
 
1160
1160
  // src/commands/init-helpers.ts
1161
+ import pc5 from "picocolors";
1161
1162
  function applyConfigDefaults(params) {
1162
1163
  return {
1163
1164
  provider: params.provider,
@@ -1197,10 +1198,43 @@ function applyConfigDefaults(params) {
1197
1198
  }
1198
1199
  };
1199
1200
  }
1201
+ function stripAnsi(str2) {
1202
+ return str2.replace(/\x1B\[[0-9;]*m/g, "");
1203
+ }
1204
+ function drawBox(lines) {
1205
+ const width = Math.max(...lines.map((l) => stripAnsi(l).length));
1206
+ const border = "\u2500".repeat(width);
1207
+ console.log(pc5.yellow(`\u250C${border}\u2510`));
1208
+ for (const line of lines) {
1209
+ const pad = width - stripAnsi(line).length;
1210
+ const padStr = pad > 0 ? " ".repeat(pad) : "";
1211
+ console.log(pc5.yellow("\u2502") + line + padStr + pc5.yellow("\u2502"));
1212
+ }
1213
+ console.log(pc5.yellow(`\u2514${border}\u2518`));
1214
+ }
1215
+ function printWelcomeMessage(projectName) {
1216
+ const sep = "\u2500".repeat(38);
1217
+ const lines = [
1218
+ ` ${pc5.bold(pc5.white("agent-harness-kit"))} `,
1219
+ ` ${pc5.gray("\u2014")} harness scaffolding ${pc5.gray("\u2014")} `,
1220
+ ` ${pc5.gray(sep)} `,
1221
+ ` ${pc5.bold("Project:")} ${projectName || "\u2014"} `,
1222
+ ` ${pc5.bold("Status:")} ${pc5.green("ready to configure")} `,
1223
+ ` ${pc5.gray(sep)} `,
1224
+ ` ${pc5.gray("Next steps:")} `,
1225
+ ` ${pc5.gray("\u2192")} ${pc5.gray("Set up your AI provider config")} `,
1226
+ ` ${pc5.gray("\u2192")} ${pc5.gray("Run your health check to verify")} `,
1227
+ ` ${pc5.gray("\u2192")} ${pc5.gray("Start adding tasks for your agents")} `
1228
+ ];
1229
+ console.log();
1230
+ drawBox(lines);
1231
+ console.log();
1232
+ }
1200
1233
 
1201
1234
  // src/commands/init.ts
1202
1235
  async function runInit(cwd2, flags) {
1203
- p2.intro(pc5.bold("agent-harness-kit \u2014 harness scaffolding"));
1236
+ const projectName = flags.name || "my-project";
1237
+ printWelcomeMessage(projectName);
1204
1238
  let name;
1205
1239
  if (flags.name) {
1206
1240
  name = flags.name;
@@ -1281,14 +1315,14 @@ async function runInit(cwd2, flags) {
1281
1315
  ]
1282
1316
  });
1283
1317
  if (p2.isCancel(val)) {
1284
- p2.cancel("Cancelled.");
1318
+ p2.cancel("Cancelled");
1285
1319
  process.exit(0);
1286
1320
  }
1287
1321
  tasksAdapter = val;
1288
1322
  }
1289
1323
  const addFirstTask = await p2.confirm({ message: "Add your first task now?", initialValue: true });
1290
1324
  if (p2.isCancel(addFirstTask)) {
1291
- p2.cancel("Cancelled.");
1325
+ p2.cancel("Cancelled");
1292
1326
  process.exit(0);
1293
1327
  }
1294
1328
  let firstTask;
@@ -1298,7 +1332,7 @@ async function runInit(cwd2, flags) {
1298
1332
  validate: (v) => v.trim() ? void 0 : "Title is required"
1299
1333
  });
1300
1334
  if (p2.isCancel(titleVal)) {
1301
- p2.cancel("Cancelled.");
1335
+ p2.cancel("Cancelled");
1302
1336
  process.exit(0);
1303
1337
  }
1304
1338
  const taskTitle = titleVal.trim();
@@ -1307,7 +1341,7 @@ async function runInit(cwd2, flags) {
1307
1341
  placeholder: "What and why"
1308
1342
  });
1309
1343
  if (p2.isCancel(taskDescVal)) {
1310
- p2.cancel("Cancelled.");
1344
+ p2.cancel("Cancelled");
1311
1345
  process.exit(0);
1312
1346
  }
1313
1347
  const taskDesc = taskDescVal.trim();
@@ -1365,29 +1399,29 @@ async function runInit(cwd2, flags) {
1365
1399
  process.exit(1);
1366
1400
  }
1367
1401
  const agentHarnessKitDir = globalInstallation ? "home directory" : "current directory";
1368
- console.log(pc5.green(`\u2713 Scaffolded harness in ${agentHarnessKitDir}`));
1402
+ console.log(pc6.green(`\u2713 Scaffolded harness in ${agentHarnessKitDir}`));
1369
1403
  const agentsDir = provider === "claude-code" ? ".claude/agents/" : ".opencode/agents/";
1370
1404
  const mcpFile = provider === "claude-code" ? ".claude/mcp.json" : "./opencode.json";
1371
1405
  console.log("");
1372
- console.log(pc5.green("\u2713 agent-harness-kit.config.ts"));
1373
- console.log(pc5.green("\u2713 AGENTS.md"));
1374
- console.log(pc5.green("\u2713 health.sh"));
1375
- console.log(pc5.green("\u2713 .harness/harness.db"));
1376
- console.log(pc5.green("\u2713 .harness/current.md"));
1377
- console.log(pc5.green(`\u2713 ${agentsDir}lead.md`));
1378
- console.log(pc5.green(`\u2713 ${agentsDir}explorer.md`));
1379
- console.log(pc5.green(`\u2713 ${agentsDir}builder.md`));
1380
- console.log(pc5.green(`\u2713 ${agentsDir}reviewer.md`));
1381
- console.log(pc5.green(`\u2713 ${mcpFile}`));
1382
- console.log(pc5.green("\u2713 .gitignore entries added"));
1406
+ console.log(pc6.green("\u2713 agent-harness-kit.config.ts"));
1407
+ console.log(pc6.green("\u2713 AGENTS.md"));
1408
+ console.log(pc6.green("\u2713 health.sh"));
1409
+ console.log(pc6.green("\u2713 .harness/harness.db"));
1410
+ console.log(pc6.green("\u2713 .harness/current.md"));
1411
+ console.log(pc6.green(`\u2713 ${agentsDir}lead.md`));
1412
+ console.log(pc6.green(`\u2713 ${agentsDir}explorer.md`));
1413
+ console.log(pc6.green(`\u2713 ${agentsDir}builder.md`));
1414
+ console.log(pc6.green(`\u2713 ${agentsDir}reviewer.md`));
1415
+ console.log(pc6.green(`\u2713 ${mcpFile}`));
1416
+ console.log(pc6.green("\u2713 .gitignore entries added"));
1383
1417
  console.log("");
1384
- console.log(pc5.cyan("\u2192") + ` Edit ${pc5.cyan("health.sh")} with your project checks`);
1385
- console.log(pc5.cyan("\u2192") + ` ${pc5.cyan("ahk task add")} to queue work for agents`);
1418
+ console.log(pc6.cyan("\u2192") + ` Edit ${pc6.cyan("health.sh")} with your project checks`);
1419
+ console.log(pc6.cyan("\u2192") + ` ${pc6.cyan("ahk task add")} to queue work for agents`);
1386
1420
  }
1387
1421
 
1388
1422
  // src/commands/migrate.ts
1389
1423
  import * as p3 from "@clack/prompts";
1390
- import pc6 from "picocolors";
1424
+ import pc7 from "picocolors";
1391
1425
  async function runMigrate(cwd2, opts) {
1392
1426
  const config = await loadConfig(cwd2);
1393
1427
  let target;
@@ -1408,7 +1442,7 @@ async function runMigrate(cwd2, opts) {
1408
1442
  target = val;
1409
1443
  }
1410
1444
  if (target === config.provider) {
1411
- console.log(pc6.dim(`Already on ${target} \u2014 nothing to migrate.`));
1445
+ console.log(pc7.dim(`Already on ${target} \u2014 nothing to migrate.`));
1412
1446
  return;
1413
1447
  }
1414
1448
  const spinner5 = p3.spinner();
@@ -1416,11 +1450,11 @@ async function runMigrate(cwd2, opts) {
1416
1450
  try {
1417
1451
  const targetMaterializer = getMaterializer(target);
1418
1452
  await targetMaterializer.build(config, cwd2);
1419
- spinner5.stop(pc6.green(`Migrated to ${target}`));
1453
+ spinner5.stop(pc7.green(`Migrated to ${target}`));
1420
1454
  p3.log.warn(`Update agent-harness-kit.config.ts: set provider: '${target}'`);
1421
1455
  p3.log.warn(`Then run: ahk build`);
1422
1456
  } catch (err) {
1423
- spinner5.stop(pc6.red("Migration failed"));
1457
+ spinner5.stop(pc7.red("Migration failed"));
1424
1458
  p3.log.error(err instanceof Error ? err.message : String(err));
1425
1459
  process.exit(1);
1426
1460
  }
@@ -1734,12 +1768,12 @@ async function runServe(cwd2, opts) {
1734
1768
 
1735
1769
  // src/commands/status.ts
1736
1770
  import Table from "cli-table3";
1737
- import pc7 from "picocolors";
1771
+ import pc8 from "picocolors";
1738
1772
  var STATUS_COLOR = {
1739
- pending: (s) => pc7.dim(s),
1740
- in_progress: (s) => pc7.cyan(s),
1741
- done: (s) => pc7.green(s),
1742
- blocked: (s) => pc7.red(s)
1773
+ pending: (s) => pc8.dim(s),
1774
+ in_progress: (s) => pc8.cyan(s),
1775
+ done: (s) => pc8.green(s),
1776
+ blocked: (s) => pc8.red(s)
1743
1777
  };
1744
1778
  async function runStatus(cwd2, opts) {
1745
1779
  const config = await loadConfig(cwd2);
@@ -1757,11 +1791,11 @@ async function runStatus(cwd2, opts) {
1757
1791
  return;
1758
1792
  }
1759
1793
  if (tasks.length === 0) {
1760
- console.log(pc7.dim("No tasks yet. Run: ahk task add"));
1794
+ console.log(pc8.dim("No tasks yet. Run: ahk task add"));
1761
1795
  return;
1762
1796
  }
1763
1797
  const table = new Table({
1764
- head: ["ID", "Slug", "Title", "Status", "Assigned", "Started"].map((h) => pc7.bold(h)),
1798
+ head: ["ID", "Slug", "Title", "Status", "Assigned", "Started"].map((h) => pc8.bold(h)),
1765
1799
  style: { head: [], border: [] }
1766
1800
  });
1767
1801
  for (const t of tasks) {
@@ -1779,12 +1813,12 @@ async function runStatus(cwd2, opts) {
1779
1813
  const inProgress = tasks.filter((t) => t.status === "in_progress");
1780
1814
  if (inProgress.length > 0) {
1781
1815
  console.log("");
1782
- console.log(pc7.bold("Active actions:"));
1816
+ console.log(pc8.bold("Active actions:"));
1783
1817
  for (const t of inProgress) {
1784
1818
  const actions = db.getActionsForTask(t.id);
1785
1819
  const active = actions.filter((a) => a.status === "in_progress");
1786
1820
  for (const a of active) {
1787
- console.log(` ${pc7.cyan(a.agent.padEnd(10))} \u2192 task #${t.id} ${t.slug}`);
1821
+ console.log(` ${pc8.cyan(a.agent.padEnd(10))} \u2192 task #${t.id} ${t.slug}`);
1788
1822
  }
1789
1823
  }
1790
1824
  }
@@ -1793,7 +1827,7 @@ async function runStatus(cwd2, opts) {
1793
1827
  const fn = STATUS_COLOR[s.status] ?? ((x) => x);
1794
1828
  return `${fn(s.status)}: ${s.total}`;
1795
1829
  });
1796
- console.log(pc7.dim("Tasks \u2014 ") + parts.join(pc7.dim(" | ")));
1830
+ console.log(pc8.dim("Tasks \u2014 ") + parts.join(pc8.dim(" | ")));
1797
1831
  } finally {
1798
1832
  db.close();
1799
1833
  }
@@ -1802,7 +1836,7 @@ async function runStatus(cwd2, opts) {
1802
1836
  // src/commands/sync.ts
1803
1837
  import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
1804
1838
  import { join as join11, resolve as resolve8 } from "path";
1805
- import pc8 from "picocolors";
1839
+ import pc9 from "picocolors";
1806
1840
  async function runSync(cwd2, opts) {
1807
1841
  const config = await loadConfig(cwd2);
1808
1842
  const direction = opts.direction ?? "both";
@@ -1821,43 +1855,43 @@ async function runSync(cwd2, opts) {
1821
1855
  }
1822
1856
  async function syncIn(featureListPath, db, dryRun) {
1823
1857
  if (!existsSync7(featureListPath)) {
1824
- console.log(pc8.dim(`feature_list.json not found at ${featureListPath} \u2014 skipping in-sync`));
1858
+ console.log(pc9.dim(`feature_list.json not found at ${featureListPath} \u2014 skipping in-sync`));
1825
1859
  return;
1826
1860
  }
1827
1861
  let seeds;
1828
1862
  try {
1829
1863
  seeds = JSON.parse(readFileSync6(featureListPath, "utf8"));
1830
1864
  } catch (err) {
1831
- console.error(pc8.red(`Failed to parse feature_list.json: ${err}`));
1865
+ console.error(pc9.red(`Failed to parse feature_list.json: ${err}`));
1832
1866
  process.exit(1);
1833
1867
  }
1834
1868
  if (dryRun) {
1835
- console.log(pc8.bold("Dry run \u2014 in-sync (feature_list.json \u2192 SQLite):"));
1869
+ console.log(pc9.bold("Dry run \u2014 in-sync (feature_list.json \u2192 SQLite):"));
1836
1870
  for (const t of seeds) {
1837
1871
  const existing = db.getTaskBySlug(t.slug);
1838
- console.log(` ${existing ? pc8.dim("skip") : pc8.green("add ")} ${t.slug}`);
1872
+ console.log(` ${existing ? pc9.dim("skip") : pc9.green("add ")} ${t.slug}`);
1839
1873
  }
1840
1874
  return;
1841
1875
  }
1842
1876
  const result = db.syncFromFeatureList(seeds);
1843
- console.log(pc8.green(`\u2713 In-sync: ${result.added} added, ${result.skipped} already existed`));
1877
+ console.log(pc9.green(`\u2713 In-sync: ${result.added} added, ${result.skipped} already existed`));
1844
1878
  }
1845
1879
  function syncOut(db, cwd2, dryRun) {
1846
1880
  if (dryRun) {
1847
1881
  const tasks = db.getTasks();
1848
- console.log(pc8.bold("Dry run \u2014 out-sync (SQLite \u2192 feature_list.json):"));
1882
+ console.log(pc9.bold("Dry run \u2014 out-sync (SQLite \u2192 feature_list.json):"));
1849
1883
  console.log(` ${tasks.length} tasks would be written`);
1850
1884
  return;
1851
1885
  }
1852
1886
  db.writeFeatureList(cwd2);
1853
- console.log(pc8.green("\u2713 Out-sync: feature_list.json updated"));
1887
+ console.log(pc9.green("\u2713 Out-sync: feature_list.json updated"));
1854
1888
  }
1855
1889
 
1856
1890
  // src/commands/task/add.ts
1857
1891
  import * as p4 from "@clack/prompts";
1858
- import pc9 from "picocolors";
1892
+ import pc10 from "picocolors";
1859
1893
  async function runTaskAdd(cwd2) {
1860
- p4.intro(pc9.bold("agent-harness-kit \u2014 add task"));
1894
+ p4.intro(pc10.bold("agent-harness-kit \u2014 add task"));
1861
1895
  const titleVal = await p4.text({
1862
1896
  message: "Task title",
1863
1897
  validate: (v) => v.trim() ? void 0 : "Title is required"
@@ -1893,10 +1927,10 @@ async function runTaskAdd(cwd2) {
1893
1927
  db.writeFeatureList(cwd2);
1894
1928
  db.close();
1895
1929
  spinner5.stop("");
1896
- console.log(pc9.green(`\u2713 Task #${task2.id} added \u2014 ${task2.slug} (pending)`));
1897
- console.log(pc9.cyan("\u2192") + " " + pc9.cyan("ahk status") + " to see all tasks");
1930
+ console.log(pc10.green(`\u2713 Task #${task2.id} added \u2014 ${task2.slug} (pending)`));
1931
+ console.log(pc10.cyan("\u2192") + " " + pc10.cyan("ahk status") + " to see all tasks");
1898
1932
  } catch (err) {
1899
- spinner5.stop(pc9.red("Failed"));
1933
+ spinner5.stop(pc10.red("Failed"));
1900
1934
  p4.log.error(err instanceof Error ? err.message : String(err));
1901
1935
  process.exit(1);
1902
1936
  }
@@ -1906,7 +1940,7 @@ async function runTaskAdd(cwd2) {
1906
1940
  import { spawnSync as spawnSync2 } from "child_process";
1907
1941
  import { existsSync as existsSync8 } from "fs";
1908
1942
  import { resolve as resolve9 } from "path";
1909
- import pc10 from "picocolors";
1943
+ import pc11 from "picocolors";
1910
1944
  async function runTaskDone(cwd2, idOrSlug) {
1911
1945
  const config = await loadConfig(cwd2);
1912
1946
  if (config.health.required) {
@@ -1914,7 +1948,7 @@ async function runTaskDone(cwd2, idOrSlug) {
1914
1948
  if (existsSync8(scriptPath)) {
1915
1949
  const result = spawnSync2("bash", [scriptPath], { cwd: cwd2, stdio: "pipe", encoding: "utf8" });
1916
1950
  if (result.status !== 0) {
1917
- console.error(pc10.red("\u2717 Health check failed \u2014 cannot mark task as done."));
1951
+ console.error(pc11.red("\u2717 Health check failed \u2014 cannot mark task as done."));
1918
1952
  if (result.stdout) console.error(result.stdout);
1919
1953
  if (result.stderr) console.error(result.stderr);
1920
1954
  process.exit(1);
@@ -1927,16 +1961,16 @@ async function runTaskDone(cwd2, idOrSlug) {
1927
1961
  const isId = !isNaN(parsed);
1928
1962
  const task2 = isId ? db.getTaskById(parsed) : db.getTaskBySlug(idOrSlug);
1929
1963
  if (!task2) {
1930
- console.error(pc10.red(`Task not found: ${idOrSlug}`));
1964
+ console.error(pc11.red(`Task not found: ${idOrSlug}`));
1931
1965
  process.exit(1);
1932
1966
  }
1933
1967
  if (task2.status === "done") {
1934
- console.log(pc10.dim(`Task #${task2.id} is already done.`));
1968
+ console.log(pc11.dim(`Task #${task2.id} is already done.`));
1935
1969
  return;
1936
1970
  }
1937
1971
  db.updateTaskStatus(task2.id, "done");
1938
1972
  db.writeFeatureList(cwd2);
1939
- console.log(pc10.green(`\u2713 Task #${task2.id} \u2014 ${task2.slug} marked as done`));
1973
+ console.log(pc11.green(`\u2713 Task #${task2.id} \u2014 ${task2.slug} marked as done`));
1940
1974
  } finally {
1941
1975
  db.close();
1942
1976
  }
@@ -1944,12 +1978,12 @@ async function runTaskDone(cwd2, idOrSlug) {
1944
1978
 
1945
1979
  // src/commands/task/list.ts
1946
1980
  import Table2 from "cli-table3";
1947
- import pc11 from "picocolors";
1981
+ import pc12 from "picocolors";
1948
1982
  var STATUS_COLOR2 = {
1949
- pending: (s) => pc11.dim(s),
1950
- in_progress: (s) => pc11.cyan(s),
1951
- done: (s) => pc11.green(s),
1952
- blocked: (s) => pc11.red(s)
1983
+ pending: (s) => pc12.dim(s),
1984
+ in_progress: (s) => pc12.cyan(s),
1985
+ done: (s) => pc12.green(s),
1986
+ blocked: (s) => pc12.red(s)
1953
1987
  };
1954
1988
  async function runTaskList(cwd2, opts) {
1955
1989
  const config = await loadConfig(cwd2);
@@ -1963,11 +1997,11 @@ async function runTaskList(cwd2, opts) {
1963
1997
  return;
1964
1998
  }
1965
1999
  if (tasks.length === 0) {
1966
- console.log(pc11.dim("No tasks" + (filterStatus ? ` with status: ${filterStatus}` : "") + "."));
2000
+ console.log(pc12.dim("No tasks" + (filterStatus ? ` with status: ${filterStatus}` : "") + "."));
1967
2001
  return;
1968
2002
  }
1969
2003
  const table = new Table2({
1970
- head: ["ID", "Slug", "Title", "Status"].map((h) => pc11.bold(h)),
2004
+ head: ["ID", "Slug", "Title", "Status"].map((h) => pc12.bold(h)),
1971
2005
  style: { head: [], border: [] }
1972
2006
  });
1973
2007
  for (const t of tasks) {
@@ -1989,7 +2023,7 @@ var pkgPath = join12(dirname5(fileURLToPath3(import.meta.url)), "..", "package.j
1989
2023
  var pkg = require2(pkgPath);
1990
2024
 
1991
2025
  // src/core/update-check.ts
1992
- import pc12 from "picocolors";
2026
+ import pc13 from "picocolors";
1993
2027
  var REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`;
1994
2028
  var TIMEOUT_MS = 2500;
1995
2029
  function checkForUpdate(currentVersion) {
@@ -2007,18 +2041,18 @@ function checkForUpdate(currentVersion) {
2007
2041
  }
2008
2042
  function printUpdateMessage({ current, latest }) {
2009
2043
  const lines = [
2010
- ` Update available ${pc12.dim(current)} \u2192 ${pc12.green(latest)} `,
2011
- ` Run: ${pc12.cyan(`npm i ${pkg.name}@${latest}`)} `
2044
+ ` Update available ${pc13.dim(current)} \u2192 ${pc13.green(latest)} `,
2045
+ ` Run: ${pc13.cyan(`npm i ${pkg.name}@${latest}`)} `
2012
2046
  ];
2013
- const width = Math.max(...lines.map((l) => stripAnsi(l).length));
2047
+ const width = Math.max(...lines.map((l) => stripAnsi2(l).length));
2014
2048
  const border = "\u2500".repeat(width);
2015
2049
  console.log();
2016
- console.log(pc12.yellow(`\u250C${border}\u2510`));
2050
+ console.log(pc13.yellow(`\u250C${border}\u2510`));
2017
2051
  for (const line of lines) {
2018
- const pad = width - stripAnsi(line).length;
2019
- console.log(pc12.yellow("\u2502") + line + " ".repeat(pad) + pc12.yellow("\u2502"));
2052
+ const pad = width - stripAnsi2(line).length;
2053
+ console.log(pc13.yellow("\u2502") + line + " ".repeat(pad) + pc13.yellow("\u2502"));
2020
2054
  }
2021
- console.log(pc12.yellow(`\u2514${border}\u2518`));
2055
+ console.log(pc13.yellow(`\u2514${border}\u2518`));
2022
2056
  console.log();
2023
2057
  }
2024
2058
  function isNewer(latest, current) {
@@ -2029,7 +2063,7 @@ function isNewer(latest, current) {
2029
2063
  if (lMin !== cMin) return lMin > cMin;
2030
2064
  return lPat > cPat;
2031
2065
  }
2032
- function stripAnsi(str2) {
2066
+ function stripAnsi2(str2) {
2033
2067
  return str2.replace(/\x1B\[[0-9;]*m/g, "");
2034
2068
  }
2035
2069