@hasna/todos 0.11.27 → 0.11.29

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
@@ -6,60 +6,39 @@ var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- function __accessProp(key) {
10
- return this[key];
11
- }
12
- var __toESMCache_node;
13
- var __toESMCache_esm;
14
9
  var __toESM = (mod, isNodeMode, target) => {
15
- var canCache = mod != null && typeof mod === "object";
16
- if (canCache) {
17
- var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
18
- var cached = cache.get(mod);
19
- if (cached)
20
- return cached;
21
- }
22
10
  target = mod != null ? __create(__getProtoOf(mod)) : {};
23
11
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
24
12
  for (let key of __getOwnPropNames(mod))
25
13
  if (!__hasOwnProp.call(to, key))
26
14
  __defProp(to, key, {
27
- get: __accessProp.bind(mod, key),
15
+ get: () => mod[key],
28
16
  enumerable: true
29
17
  });
30
- if (canCache)
31
- cache.set(mod, to);
32
18
  return to;
33
19
  };
20
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
34
21
  var __toCommonJS = (from) => {
35
- var entry = (__moduleCache ??= new WeakMap).get(from), desc;
22
+ var entry = __moduleCache.get(from), desc;
36
23
  if (entry)
37
24
  return entry;
38
25
  entry = __defProp({}, "__esModule", { value: true });
39
- if (from && typeof from === "object" || typeof from === "function") {
40
- for (var key of __getOwnPropNames(from))
41
- if (!__hasOwnProp.call(entry, key))
42
- __defProp(entry, key, {
43
- get: __accessProp.bind(from, key),
44
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
45
- });
46
- }
26
+ if (from && typeof from === "object" || typeof from === "function")
27
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
28
+ get: () => from[key],
29
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
30
+ }));
47
31
  __moduleCache.set(from, entry);
48
32
  return entry;
49
33
  };
50
- var __moduleCache;
51
34
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
52
- var __returnValue = (v) => v;
53
- function __exportSetter(name, newValue) {
54
- this[name] = __returnValue.bind(null, newValue);
55
- }
56
35
  var __export = (target, all) => {
57
36
  for (var name in all)
58
37
  __defProp(target, name, {
59
38
  get: all[name],
60
39
  enumerable: true,
61
40
  configurable: true,
62
- set: __exportSetter.bind(all, name)
41
+ set: (newValue) => all[name] = () => newValue
63
42
  });
64
43
  };
65
44
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -2444,6 +2423,32 @@ function ensureSchema(db) {
2444
2423
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_synced ON tasks(synced_at)");
2445
2424
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_projects_machine ON projects(machine_id)");
2446
2425
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_agents_machine ON agents(machine_id)");
2426
+ ensureTable("task_time_logs", `
2427
+ CREATE TABLE task_time_logs (
2428
+ id TEXT PRIMARY KEY,
2429
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
2430
+ agent_id TEXT,
2431
+ started_at TEXT,
2432
+ ended_at TEXT,
2433
+ minutes INTEGER NOT NULL,
2434
+ notes TEXT,
2435
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
2436
+ )`);
2437
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_task ON task_time_logs(task_id)");
2438
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_time_logs_agent ON task_time_logs(agent_id)");
2439
+ ensureColumn("tasks", "actual_minutes", "INTEGER");
2440
+ ensureTable("task_watchers", `
2441
+ CREATE TABLE task_watchers (
2442
+ id TEXT PRIMARY KEY,
2443
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
2444
+ agent_id TEXT NOT NULL,
2445
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
2446
+ UNIQUE(task_id, agent_id)
2447
+ )`);
2448
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_watchers_task ON task_watchers(task_id)");
2449
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_watchers_agent ON task_watchers(agent_id)");
2450
+ ensureColumn("task_dependencies", "external_project_id", "TEXT");
2451
+ ensureColumn("task_dependencies", "external_task_id", "TEXT");
2447
2452
  }
2448
2453
  function backfillTaskTags(db) {
2449
2454
  try {
@@ -3171,6 +3176,39 @@ var init_schema = __esm(() => {
3171
3176
  CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_short_id ON tasks(short_id, machine_id) WHERE short_id IS NOT NULL AND machine_id IS NOT NULL;
3172
3177
  CREATE INDEX IF NOT EXISTS idx_tasks_short_id_lookup ON tasks(short_id) WHERE short_id IS NOT NULL;
3173
3178
  INSERT OR IGNORE INTO _migrations (id) VALUES (44);
3179
+ `,
3180
+ `
3181
+ CREATE TABLE IF NOT EXISTS task_time_logs (
3182
+ id TEXT PRIMARY KEY,
3183
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
3184
+ agent_id TEXT,
3185
+ started_at TEXT,
3186
+ ended_at TEXT,
3187
+ minutes INTEGER NOT NULL,
3188
+ notes TEXT,
3189
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
3190
+ );
3191
+ CREATE INDEX IF NOT EXISTS idx_task_time_logs_task ON task_time_logs(task_id);
3192
+ CREATE INDEX IF NOT EXISTS idx_task_time_logs_agent ON task_time_logs(agent_id);
3193
+ ALTER TABLE tasks ADD COLUMN actual_minutes INTEGER;
3194
+ INSERT OR IGNORE INTO _migrations (id) VALUES (45);
3195
+ `,
3196
+ `
3197
+ CREATE TABLE IF NOT EXISTS task_watchers (
3198
+ id TEXT PRIMARY KEY,
3199
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
3200
+ agent_id TEXT NOT NULL,
3201
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
3202
+ UNIQUE(task_id, agent_id)
3203
+ );
3204
+ CREATE INDEX IF NOT EXISTS idx_task_watchers_task ON task_watchers(task_id);
3205
+ CREATE INDEX IF NOT EXISTS idx_task_watchers_agent ON task_watchers(agent_id);
3206
+ INSERT OR IGNORE INTO _migrations (id) VALUES (46);
3207
+ `,
3208
+ `
3209
+ ALTER TABLE task_dependencies ADD COLUMN external_project_id TEXT;
3210
+ ALTER TABLE task_dependencies ADD COLUMN external_task_id TEXT;
3211
+ INSERT OR IGNORE INTO _migrations (id) VALUES (47);
3174
3212
  `
3175
3213
  ];
3176
3214
  });
@@ -4161,6 +4199,7 @@ var init_recurrence = __esm(() => {
4161
4199
  // src/db/webhooks.ts
4162
4200
  var exports_webhooks = {};
4163
4201
  __export(exports_webhooks, {
4202
+ validateWebhookUrl: () => validateWebhookUrl,
4164
4203
  listWebhooks: () => listWebhooks,
4165
4204
  listDeliveries: () => listDeliveries,
4166
4205
  getWebhook: () => getWebhook,
@@ -4168,6 +4207,40 @@ __export(exports_webhooks, {
4168
4207
  deleteWebhook: () => deleteWebhook,
4169
4208
  createWebhook: () => createWebhook
4170
4209
  });
4210
+ function validateWebhookUrl(urlString) {
4211
+ try {
4212
+ const url = new URL(urlString);
4213
+ if (url.protocol !== "https:") {
4214
+ throw new Error("Webhook URLs must use HTTPS");
4215
+ }
4216
+ const hostname = url.hostname.toLowerCase();
4217
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "0.0.0.0") {
4218
+ throw new Error("Webhook URLs cannot target localhost");
4219
+ }
4220
+ if (hostname === "169.254.169.254" || hostname.startsWith("169.254.")) {
4221
+ throw new Error("Webhook URLs cannot target cloud metadata endpoints");
4222
+ }
4223
+ const privateRanges = [
4224
+ /^10\./,
4225
+ /^172\.(1[6-9]|2\d|3[01])\./,
4226
+ /^192\.168\./,
4227
+ /^127\./,
4228
+ /^169\.254\./,
4229
+ /^fc00:/i,
4230
+ /^fe80:/i
4231
+ ];
4232
+ for (const range of privateRanges) {
4233
+ if (range.test(hostname)) {
4234
+ throw new Error("Webhook URLs cannot target private IP ranges");
4235
+ }
4236
+ }
4237
+ } catch (e) {
4238
+ if (e instanceof Error && e.message.startsWith("Webhook URLs")) {
4239
+ throw e;
4240
+ }
4241
+ throw new Error(`Invalid webhook URL: ${urlString}`);
4242
+ }
4243
+ }
4171
4244
  function rowToWebhook(row) {
4172
4245
  return {
4173
4246
  ...row,
@@ -4181,6 +4254,7 @@ function rowToWebhook(row) {
4181
4254
  }
4182
4255
  function createWebhook(input, db) {
4183
4256
  const d = db || getDatabase();
4257
+ validateWebhookUrl(input.url);
4184
4258
  const id = uuid();
4185
4259
  d.run(`INSERT INTO webhooks (id, url, events, secret, project_id, task_list_id, agent_id, task_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
4186
4260
  id,
@@ -4779,7 +4853,9 @@ var init_checklists = __esm(() => {
4779
4853
  // src/db/tasks.ts
4780
4854
  var exports_tasks = {};
4781
4855
  __export(exports_tasks, {
4856
+ watchTask: () => watchTask,
4782
4857
  updateTask: () => updateTask,
4858
+ unwatchTask: () => unwatchTask,
4783
4859
  unlockTask: () => unlockTask,
4784
4860
  unarchiveTask: () => unarchiveTask,
4785
4861
  stealTask: () => stealTask,
@@ -4788,12 +4864,17 @@ __export(exports_tasks, {
4788
4864
  setTaskPriority: () => setTaskPriority,
4789
4865
  removeDependency: () => removeDependency,
4790
4866
  redistributeStaleTasks: () => redistributeStaleTasks,
4867
+ notifyWatchers: () => notifyWatchers,
4791
4868
  moveTask: () => moveTask,
4869
+ logTime: () => logTime,
4792
4870
  logCost: () => logCost,
4793
4871
  lockTask: () => lockTask,
4794
4872
  listTasks: () => listTasks,
4873
+ getTimeReport: () => getTimeReport,
4874
+ getTimeLogs: () => getTimeLogs,
4795
4875
  getTasksChangedSince: () => getTasksChangedSince,
4796
4876
  getTaskWithRelations: () => getTaskWithRelations,
4877
+ getTaskWatchers: () => getTaskWatchers,
4797
4878
  getTaskStats: () => getTaskStats,
4798
4879
  getTaskGraph: () => getTaskGraph,
4799
4880
  getTaskDependents: () => getTaskDependents,
@@ -5976,6 +6057,58 @@ function getOverdueTasks(projectId, db) {
5976
6057
  const rows = d.query(query).all(...params);
5977
6058
  return rows.map(rowToTask);
5978
6059
  }
6060
+ function logTime(input, db) {
6061
+ const d = db || getDatabase();
6062
+ const id = uuid();
6063
+ const ts = now();
6064
+ d.run(`INSERT INTO task_time_logs (id, task_id, agent_id, minutes, started_at, ended_at, notes, created_at)
6065
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, input.task_id, input.agent_id || null, input.minutes, input.started_at || null, input.ended_at || null, input.notes || null, ts]);
6066
+ return { id, task_id: input.task_id, agent_id: input.agent_id || null, minutes: input.minutes, started_at: input.started_at || null, ended_at: input.ended_at || null, notes: input.notes || null, created_at: ts };
6067
+ }
6068
+ function getTimeLogs(taskId, db) {
6069
+ const d = db || getDatabase();
6070
+ return d.query(`SELECT * FROM task_time_logs WHERE task_id = ? ORDER BY created_at DESC`).all(taskId);
6071
+ }
6072
+ function getTimeReport(opts, db) {
6073
+ const d = db || getDatabase();
6074
+ let query = `SELECT t.id as task_id, t.title, t.estimated_minutes, t.actual_minutes FROM tasks t WHERE t.status = 'completed'`;
6075
+ const params = [];
6076
+ if (opts?.project_id) {
6077
+ query += ` AND t.project_id = ?`;
6078
+ params.push(opts.project_id);
6079
+ }
6080
+ if (opts?.agent_id) {
6081
+ query += ` AND t.assigned_to = ?`;
6082
+ params.push(opts.agent_id);
6083
+ }
6084
+ if (opts?.since) {
6085
+ query += ` AND t.completed_at >= ?`;
6086
+ params.push(opts.since);
6087
+ }
6088
+ const rows = d.query(query).all(...params);
6089
+ return rows.map((row) => ({ ...row, time_logs: getTimeLogs(row.task_id, d) }));
6090
+ }
6091
+ function watchTask(taskId, agentId, db) {
6092
+ const d = db || getDatabase();
6093
+ const id = uuid();
6094
+ const ts = now();
6095
+ d.run(`INSERT OR IGNORE INTO task_watchers (id, task_id, agent_id, created_at) VALUES (?, ?, ?, ?)`, [id, taskId, agentId, ts]);
6096
+ const existing = d.query(`SELECT * FROM task_watchers WHERE task_id = ? AND agent_id = ?`).get(taskId, agentId);
6097
+ return existing;
6098
+ }
6099
+ function unwatchTask(taskId, agentId, db) {
6100
+ const d = db || getDatabase();
6101
+ const result = d.run(`DELETE FROM task_watchers WHERE task_id = ? AND agent_id = ?`, [taskId, agentId]);
6102
+ return result.changes > 0;
6103
+ }
6104
+ function getTaskWatchers(taskId, db) {
6105
+ const d = db || getDatabase();
6106
+ return d.query(`SELECT * FROM task_watchers WHERE task_id = ?`).all(taskId);
6107
+ }
6108
+ function notifyWatchers(taskId, event, data, db) {
6109
+ const watchers = getTaskWatchers(taskId, db);
6110
+ dispatchWebhook(`task.watcher.${event}`, { task_id: taskId, watchers: watchers.map((w) => w.agent_id), ...data }, db).catch(() => {});
6111
+ }
5979
6112
  var init_tasks = __esm(() => {
5980
6113
  init_types();
5981
6114
  init_database();
@@ -6062,6 +6195,9 @@ function registerAgent(input, db) {
6062
6195
  if (callerHasNoSession && existingHasActiveSession) {
6063
6196
  return buildConflictError(existing, lastSeenMs, input.pool, d);
6064
6197
  }
6198
+ if (input.project_id && existing.session_id && isActive && existing.active_project_id && existing.active_project_id !== input.project_id) {
6199
+ return buildConflictError(existing, lastSeenMs, input.pool, d);
6200
+ }
6065
6201
  }
6066
6202
  const updates = ["last_seen_at = ?", "status = 'active'"];
6067
6203
  const params = [now()];
@@ -6077,14 +6213,18 @@ function registerAgent(input, db) {
6077
6213
  updates.push("description = ?");
6078
6214
  params.push(input.description);
6079
6215
  }
6216
+ if (input.project_id && input.session_id) {
6217
+ updates.push("active_project_id = ?");
6218
+ params.push(input.project_id);
6219
+ }
6080
6220
  params.push(existing.id);
6081
6221
  d.run(`UPDATE agents SET ${updates.join(", ")} WHERE id = ?`, params);
6082
6222
  return getAgent(existing.id, d);
6083
6223
  }
6084
6224
  const id = shortUuid();
6085
6225
  const timestamp = now();
6086
- d.run(`INSERT INTO agents (id, name, description, role, title, level, permissions, capabilities, reports_to, org_id, metadata, created_at, last_seen_at, session_id, working_dir)
6087
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
6226
+ d.run(`INSERT INTO agents (id, name, description, role, title, level, permissions, capabilities, reports_to, org_id, metadata, created_at, last_seen_at, session_id, working_dir, active_project_id)
6227
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
6088
6228
  id,
6089
6229
  normalizedName,
6090
6230
  input.description || null,
@@ -6099,7 +6239,8 @@ function registerAgent(input, db) {
6099
6239
  timestamp,
6100
6240
  timestamp,
6101
6241
  input.session_id || null,
6102
- input.working_dir || null
6242
+ input.working_dir || null,
6243
+ input.project_id && input.session_id ? input.project_id : null
6103
6244
  ]);
6104
6245
  return getAgent(id, d);
6105
6246
  }
@@ -11889,7 +12030,7 @@ var init_zod = __esm(() => {
11889
12030
  init_external();
11890
12031
  });
11891
12032
 
11892
- // node_modules/@hasna/cloud/dist/index.js
12033
+ // ../../../../node_modules/@hasna/cloud/dist/index.js
11893
12034
  var exports_dist = {};
11894
12035
  __export(exports_dist, {
11895
12036
  translateSql: () => translateSql,
@@ -11984,11 +12125,11 @@ import { join as join52 } from "path";
11984
12125
  import { join as join62, dirname as dirname2 } from "path";
11985
12126
  import { existsSync as existsSync62, writeFileSync as writeFileSync22, unlinkSync, mkdirSync as mkdirSync32 } from "fs";
11986
12127
  import { homedir as homedir5, platform } from "os";
11987
- function __accessProp2(key) {
12128
+ function __accessProp(key) {
11988
12129
  return this[key];
11989
12130
  }
11990
- function __exportSetter2(name, newValue) {
11991
- this[name] = __returnValue2.bind(null, newValue);
12131
+ function __exportSetter(name, newValue) {
12132
+ this[name] = __returnValue.bind(null, newValue);
11992
12133
  }
11993
12134
  function translateSql(sql, dialect) {
11994
12135
  if (dialect === "sqlite")
@@ -14445,7 +14586,7 @@ async function ensureAllPgDatabases() {
14445
14586
  }
14446
14587
  return results;
14447
14588
  }
14448
- function registerCloudTools(server, serviceName) {
14589
+ function registerCloudTools(server, serviceName, opts = {}) {
14449
14590
  server.tool(`${serviceName}_cloud_status`, "Show cloud configuration and connection health", {}, async () => {
14450
14591
  const config = getCloudConfig();
14451
14592
  const lines = [
@@ -14478,8 +14619,13 @@ function registerCloudTools(server, serviceName) {
14478
14619
  isError: true
14479
14620
  };
14480
14621
  }
14481
- const local = new SqliteAdapter(getDbPath2(serviceName));
14622
+ const local = new SqliteAdapter(opts.dbPath ?? getDbPath2(serviceName));
14482
14623
  const cloud = new PgAdapterAsync(getConnectionString(serviceName));
14624
+ if (opts.migrations?.length) {
14625
+ for (const sql of opts.migrations) {
14626
+ await cloud.run(sql);
14627
+ }
14628
+ }
14483
14629
  const tableList = tablesStr ? tablesStr.split(",").map((t) => t.trim()) : listSqliteTables(local);
14484
14630
  const results = await syncPush(local, cloud, { tables: tableList });
14485
14631
  local.close();
@@ -14501,7 +14647,7 @@ function registerCloudTools(server, serviceName) {
14501
14647
  isError: true
14502
14648
  };
14503
14649
  }
14504
- const local = new SqliteAdapter(getDbPath2(serviceName));
14650
+ const local = new SqliteAdapter(opts.dbPath ?? getDbPath2(serviceName));
14505
14651
  const cloud = new PgAdapterAsync(getConnectionString(serviceName));
14506
14652
  let tableList;
14507
14653
  if (tablesStr) {
@@ -14624,10 +14770,10 @@ function registerCloudCommands(program2, serviceName) {
14624
14770
  }
14625
14771
  });
14626
14772
  }
14627
- var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2, __toESMCache_node2, __toESMCache_esm2, __toESM2 = (mod, isNodeMode, target) => {
14773
+ var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2, __toESMCache_node, __toESMCache_esm, __toESM2 = (mod, isNodeMode, target) => {
14628
14774
  var canCache = mod != null && typeof mod === "object";
14629
14775
  if (canCache) {
14630
- var cache = isNodeMode ? __toESMCache_node2 ??= new WeakMap : __toESMCache_esm2 ??= new WeakMap;
14776
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
14631
14777
  var cached2 = cache.get(mod);
14632
14778
  if (cached2)
14633
14779
  return cached2;
@@ -14637,19 +14783,19 @@ var __create2, __getProtoOf2, __defProp2, __getOwnPropNames2, __hasOwnProp2, __t
14637
14783
  for (let key of __getOwnPropNames2(mod))
14638
14784
  if (!__hasOwnProp2.call(to, key))
14639
14785
  __defProp2(to, key, {
14640
- get: __accessProp2.bind(mod, key),
14786
+ get: __accessProp.bind(mod, key),
14641
14787
  enumerable: true
14642
14788
  });
14643
14789
  if (canCache)
14644
14790
  cache.set(mod, to);
14645
14791
  return to;
14646
- }, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports), __returnValue2 = (v) => v, __export2 = (target, all) => {
14792
+ }, __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports), __returnValue = (v) => v, __export2 = (target, all) => {
14647
14793
  for (var name in all)
14648
14794
  __defProp2(target, name, {
14649
14795
  get: all[name],
14650
14796
  enumerable: true,
14651
14797
  configurable: true,
14652
- set: __exportSetter2.bind(all, name)
14798
+ set: __exportSetter.bind(all, name)
14653
14799
  });
14654
14800
  }, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), __require2, require_postgres_array, require_arrayParser, require_postgres_date, require_mutable, require_postgres_interval, require_postgres_bytea, require_textParsers, require_pg_int8, require_binaryParsers, require_builtins, require_pg_types, require_defaults, require_utils, require_utils_legacy, require_utils_webcrypto, require_utils2, require_cert_signatures, require_sasl, require_type_overrides, require_pg_connection_string, require_connection_parameters, require_result, require_query, require_messages, require_buffer_writer, require_serializer, require_buffer_reader, require_parser, require_dist, require_empty, require_stream, require_connection, require_split2, require_helper, require_lib, require_client, require_pg_pool, require_query2, require_client2, require_lib2, import_lib, Client, Pool, Connection, types2, Query, DatabaseError, escapeIdentifier, escapeLiteral, Result, TypeOverrides, defaults, esm_default, init_esm, init_adapter, util3, objectUtil2, ZodParsedType2, getParsedType2 = (data) => {
14655
14801
  const t = typeof data;
@@ -23710,7 +23856,8 @@ function registerWebhookTools(server, { shouldRegisterTool, formatError }) {
23710
23856
  task_id: exports_external.string().optional().describe("Only fire for events on this specific task")
23711
23857
  }, async (params) => {
23712
23858
  try {
23713
- const { createWebhook: createWebhook2 } = await Promise.resolve().then(() => (init_webhooks(), exports_webhooks));
23859
+ const { createWebhook: createWebhook2, validateWebhookUrl: validateWebhookUrl2 } = await Promise.resolve().then(() => (init_webhooks(), exports_webhooks));
23860
+ validateWebhookUrl2(params.url);
23714
23861
  const wh = createWebhook2(params);
23715
23862
  const scope = [wh.project_id && `project:${wh.project_id}`, wh.task_list_id && `list:${wh.task_list_id}`, wh.agent_id && `agent:${wh.agent_id}`, wh.task_id && `task:${wh.task_id}`].filter(Boolean).join(", ");
23716
23863
  return { content: [{ type: "text", text: `Webhook created: ${wh.id.slice(0, 8)} | ${wh.url} | events: ${wh.events.length === 0 ? "all" : wh.events.join(",")}${scope ? ` | scope: ${scope}` : ""}` }] };
@@ -25979,6 +26126,39 @@ var init_pg_migrations = __esm(() => {
25979
26126
  CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_short_id ON tasks(short_id, machine_id) WHERE short_id IS NOT NULL AND machine_id IS NOT NULL;
25980
26127
  CREATE INDEX IF NOT EXISTS idx_tasks_short_id_lookup ON tasks(short_id) WHERE short_id IS NOT NULL;
25981
26128
  INSERT INTO _migrations (id) VALUES (40) ON CONFLICT DO NOTHING;
26129
+ `,
26130
+ `
26131
+ CREATE TABLE IF NOT EXISTS task_time_logs (
26132
+ id TEXT PRIMARY KEY,
26133
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
26134
+ agent_id TEXT,
26135
+ started_at TIMESTAMPTZ,
26136
+ ended_at TIMESTAMPTZ,
26137
+ minutes INTEGER NOT NULL,
26138
+ notes TEXT,
26139
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
26140
+ );
26141
+ CREATE INDEX IF NOT EXISTS idx_task_time_logs_task ON task_time_logs(task_id);
26142
+ CREATE INDEX IF NOT EXISTS idx_task_time_logs_agent ON task_time_logs(agent_id);
26143
+ ALTER TABLE tasks ADD COLUMN actual_minutes INTEGER;
26144
+ INSERT INTO _migrations (id) VALUES (41) ON CONFLICT DO NOTHING;
26145
+ `,
26146
+ `
26147
+ CREATE TABLE IF NOT EXISTS task_watchers (
26148
+ id TEXT PRIMARY KEY,
26149
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
26150
+ agent_id TEXT NOT NULL,
26151
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
26152
+ UNIQUE(task_id, agent_id)
26153
+ );
26154
+ CREATE INDEX IF NOT EXISTS idx_task_watchers_task ON task_watchers(task_id);
26155
+ CREATE INDEX IF NOT EXISTS idx_task_watchers_agent ON task_watchers(agent_id);
26156
+ INSERT INTO _migrations (id) VALUES (42) ON CONFLICT DO NOTHING;
26157
+ `,
26158
+ `
26159
+ ALTER TABLE task_dependencies ADD COLUMN external_project_id TEXT;
26160
+ ALTER TABLE task_dependencies ADD COLUMN external_task_id TEXT;
26161
+ INSERT INTO _migrations (id) VALUES (43) ON CONFLICT DO NOTHING;
25982
26162
  `
25983
26163
  ];
25984
26164
  });
@@ -27968,7 +28148,7 @@ Blocks:
27968
28148
  }
27969
28149
  if (shouldRegisterTool("bulk_create_tasks")) {
27970
28150
  server.tool("bulk_create_tasks", "Create multiple tasks atomically with dependency support.", {
27971
- tasks: exports_external.array(exports_external.object({
28151
+ tasks: exports_external.preprocess((val) => typeof val === "string" ? JSON.parse(val) : val, exports_external.array(exports_external.object({
27972
28152
  temp_id: exports_external.string().optional(),
27973
28153
  title: exports_external.string(),
27974
28154
  description: exports_external.string().optional(),
@@ -27982,7 +28162,7 @@ Blocks:
27982
28162
  tags: exports_external.array(exports_external.string()).optional(),
27983
28163
  estimated_minutes: exports_external.number().optional(),
27984
28164
  depends_on_temp_ids: exports_external.array(exports_external.string()).optional()
27985
- })),
28165
+ }))),
27986
28166
  project_id: exports_external.string().optional(),
27987
28167
  plan_id: exports_external.string().optional(),
27988
28168
  task_list_id: exports_external.string().optional()
@@ -29718,6 +29898,143 @@ ${lines.join(`
29718
29898
  }
29719
29899
  });
29720
29900
  }
29901
+ if (shouldRegisterTool("log_time")) {
29902
+ server.tool("log_time", "Log time spent on a task.", {
29903
+ task_id: exports_external.string().describe("Task ID to log time against"),
29904
+ minutes: exports_external.number().min(1).describe("Minutes spent"),
29905
+ agent_id: exports_external.string().optional().describe("Agent logging the time"),
29906
+ started_at: exports_external.string().optional().describe("ISO timestamp when work started"),
29907
+ ended_at: exports_external.string().optional().describe("ISO timestamp when work ended"),
29908
+ notes: exports_external.string().optional().describe("Notes about what was done")
29909
+ }, async ({ task_id, minutes, agent_id, started_at, ended_at, notes }) => {
29910
+ try {
29911
+ const { logTime: logTime2 } = (init_tasks(), __toCommonJS(exports_tasks));
29912
+ logTime2({ task_id: resolveId(task_id), minutes, agent_id, started_at, ended_at, notes });
29913
+ return { content: [{ type: "text", text: `Logged ${minutes} min on task ${task_id.slice(0, 8)}` }] };
29914
+ } catch (e) {
29915
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
29916
+ }
29917
+ });
29918
+ }
29919
+ if (shouldRegisterTool("get_time_report")) {
29920
+ server.tool("get_time_report", "Get time tracking report: actual vs estimated minutes for completed tasks.", {
29921
+ project_id: exports_external.string().optional().describe("Filter by project"),
29922
+ agent_id: exports_external.string().optional().describe("Filter by assignee"),
29923
+ since: exports_external.string().optional().describe("ISO date \u2014 only tasks completed after this date")
29924
+ }, async ({ project_id, agent_id, since }) => {
29925
+ try {
29926
+ const { getTimeReport: getTimeReport2 } = (init_tasks(), __toCommonJS(exports_tasks));
29927
+ const report = getTimeReport2({ project_id: project_id ? resolveId(project_id, "projects") : undefined, agent_id, since });
29928
+ if (report.length === 0)
29929
+ return { content: [{ type: "text", text: "No completed tasks found." }] };
29930
+ const lines = report.map((r) => {
29931
+ const est = r.estimated_minutes ?? "?";
29932
+ const actual = r.actual_minutes ?? "?";
29933
+ const diff = r.estimated_minutes != null && r.actual_minutes != null ? ` (${r.actual_minutes - r.estimated_minutes >= 0 ? "+" : ""}${r.actual_minutes - r.estimated_minutes})` : "";
29934
+ return `${r.title.slice(0, 50)}: estimated ${est}min, actual ${actual}min${diff}`;
29935
+ });
29936
+ return { content: [{ type: "text", text: `Time Report:
29937
+ ${lines.join(`
29938
+ `)}` }] };
29939
+ } catch (e) {
29940
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
29941
+ }
29942
+ });
29943
+ }
29944
+ if (shouldRegisterTool("watch_task")) {
29945
+ server.tool("watch_task", "Subscribe to notifications for a task.", {
29946
+ task_id: exports_external.string().describe("Task ID to watch"),
29947
+ agent_id: exports_external.string().optional().describe("Agent subscribing (defaults to context agent)")
29948
+ }, async ({ task_id, agent_id }) => {
29949
+ try {
29950
+ const { watchTask: watchTask2 } = (init_tasks(), __toCommonJS(exports_tasks));
29951
+ watchTask2(resolveId(task_id), agent_id || "");
29952
+ return { content: [{ type: "text", text: `Now watching task ${task_id.slice(0, 8)}` }] };
29953
+ } catch (e) {
29954
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
29955
+ }
29956
+ });
29957
+ }
29958
+ if (shouldRegisterTool("unwatch_task")) {
29959
+ server.tool("unwatch_task", "Unsubscribe from notifications for a task.", {
29960
+ task_id: exports_external.string().describe("Task ID to unwatch"),
29961
+ agent_id: exports_external.string().optional().describe("Agent unsubscribing (defaults to context agent)")
29962
+ }, async ({ task_id, agent_id }) => {
29963
+ try {
29964
+ const { unwatchTask: unwatchTask2 } = (init_tasks(), __toCommonJS(exports_tasks));
29965
+ unwatchTask2(resolveId(task_id), agent_id || "");
29966
+ return { content: [{ type: "text", text: `Stopped watching task ${task_id.slice(0, 8)}` }] };
29967
+ } catch (e) {
29968
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
29969
+ }
29970
+ });
29971
+ }
29972
+ if (shouldRegisterTool("get_task_watchers")) {
29973
+ server.tool("get_task_watchers", "List agents watching a task.", {
29974
+ task_id: exports_external.string().describe("Task ID")
29975
+ }, async ({ task_id }) => {
29976
+ try {
29977
+ const { getTaskWatchers: getTaskWatchers2 } = (init_tasks(), __toCommonJS(exports_tasks));
29978
+ const watchers = getTaskWatchers2(resolveId(task_id));
29979
+ if (watchers.length === 0)
29980
+ return { content: [{ type: "text", text: "No watchers." }] };
29981
+ return { content: [{ type: "text", text: `Watching (${watchers.length}): ${watchers.map((w) => w.agent_id).join(", ")}` }] };
29982
+ } catch (e) {
29983
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
29984
+ }
29985
+ });
29986
+ }
29987
+ if (shouldRegisterTool("todos_retro")) {
29988
+ server.tool("todos_retro", "Post-completion retrospective: stats on completed tasks, low-confidence completions, avg time vs estimate, and patterns.", {
29989
+ project_id: exports_external.string().optional().describe("Filter by project"),
29990
+ plan_id: exports_external.string().optional().describe("Filter by plan"),
29991
+ task_list_id: exports_external.string().optional().describe("Filter by task list"),
29992
+ since: exports_external.string().optional().describe("ISO date \u2014 only tasks completed after this date"),
29993
+ agent_id: exports_external.string().optional().describe("Filter by assignee")
29994
+ }, async ({ project_id, plan_id, task_list_id, since, agent_id }) => {
29995
+ try {
29996
+ const { listTasks: listTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
29997
+ const { patrolTasks: patrolTasks2 } = (init_patrol(), __toCommonJS(exports_patrol));
29998
+ const completed = listTasks2({ status: "completed", project_id, plan_id, task_list_id, assigned_to: agent_id, limit: 500 }, undefined);
29999
+ const filtered = since ? completed.filter((t) => t.completed_at && t.completed_at >= since) : completed;
30000
+ const total = filtered.length;
30001
+ const lowConf = filtered.filter((t) => t.confidence != null && t.confidence < 0.7).length;
30002
+ const withEstimate = filtered.filter((t) => t.estimated_minutes != null && t.actual_minutes != null);
30003
+ const avgDiff = withEstimate.length > 0 ? withEstimate.reduce((acc, t) => acc + (t.actual_minutes - t.estimated_minutes), 0) / withEstimate.length : 0;
30004
+ const patrolResult = patrolTasks2({ project_id: project_id ? resolveId(project_id, "projects") : undefined });
30005
+ const stuck = patrolResult.issues.filter((i) => i.type === "stuck").length;
30006
+ const lines = [
30007
+ `Retro (${total} completed tasks${since ? ` since ${since}` : ""})`,
30008
+ `Low confidence: ${lowConf}/${total}`,
30009
+ `Avg time vs estimate: ${avgDiff >= 0 ? "+" : ""}${avgDiff.toFixed(1)}min`,
30010
+ `Currently stuck: ${stuck}`
30011
+ ];
30012
+ return { content: [{ type: "text", text: lines.join(`
30013
+ `) }] };
30014
+ } catch (e) {
30015
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
30016
+ }
30017
+ });
30018
+ }
30019
+ if (shouldRegisterTool("todos_inbox")) {
30020
+ server.tool("todos_inbox", "Get unassigned tasks (GTD inbox) \u2014 tasks with no assignee, not yet started.", {
30021
+ project_id: exports_external.string().optional().describe("Filter by project"),
30022
+ limit: exports_external.number().optional().describe("Max results (default: 20)")
30023
+ }, async ({ project_id, limit }) => {
30024
+ try {
30025
+ const { listTasks: listTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
30026
+ const tasks = listTasks2({ status: "pending", project_id, assigned_to: "", limit: limit || 20 }, undefined);
30027
+ if (tasks.length === 0)
30028
+ return { content: [{ type: "text", text: "Inbox is empty." }] };
30029
+ const lines = tasks.map((t) => `[${t.priority}] ${t.title.slice(0, 60)} (${t.id.slice(0, 8)})`);
30030
+ return { content: [{ type: "text", text: `Inbox (${tasks.length}):
30031
+ ${lines.join(`
30032
+ `)}` }] };
30033
+ } catch (e) {
30034
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
30035
+ }
30036
+ });
30037
+ }
29721
30038
  if (shouldRegisterTool("get_agent_metrics")) {
29722
30039
  server.tool("get_agent_metrics", "Get performance metrics for an agent: completion rate, speed, confidence, review scores.", {
29723
30040
  agent_id: exports_external.string().describe("Agent ID or name"),
@@ -32779,7 +33096,7 @@ function formatTaskLine(t) {
32779
33096
  const plan = t.plan_id ? chalk3.magenta(` [plan:${t.plan_id.slice(0, 8)}]`) : "";
32780
33097
  return `${chalk3.dim(t.id.slice(0, 8))} ${statusFn(t.status.padEnd(11))} ${priorityFn(t.priority.padEnd(8))} ${t.title}${assigned}${lock}${tags}${plan}`;
32781
33098
  }
32782
- program2.name("todos").description("Universal task management for AI coding agents").version(getPackageVersion()).option("--project <path>", "Project path").option("--json", "Output as JSON").option("--agent <name>", "Agent name").option("--session <id>", "Session ID");
33099
+ 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");
32783
33100
  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) => {
32784
33101
  const globalOpts = program2.opts();
32785
33102
  const projectId = autoProject(globalOpts);
@@ -32836,6 +33153,16 @@ program2.command("list").description("List tasks").option("-s, --status <status>
32836
33153
  const projectId = autoProject(globalOpts);
32837
33154
  const hasAssignedFilter = Boolean(opts.assigned || opts.agentName);
32838
33155
  const hasExplicitProjectFilter = Boolean(globalOpts.project || opts.projectName);
33156
+ const allowedSortFields = new Set(["updated", "created", "priority", "status"]);
33157
+ if (opts.sort && !allowedSortFields.has(opts.sort)) {
33158
+ console.error(chalk3.red(`Invalid --sort value: ${opts.sort}. Allowed values: updated, created, priority, status.`));
33159
+ process.exit(1);
33160
+ }
33161
+ const allowedFormats = new Set(["table", "compact", "csv", "json"]);
33162
+ if (opts.format && !allowedFormats.has(opts.format)) {
33163
+ console.error(chalk3.red(`Invalid --format value: ${opts.format}. Allowed values: table, compact, csv, json.`));
33164
+ process.exit(1);
33165
+ }
32839
33166
  const filter = {};
32840
33167
  if (projectId && !(hasAssignedFilter && !hasExplicitProjectFilter)) {
32841
33168
  filter["project_id"] = projectId;
@@ -32875,8 +33202,14 @@ program2.command("list").description("List tasks").option("-s, --status <status>
32875
33202
  }
32876
33203
  if (opts.recurring)
32877
33204
  filter["has_recurrence"] = true;
32878
- if (opts.limit)
32879
- filter["limit"] = parseInt(opts.limit, 10);
33205
+ if (opts.limit !== undefined) {
33206
+ const parsedLimit = Number.parseInt(String(opts.limit), 10);
33207
+ if (!Number.isInteger(parsedLimit) || parsedLimit <= 0) {
33208
+ console.error(chalk3.red(`Invalid --limit value: ${opts.limit}. Must be a positive integer.`));
33209
+ process.exit(1);
33210
+ }
33211
+ filter["limit"] = parsedLimit;
33212
+ }
32880
33213
  let tasks = listTasks(filter);
32881
33214
  if (opts.dueToday) {
32882
33215
  const todayEnd = new Date;
@@ -33877,7 +34210,7 @@ program2.command("projects").description("List and manage projects").option("--a
33877
34210
  console.log(`${chalk3.dim(p.id.slice(0, 8))} ${chalk3.bold(p.name)} ${chalk3.dim(p.path)}${taskList}${p.description ? ` - ${p.description}` : ""}`);
33878
34211
  }
33879
34212
  });
33880
- 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("--json", "Output as JSON").action((idOrSlug, newSlug, opts) => {
34213
+ 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) => {
33881
34214
  const globalOpts = program2.opts();
33882
34215
  const useJson = opts.json || globalOpts.json;
33883
34216
  try {
@@ -33907,7 +34240,7 @@ program2.command("project-rename <id-or-slug> <new-slug>").description("Rename a
33907
34240
  }
33908
34241
  });
33909
34242
  var projectsPathCmd = program2.command("projects-path").description("Manage machine-local path overrides for projects");
33910
- projectsPathCmd.command("set <project-id> <path>").description("Set the local path for a project on this machine").option("--json", "Output as JSON").action((projectId, projectPath, opts) => {
34243
+ projectsPathCmd.command("set <project-id> <path>").description("Set the local path for a project on this machine").option("-j, --json", "Output as JSON").action((projectId, projectPath, opts) => {
33911
34244
  const globalOpts = program2.opts();
33912
34245
  const useJson = opts.json || globalOpts.json;
33913
34246
  try {
@@ -33929,7 +34262,7 @@ projectsPathCmd.command("set <project-id> <path>").description("Set the local pa
33929
34262
  process.exit(1);
33930
34263
  }
33931
34264
  });
33932
- projectsPathCmd.command("list <project-id>").description("List all machine path overrides for a project").option("--json", "Output as JSON").action((projectId, opts) => {
34265
+ projectsPathCmd.command("list <project-id>").description("List all machine path overrides for a project").option("-j, --json", "Output as JSON").action((projectId, opts) => {
33933
34266
  const globalOpts = program2.opts();
33934
34267
  const useJson = opts.json || globalOpts.json;
33935
34268
  try {
@@ -34581,7 +34914,7 @@ program2.command("agent-update <name>").alias("agents-update").description("Upda
34581
34914
  handleError(e);
34582
34915
  }
34583
34916
  });
34584
- program2.command("agent <name>").description("Show all info about an agent: tasks, status, last seen, stats").option("--json", "Output as JSON").action((name, opts) => {
34917
+ program2.command("agent <name>").description("Show all info about an agent: tasks, status, last seen, stats").option("-j, --json", "Output as JSON").action((name, opts) => {
34585
34918
  const globalOpts = program2.opts();
34586
34919
  const { getAgentByName: findByName } = (init_agents(), __toCommonJS(exports_agents));
34587
34920
  const agent = findByName(name);
@@ -35014,7 +35347,7 @@ program2.command("dashboard").description("Live-updating dashboard showing proje
35014
35347
  const projectId = opts.project || autoProject(globalOpts) || undefined;
35015
35348
  render2(React.createElement(Dashboard2, { projectId, refreshMs: parseInt(opts.refresh, 10) }));
35016
35349
  });
35017
- program2.command("next").description("Show the best pending task to work on next").option("--agent <id>", "Prefer tasks assigned to this agent").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (opts) => {
35350
+ program2.command("next").description("Show the best pending task to work on next").option("--agent <id>", "Prefer tasks assigned to this agent").option("--project <id>", "Filter to project").option("-j, --json", "Output as JSON").action(async (opts) => {
35018
35351
  const globalOpts = program2.opts();
35019
35352
  const db = getDatabase();
35020
35353
  const filters = {};
@@ -35038,7 +35371,7 @@ program2.command("next").description("Show the best pending task to work on next
35038
35371
  if (task.description)
35039
35372
  console.log(chalk3.dim(` ${task.description.slice(0, 100)}`));
35040
35373
  });
35041
- program2.command("claim <agent>").description("Atomically claim the best pending task for an agent").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (agent, opts) => {
35374
+ 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) => {
35042
35375
  const db = getDatabase();
35043
35376
  const filters = {};
35044
35377
  if (opts.project)
@@ -35068,7 +35401,7 @@ program2.command("steal <agent>").description("Work-stealing: take the highest-p
35068
35401
  }
35069
35402
  console.log(chalk3.green(`Stolen: ${task.short_id || task.id.slice(0, 8)} | ${task.priority} | ${task.title}`));
35070
35403
  });
35071
- 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("--json", "Output as JSON").action(async (opts) => {
35404
+ 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) => {
35072
35405
  const db = getDatabase();
35073
35406
  const filters = {};
35074
35407
  if (opts.project)
@@ -35212,7 +35545,7 @@ Blocked:`));
35212
35545
  }
35213
35546
  console.log();
35214
35547
  });
35215
- program2.command("fail <id>").description("Mark a task as failed with optional reason and retry").option("--reason <text>", "Why it failed").option("--agent <id>", "Agent reporting the failure").option("--retry", "Auto-create a retry copy").option("--json", "Output as JSON").action(async (id, opts) => {
35548
+ program2.command("fail <id>").description("Mark a task as failed with optional reason and retry").option("--reason <text>", "Why it failed").option("--agent <id>", "Agent reporting the failure").option("--retry", "Auto-create a retry copy").option("-j, --json", "Output as JSON").action(async (id, opts) => {
35216
35549
  const db = getDatabase();
35217
35550
  const resolvedId = resolvePartialId(db, "tasks", id);
35218
35551
  if (!resolvedId) {
@@ -35230,7 +35563,7 @@ program2.command("fail <id>").description("Mark a task as failed with optional r
35230
35563
  if (result.retryTask)
35231
35564
  console.log(chalk3.yellow(`Retry created: ${result.retryTask.short_id || result.retryTask.id.slice(0, 8)} | ${result.retryTask.title}`));
35232
35565
  });
35233
- program2.command("active").description("Show all currently in-progress tasks").option("--project <id>", "Filter to project").option("--json", "Output as JSON").action(async (opts) => {
35566
+ 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) => {
35234
35567
  const db = getDatabase();
35235
35568
  const filters = {};
35236
35569
  if (opts.project)
@@ -35251,7 +35584,7 @@ program2.command("active").description("Show all currently in-progress tasks").o
35251
35584
  console.log(` ${chalk3.cyan(id)} | ${chalk3.yellow(w.priority)} | ${agent.padEnd(12)} | ${w.title}`);
35252
35585
  }
35253
35586
  });
35254
- 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("--json", "Output as JSON").action(async (opts) => {
35587
+ 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) => {
35255
35588
  const db = getDatabase();
35256
35589
  const filters = {};
35257
35590
  if (opts.project)
@@ -35272,7 +35605,7 @@ program2.command("stale").description("Find tasks stuck in_progress with no rece
35272
35605
  console.log(` ${chalk3.cyan(id)} | ${t.locked_by || t.assigned_to || "?"} | ${t.title} ${chalk3.dim(`(${staleMin}min stale)`)}`);
35273
35606
  }
35274
35607
  });
35275
- 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("--json", "Output as JSON").action(async (agent, opts) => {
35608
+ 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) => {
35276
35609
  const globalOpts = program2.opts();
35277
35610
  const db = getDatabase();
35278
35611
  const projectId = opts.project ? resolveTaskId(opts.project) : autoProject(globalOpts) ?? undefined;
@@ -35299,7 +35632,7 @@ Claimed: ${chalk3.cyan(id)} ${result.claimed.title}`));
35299
35632
  No task claimed (nothing available).`));
35300
35633
  }
35301
35634
  });
35302
- program2.command("assign <id> <agent>").description("Assign a task to an agent").option("--json", "Output as JSON").action((id, agent, opts) => {
35635
+ program2.command("assign <id> <agent>").description("Assign a task to an agent").option("-j, --json", "Output as JSON").action((id, agent, opts) => {
35303
35636
  const globalOpts = program2.opts();
35304
35637
  const resolvedId = resolveTaskId(id);
35305
35638
  const db = getDatabase();
@@ -35319,7 +35652,7 @@ program2.command("assign <id> <agent>").description("Assign a task to an agent")
35319
35652
  handleError(new Error("Failed to assign"));
35320
35653
  }
35321
35654
  });
35322
- program2.command("unassign <id>").description("Remove task assignment").option("--json", "Output as JSON").action((id, opts) => {
35655
+ program2.command("unassign <id>").description("Remove task assignment").option("-j, --json", "Output as JSON").action((id, opts) => {
35323
35656
  const globalOpts = program2.opts();
35324
35657
  const resolvedId = resolveTaskId(id);
35325
35658
  const db = getDatabase();
@@ -35339,7 +35672,7 @@ program2.command("unassign <id>").description("Remove task assignment").option("
35339
35672
  handleError(new Error("Failed to unassign"));
35340
35673
  }
35341
35674
  });
35342
- program2.command("tag <id> <tag>").description("Add a tag to a task").option("--json", "Output as JSON").action((id, tag, opts) => {
35675
+ program2.command("tag <id> <tag>").description("Add a tag to a task").option("-j, --json", "Output as JSON").action((id, tag, opts) => {
35343
35676
  const globalOpts = program2.opts();
35344
35677
  const resolvedId = resolveTaskId(id);
35345
35678
  const db = getDatabase();
@@ -35360,7 +35693,7 @@ program2.command("tag <id> <tag>").description("Add a tag to a task").option("--
35360
35693
  handleError(new Error("Failed to tag"));
35361
35694
  }
35362
35695
  });
35363
- program2.command("untag <id> <tag>").description("Remove a tag from a task").option("--json", "Output as JSON").action((id, tag, opts) => {
35696
+ program2.command("untag <id> <tag>").description("Remove a tag from a task").option("-j, --json", "Output as JSON").action((id, tag, opts) => {
35364
35697
  const globalOpts = program2.opts();
35365
35698
  const resolvedId = resolveTaskId(id);
35366
35699
  const db = getDatabase();
@@ -35381,7 +35714,7 @@ program2.command("untag <id> <tag>").description("Remove a tag from a task").opt
35381
35714
  handleError(new Error("Failed to untag"));
35382
35715
  }
35383
35716
  });
35384
- program2.command("pin <id>").description("Escalate task to critical priority").option("--json", "Output as JSON").action((id, opts) => {
35717
+ program2.command("pin <id>").description("Escalate task to critical priority").option("-j, --json", "Output as JSON").action((id, opts) => {
35385
35718
  const globalOpts = program2.opts();
35386
35719
  const resolvedId = resolveTaskId(id);
35387
35720
  const db = getDatabase();
@@ -35397,7 +35730,7 @@ program2.command("pin <id>").description("Escalate task to critical priority").o
35397
35730
  handleError(new Error("Failed to pin"));
35398
35731
  }
35399
35732
  });
35400
- program2.command("summary").description("Generate a markdown summary of recent task activity").option("--days <n>", "Days of history to include", "7").option("--project <id>", "Filter to project").option("--agent <id>", "Filter to agent").option("--json", "Output as JSON").action(async (opts) => {
35733
+ program2.command("summary").description("Generate a markdown summary of recent task activity").option("--days <n>", "Days of history to include", "7").option("--project <id>", "Filter to project").option("--agent <id>", "Filter to agent").option("-j, --json", "Output as JSON").action(async (opts) => {
35401
35734
  const globalOpts = program2.opts();
35402
35735
  const db = getDatabase();
35403
35736
  const days = parseInt(opts.days, 10);
@@ -35452,7 +35785,7 @@ program2.command("summary").description("Generate a markdown summary of recent t
35452
35785
  console.log(lines.join(`
35453
35786
  `));
35454
35787
  });
35455
- program2.command("doctor").description("Diagnose common task data issues").option("--fix", "Auto-fix recoverable issues where possible").option("--json", "Output as JSON").action(async (opts) => {
35788
+ program2.command("doctor").description("Diagnose common task data issues").option("--fix", "Auto-fix recoverable issues where possible").option("-j, --json", "Output as JSON").action(async (opts) => {
35456
35789
  const globalOpts = program2.opts();
35457
35790
  const db = getDatabase();
35458
35791
  const issues = [];
@@ -35494,7 +35827,7 @@ program2.command("doctor").description("Diagnose common task data issues").optio
35494
35827
  console.log(chalk3[errors2 > 0 ? "red" : "yellow"](`
35495
35828
  ${errors2} error(s), ${warns} warning(s). Run with --fix to auto-resolve where possible.`));
35496
35829
  });
35497
- program2.command("health").description("Check todos system health \u2014 database, config, connectivity").option("--json", "Output as JSON").action(async (opts) => {
35830
+ program2.command("health").description("Check todos system health \u2014 database, config, connectivity").option("-j, --json", "Output as JSON").action(async (opts) => {
35498
35831
  const globalOpts = program2.opts();
35499
35832
  const checks = [];
35500
35833
  try {
@@ -35549,7 +35882,7 @@ program2.command("health").description("Check todos system health \u2014 databas
35549
35882
  console.log(`
35550
35883
  ${allOk ? chalk3.green("All checks passed.") : chalk3.yellow("Some checks need attention.")}`);
35551
35884
  });
35552
- 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("--json", "Output as JSON").action(async (opts) => {
35885
+ 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) => {
35553
35886
  const globalOpts = program2.opts();
35554
35887
  const db = getDatabase();
35555
35888
  const days = parseInt(opts.days, 10);
@@ -35614,7 +35947,7 @@ program2.command("report").description("Analytics report: task activity, complet
35614
35947
  console.log(lines.join(`
35615
35948
  `));
35616
35949
  });
35617
- program2.command("today").description("Show task activity from today").option("--json", "Output as JSON").action(async (opts) => {
35950
+ program2.command("today").description("Show task activity from today").option("-j, --json", "Output as JSON").action(async (opts) => {
35618
35951
  const globalOpts = program2.opts();
35619
35952
  const db = getDatabase();
35620
35953
  const { getTasksChangedSince: getTasksChangedSince2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -35644,7 +35977,7 @@ program2.command("today").description("Show task activity from today").option("-
35644
35977
  if (completed.length === 0 && started.length === 0)
35645
35978
  console.log(chalk3.dim(" No activity today."));
35646
35979
  });
35647
- program2.command("yesterday").description("Show task activity from yesterday").option("--json", "Output as JSON").action(async (opts) => {
35980
+ program2.command("yesterday").description("Show task activity from yesterday").option("-j, --json", "Output as JSON").action(async (opts) => {
35648
35981
  const globalOpts = program2.opts();
35649
35982
  const db = getDatabase();
35650
35983
  const { getTasksChangedSince: getTasksChangedSince2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -35677,7 +36010,7 @@ program2.command("yesterday").description("Show task activity from yesterday").o
35677
36010
  if (completed.length === 0 && started.length === 0)
35678
36011
  console.log(chalk3.dim(" No activity yesterday."));
35679
36012
  });
35680
- program2.command("mine").description("Show tasks assigned to you, grouped by status").argument("<agent>", "Agent name or ID").option("--json", "Output as JSON").action(async (agent, opts) => {
36013
+ 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) => {
35681
36014
  const globalOpts = program2.opts();
35682
36015
  const db = getDatabase();
35683
36016
  const { listTasks: listTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -35728,7 +36061,7 @@ program2.command("mine").description("Show tasks assigned to you, grouped by sta
35728
36061
  if (tasks.length === 0)
35729
36062
  console.log(chalk3.dim(` No tasks assigned to ${agent}.`));
35730
36063
  });
35731
- program2.command("blocked").description("Show tasks blocked by incomplete dependencies").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
36064
+ 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) => {
35732
36065
  const globalOpts = program2.opts();
35733
36066
  const db = getDatabase();
35734
36067
  const { listTasks: listTasks2, getBlockingDeps: getBlockingDeps2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -35760,7 +36093,7 @@ program2.command("blocked").description("Show tasks blocked by incomplete depend
35760
36093
  }
35761
36094
  }
35762
36095
  });
35763
- program2.command("overdue").description("Show tasks past their due date").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
36096
+ program2.command("overdue").description("Show tasks past their due date").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
35764
36097
  const globalOpts = program2.opts();
35765
36098
  const projectId = autoProject(globalOpts) || opts.project || undefined;
35766
36099
  const { getOverdueTasks: getOverdueTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -35782,7 +36115,7 @@ program2.command("overdue").description("Show tasks past their due date").option
35782
36115
  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})`)}`);
35783
36116
  }
35784
36117
  });
35785
- program2.command("week").description("Show task activity from the past 7 days").option("--json", "Output as JSON").action(async (opts) => {
36118
+ program2.command("week").description("Show task activity from the past 7 days").option("-j, --json", "Output as JSON").action(async (opts) => {
35786
36119
  const globalOpts = program2.opts();
35787
36120
  const db = getDatabase();
35788
36121
  const { getTasksChangedSince: getTasksChangedSince2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -35835,7 +36168,7 @@ program2.command("week").description("Show task activity from the past 7 days").
35835
36168
  if (tasks.length === 0)
35836
36169
  console.log(chalk3.dim(" No activity this week."));
35837
36170
  });
35838
- program2.command("burndown").description("Show task completion velocity over the past 7 days").option("--days <n>", "Number of days", "7").option("--json", "Output as JSON").action(async (opts) => {
36171
+ 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) => {
35839
36172
  const globalOpts = program2.opts();
35840
36173
  const db = getDatabase();
35841
36174
  const { getRecentActivity: getRecentActivity2 } = (init_audit(), __toCommonJS(exports_audit));
@@ -35877,7 +36210,7 @@ program2.command("burndown").description("Show task completion velocity over the
35877
36210
  console.log(chalk3.dim(`
35878
36211
  Velocity: ${velocity}/day \xB7 ${totalCompleted} done \xB7 ${totalCreated} created`));
35879
36212
  });
35880
- program2.command("log").description("Show recent task activity log (git-log style)").option("--limit <n>", "Number of entries", "30").option("--json", "Output as JSON").action(async (opts) => {
36213
+ 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) => {
35881
36214
  const globalOpts = program2.opts();
35882
36215
  const db = getDatabase();
35883
36216
  const { getRecentActivity: getRecentActivity2 } = (init_audit(), __toCommonJS(exports_audit));
@@ -35921,7 +36254,7 @@ program2.command("log").description("Show recent task activity log (git-log styl
35921
36254
  console.log(` ${chalk3.dim(time)} ${icon} ${e.action.padEnd(8)} ${taskRef}${detail}${agent}`);
35922
36255
  }
35923
36256
  });
35924
- program2.command("ready").description("Show all tasks ready to be claimed (pending, unblocked, unlocked)").option("--json", "Output as JSON").option("--project <id>", "Filter to project").option("--limit <n>", "Max tasks to show", "20").action(async (opts) => {
36257
+ 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) => {
35925
36258
  const globalOpts = program2.opts();
35926
36259
  const db = getDatabase();
35927
36260
  const { listTasks: listTasks2, getBlockingDeps: getBlockingDeps2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -35954,7 +36287,7 @@ program2.command("ready").description("Show all tasks ready to be claimed (pendi
35954
36287
  console.log(` ${chalk3.cyan(t.short_id || t.id.slice(0, 8))} ${t.title} ${pri}${due}`);
35955
36288
  }
35956
36289
  });
35957
- program2.command("sprint").description("Sprint dashboard: in-progress, next up, blockers, and overdue").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
36290
+ 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) => {
35958
36291
  const globalOpts = program2.opts();
35959
36292
  const db = getDatabase();
35960
36293
  const { listTasks: listTasks2, getBlockingDeps: getBlockingDeps2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -36015,7 +36348,7 @@ program2.command("sprint").description("Sprint dashboard: in-progress, next up,
36015
36348
  console.log(chalk3.dim(`
36016
36349
  ${inProgress.length} active \xB7 ${pending.length} pending \xB7 ${blocked.length} blocked \xB7 ${overdue.length} overdue`));
36017
36350
  });
36018
- 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("--json", "Output as JSON").option("--limit <n>", "Number of handoffs to show", "5").action(async (opts) => {
36351
+ 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) => {
36019
36352
  const globalOpts = program2.opts();
36020
36353
  const db = getDatabase();
36021
36354
  const { createHandoff: createHandoff2, listHandoffs: listHandoffs2 } = (init_handoffs(), __toCommonJS(exports_handoffs));
@@ -36077,7 +36410,7 @@ program2.command("handoff").description("Create or view agent session handoffs")
36077
36410
  }
36078
36411
  }
36079
36412
  });
36080
- program2.command("priorities").description("Show task counts grouped by priority").option("--json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
36413
+ program2.command("priorities").description("Show task counts grouped by priority").option("-j, --json", "Output as JSON").option("--project <id>", "Filter to project").action(async (opts) => {
36081
36414
  const globalOpts = program2.opts();
36082
36415
  const db = getDatabase();
36083
36416
  const { countTasks: countTasks2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -36109,7 +36442,7 @@ program2.command("priorities").description("Show task counts grouped by priority
36109
36442
  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}`);
36110
36443
  }
36111
36444
  });
36112
- program2.command("context").description("Session start context: status, latest handoff, next task, overdue").option("--agent <name>", "Agent name for handoff lookup").option("--json", "Output as JSON").action(async (opts) => {
36445
+ 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) => {
36113
36446
  const globalOpts = program2.opts();
36114
36447
  const db = getDatabase();
36115
36448
  const { getStatus: getStatus2 } = (init_tasks(), __toCommonJS(exports_tasks));
@@ -36151,7 +36484,7 @@ program2.command("context").description("Session start context: status, latest h
36151
36484
  console.log(chalk3.dim(`
36152
36485
  as_of: ${new Date().toISOString()}`));
36153
36486
  });
36154
- 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("--json", "Output as JSON").action(async (opts) => {
36487
+ 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) => {
36155
36488
  const globalOpts = program2.opts();
36156
36489
  const { createTask: createTask2 } = (init_tasks(), __toCommonJS(exports_tasks));
36157
36490
  const { autoAssignTask: autoAssignTask2 } = await Promise.resolve().then(() => (init_auto_assign(), exports_auto_assign));
@@ -36210,7 +36543,7 @@ program2.action(async () => {
36210
36543
  });
36211
36544
  program2.addCommand(makeBrainsCommand());
36212
36545
  var dbCmd = program2.command("db").description("Database management commands");
36213
- dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the configured RDS instance").option("--connection-string <url>", "PostgreSQL connection string (overrides cloud config)").option("--json", "Output as JSON").action(async (opts) => {
36546
+ dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the configured RDS instance").option("--connection-string <url>", "PostgreSQL connection string (overrides cloud config)").option("-j, --json", "Output as JSON").action(async (opts) => {
36214
36547
  const globalOpts = program2.opts();
36215
36548
  const useJson = opts.json || globalOpts.json;
36216
36549
  let connStr;
@@ -36263,7 +36596,7 @@ dbCmd.command("migrate-pg").description("Apply PostgreSQL migrations to the conf
36263
36596
  }
36264
36597
  });
36265
36598
  var cloudCmd = program2.command("cloud").description("Cloud sync commands");
36266
- cloudCmd.command("status").description("Show cloud config, connection health, machine registry, and sync status").option("--json", "Output as JSON").action(async (opts) => {
36599
+ cloudCmd.command("status").description("Show cloud config, connection health, machine registry, and sync status").option("-j, --json", "Output as JSON").action(async (opts) => {
36267
36600
  const globalOpts = program2.opts();
36268
36601
  const useJson = opts.json || globalOpts.json;
36269
36602
  try {
@@ -36354,7 +36687,7 @@ Conflicts`));
36354
36687
  }
36355
36688
  }
36356
36689
  });
36357
- cloudCmd.command("push").description("Push local data to cloud PostgreSQL").option("--tables <tables>", "Comma-separated table names (default: all)").option("--json", "Output as JSON").action(async (opts) => {
36690
+ cloudCmd.command("push").description("Push local data to cloud PostgreSQL").option("--tables <tables>", "Comma-separated table names (default: all)").option("-j, --json", "Output as JSON").action(async (opts) => {
36358
36691
  const globalOpts = program2.opts();
36359
36692
  const useJson = opts.json || globalOpts.json;
36360
36693
  try {
@@ -36414,7 +36747,7 @@ cloudCmd.command("push").description("Push local data to cloud PostgreSQL").opti
36414
36747
  process.exit(1);
36415
36748
  }
36416
36749
  });
36417
- cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by primary key").option("--tables <tables>", "Comma-separated table names (default: all)").option("--json", "Output as JSON").action(async (opts) => {
36750
+ cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by primary key").option("--tables <tables>", "Comma-separated table names (default: all)").option("-j, --json", "Output as JSON").action(async (opts) => {
36418
36751
  const globalOpts = program2.opts();
36419
36752
  const useJson = opts.json || globalOpts.json;
36420
36753
  try {
@@ -36472,7 +36805,7 @@ cloudCmd.command("pull").description("Pull cloud data to local \u2014 merges by
36472
36805
  process.exit(1);
36473
36806
  }
36474
36807
  });
36475
- cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote changes then push local changes").option("--tables <tables>", "Comma-separated table names (default: all)").option("--json", "Output as JSON").action(async (opts) => {
36808
+ cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote changes then push local changes").option("--tables <tables>", "Comma-separated table names (default: all)").option("-j, --json", "Output as JSON").action(async (opts) => {
36476
36809
  const globalOpts = program2.opts();
36477
36810
  const useJson = opts.json || globalOpts.json;
36478
36811
  try {
@@ -36548,7 +36881,7 @@ cloudCmd.command("sync").description("Bidirectional sync \u2014 pull remote chan
36548
36881
  process.exit(1);
36549
36882
  }
36550
36883
  });
36551
- cloudCmd.command("conflicts").description("List sync conflicts detected during push/pull").option("--resolved", "Show resolved conflicts instead of unresolved").option("--table <table>", "Filter by table name").option("--limit <n>", "Max conflicts to show", "20").option("--json", "Output as JSON").action(async (opts) => {
36884
+ cloudCmd.command("conflicts").description("List sync conflicts detected during push/pull").option("--resolved", "Show resolved conflicts instead of unresolved").option("--table <table>", "Filter by table name").option("--limit <n>", "Max conflicts to show", "20").option("-j, --json", "Output as JSON").action(async (opts) => {
36552
36885
  const globalOpts = program2.opts();
36553
36886
  const useJson = opts.json || globalOpts.json;
36554
36887
  try {