@hasna/todos 0.11.30 → 0.11.31

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/cli/index.js CHANGED
@@ -3049,10 +3049,15 @@ function ensureSchema(db) {
3049
3049
  ensureTable("machines", `
3050
3050
  CREATE TABLE machines (
3051
3051
  id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, hostname TEXT, platform TEXT,
3052
+ ssh_address TEXT, is_primary INTEGER NOT NULL DEFAULT 0,
3052
3053
  last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
3054
+ archived_at TEXT,
3053
3055
  metadata TEXT DEFAULT '{}',
3054
3056
  created_at TEXT NOT NULL DEFAULT (datetime('now'))
3055
3057
  )`);
3058
+ ensureColumn("machines", "ssh_address", "TEXT");
3059
+ ensureColumn("machines", "is_primary", "INTEGER NOT NULL DEFAULT 0");
3060
+ ensureColumn("machines", "archived_at", "TEXT");
3056
3061
  ensureColumn("projects", "task_list_id", "TEXT");
3057
3062
  ensureColumn("projects", "task_prefix", "TEXT");
3058
3063
  ensureColumn("projects", "task_counter", "INTEGER NOT NULL DEFAULT 0");
@@ -3281,19 +3286,25 @@ var init_schema = __esm(() => {
3281
3286
  // src/db/machines.ts
3282
3287
  var exports_machines = {};
3283
3288
  __export(exports_machines, {
3289
+ unarchiveMachine: () => unarchiveMachine,
3290
+ setPrimaryMachine: () => setPrimaryMachine,
3284
3291
  resetMachineId: () => resetMachineId,
3292
+ registerMachine: () => registerMachine,
3285
3293
  listMachines: () => listMachines,
3294
+ getPrimaryMachine: () => getPrimaryMachine,
3286
3295
  getOrCreateLocalMachine: () => getOrCreateLocalMachine,
3287
3296
  getMachineId: () => getMachineId,
3288
3297
  getMachineByName: () => getMachineByName,
3289
3298
  getMachine: () => getMachine,
3290
3299
  deleteMachine: () => deleteMachine,
3291
- backfillMachineId: () => backfillMachineId
3300
+ backfillMachineId: () => backfillMachineId,
3301
+ archiveMachine: () => archiveMachine
3292
3302
  });
3293
3303
  import { hostname as osHostname, platform as osPlatform } from "os";
3294
3304
  function rowToMachine(row) {
3295
3305
  return {
3296
3306
  ...row,
3307
+ is_primary: !!row.is_primary,
3297
3308
  metadata: row.metadata ? JSON.parse(row.metadata) : {}
3298
3309
  };
3299
3310
  }
@@ -3310,7 +3321,7 @@ function getOrCreateLocalMachine(db) {
3310
3321
  const id = uuid();
3311
3322
  const ts = now();
3312
3323
  d.run("INSERT INTO machines (id, name, hostname, platform, last_seen_at, metadata, created_at) VALUES (?, ?, ?, ?, ?, '{}', ?)", [id, name, host, plat, ts, ts]);
3313
- return { id, name, hostname: host, platform: plat, last_seen_at: ts, metadata: {}, created_at: ts };
3324
+ return { id, name, hostname: host, platform: plat, ssh_address: null, is_primary: false, last_seen_at: ts, archived_at: null, metadata: {}, created_at: ts };
3314
3325
  }
3315
3326
  function getMachineId(db) {
3316
3327
  if (_machineId)
@@ -3332,13 +3343,77 @@ function getMachineByName(name, db) {
3332
3343
  const row = d.query("SELECT * FROM machines WHERE name = ?").get(name);
3333
3344
  return row ? rowToMachine(row) : null;
3334
3345
  }
3335
- function listMachines(db) {
3346
+ function listMachines(db, includeArchived = false) {
3336
3347
  const d = db || getDatabase();
3337
- const rows = d.query("SELECT * FROM machines ORDER BY last_seen_at DESC").all();
3348
+ const query = includeArchived ? "SELECT * FROM machines ORDER BY last_seen_at DESC" : "SELECT * FROM machines WHERE archived_at IS NULL ORDER BY last_seen_at DESC";
3349
+ const rows = d.query(query).all();
3338
3350
  return rows.map(rowToMachine);
3339
3351
  }
3352
+ function registerMachine(name, opts, db) {
3353
+ const d = db || getDatabase();
3354
+ const existing = d.query("SELECT * FROM machines WHERE name = ?").get(name);
3355
+ if (existing) {
3356
+ d.run("UPDATE machines SET hostname = ?, ssh_address = ?, last_seen_at = ? WHERE id = ?", [opts.hostname ?? existing.hostname, opts.ssh_address ?? existing.ssh_address, now(), existing.id]);
3357
+ if (opts.primary) {
3358
+ setPrimaryMachine(name, d);
3359
+ }
3360
+ return getMachine(existing.id, d);
3361
+ }
3362
+ const id = uuid();
3363
+ const ts = now();
3364
+ const host = opts.hostname || osHostname();
3365
+ const plat = osPlatform();
3366
+ d.run("INSERT INTO machines (id, name, hostname, platform, ssh_address, last_seen_at, is_primary, metadata, created_at) VALUES (?, ?, ?, ?, ?, ?, 0, '{}', ?)", [id, name, host, plat, opts.ssh_address ?? null, ts, ts]);
3367
+ if (opts.primary) {
3368
+ setPrimaryMachine(name, d);
3369
+ }
3370
+ return getMachine(id, d);
3371
+ }
3372
+ function setPrimaryMachine(name, db) {
3373
+ const d = db || getDatabase();
3374
+ const row = d.query("SELECT * FROM machines WHERE name = ?").get(name);
3375
+ if (!row)
3376
+ throw new Error(`Machine '${name}' not found`);
3377
+ if (row.archived_at)
3378
+ throw new Error(`Cannot set archived machine '${name}' as primary`);
3379
+ d.run("UPDATE machines SET is_primary = 0 WHERE archived_at IS NULL");
3380
+ d.run("UPDATE machines SET is_primary = 1 WHERE id = ?", [row.id]);
3381
+ return rowToMachine({ ...row, is_primary: 1 });
3382
+ }
3383
+ function getPrimaryMachine(db) {
3384
+ const d = db || getDatabase();
3385
+ const row = d.query("SELECT * FROM machines WHERE is_primary = 1").get();
3386
+ return row ? rowToMachine(row) : null;
3387
+ }
3388
+ function archiveMachine(id, db) {
3389
+ const d = db || getDatabase();
3390
+ const row = d.query("SELECT * FROM machines WHERE id = ?").get(id);
3391
+ if (!row)
3392
+ throw new Error(`Machine not found: ${id}`);
3393
+ if (row.is_primary)
3394
+ throw new Error("Cannot archive the primary machine");
3395
+ const activeCount = d.query("SELECT COUNT(*) as cnt FROM tasks WHERE machine_id = ? AND status IN ('pending', 'in_progress')").get(id);
3396
+ if (activeCount.cnt > 0) {
3397
+ throw new Error(`Cannot archive machine with ${activeCount.cnt} active/pending tasks`);
3398
+ }
3399
+ d.run("UPDATE machines SET archived_at = ? WHERE id = ?", [now(), id]);
3400
+ }
3401
+ function unarchiveMachine(id, db) {
3402
+ const d = db || getDatabase();
3403
+ d.run("UPDATE machines SET archived_at = NULL WHERE id = ?", [id]);
3404
+ return getMachine(id, d);
3405
+ }
3340
3406
  function deleteMachine(id, db) {
3341
3407
  const d = db || getDatabase();
3408
+ const row = d.query("SELECT * FROM machines WHERE id = ?").get(id);
3409
+ if (!row)
3410
+ return false;
3411
+ if (row.is_primary)
3412
+ throw new Error("Cannot delete the primary machine");
3413
+ const activeCount = d.query("SELECT COUNT(*) as cnt FROM tasks WHERE machine_id = ? AND status IN ('pending', 'in_progress')").get(id);
3414
+ if (activeCount.cnt > 0) {
3415
+ throw new Error(`Cannot delete machine with ${activeCount.cnt} active/pending tasks`);
3416
+ }
3342
3417
  const result = d.run("DELETE FROM machines WHERE id = ?", [id]);
3343
3418
  return result.changes > 0;
3344
3419
  }
@@ -23061,6 +23136,38 @@ var init_cloud = __esm(() => {
23061
23136
  ]);
23062
23137
  });
23063
23138
 
23139
+ // src/lib/logger.ts
23140
+ import { LogsClient } from "@hasna/logs";
23141
+ function getLogger() {
23142
+ if (client)
23143
+ return client;
23144
+ const url = process.env.LOGS_URL;
23145
+ const projectId = process.env.LOGS_PROJECT_ID;
23146
+ const apiKey = process.env.LOGS_API_KEY;
23147
+ if (!projectId)
23148
+ return null;
23149
+ client = new LogsClient({ url, projectId, apiKey });
23150
+ return client;
23151
+ }
23152
+ async function logError(message, opts) {
23153
+ const logger = getLogger();
23154
+ if (!logger)
23155
+ return;
23156
+ try {
23157
+ await logger.push({
23158
+ level: "error",
23159
+ message,
23160
+ source: "sdk",
23161
+ service: opts?.service,
23162
+ stack_trace: opts?.stack,
23163
+ trace_id: opts?.traceId,
23164
+ metadata: opts?.metadata
23165
+ });
23166
+ } catch {}
23167
+ }
23168
+ var client = null;
23169
+ var init_logger = () => {};
23170
+
23064
23171
  // src/mcp/tools/dispatch.ts
23065
23172
  function registerDispatchTools(server, { shouldRegisterTool, resolveId, formatError }) {
23066
23173
  if (shouldRegisterTool("dispatch_tasks")) {
@@ -26858,6 +26965,152 @@ var init_code_tools = __esm(() => {
26858
26965
  init_zod();
26859
26966
  });
26860
26967
 
26968
+ // src/mcp/tools/machines.ts
26969
+ import { hostname as osHostname2 } from "os";
26970
+ function getDb() {
26971
+ return getDatabase();
26972
+ }
26973
+ function registerMachineTools(server, ctx) {
26974
+ if (ctx.shouldRegisterTool("machines_register")) {
26975
+ server.tool("machines_register", "Register a machine in the todos machine registry", {
26976
+ name: exports_external.string().optional().describe("Machine name (defaults to hostname if omitted)"),
26977
+ hostname: exports_external.string().optional().describe("OS hostname"),
26978
+ ssh_address: exports_external.string().optional().describe("SSH address for cross-machine access (e.g. user@host)"),
26979
+ primary: exports_external.boolean().optional().describe("Set as primary machine")
26980
+ }, async (params) => {
26981
+ try {
26982
+ const db = getDb();
26983
+ const name = params.name || osHostname2();
26984
+ const machine = registerMachine(name, {
26985
+ hostname: params.hostname,
26986
+ ssh_address: params.ssh_address,
26987
+ primary: params.primary
26988
+ }, db);
26989
+ return {
26990
+ content: [
26991
+ {
26992
+ type: "text",
26993
+ text: `Machine registered: ${machine.name} (${machine.id.slice(0, 8)})
26994
+ Host: ${machine.hostname}
26995
+ Platform: ${machine.platform}
26996
+ Primary: ${machine.is_primary}
26997
+ SSH: ${machine.ssh_address ?? "(not set)"}`
26998
+ }
26999
+ ]
27000
+ };
27001
+ } catch (error) {
27002
+ return { content: [{ type: "text", text: ctx.formatError(error) }] };
27003
+ }
27004
+ });
27005
+ }
27006
+ if (ctx.shouldRegisterTool("machines_list")) {
27007
+ server.tool("machines_list", "List all registered machines", {
27008
+ include_archived: exports_external.boolean().optional().describe("Include archived machines")
27009
+ }, async (params) => {
27010
+ try {
27011
+ const db = getDb();
27012
+ const machines = listMachines(db, params.include_archived);
27013
+ if (machines.length === 0) {
27014
+ return {
27015
+ content: [{ type: "text", text: "No machines registered. Use machines_register to add one." }]
27016
+ };
27017
+ }
27018
+ const lines = machines.map((m) => {
27019
+ const primaryTag = m.is_primary ? " [PRIMARY]" : "";
27020
+ const archivedTag = m.archived_at ? " [ARCHIVED]" : "";
27021
+ return `${m.name} (${m.id.slice(0, 8)}) | ${m.hostname ?? "unknown"} | ${m.platform ?? "unknown"} | last: ${m.last_seen_at}${primaryTag}${archivedTag}`;
27022
+ });
27023
+ return { content: [{ type: "text", text: `Machines:
27024
+ ${lines.join(`
27025
+ `)}` }] };
27026
+ } catch (error) {
27027
+ return { content: [{ type: "text", text: ctx.formatError(error) }] };
27028
+ }
27029
+ });
27030
+ }
27031
+ if (ctx.shouldRegisterTool("machines_set_primary")) {
27032
+ server.tool("machines_set_primary", "Set the primary machine", {
27033
+ name: exports_external.string().describe("Machine name to set as primary")
27034
+ }, async (params) => {
27035
+ try {
27036
+ const db = getDb();
27037
+ const machine = setPrimaryMachine(params.name, db);
27038
+ return {
27039
+ content: [
27040
+ { type: "text", text: `Primary machine set to: ${machine.name} (${machine.id.slice(0, 8)})` }
27041
+ ]
27042
+ };
27043
+ } catch (error) {
27044
+ return { content: [{ type: "text", text: ctx.formatError(error) }] };
27045
+ }
27046
+ });
27047
+ }
27048
+ if (ctx.shouldRegisterTool("machines_archive")) {
27049
+ server.tool("machines_archive", "Archive (soft-delete) a machine. Cannot archive primary or machines with active tasks.", {
27050
+ name: exports_external.string().describe("Machine name to archive")
27051
+ }, async (params) => {
27052
+ try {
27053
+ const db = getDb();
27054
+ const machine = getMachineByName(params.name, db);
27055
+ if (!machine) {
27056
+ return { content: [{ type: "text", text: `Machine '${params.name}' not found` }] };
27057
+ }
27058
+ archiveMachine(machine.id, db);
27059
+ return { content: [{ type: "text", text: `Machine '${params.name}' archived` }] };
27060
+ } catch (error) {
27061
+ return { content: [{ type: "text", text: ctx.formatError(error) }] };
27062
+ }
27063
+ });
27064
+ }
27065
+ if (ctx.shouldRegisterTool("machines_unarchive")) {
27066
+ server.tool("machines_unarchive", "Unarchive a machine", {
27067
+ name: exports_external.string().describe("Machine name to unarchive")
27068
+ }, async (params) => {
27069
+ try {
27070
+ const db = getDb();
27071
+ const machine = getMachineByName(params.name, db);
27072
+ if (!machine) {
27073
+ return { content: [{ type: "text", text: `Machine '${params.name}' not found` }] };
27074
+ }
27075
+ const result = unarchiveMachine(machine.id, db);
27076
+ return {
27077
+ content: [
27078
+ { type: "text", text: `Machine '${params.name}' unarchived${result ? ` (${result.id.slice(0, 8)})` : ""}` }
27079
+ ]
27080
+ };
27081
+ } catch (error) {
27082
+ return { content: [{ type: "text", text: ctx.formatError(error) }] };
27083
+ }
27084
+ });
27085
+ }
27086
+ if (ctx.shouldRegisterTool("machines_delete")) {
27087
+ server.tool("machines_delete", "Hard-delete a machine. Cannot delete primary or machines with active tasks.", {
27088
+ name: exports_external.string().describe("Machine name to delete")
27089
+ }, async (params) => {
27090
+ try {
27091
+ const db = getDb();
27092
+ const machine = getMachineByName(params.name, db);
27093
+ if (!machine) {
27094
+ return { content: [{ type: "text", text: `Machine '${params.name}' not found` }] };
27095
+ }
27096
+ const result = deleteMachine(machine.id, db);
27097
+ return {
27098
+ content: [
27099
+ { type: "text", text: result ? `Machine '${params.name}' deleted` : `Failed to delete machine '${params.name}'` }
27100
+ ]
27101
+ };
27102
+ } catch (error) {
27103
+ return { content: [{ type: "text", text: ctx.formatError(error) }] };
27104
+ }
27105
+ });
27106
+ }
27107
+ }
27108
+ var init_machines2 = __esm(() => {
27109
+ init_zod();
27110
+ init_machines();
27111
+ init_database();
27112
+ });
27113
+
26861
27114
  // src/mcp/index.ts
26862
27115
  var exports_mcp = {};
26863
27116
  __export(exports_mcp, {
@@ -26958,6 +27211,7 @@ function formatError(error) {
26958
27211
  return JSON.stringify({ code: "REFERENCE_ERROR", message: "Referenced record does not exist. Check that the ID is correct.", suggestion: "Verify the referenced ID exists before creating this record." });
26959
27212
  }
26960
27213
  console.error("[mcp] Unhandled error:", msg);
27214
+ logError(`[mcp] Unhandled error: ${msg}`, { service: "mcp" }).catch(() => {});
26961
27215
  return JSON.stringify({ code: "UNKNOWN_ERROR", message: "An unexpected error occurred. Check server logs for details." });
26962
27216
  }
26963
27217
  return JSON.stringify({ code: "UNKNOWN_ERROR", message: "An unexpected error occurred." });
@@ -27023,6 +27277,7 @@ var init_mcp = __esm(() => {
27023
27277
  init_cloud();
27024
27278
  init_agents();
27025
27279
  init_database();
27280
+ init_logger();
27026
27281
  init_types();
27027
27282
  init_dispatch2();
27028
27283
  init_task_crud2();
@@ -27034,6 +27289,7 @@ var init_mcp = __esm(() => {
27034
27289
  init_task_resources();
27035
27290
  init_task_rel_tools();
27036
27291
  init_code_tools();
27292
+ init_machines2();
27037
27293
  server = new McpServer({
27038
27294
  name: "todos",
27039
27295
  version: getMcpVersion()
@@ -27091,10 +27347,15 @@ var init_mcp = __esm(() => {
27091
27347
  registerTaskResources(server, toolContext);
27092
27348
  registerTaskRelTools(server, toolContext);
27093
27349
  registerCodeTools(server, toolContext);
27350
+ registerMachineTools(server, { shouldRegisterTool, formatError });
27094
27351
  registerDispatchTools(server, { shouldRegisterTool, resolveId, formatError });
27095
27352
  registerCloudSyncTools(server, { shouldRegisterTool, formatError });
27096
- main().catch((err) => {
27353
+ main().catch(async (err) => {
27097
27354
  console.error("MCP server error:", err);
27355
+ await logError(`MCP server startup failed: ${err instanceof Error ? err.message : String(err)}`, {
27356
+ service: "mcp",
27357
+ stack: err instanceof Error ? err.stack : undefined
27358
+ }).catch(() => {});
27098
27359
  process.exit(1);
27099
27360
  });
27100
27361
  });
@@ -27223,17 +27484,17 @@ function handleSseEvents(_req, url, ctx) {
27223
27484
  const agentId = url.searchParams.get("agent_id") || undefined;
27224
27485
  const projectId = url.searchParams.get("project_id") || undefined;
27225
27486
  if (agentId || projectId) {
27226
- const client = { controller: null, agentId, projectId, events: undefined };
27487
+ const client2 = { controller: null, agentId, projectId, events: undefined };
27227
27488
  const stream2 = new ReadableStream({
27228
27489
  start(controller) {
27229
- client.controller = controller;
27230
- ctx.filteredSseClients.add(client);
27490
+ client2.controller = controller;
27491
+ ctx.filteredSseClients.add(client2);
27231
27492
  controller.enqueue(`data: ${JSON.stringify({ type: "connected", agent_id: agentId, project_id: projectId, timestamp: new Date().toISOString() })}
27232
27493
 
27233
27494
  `);
27234
27495
  },
27235
27496
  cancel() {
27236
- ctx.filteredSseClients.delete(client);
27497
+ ctx.filteredSseClients.delete(client2);
27237
27498
  }
27238
27499
  });
27239
27500
  return new Response(stream2, {
@@ -27271,11 +27532,11 @@ function handleTasksStream(_req, url, ctx) {
27271
27532
  const projectId = url.searchParams.get("project_id") || undefined;
27272
27533
  const eventsParam = url.searchParams.get("events");
27273
27534
  const eventFilter = eventsParam ? new Set(eventsParam.split(",").map((e) => e.trim())) : undefined;
27274
- const client = { controller: null, agentId, projectId, events: eventFilter };
27535
+ const client2 = { controller: null, agentId, projectId, events: eventFilter };
27275
27536
  const stream = new ReadableStream({
27276
27537
  start(controller) {
27277
- client.controller = controller;
27278
- ctx.filteredSseClients.add(client);
27538
+ client2.controller = controller;
27539
+ ctx.filteredSseClients.add(client2);
27279
27540
  controller.enqueue(`: connected
27280
27541
 
27281
27542
  data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Date().toISOString() })}
@@ -27283,7 +27544,7 @@ data: ${JSON.stringify({ type: "connected", agent_id: agentId, timestamp: new Da
27283
27544
  `);
27284
27545
  },
27285
27546
  cancel() {
27286
- ctx.filteredSseClients.delete(client);
27547
+ ctx.filteredSseClients.delete(client2);
27287
27548
  }
27288
27549
  });
27289
27550
  return new Response(stream, {
@@ -28041,24 +28302,24 @@ async function startServer(port, options) {
28041
28302
  for (const controller of deadClients)
28042
28303
  sseClients.delete(controller);
28043
28304
  const deadFiltered = [];
28044
- for (const client of filteredSseClients) {
28045
- if (client.events && !client.events.has(eventName) && !client.events.has("*"))
28305
+ for (const client2 of filteredSseClients) {
28306
+ if (client2.events && !client2.events.has(eventName) && !client2.events.has("*"))
28046
28307
  continue;
28047
- if (client.agentId && event.agent_id !== client.agentId)
28308
+ if (client2.agentId && event.agent_id !== client2.agentId)
28048
28309
  continue;
28049
- if (client.projectId && event.project_id !== client.projectId)
28310
+ if (client2.projectId && event.project_id !== client2.projectId)
28050
28311
  continue;
28051
28312
  try {
28052
- client.controller.enqueue(`event: ${eventName}
28313
+ client2.controller.enqueue(`event: ${eventName}
28053
28314
  data: ${data}
28054
28315
 
28055
28316
  `);
28056
28317
  } catch {
28057
- deadFiltered.push(client);
28318
+ deadFiltered.push(client2);
28058
28319
  }
28059
28320
  }
28060
- for (const client of deadFiltered)
28061
- filteredSseClients.delete(client);
28321
+ for (const client2 of deadFiltered)
28322
+ filteredSseClients.delete(client2);
28062
28323
  }
28063
28324
  const dashboardDir = resolveDashboardDir();
28064
28325
  const dashboardExists = existsSync9(dashboardDir);
@@ -29952,7 +30213,7 @@ init_task_lists();
29952
30213
  init_plans();
29953
30214
  init_comments();
29954
30215
  init_search();
29955
- import chalk3 from "chalk";
30216
+ import chalk4 from "chalk";
29956
30217
  import { execSync } from "child_process";
29957
30218
  import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
29958
30219
  import { basename, dirname as dirname5, join as join13, resolve as resolve4 } from "path";
@@ -30627,6 +30888,136 @@ function registerDispatchCommands(program2) {
30627
30888
  });
30628
30889
  }
30629
30890
 
30891
+ // src/cli/commands/machines.tsx
30892
+ init_machines();
30893
+ init_database();
30894
+ import chalk2 from "chalk";
30895
+ function registerMachineCommands(program2) {
30896
+ program2.command("machines").description("List registered machines").option("-a, --all", "Include archived machines").action((opts) => {
30897
+ const db = getDatabase();
30898
+ const machines = listMachines(db, opts.all);
30899
+ if (machines.length === 0) {
30900
+ console.log(chalk2.yellow("No machines registered."));
30901
+ console.log(chalk2.dim("Use `todos machines register` to add one."));
30902
+ return;
30903
+ }
30904
+ for (const m of machines) {
30905
+ const primaryTag = m.is_primary ? chalk2.bold(" [PRIMARY]") : "";
30906
+ const archivedTag = m.archived_at ? chalk2.dim(" [ARCHIVED]") : "";
30907
+ console.log(`${chalk2.cyan(m.name)} (${m.id.slice(0, 8)})${primaryTag}${archivedTag}`);
30908
+ console.log(chalk2.dim(` Host: ${m.hostname ?? "unknown"} | Platform: ${m.platform ?? "unknown"}`));
30909
+ console.log(chalk2.dim(` SSH: ${m.ssh_address ?? "(not set)"}`));
30910
+ console.log(chalk2.dim(` Last seen: ${m.last_seen_at}`));
30911
+ }
30912
+ });
30913
+ program2.command("machines register").description("Register a machine").argument("<name>", "Machine name").option("--hostname <host>", "OS hostname").option("--ssh <address>", "SSH address (e.g. user@host)").option("--arch <arch>", "Architecture (e.g. linux-arm64)").option("--primary", "Set as primary machine").action((name, opts) => {
30914
+ try {
30915
+ const db = getDatabase();
30916
+ const machine = registerMachine(name, {
30917
+ hostname: opts.hostname,
30918
+ ssh_address: opts.ssh,
30919
+ primary: opts.primary
30920
+ }, db);
30921
+ console.log(chalk2.green(`Machine registered: ${machine.name} (${machine.id.slice(0, 8)})`));
30922
+ console.log(chalk2.dim(` Host: ${machine.hostname} | Platform: ${machine.platform}`));
30923
+ console.log(chalk2.dim(` Primary: ${machine.is_primary}`));
30924
+ if (machine.ssh_address)
30925
+ console.log(chalk2.dim(` SSH: ${machine.ssh_address}`));
30926
+ } catch (err) {
30927
+ console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
30928
+ process.exit(1);
30929
+ }
30930
+ });
30931
+ program2.command("machines set-primary").description("Set the primary machine").argument("<name>", "Machine name").action((name) => {
30932
+ try {
30933
+ const db = getDatabase();
30934
+ const machine = setPrimaryMachine(name, db);
30935
+ console.log(chalk2.green(`Primary machine set to: ${machine.name} (${machine.id.slice(0, 8)})`));
30936
+ } catch (err) {
30937
+ console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
30938
+ process.exit(1);
30939
+ }
30940
+ });
30941
+ program2.command("machines archive").description("Archive a machine (soft-delete)").argument("<name>", "Machine name").action((name) => {
30942
+ try {
30943
+ const db = getDatabase();
30944
+ const machine = getMachineByName(name, db);
30945
+ if (!machine) {
30946
+ console.error(chalk2.red(`Machine '${name}' not found`));
30947
+ process.exit(1);
30948
+ }
30949
+ archiveMachine(machine.id, db);
30950
+ console.log(chalk2.green(`Machine '${name}' archived`));
30951
+ } catch (err) {
30952
+ console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
30953
+ process.exit(1);
30954
+ }
30955
+ });
30956
+ program2.command("machines unarchive").description("Unarchive a machine").argument("<name>", "Machine name").action((name) => {
30957
+ try {
30958
+ const db = getDatabase();
30959
+ const machine = getMachineByName(name, db);
30960
+ if (!machine) {
30961
+ console.error(chalk2.red(`Machine '${name}' not found`));
30962
+ process.exit(1);
30963
+ }
30964
+ unarchiveMachine(machine.id, db);
30965
+ console.log(chalk2.green(`Machine '${name}' unarchived`));
30966
+ } catch (err) {
30967
+ console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
30968
+ process.exit(1);
30969
+ }
30970
+ });
30971
+ program2.command("machines delete").description("Delete a machine (hard delete)").argument("<name>", "Machine name").action((name) => {
30972
+ try {
30973
+ const db = getDatabase();
30974
+ const machine = getMachineByName(name, db);
30975
+ if (!machine) {
30976
+ console.error(chalk2.red(`Machine '${name}' not found`));
30977
+ process.exit(1);
30978
+ }
30979
+ deleteMachine(machine.id, db);
30980
+ console.log(chalk2.green(`Machine '${name}' deleted`));
30981
+ } catch (err) {
30982
+ console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
30983
+ process.exit(1);
30984
+ }
30985
+ });
30986
+ program2.command("machines status").description("Show machine health status").action(() => {
30987
+ const db = getDatabase();
30988
+ const machines = listMachines(db);
30989
+ const primary = getPrimaryMachine(db);
30990
+ if (machines.length === 0) {
30991
+ console.log(chalk2.yellow("No machines registered."));
30992
+ return;
30993
+ }
30994
+ console.log(chalk2.bold(`
30995
+ Machine Health`));
30996
+ console.log(chalk2.dim("\u2500".repeat(60)));
30997
+ for (const m of machines) {
30998
+ const primaryTag = m.is_primary ? chalk2.bold(" [PRIMARY]") : "";
30999
+ const lastSeen = new Date(m.last_seen_at);
31000
+ const now2 = new Date;
31001
+ const diffMs = now2.getTime() - lastSeen.getTime();
31002
+ const diffMin = Math.round(diffMs / 60000);
31003
+ let status;
31004
+ if (diffMin < 5) {
31005
+ status = chalk2.green("online");
31006
+ } else if (diffMin < 60) {
31007
+ status = chalk2.yellow("stale");
31008
+ } else {
31009
+ status = chalk2.red("offline");
31010
+ }
31011
+ console.log(`${chalk2.cyan(m.name)}${primaryTag} ${status} last: ${diffMin}m ago`);
31012
+ }
31013
+ if (!primary) {
31014
+ console.log(chalk2.yellow(`
31015
+ Warning: No primary machine set.`));
31016
+ console.log(chalk2.dim("Use `todos machines set-primary <name>` to set one."));
31017
+ }
31018
+ });
31019
+ }
31020
+
30630
31021
  // src/cli/brains.ts
30631
31022
  import {
30632
31023
  existsSync as existsSync7,
@@ -30636,7 +31027,7 @@ import {
30636
31027
  } from "fs";
30637
31028
  import { homedir as homedir2 } from "os";
30638
31029
  import { join as join7 } from "path";
30639
- import chalk2 from "chalk";
31030
+ import chalk3 from "chalk";
30640
31031
 
30641
31032
  // src/lib/gatherer.ts
30642
31033
  init_tasks();
@@ -30776,13 +31167,13 @@ function getTodosGlobalDir4() {
30776
31167
  return newDir;
30777
31168
  }
30778
31169
  function printSuccess(msg) {
30779
- console.log(chalk2.green("\u2713 " + msg));
31170
+ console.log(chalk3.green("\u2713 " + msg));
30780
31171
  }
30781
31172
  function printError(msg) {
30782
- console.error(chalk2.red("\u2717 " + msg));
31173
+ console.error(chalk3.red("\u2717 " + msg));
30783
31174
  }
30784
31175
  function printInfo(msg) {
30785
- console.log(chalk2.cyan("\u2139 " + msg));
31176
+ console.log(chalk3.cyan("\u2139 " + msg));
30786
31177
  }
30787
31178
  function makeBrainsCommand() {
30788
31179
  const brains = new Command("brains");
@@ -30819,7 +31210,7 @@ function makeBrainsCommand() {
30819
31210
  }));
30820
31211
  } else {
30821
31212
  printSuccess(`Gathered ${result.count} training examples from tasks`);
30822
- console.log(chalk2.dim(` Output: ${outputPath}`));
31213
+ console.log(chalk3.dim(` Output: ${outputPath}`));
30823
31214
  }
30824
31215
  } catch (err) {
30825
31216
  printError(err instanceof Error ? err.message : String(err));
@@ -30873,9 +31264,9 @@ function makeBrainsCommand() {
30873
31264
  console.log(JSON.stringify(jobResult));
30874
31265
  } else {
30875
31266
  printSuccess(`Fine-tuning job started: ${String(jobResult["jobId"] ?? "(unknown)")}`);
30876
- console.log(chalk2.dim(` Provider: ${opts.provider}`));
30877
- console.log(chalk2.dim(` Base model: ${opts.baseModel}`));
30878
- console.log(chalk2.dim(` Name: ${modelName}`));
31267
+ console.log(chalk3.dim(` Provider: ${opts.provider}`));
31268
+ console.log(chalk3.dim(` Base model: ${opts.baseModel}`));
31269
+ console.log(chalk3.dim(` Name: ${modelName}`));
30879
31270
  if (jobResult["jobId"]) {
30880
31271
  console.log();
30881
31272
  printInfo(`Use \`todos brains model set <model-id>\` once training completes.`);
@@ -30895,9 +31286,9 @@ function makeBrainsCommand() {
30895
31286
  console.log(JSON.stringify({ activeModel: active, isDefault }));
30896
31287
  } else {
30897
31288
  if (isDefault) {
30898
- console.log(`Active model: ${chalk2.cyan(active)} ${chalk2.dim("(default)")}`);
31289
+ console.log(`Active model: ${chalk3.cyan(active)} ${chalk3.dim("(default)")}`);
30899
31290
  } else {
30900
- console.log(`Active model: ${chalk2.green(active)}`);
31291
+ console.log(`Active model: ${chalk3.green(active)}`);
30901
31292
  }
30902
31293
  }
30903
31294
  } catch (err) {
@@ -30931,9 +31322,9 @@ function makeBrainsCommand() {
30931
31322
  console.log(JSON.stringify({ activeModel: active, isDefault }));
30932
31323
  } else {
30933
31324
  if (isDefault) {
30934
- console.log(`Active model: ${chalk2.cyan(active)} ${chalk2.dim("(default)")}`);
31325
+ console.log(`Active model: ${chalk3.cyan(active)} ${chalk3.dim("(default)")}`);
30935
31326
  } else {
30936
- console.log(`Active model: ${chalk2.green(active)}`);
31327
+ console.log(`Active model: ${chalk3.green(active)}`);
30937
31328
  }
30938
31329
  }
30939
31330
  } catch (err) {
@@ -30959,7 +31350,7 @@ function handleError(e) {
30959
31350
  if (globalOpts.json) {
30960
31351
  console.log(JSON.stringify({ error: e instanceof Error ? e.message : String(e) }));
30961
31352
  } else {
30962
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
31353
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
30963
31354
  }
30964
31355
  process.exit(1);
30965
31356
  }
@@ -30969,10 +31360,10 @@ function resolveTaskId(partialId) {
30969
31360
  if (!id) {
30970
31361
  const similar = db.query("SELECT id FROM tasks WHERE id LIKE ? LIMIT 3").all(`%${partialId}%`);
30971
31362
  if (similar.length > 0) {
30972
- console.error(chalk3.red(`Could not resolve task ID: ${partialId}`));
30973
- console.error(chalk3.dim(`Did you mean: ${similar.map((s) => s.id.slice(0, 8)).join(", ")}?`));
31363
+ console.error(chalk4.red(`Could not resolve task ID: ${partialId}`));
31364
+ console.error(chalk4.dim(`Did you mean: ${similar.map((s) => s.id.slice(0, 8)).join(", ")}?`));
30974
31365
  } else {
30975
- console.error(chalk3.red(`Could not resolve task ID: ${partialId}`));
31366
+ console.error(chalk4.red(`Could not resolve task ID: ${partialId}`));
30976
31367
  }
30977
31368
  process.exit(1);
30978
31369
  }
@@ -31029,26 +31420,26 @@ function output(data, jsonMode) {
31029
31420
  }
31030
31421
  }
31031
31422
  var statusColors4 = {
31032
- pending: chalk3.yellow,
31033
- in_progress: chalk3.blue,
31034
- completed: chalk3.green,
31035
- failed: chalk3.red,
31036
- cancelled: chalk3.gray
31423
+ pending: chalk4.yellow,
31424
+ in_progress: chalk4.blue,
31425
+ completed: chalk4.green,
31426
+ failed: chalk4.red,
31427
+ cancelled: chalk4.gray
31037
31428
  };
31038
31429
  var priorityColors2 = {
31039
- critical: chalk3.red.bold,
31040
- high: chalk3.red,
31041
- medium: chalk3.yellow,
31042
- low: chalk3.gray
31430
+ critical: chalk4.red.bold,
31431
+ high: chalk4.red,
31432
+ medium: chalk4.yellow,
31433
+ low: chalk4.gray
31043
31434
  };
31044
31435
  function formatTaskLine(t) {
31045
- const statusFn = statusColors4[t.status] || chalk3.white;
31046
- const priorityFn = priorityColors2[t.priority] || chalk3.white;
31047
- const lock = t.locked_by ? chalk3.magenta(` [locked:${t.locked_by}]`) : "";
31048
- const assigned = t.assigned_to ? chalk3.cyan(` -> ${t.assigned_to}`) : "";
31049
- const tags = t.tags.length > 0 ? chalk3.dim(` [${t.tags.join(",")}]`) : "";
31050
- const plan = t.plan_id ? chalk3.magenta(` [plan:${t.plan_id.slice(0, 8)}]`) : "";
31051
- return `${chalk3.dim(t.id.slice(0, 8))} ${statusFn(t.status.padEnd(11))} ${priorityFn(t.priority.padEnd(8))} ${t.title}${assigned}${lock}${tags}${plan}`;
31436
+ const statusFn = statusColors4[t.status] || chalk4.white;
31437
+ const priorityFn = priorityColors2[t.priority] || chalk4.white;
31438
+ const lock = t.locked_by ? chalk4.magenta(` [locked:${t.locked_by}]`) : "";
31439
+ const assigned = t.assigned_to ? chalk4.cyan(` -> ${t.assigned_to}`) : "";
31440
+ const tags = t.tags.length > 0 ? chalk4.dim(` [${t.tags.join(",")}]`) : "";
31441
+ const plan = t.plan_id ? chalk4.magenta(` [plan:${t.plan_id.slice(0, 8)}]`) : "";
31442
+ return `${chalk4.dim(t.id.slice(0, 8))} ${statusFn(t.status.padEnd(11))} ${priorityFn(t.priority.padEnd(8))} ${t.title}${assigned}${lock}${tags}${plan}`;
31052
31443
  }
31053
31444
  program2.name("todos").description("Universal task management for AI coding agents").version(getPackageVersion()).option("--project <path>", "Project path").option("-j, --json", "Output as JSON").option("--agent <name>", "Agent name").option("--session <id>", "Session ID");
31054
31445
  program2.command("add <title>").description("Create a new task").option("-d, --description <text>", "Task description").option("-p, --priority <level>", "Priority: low, medium, high, critical").option("--parent <id>", "Parent task ID").option("-t, --tags <tags>", "Comma-separated tags").option("--tag <tags>", "Comma-separated tags (alias for --tags)").option("--plan <id>", "Assign to a plan").option("--assign <agent>", "Assign to agent").option("--status <status>", "Initial status").option("--list <id>", "Task list ID").option("--task-list <id>", "Task list ID (alias for --list)").option("--estimated <minutes>", "Estimated time in minutes").option("--approval", "Require approval before completion").option("--recurrence <rule>", "Recurrence rule, e.g. 'every day', 'every weekday', 'every 2 weeks'").option("--due <date>", "Due date (ISO string or YYYY-MM-DD)").option("--reason <text>", "Why this task exists").action((title, opts) => {
@@ -31060,7 +31451,7 @@ program2.command("add <title>").description("Create a new task").option("-d, --d
31060
31451
  const db = getDatabase();
31061
31452
  const id = resolvePartialId(db, "task_lists", opts.list);
31062
31453
  if (!id) {
31063
- console.error(chalk3.red(`Could not resolve task list ID: ${opts.list}`));
31454
+ console.error(chalk4.red(`Could not resolve task list ID: ${opts.list}`));
31064
31455
  process.exit(1);
31065
31456
  }
31066
31457
  return id;
@@ -31075,7 +31466,7 @@ program2.command("add <title>").description("Create a new task").option("-d, --d
31075
31466
  const db = getDatabase();
31076
31467
  const id = resolvePartialId(db, "plans", opts.plan);
31077
31468
  if (!id) {
31078
- console.error(chalk3.red(`Could not resolve plan ID: ${opts.plan}`));
31469
+ console.error(chalk4.red(`Could not resolve plan ID: ${opts.plan}`));
31079
31470
  process.exit(1);
31080
31471
  }
31081
31472
  return id;
@@ -31096,7 +31487,7 @@ program2.command("add <title>").description("Create a new task").option("-d, --d
31096
31487
  if (globalOpts.json) {
31097
31488
  output(task, true);
31098
31489
  } else {
31099
- console.log(chalk3.green("Task created:"));
31490
+ console.log(chalk4.green("Task created:"));
31100
31491
  console.log(formatTaskLine(task));
31101
31492
  }
31102
31493
  });
@@ -31109,12 +31500,12 @@ program2.command("list").description("List tasks").option("-s, --status <status>
31109
31500
  const hasExplicitProjectFilter = Boolean(globalOpts.project || opts.projectName);
31110
31501
  const allowedSortFields = new Set(["updated", "created", "priority", "status"]);
31111
31502
  if (opts.sort && !allowedSortFields.has(opts.sort)) {
31112
- console.error(chalk3.red(`Invalid --sort value: ${opts.sort}. Allowed values: updated, created, priority, status.`));
31503
+ console.error(chalk4.red(`Invalid --sort value: ${opts.sort}. Allowed values: updated, created, priority, status.`));
31113
31504
  process.exit(1);
31114
31505
  }
31115
31506
  const allowedFormats = new Set(["table", "compact", "csv", "json"]);
31116
31507
  if (opts.format && !allowedFormats.has(opts.format)) {
31117
- console.error(chalk3.red(`Invalid --format value: ${opts.format}. Allowed values: table, compact, csv, json.`));
31508
+ console.error(chalk4.red(`Invalid --format value: ${opts.format}. Allowed values: table, compact, csv, json.`));
31118
31509
  process.exit(1);
31119
31510
  }
31120
31511
  const filter = {};
@@ -31125,7 +31516,7 @@ program2.command("list").description("List tasks").option("-s, --status <status>
31125
31516
  const db = getDatabase();
31126
31517
  const listId = resolvePartialId(db, "task_lists", opts.list);
31127
31518
  if (!listId) {
31128
- console.error(chalk3.red(`Could not resolve task list ID: ${opts.list}`));
31519
+ console.error(chalk4.red(`Could not resolve task list ID: ${opts.list}`));
31129
31520
  process.exit(1);
31130
31521
  }
31131
31522
  filter["task_list_id"] = listId;
@@ -31147,7 +31538,7 @@ program2.command("list").description("List tasks").option("-s, --status <status>
31147
31538
  if (match) {
31148
31539
  filter["project_id"] = match.id;
31149
31540
  } else {
31150
- console.error(chalk3.red(`No project matching: ${opts.projectName}`));
31541
+ console.error(chalk4.red(`No project matching: ${opts.projectName}`));
31151
31542
  process.exit(1);
31152
31543
  }
31153
31544
  }
@@ -31159,7 +31550,7 @@ program2.command("list").description("List tasks").option("-s, --status <status>
31159
31550
  if (opts.limit !== undefined) {
31160
31551
  const parsedLimit = Number.parseInt(String(opts.limit), 10);
31161
31552
  if (!Number.isInteger(parsedLimit) || parsedLimit <= 0) {
31162
- console.error(chalk3.red(`Invalid --limit value: ${opts.limit}. Must be a positive integer.`));
31553
+ console.error(chalk4.red(`Invalid --limit value: ${opts.limit}. Must be a positive integer.`));
31163
31554
  process.exit(1);
31164
31555
  }
31165
31556
  filter["limit"] = parsedLimit;
@@ -31197,7 +31588,7 @@ program2.command("list").description("List tasks").option("-s, --status <status>
31197
31588
  if (fmt === "compact" || fmt === "csv")
31198
31589
  process.stdout.write("");
31199
31590
  else
31200
- console.log(chalk3.dim("No tasks found."));
31591
+ console.log(chalk4.dim("No tasks found."));
31201
31592
  return;
31202
31593
  }
31203
31594
  if (fmt === "csv") {
@@ -31224,7 +31615,7 @@ program2.command("list").description("List tasks").option("-s, --status <status>
31224
31615
  }
31225
31616
  return;
31226
31617
  }
31227
- console.log(chalk3.bold(`${tasks.length} task(s):
31618
+ console.log(chalk4.bold(`${tasks.length} task(s):
31228
31619
  `));
31229
31620
  for (const t of tasks) {
31230
31621
  console.log(formatTaskLine(t));
@@ -31241,12 +31632,12 @@ program2.command("count").description("Show task count by status").action(() =>
31241
31632
  output(counts, true);
31242
31633
  } else {
31243
31634
  const parts = [
31244
- `total: ${chalk3.bold(String(counts.total))}`,
31245
- `pending: ${chalk3.yellow(String(counts["pending"] || 0))}`,
31246
- `in_progress: ${chalk3.blue(String(counts["in_progress"] || 0))}`,
31247
- `completed: ${chalk3.green(String(counts["completed"] || 0))}`,
31248
- `failed: ${chalk3.red(String(counts["failed"] || 0))}`,
31249
- `cancelled: ${chalk3.gray(String(counts["cancelled"] || 0))}`
31635
+ `total: ${chalk4.bold(String(counts.total))}`,
31636
+ `pending: ${chalk4.yellow(String(counts["pending"] || 0))}`,
31637
+ `in_progress: ${chalk4.blue(String(counts["in_progress"] || 0))}`,
31638
+ `completed: ${chalk4.green(String(counts["completed"] || 0))}`,
31639
+ `failed: ${chalk4.red(String(counts["failed"] || 0))}`,
31640
+ `cancelled: ${chalk4.gray(String(counts["cancelled"] || 0))}`
31250
31641
  ];
31251
31642
  console.log(parts.join(" "));
31252
31643
  }
@@ -31256,83 +31647,83 @@ program2.command("show <id>").description("Show full task details").action((id)
31256
31647
  const resolvedId = resolveTaskId(id);
31257
31648
  const task = getTaskWithRelations(resolvedId);
31258
31649
  if (!task) {
31259
- console.error(chalk3.red(`Task not found: ${id}`));
31650
+ console.error(chalk4.red(`Task not found: ${id}`));
31260
31651
  process.exit(1);
31261
31652
  }
31262
31653
  if (globalOpts.json) {
31263
31654
  output(task, true);
31264
31655
  return;
31265
31656
  }
31266
- console.log(chalk3.bold(`Task Details:
31657
+ console.log(chalk4.bold(`Task Details:
31267
31658
  `));
31268
- console.log(` ${chalk3.dim("ID:")} ${task.id}`);
31269
- console.log(` ${chalk3.dim("Title:")} ${task.title}`);
31270
- console.log(` ${chalk3.dim("Status:")} ${(statusColors4[task.status] || chalk3.white)(task.status)}`);
31271
- console.log(` ${chalk3.dim("Priority:")} ${(priorityColors2[task.priority] || chalk3.white)(task.priority)}`);
31659
+ console.log(` ${chalk4.dim("ID:")} ${task.id}`);
31660
+ console.log(` ${chalk4.dim("Title:")} ${task.title}`);
31661
+ console.log(` ${chalk4.dim("Status:")} ${(statusColors4[task.status] || chalk4.white)(task.status)}`);
31662
+ console.log(` ${chalk4.dim("Priority:")} ${(priorityColors2[task.priority] || chalk4.white)(task.priority)}`);
31272
31663
  if (task.description)
31273
- console.log(` ${chalk3.dim("Desc:")} ${task.description}`);
31664
+ console.log(` ${chalk4.dim("Desc:")} ${task.description}`);
31274
31665
  if (task.assigned_to)
31275
- console.log(` ${chalk3.dim("Assigned:")} ${task.assigned_to}`);
31666
+ console.log(` ${chalk4.dim("Assigned:")} ${task.assigned_to}`);
31276
31667
  if (task.agent_id)
31277
- console.log(` ${chalk3.dim("Agent:")} ${task.agent_id}`);
31668
+ console.log(` ${chalk4.dim("Agent:")} ${task.agent_id}`);
31278
31669
  if (task.session_id)
31279
- console.log(` ${chalk3.dim("Session:")} ${task.session_id}`);
31670
+ console.log(` ${chalk4.dim("Session:")} ${task.session_id}`);
31280
31671
  if (task.locked_by)
31281
- console.log(` ${chalk3.dim("Locked:")} ${task.locked_by} (at ${task.locked_at})`);
31672
+ console.log(` ${chalk4.dim("Locked:")} ${task.locked_by} (at ${task.locked_at})`);
31282
31673
  if (task.requires_approval) {
31283
- const approvalStatus = task.approved_by ? chalk3.green(`approved by ${task.approved_by}`) : chalk3.yellow("pending approval");
31284
- console.log(` ${chalk3.dim("Approval:")} ${approvalStatus}`);
31674
+ const approvalStatus = task.approved_by ? chalk4.green(`approved by ${task.approved_by}`) : chalk4.yellow("pending approval");
31675
+ console.log(` ${chalk4.dim("Approval:")} ${approvalStatus}`);
31285
31676
  }
31286
31677
  if (task.estimated_minutes)
31287
- console.log(` ${chalk3.dim("Estimate:")} ${task.estimated_minutes} minutes`);
31678
+ console.log(` ${chalk4.dim("Estimate:")} ${task.estimated_minutes} minutes`);
31288
31679
  if (task.project_id)
31289
- console.log(` ${chalk3.dim("Project:")} ${task.project_id}`);
31680
+ console.log(` ${chalk4.dim("Project:")} ${task.project_id}`);
31290
31681
  if (task.plan_id)
31291
- console.log(` ${chalk3.dim("Plan:")} ${task.plan_id}`);
31682
+ console.log(` ${chalk4.dim("Plan:")} ${task.plan_id}`);
31292
31683
  if (task.working_dir)
31293
- console.log(` ${chalk3.dim("WorkDir:")} ${task.working_dir}`);
31684
+ console.log(` ${chalk4.dim("WorkDir:")} ${task.working_dir}`);
31294
31685
  if (task.parent)
31295
- console.log(` ${chalk3.dim("Parent:")} ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
31686
+ console.log(` ${chalk4.dim("Parent:")} ${task.parent.id.slice(0, 8)} | ${task.parent.title}`);
31296
31687
  if (task.tags.length > 0)
31297
- console.log(` ${chalk3.dim("Tags:")} ${task.tags.join(", ")}`);
31298
- console.log(` ${chalk3.dim("Version:")} ${task.version}`);
31299
- console.log(` ${chalk3.dim("Created:")} ${task.created_at}`);
31688
+ console.log(` ${chalk4.dim("Tags:")} ${task.tags.join(", ")}`);
31689
+ console.log(` ${chalk4.dim("Version:")} ${task.version}`);
31690
+ console.log(` ${chalk4.dim("Created:")} ${task.created_at}`);
31300
31691
  if (task.started_at)
31301
- console.log(` ${chalk3.dim("Started:")} ${task.started_at}`);
31692
+ console.log(` ${chalk4.dim("Started:")} ${task.started_at}`);
31302
31693
  if (task.completed_at) {
31303
- console.log(` ${chalk3.dim("Done:")} ${task.completed_at}`);
31694
+ console.log(` ${chalk4.dim("Done:")} ${task.completed_at}`);
31304
31695
  if (task.started_at) {
31305
31696
  const dur = Math.round((new Date(task.completed_at).getTime() - new Date(task.started_at).getTime()) / 60000);
31306
- console.log(` ${chalk3.dim("Duration:")} ${dur}m`);
31697
+ console.log(` ${chalk4.dim("Duration:")} ${dur}m`);
31307
31698
  }
31308
31699
  }
31309
31700
  if (task.subtasks.length > 0) {
31310
- console.log(chalk3.bold(`
31701
+ console.log(chalk4.bold(`
31311
31702
  Subtasks (${task.subtasks.length}):`));
31312
31703
  for (const st of task.subtasks) {
31313
31704
  console.log(` ${formatTaskLine(st)}`);
31314
31705
  }
31315
31706
  }
31316
31707
  if (task.dependencies.length > 0) {
31317
- console.log(chalk3.bold(`
31708
+ console.log(chalk4.bold(`
31318
31709
  Depends on (${task.dependencies.length}):`));
31319
31710
  for (const dep of task.dependencies) {
31320
31711
  console.log(` ${formatTaskLine(dep)}`);
31321
31712
  }
31322
31713
  }
31323
31714
  if (task.blocked_by.length > 0) {
31324
- console.log(chalk3.bold(`
31715
+ console.log(chalk4.bold(`
31325
31716
  Blocks (${task.blocked_by.length}):`));
31326
31717
  for (const b of task.blocked_by) {
31327
31718
  console.log(` ${formatTaskLine(b)}`);
31328
31719
  }
31329
31720
  }
31330
31721
  if (task.comments.length > 0) {
31331
- console.log(chalk3.bold(`
31722
+ console.log(chalk4.bold(`
31332
31723
  Comments (${task.comments.length}):`));
31333
31724
  for (const c of task.comments) {
31334
- const agent = c.agent_id ? chalk3.cyan(`[${c.agent_id}] `) : "";
31335
- console.log(` ${agent}${chalk3.dim(c.created_at)}: ${c.content}`);
31725
+ const agent = c.agent_id ? chalk4.cyan(`[${c.agent_id}] `) : "";
31726
+ console.log(` ${agent}${chalk4.dim(c.created_at)}: ${c.content}`);
31336
31727
  }
31337
31728
  }
31338
31729
  });
@@ -31346,12 +31737,12 @@ program2.command("inspect [id]").description("Full orientation for a task \u2014
31346
31737
  resolvedId = active[0].id;
31347
31738
  }
31348
31739
  if (!resolvedId) {
31349
- console.error(chalk3.red("No task ID given and no active task found. Pass an ID or use --agent."));
31740
+ console.error(chalk4.red("No task ID given and no active task found. Pass an ID or use --agent."));
31350
31741
  process.exit(1);
31351
31742
  }
31352
31743
  const task = getTaskWithRelations(resolvedId);
31353
31744
  if (!task) {
31354
- console.error(chalk3.red(`Task not found: ${id || resolvedId}`));
31745
+ console.error(chalk4.red(`Task not found: ${id || resolvedId}`));
31355
31746
  process.exit(1);
31356
31747
  }
31357
31748
  if (globalOpts.json) {
@@ -31371,59 +31762,59 @@ program2.command("inspect [id]").description("Full orientation for a task \u2014
31371
31762
  return;
31372
31763
  }
31373
31764
  const sid = task.short_id || task.id.slice(0, 8);
31374
- const statusColor = statusColors4[task.status] || chalk3.white;
31375
- const prioColor = priorityColors2[task.priority] || chalk3.white;
31376
- console.log(chalk3.bold(`
31377
- ${chalk3.cyan(sid)} ${statusColor(task.status)} ${prioColor(task.priority)} ${task.title}
31765
+ const statusColor = statusColors4[task.status] || chalk4.white;
31766
+ const prioColor = priorityColors2[task.priority] || chalk4.white;
31767
+ console.log(chalk4.bold(`
31768
+ ${chalk4.cyan(sid)} ${statusColor(task.status)} ${prioColor(task.priority)} ${task.title}
31378
31769
  `));
31379
31770
  if (task.description) {
31380
- console.log(chalk3.dim("Description:"));
31771
+ console.log(chalk4.dim("Description:"));
31381
31772
  console.log(` ${task.description}
31382
31773
  `);
31383
31774
  }
31384
31775
  if (task.assigned_to)
31385
- console.log(` ${chalk3.dim("Assigned:")} ${task.assigned_to}`);
31776
+ console.log(` ${chalk4.dim("Assigned:")} ${task.assigned_to}`);
31386
31777
  if (task.locked_by)
31387
- console.log(` ${chalk3.dim("Locked by:")} ${task.locked_by}`);
31778
+ console.log(` ${chalk4.dim("Locked by:")} ${task.locked_by}`);
31388
31779
  if (task.project_id)
31389
- console.log(` ${chalk3.dim("Project:")} ${task.project_id}`);
31780
+ console.log(` ${chalk4.dim("Project:")} ${task.project_id}`);
31390
31781
  if (task.plan_id)
31391
- console.log(` ${chalk3.dim("Plan:")} ${task.plan_id}`);
31782
+ console.log(` ${chalk4.dim("Plan:")} ${task.plan_id}`);
31392
31783
  if (task.started_at)
31393
- console.log(` ${chalk3.dim("Started:")} ${task.started_at}`);
31784
+ console.log(` ${chalk4.dim("Started:")} ${task.started_at}`);
31394
31785
  if (task.completed_at) {
31395
- console.log(` ${chalk3.dim("Completed:")} ${task.completed_at}`);
31786
+ console.log(` ${chalk4.dim("Completed:")} ${task.completed_at}`);
31396
31787
  if (task.started_at) {
31397
31788
  const dur = Math.round((new Date(task.completed_at).getTime() - new Date(task.started_at).getTime()) / 60000);
31398
- console.log(` ${chalk3.dim("Duration:")} ${dur}m`);
31789
+ console.log(` ${chalk4.dim("Duration:")} ${dur}m`);
31399
31790
  }
31400
31791
  }
31401
31792
  if (task.estimated_minutes)
31402
- console.log(` ${chalk3.dim("Estimate:")} ${task.estimated_minutes}m`);
31793
+ console.log(` ${chalk4.dim("Estimate:")} ${task.estimated_minutes}m`);
31403
31794
  if (task.tags.length > 0)
31404
- console.log(` ${chalk3.dim("Tags:")} ${task.tags.join(", ")}`);
31795
+ console.log(` ${chalk4.dim("Tags:")} ${task.tags.join(", ")}`);
31405
31796
  const unfinishedDeps = task.dependencies.filter((d) => d.status !== "completed" && d.status !== "cancelled");
31406
31797
  if (task.dependencies.length > 0) {
31407
- console.log(chalk3.bold(`
31798
+ console.log(chalk4.bold(`
31408
31799
  Depends on (${task.dependencies.length}):`));
31409
31800
  for (const dep of task.dependencies) {
31410
31801
  const blocked = dep.status !== "completed" && dep.status !== "cancelled";
31411
- const icon = blocked ? chalk3.red("\u2717") : chalk3.green("\u2713");
31802
+ const icon = blocked ? chalk4.red("\u2717") : chalk4.green("\u2713");
31412
31803
  console.log(` ${icon} ${formatTaskLine(dep)}`);
31413
31804
  }
31414
31805
  }
31415
31806
  if (unfinishedDeps.length > 0) {
31416
- console.log(chalk3.red(`
31807
+ console.log(chalk4.red(`
31417
31808
  BLOCKED by ${unfinishedDeps.length} unfinished dep(s)`));
31418
31809
  }
31419
31810
  if (task.blocked_by.length > 0) {
31420
- console.log(chalk3.bold(`
31811
+ console.log(chalk4.bold(`
31421
31812
  Blocks (${task.blocked_by.length}):`));
31422
31813
  for (const b of task.blocked_by)
31423
31814
  console.log(` ${formatTaskLine(b)}`);
31424
31815
  }
31425
31816
  if (task.subtasks.length > 0) {
31426
- console.log(chalk3.bold(`
31817
+ console.log(chalk4.bold(`
31427
31818
  Subtasks (${task.subtasks.length}):`));
31428
31819
  for (const st of task.subtasks)
31429
31820
  console.log(` ${formatTaskLine(st)}`);
@@ -31432,36 +31823,36 @@ ${chalk3.cyan(sid)} ${statusColor(task.status)} ${prioColor(task.priority)} ${ta
31432
31823
  const { listTaskFiles: listTaskFiles2 } = (init_task_files(), __toCommonJS(exports_task_files));
31433
31824
  const files = listTaskFiles2(task.id);
31434
31825
  if (files.length > 0) {
31435
- console.log(chalk3.bold(`
31826
+ console.log(chalk4.bold(`
31436
31827
  Files (${files.length}):`));
31437
31828
  for (const f of files)
31438
- console.log(` ${chalk3.dim(f.role || "file")} ${f.path}`);
31829
+ console.log(` ${chalk4.dim(f.role || "file")} ${f.path}`);
31439
31830
  }
31440
31831
  } catch {}
31441
31832
  try {
31442
31833
  const { getTaskCommits: getTaskCommits2 } = (init_task_commits(), __toCommonJS(exports_task_commits));
31443
31834
  const commits = getTaskCommits2(task.id);
31444
31835
  if (commits.length > 0) {
31445
- console.log(chalk3.bold(`
31836
+ console.log(chalk4.bold(`
31446
31837
  Commits (${commits.length}):`));
31447
31838
  for (const c of commits)
31448
- console.log(` ${chalk3.yellow(c.commit_hash.slice(0, 7))} ${c.message || ""}`);
31839
+ console.log(` ${chalk4.yellow(c.commit_hash.slice(0, 7))} ${c.message || ""}`);
31449
31840
  }
31450
31841
  } catch {}
31451
31842
  if (task.comments.length > 0) {
31452
- console.log(chalk3.bold(`
31843
+ console.log(chalk4.bold(`
31453
31844
  Comments (${task.comments.length}):`));
31454
31845
  for (const c of task.comments) {
31455
- const agent = c.agent_id ? chalk3.cyan(`[${c.agent_id}] `) : "";
31456
- console.log(` ${agent}${chalk3.dim(c.created_at)}: ${c.content}`);
31846
+ const agent = c.agent_id ? chalk4.cyan(`[${c.agent_id}] `) : "";
31847
+ console.log(` ${agent}${chalk4.dim(c.created_at)}: ${c.content}`);
31457
31848
  }
31458
31849
  }
31459
31850
  if (task.checklist && task.checklist.length > 0) {
31460
31851
  const done = task.checklist.filter((c) => c.checked).length;
31461
- console.log(chalk3.bold(`
31852
+ console.log(chalk4.bold(`
31462
31853
  Checklist (${done}/${task.checklist.length}):`));
31463
31854
  for (const item of task.checklist) {
31464
- const icon = item.checked ? chalk3.green("\u2611") : chalk3.dim("\u2610");
31855
+ const icon = item.checked ? chalk4.green("\u2611") : chalk4.dim("\u2610");
31465
31856
  console.log(` ${icon} ${item.text || item.title}`);
31466
31857
  }
31467
31858
  }
@@ -31477,16 +31868,16 @@ program2.command("history <id>").description("Show change history for a task (au
31477
31868
  return;
31478
31869
  }
31479
31870
  if (history.length === 0) {
31480
- console.log(chalk3.dim("No history for this task."));
31871
+ console.log(chalk4.dim("No history for this task."));
31481
31872
  return;
31482
31873
  }
31483
- console.log(chalk3.bold(`${history.length} change(s):
31874
+ console.log(chalk4.bold(`${history.length} change(s):
31484
31875
  `));
31485
31876
  for (const h of history) {
31486
- const agent = h.agent_id ? chalk3.cyan(` by ${h.agent_id}`) : "";
31487
- const field = h.field ? chalk3.yellow(` ${h.field}`) : "";
31488
- const change = h.old_value && h.new_value ? ` ${chalk3.red(h.old_value)} \u2192 ${chalk3.green(h.new_value)}` : h.new_value ? ` \u2192 ${chalk3.green(h.new_value)}` : "";
31489
- console.log(` ${chalk3.dim(h.created_at)} ${chalk3.bold(h.action)}${field}${change}${agent}`);
31877
+ const agent = h.agent_id ? chalk4.cyan(` by ${h.agent_id}`) : "";
31878
+ const field = h.field ? chalk4.yellow(` ${h.field}`) : "";
31879
+ const change = h.old_value && h.new_value ? ` ${chalk4.red(h.old_value)} \u2192 ${chalk4.green(h.new_value)}` : h.new_value ? ` \u2192 ${chalk4.green(h.new_value)}` : "";
31880
+ console.log(` ${chalk4.dim(h.created_at)} ${chalk4.bold(h.action)}${field}${change}${agent}`);
31490
31881
  }
31491
31882
  });
31492
31883
  program2.command("update <id>").description("Update a task").option("--title <text>", "New title").option("-d, --description <text>", "New description").option("-s, --status <status>", "New status").option("-p, --priority <priority>", "New priority").option("--assign <agent>", "Assign to agent").option("--tags <tags>", "New tags (comma-separated)").option("--tag <tags>", "New tags (alias for --tags)").option("--list <id>", "Move to a task list").option("--task-list <id>", "Move to a task list (alias for --list)").option("--estimated <minutes>", "Estimated time in minutes").option("--approval", "Require approval before completion").action((id, opts) => {
@@ -31496,14 +31887,14 @@ program2.command("update <id>").description("Update a task").option("--title <te
31496
31887
  const resolvedId = resolveTaskId(id);
31497
31888
  const current = getTask2(resolvedId);
31498
31889
  if (!current) {
31499
- console.error(chalk3.red(`Task not found: ${id}`));
31890
+ console.error(chalk4.red(`Task not found: ${id}`));
31500
31891
  process.exit(1);
31501
31892
  }
31502
31893
  const taskListId = opts.list ? (() => {
31503
31894
  const db = getDatabase();
31504
31895
  const resolved = resolvePartialId(db, "task_lists", opts.list);
31505
31896
  if (!resolved) {
31506
- console.error(chalk3.red(`Could not resolve task list ID: ${opts.list}`));
31897
+ console.error(chalk4.red(`Could not resolve task list ID: ${opts.list}`));
31507
31898
  process.exit(1);
31508
31899
  }
31509
31900
  return resolved;
@@ -31528,7 +31919,7 @@ program2.command("update <id>").description("Update a task").option("--title <te
31528
31919
  if (globalOpts.json) {
31529
31920
  output(task, true);
31530
31921
  } else {
31531
- console.log(chalk3.green("Task updated:"));
31922
+ console.log(chalk4.green("Task updated:"));
31532
31923
  console.log(formatTaskLine(task));
31533
31924
  }
31534
31925
  });
@@ -31548,7 +31939,7 @@ program2.command("done <id>").description("Mark a task as completed").option("--
31548
31939
  if (globalOpts.json) {
31549
31940
  output(task, true);
31550
31941
  } else {
31551
- console.log(chalk3.green("Task completed:"));
31942
+ console.log(chalk4.green("Task completed:"));
31552
31943
  console.log(formatTaskLine(task));
31553
31944
  }
31554
31945
  });
@@ -31557,15 +31948,15 @@ program2.command("approve <id>").description("Approve a task that requires appro
31557
31948
  const resolvedId = resolveTaskId(id);
31558
31949
  const task = getTask2(resolvedId);
31559
31950
  if (!task) {
31560
- console.error(chalk3.red(`Task not found: ${id}`));
31951
+ console.error(chalk4.red(`Task not found: ${id}`));
31561
31952
  process.exit(1);
31562
31953
  }
31563
31954
  if (!task.requires_approval) {
31564
- console.log(chalk3.yellow("This task does not require approval."));
31955
+ console.log(chalk4.yellow("This task does not require approval."));
31565
31956
  return;
31566
31957
  }
31567
31958
  if (task.approved_by) {
31568
- console.log(chalk3.yellow(`Already approved by ${task.approved_by}.`));
31959
+ console.log(chalk4.yellow(`Already approved by ${task.approved_by}.`));
31569
31960
  return;
31570
31961
  }
31571
31962
  try {
@@ -31573,7 +31964,7 @@ program2.command("approve <id>").description("Approve a task that requires appro
31573
31964
  if (globalOpts.json) {
31574
31965
  output(updated, true);
31575
31966
  } else {
31576
- console.log(chalk3.green(`Task approved by ${globalOpts.agent || "cli"}:`));
31967
+ console.log(chalk4.green(`Task approved by ${globalOpts.agent || "cli"}:`));
31577
31968
  console.log(formatTaskLine(updated));
31578
31969
  }
31579
31970
  } catch (e) {
@@ -31593,7 +31984,7 @@ program2.command("start <id>").description("Claim, lock, and start a task").acti
31593
31984
  if (globalOpts.json) {
31594
31985
  output(task, true);
31595
31986
  } else {
31596
- console.log(chalk3.green(`Task started by ${agentId}:`));
31987
+ console.log(chalk4.green(`Task started by ${agentId}:`));
31597
31988
  console.log(formatTaskLine(task));
31598
31989
  }
31599
31990
  });
@@ -31610,9 +32001,9 @@ program2.command("lock <id>").description("Acquire exclusive lock on a task").ac
31610
32001
  if (globalOpts.json) {
31611
32002
  output(result, true);
31612
32003
  } else if (result.success) {
31613
- console.log(chalk3.green(`Lock acquired by ${agentId}`));
32004
+ console.log(chalk4.green(`Lock acquired by ${agentId}`));
31614
32005
  } else {
31615
- console.error(chalk3.red(`Lock failed: ${result.error}`));
32006
+ console.error(chalk4.red(`Lock failed: ${result.error}`));
31616
32007
  process.exit(1);
31617
32008
  }
31618
32009
  });
@@ -31627,7 +32018,7 @@ program2.command("unlock <id>").description("Release lock on a task").action((id
31627
32018
  if (globalOpts.json) {
31628
32019
  output({ success: true }, true);
31629
32020
  } else {
31630
- console.log(chalk3.green("Lock released."));
32021
+ console.log(chalk4.green("Lock released."));
31631
32022
  }
31632
32023
  });
31633
32024
  program2.command("delete <id>").description("Delete a task").action((id) => {
@@ -31637,9 +32028,9 @@ program2.command("delete <id>").description("Delete a task").action((id) => {
31637
32028
  if (globalOpts.json) {
31638
32029
  output({ deleted }, true);
31639
32030
  } else if (deleted) {
31640
- console.log(chalk3.green("Task deleted."));
32031
+ console.log(chalk4.green("Task deleted."));
31641
32032
  } else {
31642
- console.error(chalk3.red("Task not found."));
32033
+ console.error(chalk4.red("Task not found."));
31643
32034
  process.exit(1);
31644
32035
  }
31645
32036
  });
@@ -31650,9 +32041,9 @@ program2.command("remove <id>").description("Remove/delete a task (alias for del
31650
32041
  if (globalOpts.json) {
31651
32042
  output({ deleted }, true);
31652
32043
  } else if (deleted) {
31653
- console.log(chalk3.green("Task removed."));
32044
+ console.log(chalk4.green("Task removed."));
31654
32045
  } else {
31655
- console.error(chalk3.red("Task not found."));
32046
+ console.error(chalk4.red("Task not found."));
31656
32047
  process.exit(1);
31657
32048
  }
31658
32049
  });
@@ -31672,7 +32063,7 @@ program2.command("bulk <action> <ids...>").description("Bulk operation on multip
31672
32063
  deleteTask(resolvedId);
31673
32064
  results.push({ id: resolvedId, success: true });
31674
32065
  } else {
31675
- console.error(chalk3.red(`Unknown action: ${action}. Use: done, start, delete`));
32066
+ console.error(chalk4.red(`Unknown action: ${action}. Use: done, start, delete`));
31676
32067
  process.exit(1);
31677
32068
  }
31678
32069
  } catch (e) {
@@ -31684,9 +32075,9 @@ program2.command("bulk <action> <ids...>").description("Bulk operation on multip
31684
32075
  if (globalOpts.json) {
31685
32076
  output({ results, succeeded, failed }, true);
31686
32077
  } else {
31687
- console.log(chalk3.green(`${action}: ${succeeded} succeeded, ${failed} failed`));
32078
+ console.log(chalk4.green(`${action}: ${succeeded} succeeded, ${failed} failed`));
31688
32079
  for (const r of results.filter((r2) => !r2.success)) {
31689
- console.log(chalk3.red(` ${r.id}: ${r.error}`));
32080
+ console.log(chalk4.red(` ${r.id}: ${r.error}`));
31690
32081
  }
31691
32082
  }
31692
32083
  });
@@ -31702,8 +32093,8 @@ program2.command("plans").description("List and manage plans").option("--add <na
31702
32093
  if (globalOpts.json) {
31703
32094
  output(plan, true);
31704
32095
  } else {
31705
- console.log(chalk3.green("Plan created:"));
31706
- console.log(`${chalk3.dim(plan.id.slice(0, 8))} ${chalk3.bold(plan.name)} ${chalk3.cyan(`[${plan.status}]`)}`);
32096
+ console.log(chalk4.green("Plan created:"));
32097
+ console.log(`${chalk4.dim(plan.id.slice(0, 8))} ${chalk4.bold(plan.name)} ${chalk4.cyan(`[${plan.status}]`)}`);
31707
32098
  }
31708
32099
  return;
31709
32100
  }
@@ -31711,12 +32102,12 @@ program2.command("plans").description("List and manage plans").option("--add <na
31711
32102
  const db = getDatabase();
31712
32103
  const resolvedId = resolvePartialId(db, "plans", opts.show);
31713
32104
  if (!resolvedId) {
31714
- console.error(chalk3.red(`Could not resolve plan ID: ${opts.show}`));
32105
+ console.error(chalk4.red(`Could not resolve plan ID: ${opts.show}`));
31715
32106
  process.exit(1);
31716
32107
  }
31717
32108
  const plan = getPlan(resolvedId);
31718
32109
  if (!plan) {
31719
- console.error(chalk3.red(`Plan not found: ${opts.show}`));
32110
+ console.error(chalk4.red(`Plan not found: ${opts.show}`));
31720
32111
  process.exit(1);
31721
32112
  }
31722
32113
  const tasks = listTasks({ plan_id: resolvedId });
@@ -31724,24 +32115,24 @@ program2.command("plans").description("List and manage plans").option("--add <na
31724
32115
  output({ plan, tasks }, true);
31725
32116
  return;
31726
32117
  }
31727
- console.log(chalk3.bold(`Plan Details:
32118
+ console.log(chalk4.bold(`Plan Details:
31728
32119
  `));
31729
- console.log(` ${chalk3.dim("ID:")} ${plan.id}`);
31730
- console.log(` ${chalk3.dim("Name:")} ${plan.name}`);
31731
- console.log(` ${chalk3.dim("Status:")} ${chalk3.cyan(plan.status)}`);
32120
+ console.log(` ${chalk4.dim("ID:")} ${plan.id}`);
32121
+ console.log(` ${chalk4.dim("Name:")} ${plan.name}`);
32122
+ console.log(` ${chalk4.dim("Status:")} ${chalk4.cyan(plan.status)}`);
31732
32123
  if (plan.description)
31733
- console.log(` ${chalk3.dim("Desc:")} ${plan.description}`);
32124
+ console.log(` ${chalk4.dim("Desc:")} ${plan.description}`);
31734
32125
  if (plan.project_id)
31735
- console.log(` ${chalk3.dim("Project:")} ${plan.project_id}`);
31736
- console.log(` ${chalk3.dim("Created:")} ${plan.created_at}`);
32126
+ console.log(` ${chalk4.dim("Project:")} ${plan.project_id}`);
32127
+ console.log(` ${chalk4.dim("Created:")} ${plan.created_at}`);
31737
32128
  if (tasks.length > 0) {
31738
- console.log(chalk3.bold(`
32129
+ console.log(chalk4.bold(`
31739
32130
  Tasks (${tasks.length}):`));
31740
32131
  for (const t of tasks) {
31741
32132
  console.log(` ${formatTaskLine(t)}`);
31742
32133
  }
31743
32134
  } else {
31744
- console.log(chalk3.dim(`
32135
+ console.log(chalk4.dim(`
31745
32136
  No tasks in this plan.`));
31746
32137
  }
31747
32138
  return;
@@ -31750,16 +32141,16 @@ program2.command("plans").description("List and manage plans").option("--add <na
31750
32141
  const db = getDatabase();
31751
32142
  const resolvedId = resolvePartialId(db, "plans", opts.delete);
31752
32143
  if (!resolvedId) {
31753
- console.error(chalk3.red(`Could not resolve plan ID: ${opts.delete}`));
32144
+ console.error(chalk4.red(`Could not resolve plan ID: ${opts.delete}`));
31754
32145
  process.exit(1);
31755
32146
  }
31756
32147
  const deleted = deletePlan(resolvedId);
31757
32148
  if (globalOpts.json) {
31758
32149
  output({ deleted }, true);
31759
32150
  } else if (deleted) {
31760
- console.log(chalk3.green("Plan deleted."));
32151
+ console.log(chalk4.green("Plan deleted."));
31761
32152
  } else {
31762
- console.error(chalk3.red("Plan not found."));
32153
+ console.error(chalk4.red("Plan not found."));
31763
32154
  process.exit(1);
31764
32155
  }
31765
32156
  return;
@@ -31768,7 +32159,7 @@ program2.command("plans").description("List and manage plans").option("--add <na
31768
32159
  const db = getDatabase();
31769
32160
  const resolvedId = resolvePartialId(db, "plans", opts.complete);
31770
32161
  if (!resolvedId) {
31771
- console.error(chalk3.red(`Could not resolve plan ID: ${opts.complete}`));
32162
+ console.error(chalk4.red(`Could not resolve plan ID: ${opts.complete}`));
31772
32163
  process.exit(1);
31773
32164
  }
31774
32165
  try {
@@ -31776,8 +32167,8 @@ program2.command("plans").description("List and manage plans").option("--add <na
31776
32167
  if (globalOpts.json) {
31777
32168
  output(plan, true);
31778
32169
  } else {
31779
- console.log(chalk3.green("Plan completed:"));
31780
- console.log(`${chalk3.dim(plan.id.slice(0, 8))} ${chalk3.bold(plan.name)} ${chalk3.cyan(`[${plan.status}]`)}`);
32170
+ console.log(chalk4.green("Plan completed:"));
32171
+ console.log(`${chalk4.dim(plan.id.slice(0, 8))} ${chalk4.bold(plan.name)} ${chalk4.cyan(`[${plan.status}]`)}`);
31781
32172
  }
31782
32173
  } catch (e) {
31783
32174
  handleError(e);
@@ -31790,14 +32181,14 @@ program2.command("plans").description("List and manage plans").option("--add <na
31790
32181
  return;
31791
32182
  }
31792
32183
  if (plans.length === 0) {
31793
- console.log(chalk3.dim("No plans found."));
32184
+ console.log(chalk4.dim("No plans found."));
31794
32185
  return;
31795
32186
  }
31796
- console.log(chalk3.bold(`${plans.length} plan(s):
32187
+ console.log(chalk4.bold(`${plans.length} plan(s):
31797
32188
  `));
31798
32189
  for (const p of plans) {
31799
- const desc = p.description ? chalk3.dim(` - ${p.description}`) : "";
31800
- console.log(`${chalk3.dim(p.id.slice(0, 8))} ${chalk3.bold(p.name)} ${chalk3.cyan(`[${p.status}]`)}${desc}`);
32190
+ const desc = p.description ? chalk4.dim(` - ${p.description}`) : "";
32191
+ console.log(`${chalk4.dim(p.id.slice(0, 8))} ${chalk4.bold(p.name)} ${chalk4.cyan(`[${p.status}]`)}${desc}`);
31801
32192
  }
31802
32193
  });
31803
32194
  program2.command("templates").description("List and manage task templates").option("--add <name>", "Create a template").option("--title <pattern>", "Title pattern (with --add)").option("-d, --description <text>", "Default description").option("-p, --priority <level>", "Default priority").option("-t, --tags <tags>", "Default tags (comma-separated)").option("--delete <id>", "Delete a template").option("--update <id>", "Update a template").option("--use <id>", "Create a task from a template").option("--var <vars...>", "Variable substitutions: key=value (e.g. --var feature=login)").action((opts) => {
@@ -31805,7 +32196,7 @@ program2.command("templates").description("List and manage task templates").opti
31805
32196
  const { createTemplate: createTemplate2, listTemplates: listTemplates2, deleteTemplate: deleteTemplate2, updateTemplate: updateTemplate2, taskFromTemplate: taskFromTemplate2 } = (init_templates(), __toCommonJS(exports_templates));
31806
32197
  if (opts.add) {
31807
32198
  if (!opts.title) {
31808
- console.error(chalk3.red("--title is required with --add"));
32199
+ console.error(chalk4.red("--title is required with --add"));
31809
32200
  process.exit(1);
31810
32201
  }
31811
32202
  const projectId = autoProject(globalOpts);
@@ -31820,7 +32211,7 @@ program2.command("templates").description("List and manage task templates").opti
31820
32211
  if (globalOpts.json) {
31821
32212
  output(template, true);
31822
32213
  } else {
31823
- console.log(chalk3.green(`Template created: ${template.id.slice(0, 8)} | ${template.name} | "${template.title_pattern}"`));
32214
+ console.log(chalk4.green(`Template created: ${template.id.slice(0, 8)} | ${template.name} | "${template.title_pattern}"`));
31824
32215
  }
31825
32216
  return;
31826
32217
  }
@@ -31829,9 +32220,9 @@ program2.command("templates").description("List and manage task templates").opti
31829
32220
  if (globalOpts.json) {
31830
32221
  output({ deleted }, true);
31831
32222
  } else if (deleted) {
31832
- console.log(chalk3.green("Template deleted."));
32223
+ console.log(chalk4.green("Template deleted."));
31833
32224
  } else {
31834
- console.error(chalk3.red("Template not found."));
32225
+ console.error(chalk4.red("Template not found."));
31835
32226
  process.exit(1);
31836
32227
  }
31837
32228
  return;
@@ -31850,13 +32241,13 @@ program2.command("templates").description("List and manage task templates").opti
31850
32241
  updates.tags = opts.tags.split(",").map((t) => t.trim());
31851
32242
  const updated = updateTemplate2(opts.update, updates);
31852
32243
  if (!updated) {
31853
- console.error(chalk3.red("Template not found."));
32244
+ console.error(chalk4.red("Template not found."));
31854
32245
  process.exit(1);
31855
32246
  }
31856
32247
  if (globalOpts.json) {
31857
32248
  output(updated, true);
31858
32249
  } else {
31859
- console.log(chalk3.green(`Template updated: ${updated.id.slice(0, 8)} | ${updated.name} | "${updated.title_pattern}"`));
32250
+ console.log(chalk4.green(`Template updated: ${updated.id.slice(0, 8)} | ${updated.name} | "${updated.title_pattern}"`));
31860
32251
  }
31861
32252
  return;
31862
32253
  }
@@ -31867,7 +32258,7 @@ program2.command("templates").description("List and manage task templates").opti
31867
32258
  for (const v of opts.var) {
31868
32259
  const eq = v.indexOf("=");
31869
32260
  if (eq === -1) {
31870
- console.error(chalk3.red(`Invalid variable format: ${v} (expected key=value)`));
32261
+ console.error(chalk4.red(`Invalid variable format: ${v} (expected key=value)`));
31871
32262
  process.exit(1);
31872
32263
  }
31873
32264
  variables[v.slice(0, eq)] = v.slice(eq + 1);
@@ -31889,7 +32280,7 @@ program2.command("templates").description("List and manage task templates").opti
31889
32280
  if (globalOpts.json) {
31890
32281
  output(task, true);
31891
32282
  } else {
31892
- console.log(chalk3.green("Task created from template:"));
32283
+ console.log(chalk4.green("Task created from template:"));
31893
32284
  console.log(formatTaskLine(task));
31894
32285
  }
31895
32286
  } catch (e) {
@@ -31903,14 +32294,14 @@ program2.command("templates").description("List and manage task templates").opti
31903
32294
  return;
31904
32295
  }
31905
32296
  if (templates.length === 0) {
31906
- console.log(chalk3.dim("No templates."));
32297
+ console.log(chalk4.dim("No templates."));
31907
32298
  return;
31908
32299
  }
31909
- console.log(chalk3.bold(`${templates.length} template(s):
32300
+ console.log(chalk4.bold(`${templates.length} template(s):
31910
32301
  `));
31911
32302
  for (const t of templates) {
31912
- const vars = t.variables && t.variables.length > 0 ? ` ${chalk3.dim(`(${t.variables.map((v) => `${v.name}${v.required ? "*" : ""}${v.default ? `=${v.default}` : ""}`).join(", ")})`)}` : "";
31913
- console.log(` ${chalk3.dim(t.id.slice(0, 8))} ${chalk3.bold(t.name)} ${chalk3.cyan(`"${t.title_pattern}"`)} ${chalk3.yellow(t.priority)}${vars}`);
32303
+ const vars = t.variables && t.variables.length > 0 ? ` ${chalk4.dim(`(${t.variables.map((v) => `${v.name}${v.required ? "*" : ""}${v.default ? `=${v.default}` : ""}`).join(", ")})`)}` : "";
32304
+ console.log(` ${chalk4.dim(t.id.slice(0, 8))} ${chalk4.bold(t.name)} ${chalk4.cyan(`"${t.title_pattern}"`)} ${chalk4.yellow(t.priority)}${vars}`);
31914
32305
  }
31915
32306
  });
31916
32307
  program2.command("template-init").alias("templates-init").description("Initialize built-in starter templates (open-source-project, bug-fix, feature, security-audit)").action(() => {
@@ -31922,9 +32313,9 @@ program2.command("template-init").alias("templates-init").description("Initializ
31922
32313
  return;
31923
32314
  }
31924
32315
  if (result.created === 0) {
31925
- console.log(chalk3.dim(`All ${result.skipped} built-in template(s) already exist.`));
32316
+ console.log(chalk4.dim(`All ${result.skipped} built-in template(s) already exist.`));
31926
32317
  } else {
31927
- console.log(chalk3.green(`Created ${result.created} template(s): ${result.names.join(", ")}. Skipped ${result.skipped} existing.`));
32318
+ console.log(chalk4.green(`Created ${result.created} template(s): ${result.names.join(", ")}. Skipped ${result.skipped} existing.`));
31928
32319
  }
31929
32320
  });
31930
32321
  program2.command("template-preview <id>").alias("templates-preview").description("Preview a template without creating tasks \u2014 shows resolved titles, deps, and priorities").option("--var <vars...>", "Variable substitution in key=value format (e.g. --var name=invoices)").action((id, opts) => {
@@ -31935,7 +32326,7 @@ program2.command("template-preview <id>").alias("templates-preview").description
31935
32326
  for (const v of opts.var) {
31936
32327
  const eq = v.indexOf("=");
31937
32328
  if (eq === -1) {
31938
- console.error(chalk3.red(`Invalid variable format: ${v} (expected key=value)`));
32329
+ console.error(chalk4.red(`Invalid variable format: ${v} (expected key=value)`));
31939
32330
  process.exit(1);
31940
32331
  }
31941
32332
  variables[v.slice(0, eq)] = v.slice(eq + 1);
@@ -31947,19 +32338,19 @@ program2.command("template-preview <id>").alias("templates-preview").description
31947
32338
  output(preview, true);
31948
32339
  return;
31949
32340
  }
31950
- console.log(chalk3.bold(`Preview: ${preview.template_name} (${preview.tasks.length} tasks)`));
32341
+ console.log(chalk4.bold(`Preview: ${preview.template_name} (${preview.tasks.length} tasks)`));
31951
32342
  if (preview.description)
31952
- console.log(chalk3.dim(` ${preview.description}`));
32343
+ console.log(chalk4.dim(` ${preview.description}`));
31953
32344
  if (preview.variables.length > 0) {
31954
- console.log(chalk3.dim(` Variables: ${preview.variables.map((v) => `${v.name}${v.required ? "*" : ""}${v.default ? `=${v.default}` : ""}`).join(", ")}`));
32345
+ console.log(chalk4.dim(` Variables: ${preview.variables.map((v) => `${v.name}${v.required ? "*" : ""}${v.default ? `=${v.default}` : ""}`).join(", ")}`));
31955
32346
  }
31956
32347
  if (Object.keys(preview.resolved_variables).length > 0) {
31957
- console.log(chalk3.dim(` Resolved: ${Object.entries(preview.resolved_variables).map(([k, v]) => `${k}=${v}`).join(", ")}`));
32348
+ console.log(chalk4.dim(` Resolved: ${Object.entries(preview.resolved_variables).map(([k, v]) => `${k}=${v}`).join(", ")}`));
31958
32349
  }
31959
32350
  console.log();
31960
32351
  for (const t of preview.tasks) {
31961
- const deps = t.depends_on_positions.length > 0 ? chalk3.dim(` (after: ${t.depends_on_positions.join(", ")})`) : "";
31962
- console.log(` ${chalk3.dim(`[${t.position}]`)} ${chalk3.yellow(t.priority)} | ${t.title}${deps}`);
32352
+ const deps = t.depends_on_positions.length > 0 ? chalk4.dim(` (after: ${t.depends_on_positions.join(", ")})`) : "";
32353
+ console.log(` ${chalk4.dim(`[${t.position}]`)} ${chalk4.yellow(t.priority)} | ${t.title}${deps}`);
31963
32354
  }
31964
32355
  } catch (e) {
31965
32356
  handleError(e);
@@ -31981,7 +32372,7 @@ program2.command("template-import [file]").alias("templates-import").description
31981
32372
  try {
31982
32373
  const filePath = file || opts.file;
31983
32374
  if (!filePath) {
31984
- console.error(chalk3.red("Provide a file path: todos template-import <file> or --file <path>"));
32375
+ console.error(chalk4.red("Provide a file path: todos template-import <file> or --file <path>"));
31985
32376
  process.exit(1);
31986
32377
  }
31987
32378
  const content = readFileSync8(filePath, "utf-8");
@@ -31990,7 +32381,7 @@ program2.command("template-import [file]").alias("templates-import").description
31990
32381
  if (globalOpts.json) {
31991
32382
  output(template, true);
31992
32383
  } else {
31993
- console.log(chalk3.green(`Template imported: ${template.id.slice(0, 8)} | ${template.name} | "${template.title_pattern}"`));
32384
+ console.log(chalk4.green(`Template imported: ${template.id.slice(0, 8)} | ${template.name} | "${template.title_pattern}"`));
31994
32385
  }
31995
32386
  } catch (e) {
31996
32387
  handleError(e);
@@ -32002,7 +32393,7 @@ program2.command("template-history <id>").alias("templates-history").description
32002
32393
  try {
32003
32394
  const template = getTemplate2(id);
32004
32395
  if (!template) {
32005
- console.error(chalk3.red("Template not found."));
32396
+ console.error(chalk4.red("Template not found."));
32006
32397
  process.exit(1);
32007
32398
  }
32008
32399
  const versions = listTemplateVersions2(id);
@@ -32010,13 +32401,13 @@ program2.command("template-history <id>").alias("templates-history").description
32010
32401
  output({ current_version: template.version, versions }, true);
32011
32402
  return;
32012
32403
  }
32013
- console.log(chalk3.bold(`${template.name} \u2014 current version: ${template.version}`));
32404
+ console.log(chalk4.bold(`${template.name} \u2014 current version: ${template.version}`));
32014
32405
  if (versions.length === 0) {
32015
- console.log(chalk3.dim(" No previous versions."));
32406
+ console.log(chalk4.dim(" No previous versions."));
32016
32407
  } else {
32017
32408
  for (const v of versions) {
32018
32409
  const snap = JSON.parse(v.snapshot);
32019
- console.log(` ${chalk3.dim(`v${v.version}`)} | ${v.created_at} | ${snap.name} | "${snap.title_pattern}"`);
32410
+ console.log(` ${chalk4.dim(`v${v.version}`)} | ${v.created_at} | ${snap.name} | "${snap.title_pattern}"`);
32020
32411
  }
32021
32412
  }
32022
32413
  } catch (e) {
@@ -32035,7 +32426,7 @@ program2.command("comment <id> <text>").description("Add a comment to a task").a
32035
32426
  if (globalOpts.json) {
32036
32427
  output(comment, true);
32037
32428
  } else {
32038
- console.log(chalk3.green("Comment added."));
32429
+ console.log(chalk4.green("Comment added."));
32039
32430
  }
32040
32431
  });
32041
32432
  program2.command("search <query>").description("Search tasks").option("--status <status>", "Filter by status").option("--priority <p>", "Filter by priority").option("--assigned <agent>", "Filter by assigned agent").option("--since <date>", "Only tasks updated after this date (ISO)").option("--blocked", "Only blocked tasks (incomplete dependencies)").option("--has-deps", "Only tasks with dependencies").action((query, opts) => {
@@ -32060,10 +32451,10 @@ program2.command("search <query>").description("Search tasks").option("--status
32060
32451
  return;
32061
32452
  }
32062
32453
  if (tasks.length === 0) {
32063
- console.log(chalk3.dim(`No tasks matching "${query}".`));
32454
+ console.log(chalk4.dim(`No tasks matching "${query}".`));
32064
32455
  return;
32065
32456
  }
32066
- console.log(chalk3.bold(`${tasks.length} result(s) for "${query}":
32457
+ console.log(chalk4.bold(`${tasks.length} result(s) for "${query}":
32067
32458
  `));
32068
32459
  for (const t of tasks) {
32069
32460
  console.log(formatTaskLine(t));
@@ -32077,13 +32468,13 @@ program2.command("deps <id>").description("Manage task dependencies").option("--
32077
32468
  try {
32078
32469
  addDependency(resolvedId, depId);
32079
32470
  } catch (e) {
32080
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
32471
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
32081
32472
  process.exit(1);
32082
32473
  }
32083
32474
  if (globalOpts.json) {
32084
32475
  output({ task_id: resolvedId, depends_on: depId }, true);
32085
32476
  } else {
32086
- console.log(chalk3.green("Dependency added."));
32477
+ console.log(chalk4.green("Dependency added."));
32087
32478
  }
32088
32479
  } else if (opts.remove) {
32089
32480
  const depId = resolveTaskId(opts.remove);
@@ -32091,12 +32482,12 @@ program2.command("deps <id>").description("Manage task dependencies").option("--
32091
32482
  if (globalOpts.json) {
32092
32483
  output({ removed }, true);
32093
32484
  } else {
32094
- console.log(removed ? chalk3.green("Dependency removed.") : chalk3.red("Dependency not found."));
32485
+ console.log(removed ? chalk4.green("Dependency removed.") : chalk4.red("Dependency not found."));
32095
32486
  }
32096
32487
  } else {
32097
32488
  const task = getTaskWithRelations(resolvedId);
32098
32489
  if (!task) {
32099
- console.error(chalk3.red("Task not found."));
32490
+ console.error(chalk4.red("Task not found."));
32100
32491
  process.exit(1);
32101
32492
  }
32102
32493
  if (globalOpts.json) {
@@ -32104,19 +32495,19 @@ program2.command("deps <id>").description("Manage task dependencies").option("--
32104
32495
  return;
32105
32496
  }
32106
32497
  if (task.dependencies.length > 0) {
32107
- console.log(chalk3.bold("Depends on:"));
32498
+ console.log(chalk4.bold("Depends on:"));
32108
32499
  for (const dep of task.dependencies) {
32109
32500
  console.log(` ${formatTaskLine(dep)}`);
32110
32501
  }
32111
32502
  }
32112
32503
  if (task.blocked_by.length > 0) {
32113
- console.log(chalk3.bold("Blocks:"));
32504
+ console.log(chalk4.bold("Blocks:"));
32114
32505
  for (const b of task.blocked_by) {
32115
32506
  console.log(` ${formatTaskLine(b)}`);
32116
32507
  }
32117
32508
  }
32118
32509
  if (task.dependencies.length === 0 && task.blocked_by.length === 0) {
32119
- console.log(chalk3.dim("No dependencies."));
32510
+ console.log(chalk4.dim("No dependencies."));
32120
32511
  }
32121
32512
  }
32122
32513
  });
@@ -32142,9 +32533,9 @@ program2.command("projects").description("List and manage projects").option("--a
32142
32533
  if (globalOpts.json) {
32143
32534
  output(project, true);
32144
32535
  } else {
32145
- console.log(chalk3.green(`Project registered: ${project.name} (${project.path})`));
32536
+ console.log(chalk4.green(`Project registered: ${project.name} (${project.path})`));
32146
32537
  if (project.task_list_id)
32147
- console.log(chalk3.dim(` Task list: ${project.task_list_id}`));
32538
+ console.log(chalk4.dim(` Task list: ${project.task_list_id}`));
32148
32539
  }
32149
32540
  return;
32150
32541
  }
@@ -32154,14 +32545,14 @@ program2.command("projects").description("List and manage projects").option("--a
32154
32545
  return;
32155
32546
  }
32156
32547
  if (projects.length === 0) {
32157
- console.log(chalk3.dim("No projects registered."));
32548
+ console.log(chalk4.dim("No projects registered."));
32158
32549
  return;
32159
32550
  }
32160
- console.log(chalk3.bold(`${projects.length} project(s):
32551
+ console.log(chalk4.bold(`${projects.length} project(s):
32161
32552
  `));
32162
32553
  for (const p of projects) {
32163
- const taskList = p.task_list_id ? chalk3.cyan(` [${p.task_list_id}]`) : "";
32164
- console.log(`${chalk3.dim(p.id.slice(0, 8))} ${chalk3.bold(p.name)} ${chalk3.dim(p.path)}${taskList}${p.description ? ` - ${p.description}` : ""}`);
32554
+ const taskList = p.task_list_id ? chalk4.cyan(` [${p.task_list_id}]`) : "";
32555
+ console.log(`${chalk4.dim(p.id.slice(0, 8))} ${chalk4.bold(p.name)} ${chalk4.dim(p.path)}${taskList}${p.description ? ` - ${p.description}` : ""}`);
32165
32556
  }
32166
32557
  });
32167
32558
  program2.command("project-rename <id-or-slug> <new-slug>").description("Rename a project slug. Cascades to matching task lists. Task prefixes (e.g. APP-00001) are unchanged.").option("--name <name>", "Also update the project display name").option("-j, --json", "Output as JSON").action((idOrSlug, newSlug, opts) => {
@@ -32176,20 +32567,20 @@ program2.command("project-rename <id-or-slug> <new-slug>").description("Rename a
32176
32567
  resolvedId = bySlug?.id ?? null;
32177
32568
  }
32178
32569
  if (!resolvedId) {
32179
- console.error(chalk3.red(`Project not found: ${idOrSlug}`));
32570
+ console.error(chalk4.red(`Project not found: ${idOrSlug}`));
32180
32571
  process.exit(1);
32181
32572
  }
32182
32573
  const result = renameProject2(resolvedId, { name: opts.name, new_slug: newSlug });
32183
32574
  if (useJson) {
32184
32575
  output({ project: result.project, task_lists_updated: result.task_lists_updated }, true);
32185
32576
  } else {
32186
- console.log(chalk3.green(`Project renamed: ${result.project.name} (slug: ${result.project.task_list_id})`));
32577
+ console.log(chalk4.green(`Project renamed: ${result.project.name} (slug: ${result.project.task_list_id})`));
32187
32578
  if (result.task_lists_updated > 0) {
32188
- console.log(chalk3.dim(` Updated ${result.task_lists_updated} task list slug(s).`));
32579
+ console.log(chalk4.dim(` Updated ${result.task_lists_updated} task list slug(s).`));
32189
32580
  }
32190
32581
  }
32191
32582
  } catch (e) {
32192
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
32583
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
32193
32584
  process.exit(1);
32194
32585
  }
32195
32586
  });
@@ -32202,17 +32593,17 @@ projectsPathCmd.command("set <project-id> <path>").description("Set the local pa
32202
32593
  const db = getDatabase();
32203
32594
  const resolved = resolvePartialId(db, "projects", projectId);
32204
32595
  if (!resolved) {
32205
- console.error(chalk3.red(`Project not found: ${projectId}`));
32596
+ console.error(chalk4.red(`Project not found: ${projectId}`));
32206
32597
  process.exit(1);
32207
32598
  }
32208
32599
  const entry = setMachineLocalPath2(resolved, resolve4(projectPath));
32209
32600
  if (useJson) {
32210
32601
  output(entry, true);
32211
32602
  } else {
32212
- console.log(chalk3.green(`Local path set: ${entry.path} (machine: ${entry.machine_id.slice(0, 8)})`));
32603
+ console.log(chalk4.green(`Local path set: ${entry.path} (machine: ${entry.machine_id.slice(0, 8)})`));
32213
32604
  }
32214
32605
  } catch (e) {
32215
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
32606
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
32216
32607
  process.exit(1);
32217
32608
  }
32218
32609
  });
@@ -32224,7 +32615,7 @@ projectsPathCmd.command("list <project-id>").description("List all machine path
32224
32615
  const db = getDatabase();
32225
32616
  const resolved = resolvePartialId(db, "projects", projectId);
32226
32617
  if (!resolved) {
32227
- console.error(chalk3.red(`Project not found: ${projectId}`));
32618
+ console.error(chalk4.red(`Project not found: ${projectId}`));
32228
32619
  process.exit(1);
32229
32620
  }
32230
32621
  const paths = listMachineLocalPaths2(resolved);
@@ -32233,14 +32624,14 @@ projectsPathCmd.command("list <project-id>").description("List all machine path
32233
32624
  return;
32234
32625
  }
32235
32626
  if (paths.length === 0) {
32236
- console.log(chalk3.dim("No machine path overrides."));
32627
+ console.log(chalk4.dim("No machine path overrides."));
32237
32628
  return;
32238
32629
  }
32239
32630
  for (const p of paths) {
32240
- console.log(`${chalk3.dim(p.machine_id.slice(0, 8))} ${p.path} ${chalk3.dim(p.updated_at)}`);
32631
+ console.log(`${chalk4.dim(p.machine_id.slice(0, 8))} ${p.path} ${chalk4.dim(p.updated_at)}`);
32241
32632
  }
32242
32633
  } catch (e) {
32243
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
32634
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
32244
32635
  process.exit(1);
32245
32636
  }
32246
32637
  });
@@ -32250,17 +32641,17 @@ projectsPathCmd.command("remove <project-id>").description("Remove the local pat
32250
32641
  const db = getDatabase();
32251
32642
  const resolved = resolvePartialId(db, "projects", projectId);
32252
32643
  if (!resolved) {
32253
- console.error(chalk3.red(`Project not found: ${projectId}`));
32644
+ console.error(chalk4.red(`Project not found: ${projectId}`));
32254
32645
  process.exit(1);
32255
32646
  }
32256
32647
  const removed = removeMachineLocalPath2(resolved, opts.machine);
32257
32648
  if (removed) {
32258
- console.log(chalk3.green("Machine path override removed."));
32649
+ console.log(chalk4.green("Machine path override removed."));
32259
32650
  } else {
32260
- console.log(chalk3.dim("No override found to remove."));
32651
+ console.log(chalk4.dim("No override found to remove."));
32261
32652
  }
32262
32653
  } catch (e) {
32263
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
32654
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
32264
32655
  process.exit(1);
32265
32656
  }
32266
32657
  });
@@ -32274,7 +32665,7 @@ program2.command("extract <path>").description("Extract TODO/FIXME/HACK/BUG/XXX/
32274
32665
  const db = getDatabase();
32275
32666
  const id = resolvePartialId(db, "task_lists", opts.list);
32276
32667
  if (!id) {
32277
- console.error(chalk3.red(`Could not resolve task list ID: ${opts.list}`));
32668
+ console.error(chalk4.red(`Could not resolve task list ID: ${opts.list}`));
32278
32669
  process.exit(1);
32279
32670
  }
32280
32671
  return id;
@@ -32293,18 +32684,18 @@ program2.command("extract <path>").description("Extract TODO/FIXME/HACK/BUG/XXX/
32293
32684
  if (globalOpts.json) {
32294
32685
  console.log(JSON.stringify(opts.dryRun ? { comments: result.comments } : { tasks_created: result.tasks.length, skipped: result.skipped, comments: result.comments.length }, null, 2));
32295
32686
  } else if (opts.dryRun) {
32296
- console.log(chalk3.cyan(`Found ${result.comments.length} comment(s):
32687
+ console.log(chalk4.cyan(`Found ${result.comments.length} comment(s):
32297
32688
  `));
32298
32689
  for (const c of result.comments) {
32299
- console.log(` ${chalk3.yellow(`[${c.tag}]`)} ${c.message}`);
32300
- console.log(` ${chalk3.gray(`${c.file}:${c.line}`)}`);
32690
+ console.log(` ${chalk4.yellow(`[${c.tag}]`)} ${c.message}`);
32691
+ console.log(` ${chalk4.gray(`${c.file}:${c.line}`)}`);
32301
32692
  }
32302
32693
  } else {
32303
- console.log(chalk3.green(`Created ${result.tasks.length} task(s)`));
32694
+ console.log(chalk4.green(`Created ${result.tasks.length} task(s)`));
32304
32695
  if (result.skipped > 0) {
32305
- console.log(chalk3.gray(`Skipped ${result.skipped} duplicate(s)`));
32696
+ console.log(chalk4.gray(`Skipped ${result.skipped} duplicate(s)`));
32306
32697
  }
32307
- console.log(chalk3.gray(`Total comments found: ${result.comments.length}`));
32698
+ console.log(chalk4.gray(`Total comments found: ${result.comments.length}`));
32308
32699
  for (const t of result.tasks) {
32309
32700
  console.log(formatTaskLine(t));
32310
32701
  }
@@ -32354,7 +32745,7 @@ program2.command("sync").description("Sync tasks with an agent task list (Claude
32354
32745
  const agent = opts.agent || "claude";
32355
32746
  const taskListId = resolveTaskListId(agent, opts.taskList, project?.task_list_id);
32356
32747
  if (!taskListId) {
32357
- console.error(chalk3.red(`Could not detect task list ID for ${agent}. Use --task-list <id> or set appropriate env vars.`));
32748
+ console.error(chalk4.red(`Could not detect task list ID for ${agent}. Use --task-list <id> or set appropriate env vars.`));
32358
32749
  process.exit(1);
32359
32750
  }
32360
32751
  result = syncWithAgent(agent, taskListId, projectId, direction, { prefer });
@@ -32364,14 +32755,14 @@ program2.command("sync").description("Sync tasks with an agent task list (Claude
32364
32755
  return;
32365
32756
  }
32366
32757
  if (result.pulled > 0)
32367
- console.log(chalk3.green(`Pulled ${result.pulled} task(s).`));
32758
+ console.log(chalk4.green(`Pulled ${result.pulled} task(s).`));
32368
32759
  if (result.pushed > 0)
32369
- console.log(chalk3.green(`Pushed ${result.pushed} task(s).`));
32760
+ console.log(chalk4.green(`Pushed ${result.pushed} task(s).`));
32370
32761
  if (result.pulled === 0 && result.pushed === 0 && result.errors.length === 0) {
32371
- console.log(chalk3.dim("Nothing to sync."));
32762
+ console.log(chalk4.dim("Nothing to sync."));
32372
32763
  }
32373
32764
  for (const err of result.errors) {
32374
- console.error(chalk3.red(` Error: ${err}`));
32765
+ console.error(chalk4.red(` Error: ${err}`));
32375
32766
  }
32376
32767
  });
32377
32768
  var hooks = program2.command("hooks").description("Manage Claude Code hook integration");
@@ -32411,7 +32802,7 @@ exit 0
32411
32802
  const hookPath = join13(hooksDir, "todos-sync.sh");
32412
32803
  writeFileSync6(hookPath, hookScript);
32413
32804
  execSync(`chmod +x "${hookPath}"`);
32414
- console.log(chalk3.green(`Hook script created: ${hookPath}`));
32805
+ console.log(chalk4.green(`Hook script created: ${hookPath}`));
32415
32806
  const settingsPath = join13(process.cwd(), ".claude", "settings.json");
32416
32807
  const settings = readJsonFile2(settingsPath);
32417
32808
  if (!settings["hooks"]) {
@@ -32438,8 +32829,8 @@ exit 0
32438
32829
  });
32439
32830
  hooksConfig["PostToolUse"] = filtered;
32440
32831
  writeJsonFile2(settingsPath, settings);
32441
- console.log(chalk3.green(`Claude Code hooks configured in: ${settingsPath}`));
32442
- console.log(chalk3.dim("Task list ID auto-detected from project."));
32832
+ console.log(chalk4.green(`Claude Code hooks configured in: ${settingsPath}`));
32833
+ console.log(chalk4.dim("Task list ID auto-detected from project."));
32443
32834
  });
32444
32835
  program2.command("mcp").description("Start MCP server (stdio)").option("--register <agent>", "Register MCP server with an agent (claude, codex, gemini, all)").option("--unregister <agent>", "Unregister MCP server from an agent (claude, codex, gemini, all)").option("-g, --global", "Register/unregister globally (user-level) instead of project-level").action(async (opts) => {
32445
32836
  if (opts.register) {
@@ -32497,20 +32888,20 @@ function registerClaude(binPath, global2) {
32497
32888
  try {
32498
32889
  const { execSync: execSync2 } = __require("child_process");
32499
32890
  execSync2(cmd, { stdio: "pipe" });
32500
- console.log(chalk3.green(`Claude Code (${scope}): registered via 'claude mcp add'`));
32891
+ console.log(chalk4.green(`Claude Code (${scope}): registered via 'claude mcp add'`));
32501
32892
  } catch {
32502
- console.log(chalk3.yellow(`Claude Code: could not auto-register. Run this command manually:`));
32503
- console.log(chalk3.cyan(` ${cmd}`));
32893
+ console.log(chalk4.yellow(`Claude Code: could not auto-register. Run this command manually:`));
32894
+ console.log(chalk4.cyan(` ${cmd}`));
32504
32895
  }
32505
32896
  }
32506
32897
  function unregisterClaude(_global) {
32507
32898
  try {
32508
32899
  const { execSync: execSync2 } = __require("child_process");
32509
32900
  execSync2("claude mcp remove todos", { stdio: "pipe" });
32510
- console.log(chalk3.green(`Claude Code: removed todos MCP server`));
32901
+ console.log(chalk4.green(`Claude Code: removed todos MCP server`));
32511
32902
  } catch {
32512
- console.log(chalk3.yellow(`Claude Code: could not auto-remove. Run manually:`));
32513
- console.log(chalk3.cyan(" claude mcp remove todos"));
32903
+ console.log(chalk4.yellow(`Claude Code: could not auto-remove. Run manually:`));
32904
+ console.log(chalk4.cyan(" claude mcp remove todos"));
32514
32905
  }
32515
32906
  }
32516
32907
  function registerCodex(binPath) {
@@ -32525,19 +32916,19 @@ args = []
32525
32916
  content = content.trimEnd() + `
32526
32917
  ` + block;
32527
32918
  writeTomlFile(configPath, content);
32528
- console.log(chalk3.green(`Codex CLI: registered in ${configPath}`));
32919
+ console.log(chalk4.green(`Codex CLI: registered in ${configPath}`));
32529
32920
  }
32530
32921
  function unregisterCodex() {
32531
32922
  const configPath = join13(HOME2, ".codex", "config.toml");
32532
32923
  let content = readTomlFile(configPath);
32533
32924
  if (!content.includes("[mcp_servers.todos]")) {
32534
- console.log(chalk3.dim(`Codex CLI: todos not found in ${configPath}`));
32925
+ console.log(chalk4.dim(`Codex CLI: todos not found in ${configPath}`));
32535
32926
  return;
32536
32927
  }
32537
32928
  content = removeTomlBlock(content, "mcp_servers.todos");
32538
32929
  writeTomlFile(configPath, content.trimEnd() + `
32539
32930
  `);
32540
- console.log(chalk3.green(`Codex CLI: unregistered from ${configPath}`));
32931
+ console.log(chalk4.green(`Codex CLI: unregistered from ${configPath}`));
32541
32932
  }
32542
32933
  function removeTomlBlock(content, blockName) {
32543
32934
  const lines = content.split(`
@@ -32572,19 +32963,19 @@ function registerGemini(binPath) {
32572
32963
  args: []
32573
32964
  };
32574
32965
  writeJsonFile2(configPath, config);
32575
- console.log(chalk3.green(`Gemini CLI: registered in ${configPath}`));
32966
+ console.log(chalk4.green(`Gemini CLI: registered in ${configPath}`));
32576
32967
  }
32577
32968
  function unregisterGemini() {
32578
32969
  const configPath = join13(HOME2, ".gemini", "settings.json");
32579
32970
  const config = readJsonFile2(configPath);
32580
32971
  const servers = config["mcpServers"];
32581
32972
  if (!servers || !("todos" in servers)) {
32582
- console.log(chalk3.dim(`Gemini CLI: todos not found in ${configPath}`));
32973
+ console.log(chalk4.dim(`Gemini CLI: todos not found in ${configPath}`));
32583
32974
  return;
32584
32975
  }
32585
32976
  delete servers["todos"];
32586
32977
  writeJsonFile2(configPath, config);
32587
- console.log(chalk3.green(`Gemini CLI: unregistered from ${configPath}`));
32978
+ console.log(chalk4.green(`Gemini CLI: unregistered from ${configPath}`));
32588
32979
  }
32589
32980
  function registerMcp(agent, global2) {
32590
32981
  const agents = agent === "all" ? ["claude", "codex", "gemini"] : [agent];
@@ -32601,7 +32992,7 @@ function registerMcp(agent, global2) {
32601
32992
  registerGemini(binPath);
32602
32993
  break;
32603
32994
  default:
32604
- console.error(chalk3.red(`Unknown agent: ${a}. Use: claude, codex, gemini, all`));
32995
+ console.error(chalk4.red(`Unknown agent: ${a}. Use: claude, codex, gemini, all`));
32605
32996
  }
32606
32997
  }
32607
32998
  }
@@ -32619,7 +33010,7 @@ function unregisterMcp(agent, global2) {
32619
33010
  unregisterGemini();
32620
33011
  break;
32621
33012
  default:
32622
- console.error(chalk3.red(`Unknown agent: ${a}. Use: claude, codex, gemini, all`));
33013
+ console.error(chalk4.red(`Unknown agent: ${a}. Use: claude, codex, gemini, all`));
32623
33014
  }
32624
33015
  }
32625
33016
  }
@@ -32628,7 +33019,7 @@ program2.command("import <url>").description("Import a GitHub issue as a task").
32628
33019
  const { parseGitHubUrl: parseGitHubUrl2, fetchGitHubIssue: fetchGitHubIssue2, issueToTask: issueToTask2 } = (init_github(), __toCommonJS(exports_github));
32629
33020
  const parsed = parseGitHubUrl2(url);
32630
33021
  if (!parsed) {
32631
- console.error(chalk3.red("Invalid GitHub issue URL. Expected: https://github.com/owner/repo/issues/123"));
33022
+ console.error(chalk4.red("Invalid GitHub issue URL. Expected: https://github.com/owner/repo/issues/123"));
32632
33023
  process.exit(1);
32633
33024
  }
32634
33025
  try {
@@ -32640,15 +33031,15 @@ program2.command("import <url>").description("Import a GitHub issue as a task").
32640
33031
  output(task, true);
32641
33032
  return;
32642
33033
  }
32643
- console.log(chalk3.green(`Imported GH#${issue.number}: ${issue.title}`));
32644
- console.log(` ${chalk3.dim("Task ID:")} ${task.short_id || task.id}`);
32645
- console.log(` ${chalk3.dim("Labels:")} ${issue.labels.join(", ") || "none"}`);
32646
- console.log(` ${chalk3.dim("Priority:")} ${task.priority}`);
33034
+ console.log(chalk4.green(`Imported GH#${issue.number}: ${issue.title}`));
33035
+ console.log(` ${chalk4.dim("Task ID:")} ${task.short_id || task.id}`);
33036
+ console.log(` ${chalk4.dim("Labels:")} ${issue.labels.join(", ") || "none"}`);
33037
+ console.log(` ${chalk4.dim("Priority:")} ${task.priority}`);
32647
33038
  } catch (e) {
32648
33039
  if (e.message?.includes("gh")) {
32649
- console.error(chalk3.red("GitHub CLI (gh) not found or not authenticated. Install: https://cli.github.com"));
33040
+ console.error(chalk4.red("GitHub CLI (gh) not found or not authenticated. Install: https://cli.github.com"));
32650
33041
  } else {
32651
- console.error(chalk3.red(`Import failed: ${e.message}`));
33042
+ console.error(chalk4.red(`Import failed: ${e.message}`));
32652
33043
  }
32653
33044
  process.exit(1);
32654
33045
  }
@@ -32668,7 +33059,7 @@ program2.command("link-commit <task-id> <sha>").description("Link a git commit t
32668
33059
  output(commit, true);
32669
33060
  return;
32670
33061
  }
32671
- console.log(chalk3.green(`Linked commit ${sha.slice(0, 7)} to task ${taskId}`));
33062
+ console.log(chalk4.green(`Linked commit ${sha.slice(0, 7)} to task ${taskId}`));
32672
33063
  });
32673
33064
  var hookCmd = program2.command("hook").description("Manage git hooks for auto-linking commits to tasks");
32674
33065
  hookCmd.command("install").description("Install post-commit hook that auto-links commits to tasks").action(() => {
@@ -32681,7 +33072,7 @@ hookCmd.command("install").description("Install post-commit hook that auto-links
32681
33072
  if (existsSync11(hookPath)) {
32682
33073
  const existing = readFileSync8(hookPath, "utf-8");
32683
33074
  if (existing.includes(marker)) {
32684
- console.log(chalk3.yellow("Hook already installed."));
33075
+ console.log(chalk4.yellow("Hook already installed."));
32685
33076
  return;
32686
33077
  }
32687
33078
  writeFileSync7(hookPath, existing + `
@@ -32695,9 +33086,9 @@ $(dirname "$0")/../../scripts/post-commit-hook.sh
32695
33086
  `);
32696
33087
  chmodSync(hookPath, 493);
32697
33088
  }
32698
- console.log(chalk3.green("Post-commit hook installed. Commits with task IDs (e.g. OPE-00042) will auto-link."));
33089
+ console.log(chalk4.green("Post-commit hook installed. Commits with task IDs (e.g. OPE-00042) will auto-link."));
32699
33090
  } catch (e) {
32700
- console.error(chalk3.red("Not in a git repository or hook install failed."));
33091
+ console.error(chalk4.red("Not in a git repository or hook install failed."));
32701
33092
  process.exit(1);
32702
33093
  }
32703
33094
  });
@@ -32709,12 +33100,12 @@ hookCmd.command("uninstall").description("Remove the todos post-commit hook").ac
32709
33100
  const { existsSync: existsSync11, readFileSync: readFileSync8, writeFileSync: writeFileSync7 } = __require("fs");
32710
33101
  const marker = "# todos-auto-link";
32711
33102
  if (!existsSync11(hookPath)) {
32712
- console.log(chalk3.dim("No post-commit hook found."));
33103
+ console.log(chalk4.dim("No post-commit hook found."));
32713
33104
  return;
32714
33105
  }
32715
33106
  const content = readFileSync8(hookPath, "utf-8");
32716
33107
  if (!content.includes(marker)) {
32717
- console.log(chalk3.dim("Hook not managed by todos."));
33108
+ console.log(chalk4.dim("Hook not managed by todos."));
32718
33109
  return;
32719
33110
  }
32720
33111
  const cleaned = content.split(`
@@ -32726,9 +33117,9 @@ hookCmd.command("uninstall").description("Remove the todos post-commit hook").ac
32726
33117
  writeFileSync7(hookPath, cleaned + `
32727
33118
  `);
32728
33119
  }
32729
- console.log(chalk3.green("Post-commit hook removed."));
33120
+ console.log(chalk4.green("Post-commit hook removed."));
32730
33121
  } catch (e) {
32731
- console.error(chalk3.red("Not in a git repository or hook removal failed."));
33122
+ console.error(chalk4.red("Not in a git repository or hook removal failed."));
32732
33123
  process.exit(1);
32733
33124
  }
32734
33125
  });
@@ -32737,17 +33128,17 @@ program2.command("init <name>").description("Register an agent and get a short U
32737
33128
  try {
32738
33129
  const result = registerAgent({ name, description: opts.description });
32739
33130
  if (isAgentConflict(result)) {
32740
- console.error(chalk3.red("CONFLICT:"), result.message);
33131
+ console.error(chalk4.red("CONFLICT:"), result.message);
32741
33132
  process.exit(1);
32742
33133
  }
32743
33134
  if (globalOpts.json) {
32744
33135
  output(result, true);
32745
33136
  } else {
32746
- console.log(chalk3.green("Agent registered:"));
32747
- console.log(` ${chalk3.dim("ID:")} ${result.id}`);
32748
- console.log(` ${chalk3.dim("Name:")} ${result.name}`);
33137
+ console.log(chalk4.green("Agent registered:"));
33138
+ console.log(` ${chalk4.dim("ID:")} ${result.id}`);
33139
+ console.log(` ${chalk4.dim("Name:")} ${result.name}`);
32749
33140
  console.log(`
32750
- Use ${chalk3.cyan(`--agent ${result.id}`)} on future commands.`);
33141
+ Use ${chalk4.cyan(`--agent ${result.id}`)} on future commands.`);
32751
33142
  }
32752
33143
  } catch (e) {
32753
33144
  handleError(e);
@@ -32757,51 +33148,51 @@ program2.command("heartbeat [agent]").description("Update last_seen_at to signal
32757
33148
  const globalOpts = program2.opts();
32758
33149
  const agentId = agent || globalOpts.agent;
32759
33150
  if (!agentId) {
32760
- console.error(chalk3.red("Agent ID required. Use --agent or pass as argument."));
33151
+ console.error(chalk4.red("Agent ID required. Use --agent or pass as argument."));
32761
33152
  process.exit(1);
32762
33153
  }
32763
33154
  const { updateAgentActivity: updateAgentActivity2, getAgent: getAgent2 } = (init_agents(), __toCommonJS(exports_agents));
32764
33155
  const a = getAgent2(agentId) || (init_agents(), __toCommonJS(exports_agents)).getAgentByName(agentId);
32765
33156
  if (!a) {
32766
- console.error(chalk3.red(`Agent not found: ${agentId}`));
33157
+ console.error(chalk4.red(`Agent not found: ${agentId}`));
32767
33158
  process.exit(1);
32768
33159
  }
32769
33160
  updateAgentActivity2(a.id);
32770
33161
  if (globalOpts.json) {
32771
33162
  console.log(JSON.stringify({ agent_id: a.id, name: a.name, last_seen_at: new Date().toISOString() }));
32772
33163
  } else {
32773
- console.log(chalk3.green(`\u2665 ${a.name} (${a.id.slice(0, 8)}) \u2014 heartbeat sent`));
33164
+ console.log(chalk4.green(`\u2665 ${a.name} (${a.id.slice(0, 8)}) \u2014 heartbeat sent`));
32774
33165
  }
32775
33166
  });
32776
33167
  program2.command("release [agent]").description("Release/logout an agent \u2014 clears session binding so the name is immediately available").option("--session-id <id>", "Only release if session ID matches").action((agent, opts) => {
32777
33168
  const globalOpts = program2.opts();
32778
33169
  const agentId = agent || globalOpts.agent;
32779
33170
  if (!agentId) {
32780
- console.error(chalk3.red("Agent ID or name required. Use --agent or pass as argument."));
33171
+ console.error(chalk4.red("Agent ID or name required. Use --agent or pass as argument."));
32781
33172
  process.exit(1);
32782
33173
  }
32783
33174
  const { getAgent: getAgent2, getAgentByName: getAgentByName2 } = (init_agents(), __toCommonJS(exports_agents));
32784
33175
  const a = getAgent2(agentId) || getAgentByName2(agentId);
32785
33176
  if (!a) {
32786
- console.error(chalk3.red(`Agent not found: ${agentId}`));
33177
+ console.error(chalk4.red(`Agent not found: ${agentId}`));
32787
33178
  process.exit(1);
32788
33179
  }
32789
33180
  const released = releaseAgent(a.id, opts?.sessionId);
32790
33181
  if (!released) {
32791
- console.error(chalk3.red("Release denied: session_id does not match agent's current session."));
33182
+ console.error(chalk4.red("Release denied: session_id does not match agent's current session."));
32792
33183
  process.exit(1);
32793
33184
  }
32794
33185
  if (globalOpts.json) {
32795
33186
  console.log(JSON.stringify({ agent_id: a.id, name: a.name, released: true }));
32796
33187
  } else {
32797
- console.log(chalk3.green(`\u2713 ${a.name} (${a.id}) released \u2014 name is now available.`));
33188
+ console.log(chalk4.green(`\u2713 ${a.name} (${a.id}) released \u2014 name is now available.`));
32798
33189
  }
32799
33190
  });
32800
33191
  program2.command("focus [project]").description("Focus on a project (or clear focus if no project given)").action((project) => {
32801
33192
  const globalOpts = program2.opts();
32802
33193
  const agentId = globalOpts.agent;
32803
33194
  if (!agentId) {
32804
- console.error(chalk3.red("Agent ID required. Use --agent."));
33195
+ console.error(chalk4.red("Agent ID required. Use --agent."));
32805
33196
  process.exit(1);
32806
33197
  }
32807
33198
  const db = getDatabase();
@@ -32813,10 +33204,10 @@ program2.command("focus [project]").description("Focus on a project (or clear fo
32813
33204
  })() || db.query("SELECT * FROM projects WHERE name = ? OR task_list_id = ?").get(project, project);
32814
33205
  const projectId = p?.id || project;
32815
33206
  db.run("UPDATE agents SET active_project_id = ? WHERE id = ? OR name = ?", [projectId, agentId, agentId]);
32816
- console.log(chalk3.green(`Focused on: ${p?.name || projectId}`));
33207
+ console.log(chalk4.green(`Focused on: ${p?.name || projectId}`));
32817
33208
  } else {
32818
33209
  db.run("UPDATE agents SET active_project_id = NULL WHERE id = ? OR name = ?", [agentId, agentId]);
32819
- console.log(chalk3.dim("Focus cleared."));
33210
+ console.log(chalk4.dim("Focus cleared."));
32820
33211
  }
32821
33212
  });
32822
33213
  program2.command("agents").description("List registered agents").action(() => {
@@ -32828,11 +33219,11 @@ program2.command("agents").description("List registered agents").action(() => {
32828
33219
  return;
32829
33220
  }
32830
33221
  if (agents.length === 0) {
32831
- console.log(chalk3.dim("No agents registered. Use 'todos init <name>' to register."));
33222
+ console.log(chalk4.dim("No agents registered. Use 'todos init <name>' to register."));
32832
33223
  return;
32833
33224
  }
32834
33225
  for (const a of agents) {
32835
- console.log(` ${chalk3.cyan(a.id)} ${chalk3.bold(a.name)} ${chalk3.dim(a.last_seen_at)}`);
33226
+ console.log(` ${chalk4.cyan(a.id)} ${chalk4.bold(a.name)} ${chalk4.dim(a.last_seen_at)}`);
32836
33227
  }
32837
33228
  } catch (e) {
32838
33229
  handleError(e);
@@ -32844,7 +33235,7 @@ program2.command("agent-update <name>").alias("agents-update").description("Upda
32844
33235
  const { getAgentByName: findByName, updateAgent: doUpdate } = (init_agents(), __toCommonJS(exports_agents));
32845
33236
  const agent = findByName(name);
32846
33237
  if (!agent) {
32847
- console.error(chalk3.red(`Agent not found: ${name}`));
33238
+ console.error(chalk4.red(`Agent not found: ${name}`));
32848
33239
  process.exit(1);
32849
33240
  }
32850
33241
  const updates = {};
@@ -32858,11 +33249,11 @@ program2.command("agent-update <name>").alias("agents-update").description("Upda
32858
33249
  if (globalOpts.json) {
32859
33250
  output(updated, true);
32860
33251
  } else {
32861
- console.log(chalk3.green(`Updated agent: ${updated.name} (${updated.id.slice(0, 8)})`));
33252
+ console.log(chalk4.green(`Updated agent: ${updated.name} (${updated.id.slice(0, 8)})`));
32862
33253
  if (updated.description)
32863
- console.log(chalk3.dim(` Description: ${updated.description}`));
33254
+ console.log(chalk4.dim(` Description: ${updated.description}`));
32864
33255
  if (updated.role)
32865
- console.log(chalk3.dim(` Role: ${updated.role}`));
33256
+ console.log(chalk4.dim(` Role: ${updated.role}`));
32866
33257
  }
32867
33258
  } catch (e) {
32868
33259
  handleError(e);
@@ -32873,7 +33264,7 @@ program2.command("agent <name>").description("Show all info about an agent: task
32873
33264
  const { getAgentByName: findByName } = (init_agents(), __toCommonJS(exports_agents));
32874
33265
  const agent = findByName(name);
32875
33266
  if (!agent) {
32876
- console.error(chalk3.red(`Agent not found: ${name}`));
33267
+ console.error(chalk4.red(`Agent not found: ${name}`));
32877
33268
  process.exit(1);
32878
33269
  }
32879
33270
  const byAssigned = listTasks({ assigned_to: agent.name });
@@ -32892,53 +33283,53 @@ program2.command("agent <name>").description("Show all info about an agent: task
32892
33283
  const rate = allTasks.length > 0 ? Math.round(completed.length / allTasks.length * 100) : 0;
32893
33284
  const lastSeenMs = Date.now() - new Date(agent.last_seen_at).getTime();
32894
33285
  const lastSeenMins = Math.floor(lastSeenMs / 60000);
32895
- const lastSeenStr = lastSeenMins < 2 ? chalk3.green("just now") : lastSeenMins < 60 ? chalk3.yellow(`${lastSeenMins}m ago`) : lastSeenMins < 1440 ? chalk3.yellow(`${Math.floor(lastSeenMins / 60)}h ago`) : chalk3.dim(`${Math.floor(lastSeenMins / 1440)}d ago`);
33286
+ const lastSeenStr = lastSeenMins < 2 ? chalk4.green("just now") : lastSeenMins < 60 ? chalk4.yellow(`${lastSeenMins}m ago`) : lastSeenMins < 1440 ? chalk4.yellow(`${Math.floor(lastSeenMins / 60)}h ago`) : chalk4.dim(`${Math.floor(lastSeenMins / 1440)}d ago`);
32896
33287
  const isOnline = lastSeenMins < 5;
32897
33288
  if (opts.json || globalOpts.json) {
32898
33289
  console.log(JSON.stringify({ agent, tasks: { pending: pending.length, in_progress: inProgress.length, completed: completed.length, failed: failed.length, total: allTasks.length, completion_rate: rate }, all_tasks: allTasks }, null, 2));
32899
33290
  return;
32900
33291
  }
32901
33292
  console.log(`
32902
- ${isOnline ? chalk3.green("\u25CF") : chalk3.dim("\u25CB")} ${chalk3.bold(agent.name)} ${chalk3.dim(`(${agent.id})`)} ${lastSeenStr}`);
33293
+ ${isOnline ? chalk4.green("\u25CF") : chalk4.dim("\u25CB")} ${chalk4.bold(agent.name)} ${chalk4.dim(`(${agent.id})`)} ${lastSeenStr}`);
32903
33294
  if (agent.description)
32904
- console.log(chalk3.dim(` ${agent.description}`));
33295
+ console.log(chalk4.dim(` ${agent.description}`));
32905
33296
  if (agent.role)
32906
- console.log(chalk3.dim(` Role: ${agent.role}`));
33297
+ console.log(chalk4.dim(` Role: ${agent.role}`));
32907
33298
  console.log();
32908
- console.log(` ${chalk3.yellow(String(pending.length))} pending ${chalk3.blue(String(inProgress.length))} active ${chalk3.green(String(completed.length))} done ${chalk3.dim(`${rate}% rate`)}`);
33299
+ console.log(` ${chalk4.yellow(String(pending.length))} pending ${chalk4.blue(String(inProgress.length))} active ${chalk4.green(String(completed.length))} done ${chalk4.dim(`${rate}% rate`)}`);
32909
33300
  console.log();
32910
33301
  if (inProgress.length > 0) {
32911
- console.log(chalk3.bold(" In progress:"));
33302
+ console.log(chalk4.bold(" In progress:"));
32912
33303
  for (const t of inProgress) {
32913
33304
  const id = t.short_id || t.id.slice(0, 8);
32914
- const staleFlag = new Date(t.updated_at).getTime() < Date.now() - 30 * 60 * 1000 ? chalk3.red(" [stale]") : "";
32915
- console.log(` ${chalk3.cyan(id)} ${chalk3.yellow(t.priority)} ${t.title}${staleFlag}`);
33305
+ const staleFlag = new Date(t.updated_at).getTime() < Date.now() - 30 * 60 * 1000 ? chalk4.red(" [stale]") : "";
33306
+ console.log(` ${chalk4.cyan(id)} ${chalk4.yellow(t.priority)} ${t.title}${staleFlag}`);
32916
33307
  }
32917
33308
  console.log();
32918
33309
  }
32919
33310
  if (pending.length > 0) {
32920
- console.log(chalk3.bold(` Pending (${pending.length}):`));
33311
+ console.log(chalk4.bold(` Pending (${pending.length}):`));
32921
33312
  for (const t of pending.slice(0, 5)) {
32922
33313
  const id = t.short_id || t.id.slice(0, 8);
32923
- const due = t.due_at ? chalk3.dim(` due:${t.due_at.slice(0, 10)}`) : "";
32924
- console.log(` ${chalk3.dim(id)} ${t.priority.padEnd(8)} ${t.title}${due}`);
33314
+ const due = t.due_at ? chalk4.dim(` due:${t.due_at.slice(0, 10)}`) : "";
33315
+ console.log(` ${chalk4.dim(id)} ${t.priority.padEnd(8)} ${t.title}${due}`);
32925
33316
  }
32926
33317
  if (pending.length > 5)
32927
- console.log(chalk3.dim(` ... and ${pending.length - 5} more`));
33318
+ console.log(chalk4.dim(` ... and ${pending.length - 5} more`));
32928
33319
  console.log();
32929
33320
  }
32930
33321
  const recentDone = completed.filter((t) => t.completed_at).sort((a, b) => new Date(b.completed_at).getTime() - new Date(a.completed_at).getTime()).slice(0, 3);
32931
33322
  if (recentDone.length > 0) {
32932
- console.log(chalk3.bold(" Recently completed:"));
33323
+ console.log(chalk4.bold(" Recently completed:"));
32933
33324
  for (const t of recentDone) {
32934
33325
  const id = t.short_id || t.id.slice(0, 8);
32935
- const when = t.completed_at ? chalk3.dim(new Date(t.completed_at).toLocaleDateString()) : "";
32936
- console.log(` ${chalk3.green("\u2713")} ${chalk3.dim(id)} ${t.title} ${when}`);
33326
+ const when = t.completed_at ? chalk4.dim(new Date(t.completed_at).toLocaleDateString()) : "";
33327
+ console.log(` ${chalk4.green("\u2713")} ${chalk4.dim(id)} ${t.title} ${when}`);
32937
33328
  }
32938
33329
  console.log();
32939
33330
  }
32940
33331
  if (allTasks.length === 0) {
32941
- console.log(chalk3.dim(" No tasks assigned to this agent."));
33332
+ console.log(chalk4.dim(" No tasks assigned to this agent."));
32942
33333
  }
32943
33334
  });
32944
33335
  program2.command("org").description("Show agent org chart \u2014 who reports to who").option("--set <agent=manager>", "Set reporting: 'seneca=julius' or 'seneca=' to clear").action((opts) => {
@@ -32948,14 +33339,14 @@ program2.command("org").description("Show agent org chart \u2014 who reports to
32948
33339
  const [agentName, managerName] = opts.set.split("=");
32949
33340
  const agent = getByName(agentName);
32950
33341
  if (!agent) {
32951
- console.error(chalk3.red(`Agent not found: ${agentName}`));
33342
+ console.error(chalk4.red(`Agent not found: ${agentName}`));
32952
33343
  process.exit(1);
32953
33344
  }
32954
33345
  let managerId = null;
32955
33346
  if (managerName) {
32956
33347
  const manager = getByName(managerName);
32957
33348
  if (!manager) {
32958
- console.error(chalk3.red(`Manager not found: ${managerName}`));
33349
+ console.error(chalk4.red(`Manager not found: ${managerName}`));
32959
33350
  process.exit(1);
32960
33351
  }
32961
33352
  managerId = manager.id;
@@ -32964,7 +33355,7 @@ program2.command("org").description("Show agent org chart \u2014 who reports to
32964
33355
  if (globalOpts.json) {
32965
33356
  output({ agent: agentName, reports_to: managerName || null }, true);
32966
33357
  } else {
32967
- console.log(chalk3.green(managerId ? `${agentName} \u2192 ${managerName}` : `${agentName} \u2192 (top-level)`));
33358
+ console.log(chalk4.green(managerId ? `${agentName} \u2192 ${managerName}` : `${agentName} \u2192 (top-level)`));
32968
33359
  }
32969
33360
  return;
32970
33361
  }
@@ -32974,15 +33365,15 @@ program2.command("org").description("Show agent org chart \u2014 who reports to
32974
33365
  return;
32975
33366
  }
32976
33367
  if (tree.length === 0) {
32977
- console.log(chalk3.dim("No agents registered."));
33368
+ console.log(chalk4.dim("No agents registered."));
32978
33369
  return;
32979
33370
  }
32980
33371
  function render2(nodes, indent = 0) {
32981
33372
  for (const n of nodes) {
32982
33373
  const prefix = " ".repeat(indent);
32983
- const title = n.agent.title ? chalk3.cyan(` \u2014 ${n.agent.title}`) : "";
32984
- const level = n.agent.level ? chalk3.dim(` (${n.agent.level})`) : "";
32985
- console.log(`${prefix}${indent > 0 ? "\u251C\u2500\u2500 " : ""}${chalk3.bold(n.agent.name)}${title}${level}`);
33374
+ const title = n.agent.title ? chalk4.cyan(` \u2014 ${n.agent.title}`) : "";
33375
+ const level = n.agent.level ? chalk4.dim(` (${n.agent.level})`) : "";
33376
+ console.log(`${prefix}${indent > 0 ? "\u251C\u2500\u2500 " : ""}${chalk4.bold(n.agent.name)}${title}${level}`);
32986
33377
  render2(n.reports, indent + 1);
32987
33378
  }
32988
33379
  }
@@ -32998,21 +33389,21 @@ program2.command("lists").aliases(["task-lists", "tl"]).description("List and ma
32998
33389
  output(list, true);
32999
33390
  return;
33000
33391
  }
33001
- console.log(chalk3.green("Task list created:"));
33002
- console.log(` ${chalk3.dim("ID:")} ${list.id.slice(0, 8)}`);
33003
- console.log(` ${chalk3.dim("Slug:")} ${list.slug}`);
33004
- console.log(` ${chalk3.dim("Name:")} ${list.name}`);
33392
+ console.log(chalk4.green("Task list created:"));
33393
+ console.log(` ${chalk4.dim("ID:")} ${list.id.slice(0, 8)}`);
33394
+ console.log(` ${chalk4.dim("Slug:")} ${list.slug}`);
33395
+ console.log(` ${chalk4.dim("Name:")} ${list.name}`);
33005
33396
  return;
33006
33397
  }
33007
33398
  if (opts.delete) {
33008
33399
  const db = getDatabase();
33009
33400
  const resolved = resolvePartialId(db, "task_lists", opts.delete);
33010
33401
  if (!resolved) {
33011
- console.error(chalk3.red("Task list not found"));
33402
+ console.error(chalk4.red("Task list not found"));
33012
33403
  process.exit(1);
33013
33404
  }
33014
33405
  deleteTaskList(resolved);
33015
- console.log(chalk3.green("Task list deleted."));
33406
+ console.log(chalk4.green("Task list deleted."));
33016
33407
  return;
33017
33408
  }
33018
33409
  const lists = listTaskLists(projectId);
@@ -33021,11 +33412,11 @@ program2.command("lists").aliases(["task-lists", "tl"]).description("List and ma
33021
33412
  return;
33022
33413
  }
33023
33414
  if (lists.length === 0) {
33024
- console.log(chalk3.dim("No task lists. Use 'todos lists --add <name>' to create one."));
33415
+ console.log(chalk4.dim("No task lists. Use 'todos lists --add <name>' to create one."));
33025
33416
  return;
33026
33417
  }
33027
33418
  for (const l of lists) {
33028
- console.log(` ${chalk3.dim(l.id.slice(0, 8))} ${chalk3.bold(l.name)} ${chalk3.dim(`(${l.slug})`)}`);
33419
+ console.log(` ${chalk4.dim(l.id.slice(0, 8))} ${chalk4.bold(l.name)} ${chalk4.dim(`(${l.slug})`)}`);
33029
33420
  }
33030
33421
  } catch (e) {
33031
33422
  handleError(e);
@@ -33036,20 +33427,20 @@ program2.command("upgrade").alias("self-update").description("Update todos to th
33036
33427
  const currentVersion = getPackageVersion();
33037
33428
  const res = await fetch("https://registry.npmjs.org/@hasna/todos/latest");
33038
33429
  if (!res.ok) {
33039
- console.error(chalk3.red("Failed to check for updates."));
33430
+ console.error(chalk4.red("Failed to check for updates."));
33040
33431
  process.exit(1);
33041
33432
  }
33042
33433
  const data = await res.json();
33043
33434
  const latestVersion = data.version;
33044
- console.log(` Current: ${chalk3.dim(currentVersion)}`);
33045
- console.log(` Latest: ${chalk3.green(latestVersion)}`);
33435
+ console.log(` Current: ${chalk4.dim(currentVersion)}`);
33436
+ console.log(` Latest: ${chalk4.green(latestVersion)}`);
33046
33437
  if (currentVersion === latestVersion) {
33047
- console.log(chalk3.green(`
33438
+ console.log(chalk4.green(`
33048
33439
  Already up to date!`));
33049
33440
  return;
33050
33441
  }
33051
33442
  if (opts.check) {
33052
- console.log(chalk3.yellow(`
33443
+ console.log(chalk4.yellow(`
33053
33444
  Update available: ${currentVersion} \u2192 ${latestVersion}`));
33054
33445
  return;
33055
33446
  }
@@ -33059,10 +33450,10 @@ Update available: ${currentVersion} \u2192 ${latestVersion}`));
33059
33450
  useBun = true;
33060
33451
  } catch {}
33061
33452
  const cmd = useBun ? "bun add -g @hasna/todos@latest" : "npm install -g @hasna/todos@latest";
33062
- console.log(chalk3.dim(`
33453
+ console.log(chalk4.dim(`
33063
33454
  Running: ${cmd}`));
33064
33455
  execSync(cmd, { stdio: "inherit" });
33065
- console.log(chalk3.green(`
33456
+ console.log(chalk4.green(`
33066
33457
  Updated to ${latestVersion}!`));
33067
33458
  } catch (e) {
33068
33459
  handleError(e);
@@ -33084,7 +33475,7 @@ program2.command("config").description("View or update configuration").option("-
33084
33475
  if (globalOpts.json) {
33085
33476
  output({ key: opts.get, value }, true);
33086
33477
  } else {
33087
- console.log(value !== undefined ? JSON.stringify(value, null, 2) : chalk3.dim("(not set)"));
33478
+ console.log(value !== undefined ? JSON.stringify(value, null, 2) : chalk4.dim("(not set)"));
33088
33479
  }
33089
33480
  return;
33090
33481
  }
@@ -33116,7 +33507,7 @@ program2.command("config").description("View or update configuration").option("-
33116
33507
  if (globalOpts.json) {
33117
33508
  output({ key, value: parsedValue }, true);
33118
33509
  } else {
33119
- console.log(chalk3.green(`Set ${key} = ${JSON.stringify(parsedValue)}`));
33510
+ console.log(chalk4.green(`Set ${key} = ${JSON.stringify(parsedValue)}`));
33120
33511
  }
33121
33512
  return;
33122
33513
  }
@@ -33157,25 +33548,25 @@ program2.command("watch").description("Live-updating task list (refreshes every
33157
33548
  counts[t.status] = (counts[t.status] || 0) + 1;
33158
33549
  process.stdout.write("\x1B[2J\x1B[0f");
33159
33550
  const now2 = new Date().toLocaleTimeString();
33160
- console.log(chalk3.bold(`todos watch`) + chalk3.dim(` \u2014 ${now2} \u2014 refreshing every ${opts.interval}s \u2014 Ctrl+C to stop
33551
+ console.log(chalk4.bold(`todos watch`) + chalk4.dim(` \u2014 ${now2} \u2014 refreshing every ${opts.interval}s \u2014 Ctrl+C to stop
33161
33552
  `));
33162
33553
  const parts = [
33163
- `total: ${chalk3.bold(String(all.length))}`,
33164
- `pending: ${chalk3.yellow(String(counts["pending"] || 0))}`,
33165
- `in_progress: ${chalk3.blue(String(counts["in_progress"] || 0))}`,
33166
- `completed: ${chalk3.green(String(counts["completed"] || 0))}`,
33167
- `failed: ${chalk3.red(String(counts["failed"] || 0))}`
33554
+ `total: ${chalk4.bold(String(all.length))}`,
33555
+ `pending: ${chalk4.yellow(String(counts["pending"] || 0))}`,
33556
+ `in_progress: ${chalk4.blue(String(counts["in_progress"] || 0))}`,
33557
+ `completed: ${chalk4.green(String(counts["completed"] || 0))}`,
33558
+ `failed: ${chalk4.red(String(counts["failed"] || 0))}`
33168
33559
  ];
33169
33560
  console.log(parts.join(" ") + `
33170
33561
  `);
33171
33562
  if (tasks.length === 0) {
33172
- console.log(chalk3.dim("No matching tasks."));
33563
+ console.log(chalk4.dim("No matching tasks."));
33173
33564
  return;
33174
33565
  }
33175
33566
  for (const t of tasks) {
33176
33567
  console.log(formatTaskLine(t));
33177
33568
  }
33178
- console.log(chalk3.dim(`
33569
+ console.log(chalk4.dim(`
33179
33570
  ${tasks.length} task(s) shown`));
33180
33571
  }
33181
33572
  render2();
@@ -33195,19 +33586,19 @@ program2.command("stream").description("Subscribe to real-time task events via S
33195
33586
  params.set("events", opts.events);
33196
33587
  const url = `${baseUrl}/api/tasks/stream?${params}`;
33197
33588
  const eventColors = {
33198
- "task.created": chalk3.blue,
33199
- "task.started": chalk3.cyan,
33200
- "task.completed": chalk3.green,
33201
- "task.failed": chalk3.red,
33202
- "task.assigned": chalk3.yellow,
33203
- "task.status_changed": chalk3.magenta
33589
+ "task.created": chalk4.blue,
33590
+ "task.started": chalk4.cyan,
33591
+ "task.completed": chalk4.green,
33592
+ "task.failed": chalk4.red,
33593
+ "task.assigned": chalk4.yellow,
33594
+ "task.status_changed": chalk4.magenta
33204
33595
  };
33205
- console.log(chalk3.dim(`Connecting to ${url} \u2014 Ctrl+C to stop
33596
+ console.log(chalk4.dim(`Connecting to ${url} \u2014 Ctrl+C to stop
33206
33597
  `));
33207
33598
  try {
33208
33599
  const resp = await fetch(url);
33209
33600
  if (!resp.ok || !resp.body) {
33210
- console.error(chalk3.red(`Failed to connect: ${resp.status}`));
33601
+ console.error(chalk4.red(`Failed to connect: ${resp.status}`));
33211
33602
  process.exit(1);
33212
33603
  }
33213
33604
  const reader = resp.body.getReader();
@@ -33233,11 +33624,11 @@ program2.command("stream").description("Subscribe to real-time task events via S
33233
33624
  if (opts.json) {
33234
33625
  console.log(JSON.stringify({ event: eventName, ...data }));
33235
33626
  } else {
33236
- const colorFn = eventColors[eventName] || chalk3.white;
33627
+ const colorFn = eventColors[eventName] || chalk4.white;
33237
33628
  const ts = new Date(data.timestamp || Date.now()).toLocaleTimeString();
33238
33629
  const taskId = data.task_id ? data.task_id.slice(0, 8) : "";
33239
33630
  const agentInfo = data.agent_id ? ` [${data.agent_id}]` : "";
33240
- console.log(`${chalk3.dim(ts)} ${colorFn(eventName.padEnd(25))} ${taskId}${agentInfo}`);
33631
+ console.log(`${chalk4.dim(ts)} ${colorFn(eventName.padEnd(25))} ${taskId}${agentInfo}`);
33241
33632
  }
33242
33633
  } catch {}
33243
33634
  eventName = "";
@@ -33245,8 +33636,8 @@ program2.command("stream").description("Subscribe to real-time task events via S
33245
33636
  }
33246
33637
  }
33247
33638
  } catch (e) {
33248
- console.error(chalk3.red(`Connection error: ${e instanceof Error ? e.message : e}`));
33249
- console.error(chalk3.dim("Is `todos serve` running?"));
33639
+ console.error(chalk4.red(`Connection error: ${e instanceof Error ? e.message : e}`));
33640
+ console.error(chalk4.dim("Is `todos serve` running?"));
33250
33641
  process.exit(1);
33251
33642
  }
33252
33643
  });
@@ -33267,29 +33658,29 @@ program2.command("blame <file>").description("Show which tasks/agents touched a
33267
33658
  output({ file: filePath, task_files: taskFiles, commits: commitRows }, true);
33268
33659
  return;
33269
33660
  }
33270
- console.log(chalk3.bold(`
33661
+ console.log(chalk4.bold(`
33271
33662
  Blame: ${filePath}
33272
33663
  `));
33273
33664
  if (taskFiles.length > 0) {
33274
- console.log(chalk3.bold("Task File Links:"));
33665
+ console.log(chalk4.bold("Task File Links:"));
33275
33666
  for (const tf of taskFiles) {
33276
33667
  const task = getTask5(tf.task_id, db);
33277
33668
  const title = task ? task.title : "unknown";
33278
33669
  const sid = task?.short_id || tf.task_id.slice(0, 8);
33279
- console.log(` ${chalk3.cyan(sid)} ${title} \u2014 ${chalk3.dim(tf.role || "file")} ${chalk3.dim(tf.updated_at)}`);
33670
+ console.log(` ${chalk4.cyan(sid)} ${title} \u2014 ${chalk4.dim(tf.role || "file")} ${chalk4.dim(tf.updated_at)}`);
33280
33671
  }
33281
33672
  }
33282
33673
  if (commitRows.length > 0) {
33283
- console.log(chalk3.bold(`
33674
+ console.log(chalk4.bold(`
33284
33675
  Commit Links (${commitRows.length}):`));
33285
33676
  for (const c of commitRows) {
33286
33677
  const sid = c.short_id || c.task_id.slice(0, 8);
33287
- console.log(` ${chalk3.yellow(c.sha?.slice(0, 7) || "?")} ${chalk3.cyan(sid)} ${c.title || ""} \u2014 ${chalk3.dim(c.author || "")} ${chalk3.dim(c.committed_at || "")}`);
33678
+ console.log(` ${chalk4.yellow(c.sha?.slice(0, 7) || "?")} ${chalk4.cyan(sid)} ${c.title || ""} \u2014 ${chalk4.dim(c.author || "")} ${chalk4.dim(c.committed_at || "")}`);
33288
33679
  }
33289
33680
  }
33290
33681
  if (taskFiles.length === 0 && commitRows.length === 0) {
33291
- console.log(chalk3.dim("No task or commit links found for this file."));
33292
- console.log(chalk3.dim("Use 'todos hook install' to auto-link future commits."));
33682
+ console.log(chalk4.dim("No task or commit links found for this file."));
33683
+ console.log(chalk4.dim("Use 'todos hook install' to auto-link future commits."));
33293
33684
  }
33294
33685
  console.log();
33295
33686
  });
@@ -33313,17 +33704,17 @@ program2.command("next").description("Show the best pending task to work on next
33313
33704
  }
33314
33705
  const task = getNextTask(opts.agent, Object.keys(filters).length ? filters : undefined, db);
33315
33706
  if (!task) {
33316
- console.log(chalk3.dim("No tasks available."));
33707
+ console.log(chalk4.dim("No tasks available."));
33317
33708
  return;
33318
33709
  }
33319
33710
  if (opts.json) {
33320
33711
  console.log(JSON.stringify(task, null, 2));
33321
33712
  return;
33322
33713
  }
33323
- console.log(chalk3.bold("Next task:"));
33324
- console.log(` ${chalk3.cyan(task.short_id || task.id.slice(0, 8))} ${chalk3.yellow(task.priority)} ${task.title}`);
33714
+ console.log(chalk4.bold("Next task:"));
33715
+ console.log(` ${chalk4.cyan(task.short_id || task.id.slice(0, 8))} ${chalk4.yellow(task.priority)} ${task.title}`);
33325
33716
  if (task.description)
33326
- console.log(chalk3.dim(` ${task.description.slice(0, 100)}`));
33717
+ console.log(chalk4.dim(` ${task.description.slice(0, 100)}`));
33327
33718
  });
33328
33719
  program2.command("claim <agent>").description("Atomically claim the best pending task for an agent").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (agent, opts) => {
33329
33720
  const db = getDatabase();
@@ -33332,28 +33723,28 @@ program2.command("claim <agent>").description("Atomically claim the best pending
33332
33723
  filters.project_id = opts.project;
33333
33724
  const task = claimNextTask(agent, Object.keys(filters).length ? filters : undefined, db);
33334
33725
  if (!task) {
33335
- console.log(chalk3.dim("No tasks available to claim."));
33726
+ console.log(chalk4.dim("No tasks available to claim."));
33336
33727
  return;
33337
33728
  }
33338
33729
  if (opts.json) {
33339
33730
  console.log(JSON.stringify(task, null, 2));
33340
33731
  return;
33341
33732
  }
33342
- console.log(chalk3.green(`Claimed: ${task.short_id || task.id.slice(0, 8)} | ${task.priority} | ${task.title}`));
33733
+ console.log(chalk4.green(`Claimed: ${task.short_id || task.id.slice(0, 8)} | ${task.priority} | ${task.title}`));
33343
33734
  });
33344
33735
  program2.command("steal <agent>").description("Work-stealing: take the highest-priority stale task from another agent").option("--stale-minutes <n>", "How long a task must be stale (default: 30)", "30").option("--project <id>", "Filter to project").action((agent, opts) => {
33345
33736
  const globalOpts = program2.opts();
33346
33737
  const { stealTask: stealTask2 } = (init_tasks(), __toCommonJS(exports_tasks));
33347
33738
  const task = stealTask2(agent, { stale_minutes: parseInt(opts.staleMinutes, 10), project_id: opts.project });
33348
33739
  if (!task) {
33349
- console.log(chalk3.dim("No stale tasks available to steal."));
33740
+ console.log(chalk4.dim("No stale tasks available to steal."));
33350
33741
  return;
33351
33742
  }
33352
33743
  if (globalOpts.json) {
33353
33744
  output(task, true);
33354
33745
  return;
33355
33746
  }
33356
- console.log(chalk3.green(`Stolen: ${task.short_id || task.id.slice(0, 8)} | ${task.priority} | ${task.title}`));
33747
+ console.log(chalk4.green(`Stolen: ${task.short_id || task.id.slice(0, 8)} | ${task.priority} | ${task.title}`));
33357
33748
  });
33358
33749
  program2.command("status").description("Show full project health snapshot").option("--agent <id>", "Include next task for this agent").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
33359
33750
  const db = getDatabase();
@@ -33365,24 +33756,24 @@ program2.command("status").description("Show full project health snapshot").opti
33365
33756
  console.log(JSON.stringify(s, null, 2));
33366
33757
  return;
33367
33758
  }
33368
- console.log(`Tasks: ${chalk3.yellow(s.pending)} pending | ${chalk3.blue(s.in_progress)} active | ${chalk3.green(s.completed)} done | ${s.total} total`);
33759
+ console.log(`Tasks: ${chalk4.yellow(s.pending)} pending | ${chalk4.blue(s.in_progress)} active | ${chalk4.green(s.completed)} done | ${s.total} total`);
33369
33760
  if (s.stale_count > 0)
33370
- console.log(chalk3.red(`\u26A0\uFE0F ${s.stale_count} stale tasks (stuck in_progress)`));
33761
+ console.log(chalk4.red(`\u26A0\uFE0F ${s.stale_count} stale tasks (stuck in_progress)`));
33371
33762
  if (s.overdue_recurring > 0)
33372
- console.log(chalk3.yellow(`\uD83D\uDD01 ${s.overdue_recurring} overdue recurring`));
33763
+ console.log(chalk4.yellow(`\uD83D\uDD01 ${s.overdue_recurring} overdue recurring`));
33373
33764
  if (s.active_work.length > 0) {
33374
- console.log(chalk3.bold(`
33765
+ console.log(chalk4.bold(`
33375
33766
  Active:`));
33376
33767
  for (const w of s.active_work.slice(0, 5)) {
33377
33768
  const id = w.short_id || w.id.slice(0, 8);
33378
- console.log(` ${chalk3.cyan(id)} | ${w.assigned_to || w.locked_by || "?"} | ${w.title}`);
33769
+ console.log(` ${chalk4.cyan(id)} | ${w.assigned_to || w.locked_by || "?"} | ${w.title}`);
33379
33770
  }
33380
33771
  }
33381
33772
  if (s.next_task) {
33382
- console.log(chalk3.bold(`
33773
+ console.log(chalk4.bold(`
33383
33774
  Next up:`));
33384
33775
  const t = s.next_task;
33385
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${chalk3.yellow(t.priority)} ${t.title}`);
33776
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${chalk4.yellow(t.priority)} ${t.title}`);
33386
33777
  }
33387
33778
  });
33388
33779
  program2.command("recap").description("Show what happened in the last N hours \u2014 completed tasks, new tasks, agent activity, blockers").option("--hours <n>", "Look back N hours (default: 8)", "8").option("--project <id>", "Filter to project").action((opts) => {
@@ -33393,60 +33784,60 @@ program2.command("recap").description("Show what happened in the last N hours \u
33393
33784
  output(recap, true);
33394
33785
  return;
33395
33786
  }
33396
- console.log(chalk3.bold(`
33787
+ console.log(chalk4.bold(`
33397
33788
  Recap \u2014 last ${recap.hours} hours (since ${new Date(recap.since).toLocaleString()})
33398
33789
  `));
33399
33790
  if (recap.completed.length > 0) {
33400
- console.log(chalk3.green.bold(`Completed (${recap.completed.length}):`));
33791
+ console.log(chalk4.green.bold(`Completed (${recap.completed.length}):`));
33401
33792
  for (const t of recap.completed) {
33402
33793
  const id = t.short_id || t.id.slice(0, 8);
33403
33794
  const dur = t.duration_minutes != null ? ` (${t.duration_minutes}m)` : "";
33404
- console.log(` ${chalk3.green("\u2713")} ${chalk3.cyan(id)} ${t.title}${dur}${t.assigned_to ? ` \u2014 ${chalk3.dim(t.assigned_to)}` : ""}`);
33795
+ console.log(` ${chalk4.green("\u2713")} ${chalk4.cyan(id)} ${t.title}${dur}${t.assigned_to ? ` \u2014 ${chalk4.dim(t.assigned_to)}` : ""}`);
33405
33796
  }
33406
33797
  } else {
33407
- console.log(chalk3.dim("No tasks completed in this period."));
33798
+ console.log(chalk4.dim("No tasks completed in this period."));
33408
33799
  }
33409
33800
  if (recap.in_progress.length > 0) {
33410
- console.log(chalk3.blue.bold(`
33801
+ console.log(chalk4.blue.bold(`
33411
33802
  In Progress (${recap.in_progress.length}):`));
33412
33803
  for (const t of recap.in_progress) {
33413
33804
  const id = t.short_id || t.id.slice(0, 8);
33414
- console.log(` ${chalk3.blue("\u2192")} ${chalk3.cyan(id)} ${t.title}${t.assigned_to ? ` \u2014 ${chalk3.dim(t.assigned_to)}` : ""}`);
33805
+ console.log(` ${chalk4.blue("\u2192")} ${chalk4.cyan(id)} ${t.title}${t.assigned_to ? ` \u2014 ${chalk4.dim(t.assigned_to)}` : ""}`);
33415
33806
  }
33416
33807
  }
33417
33808
  if (recap.blocked.length > 0) {
33418
- console.log(chalk3.red.bold(`
33809
+ console.log(chalk4.red.bold(`
33419
33810
  Blocked (${recap.blocked.length}):`));
33420
33811
  for (const t of recap.blocked) {
33421
33812
  const id = t.short_id || t.id.slice(0, 8);
33422
- console.log(` ${chalk3.red("\u2717")} ${chalk3.cyan(id)} ${t.title}`);
33813
+ console.log(` ${chalk4.red("\u2717")} ${chalk4.cyan(id)} ${t.title}`);
33423
33814
  }
33424
33815
  }
33425
33816
  if (recap.stale.length > 0) {
33426
- console.log(chalk3.yellow.bold(`
33817
+ console.log(chalk4.yellow.bold(`
33427
33818
  Stale (${recap.stale.length}):`));
33428
33819
  for (const t of recap.stale) {
33429
33820
  const id = t.short_id || t.id.slice(0, 8);
33430
33821
  const ago = Math.round((Date.now() - new Date(t.updated_at).getTime()) / 60000);
33431
- console.log(` ${chalk3.yellow("!")} ${chalk3.cyan(id)} ${t.title} \u2014 last update ${ago}m ago`);
33822
+ console.log(` ${chalk4.yellow("!")} ${chalk4.cyan(id)} ${t.title} \u2014 last update ${ago}m ago`);
33432
33823
  }
33433
33824
  }
33434
33825
  if (recap.created.length > 0) {
33435
- console.log(chalk3.dim.bold(`
33826
+ console.log(chalk4.dim.bold(`
33436
33827
  Created (${recap.created.length}):`));
33437
33828
  for (const t of recap.created.slice(0, 10)) {
33438
33829
  const id = t.short_id || t.id.slice(0, 8);
33439
- console.log(` ${chalk3.dim("+")} ${chalk3.cyan(id)} ${t.title}`);
33830
+ console.log(` ${chalk4.dim("+")} ${chalk4.cyan(id)} ${t.title}`);
33440
33831
  }
33441
33832
  if (recap.created.length > 10)
33442
- console.log(chalk3.dim(` ... and ${recap.created.length - 10} more`));
33833
+ console.log(chalk4.dim(` ... and ${recap.created.length - 10} more`));
33443
33834
  }
33444
33835
  if (recap.agents.length > 0) {
33445
- console.log(chalk3.bold(`
33836
+ console.log(chalk4.bold(`
33446
33837
  Agents:`));
33447
33838
  for (const a of recap.agents) {
33448
33839
  const seen = Math.round((Date.now() - new Date(a.last_seen_at).getTime()) / 60000);
33449
- console.log(` ${a.name}: ${chalk3.green(a.completed_count + " done")} | ${chalk3.blue(a.in_progress_count + " active")} | last seen ${seen}m ago`);
33840
+ console.log(` ${a.name}: ${chalk4.green(a.completed_count + " done")} | ${chalk4.blue(a.in_progress_count + " active")} | last seen ${seen}m ago`);
33450
33841
  }
33451
33842
  }
33452
33843
  console.log();
@@ -33461,7 +33852,7 @@ program2.command("standup").description("Generate standup notes \u2014 completed
33461
33852
  output(recap, true);
33462
33853
  return;
33463
33854
  }
33464
- console.log(chalk3.bold(`
33855
+ console.log(chalk4.bold(`
33465
33856
  Standup \u2014 since ${sinceDate.toLocaleDateString()}
33466
33857
  `));
33467
33858
  const byAgent = new Map;
@@ -33472,29 +33863,29 @@ Standup \u2014 since ${sinceDate.toLocaleDateString()}
33472
33863
  byAgent.get(agent).push(t);
33473
33864
  }
33474
33865
  if (byAgent.size > 0) {
33475
- console.log(chalk3.green.bold("Done:"));
33866
+ console.log(chalk4.green.bold("Done:"));
33476
33867
  for (const [agent, tasks] of byAgent) {
33477
- console.log(` ${chalk3.cyan(agent)}:`);
33868
+ console.log(` ${chalk4.cyan(agent)}:`);
33478
33869
  for (const t of tasks) {
33479
33870
  const dur = t.duration_minutes != null ? ` (${t.duration_minutes}m)` : "";
33480
- console.log(` ${chalk3.green("\u2713")} ${t.short_id || t.id.slice(0, 8)} ${t.title}${dur}`);
33871
+ console.log(` ${chalk4.green("\u2713")} ${t.short_id || t.id.slice(0, 8)} ${t.title}${dur}`);
33481
33872
  }
33482
33873
  }
33483
33874
  } else {
33484
- console.log(chalk3.dim("Nothing completed."));
33875
+ console.log(chalk4.dim("Nothing completed."));
33485
33876
  }
33486
33877
  if (recap.in_progress.length > 0) {
33487
- console.log(chalk3.blue.bold(`
33878
+ console.log(chalk4.blue.bold(`
33488
33879
  In Progress:`));
33489
33880
  for (const t of recap.in_progress) {
33490
- console.log(` ${chalk3.blue("\u2192")} ${t.short_id || t.id.slice(0, 8)} ${t.title}${t.assigned_to ? ` \u2014 ${chalk3.dim(t.assigned_to)}` : ""}`);
33881
+ console.log(` ${chalk4.blue("\u2192")} ${t.short_id || t.id.slice(0, 8)} ${t.title}${t.assigned_to ? ` \u2014 ${chalk4.dim(t.assigned_to)}` : ""}`);
33491
33882
  }
33492
33883
  }
33493
33884
  if (recap.blocked.length > 0) {
33494
- console.log(chalk3.red.bold(`
33885
+ console.log(chalk4.red.bold(`
33495
33886
  Blocked:`));
33496
33887
  for (const t of recap.blocked) {
33497
- console.log(` ${chalk3.red("\u2717")} ${t.short_id || t.id.slice(0, 8)} ${t.title}`);
33888
+ console.log(` ${chalk4.red("\u2717")} ${t.short_id || t.id.slice(0, 8)} ${t.title}`);
33498
33889
  }
33499
33890
  }
33500
33891
  console.log();
@@ -33503,7 +33894,7 @@ program2.command("fail <id>").description("Mark a task as failed with optional r
33503
33894
  const db = getDatabase();
33504
33895
  const resolvedId = resolvePartialId(db, "tasks", id);
33505
33896
  if (!resolvedId) {
33506
- console.error(chalk3.red(`Task not found: ${id}`));
33897
+ console.error(chalk4.red(`Task not found: ${id}`));
33507
33898
  process.exit(1);
33508
33899
  }
33509
33900
  const result = failTask(resolvedId, opts.agent, opts.reason, { retry: opts.retry }, db);
@@ -33511,11 +33902,11 @@ program2.command("fail <id>").description("Mark a task as failed with optional r
33511
33902
  console.log(JSON.stringify(result, null, 2));
33512
33903
  return;
33513
33904
  }
33514
- console.log(chalk3.red(`Failed: ${result.task.short_id || result.task.id.slice(0, 8)} | ${result.task.title}`));
33905
+ console.log(chalk4.red(`Failed: ${result.task.short_id || result.task.id.slice(0, 8)} | ${result.task.title}`));
33515
33906
  if (opts.reason)
33516
- console.log(chalk3.dim(`Reason: ${opts.reason}`));
33907
+ console.log(chalk4.dim(`Reason: ${opts.reason}`));
33517
33908
  if (result.retryTask)
33518
- console.log(chalk3.yellow(`Retry created: ${result.retryTask.short_id || result.retryTask.id.slice(0, 8)} | ${result.retryTask.title}`));
33909
+ console.log(chalk4.yellow(`Retry created: ${result.retryTask.short_id || result.retryTask.id.slice(0, 8)} | ${result.retryTask.title}`));
33519
33910
  });
33520
33911
  program2.command("active").description("Show all currently in-progress tasks").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
33521
33912
  const db = getDatabase();
@@ -33528,14 +33919,14 @@ program2.command("active").description("Show all currently in-progress tasks").o
33528
33919
  return;
33529
33920
  }
33530
33921
  if (work.length === 0) {
33531
- console.log(chalk3.dim("No active work."));
33922
+ console.log(chalk4.dim("No active work."));
33532
33923
  return;
33533
33924
  }
33534
- console.log(chalk3.bold(`Active work (${work.length}):`));
33925
+ console.log(chalk4.bold(`Active work (${work.length}):`));
33535
33926
  for (const w of work) {
33536
33927
  const id = w.short_id || w.id.slice(0, 8);
33537
33928
  const agent = w.assigned_to || w.locked_by || "unassigned";
33538
- console.log(` ${chalk3.cyan(id)} | ${chalk3.yellow(w.priority)} | ${agent.padEnd(12)} | ${w.title}`);
33929
+ console.log(` ${chalk4.cyan(id)} | ${chalk4.yellow(w.priority)} | ${agent.padEnd(12)} | ${w.title}`);
33539
33930
  }
33540
33931
  });
33541
33932
  program2.command("stale").description("Find tasks stuck in_progress with no recent activity").option("--minutes <n>", "Stale threshold in minutes", "30").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
@@ -33549,14 +33940,14 @@ program2.command("stale").description("Find tasks stuck in_progress with no rece
33549
33940
  return;
33550
33941
  }
33551
33942
  if (tasks.length === 0) {
33552
- console.log(chalk3.dim("No stale tasks."));
33943
+ console.log(chalk4.dim("No stale tasks."));
33553
33944
  return;
33554
33945
  }
33555
- console.log(chalk3.bold(`Stale tasks (${tasks.length}):`));
33946
+ console.log(chalk4.bold(`Stale tasks (${tasks.length}):`));
33556
33947
  for (const t of tasks) {
33557
33948
  const id = t.short_id || t.id.slice(0, 8);
33558
33949
  const staleMin = Math.round((Date.now() - new Date(t.updated_at).getTime()) / 60000);
33559
- console.log(` ${chalk3.cyan(id)} | ${t.locked_by || t.assigned_to || "?"} | ${t.title} ${chalk3.dim(`(${staleMin}min stale)`)}`);
33950
+ console.log(` ${chalk4.cyan(id)} | ${t.locked_by || t.assigned_to || "?"} | ${t.title} ${chalk4.dim(`(${staleMin}min stale)`)}`);
33560
33951
  }
33561
33952
  });
33562
33953
  program2.command("redistribute <agent>").description("Release stale in-progress tasks and claim the best one (work-stealing)").option("--max-age <minutes>", "Stale threshold in minutes", "60").option("--project <id>", "Limit to a specific project").option("--limit <n>", "Max stale tasks to release").option("-j, --json", "Output as JSON").action(async (agent, opts) => {
@@ -33572,17 +33963,17 @@ program2.command("redistribute <agent>").description("Release stale in-progress
33572
33963
  console.log(JSON.stringify(result, null, 2));
33573
33964
  return;
33574
33965
  }
33575
- console.log(chalk3.bold(`Released ${result.released.length} stale task(s).`));
33966
+ console.log(chalk4.bold(`Released ${result.released.length} stale task(s).`));
33576
33967
  for (const t of result.released) {
33577
33968
  const id = t.short_id || t.id.slice(0, 8);
33578
- console.log(` ${chalk3.yellow("released")} ${chalk3.cyan(id)} ${t.title}`);
33969
+ console.log(` ${chalk4.yellow("released")} ${chalk4.cyan(id)} ${t.title}`);
33579
33970
  }
33580
33971
  if (result.claimed) {
33581
33972
  const id = result.claimed.short_id || result.claimed.id.slice(0, 8);
33582
- console.log(chalk3.green(`
33583
- Claimed: ${chalk3.cyan(id)} ${result.claimed.title}`));
33973
+ console.log(chalk4.green(`
33974
+ Claimed: ${chalk4.cyan(id)} ${result.claimed.title}`));
33584
33975
  } else {
33585
- console.log(chalk3.dim(`
33976
+ console.log(chalk4.dim(`
33586
33977
  No task claimed (nothing available).`));
33587
33978
  }
33588
33979
  });
@@ -33592,7 +33983,7 @@ program2.command("assign <id> <agent>").description("Assign a task to an agent")
33592
33983
  const db = getDatabase();
33593
33984
  const task = getTask2(resolvedId, db);
33594
33985
  if (!task) {
33595
- console.error(chalk3.red(`Task not found: ${id}`));
33986
+ console.error(chalk4.red(`Task not found: ${id}`));
33596
33987
  process.exit(1);
33597
33988
  }
33598
33989
  try {
@@ -33601,7 +33992,7 @@ program2.command("assign <id> <agent>").description("Assign a task to an agent")
33601
33992
  console.log(JSON.stringify(updated));
33602
33993
  return;
33603
33994
  }
33604
- console.log(chalk3.green(`Assigned to ${agent}: ${formatTaskLine(updated)}`));
33995
+ console.log(chalk4.green(`Assigned to ${agent}: ${formatTaskLine(updated)}`));
33605
33996
  } catch {
33606
33997
  handleError(new Error("Failed to assign"));
33607
33998
  }
@@ -33612,7 +34003,7 @@ program2.command("unassign <id>").description("Remove task assignment").option("
33612
34003
  const db = getDatabase();
33613
34004
  const task = getTask2(resolvedId, db);
33614
34005
  if (!task) {
33615
- console.error(chalk3.red(`Task not found: ${id}`));
34006
+ console.error(chalk4.red(`Task not found: ${id}`));
33616
34007
  process.exit(1);
33617
34008
  }
33618
34009
  try {
@@ -33621,7 +34012,7 @@ program2.command("unassign <id>").description("Remove task assignment").option("
33621
34012
  console.log(JSON.stringify(updated));
33622
34013
  return;
33623
34014
  }
33624
- console.log(chalk3.green(`Unassigned: ${formatTaskLine(updated)}`));
34015
+ console.log(chalk4.green(`Unassigned: ${formatTaskLine(updated)}`));
33625
34016
  } catch {
33626
34017
  handleError(new Error("Failed to unassign"));
33627
34018
  }
@@ -33632,7 +34023,7 @@ program2.command("tag <id> <tag>").description("Add a tag to a task").option("-j
33632
34023
  const db = getDatabase();
33633
34024
  const task = getTask2(resolvedId, db);
33634
34025
  if (!task) {
33635
- console.error(chalk3.red(`Task not found: ${id}`));
34026
+ console.error(chalk4.red(`Task not found: ${id}`));
33636
34027
  process.exit(1);
33637
34028
  }
33638
34029
  const newTags = [...new Set([...task.tags, tag])];
@@ -33642,7 +34033,7 @@ program2.command("tag <id> <tag>").description("Add a tag to a task").option("-j
33642
34033
  console.log(JSON.stringify(updated));
33643
34034
  return;
33644
34035
  }
33645
- console.log(chalk3.green(`Tagged [${tag}]: ${formatTaskLine(updated)}`));
34036
+ console.log(chalk4.green(`Tagged [${tag}]: ${formatTaskLine(updated)}`));
33646
34037
  } catch {
33647
34038
  handleError(new Error("Failed to tag"));
33648
34039
  }
@@ -33653,7 +34044,7 @@ program2.command("untag <id> <tag>").description("Remove a tag from a task").opt
33653
34044
  const db = getDatabase();
33654
34045
  const task = getTask2(resolvedId, db);
33655
34046
  if (!task) {
33656
- console.error(chalk3.red(`Task not found: ${id}`));
34047
+ console.error(chalk4.red(`Task not found: ${id}`));
33657
34048
  process.exit(1);
33658
34049
  }
33659
34050
  const newTags = task.tags.filter((t) => t !== tag);
@@ -33663,7 +34054,7 @@ program2.command("untag <id> <tag>").description("Remove a tag from a task").opt
33663
34054
  console.log(JSON.stringify(updated));
33664
34055
  return;
33665
34056
  }
33666
- console.log(chalk3.green(`Untagged [${tag}]: ${formatTaskLine(updated)}`));
34057
+ console.log(chalk4.green(`Untagged [${tag}]: ${formatTaskLine(updated)}`));
33667
34058
  } catch {
33668
34059
  handleError(new Error("Failed to untag"));
33669
34060
  }
@@ -33679,7 +34070,7 @@ program2.command("pin <id>").description("Escalate task to critical priority").o
33679
34070
  console.log(JSON.stringify(updated));
33680
34071
  return;
33681
34072
  }
33682
- console.log(chalk3.red(`\uD83D\uDCCC Pinned (critical): ${formatTaskLine(updated)}`));
34073
+ console.log(chalk4.red(`\uD83D\uDCCC Pinned (critical): ${formatTaskLine(updated)}`));
33683
34074
  } catch {
33684
34075
  handleError(new Error("Failed to pin"));
33685
34076
  }
@@ -33766,19 +34157,19 @@ program2.command("doctor").description("Diagnose common task data issues").optio
33766
34157
  console.log(JSON.stringify({ issues, ok: !issues.some((i) => i.severity === "error") }));
33767
34158
  return;
33768
34159
  }
33769
- console.log(chalk3.bold(`todos doctor
34160
+ console.log(chalk4.bold(`todos doctor
33770
34161
  `));
33771
34162
  for (const issue of issues) {
33772
- const icon = issue.severity === "error" ? chalk3.red("\u2717") : issue.severity === "warn" ? chalk3.yellow("\u26A0") : chalk3.green("\u2713");
34163
+ const icon = issue.severity === "error" ? chalk4.red("\u2717") : issue.severity === "warn" ? chalk4.yellow("\u26A0") : chalk4.green("\u2713");
33773
34164
  console.log(` ${icon} ${issue.message}`);
33774
34165
  }
33775
34166
  const errors2 = issues.filter((i) => i.severity === "error").length;
33776
34167
  const warns = issues.filter((i) => i.severity === "warn").length;
33777
34168
  if (errors2 === 0 && warns === 0)
33778
- console.log(chalk3.green(`
34169
+ console.log(chalk4.green(`
33779
34170
  All clear.`));
33780
34171
  else
33781
- console.log(chalk3[errors2 > 0 ? "red" : "yellow"](`
34172
+ console.log(chalk4[errors2 > 0 ? "red" : "yellow"](`
33782
34173
  ${errors2} error(s), ${warns} warning(s). Run with --fix to auto-resolve where possible.`));
33783
34174
  });
33784
34175
  program2.command("health").description("Check todos system health \u2014 database, config, connectivity").option("-j, --json", "Output as JSON").action(async (opts) => {
@@ -33793,7 +34184,7 @@ program2.command("health").description("Check todos system health \u2014 databas
33793
34184
  try {
33794
34185
  size = `${(statSync3(dbPath).size / 1024 / 1024).toFixed(1)} MB`;
33795
34186
  } catch {}
33796
- checks.push({ name: "Database", ok: true, message: `${row.count} tasks \xB7 ${size} \xB7 ${chalk3.dim(dbPath)}` });
34187
+ checks.push({ name: "Database", ok: true, message: `${row.count} tasks \xB7 ${size} \xB7 ${chalk4.dim(dbPath)}` });
33797
34188
  } catch (e) {
33798
34189
  checks.push({ name: "Database", ok: false, message: e instanceof Error ? e.message : "Failed" });
33799
34190
  }
@@ -33826,15 +34217,15 @@ program2.command("health").description("Check todos system health \u2014 databas
33826
34217
  console.log(JSON.stringify({ ok, checks }));
33827
34218
  return;
33828
34219
  }
33829
- console.log(chalk3.bold(`todos health
34220
+ console.log(chalk4.bold(`todos health
33830
34221
  `));
33831
34222
  for (const c of checks) {
33832
- const icon = c.ok ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
34223
+ const icon = c.ok ? chalk4.green("\u2713") : chalk4.yellow("\u26A0");
33833
34224
  console.log(` ${icon} ${c.name.padEnd(14)} ${c.message}`);
33834
34225
  }
33835
34226
  const allOk = checks.every((c) => c.ok);
33836
34227
  console.log(`
33837
- ${allOk ? chalk3.green("All checks passed.") : chalk3.yellow("Some checks need attention.")}`);
34228
+ ${allOk ? chalk4.green("All checks passed.") : chalk4.yellow("Some checks need attention.")}`);
33838
34229
  });
33839
34230
  program2.command("report").description("Analytics report: task activity, completion rates, agent breakdown").option("--days <n>", "Days to include in report", "7").option("--project <id>", "Filter to project").option("--markdown", "Output as markdown").option("-j, --json", "Output as JSON").action(async (opts) => {
33840
34231
  const globalOpts = program2.opts();
@@ -33883,15 +34274,15 @@ program2.command("report").description("Analytics report: task activity, complet
33883
34274
  if (sparkline)
33884
34275
  lines.push(`| Activity | \`${sparkline}\` |`);
33885
34276
  } else {
33886
- lines.push(chalk3.bold(`todos report \u2014 last ${days} day${days !== 1 ? "s" : ""}`));
34277
+ lines.push(chalk4.bold(`todos report \u2014 last ${days} day${days !== 1 ? "s" : ""}`));
33887
34278
  lines.push("");
33888
- lines.push(` Total: ${chalk3.bold(String(all.length))} tasks (${chalk3.yellow(String(stats.by_status?.pending ?? 0))} pending, ${chalk3.blue(String(stats.by_status?.in_progress ?? 0))} active)`);
33889
- lines.push(` Changed: ${chalk3.bold(String(changed.length))} in period`);
33890
- lines.push(` Completed: ${chalk3.green(String(completed.length))} (${completionRate}% rate)`);
34279
+ lines.push(` Total: ${chalk4.bold(String(all.length))} tasks (${chalk4.yellow(String(stats.by_status?.pending ?? 0))} pending, ${chalk4.blue(String(stats.by_status?.in_progress ?? 0))} active)`);
34280
+ lines.push(` Changed: ${chalk4.bold(String(changed.length))} in period`);
34281
+ lines.push(` Completed: ${chalk4.green(String(completed.length))} (${completionRate}% rate)`);
33891
34282
  if (failed.length > 0)
33892
- lines.push(` Failed: ${chalk3.red(String(failed.length))}`);
34283
+ lines.push(` Failed: ${chalk4.red(String(failed.length))}`);
33893
34284
  if (sparkline)
33894
- lines.push(` Activity: ${chalk3.dim(sparkline)}`);
34285
+ lines.push(` Activity: ${chalk4.dim(sparkline)}`);
33895
34286
  if (Object.keys(byAgent).length > 0) {
33896
34287
  lines.push(` By agent: ${Object.entries(byAgent).map(([a, n]) => `${a}=${n}`).join(" ")}`);
33897
34288
  }
@@ -33915,21 +34306,21 @@ program2.command("today").description("Show task activity from today").option("-
33915
34306
  console.log(JSON.stringify({ date: start.toISOString().slice(0, 10), completed, started, changed: other }));
33916
34307
  return;
33917
34308
  }
33918
- console.log(chalk3.bold(`Today \u2014 ${start.toISOString().slice(0, 10)}
34309
+ console.log(chalk4.bold(`Today \u2014 ${start.toISOString().slice(0, 10)}
33919
34310
  `));
33920
34311
  if (completed.length > 0) {
33921
- console.log(chalk3.green(` \u2713 Completed (${completed.length}):`));
34312
+ console.log(chalk4.green(` \u2713 Completed (${completed.length}):`));
33922
34313
  for (const t of completed)
33923
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : ""}`);
34314
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk4.dim(` \u2014 ${t.assigned_to}`) : ""}`);
33924
34315
  }
33925
34316
  if (started.length > 0) {
33926
- console.log(chalk3.blue(`
34317
+ console.log(chalk4.blue(`
33927
34318
  \u25B6 Started (${started.length}):`));
33928
34319
  for (const t of started)
33929
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : ""}`);
34320
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk4.dim(` \u2014 ${t.assigned_to}`) : ""}`);
33930
34321
  }
33931
34322
  if (completed.length === 0 && started.length === 0)
33932
- console.log(chalk3.dim(" No activity today."));
34323
+ console.log(chalk4.dim(" No activity today."));
33933
34324
  });
33934
34325
  program2.command("yesterday").description("Show task activity from yesterday").option("-j, --json", "Output as JSON").action(async (opts) => {
33935
34326
  const globalOpts = program2.opts();
@@ -33948,21 +34339,21 @@ program2.command("yesterday").description("Show task activity from yesterday").o
33948
34339
  console.log(JSON.stringify({ date: start.toISOString().slice(0, 10), completed, started }));
33949
34340
  return;
33950
34341
  }
33951
- console.log(chalk3.bold(`Yesterday \u2014 ${start.toISOString().slice(0, 10)}
34342
+ console.log(chalk4.bold(`Yesterday \u2014 ${start.toISOString().slice(0, 10)}
33952
34343
  `));
33953
34344
  if (completed.length > 0) {
33954
- console.log(chalk3.green(` \u2713 Completed (${completed.length}):`));
34345
+ console.log(chalk4.green(` \u2713 Completed (${completed.length}):`));
33955
34346
  for (const t of completed)
33956
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : ""}`);
34347
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk4.dim(` \u2014 ${t.assigned_to}`) : ""}`);
33957
34348
  }
33958
34349
  if (started.length > 0) {
33959
- console.log(chalk3.blue(`
34350
+ console.log(chalk4.blue(`
33960
34351
  \u25B6 Started (${started.length}):`));
33961
34352
  for (const t of started)
33962
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}`);
34353
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}`);
33963
34354
  }
33964
34355
  if (completed.length === 0 && started.length === 0)
33965
- console.log(chalk3.dim(" No activity yesterday."));
34356
+ console.log(chalk4.dim(" No activity yesterday."));
33966
34357
  });
33967
34358
  program2.command("mine").description("Show tasks assigned to you, grouped by status").argument("<agent>", "Agent name or ID").option("-j, --json", "Output as JSON").action(async (agent, opts) => {
33968
34359
  const globalOpts = program2.opts();
@@ -33997,23 +34388,23 @@ program2.command("mine").description("Show tasks assigned to you, grouped by sta
33997
34388
  }
33998
34389
  const statusOrder = ["in_progress", "pending", "blocked", "completed", "failed", "cancelled"];
33999
34390
  const statusIcons2 = { in_progress: "\u25B6", pending: "\u25CB", blocked: "\u2298", completed: "\u2713", failed: "\u2717", cancelled: "\u2014" };
34000
- const statusColors5 = { in_progress: chalk3.blue, pending: chalk3.white, blocked: chalk3.red, completed: chalk3.green, failed: chalk3.red, cancelled: chalk3.dim };
34001
- console.log(chalk3.bold(`Tasks for ${agent} (${tasks.length} total):
34391
+ const statusColors5 = { in_progress: chalk4.blue, pending: chalk4.white, blocked: chalk4.red, completed: chalk4.green, failed: chalk4.red, cancelled: chalk4.dim };
34392
+ console.log(chalk4.bold(`Tasks for ${agent} (${tasks.length} total):
34002
34393
  `));
34003
34394
  for (const status of statusOrder) {
34004
34395
  const group = groups[status];
34005
34396
  if (!group || group.length === 0)
34006
34397
  continue;
34007
- const color = statusColors5[status] || chalk3.white;
34398
+ const color = statusColors5[status] || chalk4.white;
34008
34399
  const icon = statusIcons2[status] || "?";
34009
34400
  console.log(color(` ${icon} ${status.replace("_", " ")} (${group.length}):`));
34010
34401
  for (const t of group) {
34011
- const priority = t.priority === "critical" || t.priority === "high" ? chalk3.red(` [${t.priority}]`) : "";
34012
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${priority}`);
34402
+ const priority = t.priority === "critical" || t.priority === "high" ? chalk4.red(` [${t.priority}]`) : "";
34403
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${priority}`);
34013
34404
  }
34014
34405
  }
34015
34406
  if (tasks.length === 0)
34016
- console.log(chalk3.dim(` No tasks assigned to ${agent}.`));
34407
+ console.log(chalk4.dim(` No tasks assigned to ${agent}.`));
34017
34408
  });
34018
34409
  program2.command("blocked").description("Show tasks blocked by incomplete dependencies").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
34019
34410
  const globalOpts = program2.opts();
@@ -34035,15 +34426,15 @@ program2.command("blocked").description("Show tasks blocked by incomplete depend
34035
34426
  return;
34036
34427
  }
34037
34428
  if (blockedTasks.length === 0) {
34038
- console.log(chalk3.green(" No blocked tasks!"));
34429
+ console.log(chalk4.green(" No blocked tasks!"));
34039
34430
  return;
34040
34431
  }
34041
- console.log(chalk3.bold(`Blocked (${blockedTasks.length}):
34432
+ console.log(chalk4.bold(`Blocked (${blockedTasks.length}):
34042
34433
  `));
34043
34434
  for (const { task, blockers } of blockedTasks) {
34044
- console.log(` ${chalk3.cyan(task.short_id || task.id.slice(0, 8))} ${task.title}`);
34435
+ console.log(` ${chalk4.cyan(task.short_id || task.id.slice(0, 8))} ${task.title}`);
34045
34436
  for (const bl of blockers) {
34046
- console.log(` ${chalk3.red("\u2298")} ${chalk3.dim(bl.short_id || bl.id.slice(0, 8))} ${chalk3.dim(bl.title)} ${chalk3.yellow(`[${bl.status}]`)}`);
34437
+ console.log(` ${chalk4.red("\u2298")} ${chalk4.dim(bl.short_id || bl.id.slice(0, 8))} ${chalk4.dim(bl.title)} ${chalk4.yellow(`[${bl.status}]`)}`);
34047
34438
  }
34048
34439
  }
34049
34440
  });
@@ -34057,16 +34448,16 @@ program2.command("overdue").description("Show tasks past their due date").option
34057
34448
  return;
34058
34449
  }
34059
34450
  if (tasks.length === 0) {
34060
- console.log(chalk3.green(" No overdue tasks!"));
34451
+ console.log(chalk4.green(" No overdue tasks!"));
34061
34452
  return;
34062
34453
  }
34063
- console.log(chalk3.bold.red(`Overdue (${tasks.length}):
34454
+ console.log(chalk4.bold.red(`Overdue (${tasks.length}):
34064
34455
  `));
34065
34456
  for (const t of tasks) {
34066
34457
  const dueDate = t.due_at.slice(0, 10);
34067
34458
  const daysOverdue = Math.floor((Date.now() - new Date(t.due_at).getTime()) / 86400000);
34068
- const urgency = daysOverdue > 7 ? chalk3.bgRed.white(` ${daysOverdue}d `) : chalk3.red(`${daysOverdue}d`);
34069
- console.log(` ${urgency} ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : ""} ${chalk3.dim(`(due ${dueDate})`)}`);
34459
+ const urgency = daysOverdue > 7 ? chalk4.bgRed.white(` ${daysOverdue}d `) : chalk4.red(`${daysOverdue}d`);
34460
+ console.log(` ${urgency} ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk4.dim(` \u2014 ${t.assigned_to}`) : ""} ${chalk4.dim(`(due ${dueDate})`)}`);
34070
34461
  }
34071
34462
  });
34072
34463
  program2.command("week").description("Show task activity from the past 7 days").option("-j, --json", "Output as JSON").action(async (opts) => {
@@ -34101,8 +34492,8 @@ program2.command("week").description("Show task activity from the past 7 days").
34101
34492
  }
34102
34493
  const totalCompleted = tasks.filter((t) => t.status === "completed").length;
34103
34494
  const totalStarted = tasks.filter((t) => t.status === "in_progress").length;
34104
- console.log(chalk3.bold(`Week \u2014 ${start.toISOString().slice(0, 10)} to ${now2.toISOString().slice(0, 10)}`));
34105
- console.log(chalk3.dim(` ${totalCompleted} completed, ${totalStarted} in progress, ${tasks.length} total changes
34495
+ console.log(chalk4.bold(`Week \u2014 ${start.toISOString().slice(0, 10)} to ${now2.toISOString().slice(0, 10)}`));
34496
+ console.log(chalk4.dim(` ${totalCompleted} completed, ${totalStarted} in progress, ${tasks.length} total changes
34106
34497
  `));
34107
34498
  const sortedDays = Object.keys(days).sort().reverse();
34108
34499
  for (const day of sortedDays) {
@@ -34113,14 +34504,14 @@ program2.command("week").description("Show task activity from the past 7 days").
34113
34504
  if (completed.length === 0 && started.length === 0)
34114
34505
  continue;
34115
34506
  const weekday = new Date(day + "T12:00:00").toLocaleDateString("en-US", { weekday: "short" });
34116
- console.log(chalk3.bold(` ${weekday} ${day}`));
34507
+ console.log(chalk4.bold(` ${weekday} ${day}`));
34117
34508
  for (const t of completed)
34118
- console.log(` ${chalk3.green("\u2713")} ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : ""}`);
34509
+ console.log(` ${chalk4.green("\u2713")} ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk4.dim(` \u2014 ${t.assigned_to}`) : ""}`);
34119
34510
  for (const t of started)
34120
- console.log(` ${chalk3.blue("\u25B6")} ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : ""}`);
34511
+ console.log(` ${chalk4.blue("\u25B6")} ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${t.assigned_to ? chalk4.dim(` \u2014 ${t.assigned_to}`) : ""}`);
34121
34512
  }
34122
34513
  if (tasks.length === 0)
34123
- console.log(chalk3.dim(" No activity this week."));
34514
+ console.log(chalk4.dim(" No activity this week."));
34124
34515
  });
34125
34516
  program2.command("burndown").description("Show task completion velocity over the past 7 days").option("--days <n>", "Number of days", "7").option("-j, --json", "Output as JSON").action(async (opts) => {
34126
34517
  const globalOpts = program2.opts();
@@ -34148,20 +34539,20 @@ program2.command("burndown").description("Show task completion velocity over the
34148
34539
  }
34149
34540
  const maxVal = Math.max(...dayStats.map((d) => Math.max(d.completed, d.created)), 1);
34150
34541
  const barWidth = 30;
34151
- console.log(chalk3.bold("Burndown (last " + numDays + ` days):
34542
+ console.log(chalk4.bold("Burndown (last " + numDays + ` days):
34152
34543
  `));
34153
- console.log(chalk3.dim(" Date Done New Failed Chart"));
34544
+ console.log(chalk4.dim(" Date Done New Failed Chart"));
34154
34545
  for (const day of dayStats) {
34155
34546
  const weekday = new Date(day.date + "T12:00:00").toLocaleDateString("en-US", { weekday: "short" });
34156
- const completedBar = chalk3.green("\u2588".repeat(Math.round(day.completed / maxVal * barWidth)));
34157
- const createdBar = chalk3.blue("\u2591".repeat(Math.round(day.created / maxVal * barWidth)));
34158
- const failed = day.failed > 0 ? chalk3.red(String(day.failed).padStart(4)) : chalk3.dim(" 0");
34159
- console.log(` ${weekday} ${day.date.slice(5)} ${chalk3.green(String(day.completed).padStart(4))} ${chalk3.blue(String(day.created).padStart(4))} ${failed} ${completedBar}${createdBar}`);
34547
+ const completedBar = chalk4.green("\u2588".repeat(Math.round(day.completed / maxVal * barWidth)));
34548
+ const createdBar = chalk4.blue("\u2591".repeat(Math.round(day.created / maxVal * barWidth)));
34549
+ const failed = day.failed > 0 ? chalk4.red(String(day.failed).padStart(4)) : chalk4.dim(" 0");
34550
+ console.log(` ${weekday} ${day.date.slice(5)} ${chalk4.green(String(day.completed).padStart(4))} ${chalk4.blue(String(day.created).padStart(4))} ${failed} ${completedBar}${createdBar}`);
34160
34551
  }
34161
34552
  const totalCompleted = dayStats.reduce((s, d) => s + d.completed, 0);
34162
34553
  const totalCreated = dayStats.reduce((s, d) => s + d.created, 0);
34163
34554
  const velocity = (totalCompleted / numDays).toFixed(1);
34164
- console.log(chalk3.dim(`
34555
+ console.log(chalk4.dim(`
34165
34556
  Velocity: ${velocity}/day \xB7 ${totalCompleted} done \xB7 ${totalCreated} created`));
34166
34557
  });
34167
34558
  program2.command("log").description("Show recent task activity log (git-log style)").option("--limit <n>", "Number of entries", "30").option("-j, --json", "Output as JSON").action(async (opts) => {
@@ -34174,38 +34565,38 @@ program2.command("log").description("Show recent task activity log (git-log styl
34174
34565
  return;
34175
34566
  }
34176
34567
  if (entries.length === 0) {
34177
- console.log(chalk3.dim(" No activity yet."));
34568
+ console.log(chalk4.dim(" No activity yet."));
34178
34569
  return;
34179
34570
  }
34180
34571
  const actionIcons = {
34181
- create: chalk3.green("+"),
34182
- start: chalk3.blue("\u25B6"),
34183
- complete: chalk3.green("\u2713"),
34184
- fail: chalk3.red("\u2717"),
34185
- update: chalk3.yellow("~"),
34186
- approve: chalk3.green("\u2605"),
34187
- lock: chalk3.dim("\uD83D\uDD12"),
34188
- unlock: chalk3.dim("\uD83D\uDD13")
34572
+ create: chalk4.green("+"),
34573
+ start: chalk4.blue("\u25B6"),
34574
+ complete: chalk4.green("\u2713"),
34575
+ fail: chalk4.red("\u2717"),
34576
+ update: chalk4.yellow("~"),
34577
+ approve: chalk4.green("\u2605"),
34578
+ lock: chalk4.dim("\uD83D\uDD12"),
34579
+ unlock: chalk4.dim("\uD83D\uDD13")
34189
34580
  };
34190
34581
  let lastDate = "";
34191
34582
  for (const e of entries) {
34192
34583
  const date = e.created_at.slice(0, 10);
34193
34584
  const time = e.created_at.slice(11, 16);
34194
34585
  if (date !== lastDate) {
34195
- console.log(chalk3.bold(`
34586
+ console.log(chalk4.bold(`
34196
34587
  ${date}`));
34197
34588
  lastDate = date;
34198
34589
  }
34199
- const icon = actionIcons[e.action] || chalk3.dim("\xB7");
34200
- const agent = e.agent_id ? chalk3.dim(` (${e.agent_id})`) : "";
34201
- const taskRef = chalk3.cyan(e.task_id.slice(0, 8));
34590
+ const icon = actionIcons[e.action] || chalk4.dim("\xB7");
34591
+ const agent = e.agent_id ? chalk4.dim(` (${e.agent_id})`) : "";
34592
+ const taskRef = chalk4.cyan(e.task_id.slice(0, 8));
34202
34593
  let detail = "";
34203
34594
  if (e.field && e.old_value && e.new_value) {
34204
- detail = chalk3.dim(` ${e.field}: ${e.old_value} \u2192 ${e.new_value}`);
34595
+ detail = chalk4.dim(` ${e.field}: ${e.old_value} \u2192 ${e.new_value}`);
34205
34596
  } else if (e.field && e.new_value) {
34206
- detail = chalk3.dim(` ${e.field}: ${e.new_value}`);
34597
+ detail = chalk4.dim(` ${e.field}: ${e.new_value}`);
34207
34598
  }
34208
- console.log(` ${chalk3.dim(time)} ${icon} ${e.action.padEnd(8)} ${taskRef}${detail}${agent}`);
34599
+ console.log(` ${chalk4.dim(time)} ${icon} ${e.action.padEnd(8)} ${taskRef}${detail}${agent}`);
34209
34600
  }
34210
34601
  });
34211
34602
  program2.command("ready").description("Show all tasks ready to be claimed (pending, unblocked, unlocked)").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").option("--limit <n>", "Max tasks to show", "20").action(async (opts) => {
@@ -34230,15 +34621,15 @@ program2.command("ready").description("Show all tasks ready to be claimed (pendi
34230
34621
  return;
34231
34622
  }
34232
34623
  if (limited.length === 0) {
34233
- console.log(chalk3.dim(" No tasks ready to claim."));
34624
+ console.log(chalk4.dim(" No tasks ready to claim."));
34234
34625
  return;
34235
34626
  }
34236
- console.log(chalk3.bold(`Ready to claim (${ready.length}${ready.length > limited.length ? `, showing ${limited.length}` : ""}):
34627
+ console.log(chalk4.bold(`Ready to claim (${ready.length}${ready.length > limited.length ? `, showing ${limited.length}` : ""}):
34237
34628
  `));
34238
34629
  for (const t of limited) {
34239
- const pri = t.priority === "critical" ? chalk3.bgRed.white(" CRIT ") : t.priority === "high" ? chalk3.red("[high]") : t.priority === "medium" ? chalk3.yellow("[med]") : "";
34240
- const due = t.due_at ? chalk3.dim(` due ${t.due_at.slice(0, 10)}`) : "";
34241
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title} ${pri}${due}`);
34630
+ const pri = t.priority === "critical" ? chalk4.bgRed.white(" CRIT ") : t.priority === "high" ? chalk4.red("[high]") : t.priority === "medium" ? chalk4.yellow("[med]") : "";
34631
+ const due = t.due_at ? chalk4.dim(` due ${t.due_at.slice(0, 10)}`) : "";
34632
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title} ${pri}${due}`);
34242
34633
  }
34243
34634
  });
34244
34635
  program2.command("sprint").description("Sprint dashboard: in-progress, next up, blockers, and overdue").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
@@ -34265,41 +34656,41 @@ program2.command("sprint").description("Sprint dashboard: in-progress, next up,
34265
34656
  console.log(JSON.stringify({ in_progress: inProgress, next_up: nextUp, blocked, overdue }));
34266
34657
  return;
34267
34658
  }
34268
- console.log(chalk3.bold(`Sprint Dashboard
34659
+ console.log(chalk4.bold(`Sprint Dashboard
34269
34660
  `));
34270
- console.log(chalk3.blue(` \u25B6 In Progress (${inProgress.length}):`));
34661
+ console.log(chalk4.blue(` \u25B6 In Progress (${inProgress.length}):`));
34271
34662
  if (inProgress.length === 0)
34272
- console.log(chalk3.dim(" (none)"));
34663
+ console.log(chalk4.dim(" (none)"));
34273
34664
  for (const t of inProgress) {
34274
- const agent = t.assigned_to ? chalk3.dim(` \u2014 ${t.assigned_to}`) : "";
34275
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${agent}`);
34665
+ const agent = t.assigned_to ? chalk4.dim(` \u2014 ${t.assigned_to}`) : "";
34666
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}${agent}`);
34276
34667
  }
34277
- console.log(chalk3.white(`
34668
+ console.log(chalk4.white(`
34278
34669
  \u25CB Next Up (${nextUp.length}):`));
34279
34670
  if (nextUp.length === 0)
34280
- console.log(chalk3.dim(" (none)"));
34671
+ console.log(chalk4.dim(" (none)"));
34281
34672
  for (const t of nextUp) {
34282
- const pri = t.priority === "critical" ? chalk3.bgRed.white(" CRIT ") : t.priority === "high" ? chalk3.red("[high]") : "";
34283
- console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title} ${pri}`);
34673
+ const pri = t.priority === "critical" ? chalk4.bgRed.white(" CRIT ") : t.priority === "high" ? chalk4.red("[high]") : "";
34674
+ console.log(` ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title} ${pri}`);
34284
34675
  }
34285
34676
  if (blocked.length > 0) {
34286
- console.log(chalk3.red(`
34677
+ console.log(chalk4.red(`
34287
34678
  \u2298 Blocked (${blocked.length}):`));
34288
34679
  for (const { task, blockers } of blocked) {
34289
- console.log(` ${chalk3.cyan(task.short_id || task.id.slice(0, 8))} ${task.title}`);
34680
+ console.log(` ${chalk4.cyan(task.short_id || task.id.slice(0, 8))} ${task.title}`);
34290
34681
  for (const bl of blockers)
34291
- console.log(` ${chalk3.dim("\u2190 " + (bl.short_id || bl.id.slice(0, 8)) + " " + bl.title)} ${chalk3.yellow(`[${bl.status}]`)}`);
34682
+ console.log(` ${chalk4.dim("\u2190 " + (bl.short_id || bl.id.slice(0, 8)) + " " + bl.title)} ${chalk4.yellow(`[${bl.status}]`)}`);
34292
34683
  }
34293
34684
  }
34294
34685
  if (overdue.length > 0) {
34295
- console.log(chalk3.red(`
34686
+ console.log(chalk4.red(`
34296
34687
  \u26A0 Overdue (${overdue.length}):`));
34297
34688
  for (const t of overdue) {
34298
34689
  const daysOver = Math.floor((Date.now() - new Date(t.due_at).getTime()) / 86400000);
34299
- console.log(` ${chalk3.red(`${daysOver}d`)} ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}`);
34690
+ console.log(` ${chalk4.red(`${daysOver}d`)} ${chalk4.cyan(t.short_id || t.id.slice(0, 8))} ${t.title}`);
34300
34691
  }
34301
34692
  }
34302
- console.log(chalk3.dim(`
34693
+ console.log(chalk4.dim(`
34303
34694
  ${inProgress.length} active \xB7 ${pending.length} pending \xB7 ${blocked.length} blocked \xB7 ${overdue.length} overdue`));
34304
34695
  });
34305
34696
  program2.command("handoff").description("Create or view agent session handoffs").option("--create", "Create a new handoff").option("--agent <name>", "Agent name").option("--summary <text>", "Handoff summary").option("--completed <items>", "Comma-separated completed items").option("--in-progress <items>", "Comma-separated in-progress items").option("--blockers <items>", "Comma-separated blockers").option("--next <items>", "Comma-separated next steps").option("-j, --json", "Output as JSON").option("--limit <n>", "Number of handoffs to show", "5").action(async (opts) => {
@@ -34309,7 +34700,7 @@ program2.command("handoff").description("Create or view agent session handoffs")
34309
34700
  const projectId = autoProject(globalOpts) || undefined;
34310
34701
  if (opts.create || opts.summary) {
34311
34702
  if (!opts.summary) {
34312
- console.error(chalk3.red(" --summary is required for creating a handoff"));
34703
+ console.error(chalk4.red(" --summary is required for creating a handoff"));
34313
34704
  process.exit(1);
34314
34705
  }
34315
34706
  const handoff = createHandoff2({
@@ -34325,7 +34716,7 @@ program2.command("handoff").description("Create or view agent session handoffs")
34325
34716
  console.log(JSON.stringify(handoff));
34326
34717
  return;
34327
34718
  }
34328
- console.log(chalk3.green(` \u2713 Handoff created by ${handoff.agent_id || "unknown"}`));
34719
+ console.log(chalk4.green(` \u2713 Handoff created by ${handoff.agent_id || "unknown"}`));
34329
34720
  return;
34330
34721
  }
34331
34722
  const handoffs = listHandoffs2(projectId, parseInt(opts.limit, 10), db);
@@ -34334,31 +34725,31 @@ program2.command("handoff").description("Create or view agent session handoffs")
34334
34725
  return;
34335
34726
  }
34336
34727
  if (handoffs.length === 0) {
34337
- console.log(chalk3.dim(" No handoffs yet."));
34728
+ console.log(chalk4.dim(" No handoffs yet."));
34338
34729
  return;
34339
34730
  }
34340
34731
  for (const h of handoffs) {
34341
34732
  const time = h.created_at.slice(0, 16).replace("T", " ");
34342
- console.log(chalk3.bold(`
34733
+ console.log(chalk4.bold(`
34343
34734
  ${time} ${h.agent_id || "unknown"}`));
34344
34735
  console.log(` ${h.summary}`);
34345
34736
  if (h.completed?.length) {
34346
- console.log(chalk3.green(` \u2713 Completed:`));
34737
+ console.log(chalk4.green(` \u2713 Completed:`));
34347
34738
  for (const c of h.completed)
34348
34739
  console.log(` - ${c}`);
34349
34740
  }
34350
34741
  if (h.in_progress?.length) {
34351
- console.log(chalk3.blue(` \u25B6 In progress:`));
34742
+ console.log(chalk4.blue(` \u25B6 In progress:`));
34352
34743
  for (const c of h.in_progress)
34353
34744
  console.log(` - ${c}`);
34354
34745
  }
34355
34746
  if (h.blockers?.length) {
34356
- console.log(chalk3.red(` \u2298 Blockers:`));
34747
+ console.log(chalk4.red(` \u2298 Blockers:`));
34357
34748
  for (const c of h.blockers)
34358
34749
  console.log(` - ${c}`);
34359
34750
  }
34360
34751
  if (h.next_steps?.length) {
34361
- console.log(chalk3.cyan(` \u2192 Next steps:`));
34752
+ console.log(chalk4.cyan(` \u2192 Next steps:`));
34362
34753
  for (const c of h.next_steps)
34363
34754
  console.log(` - ${c}`);
34364
34755
  }
@@ -34384,16 +34775,16 @@ program2.command("priorities").description("Show task counts grouped by priority
34384
34775
  console.log(JSON.stringify(counts));
34385
34776
  return;
34386
34777
  }
34387
- console.log(chalk3.bold(`Priority Breakdown:
34778
+ console.log(chalk4.bold(`Priority Breakdown:
34388
34779
  `));
34389
- const priColors = { critical: chalk3.bgRed.white, high: chalk3.red, medium: chalk3.yellow, low: chalk3.blue, none: chalk3.dim };
34780
+ const priColors = { critical: chalk4.bgRed.white, high: chalk4.red, medium: chalk4.yellow, low: chalk4.blue, none: chalk4.dim };
34390
34781
  for (const p of priorities) {
34391
34782
  const c = counts[p];
34392
34783
  if (!c || c.total === 0)
34393
34784
  continue;
34394
- const color = priColors[p] || chalk3.white;
34395
- const bar = chalk3.green("\u2588".repeat(Math.min(c.completed, 30))) + chalk3.blue("\u2591".repeat(Math.min(c.in_progress, 10))) + chalk3.dim("\xB7".repeat(Math.min(c.pending, 20)));
34396
- console.log(` ${color(p.padEnd(9))} ${String(c.total).padStart(4)} total ${chalk3.green(String(c.completed).padStart(3))} done ${chalk3.blue(String(c.in_progress).padStart(3))} active ${chalk3.dim(String(c.pending).padStart(3))} pending ${bar}`);
34785
+ const color = priColors[p] || chalk4.white;
34786
+ const bar = chalk4.green("\u2588".repeat(Math.min(c.completed, 30))) + chalk4.blue("\u2591".repeat(Math.min(c.in_progress, 10))) + chalk4.dim("\xB7".repeat(Math.min(c.pending, 20)));
34787
+ console.log(` ${color(p.padEnd(9))} ${String(c.total).padStart(4)} total ${chalk4.green(String(c.completed).padStart(3))} done ${chalk4.blue(String(c.in_progress).padStart(3))} active ${chalk4.dim(String(c.pending).padStart(3))} pending ${bar}`);
34397
34788
  }
34398
34789
  });
34399
34790
  program2.command("context").description("Session start context: status, latest handoff, next task, overdue").option("--agent <name>", "Agent name for handoff lookup").option("-j, --json", "Output as JSON").action(async (opts) => {
@@ -34413,21 +34804,21 @@ program2.command("context").description("Session start context: status, latest h
34413
34804
  console.log(JSON.stringify({ status, next_task: nextTask, overdue_count: overdue.length, latest_handoff: handoff, as_of: new Date().toISOString() }));
34414
34805
  return;
34415
34806
  }
34416
- console.log(chalk3.bold(`Session Context
34807
+ console.log(chalk4.bold(`Session Context
34417
34808
  `));
34418
34809
  console.log(` ${status.pending} pending \xB7 ${status.in_progress} active \xB7 ${status.completed} done \xB7 ${status.total} total`);
34419
34810
  if (status.stale_count > 0)
34420
- console.log(chalk3.yellow(` \u26A0 ${status.stale_count} stale tasks`));
34811
+ console.log(chalk4.yellow(` \u26A0 ${status.stale_count} stale tasks`));
34421
34812
  if (overdue.length > 0)
34422
- console.log(chalk3.red(` \u26A0 ${overdue.length} overdue tasks`));
34813
+ console.log(chalk4.red(` \u26A0 ${overdue.length} overdue tasks`));
34423
34814
  if (nextTask) {
34424
- const pri = nextTask.priority === "critical" || nextTask.priority === "high" ? chalk3.red(` [${nextTask.priority}]`) : "";
34425
- console.log(chalk3.bold(`
34815
+ const pri = nextTask.priority === "critical" || nextTask.priority === "high" ? chalk4.red(` [${nextTask.priority}]`) : "";
34816
+ console.log(chalk4.bold(`
34426
34817
  Next up:`));
34427
- console.log(` ${chalk3.cyan(nextTask.short_id || nextTask.id.slice(0, 8))} ${nextTask.title}${pri}`);
34818
+ console.log(` ${chalk4.cyan(nextTask.short_id || nextTask.id.slice(0, 8))} ${nextTask.title}${pri}`);
34428
34819
  }
34429
34820
  if (handoff) {
34430
- console.log(chalk3.bold(`
34821
+ console.log(chalk4.bold(`
34431
34822
  Last handoff (${handoff.agent_id || "unknown"}, ${handoff.created_at.slice(0, 16).replace("T", " ")}):`));
34432
34823
  console.log(` ${handoff.summary}`);
34433
34824
  if (handoff.next_steps?.length) {
@@ -34435,7 +34826,7 @@ program2.command("context").description("Session start context: status, latest h
34435
34826
  console.log(` \u2192 ${s}`);
34436
34827
  }
34437
34828
  }
34438
- console.log(chalk3.dim(`
34829
+ console.log(chalk4.dim(`
34439
34830
  as_of: ${new Date().toISOString()}`));
34440
34831
  });
34441
34832
  program2.command("report-failure").description("Create a task from a test/build/typecheck failure and auto-assign it").requiredOption("--error <message>", "Error message or summary").option("--type <type>", "Failure type: test, build, typecheck, runtime, other", "test").option("--file <path>", "File where failure occurred").option("--stack <trace>", "Stack trace or detailed output").option("--title <title>", "Custom task title (auto-generated if omitted)").option("--priority <p>", "Priority: low, medium, high, critical").option("-j, --json", "Output as JSON").action(async (opts) => {
@@ -34474,11 +34865,11 @@ ${opts.stack.slice(0, 1500)}
34474
34865
  console.log(JSON.stringify({ task_id: task.id, short_id: task.short_id, title: task.title, assigned_to: assignResult.agent_name, method: assignResult.method }));
34475
34866
  return;
34476
34867
  }
34477
- console.log(chalk3.green(`\u2713 Created task ${task.short_id || task.id.slice(0, 8)}: ${task.title}`));
34868
+ console.log(chalk4.green(`\u2713 Created task ${task.short_id || task.id.slice(0, 8)}: ${task.title}`));
34478
34869
  if (assignResult.agent_name) {
34479
- console.log(chalk3.cyan(` Assigned to: ${assignResult.agent_name} (via ${assignResult.method})`));
34870
+ console.log(chalk4.cyan(` Assigned to: ${assignResult.agent_name} (via ${assignResult.method})`));
34480
34871
  if (assignResult.reason)
34481
- console.log(chalk3.dim(` Reason: ${assignResult.reason}`));
34872
+ console.log(chalk4.dim(` Reason: ${assignResult.reason}`));
34482
34873
  }
34483
34874
  });
34484
34875
  program2.action(async () => {
@@ -34512,7 +34903,7 @@ dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the conf
34512
34903
  if (useJson) {
34513
34904
  console.log(JSON.stringify({ error: msg }));
34514
34905
  } else {
34515
- console.error(chalk3.red(msg));
34906
+ console.error(chalk4.red(msg));
34516
34907
  }
34517
34908
  process.exit(1);
34518
34909
  }
@@ -34525,26 +34916,26 @@ dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the conf
34525
34916
  return;
34526
34917
  }
34527
34918
  if (result.applied.length > 0) {
34528
- console.log(chalk3.green(`Applied ${result.applied.length} migration(s): ${result.applied.join(", ")}`));
34919
+ console.log(chalk4.green(`Applied ${result.applied.length} migration(s): ${result.applied.join(", ")}`));
34529
34920
  }
34530
34921
  if (result.alreadyApplied.length > 0) {
34531
- console.log(chalk3.dim(`Already applied: ${result.alreadyApplied.length} migration(s)`));
34922
+ console.log(chalk4.dim(`Already applied: ${result.alreadyApplied.length} migration(s)`));
34532
34923
  }
34533
34924
  if (result.errors.length > 0) {
34534
34925
  for (const err of result.errors) {
34535
- console.error(chalk3.red(` Error: ${err}`));
34926
+ console.error(chalk4.red(` Error: ${err}`));
34536
34927
  }
34537
34928
  process.exit(1);
34538
34929
  }
34539
34930
  if (result.applied.length === 0 && result.errors.length === 0) {
34540
- console.log(chalk3.dim("Schema is up to date."));
34931
+ console.log(chalk4.dim("Schema is up to date."));
34541
34932
  }
34542
34933
  } catch (e) {
34543
34934
  const msg = e instanceof Error ? e.message : String(e);
34544
34935
  if (useJson) {
34545
34936
  console.log(JSON.stringify({ error: msg }));
34546
34937
  } else {
34547
- console.error(chalk3.red(`Migration failed: ${msg}`));
34938
+ console.error(chalk4.red(`Migration failed: ${msg}`));
34548
34939
  }
34549
34940
  process.exit(1);
34550
34941
  }
@@ -34602,34 +34993,34 @@ cloudCmd.command("status").description("Show cloud config, connection health, ma
34602
34993
  if (useJson) {
34603
34994
  console.log(JSON.stringify(info, null, 2));
34604
34995
  } else {
34605
- console.log(chalk3.bold("Cloud Status"));
34996
+ console.log(chalk4.bold("Cloud Status"));
34606
34997
  console.log(` Mode: ${info.mode}`);
34607
34998
  console.log(` Machine: ${machineId}`);
34608
34999
  console.log(` RDS Host: ${info.rds_host}`);
34609
35000
  if (info.postgresql)
34610
35001
  console.log(` PostgreSQL: ${info.postgresql}`);
34611
35002
  if (machines.length > 0) {
34612
- console.log(chalk3.bold(`
35003
+ console.log(chalk4.bold(`
34613
35004
  Machines`));
34614
35005
  for (const m of machines) {
34615
- const current = m.id === machineId ? chalk3.green(" (this)") : "";
35006
+ const current = m.id === machineId ? chalk4.green(" (this)") : "";
34616
35007
  console.log(` ${m.name}${current} \u2014 ${m.hostname || "?"} / ${m.platform || "?"} \u2014 last seen ${m.last_seen_at}`);
34617
35008
  }
34618
35009
  }
34619
35010
  const healthItems = info.sync_health.filter((s) => s.total > 0);
34620
35011
  if (healthItems.length > 0) {
34621
- console.log(chalk3.bold(`
35012
+ console.log(chalk4.bold(`
34622
35013
  Sync Health`));
34623
35014
  for (const s of healthItems) {
34624
35015
  const pct = s.total > 0 ? Math.round((s.total - s.unsynced) / s.total * 100) : 100;
34625
- const color = pct === 100 ? chalk3.green : pct > 50 ? chalk3.yellow : chalk3.red;
35016
+ const color = pct === 100 ? chalk4.green : pct > 50 ? chalk4.yellow : chalk4.red;
34626
35017
  console.log(` ${s.table}: ${color(`${pct}%`)} synced (${s.unsynced} unsynced / ${s.total} total)${s.last_synced ? ` \u2014 last: ${s.last_synced}` : ""}`);
34627
35018
  }
34628
35019
  }
34629
35020
  if (info.conflicts_unresolved > 0) {
34630
- console.log(chalk3.bold(`
35021
+ console.log(chalk4.bold(`
34631
35022
  Conflicts`));
34632
- console.log(` ${chalk3.yellow(`${info.conflicts_unresolved} unresolved`)} \u2014 run \`todos cloud conflicts\` to review`);
35023
+ console.log(` ${chalk4.yellow(`${info.conflicts_unresolved} unresolved`)} \u2014 run \`todos cloud conflicts\` to review`);
34633
35024
  }
34634
35025
  }
34635
35026
  } catch (e) {
@@ -34637,7 +35028,7 @@ Conflicts`));
34637
35028
  if (useJson) {
34638
35029
  console.log(JSON.stringify({ error: msg }));
34639
35030
  } else {
34640
- console.error(chalk3.red(msg));
35031
+ console.error(chalk4.red(msg));
34641
35032
  }
34642
35033
  }
34643
35034
  });
@@ -34654,7 +35045,7 @@ cloudCmd.command("push").description("Push local data to cloud PostgreSQL").opti
34654
35045
  if (useJson) {
34655
35046
  console.log(JSON.stringify({ error: msg }));
34656
35047
  } else {
34657
- console.error(chalk3.red(msg));
35048
+ console.error(chalk4.red(msg));
34658
35049
  }
34659
35050
  process.exit(1);
34660
35051
  }
@@ -34689,14 +35080,14 @@ cloudCmd.command("push").description("Push local data to cloud PostgreSQL").opti
34689
35080
  if (useJson) {
34690
35081
  console.log(JSON.stringify({ total, machine_id: machineId, tables: results }));
34691
35082
  } else {
34692
- console.log(chalk3.green(`Done. ${total} rows pushed (machine: ${machineId}).`));
35083
+ console.log(chalk4.green(`Done. ${total} rows pushed (machine: ${machineId}).`));
34693
35084
  }
34694
35085
  } catch (e) {
34695
35086
  const msg = e instanceof Error ? e.message : String(e);
34696
35087
  if (useJson) {
34697
35088
  console.log(JSON.stringify({ error: msg }));
34698
35089
  } else {
34699
- console.error(chalk3.red(msg));
35090
+ console.error(chalk4.red(msg));
34700
35091
  }
34701
35092
  process.exit(1);
34702
35093
  }
@@ -34713,7 +35104,7 @@ cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by
34713
35104
  if (useJson) {
34714
35105
  console.log(JSON.stringify({ error: msg }));
34715
35106
  } else {
34716
- console.error(chalk3.red(msg));
35107
+ console.error(chalk4.red(msg));
34717
35108
  }
34718
35109
  process.exit(1);
34719
35110
  }
@@ -34747,14 +35138,14 @@ cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by
34747
35138
  if (useJson) {
34748
35139
  console.log(JSON.stringify({ total, tables: results }));
34749
35140
  } else {
34750
- console.log(chalk3.green(`Done. ${total} rows pulled.`));
35141
+ console.log(chalk4.green(`Done. ${total} rows pulled.`));
34751
35142
  }
34752
35143
  } catch (e) {
34753
35144
  const msg = e instanceof Error ? e.message : String(e);
34754
35145
  if (useJson) {
34755
35146
  console.log(JSON.stringify({ error: msg }));
34756
35147
  } else {
34757
- console.error(chalk3.red(msg));
35148
+ console.error(chalk4.red(msg));
34758
35149
  }
34759
35150
  process.exit(1);
34760
35151
  }
@@ -34772,7 +35163,7 @@ cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote chan
34772
35163
  if (useJson) {
34773
35164
  console.log(JSON.stringify({ error: msg }));
34774
35165
  } else {
34775
- console.error(chalk3.red(msg));
35166
+ console.error(chalk4.red(msg));
34776
35167
  }
34777
35168
  process.exit(1);
34778
35169
  }
@@ -34788,7 +35179,7 @@ cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote chan
34788
35179
  tableList = [...new Set([...localTables, ...remoteTables])];
34789
35180
  }
34790
35181
  if (!useJson)
34791
- console.log(chalk3.bold("Pulling..."));
35182
+ console.log(chalk4.bold("Pulling..."));
34792
35183
  const pullResults = await syncPull2(cloud, local, {
34793
35184
  tables: tableList,
34794
35185
  onProgress: (p) => {
@@ -34803,7 +35194,7 @@ cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote chan
34803
35194
  } catch {}
34804
35195
  }
34805
35196
  if (!useJson)
34806
- console.log(chalk3.bold("Pushing..."));
35197
+ console.log(chalk4.bold("Pushing..."));
34807
35198
  const pushResults = await syncPush2(local, cloud, {
34808
35199
  tables: tableList,
34809
35200
  onProgress: (p) => {
@@ -34823,14 +35214,14 @@ cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote chan
34823
35214
  if (useJson) {
34824
35215
  console.log(JSON.stringify({ pulled: pullTotal, pushed: pushTotal, machine_id: machineId, tables: tableList.length }));
34825
35216
  } else {
34826
- console.log(chalk3.green(`Done. Pulled ${pullTotal}, pushed ${pushTotal} rows across ${tableList.length} table(s) (machine: ${machineId}).`));
35217
+ console.log(chalk4.green(`Done. Pulled ${pullTotal}, pushed ${pushTotal} rows across ${tableList.length} table(s) (machine: ${machineId}).`));
34827
35218
  }
34828
35219
  } catch (e) {
34829
35220
  const msg = e instanceof Error ? e.message : String(e);
34830
35221
  if (useJson) {
34831
35222
  console.log(JSON.stringify({ error: msg }));
34832
35223
  } else {
34833
- console.error(chalk3.red(msg));
35224
+ console.error(chalk4.red(msg));
34834
35225
  }
34835
35226
  process.exit(1);
34836
35227
  }
@@ -34851,17 +35242,17 @@ cloudCmd.command("conflicts").description("List sync conflicts detected during p
34851
35242
  return;
34852
35243
  }
34853
35244
  if (shown.length === 0) {
34854
- console.log(chalk3.dim(opts.resolved ? "No resolved conflicts." : "No unresolved conflicts."));
35245
+ console.log(chalk4.dim(opts.resolved ? "No resolved conflicts." : "No unresolved conflicts."));
34855
35246
  return;
34856
35247
  }
34857
35248
  console.log(`${conflicts.length} conflict(s)${conflicts.length > shown.length ? ` (showing ${shown.length})` : ""}:
34858
35249
  `);
34859
35250
  for (const c of shown) {
34860
- console.log(chalk3.yellow(`[${c.id}]`) + ` ${c.table_name}/${c.row_id}`);
35251
+ console.log(chalk4.yellow(`[${c.id}]`) + ` ${c.table_name}/${c.row_id}`);
34861
35252
  console.log(` Local: ${c.local_updated_at}`);
34862
35253
  console.log(` Remote: ${c.remote_updated_at}`);
34863
35254
  if (c.resolution)
34864
- console.log(` Resolution: ${chalk3.green(c.resolution)} at ${c.resolved_at}`);
35255
+ console.log(` Resolution: ${chalk4.green(c.resolution)} at ${c.resolved_at}`);
34865
35256
  console.log();
34866
35257
  }
34867
35258
  } catch (e) {
@@ -34869,9 +35260,10 @@ cloudCmd.command("conflicts").description("List sync conflicts detected during p
34869
35260
  if (useJson) {
34870
35261
  console.log(JSON.stringify({ error: msg }));
34871
35262
  } else {
34872
- console.error(chalk3.red(msg));
35263
+ console.error(chalk4.red(msg));
34873
35264
  }
34874
35265
  }
34875
35266
  });
34876
35267
  registerDispatchCommands(program2);
35268
+ registerMachineCommands(program2);
34877
35269
  program2.parse();