@hasna/todos 0.13.11 → 0.14.0

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.
Files changed (54) hide show
  1. package/dist/cli/cloud-router.d.ts.map +1 -1
  2. package/dist/cli/commands/agent-commands.d.ts +39 -0
  3. package/dist/cli/commands/agent-commands.d.ts.map +1 -1
  4. package/dist/cli/commands/dispatch.d.ts.map +1 -1
  5. package/dist/cli/commands/project-commands.d.ts.map +1 -1
  6. package/dist/cli/commands/task-commands.d.ts.map +1 -1
  7. package/dist/cli/helpers.d.ts +64 -2
  8. package/dist/cli/helpers.d.ts.map +1 -1
  9. package/dist/cli/index.js +510 -149
  10. package/dist/contracts.js +102 -71
  11. package/dist/db/agent-metrics.d.ts.map +1 -1
  12. package/dist/db/audit.d.ts.map +1 -1
  13. package/dist/db/budgets.d.ts.map +1 -1
  14. package/dist/db/database.d.ts +44 -0
  15. package/dist/db/database.d.ts.map +1 -1
  16. package/dist/db/handoffs.d.ts.map +1 -1
  17. package/dist/db/task-crud.d.ts +1 -0
  18. package/dist/db/task-crud.d.ts.map +1 -1
  19. package/dist/db/task-files.d.ts.map +1 -1
  20. package/dist/db/task-lifecycle.d.ts.map +1 -1
  21. package/dist/db/task-relations.d.ts.map +1 -1
  22. package/dist/db/task-status.d.ts.map +1 -1
  23. package/dist/db/webhooks.d.ts.map +1 -1
  24. package/dist/index.js +134 -93
  25. package/dist/lib/capacity-forecasts.d.ts.map +1 -1
  26. package/dist/lib/completion-guard.d.ts.map +1 -1
  27. package/dist/lib/enum-vocabulary.d.ts +72 -0
  28. package/dist/lib/enum-vocabulary.d.ts.map +1 -0
  29. package/dist/lib/local-notifications.d.ts.map +1 -1
  30. package/dist/lib/local-reports.d.ts.map +1 -1
  31. package/dist/lib/notification-reminders.d.ts.map +1 -1
  32. package/dist/lib/saved-search-views.d.ts +12 -1
  33. package/dist/lib/saved-search-views.d.ts.map +1 -1
  34. package/dist/lib/search.d.ts.map +1 -1
  35. package/dist/lib/usage-ledger.d.ts.map +1 -1
  36. package/dist/mcp/index.js +349 -115
  37. package/dist/mcp/tools/agents.d.ts.map +1 -1
  38. package/dist/mcp/tools/task-adv-tools.d.ts.map +1 -1
  39. package/dist/mcp/tools/task-auto-tools.d.ts.map +1 -1
  40. package/dist/mcp/tools/task-resources.d.ts.map +1 -1
  41. package/dist/mcp.js +1 -1
  42. package/dist/registry.js +102 -71
  43. package/dist/release-provenance.json +5 -5
  44. package/dist/sdk/v1.generated.d.ts +2 -2
  45. package/dist/sdk/v1.generated.d.ts.map +1 -1
  46. package/dist/server/index.js +349 -115
  47. package/dist/server/openapi.d.ts +58 -0
  48. package/dist/server/openapi.d.ts.map +1 -1
  49. package/dist/server/routes.d.ts.map +1 -1
  50. package/dist/server/v1.d.ts.map +1 -1
  51. package/dist/storage.js +69 -46
  52. package/dist/types/index.d.ts +11 -0
  53. package/dist/types/index.d.ts.map +1 -1
  54. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3430,6 +3430,9 @@ var init_machines = __esm(() => {
3430
3430
  function isBlockingDependencyStatus(status) {
3431
3431
  return status !== "completed" && status !== "cancelled";
3432
3432
  }
3433
+ function isTerminalStatus(status) {
3434
+ return status === "completed" || status === "failed" || status === "cancelled";
3435
+ }
3433
3436
  var TASK_STATUSES, TASK_PRIORITIES, PLAN_STATUSES, VersionConflictError, TaskNotFoundError, TaskNotStartableError, TaskReferenceAmbiguousError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DISPATCH_STATUSES, DispatchNotFoundError;
3434
3437
  var init_types = __esm(() => {
3435
3438
  TASK_STATUSES = [
@@ -4103,14 +4106,17 @@ var exports_database = {};
4103
4106
  __export(exports_database, {
4104
4107
  uuid: () => uuid,
4105
4108
  resolvePartialId: () => resolvePartialId,
4109
+ resolveAssignedToAliases: () => resolveAssignedToAliases,
4106
4110
  resetDatabase: () => resetDatabase,
4107
4111
  now: () => now,
4112
+ lowerInClause: () => lowerInClause,
4108
4113
  lockExpiryCutoff: () => lockExpiryCutoff,
4109
4114
  isLockExpired: () => isLockExpired,
4110
4115
  getDatabasePath: () => getDatabasePath,
4111
4116
  getDatabase: () => getDatabase,
4112
4117
  closeDatabase: () => closeDatabase,
4113
4118
  clearExpiredLocks: () => clearExpiredLocks,
4119
+ assignedToAliasSet: () => assignedToAliasSet,
4114
4120
  LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
4115
4121
  });
4116
4122
  import { Database } from "bun:sqlite";
@@ -4339,6 +4345,33 @@ function resolvePartialId(db, table, partialId) {
4339
4345
  }
4340
4346
  return null;
4341
4347
  }
4348
+ function resolveAssignedToAliases(db, ref) {
4349
+ const aliases = new Set([ref]);
4350
+ let agentId;
4351
+ try {
4352
+ agentId = resolvePartialId(db, "agents", ref);
4353
+ } catch (err) {
4354
+ if (!(err instanceof IdentityAliasAmbiguousError))
4355
+ throw err;
4356
+ agentId = null;
4357
+ }
4358
+ if (agentId) {
4359
+ aliases.add(agentId);
4360
+ const row = db.query("SELECT name FROM agents WHERE id = ?").get(agentId);
4361
+ if (row?.name)
4362
+ aliases.add(row.name);
4363
+ }
4364
+ return [...aliases];
4365
+ }
4366
+ function assignedToAliasSet(db, ref) {
4367
+ return new Set(resolveAssignedToAliases(db, ref).map((a) => a.toLowerCase()));
4368
+ }
4369
+ function lowerInClause(column, values, params) {
4370
+ if (values.length === 0)
4371
+ return "1=0";
4372
+ params.push(...values.map((v) => v.toLowerCase()));
4373
+ return `LOWER(${column}) IN (${values.map(() => "?").join(",")})`;
4374
+ }
4342
4375
  var LOCK_EXPIRY_MINUTES = 30, _db = null, _dbPath = null, ALLOWED_TABLES;
4343
4376
  var init_database = __esm(() => {
4344
4377
  init_schema();
@@ -4979,17 +5012,19 @@ function checkCompletionGuard(task, agentId, db, configOverride) {
4979
5012
  throw new CompletionGuardError(`Too fast: task was started ${Math.floor(elapsedSeconds)}s ago. Minimum work duration is ${config.min_work_seconds}s. Wait ${remaining}s.`, remaining);
4980
5013
  }
4981
5014
  }
5015
+ const assignedAliasParams = [];
5016
+ const assignedInClause = agent ? lowerInClause("assigned_to", resolveAssignedToAliases(db, agent), assignedAliasParams) : "";
4982
5017
  if (agent && config.max_completions_per_window && config.window_minutes) {
4983
5018
  const windowStart = new Date(Date.now() - config.window_minutes * 60 * 1000).toISOString();
4984
5019
  const result = db.query(`SELECT COUNT(*) as count FROM tasks
4985
- WHERE completed_at > ? AND (assigned_to = ? OR agent_id = ?)`).get(windowStart, agent, agent);
5020
+ WHERE completed_at > ? AND (${assignedInClause} OR agent_id = ?)`).get(windowStart, ...assignedAliasParams, agent);
4986
5021
  if (result.count >= config.max_completions_per_window) {
4987
5022
  throw new CompletionGuardError(`Rate limit: ${result.count} tasks completed in the last ${config.window_minutes} minutes (max ${config.max_completions_per_window}). Slow down.`);
4988
5023
  }
4989
5024
  }
4990
5025
  if (agent && config.cooldown_seconds) {
4991
5026
  const result = db.query(`SELECT MAX(completed_at) as last_completed FROM tasks
4992
- WHERE completed_at IS NOT NULL AND (assigned_to = ? OR agent_id = ?) AND id != ?`).get(agent, agent, task.id);
5027
+ WHERE completed_at IS NOT NULL AND (${assignedInClause} OR agent_id = ?) AND id != ?`).get(...assignedAliasParams, agent, task.id);
4993
5028
  if (result.last_completed) {
4994
5029
  const elapsedSeconds = (Date.now() - new Date(result.last_completed).getTime()) / 1000;
4995
5030
  if (elapsedSeconds < config.cooldown_seconds) {
@@ -5003,6 +5038,7 @@ var init_completion_guard = __esm(() => {
5003
5038
  init_types();
5004
5039
  init_config2();
5005
5040
  init_projects();
5041
+ init_database();
5006
5042
  });
5007
5043
 
5008
5044
  // src/lib/event-emission-safety.ts
@@ -7232,7 +7268,7 @@ function getRecap(hours = 8, projectId, db) {
7232
7268
  const in_progress = projectId ? d.query(`SELECT id, short_id, title, assigned_to, started_at FROM tasks WHERE status = 'in_progress' AND project_id = ? ORDER BY updated_at DESC`).all(projectId) : d.query(`SELECT id, short_id, title, assigned_to, started_at FROM tasks WHERE status = 'in_progress' ORDER BY updated_at DESC`).all();
7233
7269
  const blocked = projectId ? d.query(`SELECT DISTINCT t.id, t.short_id, t.title, t.assigned_to FROM tasks t JOIN task_dependencies td ON td.task_id = t.id JOIN tasks dep ON dep.id = td.depends_on AND dep.status NOT IN ('completed','cancelled') WHERE t.status = 'pending'${tpf}`).all(projectId) : d.query(`SELECT DISTINCT t.id, t.short_id, t.title, t.assigned_to FROM tasks t JOIN task_dependencies td ON td.task_id = t.id JOIN tasks dep ON dep.id = td.depends_on AND dep.status NOT IN ('completed','cancelled') WHERE t.status = 'pending'`).all();
7234
7270
  const stale = projectId ? d.query(`SELECT id, short_id, title, assigned_to, updated_at FROM tasks WHERE status = 'in_progress' AND updated_at < ? AND project_id = ? ORDER BY updated_at ASC`).all(staleWindow, projectId) : d.query(`SELECT id, short_id, title, assigned_to, updated_at FROM tasks WHERE status = 'in_progress' AND updated_at < ? ORDER BY updated_at ASC`).all(staleWindow);
7235
- const agents = projectId ? d.query(`SELECT a.name, a.last_seen_at, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR t.agent_id = a.id) AND t.status = 'completed' AND t.completed_at > ?${tpf}) as completed_count, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR t.agent_id = a.id) AND t.status = 'in_progress'${tpf}) as in_progress_count FROM agents a WHERE a.status = 'active' AND a.last_seen_at > ? ORDER BY completed_count DESC`).all(since, projectId, projectId, since) : d.query(`SELECT a.name, a.last_seen_at, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR t.agent_id = a.id) AND t.status = 'completed' AND t.completed_at > ?) as completed_count, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR t.agent_id = a.id) AND t.status = 'in_progress') as in_progress_count FROM agents a WHERE a.status = 'active' AND a.last_seen_at > ? ORDER BY completed_count DESC`).all(since, since);
7271
+ const agents = projectId ? d.query(`SELECT a.name, a.last_seen_at, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR LOWER(t.assigned_to) = LOWER(a.name) OR t.agent_id = a.id) AND t.status = 'completed' AND t.completed_at > ?${tpf}) as completed_count, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR LOWER(t.assigned_to) = LOWER(a.name) OR t.agent_id = a.id) AND t.status = 'in_progress'${tpf}) as in_progress_count FROM agents a WHERE a.status = 'active' AND a.last_seen_at > ? ORDER BY completed_count DESC`).all(since, projectId, projectId, since) : d.query(`SELECT a.name, a.last_seen_at, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR LOWER(t.assigned_to) = LOWER(a.name) OR t.agent_id = a.id) AND t.status = 'completed' AND t.completed_at > ?) as completed_count, (SELECT COUNT(*) FROM tasks t WHERE (t.assigned_to = a.id OR LOWER(t.assigned_to) = LOWER(a.name) OR t.agent_id = a.id) AND t.status = 'in_progress') as in_progress_count FROM agents a WHERE a.status = 'active' AND a.last_seen_at > ? ORDER BY completed_count DESC`).all(since, since);
7236
7272
  return {
7237
7273
  hours,
7238
7274
  since,
@@ -7385,13 +7421,17 @@ function logDelivery(d, webhookId, event, payload, statusCode, response, attempt
7385
7421
  const id = uuid();
7386
7422
  d.run(`INSERT INTO webhook_deliveries (id, webhook_id, event, payload, status_code, response, attempt, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, webhookId, event, payload, statusCode, response, attempt, now()]);
7387
7423
  }
7388
- function matchesScope(wh, payload) {
7424
+ function matchesScope(wh, payload, db) {
7389
7425
  if (wh.project_id && payload.project_id !== wh.project_id)
7390
7426
  return false;
7391
7427
  if (wh.task_list_id && payload.task_list_id !== wh.task_list_id)
7392
7428
  return false;
7393
- if (wh.agent_id && payload.agent_id !== wh.agent_id && payload.assigned_to !== wh.agent_id)
7394
- return false;
7429
+ if (wh.agent_id && payload.agent_id !== wh.agent_id) {
7430
+ const aliasSet = assignedToAliasSet(db, wh.agent_id);
7431
+ const assignedTo = typeof payload.assigned_to === "string" ? payload.assigned_to.toLowerCase() : "";
7432
+ if (!aliasSet.has(assignedTo))
7433
+ return false;
7434
+ }
7395
7435
  if (wh.task_id && payload.id !== wh.task_id)
7396
7436
  return false;
7397
7437
  return true;
@@ -7458,7 +7498,7 @@ async function dispatchWebhook2(event, payload, db) {
7458
7498
  const webhooks = listWebhooks(d).filter((w) => w.active && (w.events.length === 0 || w.events.includes(event)));
7459
7499
  const payloadObj = typeof payload === "object" && payload !== null ? payload : {};
7460
7500
  for (const wh of webhooks) {
7461
- if (!matchesScope(wh, payloadObj))
7501
+ if (!matchesScope(wh, payloadObj, d))
7462
7502
  continue;
7463
7503
  const body = JSON.stringify({ event, payload, timestamp: now() });
7464
7504
  deliverWebhook(wh, event, body, 1, d).catch((err) => {
@@ -8561,14 +8601,16 @@ function getNextTask(agentId, filters, db) {
8561
8601
  conditions.push("id NOT IN (SELECT td.task_id FROM task_dependencies td JOIN tasks dep ON dep.id = td.depends_on WHERE dep.status != 'completed')");
8562
8602
  const where = conditions.join(" AND ");
8563
8603
  let recentProjectIds = [];
8604
+ const assignedAliasParams = [];
8605
+ const assignedInClause = agentId ? lowerInClause("assigned_to", resolveAssignedToAliases(d, agentId), assignedAliasParams) : "";
8564
8606
  if (agentId) {
8565
- const recentRows = d.query(`SELECT DISTINCT project_id FROM tasks WHERE assigned_to = ? AND status = 'completed' AND project_id IS NOT NULL ORDER BY completed_at DESC LIMIT 3`).all(agentId);
8607
+ const recentRows = d.query(`SELECT DISTINCT project_id FROM tasks WHERE ${assignedInClause} AND status = 'completed' AND project_id IS NOT NULL ORDER BY completed_at DESC LIMIT 3`).all(...assignedAliasParams);
8566
8608
  recentProjectIds = recentRows.map((r) => r.project_id);
8567
8609
  }
8568
8610
  let sql = `SELECT * FROM tasks WHERE ${where} ORDER BY `;
8569
8611
  if (agentId) {
8570
- sql += `CASE WHEN assigned_to = ? THEN 0 WHEN assigned_to IS NULL THEN 1 ELSE 2 END, `;
8571
- params.push(agentId);
8612
+ sql += `CASE WHEN ${assignedInClause} THEN 0 WHEN assigned_to IS NULL THEN 1 ELSE 2 END, `;
8613
+ params.push(...assignedAliasParams);
8572
8614
  }
8573
8615
  if (recentProjectIds.length > 0) {
8574
8616
  const placeholders = recentProjectIds.map(() => "?").join(",");
@@ -8962,30 +9004,6 @@ function getTaskWithRelations(id, db) {
8962
9004
  checklist
8963
9005
  };
8964
9006
  }
8965
- function resolveAssignedToAliases(db, ref) {
8966
- const aliases = new Set([ref]);
8967
- let agentId;
8968
- try {
8969
- agentId = resolvePartialId(db, "agents", ref);
8970
- } catch (err) {
8971
- if (!(err instanceof IdentityAliasAmbiguousError))
8972
- throw err;
8973
- agentId = null;
8974
- }
8975
- if (agentId) {
8976
- aliases.add(agentId);
8977
- const row = db.query("SELECT name FROM agents WHERE id = ?").get(agentId);
8978
- if (row?.name)
8979
- aliases.add(row.name);
8980
- }
8981
- return [...aliases];
8982
- }
8983
- function lowerInClause(column, values, params) {
8984
- if (values.length === 0)
8985
- return "1=0";
8986
- params.push(...values.map((v) => v.toLowerCase()));
8987
- return `LOWER(${column}) IN (${values.map(() => "?").join(",")})`;
8988
- }
8989
9007
  function listTasks(filter = {}, db) {
8990
9008
  const d = db || getDatabase();
8991
9009
  const { clearExpiredLocks: clearExpiredLocks2 } = (init_database(), __toCommonJS(exports_database));
@@ -9271,11 +9289,13 @@ function updateTask(id, input, db) {
9271
9289
  }
9272
9290
  sets.push("status = ?");
9273
9291
  params.push(input.status);
9292
+ if (isTerminalStatus(input.status)) {
9293
+ sets.push("locked_by = NULL");
9294
+ sets.push("locked_at = NULL");
9295
+ }
9274
9296
  if (input.status === "completed") {
9275
9297
  sets.push("completed_at = ?");
9276
9298
  params.push(completionTimestamp);
9277
- sets.push("locked_by = NULL");
9278
- sets.push("locked_at = NULL");
9279
9299
  } else if (task.status === "completed" && input.completed_at === undefined) {
9280
9300
  sets.push("completed_at = NULL");
9281
9301
  }
@@ -9399,6 +9419,7 @@ function updateTask(id, input, db) {
9399
9419
  logTaskChange(id, "approve", "approved_by", null, input.approved_by, agentId, d);
9400
9420
  const reopened = input.status !== undefined && input.status !== "completed" && task.status === "completed" && input.completed_at === undefined;
9401
9421
  const completedNow = input.status === "completed";
9422
+ const terminalNow = input.status !== undefined && isTerminalStatus(input.status);
9402
9423
  const updatedTask = {
9403
9424
  ...task,
9404
9425
  ...Object.fromEntries(Object.entries(input).filter(([, v]) => v !== undefined)),
@@ -9406,8 +9427,8 @@ function updateTask(id, input, db) {
9406
9427
  metadata: input.metadata ?? task.metadata,
9407
9428
  version: task.version + 1,
9408
9429
  updated_at: timestamp2,
9409
- locked_by: completedNow ? null : task.locked_by,
9410
- locked_at: completedNow ? null : task.locked_at,
9430
+ locked_by: terminalNow ? null : task.locked_by,
9431
+ locked_at: terminalNow ? null : task.locked_at,
9411
9432
  completed_at: completedNow ? completionTimestamp : reopened ? null : input.completed_at !== undefined ? input.completed_at : task.completed_at,
9412
9433
  sla_minutes: input.sla_minutes !== undefined ? input.sla_minutes : task.sla_minutes,
9413
9434
  actual_minutes: input.actual_minutes ?? task.actual_minutes,
@@ -9458,6 +9479,7 @@ function deleteTask(id, db) {
9458
9479
  var init_task_crud = __esm(() => {
9459
9480
  init_types();
9460
9481
  init_database();
9482
+ init_database();
9461
9483
  init_completion_guard();
9462
9484
  init_event_emission_safety();
9463
9485
  init_event_hooks();
@@ -9620,8 +9642,8 @@ function getTaskStats(filters, db) {
9620
9642
  params.push(filters.task_list_id);
9621
9643
  }
9622
9644
  if (filters?.agent_id) {
9623
- conditions.push("(agent_id = ? OR assigned_to = ?)");
9624
- params.push(filters.agent_id, filters.agent_id);
9645
+ params.push(filters.agent_id);
9646
+ conditions.push(`(agent_id = ? OR ${lowerInClause("assigned_to", resolveAssignedToAliases(d, filters.agent_id), params)})`);
9625
9647
  }
9626
9648
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
9627
9649
  const totalRow = d.query(`SELECT COUNT(*) as count FROM tasks ${where}`).get(...params);
@@ -9757,8 +9779,7 @@ function getEscalatedTasks(opts = {}, db, at = new Date) {
9757
9779
  params.push(opts.project_id);
9758
9780
  }
9759
9781
  if (opts.agent_id) {
9760
- conditions.push("assigned_to = ?");
9761
- params.push(opts.agent_id);
9782
+ conditions.push(lowerInClause("assigned_to", resolveAssignedToAliases(d, opts.agent_id), params));
9762
9783
  }
9763
9784
  const rows = d.query(`SELECT * FROM tasks WHERE ${conditions.join(" AND ")} ORDER BY due_at ASC, created_at ASC`).all(...params);
9764
9785
  return rows.map(rowToTask).map((task) => {
@@ -9991,13 +10012,14 @@ function getTimeReport(opts, db) {
9991
10012
  params.push(opts.plan_id);
9992
10013
  }
9993
10014
  if (opts?.agent_id) {
10015
+ const assignedInClause = lowerInClause("t.assigned_to", resolveAssignedToAliases(d, opts.agent_id), params);
9994
10016
  conditions.push(`(
9995
- t.assigned_to = ?
10017
+ ${assignedInClause}
9996
10018
  OR t.agent_id = ?
9997
10019
  OR EXISTS (SELECT 1 FROM task_time_logs ttl WHERE ttl.task_id = t.id AND ttl.agent_id = ?)
9998
10020
  OR EXISTS (SELECT 1 FROM focus_sessions fs WHERE fs.task_id = t.id AND fs.agent_id = ?)
9999
10021
  )`);
10000
- params.push(opts.agent_id, opts.agent_id, opts.agent_id, opts.agent_id);
10022
+ params.push(opts.agent_id, opts.agent_id, opts.agent_id);
10001
10023
  }
10002
10024
  if (opts?.since) {
10003
10025
  conditions.push("(t.completed_at >= ? OR t.updated_at >= ?)");
@@ -12122,7 +12144,7 @@ var init_dispatches = __esm(() => {
12122
12144
  // package.json
12123
12145
  var package_default = {
12124
12146
  name: "@hasna/todos",
12125
- version: "0.13.11",
12147
+ version: "0.14.0",
12126
12148
  description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
12127
12149
  type: "module",
12128
12150
  main: "dist/index.js",
@@ -22134,11 +22156,12 @@ function runAlerts(input, db, checkedAt, quieted) {
22134
22156
  if (input.include_runs === false)
22135
22157
  return [];
22136
22158
  const since = Date.parse(input.run_since || new Date(Date.parse(checkedAt) - 24 * 60 * 60000).toISOString());
22159
+ const runAlertAliases = input.agent_id ? assignedToAliasSet(db, input.agent_id) : null;
22137
22160
  return listTaskRuns(undefined, db).filter((run) => run.completed_at && Date.parse(run.completed_at) >= since).map((run) => {
22138
22161
  const task2 = getTask(run.task_id, db);
22139
22162
  if (input.project_id && task2?.project_id !== input.project_id)
22140
22163
  return null;
22141
- if (input.agent_id && run.agent_id !== input.agent_id && task2?.assigned_to !== input.agent_id)
22164
+ if (input.agent_id && run.agent_id !== input.agent_id && !(runAlertAliases && runAlertAliases.has((task2?.assigned_to ?? "").toLowerCase())))
22142
22165
  return null;
22143
22166
  const failed = ["failed", "cancelled"].includes(run.status);
22144
22167
  return {
@@ -22183,6 +22206,7 @@ async function checkLocalNotifications(input = {}, db) {
22183
22206
  const warnings = [];
22184
22207
  if (Number.isNaN(checkedMs))
22185
22208
  warnings.push("Invalid check timestamp; due-soon window may be incomplete.");
22209
+ const notifyAgentAliases = input.agent_id ? assignedToAliasSet(d, input.agent_id) : null;
22186
22210
  const alerts = [];
22187
22211
  for (const escalation of getEscalatedTasks({ project_id: input.project_id, agent_id: input.agent_id }, d, new Date(checkedAt))) {
22188
22212
  for (const reason of escalation.reasons) {
@@ -22194,7 +22218,7 @@ async function checkLocalNotifications(input = {}, db) {
22194
22218
  for (const task2 of listTasks({ project_id: input.project_id, include_archived: false, limit: 5000 }, d)) {
22195
22219
  if (!unfinished(task2) || !task2.due_at)
22196
22220
  continue;
22197
- if (input.agent_id && task2.assigned_to !== input.agent_id && task2.agent_id !== input.agent_id)
22221
+ if (input.agent_id && task2.agent_id !== input.agent_id && !(notifyAgentAliases && notifyAgentAliases.has((task2.assigned_to ?? "").toLowerCase())))
22198
22222
  continue;
22199
22223
  if (task2.due_at > checkedAt && task2.due_at <= dueSoonUntil) {
22200
22224
  alerts.push(taskAlert(task2, "task_due_soon", "task.due_soon", "warning", `Due soon: ${task2.title}`, task2.due_at, quieted));
@@ -22202,7 +22226,7 @@ async function checkLocalNotifications(input = {}, db) {
22202
22226
  }
22203
22227
  }
22204
22228
  for (const task2 of getStaleTasks(staleMinutes, { project_id: input.project_id }, d)) {
22205
- if (input.agent_id && task2.assigned_to !== input.agent_id && task2.agent_id !== input.agent_id)
22229
+ if (input.agent_id && task2.agent_id !== input.agent_id && !(notifyAgentAliases && notifyAgentAliases.has((task2.assigned_to ?? "").toLowerCase())))
22206
22230
  continue;
22207
22231
  alerts.push(taskAlert(task2, "task_stale", "task.stale", "warning", `Stale task: ${task2.title}`, checkedAt, quieted, { stale_minutes: staleMinutes }));
22208
22232
  }
@@ -22330,14 +22354,15 @@ function millisBetween(start, end) {
22330
22354
  return 0;
22331
22355
  return endMs - startMs;
22332
22356
  }
22333
- function addTaskScope(where, params, options, alias = "t") {
22357
+ function addTaskScope(where, params, options, db, alias = "t") {
22334
22358
  if (options.project_id) {
22335
22359
  where.push(`${alias}.project_id = ?`);
22336
22360
  params.push(options.project_id);
22337
22361
  }
22338
22362
  if (options.agent_id) {
22339
- where.push(`(${alias}.agent_id = ? OR ${alias}.assigned_to = ?)`);
22340
- params.push(options.agent_id, options.agent_id);
22363
+ params.push(options.agent_id);
22364
+ const assignedInClause = lowerInClause(`${alias}.assigned_to`, resolveAssignedToAliases(db, options.agent_id), params);
22365
+ where.push(`(${alias}.agent_id = ? OR ${assignedInClause})`);
22341
22366
  }
22342
22367
  if (options.since) {
22343
22368
  where.push(`${alias}.created_at >= ?`);
@@ -22348,14 +22373,15 @@ function addTaskScope(where, params, options, alias = "t") {
22348
22373
  params.push(options.until);
22349
22374
  }
22350
22375
  }
22351
- function addRunScope(where, params, options, runAlias = "r", taskAlias = "t") {
22376
+ function addRunScope(where, params, options, db, runAlias = "r", taskAlias = "t") {
22352
22377
  if (options.project_id) {
22353
22378
  where.push(`${taskAlias}.project_id = ?`);
22354
22379
  params.push(options.project_id);
22355
22380
  }
22356
22381
  if (options.agent_id) {
22357
- where.push(`(${runAlias}.agent_id = ? OR ${taskAlias}.agent_id = ? OR ${taskAlias}.assigned_to = ?)`);
22358
- params.push(options.agent_id, options.agent_id, options.agent_id);
22382
+ params.push(options.agent_id, options.agent_id);
22383
+ const assignedInClause = lowerInClause(`${taskAlias}.assigned_to`, resolveAssignedToAliases(db, options.agent_id), params);
22384
+ where.push(`(${runAlias}.agent_id = ? OR ${taskAlias}.agent_id = ? OR ${assignedInClause})`);
22359
22385
  }
22360
22386
  if (options.since) {
22361
22387
  where.push(`${runAlias}.started_at >= ?`);
@@ -22366,14 +22392,15 @@ function addRunScope(where, params, options, runAlias = "r", taskAlias = "t") {
22366
22392
  params.push(options.until);
22367
22393
  }
22368
22394
  }
22369
- function addTraceScope(where, params, options, traceAlias = "tr", taskAlias = "t") {
22395
+ function addTraceScope(where, params, options, db, traceAlias = "tr", taskAlias = "t") {
22370
22396
  if (options.project_id) {
22371
22397
  where.push(`${taskAlias}.project_id = ?`);
22372
22398
  params.push(options.project_id);
22373
22399
  }
22374
22400
  if (options.agent_id) {
22375
- where.push(`(${traceAlias}.agent_id = ? OR ${taskAlias}.agent_id = ? OR ${taskAlias}.assigned_to = ?)`);
22376
- params.push(options.agent_id, options.agent_id, options.agent_id);
22401
+ params.push(options.agent_id, options.agent_id);
22402
+ const assignedInClause = lowerInClause(`${taskAlias}.assigned_to`, resolveAssignedToAliases(db, options.agent_id), params);
22403
+ where.push(`(${traceAlias}.agent_id = ? OR ${taskAlias}.agent_id = ? OR ${assignedInClause})`);
22377
22404
  }
22378
22405
  if (options.since) {
22379
22406
  where.push(`${traceAlias}.created_at >= ?`);
@@ -22433,7 +22460,7 @@ function createLocalUsageLedger(options = {}, db) {
22433
22460
  const generatedAt = options.generated_at || new Date().toISOString();
22434
22461
  const taskWhere = [];
22435
22462
  const taskParams = [];
22436
- addTaskScope(taskWhere, taskParams, options);
22463
+ addTaskScope(taskWhere, taskParams, options, d);
22437
22464
  const taskClause = taskWhere.length ? `WHERE ${taskWhere.join(" AND ")}` : "";
22438
22465
  const taskTotals = queryOne(d, `SELECT COUNT(*) as tasks, COALESCE(SUM(cost_tokens), 0) as task_tokens, COALESCE(SUM(cost_usd), 0) as task_cost_usd FROM tasks t ${taskClause}`, taskParams);
22439
22466
  let projectCount = 0;
@@ -22442,14 +22469,14 @@ function createLocalUsageLedger(options = {}, db) {
22442
22469
  } else if (options.agent_id) {
22443
22470
  const projectWhere = ["t.project_id IS NOT NULL"];
22444
22471
  const projectParams = [];
22445
- addTaskScope(projectWhere, projectParams, options);
22472
+ addTaskScope(projectWhere, projectParams, options, d);
22446
22473
  projectCount = queryOne(d, `SELECT COUNT(DISTINCT t.project_id) as count FROM tasks t WHERE ${projectWhere.join(" AND ")}`, projectParams).count;
22447
22474
  } else {
22448
22475
  projectCount = queryOne(d, "SELECT COUNT(*) as count FROM projects", []).count;
22449
22476
  }
22450
22477
  const runWhere = [];
22451
22478
  const runParams = [];
22452
- addRunScope(runWhere, runParams, options);
22479
+ addRunScope(runWhere, runParams, options, d);
22453
22480
  const runClause = runWhere.length ? `WHERE ${runWhere.join(" AND ")}` : "";
22454
22481
  const runs = queryAll(d, `SELECT r.id, r.started_at, r.completed_at, r.metadata
22455
22482
  FROM task_runs r JOIN tasks t ON t.id = r.task_id
@@ -22466,7 +22493,7 @@ function createLocalUsageLedger(options = {}, db) {
22466
22493
  ${runClause}`, runParams);
22467
22494
  const traceWhere = [];
22468
22495
  const traceParams = [];
22469
- addTraceScope(traceWhere, traceParams, options);
22496
+ addTraceScope(traceWhere, traceParams, options, d);
22470
22497
  const traceClause = traceWhere.length ? `WHERE ${traceWhere.join(" AND ")}` : "";
22471
22498
  const traceTotals = queryOne(d, `SELECT COUNT(*) as traces,
22472
22499
  COALESCE(SUM(tr.tokens), 0) as tokens,
@@ -22598,7 +22625,6 @@ function renderLocalUsageLedgerMarkdown(report) {
22598
22625
  }
22599
22626
  // src/lib/local-reports.ts
22600
22627
  init_database();
22601
- init_database();
22602
22628
  init_plans();
22603
22629
  init_tasks();
22604
22630
  var LOCAL_REPORT_SCHEMA_VERSION = 1;
@@ -22621,10 +22647,12 @@ function limitValue(value) {
22621
22647
  function isTerminal(task2) {
22622
22648
  return task2.status === "completed" || task2.status === "failed" || task2.status === "cancelled";
22623
22649
  }
22624
- function sameAgent(task2, agentId) {
22650
+ function sameAgent(task2, agentId, aliasSet) {
22625
22651
  if (!agentId)
22626
22652
  return true;
22627
- return task2.assigned_to === agentId || task2.agent_id === agentId;
22653
+ if (task2.agent_id === agentId)
22654
+ return true;
22655
+ return aliasSet ? aliasSet.has((task2.assigned_to ?? "").toLowerCase()) : task2.assigned_to === agentId;
22628
22656
  }
22629
22657
  function withinTaskWindow(task2, options) {
22630
22658
  const time = Date.parse(task2.updated_at);
@@ -22637,11 +22665,12 @@ function withinTaskWindow(task2, options) {
22637
22665
  return true;
22638
22666
  }
22639
22667
  function scopedTasks(options, db) {
22668
+ const aliasSet = options.agent_id ? assignedToAliasSet(db, options.agent_id) : undefined;
22640
22669
  return listTasks({
22641
22670
  project_id: options.project_id,
22642
22671
  plan_id: options.plan_id,
22643
22672
  include_archived: false
22644
- }, db).filter((task2) => sameAgent(task2, options.agent_id) && withinTaskWindow(task2, options));
22673
+ }, db).filter((task2) => sameAgent(task2, options.agent_id, aliasSet) && withinTaskWindow(task2, options));
22645
22674
  }
22646
22675
  function summarizeTask(task2) {
22647
22676
  return {
@@ -22707,7 +22736,7 @@ function initialAgentSummary(agentId) {
22707
22736
  }
22708
22737
  };
22709
22738
  }
22710
- function addScopeClauses(where, params, options, timeColumn) {
22739
+ function addScopeClauses(where, params, options, timeColumn, db) {
22711
22740
  if (options.project_id) {
22712
22741
  where.push("t.project_id = ?");
22713
22742
  params.push(options.project_id);
@@ -22717,8 +22746,9 @@ function addScopeClauses(where, params, options, timeColumn) {
22717
22746
  params.push(options.plan_id);
22718
22747
  }
22719
22748
  if (options.agent_id) {
22720
- where.push("(r.agent_id = ? OR t.agent_id = ? OR t.assigned_to = ?)");
22721
- params.push(options.agent_id, options.agent_id, options.agent_id);
22749
+ params.push(options.agent_id, options.agent_id);
22750
+ const assignedInClause = lowerInClause("t.assigned_to", resolveAssignedToAliases(db, options.agent_id), params);
22751
+ where.push(`(r.agent_id = ? OR t.agent_id = ? OR ${assignedInClause})`);
22722
22752
  }
22723
22753
  if (options.since) {
22724
22754
  where.push(`${timeColumn} >= ?`);
@@ -22732,7 +22762,7 @@ function addScopeClauses(where, params, options, timeColumn) {
22732
22762
  function loadRuns(options, db) {
22733
22763
  const where = ["t.archived_at IS NULL"];
22734
22764
  const params = [];
22735
- addScopeClauses(where, params, options, "r.started_at");
22765
+ addScopeClauses(where, params, options, "r.started_at", db);
22736
22766
  return db.query(`
22737
22767
  SELECT
22738
22768
  r.id,
@@ -22772,8 +22802,9 @@ function loadVerifications(options, db) {
22772
22802
  params.push(options.plan_id);
22773
22803
  }
22774
22804
  if (options.agent_id) {
22775
- where.push("(v.agent_id = ? OR t.agent_id = ? OR t.assigned_to = ?)");
22776
- params.push(options.agent_id, options.agent_id, options.agent_id);
22805
+ params.push(options.agent_id, options.agent_id);
22806
+ const assignedInClause = lowerInClause("t.assigned_to", resolveAssignedToAliases(db, options.agent_id), params);
22807
+ where.push(`(v.agent_id = ? OR t.agent_id = ? OR ${assignedInClause})`);
22777
22808
  }
22778
22809
  if (options.since) {
22779
22810
  where.push("v.run_at >= ?");
@@ -23955,8 +23986,7 @@ function searchTasks(options, projectId, taskListId, db) {
23955
23986
  }
23956
23987
  }
23957
23988
  if (opts.assigned_to) {
23958
- sql += " AND t.assigned_to = ?";
23959
- params.push(opts.assigned_to);
23989
+ sql += ` AND ${lowerInClause("t.assigned_to", resolveAssignedToAliases(d, opts.assigned_to), params)}`;
23960
23990
  }
23961
23991
  if (opts.agent_id) {
23962
23992
  sql += " AND t.agent_id = ?";
@@ -26711,9 +26741,11 @@ async function updateTask2(id, input, store) {
26711
26741
  throw new Error(`Task ${id} version conflict: expected ${existing.version}, got ${input.version}`);
26712
26742
  }
26713
26743
  const reopened = existing.status === "completed" && input.status !== undefined && input.status !== "completed" && input.completed_at === undefined;
26744
+ const terminalNow = input.status !== undefined && isTerminalStatus(input.status);
26714
26745
  const task2 = {
26715
26746
  ...existing,
26716
26747
  ...definedPatch(input),
26748
+ ...terminalNow ? { locked_by: null, locked_at: null } : {},
26717
26749
  version: existing.version + 1,
26718
26750
  updated_at: new Date().toISOString(),
26719
26751
  tags: input.tags ?? existing.tags,
@@ -34947,8 +34979,10 @@ function getLatestHandoff(agentId, projectId, db) {
34947
34979
  function createSessionRecoveryHandoff(input, db) {
34948
34980
  const d = db || getDatabase();
34949
34981
  const limit = input.limit || 20;
34950
- const conditions = ["status = 'in_progress'", "(assigned_to = ? OR agent_id = ? OR locked_by = ?)"];
34951
- const params = [input.agent_id, input.agent_id, input.agent_id];
34982
+ const params = [];
34983
+ const assignedInClause = lowerInClause("assigned_to", resolveAssignedToAliases(d, input.agent_id), params);
34984
+ const conditions = ["status = 'in_progress'", `(${assignedInClause} OR agent_id = ? OR locked_by = ?)`];
34985
+ params.push(input.agent_id, input.agent_id);
34952
34986
  if (input.session_id) {
34953
34987
  conditions.push("session_id = ?");
34954
34988
  params.push(input.session_id);
@@ -41630,8 +41664,7 @@ function getUpcomingDueTasks(filters = {}, db) {
41630
41664
  params.push(filters.project_id);
41631
41665
  }
41632
41666
  if (filters.agent_id) {
41633
- query += " AND assigned_to = ?";
41634
- params.push(filters.agent_id);
41667
+ query += ` AND ${lowerInClause("assigned_to", resolveAssignedToAliases(d, filters.agent_id), params)}`;
41635
41668
  }
41636
41669
  query += " ORDER BY due_at ASC";
41637
41670
  const rows = d.query(query).all(...params);
@@ -41674,8 +41707,9 @@ function scanDueDateReminders(prefs, filters, d) {
41674
41707
  updated++;
41675
41708
  reminders.push(result.reminder);
41676
41709
  }
41710
+ const overdueAliases = filters.agent_id ? assignedToAliasSet(d, filters.agent_id) : null;
41677
41711
  const overdue = getOverdueTasks(filters.project_id, d).filter((t) => {
41678
- if (filters.agent_id && t.assigned_to !== filters.agent_id)
41712
+ if (overdueAliases && !overdueAliases.has((t.assigned_to ?? "").toLowerCase()))
41679
41713
  return false;
41680
41714
  return true;
41681
41715
  });
@@ -47635,27 +47669,29 @@ function getAgentMetrics(agentId, opts, db) {
47635
47669
  const agent = d.query("SELECT id, name FROM agents WHERE id = ? OR LOWER(name) = LOWER(?)").get(agentId, agentId);
47636
47670
  if (!agent)
47637
47671
  return null;
47672
+ const assignedAliases = resolveAssignedToAliases(d, agent.id).map((a) => a.toLowerCase());
47673
+ const assignedInClause = `LOWER(assigned_to) IN (${assignedAliases.map(() => "?").join(",")})`;
47638
47674
  let projectFilter2 = "";
47639
- const params = [agent.id, agent.id];
47675
+ const params = [agent.id, ...assignedAliases];
47640
47676
  if (opts?.project_id) {
47641
47677
  projectFilter2 = " AND project_id = ?";
47642
47678
  params.push(opts.project_id);
47643
47679
  }
47644
- const completed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR assigned_to = ?) AND status = 'completed'${projectFilter2}`).get(...params).count;
47645
- const failed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR assigned_to = ?) AND status = 'failed'${projectFilter2}`).get(...params).count;
47646
- const inProgress = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR assigned_to = ?) AND status = 'in_progress'${projectFilter2}`).get(...params).count;
47680
+ const completed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed'${projectFilter2}`).get(...params).count;
47681
+ const failed = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'failed'${projectFilter2}`).get(...params).count;
47682
+ const inProgress = d.query(`SELECT COUNT(*) as count FROM tasks WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'in_progress'${projectFilter2}`).get(...params).count;
47647
47683
  const total = completed + failed;
47648
47684
  const completionRate = total > 0 ? completed / total : 0;
47649
47685
  const avgTime = d.query(`SELECT AVG(
47650
47686
  (julianday(completed_at) - julianday(created_at)) * 24 * 60
47651
47687
  ) as avg_minutes
47652
47688
  FROM tasks
47653
- WHERE (agent_id = ? OR assigned_to = ?) AND status = 'completed' AND completed_at IS NOT NULL${projectFilter2}`).get(...params);
47689
+ WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed' AND completed_at IS NOT NULL${projectFilter2}`).get(...params);
47654
47690
  const avgConf = d.query(`SELECT AVG(confidence) as avg_confidence
47655
47691
  FROM tasks
47656
- WHERE (agent_id = ? OR assigned_to = ?) AND status = 'completed' AND confidence IS NOT NULL${projectFilter2}`).get(...params);
47692
+ WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed' AND confidence IS NOT NULL${projectFilter2}`).get(...params);
47657
47693
  const reviewTasks = d.query(`SELECT metadata FROM tasks
47658
- WHERE (agent_id = ? OR assigned_to = ?) AND status = 'completed'${projectFilter2}
47694
+ WHERE (agent_id = ? OR ${assignedInClause}) AND status = 'completed'${projectFilter2}
47659
47695
  AND metadata LIKE '%_review_score%'`).all(...params);
47660
47696
  let reviewScoreAvg = null;
47661
47697
  if (reviewTasks.length > 0) {
@@ -48128,6 +48164,7 @@ function queryTasksByLocalFields(query, db) {
48128
48164
  }
48129
48165
 
48130
48166
  // src/lib/saved-search-views.ts
48167
+ var SAVED_SEARCH_SCOPES = ["all", "tasks", "projects", "plans", "runs", "comments"];
48131
48168
  function parseFilters(value) {
48132
48169
  if (!value)
48133
48170
  return {};
@@ -48146,10 +48183,8 @@ function rowToSavedSearchView(row) {
48146
48183
  };
48147
48184
  }
48148
48185
  function normalizeScope(scope) {
48149
- if (scope === "all" || scope === "tasks" || scope === "projects" || scope === "plans" || scope === "runs" || scope === "comments") {
48150
- return scope;
48151
- }
48152
- return "tasks";
48186
+ const candidate = (scope ?? "").trim().toLowerCase();
48187
+ return SAVED_SEARCH_SCOPES.includes(candidate) ? candidate : "tasks";
48153
48188
  }
48154
48189
  function normalizeName3(name) {
48155
48190
  const normalized = name.trim();
@@ -49524,7 +49559,9 @@ function checkBudget(agentId, db) {
49524
49559
  }
49525
49560
  if (budget.max_cost_usd != null) {
49526
49561
  const periodStart = new Date(Date.now() - budget.period_hours * 60 * 60 * 1000).toISOString();
49527
- const costRow = d.query("SELECT COALESCE(SUM(cost_usd), 0) as total FROM tasks WHERE (assigned_to = ? OR agent_id = ?) AND updated_at > ?").get(agentId, agentId, periodStart);
49562
+ const costParams = [];
49563
+ const assignedInClause = lowerInClause("assigned_to", resolveAssignedToAliases(d, agentId), costParams);
49564
+ const costRow = d.query(`SELECT COALESCE(SUM(cost_usd), 0) as total FROM tasks WHERE (${assignedInClause} OR agent_id = ?) AND updated_at > ?`).get(...costParams, agentId, periodStart);
49528
49565
  if (costRow.total >= budget.max_cost_usd) {
49529
49566
  return { allowed: false, reason: `Cost limit reached ($${costRow.total.toFixed(2)}/$${budget.max_cost_usd.toFixed(2)} in ${budget.period_hours}h)`, current_concurrent: concurrent, max_concurrent: budget.max_concurrent, current_cost_usd: costRow.total, max_cost_usd: budget.max_cost_usd };
49530
49567
  }
@@ -52350,6 +52387,7 @@ function runTodosDoctor(options = {}) {
52350
52387
  };
52351
52388
  }
52352
52389
  // src/lib/capacity-forecasts.ts
52390
+ init_database();
52353
52391
  init_tasks();
52354
52392
  init_task_relations();
52355
52393
  init_config2();
@@ -52393,10 +52431,12 @@ function matchesProfile(profile, query) {
52393
52431
  return false;
52394
52432
  return true;
52395
52433
  }
52396
- function taskMatchesAgent(task2, agentId) {
52434
+ function taskMatchesAgent(task2, agentId, aliasSet) {
52397
52435
  if (!agentId)
52398
52436
  return true;
52399
- return task2.assigned_to === agentId || task2.agent_id === agentId;
52437
+ if (task2.agent_id === agentId)
52438
+ return true;
52439
+ return aliasSet ? aliasSet.has((task2.assigned_to ?? "").toLowerCase()) : task2.assigned_to === agentId;
52400
52440
  }
52401
52441
  function estimateRemaining(task2) {
52402
52442
  if (task2.status === "completed" || task2.status === "cancelled")
@@ -52466,7 +52506,8 @@ function removeCapacityProfile(idOrAgent, projectId) {
52466
52506
  }
52467
52507
  function getPlanningForecast(input = {}, db) {
52468
52508
  const startDate = input.start_date ? dateOnly(input.start_date) : todayIso();
52469
- const tasks = listTasks({ project_id: input.project_id, plan_id: input.plan_id, limit: 1e4 }, db).filter((task2) => taskMatchesAgent(task2, input.agent_id));
52509
+ const aliasSet = input.agent_id ? assignedToAliasSet(db || getDatabase(), input.agent_id) : undefined;
52510
+ const tasks = listTasks({ project_id: input.project_id, plan_id: input.plan_id, limit: 1e4 }, db).filter((task2) => taskMatchesAgent(task2, input.agent_id, aliasSet));
52470
52511
  const reportByTask = new Map(getTimeReport({ project_id: input.project_id, plan_id: input.plan_id, agent_id: input.agent_id, include_open: true }, db).map((entry2) => [entry2.task_id, entry2]));
52471
52512
  const profiles = listCapacityProfiles({ agent_id: input.agent_id, project_id: input.project_id });
52472
52513
  const globalProfiles = input.project_id ? listCapacityProfiles({ agent_id: input.agent_id }).filter((profile) => profile.project_id === null) : [];
@@ -1 +1 @@
1
- {"version":3,"file":"capacity-forecasts.d.ts","sourceRoot":"","sources":["../../src/lib/capacity-forecasts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capacity-forecasts.d.ts","sourceRoot":"","sources":["../../src/lib/capacity-forecasts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAK3C,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,MAAM,MAAM,gBAAgB,GACxB,mBAAmB,GACnB,aAAa,GACb,mBAAmB,GACnB,aAAa,GACb,oBAAoB,CAAC;AAEzB,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,2BAA2B,EAAE,MAAM,CAAC;IACpC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,OAAO,6BAA6B,CAAC;IACrD,UAAU,EAAE,IAAI,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,iBAAiB,EAAE,0BAA0B,EAAE,CAAC;IAChD,wBAAwB,EAAE,MAAM,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2BAA2B,EAAE,MAAM,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,KAAK,EAAE,oBAAoB,EAAE,CAAC;CAC/B;AAuFD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,GAAG,0BAA0B,CAqBnG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,GAAE,oBAAyB,GAAG,0BAA0B,EAAE,CAInG;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAU3F;AAED,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,qBAA0B,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,gBAAgB,CA2EtG;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAkBjF"}
@@ -1 +1 @@
1
- {"version":3,"file":"completion-guard.d.ts","sourceRoot":"","sources":["../../src/lib/completion-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGnF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,EAAE,EAAE,QAAQ,EACZ,cAAc,CAAC,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAC/C,IAAI,CAyEN"}
1
+ {"version":3,"file":"completion-guard.d.ts","sourceRoot":"","sources":["../../src/lib/completion-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAInF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,EAAE,EAAE,QAAQ,EACZ,cAAc,CAAC,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAC/C,IAAI,CAqFN"}