@hasna/todos 0.11.65 → 0.11.66

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/index.js CHANGED
@@ -7733,39 +7733,9 @@ function ensureTaskList(name, slug, projectId, db) {
7733
7733
  return createTaskList({ name, slug, project_id: projectId }, d);
7734
7734
  }
7735
7735
 
7736
- // src/lib/shared-events.ts
7737
- var SOURCE = "todos";
7738
- function taskEventData(task, extra = {}) {
7739
- return {
7740
- id: task.id,
7741
- task_id: task.id,
7742
- short_id: task.short_id,
7743
- title: task.title,
7744
- description: task.description,
7745
- status: task.status,
7746
- priority: task.priority,
7747
- project_id: task.project_id,
7748
- parent_id: task.parent_id,
7749
- plan_id: task.plan_id,
7750
- task_list_id: task.task_list_id,
7751
- agent_id: task.agent_id,
7752
- assigned_to: task.assigned_to,
7753
- session_id: task.session_id,
7754
- working_dir: task.working_dir,
7755
- tags: task.tags,
7756
- metadata: task.metadata,
7757
- version: task.version,
7758
- created_at: task.created_at,
7759
- updated_at: task.updated_at,
7760
- started_at: task.started_at,
7761
- completed_at: task.completed_at,
7762
- due_at: task.due_at,
7763
- requires_approval: task.requires_approval,
7764
- approved_by: task.approved_by,
7765
- approved_at: task.approved_at,
7766
- ...extra
7767
- };
7768
- }
7736
+ // src/lib/task-route-contract.ts
7737
+ var TODOS_TASK_ROUTE_STATE_SCHEMA_VERSION = "todos.task_route_state.v1";
7738
+ var TASK_WORKFLOW_POINTER_SCHEMA_VERSION = "todos.task_workflow_pointer.v1";
7769
7739
  function booleanField(value) {
7770
7740
  if (typeof value === "boolean")
7771
7741
  return value;
@@ -7787,21 +7757,31 @@ function booleanField(value) {
7787
7757
  function objectField(value) {
7788
7758
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
7789
7759
  }
7790
- function firstBoolean(records, keys) {
7760
+ function collectBooleans(records, keys) {
7761
+ const values = [];
7791
7762
  for (const record of records) {
7763
+ if (!record)
7764
+ continue;
7792
7765
  for (const key of keys) {
7793
7766
  const value = booleanField(record[key]);
7794
7767
  if (value !== undefined)
7795
- return value;
7768
+ values.push(value);
7796
7769
  }
7797
7770
  }
7798
- return;
7771
+ return values;
7799
7772
  }
7800
- function routingAutomationMetadata(task) {
7801
- const automation = objectField(task.metadata.automation);
7802
- const records = [task.metadata];
7803
- if (automation)
7804
- records.push(automation);
7773
+ function mergedBoolean(records, keys, trueWins) {
7774
+ const values = collectBooleans(records, keys);
7775
+ if (values.length === 0)
7776
+ return;
7777
+ if (trueWins)
7778
+ return values.some(Boolean);
7779
+ return values.includes(false) ? false : true;
7780
+ }
7781
+ function routingAutomationMetadata(task, taskList) {
7782
+ const taskAutomation = objectField(task.metadata.automation);
7783
+ const taskListAutomation = taskList ? objectField(taskList.metadata.automation) : undefined;
7784
+ const records = [task.metadata, taskAutomation, taskList?.metadata, taskListAutomation];
7805
7785
  const result = {};
7806
7786
  const aliases = [
7807
7787
  ["allowed", ["allowed", "automation_allowed", "automationAllowed"]],
@@ -7812,7 +7792,7 @@ function routingAutomationMetadata(task) {
7812
7792
  ["approval_required", ["approval_required", "approvalRequired"]]
7813
7793
  ];
7814
7794
  for (const [canonical, keys] of aliases) {
7815
- const value = firstBoolean(records, keys);
7795
+ const value = mergedBoolean(records, keys, canonical !== "allowed");
7816
7796
  if (value !== undefined)
7817
7797
  result[canonical] = value;
7818
7798
  }
@@ -7820,23 +7800,91 @@ function routingAutomationMetadata(task) {
7820
7800
  result.requires_approval = true;
7821
7801
  return Object.keys(result).length > 0 ? result : undefined;
7822
7802
  }
7803
+ function routeEnabledForTask(task, taskList) {
7804
+ const explicit = booleanField(task.metadata.route_enabled);
7805
+ if (explicit !== undefined)
7806
+ return explicit;
7807
+ if (task.tags.includes("auto:route") || task.tags.includes("route:enabled"))
7808
+ return true;
7809
+ const taskListDefault = taskList ? booleanField(taskList.metadata.route_enabled) : undefined;
7810
+ if (taskListDefault !== undefined)
7811
+ return taskListDefault;
7812
+ return;
7813
+ }
7814
+ function stringField(value) {
7815
+ return typeof value === "string" && value.trim() ? value : undefined;
7816
+ }
7817
+ function workflowPointersFromMetadata(metadata) {
7818
+ const nested = objectField(metadata.workflow_invocation) ?? objectField(metadata.workflow) ?? {};
7819
+ return {
7820
+ current_workflow_invocation_id: stringField(metadata.current_workflow_invocation_id) ?? stringField(nested.current_workflow_invocation_id) ?? stringField(nested.invocation_id),
7821
+ current_run_id: stringField(metadata.current_run_id) ?? stringField(nested.current_run_id) ?? stringField(nested.run_id),
7822
+ latest_manifest_path: stringField(metadata.latest_manifest_path) ?? stringField(nested.latest_manifest_path) ?? stringField(nested.manifest_path),
7823
+ latest_evaluation_path: stringField(metadata.latest_evaluation_path) ?? stringField(nested.latest_evaluation_path) ?? stringField(nested.evaluation_path),
7824
+ workflow_state: stringField(metadata.workflow_state) ?? stringField(nested.workflow_state) ?? stringField(nested.state)
7825
+ };
7826
+ }
7827
+ function compactWorkflowPointers(pointers) {
7828
+ return Object.fromEntries(Object.entries(pointers).filter(([, value]) => typeof value === "string" && value.length > 0));
7829
+ }
7830
+ function classifyProjectKind(path) {
7831
+ return path.includes("/hasna/opensource/") ? "open-source" : "unknown";
7832
+ }
7833
+ function isWorktreePath(path) {
7834
+ return path.includes("/.codewith/worktrees/") || path.includes("/.worktrees/");
7835
+ }
7836
+ function inferRootProjectId(project) {
7837
+ return isWorktreePath(project.path) ? null : project.id;
7838
+ }
7839
+
7840
+ // src/lib/shared-events.ts
7841
+ var SOURCE = "todos";
7842
+ function taskEventData(task, extra = {}) {
7843
+ return {
7844
+ id: task.id,
7845
+ task_id: task.id,
7846
+ short_id: task.short_id,
7847
+ title: task.title,
7848
+ description: task.description,
7849
+ status: task.status,
7850
+ priority: task.priority,
7851
+ project_id: task.project_id,
7852
+ parent_id: task.parent_id,
7853
+ plan_id: task.plan_id,
7854
+ task_list_id: task.task_list_id,
7855
+ agent_id: task.agent_id,
7856
+ assigned_to: task.assigned_to,
7857
+ session_id: task.session_id,
7858
+ working_dir: task.working_dir,
7859
+ tags: task.tags,
7860
+ metadata: task.metadata,
7861
+ version: task.version,
7862
+ created_at: task.created_at,
7863
+ updated_at: task.updated_at,
7864
+ started_at: task.started_at,
7865
+ completed_at: task.completed_at,
7866
+ due_at: task.due_at,
7867
+ requires_approval: task.requires_approval,
7868
+ approved_by: task.approved_by,
7869
+ approved_at: task.approved_at,
7870
+ ...extra
7871
+ };
7872
+ }
7823
7873
  function taskEventMetadata(task) {
7824
7874
  const metadata = {
7825
7875
  package: "@hasna/todos",
7826
7876
  todos_event_schema_version: 1,
7877
+ route_state_schema_version: TODOS_TASK_ROUTE_STATE_SCHEMA_VERSION,
7827
7878
  task_id: task.id,
7828
7879
  task_short_id: task.short_id,
7829
7880
  project_id: task.project_id,
7830
7881
  task_list_id: task.task_list_id,
7831
7882
  working_dir: task.working_dir
7832
7883
  };
7833
- const routeEnabled = booleanField(task.metadata.route_enabled);
7834
- if (routeEnabled !== undefined) {
7835
- metadata.route_enabled = routeEnabled;
7836
- }
7837
- const automation = routingAutomationMetadata(task);
7838
- if (automation) {
7839
- metadata.automation = automation;
7884
+ const pointers = workflowPointersFromMetadata(task.metadata);
7885
+ for (const [key, value] of Object.entries(pointers)) {
7886
+ if (value)
7887
+ metadata[key] = value;
7840
7888
  }
7841
7889
  try {
7842
7890
  const project = task.project_id ? getProject(task.project_id) : null;
@@ -7865,18 +7913,20 @@ function taskEventMetadata(task) {
7865
7913
  metadata.task_list_project_id = taskList.project_id;
7866
7914
  metadata.task_list_is_project_default = Boolean(project?.task_list_id && taskList.slug === project.task_list_id);
7867
7915
  }
7916
+ const routeEnabled = routeEnabledForTask(task, taskList);
7917
+ if (routeEnabled !== undefined) {
7918
+ metadata.route_enabled = routeEnabled;
7919
+ }
7920
+ const automation = routingAutomationMetadata(task, taskList);
7921
+ if (automation) {
7922
+ metadata.automation = automation;
7923
+ metadata.route_blocked_by_no_auto = automation.no_auto === true;
7924
+ metadata.route_blocked_by_manual = automation.manual === true || automation.manual_required === true;
7925
+ metadata.route_blocked_by_approval = (automation.requires_approval === true || automation.approval_required === true) && !task.approved_by;
7926
+ }
7868
7927
  } catch {}
7869
7928
  return metadata;
7870
7929
  }
7871
- function classifyProjectKind(path) {
7872
- return path.includes("/hasna/opensource/") ? "open-source" : "unknown";
7873
- }
7874
- function isWorktreePath(path) {
7875
- return path.includes("/.codewith/worktrees/") || path.includes("/.worktrees/");
7876
- }
7877
- function inferRootProjectId(project) {
7878
- return isWorktreePath(project.path) ? null : project.id;
7879
- }
7880
7930
  function readMachineLocalPath(project) {
7881
7931
  const machineId = process.env["TODOS_MACHINE_ID"];
7882
7932
  if (!machineId)
@@ -25578,7 +25628,19 @@ function bootstrapProject(options = {}, db) {
25578
25628
  }
25579
25629
  setMachineLocalPath(project.id, discovery.projectPath, d);
25580
25630
  const beforeTaskList = d.query("SELECT id FROM task_lists WHERE project_id = ? AND slug = ?").get(project.id, taskListSlug);
25581
- const taskList = ensureTaskList(`${project.name} Tasks`, taskListSlug, project.id, d);
25631
+ let taskList = ensureTaskList(`${project.name} Tasks`, taskListSlug, project.id, d);
25632
+ if (options.routeEnabled && taskList.metadata.route_enabled !== true) {
25633
+ taskList = updateTaskList(taskList.id, {
25634
+ metadata: {
25635
+ ...taskList.metadata,
25636
+ route_enabled: true,
25637
+ automation: {
25638
+ ...taskList.metadata.automation && typeof taskList.metadata.automation === "object" && !Array.isArray(taskList.metadata.automation) ? taskList.metadata.automation : {},
25639
+ no_auto: false
25640
+ }
25641
+ }
25642
+ }, d);
25643
+ }
25582
25644
  const createdSources = [];
25583
25645
  for (const source9 of [
25584
25646
  addSourceOnce(project.id, "local", "Project root", discovery.projectPath, { role: "project-root" }, d),
@@ -25622,6 +25684,172 @@ function getProjectByPathForBootstrap(path, db) {
25622
25684
  WHERE pmp.path = ?`).get(path);
25623
25685
  return machineRow ?? null;
25624
25686
  }
25687
+ // src/lib/task-routing.ts
25688
+ init_database();
25689
+ function classifyProjectKind2(path) {
25690
+ if (!path)
25691
+ return null;
25692
+ return path.includes("/hasna/opensource/") ? "open-source" : "unknown";
25693
+ }
25694
+ function machineLocalPath(project, db) {
25695
+ const machineId = process.env["TODOS_MACHINE_ID"];
25696
+ if (!machineId)
25697
+ return null;
25698
+ try {
25699
+ const row = db.query("SELECT path FROM project_machine_paths WHERE project_id = ? AND machine_id = ?").get(project.id, machineId);
25700
+ return row?.path ?? null;
25701
+ } catch {
25702
+ return null;
25703
+ }
25704
+ }
25705
+ function resolveProject(task2, db) {
25706
+ const project = task2.project_id ? getProject(task2.project_id, db) : null;
25707
+ const projectPath = project ? machineLocalPath(project, db) ?? project.path : task2.working_dir;
25708
+ return { project, projectPath: projectPath ?? null };
25709
+ }
25710
+ function resolveTaskList(task2, project, db) {
25711
+ if (task2.task_list_id) {
25712
+ return getTaskList(task2.task_list_id, db) ?? (project ? getTaskListBySlug(task2.task_list_id, project.id, db) : null);
25713
+ }
25714
+ if (project?.task_list_id) {
25715
+ return getTaskListBySlug(project.task_list_id, project.id, db);
25716
+ }
25717
+ return null;
25718
+ }
25719
+ function isTerminal2(status) {
25720
+ return status === "completed" || status === "cancelled" || status === "failed";
25721
+ }
25722
+ function routeConcurrencyKey(task2, project, taskList, projectPath) {
25723
+ if (project?.id)
25724
+ return `project:${project.id}`;
25725
+ if (taskList?.id)
25726
+ return `task-list:${taskList.id}`;
25727
+ if (projectPath)
25728
+ return `path:${projectPath}`;
25729
+ return `task:${task2.id}`;
25730
+ }
25731
+ function getTaskRouteState(taskOrId, db) {
25732
+ const d = db || getDatabase();
25733
+ const task2 = typeof taskOrId === "string" ? getTask(taskOrId, d) : taskOrId;
25734
+ if (!task2)
25735
+ throw new Error(`Task not found: ${taskOrId}`);
25736
+ const { project, projectPath } = resolveProject(task2, d);
25737
+ const taskList = resolveTaskList(task2, project, d);
25738
+ const automation = routingAutomationMetadata(task2, taskList) ?? {};
25739
+ const routeEnabled = routeEnabledForTask(task2, taskList) === true;
25740
+ const tagOptIn = task2.tags.includes("auto:route") || task2.tags.includes("route:enabled");
25741
+ const locked = Boolean(task2.locked_by && !isLockExpired(task2.locked_at));
25742
+ const blockers = getBlockingDeps(task2.id, d);
25743
+ const blocked = blockers.length > 0;
25744
+ const terminal = isTerminal2(task2.status);
25745
+ const requiresApproval = automation.requires_approval === true || task2.requires_approval === true;
25746
+ const approvalRequired = automation.approval_required === true;
25747
+ const approved = Boolean(task2.approved_by);
25748
+ const gates = {
25749
+ route_enabled: routeEnabled,
25750
+ tag_opt_in: tagOptIn,
25751
+ no_auto: automation.no_auto === true,
25752
+ manual: automation.manual === true,
25753
+ manual_required: automation.manual_required === true,
25754
+ requires_approval: requiresApproval,
25755
+ approval_required: approvalRequired,
25756
+ approved,
25757
+ locked,
25758
+ blocked,
25759
+ terminal
25760
+ };
25761
+ const reasons = [];
25762
+ if (task2.status !== "pending")
25763
+ reasons.push("task_not_pending");
25764
+ if (terminal)
25765
+ reasons.push("task_terminal");
25766
+ if (!routeEnabled)
25767
+ reasons.push("route_not_enabled");
25768
+ if (locked)
25769
+ reasons.push("task_locked");
25770
+ if (blocked)
25771
+ reasons.push("task_blocked");
25772
+ if (gates.no_auto)
25773
+ reasons.push("no_auto");
25774
+ if (gates.manual)
25775
+ reasons.push("manual");
25776
+ if (gates.manual_required)
25777
+ reasons.push("manual_required");
25778
+ if (requiresApproval && !approved)
25779
+ reasons.push("requires_approval");
25780
+ if (approvalRequired && !approved)
25781
+ reasons.push("approval_required");
25782
+ if (automation.allowed === false)
25783
+ reasons.push("automation_disallowed");
25784
+ return {
25785
+ schema_version: TODOS_TASK_ROUTE_STATE_SCHEMA_VERSION,
25786
+ task_id: task2.id,
25787
+ task_short_id: task2.short_id,
25788
+ status: task2.status,
25789
+ eligible: reasons.length === 0,
25790
+ reasons,
25791
+ blockers: blockers.map((blocker) => ({
25792
+ id: blocker.id,
25793
+ short_id: blocker.short_id,
25794
+ title: blocker.title,
25795
+ status: blocker.status
25796
+ })),
25797
+ gates,
25798
+ automation: Object.keys(automation).length > 0 ? automation : null,
25799
+ route: {
25800
+ project_id: project?.id ?? task2.project_id,
25801
+ project_path: projectPath,
25802
+ working_dir: task2.working_dir ?? projectPath,
25803
+ project_kind: classifyProjectKind2(projectPath),
25804
+ task_list_id: taskList?.id ?? task2.task_list_id,
25805
+ task_list_slug: taskList?.slug ?? null,
25806
+ task_list_name: taskList?.name ?? null,
25807
+ concurrency_key: routeConcurrencyKey(task2, project, taskList, projectPath)
25808
+ },
25809
+ pointers: workflowPointersFromMetadata(task2.metadata)
25810
+ };
25811
+ }
25812
+ function setTaskWorkflowPointers(taskId, input, db) {
25813
+ const d = db || getDatabase();
25814
+ const task2 = getTask(taskId, d);
25815
+ if (!task2)
25816
+ throw new Error(`Task not found: ${taskId}`);
25817
+ const previous = workflowPointersFromMetadata(task2.metadata);
25818
+ const next = compactWorkflowPointers({
25819
+ current_workflow_invocation_id: pointerPatch(previous.current_workflow_invocation_id, input, "current_workflow_invocation_id"),
25820
+ current_run_id: pointerPatch(previous.current_run_id, input, "current_run_id"),
25821
+ latest_manifest_path: pointerPatch(previous.latest_manifest_path, input, "latest_manifest_path"),
25822
+ latest_evaluation_path: pointerPatch(previous.latest_evaluation_path, input, "latest_evaluation_path"),
25823
+ workflow_state: pointerPatch(previous.workflow_state, input, "workflow_state")
25824
+ });
25825
+ const timestamp2 = now();
25826
+ const {
25827
+ current_workflow_invocation_id,
25828
+ current_run_id,
25829
+ latest_manifest_path,
25830
+ latest_evaluation_path,
25831
+ workflow_state,
25832
+ workflow_invocation,
25833
+ ...baseMetadata
25834
+ } = task2.metadata;
25835
+ const metadata = {
25836
+ ...baseMetadata,
25837
+ ...next,
25838
+ workflow_invocation: {
25839
+ schema_version: TASK_WORKFLOW_POINTER_SCHEMA_VERSION,
25840
+ ...next,
25841
+ updated_at: timestamp2,
25842
+ updated_by: input.actor ?? null
25843
+ }
25844
+ };
25845
+ return updateTask(task2.id, { version: task2.version, metadata }, d);
25846
+ }
25847
+ function pointerPatch(previous, input, key) {
25848
+ if (!Object.prototype.hasOwnProperty.call(input, key))
25849
+ return previous;
25850
+ const value = input[key];
25851
+ return typeof value === "string" && value.trim() ? value : undefined;
25852
+ }
25625
25853
  // src/db/api-keys.ts
25626
25854
  init_database();
25627
25855
  import { createHash as createHash10, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual3 } from "crypto";
@@ -44081,6 +44309,7 @@ export {
44081
44309
  writeBackupManifest,
44082
44310
  writeArtifactExportManifest,
44083
44311
  wrapWithSchemaVersion,
44312
+ workflowPointersFromMetadata,
44084
44313
  watchSourceTodos,
44085
44314
  verifyTaskRunArtifacts,
44086
44315
  verifyStoredArtifact,
@@ -44180,6 +44409,7 @@ export {
44180
44409
  shouldRegisterToolForProfile2 as shouldRegisterToolForAccessProfile,
44181
44410
  setupEphemeralDemoDb,
44182
44411
  setTaskWorkflowState,
44412
+ setTaskWorkflowPointers,
44183
44413
  setTaskStatus,
44184
44414
  setTaskPriorityMeta,
44185
44415
  setTaskPriority,
@@ -44222,6 +44452,8 @@ export {
44222
44452
  runNextAgentDispatch,
44223
44453
  runDueDispatches,
44224
44454
  runAgentWorkflowDemo,
44455
+ routingAutomationMetadata,
44456
+ routeEnabledForTask,
44225
44457
  revokeApiKey,
44226
44458
  returnReviewItem,
44227
44459
  retryAgentRunDispatch,
@@ -44358,6 +44590,7 @@ export {
44358
44590
  parseFeedback,
44359
44591
  parseErrorPaste,
44360
44592
  parseCiLog,
44593
+ objectField,
44361
44594
  now,
44362
44595
  notifyUpcomingDeadlines2 as notifyUpcomingDeadlines,
44363
44596
  normalizeTesterIssueReport,
@@ -44490,6 +44723,7 @@ export {
44490
44723
  linkRunVerification,
44491
44724
  linkRunArtifact,
44492
44725
  issueToTask,
44726
+ isWorktreePath,
44493
44727
  isValidRecurrenceRule,
44494
44728
  isTodosRemoteStorageEnabled,
44495
44729
  isSnapshotStale,
@@ -44503,6 +44737,7 @@ export {
44503
44737
  inspectGitCommit,
44504
44738
  inspectExtensionSource,
44505
44739
  initBuiltinTemplates,
44740
+ inferRootProjectId,
44506
44741
  importUserScaffold,
44507
44742
  importTodosMarkdown,
44508
44743
  importTemplateFromFile,
@@ -44554,6 +44789,7 @@ export {
44554
44789
  getTaskStats,
44555
44790
  getTaskRunLedger,
44556
44791
  getTaskRun,
44792
+ getTaskRouteState,
44557
44793
  getTaskReview,
44558
44794
  getTaskRelationships,
44559
44795
  getTaskRelationship,
@@ -44924,6 +45160,7 @@ export {
44924
45160
  completeAgentRun,
44925
45161
  compareEnvironmentSnapshots,
44926
45162
  compareEnvironmentSnapshotFiles,
45163
+ compactWorkflowPointers,
44927
45164
  compactScaleStorage,
44928
45165
  compactDatabase,
44929
45166
  collectCliCommandEntries,
@@ -44934,6 +45171,7 @@ export {
44934
45171
  clearActiveModel,
44935
45172
  cleanupArtifacts,
44936
45173
  cleanExpiredLocks,
45174
+ classifyProjectKind,
44937
45175
  claimReviewItem,
44938
45176
  claimPlanStep,
44939
45177
  claimOrSteal,
@@ -44978,6 +45216,7 @@ export {
44978
45216
  buildCodebaseIndex,
44979
45217
  buildArtifactExportManifest,
44980
45218
  bootstrapProject,
45219
+ booleanField,
44981
45220
  beginTaskRunTransaction,
44982
45221
  backupDatabase,
44983
45222
  autoReleaseStaleAgents,
@@ -45028,6 +45267,7 @@ export {
45028
45267
  TaskNotFoundError,
45029
45268
  TaskListNotFoundError,
45030
45269
  TUI_DASHBOARD_VIEWS,
45270
+ TODOS_TASK_ROUTE_STATE_SCHEMA_VERSION,
45031
45271
  TODOS_STORAGE_TABLES,
45032
45272
  TODOS_STORAGE_FALLBACK_ENV,
45033
45273
  TODOS_STORAGE_ENV,
@@ -45061,6 +45301,7 @@ export {
45061
45301
  TESTERS_ISSUE_REPORT_SCHEMA_VERSION,
45062
45302
  TESTERS_ISSUE_REPORT_RESULT_SCHEMA_VERSION,
45063
45303
  TESTERS_ISSUE_REPORT_BATCH_RESULT_SCHEMA_VERSION,
45304
+ TASK_WORKFLOW_POINTER_SCHEMA_VERSION,
45064
45305
  TASK_STATUSES,
45065
45306
  TASK_SCHEDULING_SCHEMA,
45066
45307
  TASK_PRIORITIES,
@@ -5,6 +5,7 @@ export interface ProjectBootstrapOptions {
5
5
  name?: string;
6
6
  taskListSlug?: string;
7
7
  dryRun?: boolean;
8
+ routeEnabled?: boolean;
8
9
  }
9
10
  export interface ProjectWorkspaceDiscovery {
10
11
  inputPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"project-bootstrap.d.ts","sourceRoot":"","sources":["../../src/lib/project-bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAa3C,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE1E,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,yBAAyB,CAAC;IACrC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,OAAO,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH;AA6DD,wBAAgB,wBAAwB,CAAC,SAAS,SAAgB,GAAG,yBAAyB,CAuB7F;AAkBD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,sBAAsB,CA2D7G"}
1
+ {"version":3,"file":"project-bootstrap.d.ts","sourceRoot":"","sources":["../../src/lib/project-bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAa3C,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE1E,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,yBAAyB,CAAC;IACrC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,OAAO,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH;AA6DD,wBAAgB,wBAAwB,CAAC,SAAS,SAAgB,GAAG,yBAAyB,CAuB7F;AAkBD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,sBAAsB,CAyE7G"}
@@ -1 +1 @@
1
- {"version":3,"file":"shared-events.d.ts","sourceRoot":"","sources":["../../src/lib/shared-events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAKnD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,eAAe,GACf,qBAAqB,GACrB,gBAAgB,CAAC;AAErB,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA8BtG;AA0ID,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAehB;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAE/F"}
1
+ {"version":3,"file":"shared-events.d.ts","sourceRoot":"","sources":["../../src/lib/shared-events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAKnD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAa9C,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,eAAe,GACf,qBAAqB,GACrB,gBAAgB,CAAC;AAErB,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA8BtG;AAmFD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAehB;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAE/F"}
@@ -0,0 +1,33 @@
1
+ import type { Project, Task, TaskList } from "../types/index.js";
2
+ export declare const TODOS_TASK_ROUTE_STATE_SCHEMA_VERSION = "todos.task_route_state.v1";
3
+ export declare const TASK_WORKFLOW_POINTER_SCHEMA_VERSION = "todos.task_workflow_pointer.v1";
4
+ export interface TaskRoutingAutomationMetadata {
5
+ allowed?: boolean;
6
+ no_auto?: boolean;
7
+ manual?: boolean;
8
+ manual_required?: boolean;
9
+ requires_approval?: boolean;
10
+ approval_required?: boolean;
11
+ }
12
+ export interface TaskWorkflowPointers {
13
+ current_workflow_invocation_id?: string;
14
+ current_run_id?: string;
15
+ latest_manifest_path?: string;
16
+ latest_evaluation_path?: string;
17
+ workflow_state?: string;
18
+ }
19
+ export interface ResolvedTaskRouteContext {
20
+ project?: Project | null;
21
+ projectPath?: string | null;
22
+ taskList?: TaskList | null;
23
+ }
24
+ export declare function booleanField(value: unknown): boolean | undefined;
25
+ export declare function objectField(value: unknown): Record<string, unknown> | undefined;
26
+ export declare function routingAutomationMetadata(task: Pick<Task, "metadata" | "requires_approval">, taskList?: Pick<TaskList, "metadata"> | null): TaskRoutingAutomationMetadata | undefined;
27
+ export declare function routeEnabledForTask(task: Pick<Task, "metadata" | "tags">, taskList?: Pick<TaskList, "metadata"> | null): boolean | undefined;
28
+ export declare function workflowPointersFromMetadata(metadata: Record<string, unknown>): TaskWorkflowPointers;
29
+ export declare function compactWorkflowPointers(pointers: TaskWorkflowPointers): TaskWorkflowPointers;
30
+ export declare function classifyProjectKind(path: string): string;
31
+ export declare function isWorktreePath(path: string): boolean;
32
+ export declare function inferRootProjectId(project: Project): string | null;
33
+ //# sourceMappingURL=task-route-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-route-contract.d.ts","sourceRoot":"","sources":["../../src/lib/task-route-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEjE,eAAO,MAAM,qCAAqC,8BAA8B,CAAC;AACjF,eAAO,MAAM,oCAAoC,mCAAmC,CAAC;AAErF,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAYhE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAE/E;AAqBD,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,mBAAmB,CAAC,EAClD,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,IAAI,GAC3C,6BAA6B,GAAG,SAAS,CAsB3C;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,CAO5I;AAMD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB,CAcpG;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,oBAAoB,CAI5F;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAElE"}
@@ -0,0 +1,55 @@
1
+ import type { Database } from "bun:sqlite";
2
+ import type { Task } from "../types/index.js";
3
+ import { TODOS_TASK_ROUTE_STATE_SCHEMA_VERSION, type TaskRoutingAutomationMetadata, type TaskWorkflowPointers } from "./task-route-contract.js";
4
+ export interface TaskRouteGates {
5
+ route_enabled: boolean;
6
+ tag_opt_in: boolean;
7
+ no_auto: boolean;
8
+ manual: boolean;
9
+ manual_required: boolean;
10
+ requires_approval: boolean;
11
+ approval_required: boolean;
12
+ approved: boolean;
13
+ locked: boolean;
14
+ blocked: boolean;
15
+ terminal: boolean;
16
+ }
17
+ export interface TaskRouteContext {
18
+ project_id: string | null;
19
+ project_path: string | null;
20
+ working_dir: string | null;
21
+ project_kind: string | null;
22
+ task_list_id: string | null;
23
+ task_list_slug: string | null;
24
+ task_list_name: string | null;
25
+ concurrency_key: string;
26
+ }
27
+ export interface TaskRouteState {
28
+ schema_version: typeof TODOS_TASK_ROUTE_STATE_SCHEMA_VERSION;
29
+ task_id: string;
30
+ task_short_id: string | null;
31
+ status: Task["status"];
32
+ eligible: boolean;
33
+ reasons: string[];
34
+ blockers: Array<{
35
+ id: string;
36
+ short_id: string | null;
37
+ title: string;
38
+ status: Task["status"];
39
+ }>;
40
+ gates: TaskRouteGates;
41
+ automation: TaskRoutingAutomationMetadata | null;
42
+ route: TaskRouteContext;
43
+ pointers: TaskWorkflowPointers;
44
+ }
45
+ export interface SetTaskWorkflowPointersInput {
46
+ current_workflow_invocation_id?: string | null;
47
+ current_run_id?: string | null;
48
+ latest_manifest_path?: string | null;
49
+ latest_evaluation_path?: string | null;
50
+ workflow_state?: string | null;
51
+ actor?: string;
52
+ }
53
+ export declare function getTaskRouteState(taskOrId: Task | string, db?: Database): TaskRouteState;
54
+ export declare function setTaskWorkflowPointers(taskId: string, input: SetTaskWorkflowPointersInput, db?: Database): Task;
55
+ //# sourceMappingURL=task-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-routing.d.ts","sourceRoot":"","sources":["../../src/lib/task-routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAM3C,OAAO,KAAK,EAAW,IAAI,EAAY,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAKL,qCAAqC,EAErC,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,OAAO,qCAAqC,CAAC;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC,CAAC;IAChG,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,6BAA6B,GAAG,IAAI,CAAC;IACjD,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,oBAAoB,CAAC;CAChC;AAED,MAAM,WAAW,4BAA4B;IAC3C,8BAA8B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+CD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,IAAI,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,cAAc,CAwExF;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,4BAA4B,EACnC,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,CAoCN"}