@cardor/agent-harness-kit 0.16.3 → 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.
- package/dist/agent-templates/builder.md +37 -7
- package/dist/agent-templates/explorer.md +25 -6
- package/dist/agent-templates/lead.md +23 -0
- package/dist/agent-templates/reviewer.md +35 -6
- package/dist/cli.js +149 -70
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1007,6 +1007,9 @@ var HarnessDB = class {
|
|
|
1007
1007
|
}
|
|
1008
1008
|
return { added, skipped };
|
|
1009
1009
|
}
|
|
1010
|
+
markAcceptanceMet(criterionId) {
|
|
1011
|
+
this.db.prepare(`UPDATE task_acceptance SET met = 1 WHERE id = ?`).run(criterionId);
|
|
1012
|
+
}
|
|
1010
1013
|
writeFeatureList(cwd2) {
|
|
1011
1014
|
const tasks = this.getTasks();
|
|
1012
1015
|
const list = tasks.map((t) => ({
|
|
@@ -1152,9 +1155,10 @@ import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
|
1152
1155
|
import { homedir } from "os";
|
|
1153
1156
|
import { join as join9 } from "path";
|
|
1154
1157
|
import * as p2 from "@clack/prompts";
|
|
1155
|
-
import
|
|
1158
|
+
import pc6 from "picocolors";
|
|
1156
1159
|
|
|
1157
1160
|
// src/commands/init-helpers.ts
|
|
1161
|
+
import pc5 from "picocolors";
|
|
1158
1162
|
function applyConfigDefaults(params) {
|
|
1159
1163
|
return {
|
|
1160
1164
|
provider: params.provider,
|
|
@@ -1194,10 +1198,43 @@ function applyConfigDefaults(params) {
|
|
|
1194
1198
|
}
|
|
1195
1199
|
};
|
|
1196
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
|
+
}
|
|
1197
1233
|
|
|
1198
1234
|
// src/commands/init.ts
|
|
1199
1235
|
async function runInit(cwd2, flags) {
|
|
1200
|
-
|
|
1236
|
+
const projectName = flags.name || "my-project";
|
|
1237
|
+
printWelcomeMessage(projectName);
|
|
1201
1238
|
let name;
|
|
1202
1239
|
if (flags.name) {
|
|
1203
1240
|
name = flags.name;
|
|
@@ -1278,14 +1315,14 @@ async function runInit(cwd2, flags) {
|
|
|
1278
1315
|
]
|
|
1279
1316
|
});
|
|
1280
1317
|
if (p2.isCancel(val)) {
|
|
1281
|
-
p2.cancel("Cancelled
|
|
1318
|
+
p2.cancel("Cancelled");
|
|
1282
1319
|
process.exit(0);
|
|
1283
1320
|
}
|
|
1284
1321
|
tasksAdapter = val;
|
|
1285
1322
|
}
|
|
1286
1323
|
const addFirstTask = await p2.confirm({ message: "Add your first task now?", initialValue: true });
|
|
1287
1324
|
if (p2.isCancel(addFirstTask)) {
|
|
1288
|
-
p2.cancel("Cancelled
|
|
1325
|
+
p2.cancel("Cancelled");
|
|
1289
1326
|
process.exit(0);
|
|
1290
1327
|
}
|
|
1291
1328
|
let firstTask;
|
|
@@ -1295,7 +1332,7 @@ async function runInit(cwd2, flags) {
|
|
|
1295
1332
|
validate: (v) => v.trim() ? void 0 : "Title is required"
|
|
1296
1333
|
});
|
|
1297
1334
|
if (p2.isCancel(titleVal)) {
|
|
1298
|
-
p2.cancel("Cancelled
|
|
1335
|
+
p2.cancel("Cancelled");
|
|
1299
1336
|
process.exit(0);
|
|
1300
1337
|
}
|
|
1301
1338
|
const taskTitle = titleVal.trim();
|
|
@@ -1304,7 +1341,7 @@ async function runInit(cwd2, flags) {
|
|
|
1304
1341
|
placeholder: "What and why"
|
|
1305
1342
|
});
|
|
1306
1343
|
if (p2.isCancel(taskDescVal)) {
|
|
1307
|
-
p2.cancel("Cancelled
|
|
1344
|
+
p2.cancel("Cancelled");
|
|
1308
1345
|
process.exit(0);
|
|
1309
1346
|
}
|
|
1310
1347
|
const taskDesc = taskDescVal.trim();
|
|
@@ -1362,29 +1399,29 @@ async function runInit(cwd2, flags) {
|
|
|
1362
1399
|
process.exit(1);
|
|
1363
1400
|
}
|
|
1364
1401
|
const agentHarnessKitDir = globalInstallation ? "home directory" : "current directory";
|
|
1365
|
-
console.log(
|
|
1402
|
+
console.log(pc6.green(`\u2713 Scaffolded harness in ${agentHarnessKitDir}`));
|
|
1366
1403
|
const agentsDir = provider === "claude-code" ? ".claude/agents/" : ".opencode/agents/";
|
|
1367
1404
|
const mcpFile = provider === "claude-code" ? ".claude/mcp.json" : "./opencode.json";
|
|
1368
1405
|
console.log("");
|
|
1369
|
-
console.log(
|
|
1370
|
-
console.log(
|
|
1371
|
-
console.log(
|
|
1372
|
-
console.log(
|
|
1373
|
-
console.log(
|
|
1374
|
-
console.log(
|
|
1375
|
-
console.log(
|
|
1376
|
-
console.log(
|
|
1377
|
-
console.log(
|
|
1378
|
-
console.log(
|
|
1379
|
-
console.log(
|
|
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"));
|
|
1380
1417
|
console.log("");
|
|
1381
|
-
console.log(
|
|
1382
|
-
console.log(
|
|
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`);
|
|
1383
1420
|
}
|
|
1384
1421
|
|
|
1385
1422
|
// src/commands/migrate.ts
|
|
1386
1423
|
import * as p3 from "@clack/prompts";
|
|
1387
|
-
import
|
|
1424
|
+
import pc7 from "picocolors";
|
|
1388
1425
|
async function runMigrate(cwd2, opts) {
|
|
1389
1426
|
const config = await loadConfig(cwd2);
|
|
1390
1427
|
let target;
|
|
@@ -1405,7 +1442,7 @@ async function runMigrate(cwd2, opts) {
|
|
|
1405
1442
|
target = val;
|
|
1406
1443
|
}
|
|
1407
1444
|
if (target === config.provider) {
|
|
1408
|
-
console.log(
|
|
1445
|
+
console.log(pc7.dim(`Already on ${target} \u2014 nothing to migrate.`));
|
|
1409
1446
|
return;
|
|
1410
1447
|
}
|
|
1411
1448
|
const spinner5 = p3.spinner();
|
|
@@ -1413,11 +1450,11 @@ async function runMigrate(cwd2, opts) {
|
|
|
1413
1450
|
try {
|
|
1414
1451
|
const targetMaterializer = getMaterializer(target);
|
|
1415
1452
|
await targetMaterializer.build(config, cwd2);
|
|
1416
|
-
spinner5.stop(
|
|
1453
|
+
spinner5.stop(pc7.green(`Migrated to ${target}`));
|
|
1417
1454
|
p3.log.warn(`Update agent-harness-kit.config.ts: set provider: '${target}'`);
|
|
1418
1455
|
p3.log.warn(`Then run: ahk build`);
|
|
1419
1456
|
} catch (err) {
|
|
1420
|
-
spinner5.stop(
|
|
1457
|
+
spinner5.stop(pc7.red("Migration failed"));
|
|
1421
1458
|
p3.log.error(err instanceof Error ? err.message : String(err));
|
|
1422
1459
|
process.exit(1);
|
|
1423
1460
|
}
|
|
@@ -1451,14 +1488,14 @@ var TOOLS = [
|
|
|
1451
1488
|
},
|
|
1452
1489
|
{
|
|
1453
1490
|
name: "actions.write",
|
|
1454
|
-
description: "Record a section in an action. Standard sections: result, tools_used,
|
|
1491
|
+
description: "Record a section in an action. Standard sections: result, tools_used, blockers, next_steps. Note: files_modified is a plain-text note only \u2014 it does NOT populate the files dashboard. Use actions.record_file to register files in the dashboard.",
|
|
1455
1492
|
inputSchema: {
|
|
1456
1493
|
type: "object",
|
|
1457
1494
|
properties: {
|
|
1458
1495
|
actionId: { type: "string", description: "UUID returned by actions.start" },
|
|
1459
1496
|
sectionType: {
|
|
1460
1497
|
type: "string",
|
|
1461
|
-
description: "Section name: result | tools_used |
|
|
1498
|
+
description: "Section name: result | tools_used | blockers | next_steps | <custom>. Do NOT use files_modified to track files \u2014 it is stored as plain text only. Use actions.record_file instead."
|
|
1462
1499
|
},
|
|
1463
1500
|
content: { type: "string", description: "Content for this section" }
|
|
1464
1501
|
},
|
|
@@ -1539,6 +1576,35 @@ var TOOLS = [
|
|
|
1539
1576
|
},
|
|
1540
1577
|
required: ["query"]
|
|
1541
1578
|
}
|
|
1579
|
+
},
|
|
1580
|
+
{
|
|
1581
|
+
name: "actions.record_file",
|
|
1582
|
+
description: "Record a file touched during an action. This is the only way to populate the files-touched count shown in the dashboard. Call once per file.",
|
|
1583
|
+
inputSchema: {
|
|
1584
|
+
type: "object",
|
|
1585
|
+
properties: {
|
|
1586
|
+
actionId: { type: "string", description: "UUID returned by actions.start" },
|
|
1587
|
+
filePath: { type: "string", description: "Absolute or repo-relative path of the file" },
|
|
1588
|
+
operation: {
|
|
1589
|
+
type: "string",
|
|
1590
|
+
enum: ["read", "created", "modified", "deleted"],
|
|
1591
|
+
description: "What was done to the file"
|
|
1592
|
+
},
|
|
1593
|
+
notes: { type: "string", description: "Optional short note about the change" }
|
|
1594
|
+
},
|
|
1595
|
+
required: ["actionId", "filePath", "operation"]
|
|
1596
|
+
}
|
|
1597
|
+
},
|
|
1598
|
+
{
|
|
1599
|
+
name: "tasks.acceptance.update",
|
|
1600
|
+
description: "Mark an acceptance criterion as met. Use the criterion id from tasks.get.",
|
|
1601
|
+
inputSchema: {
|
|
1602
|
+
type: "object",
|
|
1603
|
+
properties: {
|
|
1604
|
+
criterionId: { type: "number", description: "The id of the acceptance criterion to mark as met" }
|
|
1605
|
+
},
|
|
1606
|
+
required: ["criterionId"]
|
|
1607
|
+
}
|
|
1542
1608
|
}
|
|
1543
1609
|
];
|
|
1544
1610
|
async function startMcpServer(config, cwd2) {
|
|
@@ -1617,6 +1683,19 @@ async function dispatch(name, args, db, docsPath) {
|
|
|
1617
1683
|
const results = searchDocs(docsPath, query);
|
|
1618
1684
|
return ok(JSON.stringify(results, null, 2));
|
|
1619
1685
|
}
|
|
1686
|
+
case "actions.record_file": {
|
|
1687
|
+
const actionId = str(args, "actionId");
|
|
1688
|
+
const filePath = str(args, "filePath");
|
|
1689
|
+
const operation = str(args, "operation");
|
|
1690
|
+
const notes = args["notes"];
|
|
1691
|
+
db.recordFile(actionId, filePath, operation, notes);
|
|
1692
|
+
return ok(JSON.stringify({ actionId, filePath, operation, recorded: true }));
|
|
1693
|
+
}
|
|
1694
|
+
case "tasks.acceptance.update": {
|
|
1695
|
+
const criterionId = num(args, "criterionId");
|
|
1696
|
+
db.markAcceptanceMet(criterionId);
|
|
1697
|
+
return ok(JSON.stringify({ criterionId, met: true }));
|
|
1698
|
+
}
|
|
1620
1699
|
default:
|
|
1621
1700
|
return ok(`Unknown tool: ${name}`, true);
|
|
1622
1701
|
}
|
|
@@ -1689,12 +1768,12 @@ async function runServe(cwd2, opts) {
|
|
|
1689
1768
|
|
|
1690
1769
|
// src/commands/status.ts
|
|
1691
1770
|
import Table from "cli-table3";
|
|
1692
|
-
import
|
|
1771
|
+
import pc8 from "picocolors";
|
|
1693
1772
|
var STATUS_COLOR = {
|
|
1694
|
-
pending: (s) =>
|
|
1695
|
-
in_progress: (s) =>
|
|
1696
|
-
done: (s) =>
|
|
1697
|
-
blocked: (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)
|
|
1698
1777
|
};
|
|
1699
1778
|
async function runStatus(cwd2, opts) {
|
|
1700
1779
|
const config = await loadConfig(cwd2);
|
|
@@ -1712,11 +1791,11 @@ async function runStatus(cwd2, opts) {
|
|
|
1712
1791
|
return;
|
|
1713
1792
|
}
|
|
1714
1793
|
if (tasks.length === 0) {
|
|
1715
|
-
console.log(
|
|
1794
|
+
console.log(pc8.dim("No tasks yet. Run: ahk task add"));
|
|
1716
1795
|
return;
|
|
1717
1796
|
}
|
|
1718
1797
|
const table = new Table({
|
|
1719
|
-
head: ["ID", "Slug", "Title", "Status", "Assigned", "Started"].map((h) =>
|
|
1798
|
+
head: ["ID", "Slug", "Title", "Status", "Assigned", "Started"].map((h) => pc8.bold(h)),
|
|
1720
1799
|
style: { head: [], border: [] }
|
|
1721
1800
|
});
|
|
1722
1801
|
for (const t of tasks) {
|
|
@@ -1734,12 +1813,12 @@ async function runStatus(cwd2, opts) {
|
|
|
1734
1813
|
const inProgress = tasks.filter((t) => t.status === "in_progress");
|
|
1735
1814
|
if (inProgress.length > 0) {
|
|
1736
1815
|
console.log("");
|
|
1737
|
-
console.log(
|
|
1816
|
+
console.log(pc8.bold("Active actions:"));
|
|
1738
1817
|
for (const t of inProgress) {
|
|
1739
1818
|
const actions = db.getActionsForTask(t.id);
|
|
1740
1819
|
const active = actions.filter((a) => a.status === "in_progress");
|
|
1741
1820
|
for (const a of active) {
|
|
1742
|
-
console.log(` ${
|
|
1821
|
+
console.log(` ${pc8.cyan(a.agent.padEnd(10))} \u2192 task #${t.id} ${t.slug}`);
|
|
1743
1822
|
}
|
|
1744
1823
|
}
|
|
1745
1824
|
}
|
|
@@ -1748,7 +1827,7 @@ async function runStatus(cwd2, opts) {
|
|
|
1748
1827
|
const fn = STATUS_COLOR[s.status] ?? ((x) => x);
|
|
1749
1828
|
return `${fn(s.status)}: ${s.total}`;
|
|
1750
1829
|
});
|
|
1751
|
-
console.log(
|
|
1830
|
+
console.log(pc8.dim("Tasks \u2014 ") + parts.join(pc8.dim(" | ")));
|
|
1752
1831
|
} finally {
|
|
1753
1832
|
db.close();
|
|
1754
1833
|
}
|
|
@@ -1757,7 +1836,7 @@ async function runStatus(cwd2, opts) {
|
|
|
1757
1836
|
// src/commands/sync.ts
|
|
1758
1837
|
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
|
|
1759
1838
|
import { join as join11, resolve as resolve8 } from "path";
|
|
1760
|
-
import
|
|
1839
|
+
import pc9 from "picocolors";
|
|
1761
1840
|
async function runSync(cwd2, opts) {
|
|
1762
1841
|
const config = await loadConfig(cwd2);
|
|
1763
1842
|
const direction = opts.direction ?? "both";
|
|
@@ -1776,43 +1855,43 @@ async function runSync(cwd2, opts) {
|
|
|
1776
1855
|
}
|
|
1777
1856
|
async function syncIn(featureListPath, db, dryRun) {
|
|
1778
1857
|
if (!existsSync7(featureListPath)) {
|
|
1779
|
-
console.log(
|
|
1858
|
+
console.log(pc9.dim(`feature_list.json not found at ${featureListPath} \u2014 skipping in-sync`));
|
|
1780
1859
|
return;
|
|
1781
1860
|
}
|
|
1782
1861
|
let seeds;
|
|
1783
1862
|
try {
|
|
1784
1863
|
seeds = JSON.parse(readFileSync6(featureListPath, "utf8"));
|
|
1785
1864
|
} catch (err) {
|
|
1786
|
-
console.error(
|
|
1865
|
+
console.error(pc9.red(`Failed to parse feature_list.json: ${err}`));
|
|
1787
1866
|
process.exit(1);
|
|
1788
1867
|
}
|
|
1789
1868
|
if (dryRun) {
|
|
1790
|
-
console.log(
|
|
1869
|
+
console.log(pc9.bold("Dry run \u2014 in-sync (feature_list.json \u2192 SQLite):"));
|
|
1791
1870
|
for (const t of seeds) {
|
|
1792
1871
|
const existing = db.getTaskBySlug(t.slug);
|
|
1793
|
-
console.log(` ${existing ?
|
|
1872
|
+
console.log(` ${existing ? pc9.dim("skip") : pc9.green("add ")} ${t.slug}`);
|
|
1794
1873
|
}
|
|
1795
1874
|
return;
|
|
1796
1875
|
}
|
|
1797
1876
|
const result = db.syncFromFeatureList(seeds);
|
|
1798
|
-
console.log(
|
|
1877
|
+
console.log(pc9.green(`\u2713 In-sync: ${result.added} added, ${result.skipped} already existed`));
|
|
1799
1878
|
}
|
|
1800
1879
|
function syncOut(db, cwd2, dryRun) {
|
|
1801
1880
|
if (dryRun) {
|
|
1802
1881
|
const tasks = db.getTasks();
|
|
1803
|
-
console.log(
|
|
1882
|
+
console.log(pc9.bold("Dry run \u2014 out-sync (SQLite \u2192 feature_list.json):"));
|
|
1804
1883
|
console.log(` ${tasks.length} tasks would be written`);
|
|
1805
1884
|
return;
|
|
1806
1885
|
}
|
|
1807
1886
|
db.writeFeatureList(cwd2);
|
|
1808
|
-
console.log(
|
|
1887
|
+
console.log(pc9.green("\u2713 Out-sync: feature_list.json updated"));
|
|
1809
1888
|
}
|
|
1810
1889
|
|
|
1811
1890
|
// src/commands/task/add.ts
|
|
1812
1891
|
import * as p4 from "@clack/prompts";
|
|
1813
|
-
import
|
|
1892
|
+
import pc10 from "picocolors";
|
|
1814
1893
|
async function runTaskAdd(cwd2) {
|
|
1815
|
-
p4.intro(
|
|
1894
|
+
p4.intro(pc10.bold("agent-harness-kit \u2014 add task"));
|
|
1816
1895
|
const titleVal = await p4.text({
|
|
1817
1896
|
message: "Task title",
|
|
1818
1897
|
validate: (v) => v.trim() ? void 0 : "Title is required"
|
|
@@ -1848,10 +1927,10 @@ async function runTaskAdd(cwd2) {
|
|
|
1848
1927
|
db.writeFeatureList(cwd2);
|
|
1849
1928
|
db.close();
|
|
1850
1929
|
spinner5.stop("");
|
|
1851
|
-
console.log(
|
|
1852
|
-
console.log(
|
|
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");
|
|
1853
1932
|
} catch (err) {
|
|
1854
|
-
spinner5.stop(
|
|
1933
|
+
spinner5.stop(pc10.red("Failed"));
|
|
1855
1934
|
p4.log.error(err instanceof Error ? err.message : String(err));
|
|
1856
1935
|
process.exit(1);
|
|
1857
1936
|
}
|
|
@@ -1861,7 +1940,7 @@ async function runTaskAdd(cwd2) {
|
|
|
1861
1940
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
1862
1941
|
import { existsSync as existsSync8 } from "fs";
|
|
1863
1942
|
import { resolve as resolve9 } from "path";
|
|
1864
|
-
import
|
|
1943
|
+
import pc11 from "picocolors";
|
|
1865
1944
|
async function runTaskDone(cwd2, idOrSlug) {
|
|
1866
1945
|
const config = await loadConfig(cwd2);
|
|
1867
1946
|
if (config.health.required) {
|
|
@@ -1869,7 +1948,7 @@ async function runTaskDone(cwd2, idOrSlug) {
|
|
|
1869
1948
|
if (existsSync8(scriptPath)) {
|
|
1870
1949
|
const result = spawnSync2("bash", [scriptPath], { cwd: cwd2, stdio: "pipe", encoding: "utf8" });
|
|
1871
1950
|
if (result.status !== 0) {
|
|
1872
|
-
console.error(
|
|
1951
|
+
console.error(pc11.red("\u2717 Health check failed \u2014 cannot mark task as done."));
|
|
1873
1952
|
if (result.stdout) console.error(result.stdout);
|
|
1874
1953
|
if (result.stderr) console.error(result.stderr);
|
|
1875
1954
|
process.exit(1);
|
|
@@ -1882,16 +1961,16 @@ async function runTaskDone(cwd2, idOrSlug) {
|
|
|
1882
1961
|
const isId = !isNaN(parsed);
|
|
1883
1962
|
const task2 = isId ? db.getTaskById(parsed) : db.getTaskBySlug(idOrSlug);
|
|
1884
1963
|
if (!task2) {
|
|
1885
|
-
console.error(
|
|
1964
|
+
console.error(pc11.red(`Task not found: ${idOrSlug}`));
|
|
1886
1965
|
process.exit(1);
|
|
1887
1966
|
}
|
|
1888
1967
|
if (task2.status === "done") {
|
|
1889
|
-
console.log(
|
|
1968
|
+
console.log(pc11.dim(`Task #${task2.id} is already done.`));
|
|
1890
1969
|
return;
|
|
1891
1970
|
}
|
|
1892
1971
|
db.updateTaskStatus(task2.id, "done");
|
|
1893
1972
|
db.writeFeatureList(cwd2);
|
|
1894
|
-
console.log(
|
|
1973
|
+
console.log(pc11.green(`\u2713 Task #${task2.id} \u2014 ${task2.slug} marked as done`));
|
|
1895
1974
|
} finally {
|
|
1896
1975
|
db.close();
|
|
1897
1976
|
}
|
|
@@ -1899,12 +1978,12 @@ async function runTaskDone(cwd2, idOrSlug) {
|
|
|
1899
1978
|
|
|
1900
1979
|
// src/commands/task/list.ts
|
|
1901
1980
|
import Table2 from "cli-table3";
|
|
1902
|
-
import
|
|
1981
|
+
import pc12 from "picocolors";
|
|
1903
1982
|
var STATUS_COLOR2 = {
|
|
1904
|
-
pending: (s) =>
|
|
1905
|
-
in_progress: (s) =>
|
|
1906
|
-
done: (s) =>
|
|
1907
|
-
blocked: (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)
|
|
1908
1987
|
};
|
|
1909
1988
|
async function runTaskList(cwd2, opts) {
|
|
1910
1989
|
const config = await loadConfig(cwd2);
|
|
@@ -1918,11 +1997,11 @@ async function runTaskList(cwd2, opts) {
|
|
|
1918
1997
|
return;
|
|
1919
1998
|
}
|
|
1920
1999
|
if (tasks.length === 0) {
|
|
1921
|
-
console.log(
|
|
2000
|
+
console.log(pc12.dim("No tasks" + (filterStatus ? ` with status: ${filterStatus}` : "") + "."));
|
|
1922
2001
|
return;
|
|
1923
2002
|
}
|
|
1924
2003
|
const table = new Table2({
|
|
1925
|
-
head: ["ID", "Slug", "Title", "Status"].map((h) =>
|
|
2004
|
+
head: ["ID", "Slug", "Title", "Status"].map((h) => pc12.bold(h)),
|
|
1926
2005
|
style: { head: [], border: [] }
|
|
1927
2006
|
});
|
|
1928
2007
|
for (const t of tasks) {
|
|
@@ -1944,7 +2023,7 @@ var pkgPath = join12(dirname5(fileURLToPath3(import.meta.url)), "..", "package.j
|
|
|
1944
2023
|
var pkg = require2(pkgPath);
|
|
1945
2024
|
|
|
1946
2025
|
// src/core/update-check.ts
|
|
1947
|
-
import
|
|
2026
|
+
import pc13 from "picocolors";
|
|
1948
2027
|
var REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`;
|
|
1949
2028
|
var TIMEOUT_MS = 2500;
|
|
1950
2029
|
function checkForUpdate(currentVersion) {
|
|
@@ -1962,18 +2041,18 @@ function checkForUpdate(currentVersion) {
|
|
|
1962
2041
|
}
|
|
1963
2042
|
function printUpdateMessage({ current, latest }) {
|
|
1964
2043
|
const lines = [
|
|
1965
|
-
` Update available ${
|
|
1966
|
-
` Run: ${
|
|
2044
|
+
` Update available ${pc13.dim(current)} \u2192 ${pc13.green(latest)} `,
|
|
2045
|
+
` Run: ${pc13.cyan(`npm i ${pkg.name}@${latest}`)} `
|
|
1967
2046
|
];
|
|
1968
|
-
const width = Math.max(...lines.map((l) =>
|
|
2047
|
+
const width = Math.max(...lines.map((l) => stripAnsi2(l).length));
|
|
1969
2048
|
const border = "\u2500".repeat(width);
|
|
1970
2049
|
console.log();
|
|
1971
|
-
console.log(
|
|
2050
|
+
console.log(pc13.yellow(`\u250C${border}\u2510`));
|
|
1972
2051
|
for (const line of lines) {
|
|
1973
|
-
const pad = width -
|
|
1974
|
-
console.log(
|
|
2052
|
+
const pad = width - stripAnsi2(line).length;
|
|
2053
|
+
console.log(pc13.yellow("\u2502") + line + " ".repeat(pad) + pc13.yellow("\u2502"));
|
|
1975
2054
|
}
|
|
1976
|
-
console.log(
|
|
2055
|
+
console.log(pc13.yellow(`\u2514${border}\u2518`));
|
|
1977
2056
|
console.log();
|
|
1978
2057
|
}
|
|
1979
2058
|
function isNewer(latest, current) {
|
|
@@ -1984,7 +2063,7 @@ function isNewer(latest, current) {
|
|
|
1984
2063
|
if (lMin !== cMin) return lMin > cMin;
|
|
1985
2064
|
return lPat > cPat;
|
|
1986
2065
|
}
|
|
1987
|
-
function
|
|
2066
|
+
function stripAnsi2(str2) {
|
|
1988
2067
|
return str2.replace(/\x1B\[[0-9;]*m/g, "");
|
|
1989
2068
|
}
|
|
1990
2069
|
|