@hasna/todos 0.15.18 → 0.15.20

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 (47) hide show
  1. package/dist/cli/cloud-router.d.ts +20 -1
  2. package/dist/cli/cloud-router.d.ts.map +1 -1
  3. package/dist/cli/commands/project-commands.d.ts.map +1 -1
  4. package/dist/cli/commands/query-commands.d.ts.map +1 -1
  5. package/dist/cli/commands/task-commands.d.ts.map +1 -1
  6. package/dist/cli/index.js +1306 -122
  7. package/dist/cli/stage-a.d.ts +21 -10
  8. package/dist/cli/stage-a.d.ts.map +1 -1
  9. package/dist/contracts.js +283 -16
  10. package/dist/db/audit.d.ts +8 -0
  11. package/dist/db/audit.d.ts.map +1 -1
  12. package/dist/db/plans.d.ts +4 -0
  13. package/dist/db/plans.d.ts.map +1 -1
  14. package/dist/db/task-lifecycle.d.ts +7 -1
  15. package/dist/db/task-lifecycle.d.ts.map +1 -1
  16. package/dist/db/tasks.d.ts +1 -1
  17. package/dist/db/tasks.d.ts.map +1 -1
  18. package/dist/index.js +599 -26
  19. package/dist/lib/cli-help.d.ts +3 -2
  20. package/dist/lib/cli-help.d.ts.map +1 -1
  21. package/dist/lib/stale-lock-handoff.d.ts +25 -0
  22. package/dist/lib/stale-lock-handoff.d.ts.map +1 -0
  23. package/dist/mcp/index.js +954 -46
  24. package/dist/mcp.js +3 -1
  25. package/dist/project-registration.js +4250 -3684
  26. package/dist/registry.js +283 -16
  27. package/dist/release-provenance.json +5 -5
  28. package/dist/sdk/index.js +7 -0
  29. package/dist/sdk/v1.generated.d.ts +40 -1
  30. package/dist/sdk/v1.generated.d.ts.map +1 -1
  31. package/dist/server/index.js +1287 -379
  32. package/dist/server/openapi.d.ts +232 -0
  33. package/dist/server/openapi.d.ts.map +1 -1
  34. package/dist/server/v1.d.ts.map +1 -1
  35. package/dist/storage/audit-history-import.d.ts +14 -0
  36. package/dist/storage/audit-history-import.d.ts.map +1 -0
  37. package/dist/storage/interfaces.d.ts +22 -1
  38. package/dist/storage/interfaces.d.ts.map +1 -1
  39. package/dist/storage/local-sqlite.d.ts.map +1 -1
  40. package/dist/storage/postgres-adapter.d.ts.map +1 -1
  41. package/dist/storage/shadow.d.ts.map +1 -1
  42. package/dist/storage/sqlite-snapshot.d.ts.map +1 -1
  43. package/dist/storage.js +596 -25
  44. package/dist/task-manifest.js +24 -1
  45. package/dist/types/index.d.ts +50 -0
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/package.json +3 -1
@@ -3,6 +3,7 @@ type Env = Record<string, string | undefined>;
3
3
  export type TodosCliAuthorityInitialization = {
4
4
  route: "local";
5
5
  v1_base_url: null;
6
+ selected_by?: "local-only-command";
6
7
  } | {
7
8
  route: "remote-diagnostic";
8
9
  v1_base_url: string | null;
@@ -11,6 +12,14 @@ export type TodosCliAuthorityInitialization = {
11
12
  v1_base_url: string;
12
13
  };
13
14
  export type TodosCliCommandOwner = "diagnostic" | "remote-http" | "local-only";
15
+ /**
16
+ * Stage A is intentionally pure: it decides the authority route without
17
+ * mutating the caller's environment. The executable applies that decision
18
+ * before importing command modules so any later `getTodosCloudClient()` call
19
+ * observes the same local-only route instead of reconstructing hosted routing
20
+ * from the ambient selector.
21
+ */
22
+ export declare function applyTodosCliAuthorityEnvironment(authority: TodosCliAuthorityInitialization, env?: Env): void;
14
23
  export declare const TODOS_CLI_COMMAND_ALIASES: {
15
24
  readonly onboarding: readonly ["demo-fixtures"];
16
25
  readonly retrospectives: readonly ["retro"];
@@ -40,24 +49,26 @@ export declare const TODOS_CLI_COMMAND_ALIASES: {
40
49
  export declare function getTodosCliCommandCapabilityMatrix(): ReadonlyMap<string, TodosCliCommandOwner>;
41
50
  /**
42
51
  * Whether a top-level command should be advertised (help/manual/completions) for
43
- * a resolved authority route. In a remote route the CLI fails closed on
44
- * `local-only` commands (Stage A throws REMOTE_COMMAND_UNSUPPORTED), so the help
45
- * surface must not advertise commands it will reject. Diagnostic and remote-http
46
- * owners stay visible. Commands with no capability owner (e.g. optional
52
+ * a resolved authority route. Remote help describes the authority-served
53
+ * surface, while an explicitly named `local-only` command can still select the
54
+ * local route before command modules load. Diagnostic and remote-http owners
55
+ * stay visible. Commands with no capability owner (e.g. optional
47
56
  * dynamically-registered families) self-gate at runtime and remain visible.
48
57
  */
49
58
  export declare function isTodosCliCommandVisibleForRoute(command: string, route: TodosCliAuthorityInitialization["route"]): boolean;
50
59
  /**
51
- * Filter the commander help output so it only lists top-level commands the given
52
- * authority route can execute. This keeps `todos --help` honest without
53
- * unregistering commands, so Stage A remains the single source of truth for
54
- * execution gating and error messaging.
60
+ * Filter commander help to the authority-served catalog. Explicitly named
61
+ * local-only commands select their own local route, but are omitted from remote
62
+ * metadata so help/manual/completions continue to describe the shared /v1
63
+ * surface rather than mixing two authorities into one catalog.
55
64
  */
56
65
  export declare function applyTodosCliHelpVisibility(program: Command, route: TodosCliAuthorityInitialization["route"]): void;
57
66
  /**
58
67
  * Stage A runs before importing any command module that can reach SQLite or
59
- * native Postgres adapters. It validates the complete mode state, gates the
60
- * remote command surface, then constructs only the authenticated HTTP client.
68
+ * native Postgres adapters. It validates the complete mode state, routes an
69
+ * explicitly named local-only command back to the local transport, gates the
70
+ * remote command surface, then constructs only the authenticated HTTP client
71
+ * for remote-supported commands.
61
72
  */
62
73
  export declare function initializeTodosCliAuthority(args?: string[], env?: Env): TodosCliAuthorityInitialization;
63
74
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAO1C,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,MAAM,+BAA+B,GACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,IAAI,CAAA;CAAE,GACrC;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;AAyB/E,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;CA8BgB,CAAC;AAyEvD,wBAAgB,kCAAkC,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAC9C,OAAO,CAKT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAAG,IAAI,CASnH;AAuWD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,GAAE,MAAM,EAA0B,EACtC,GAAG,GAAE,GAAwB,GAC5B,+BAA+B,CAgBjC"}
1
+ {"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAO1C,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,MAAM,+BAA+B,GACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,oBAAoB,CAAA;CAAE,GACzE;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;AAE/E;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,+BAA+B,EAC1C,GAAG,GAAE,GAAwB,GAC5B,IAAI,CAIN;AAyBD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;CA8BgB,CAAC;AAyEvD,wBAAgB,kCAAkC,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAC9C,OAAO,CAKT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAAG,IAAI,CASnH;AA8WD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,GAAE,MAAM,EAA0B,EACtC,GAAG,GAAE,GAAwB,GAC5B,+BAA+B,CAqBjC"}
package/dist/contracts.js CHANGED
@@ -3662,7 +3662,7 @@ function isBlockingDependencyStatus(status) {
3662
3662
  function isTerminalStatus(status) {
3663
3663
  return status === "completed" || status === "failed" || status === "cancelled";
3664
3664
  }
3665
- var TASK_STATUSES, TASK_PRIORITIES, PLAN_STATUSES, VersionConflictError, TaskNotFoundError, TaskNotStartableError, TaskReferenceAmbiguousError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DISPATCH_STATUSES, DispatchNotFoundError;
3665
+ var TASK_STATUSES, TASK_PRIORITIES, PLAN_STATUSES, VersionConflictError, TaskNotFoundError, TaskNotStartableError, TaskReferenceAmbiguousError, ProjectNotFoundError, ResourceConflictError, PlanRevisionConflictError, PlanNotFoundError, LockError, StaleLockHandoffError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DISPATCH_STATUSES, DispatchNotFoundError;
3666
3666
  var init_types = __esm(() => {
3667
3667
  TASK_STATUSES = [
3668
3668
  "pending",
@@ -3750,6 +3750,19 @@ var init_types = __esm(() => {
3750
3750
  this.name = "ResourceConflictError";
3751
3751
  }
3752
3752
  };
3753
+ PlanRevisionConflictError = class PlanRevisionConflictError extends Error {
3754
+ planId;
3755
+ expectedUpdatedAt;
3756
+ currentUpdatedAt;
3757
+ static code = "PLAN_REVISION_CONFLICT";
3758
+ constructor(planId, expectedUpdatedAt, currentUpdatedAt) {
3759
+ super(`Plan revision conflict for ${planId}: expected ${expectedUpdatedAt}, current ${currentUpdatedAt}`);
3760
+ this.planId = planId;
3761
+ this.expectedUpdatedAt = expectedUpdatedAt;
3762
+ this.currentUpdatedAt = currentUpdatedAt;
3763
+ this.name = "PlanRevisionConflictError";
3764
+ }
3765
+ };
3753
3766
  PlanNotFoundError = class PlanNotFoundError extends Error {
3754
3767
  planId;
3755
3768
  static code = "PLAN_NOT_FOUND";
@@ -3772,6 +3785,16 @@ var init_types = __esm(() => {
3772
3785
  this.name = "LockError";
3773
3786
  }
3774
3787
  };
3788
+ StaleLockHandoffError = class StaleLockHandoffError extends Error {
3789
+ code;
3790
+ details;
3791
+ constructor(code, message, details = {}) {
3792
+ super(message);
3793
+ this.code = code;
3794
+ this.details = details;
3795
+ this.name = "StaleLockHandoffError";
3796
+ }
3797
+ };
3775
3798
  AgentNotFoundError = class AgentNotFoundError extends Error {
3776
3799
  agentId;
3777
3800
  static code = "AGENT_NOT_FOUND";
@@ -7490,28 +7513,55 @@ var init_activity_audit = __esm(() => {
7490
7513
  function sanitizeHistoryValue(value, context) {
7491
7514
  return value === undefined || value === null ? null : sanitizePreWriteText(String(value), context);
7492
7515
  }
7493
- function logTaskChange(taskId, action, field2, oldValue, newValue, agentId, db) {
7516
+ function insertTaskHistory(entry, db) {
7494
7517
  const d = db || getDatabase();
7495
- const id = uuid();
7496
- const timestamp2 = now();
7497
- const machineId = currentStorageMachineId(d);
7498
- const safeOldValue = sanitizeHistoryValue(oldValue, "task_history.old_value");
7499
- const safeNewValue = sanitizeHistoryValue(newValue, "task_history.new_value");
7518
+ const safeEntry = {
7519
+ ...entry,
7520
+ field: entry.field || null,
7521
+ old_value: sanitizeHistoryValue(entry.old_value, "task_history.old_value"),
7522
+ new_value: sanitizeHistoryValue(entry.new_value, "task_history.new_value"),
7523
+ agent_id: entry.agent_id || null,
7524
+ machine_id: entry.machine_id ?? currentStorageMachineId(d)
7525
+ };
7500
7526
  d.run(`INSERT INTO task_history (id, task_id, action, field, old_value, new_value, agent_id, created_at, machine_id)
7501
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [id, taskId, action, field2 || null, safeOldValue, safeNewValue, agentId || null, timestamp2, machineId]);
7527
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
7528
+ safeEntry.id,
7529
+ safeEntry.task_id,
7530
+ safeEntry.action,
7531
+ safeEntry.field,
7532
+ safeEntry.old_value,
7533
+ safeEntry.new_value,
7534
+ safeEntry.agent_id,
7535
+ safeEntry.created_at,
7536
+ safeEntry.machine_id ?? null
7537
+ ]);
7502
7538
  try {
7503
7539
  const { logActivity: logActivity2 } = (init_activity_audit(), __toCommonJS(exports_activity_audit));
7504
7540
  logActivity2({
7505
7541
  entity_type: "task",
7506
- entity_id: taskId,
7507
- action,
7508
- field: field2,
7509
- old_value: safeOldValue,
7510
- new_value: safeNewValue,
7511
- actor_id: agentId ?? undefined
7542
+ entity_id: safeEntry.task_id,
7543
+ action: safeEntry.action,
7544
+ field: safeEntry.field ?? undefined,
7545
+ old_value: safeEntry.old_value,
7546
+ new_value: safeEntry.new_value,
7547
+ actor_id: safeEntry.agent_id ?? undefined
7512
7548
  }, d);
7513
7549
  } catch {}
7514
- return { id, task_id: taskId, action, field: field2 || null, old_value: safeOldValue, new_value: safeNewValue, agent_id: agentId || null, created_at: timestamp2, machine_id: machineId };
7550
+ return safeEntry;
7551
+ }
7552
+ function logTaskChange(taskId, action, field2, oldValue, newValue, agentId, db) {
7553
+ const d = db || getDatabase();
7554
+ return insertTaskHistory({
7555
+ id: uuid(),
7556
+ task_id: taskId,
7557
+ action,
7558
+ field: field2 || null,
7559
+ old_value: oldValue ?? null,
7560
+ new_value: newValue ?? null,
7561
+ agent_id: agentId || null,
7562
+ created_at: now(),
7563
+ machine_id: currentStorageMachineId(d)
7564
+ }, d);
7515
7565
  }
7516
7566
  function getTaskHistory(taskId, db) {
7517
7567
  const d = db || getDatabase();
@@ -8534,6 +8584,145 @@ var init_task_graph = __esm(() => {
8534
8584
  init_task_crud();
8535
8585
  });
8536
8586
 
8587
+ // src/lib/stale-lock-handoff.ts
8588
+ function normalizeExactTaskId(value) {
8589
+ if (typeof value !== "string" || !EXACT_TASK_UUID_RE.test(value.trim())) {
8590
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_TASK_ID", "stale-lock handoff requires one exact full task UUID", { task_id: typeof value === "string" ? value : null });
8591
+ }
8592
+ return value.trim().toLowerCase();
8593
+ }
8594
+ function requireNonEmptyString(value, field2) {
8595
+ if (typeof value !== "string" || !value.trim()) {
8596
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", `${field2} must be a non-empty string`, { field: field2 });
8597
+ }
8598
+ const trimmed = value.trim();
8599
+ if (field2 === "reason" && trimmed.length > MAX_REASON_LENGTH) {
8600
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", `reason must be at most ${MAX_REASON_LENGTH} characters`, { field: field2, max_length: MAX_REASON_LENGTH });
8601
+ }
8602
+ return trimmed;
8603
+ }
8604
+ function requireCanonicalLockVersion(value) {
8605
+ if (typeof value !== "string" || !CANONICAL_LOCK_VERSION_RE.test(value)) {
8606
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "expected_lock_version must be the exact canonical locked_at timestamp (YYYY-MM-DDTHH:mm:ss.sssZ)", { field: "expected_lock_version" });
8607
+ }
8608
+ const parsed = Date.parse(value);
8609
+ if (Number.isNaN(parsed) || new Date(parsed).toISOString() !== value) {
8610
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "expected_lock_version must name a real canonical UTC instant", { field: "expected_lock_version" });
8611
+ }
8612
+ return value;
8613
+ }
8614
+ function requireStaleThreshold(value) {
8615
+ if (!Number.isSafeInteger(value) || Number(value) <= 0) {
8616
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "stale_after_seconds must be a positive safe integer", { field: "stale_after_seconds" });
8617
+ }
8618
+ return Number(value);
8619
+ }
8620
+ function prepareStaleLockHandoff(input, options = {}) {
8621
+ const taskId = normalizeExactTaskId(input.task_id);
8622
+ const actor = requireNonEmptyString(input.actor, "actor");
8623
+ const expectedHolder = requireNonEmptyString(input.expected_holder, "expected_holder");
8624
+ const newHolder = requireNonEmptyString(input.new_holder, "new_holder");
8625
+ const expectedLockVersion = requireCanonicalLockVersion(input.expected_lock_version);
8626
+ const staleAfterSeconds = requireStaleThreshold(input.stale_after_seconds);
8627
+ const reason = sanitizePreWriteText(requireNonEmptyString(input.reason, "reason"), "stale_lock_handoff.reason").trim();
8628
+ if (!reason) {
8629
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "reason must remain non-empty after safety filtering", { field: "reason" });
8630
+ }
8631
+ if (canonicalAgentRef(actor) !== canonicalAgentRef(newHolder)) {
8632
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_ACTOR_MISMATCH", "new_holder must match the authenticated actor", { actor, new_holder: newHolder });
8633
+ }
8634
+ if (canonicalAgentRef(expectedHolder) === canonicalAgentRef(newHolder)) {
8635
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "new_holder must differ from expected_holder", { field: "new_holder" });
8636
+ }
8637
+ const operationTimestamp = options.now ?? new Date().toISOString();
8638
+ if (!CANONICAL_LOCK_VERSION_RE.test(operationTimestamp) || new Date(Date.parse(operationTimestamp)).toISOString() !== operationTimestamp) {
8639
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_INVALID_INPUT", "operation timestamp must be a canonical UTC instant");
8640
+ }
8641
+ const staleCutoff = new Date(Date.parse(operationTimestamp) - staleAfterSeconds * 1000).toISOString();
8642
+ return {
8643
+ task_id: taskId,
8644
+ actor,
8645
+ expected_holder: expectedHolder,
8646
+ expected_lock_version: expectedLockVersion,
8647
+ stale_after_seconds: staleAfterSeconds,
8648
+ new_holder: newHolder,
8649
+ reason,
8650
+ operation_timestamp: operationTimestamp,
8651
+ stale_cutoff: staleCutoff,
8652
+ receipt_id: options.receiptId ?? crypto.randomUUID()
8653
+ };
8654
+ }
8655
+ function buildStaleLockHandoffReceipt(input) {
8656
+ return {
8657
+ schema_version: STALE_LOCK_HANDOFF_SCHEMA_VERSION,
8658
+ receipt_id: input.receipt_id,
8659
+ task_id: input.task_id,
8660
+ actor: input.actor,
8661
+ previous_holder: input.expected_holder,
8662
+ previous_lock_version: input.expected_lock_version,
8663
+ new_holder: input.new_holder,
8664
+ new_lock_version: input.operation_timestamp,
8665
+ stale_after_seconds: input.stale_after_seconds,
8666
+ stale_cutoff: input.stale_cutoff,
8667
+ reason: input.reason,
8668
+ created_at: input.operation_timestamp
8669
+ };
8670
+ }
8671
+ function staleLockHandoffHistory(receipt, machineId) {
8672
+ return {
8673
+ id: receipt.receipt_id,
8674
+ task_id: receipt.task_id,
8675
+ action: STALE_LOCK_HANDOFF_ACTION,
8676
+ field: STALE_LOCK_HANDOFF_FIELD,
8677
+ old_value: JSON.stringify({
8678
+ holder: receipt.previous_holder,
8679
+ lock_version: receipt.previous_lock_version
8680
+ }),
8681
+ new_value: JSON.stringify(receipt),
8682
+ agent_id: receipt.actor,
8683
+ created_at: receipt.created_at,
8684
+ machine_id: machineId
8685
+ };
8686
+ }
8687
+ function throwStaleLockHandoffConflict(task, input) {
8688
+ if (!task.locked_by || !task.locked_at) {
8689
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_NOT_LOCKED", `Task ${input.task_id} does not have a complete lock to hand off`, { task_id: input.task_id });
8690
+ }
8691
+ if (task.locked_at !== input.expected_lock_version) {
8692
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_VERSION_MISMATCH", `Task ${input.task_id} lock version changed`, {
8693
+ task_id: input.task_id,
8694
+ expected_lock_version: input.expected_lock_version,
8695
+ current_lock_version: task.locked_at
8696
+ });
8697
+ }
8698
+ if (task.locked_by !== input.expected_holder) {
8699
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_HOLDER_MISMATCH", `Task ${input.task_id} lock holder changed`, {
8700
+ task_id: input.task_id,
8701
+ expected_holder: input.expected_holder,
8702
+ current_holder: task.locked_by
8703
+ });
8704
+ }
8705
+ if (isTerminalStatus(task.status)) {
8706
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_TERMINAL", `Task ${input.task_id} is ${task.status} and cannot transfer a lock`, { task_id: input.task_id, status: task.status });
8707
+ }
8708
+ if (task.locked_at >= input.stale_cutoff) {
8709
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_NOT_STALE", `Task ${input.task_id} lock is not older than the supplied stale threshold`, {
8710
+ task_id: input.task_id,
8711
+ current_lock_version: task.locked_at,
8712
+ stale_cutoff: input.stale_cutoff
8713
+ });
8714
+ }
8715
+ throw new StaleLockHandoffError("STALE_LOCK_HANDOFF_CONFLICT", `Task ${input.task_id} changed during stale-lock handoff`, { task_id: input.task_id });
8716
+ }
8717
+ var STALE_LOCK_HANDOFF_SCHEMA_VERSION = "todos.stale-lock-handoff.v1", STALE_LOCK_HANDOFF_ACTION = "stale_lock_handoff", STALE_LOCK_HANDOFF_FIELD = "lock", EXACT_TASK_UUID_RE, CANONICAL_LOCK_VERSION_RE, MAX_REASON_LENGTH = 4096;
8718
+ var init_stale_lock_handoff = __esm(() => {
8719
+ init_types();
8720
+ init_creator_identity();
8721
+ init_prewrite_secrets();
8722
+ EXACT_TASK_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
8723
+ CANONICAL_LOCK_VERSION_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
8724
+ });
8725
+
8537
8726
  // src/db/task-lifecycle.ts
8538
8727
  var exports_task_lifecycle = {};
8539
8728
  __export(exports_task_lifecycle, {
@@ -8542,6 +8731,7 @@ __export(exports_task_lifecycle, {
8542
8731
  startTask: () => startTask,
8543
8732
  spawnNextRecurrence: () => spawnNextRecurrence,
8544
8733
  lockTask: () => lockTask,
8734
+ handoffStaleTaskLock: () => handoffStaleTaskLock,
8545
8735
  getTasksChangedSince: () => getTasksChangedSince,
8546
8736
  getTaskLockStatus: () => getTaskLockStatus,
8547
8737
  getStaleTasks: () => getStaleTasks,
@@ -8810,6 +9000,38 @@ function unlockTask(id, agentId, db) {
8810
9000
  WHERE id = ?`, [timestamp2, id]);
8811
9001
  return true;
8812
9002
  }
9003
+ function handoffStaleTaskLock(input, db) {
9004
+ const d = db || getDatabase();
9005
+ const prepared = prepareStaleLockHandoff(input);
9006
+ const receipt = buildStaleLockHandoffReceipt(prepared);
9007
+ const history = staleLockHandoffHistory(receipt, null);
9008
+ const transfer = d.transaction(() => {
9009
+ const result = d.run(`UPDATE tasks
9010
+ SET locked_by = ?, locked_at = ?, updated_at = ?, version = version + 1
9011
+ WHERE id = ?
9012
+ AND locked_by = ?
9013
+ AND locked_at = ?
9014
+ AND julianday(locked_at) < julianday(?)
9015
+ AND status NOT IN ('completed', 'failed', 'cancelled')`, [
9016
+ prepared.new_holder,
9017
+ prepared.operation_timestamp,
9018
+ prepared.operation_timestamp,
9019
+ prepared.task_id,
9020
+ prepared.expected_holder,
9021
+ prepared.expected_lock_version,
9022
+ prepared.stale_cutoff
9023
+ ]);
9024
+ if (result.changes === 0) {
9025
+ const current = getTask(prepared.task_id, d);
9026
+ if (!current)
9027
+ throw new TaskNotFoundError(prepared.task_id);
9028
+ throwStaleLockHandoffConflict(current, prepared);
9029
+ }
9030
+ insertTaskHistory(history, d);
9031
+ });
9032
+ transfer();
9033
+ return receipt;
9034
+ }
8813
9035
  function getTaskLockStatus(id, db) {
8814
9036
  const d = db || getDatabase();
8815
9037
  const task = getTask(id, d);
@@ -9110,6 +9332,7 @@ var init_task_lifecycle = __esm(() => {
9110
9332
  init_task_crud();
9111
9333
  init_task_graph();
9112
9334
  init_prewrite_secrets();
9335
+ init_stale_lock_handoff();
9113
9336
  });
9114
9337
 
9115
9338
  // src/db/task-crud.ts
@@ -10521,6 +10744,48 @@ function updatePlan(id, input, db) {
10521
10744
  return updatePlanStored(id, input, d);
10522
10745
  })();
10523
10746
  }
10747
+ function nextPlanCompletionTimestamp(expectedUpdatedAt) {
10748
+ const expected = Date.parse(expectedUpdatedAt);
10749
+ const minimum = Number.isNaN(expected) ? Date.now() : expected + 2;
10750
+ return new Date(Math.max(Date.now(), minimum)).toISOString();
10751
+ }
10752
+ function completePlanAtRevision(id, expectedUpdatedAt, db) {
10753
+ const d = db || getDatabase();
10754
+ return d.transaction(() => {
10755
+ guardPlanRowsSqlite([id], d);
10756
+ const plan = getPlan(id, d);
10757
+ if (!plan)
10758
+ throw new PlanNotFoundError(id);
10759
+ if (plan.updated_at !== expectedUpdatedAt) {
10760
+ throw new PlanRevisionConflictError(id, expectedUpdatedAt, plan.updated_at);
10761
+ }
10762
+ if (plan.status === "completed")
10763
+ return { plan, applied: false };
10764
+ const updatedAt = nextPlanCompletionTimestamp(expectedUpdatedAt);
10765
+ const result = d.run(`UPDATE plans
10766
+ SET status = 'completed', updated_at = ?
10767
+ WHERE id = ? AND updated_at = ? AND status <> 'completed'`, [updatedAt, id, expectedUpdatedAt]);
10768
+ if (result.changes !== 1) {
10769
+ const current = getPlan(id, d);
10770
+ if (!current)
10771
+ throw new PlanNotFoundError(id);
10772
+ throw new PlanRevisionConflictError(id, expectedUpdatedAt, current.updated_at);
10773
+ }
10774
+ const completed = getPlan(id, d);
10775
+ emitLocalEventHooksQuiet({
10776
+ type: "plan.updated",
10777
+ payload: {
10778
+ id,
10779
+ old_status: plan.status,
10780
+ new_status: completed.status,
10781
+ name: completed.name,
10782
+ project_id: completed.project_id
10783
+ },
10784
+ databasePath: databasePathFromDatabase(d)
10785
+ });
10786
+ return { plan: completed, applied: true };
10787
+ })();
10788
+ }
10524
10789
  function deletePlan(id, db) {
10525
10790
  const d = db || getDatabase();
10526
10791
  const plan = getPlan(id, d);
@@ -12380,7 +12645,7 @@ var init_tasks = __esm(() => {
12380
12645
  // package.json
12381
12646
  var package_default = {
12382
12647
  name: "@hasna/todos",
12383
- version: "0.15.18",
12648
+ version: "0.15.20",
12384
12649
  description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
12385
12650
  type: "module",
12386
12651
  main: "dist/index.js",
@@ -12451,6 +12716,8 @@ var package_default = {
12451
12716
  "dev:mcp": "bun run src/mcp/index.ts",
12452
12717
  "dev:serve": "bun run src/server/index.ts",
12453
12718
  "verify:release": "bun run scripts/verify-public-release.ts --mode=review",
12719
+ "verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
12720
+ "issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
12454
12721
  prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
12455
12722
  postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
12456
12723
  },
@@ -1,5 +1,13 @@
1
1
  import type { Database } from "bun:sqlite";
2
2
  import type { TaskHistory } from "../types/index.js";
3
+ /**
4
+ * Insert one caller-constructed history entry through the owning audit path.
5
+ *
6
+ * Operations that must mutate a task and persist their immutable receipt in the
7
+ * SAME transaction use this form. Ordinary callers should keep using
8
+ * logTaskChange(), which creates the id and timestamp for them.
9
+ */
10
+ export declare function insertTaskHistory(entry: TaskHistory, db?: Database): TaskHistory;
3
11
  export declare function logTaskChange(taskId: string, action: string, field?: string, oldValue?: string | null, newValue?: string | null, agentId?: string | null, db?: Database): TaskHistory;
4
12
  export declare function getTaskHistory(taskId: string, db?: Database): TaskHistory[];
5
13
  export declare function getRecentActivity(limit?: number, db?: Database): TaskHistory[];
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/db/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASrD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EACvB,EAAE,CAAC,EAAE,QAAQ,GACZ,WAAW,CA6Bb;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,WAAW,EAAE,CAG3E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,SAAK,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,WAAW,EAAE,CAG1E;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IAC9J,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/G,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IAC7H,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IAC9F,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChH,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtG;AAED,wBAAgB,QAAQ,CAAC,KAAK,SAAI,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,YAAY,CAyDnF"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/db/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASrD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,WAAW,CA0ChF;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EACvB,EAAE,CAAC,EAAE,QAAQ,GACZ,WAAW,CAab;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,WAAW,EAAE,CAG3E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,SAAK,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,WAAW,EAAE,CAG1E;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IAC9J,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/G,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IAC7H,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IAC9F,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChH,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtG;AAED,wBAAgB,QAAQ,CAAC,KAAK,SAAI,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,YAAY,CAyDnF"}
@@ -12,5 +12,9 @@ export declare function createPlan(input: CreatePlanInput, db?: Database): Plan;
12
12
  export declare function getPlan(id: string, db?: Database): Plan | null;
13
13
  export declare function listPlans(projectId?: string, db?: Database): Plan[];
14
14
  export declare function updatePlan(id: string, input: UpdatePlanInput, db?: Database): Plan;
15
+ export declare function completePlanAtRevision(id: string, expectedUpdatedAt: string, db?: Database): {
16
+ plan: Plan;
17
+ applied: boolean;
18
+ };
15
19
  export declare function deletePlan(id: string, db?: Database): boolean;
16
20
  //# sourceMappingURL=plans.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/db/plans.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAShF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;IAClD,OAAO,EAAE,IAAI,EAAE,CAAC;CACjB;AAMD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIvD;AAsCD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,oBAAoB,CAalH;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEnG;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CA2BtE;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAI9D;AAED,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,EAAE,CAUnE;AAuDD,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,eAAe,EACtB,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,CAMN;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAW7D"}
1
+ {"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/db/plans.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAShF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;IAClD,OAAO,EAAE,IAAI,EAAE,CAAC;CACjB;AAMD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIvD;AAsCD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,oBAAoB,CAalH;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEnG;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CA2BtE;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAI9D;AAED,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,EAAE,CAUnE;AAuDD,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,eAAe,EACtB,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,CAMN;AAQD,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,MAAM,EACV,iBAAiB,EAAE,MAAM,EACzB,EAAE,CAAC,EAAE,QAAQ,GACZ;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAqClC;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAW7D"}
@@ -1,5 +1,5 @@
1
1
  import type { Database } from "bun:sqlite";
2
- import type { LockResult, Task } from "../types/index.js";
2
+ import type { LockResult, StaleLockHandoffInput, StaleLockHandoffReceipt, Task } from "../types/index.js";
3
3
  export declare function getBlockingDeps(id: string, db?: Database): Task[];
4
4
  export declare function startTask(id: string, agentId: string, db?: Database): Task;
5
5
  export declare function completeTask(id: string, agentId?: string, db?: Database, options?: {
@@ -14,6 +14,12 @@ export declare function completeTask(id: string, agentId?: string, db?: Database
14
14
  }): Task;
15
15
  export declare function lockTask(id: string, agentId: string, db?: Database): LockResult;
16
16
  export declare function unlockTask(id: string, agentId?: string, db?: Database): boolean;
17
+ /**
18
+ * Atomically transfer exactly one stale lock from its observed holder/version
19
+ * to the authenticated new holder, and persist the immutable receipt in the
20
+ * owning task_history table inside the same SQLite transaction.
21
+ */
22
+ export declare function handoffStaleTaskLock(input: StaleLockHandoffInput, db?: Database): StaleLockHandoffReceipt;
17
23
  export interface TaskLockStatus {
18
24
  task_id: string;
19
25
  locked: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"task-lifecycle.d.ts","sourceRoot":"","sources":["../../src/db/task-lifecycle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-lifecycle.d.ts","sourceRoot":"","sources":["../../src/db/task-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EACV,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACvB,IAAI,EAEL,MAAM,mBAAmB,CAAC;AAwE3B,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,EAAE,CAUjE;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,CAmDN;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,QAAQ,EACb,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACpM,IAAI,CA8KN;AAED,wBAAgB,QAAQ,CACtB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,EAAE,CAAC,EAAE,QAAQ,GACZ,UAAU,CAyDZ;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,CAkBT;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,qBAAqB,EAC5B,EAAE,CAAC,EAAE,QAAQ,GACZ,uBAAuB,CAoCzB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,cAAc,CAa3E;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,EAC3F,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,GAAG,IAAI,CA0Bb;AAED,wBAAgB,WAAW,CACzB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,EAC3F,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,GAAG,IAAI,CAkDb;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAC3B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EACxD,EAAE,CAAC,EAAE,QAAQ,GACZ,cAAc,EAAE,CAiBlB;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EACxD,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,EAAE,CAWR;AAED,wBAAgB,QAAQ,CACtB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EACxE,EAAE,CAAC,EAAE,QAAQ,GACZ;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,IAAI,CAAA;CAAE,CAmGlC;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,UAAU,GAAE,cAAmB,EAC/B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EACxD,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,EAAE,CAyBR;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7E,EAAE,CAAC,EAAE,QAAQ,GACZ,IAAI,GAAG,IAAI,CA8Bb;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EACnH,EAAE,CAAC,EAAE,QAAQ,GACZ;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAexC;AAID,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CA6BhG"}
@@ -1,5 +1,5 @@
1
1
  export { createTask, getTask, getTaskWithRelations, listTasks, countTasks, updateTask, upsertTaskByFingerprint, getTaskByFingerprint, deleteTask, rowToTask, insertTaskTags, replaceTaskTags, } from "./task-crud.js";
2
- export { startTask, completeTask, failTask, lockTask, unlockTask, getTaskLockStatus, claimNextTask, getNextTask, getActiveWork, getTasksChangedSince, stealTask, claimOrSteal, getBlockingDeps, getStaleTasks, } from "./task-lifecycle.js";
2
+ export { startTask, completeTask, failTask, lockTask, unlockTask, handoffStaleTaskLock, getTaskLockStatus, claimNextTask, getNextTask, getActiveWork, getTasksChangedSince, stealTask, claimOrSteal, getBlockingDeps, getStaleTasks, } from "./task-lifecycle.js";
3
3
  export type { ActiveWorkItem, StaleTaskQuery, TaskLockStatus } from "./task-lifecycle.js";
4
4
  export { addDependency, removeDependency, getTaskDependencies, getTaskDependents, cloneTask, getTaskGraph, moveTask, } from "./task-graph.js";
5
5
  export type { TaskGraphNode, TaskGraph } from "./task-graph.js";
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/db/tasks.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,UAAU,EACV,OAAO,EACP,oBAAoB,EACpB,SAAS,EACT,UAAU,EACV,UAAU,EACV,uBAAuB,EACvB,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1F,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EACL,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,OAAO,EACL,eAAe,EACf,eAAe,EACf,eAAe,EACf,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,0BAA0B,EAC1B,SAAS,EACT,WAAW,EACX,eAAe,EACf,cAAc,EACd,OAAO,GACR,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,GAChB,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,4BAA4B,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/db/tasks.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,UAAU,EACV,OAAO,EACP,oBAAoB,EACpB,SAAS,EACT,UAAU,EACV,UAAU,EACV,uBAAuB,EACvB,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1F,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EACL,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,OAAO,EACL,eAAe,EACf,eAAe,EACf,eAAe,EACf,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,0BAA0B,EAC1B,SAAS,EACT,WAAW,EACX,eAAe,EACf,cAAc,EACd,OAAO,GACR,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,GAChB,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,4BAA4B,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC"}