@hasna/todos 0.15.15 → 0.15.16

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.
@@ -70,7 +70,7 @@ var package_default;
70
70
  var init_package = __esm(() => {
71
71
  package_default = {
72
72
  name: "@hasna/todos",
73
- version: "0.15.15",
73
+ version: "0.15.16",
74
74
  description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
75
75
  type: "module",
76
76
  main: "dist/index.js",
@@ -26036,6 +26036,22 @@ class PostgresTodosTaskManifestBackend {
26036
26036
  async markOutboxDelivered(outboxId, deliveredAt) {
26037
26037
  await this.ensureSchema();
26038
26038
  await this.client.transaction(async (tx) => {
26039
+ const owned = await tx.query(`SELECT r.operation_id
26040
+ FROM todos_task_manifest_outbox o
26041
+ JOIN todos_task_manifest_receipts r
26042
+ ON r.receipt_id = o.apply_receipt_id
26043
+ WHERE r.tenant_id = $1
26044
+ AND r.authority = 'todos'
26045
+ AND r.route = 'todos.task-manifest.v1'
26046
+ AND r.schema_version = 1
26047
+ AND r.kind = 'apply'
26048
+ AND o.id = $2
26049
+ LIMIT 1`, [this.tenantId, outboxId]);
26050
+ const operationId = owned.rows[0]?.operation_id;
26051
+ if (operationId == null) {
26052
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
26053
+ }
26054
+ await tx.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [`${this.service}\x1F${String(operationId)}`]);
26039
26055
  const result = await tx.query(`UPDATE todos_task_manifest_outbox
26040
26056
  SET status = 'delivered', delivered_at = $1, attempts = attempts + 1
26041
26057
  WHERE id = $2 AND status = 'pending'
@@ -26043,10 +26059,28 @@ class PostgresTodosTaskManifestBackend {
26043
26059
  SELECT 1 FROM todos_task_manifest_receipts r
26044
26060
  WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
26045
26061
  AND r.tenant_id = $3
26062
+ AND r.authority = 'todos'
26063
+ AND r.route = 'todos.task-manifest.v1'
26064
+ AND r.schema_version = 1
26065
+ AND r.kind = 'apply'
26046
26066
  )
26047
26067
  RETURNING id`, [deliveredAt, outboxId, this.tenantId]);
26048
- if (!result.rows[0])
26049
- throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
26068
+ if (result.rows[0])
26069
+ return;
26070
+ const existing = await tx.query(`SELECT o.status
26071
+ FROM todos_task_manifest_outbox o
26072
+ JOIN todos_task_manifest_receipts r
26073
+ ON r.receipt_id = o.apply_receipt_id
26074
+ WHERE r.tenant_id = $1
26075
+ AND r.authority = 'todos'
26076
+ AND r.route = 'todos.task-manifest.v1'
26077
+ AND r.schema_version = 1
26078
+ AND r.kind = 'apply'
26079
+ AND o.id = $2
26080
+ LIMIT 1`, [this.tenantId, outboxId]);
26081
+ if (existing.rows[0]?.status === "delivered")
26082
+ return;
26083
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
26050
26084
  });
26051
26085
  }
26052
26086
  async compensate(input, receipt, compensationReceiptId, requestDigest, now3) {
@@ -26078,7 +26112,13 @@ class PostgresTodosTaskManifestBackend {
26078
26112
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Graph is not applied");
26079
26113
  const delivered = await tx.query(`SELECT o.id FROM todos_task_manifest_outbox o
26080
26114
  JOIN todos_task_manifest_receipts r ON r.receipt_id = o.apply_receipt_id
26081
- WHERE r.tenant_id = $1 AND o.apply_receipt_id = $2 AND o.status = 'delivered'
26115
+ WHERE r.tenant_id = $1
26116
+ AND r.authority = 'todos'
26117
+ AND r.route = 'todos.task-manifest.v1'
26118
+ AND r.schema_version = 1
26119
+ AND r.kind = 'apply'
26120
+ AND o.apply_receipt_id = $2
26121
+ AND o.status = 'delivered'
26082
26122
  LIMIT 1`, [this.tenantId, input.receipt_id]);
26083
26123
  if (delivered.rows[0])
26084
26124
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: delivered outbox row exists");
@@ -26091,15 +26131,20 @@ class PostgresTodosTaskManifestBackend {
26091
26131
  },
26092
26132
  ...(manifest.effects ?? []).map((effect2) => ({ topic: effect2.topic, payload: effect2.payload }))
26093
26133
  ];
26094
- const outboxRows = await tx.query(`SELECT id, topic, payload, payload_digest, status, attempts, delivered_at
26095
- FROM todos_task_manifest_outbox
26096
- WHERE apply_receipt_id = $1
26134
+ const outboxRows = await tx.query(`SELECT o.id, o.topic, o.payload, o.payload_digest, o.status, o.attempts, o.delivered_at
26135
+ FROM todos_task_manifest_outbox o
26136
+ WHERE o.apply_receipt_id = $1
26097
26137
  AND EXISTS (
26098
26138
  SELECT 1 FROM todos_task_manifest_receipts r
26099
- WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
26139
+ WHERE r.receipt_id = o.apply_receipt_id
26100
26140
  AND r.tenant_id = $2
26141
+ AND r.authority = 'todos'
26142
+ AND r.route = 'todos.task-manifest.v1'
26143
+ AND r.schema_version = 1
26144
+ AND r.kind = 'apply'
26101
26145
  )
26102
- ORDER BY id`, [input.receipt_id, this.tenantId]);
26146
+ ORDER BY o.id
26147
+ FOR UPDATE OF o`, [input.receipt_id, this.tenantId]);
26103
26148
  if (outboxRows.rows.length !== expectedEffects.length) {
26104
26149
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: outbox changed since apply");
26105
26150
  }
@@ -26199,14 +26244,23 @@ class PostgresTodosTaskManifestBackend {
26199
26244
  }
26200
26245
  if (stored.rows.length !== managedIds.length)
26201
26246
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: managed graph is incomplete");
26202
- await tx.query(`UPDATE todos_task_manifest_outbox
26247
+ const cancelled = await tx.query(`UPDATE todos_task_manifest_outbox
26203
26248
  SET status = 'cancelled'
26204
26249
  WHERE apply_receipt_id = $1 AND status = 'pending'
26205
26250
  AND EXISTS (
26206
26251
  SELECT 1 FROM todos_task_manifest_receipts r
26207
26252
  WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
26208
26253
  AND r.tenant_id = $2
26209
- )`, [input.receipt_id, this.tenantId]);
26254
+ AND r.authority = 'todos'
26255
+ AND r.route = 'todos.task-manifest.v1'
26256
+ AND r.schema_version = 1
26257
+ AND r.kind = 'apply'
26258
+ )
26259
+ RETURNING id`, [input.receipt_id, this.tenantId]);
26260
+ const cancelledIds = new Set(cancelled.rows.map((row) => String(row.id)));
26261
+ if (cancelledIds.size !== applyResult.outbox_ids.length || applyResult.outbox_ids.some((id) => !cancelledIds.has(id))) {
26262
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: failed to cancel every expected outbox row");
26263
+ }
26210
26264
  const typedIds = [
26211
26265
  ["dependencies", applyResult.graph.dependency_ids],
26212
26266
  ["comments", applyResult.graph.comment_ids],
@@ -26389,6 +26443,7 @@ class PackageOwnedTodosTaskManifestAuthority {
26389
26443
  deterministic_ids: true,
26390
26444
  immutable_receipts: true,
26391
26445
  transactional_outbox: true,
26446
+ idempotent_outbox_delivery: true,
26392
26447
  exact_bounded_readback: true,
26393
26448
  conditional_compensation: true,
26394
26449
  transcript_safe: false,
@@ -63878,10 +63933,72 @@ async function requireTagsFilterCapability(client) {
63878
63933
  throw new Error(`REMOTE_TAGS_FILTER_UNSUPPORTED: configured Todos authority ${authority} does not advertise the tags ` + "query param on GET /v1/tasks; deploy the current @hasna/todos /v1 server to filter by tag; " + "no unfiltered task read was issued");
63879
63934
  }
63880
63935
  }
63881
- async function requestCloudTaskPage(client, filter) {
63936
+ function parseCloudTaskTotal(raw) {
63937
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
63938
+ return;
63939
+ const total = raw.total;
63940
+ return typeof total === "number" && Number.isSafeInteger(total) && total >= 0 ? total : undefined;
63941
+ }
63942
+ async function requestRawCloudTaskPage(client, filter) {
63882
63943
  const res = await requiredRemoteRoute(client, "/v1/tasks", () => client.list("tasks", { query: toListQuery(filter) }));
63883
63944
  const envelope = res.raw;
63884
- return Array.isArray(envelope?.tasks) ? envelope.tasks : res.items;
63945
+ return {
63946
+ tasks: Array.isArray(envelope?.tasks) ? envelope.tasks : res.items,
63947
+ total: parseCloudTaskTotal(res.raw)
63948
+ };
63949
+ }
63950
+ function cloudTaskListFilterError(code, taskListId, detail) {
63951
+ return new Error(`${code}: hosted authority returned rows outside requested task_list_id ${taskListId}; ${detail}; refusing an incomplete exact-list result`);
63952
+ }
63953
+ async function requestCloudTaskPage(client, filter) {
63954
+ const firstPage = await requestRawCloudTaskPage(client, filter);
63955
+ const tasks = firstPage.tasks;
63956
+ if (filter.task_list_id === undefined)
63957
+ return tasks;
63958
+ const taskListId = filter.task_list_id;
63959
+ if (tasks.every((task2) => task2.task_list_id === taskListId))
63960
+ return tasks;
63961
+ const scanLimit = filter.limit;
63962
+ const startOffset = filter.offset ?? 0;
63963
+ if (startOffset !== 0 || scanLimit === undefined || !Number.isSafeInteger(scanLimit) || scanLimit <= 0 || firstPage.total === undefined) {
63964
+ throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, "the response does not provide complete bounded total/offset pagination evidence");
63965
+ }
63966
+ const total = firstPage.total;
63967
+ if (total > scanLimit) {
63968
+ throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_INCOMPLETE", taskListId, `reported total ${total} exceeds bounded scan limit ${scanLimit}`);
63969
+ }
63970
+ if (tasks.length > total) {
63971
+ throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `the first page contains ${tasks.length} rows but reports total ${total}`);
63972
+ }
63973
+ const seenTaskIds = new Set;
63974
+ for (const task2 of tasks) {
63975
+ if (seenTaskIds.has(task2.id)) {
63976
+ throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `the first page repeats task id ${task2.id}`);
63977
+ }
63978
+ seenTaskIds.add(task2.id);
63979
+ }
63980
+ while (tasks.length < total) {
63981
+ const remaining = total - tasks.length;
63982
+ const page = await requestRawCloudTaskPage(client, {
63983
+ ...filter,
63984
+ offset: tasks.length,
63985
+ limit: Math.min(scanLimit - tasks.length, remaining)
63986
+ });
63987
+ if (page.total !== total) {
63988
+ throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `pagination total changed from ${total} to ${String(page.total)}`);
63989
+ }
63990
+ if (page.tasks.length === 0 || tasks.length + page.tasks.length > total) {
63991
+ throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, "pagination did not make bounded progress toward the reported total");
63992
+ }
63993
+ for (const task2 of page.tasks) {
63994
+ if (seenTaskIds.has(task2.id)) {
63995
+ throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `pagination repeats task id ${task2.id}`);
63996
+ }
63997
+ seenTaskIds.add(task2.id);
63998
+ }
63999
+ tasks.push(...page.tasks);
64000
+ }
64001
+ return tasks.filter((task2) => task2.task_list_id === taskListId);
63885
64002
  }
63886
64003
  async function cloudListTasks(client, filter = {}) {
63887
64004
  if (filter.tags?.length)
@@ -63920,12 +64037,10 @@ async function cloudGetTask(client, id) {
63920
64037
  }
63921
64038
  async function cloudCreateTask(client, input) {
63922
64039
  const expectedParentId = typeof input["parent_id"] === "string" ? input["parent_id"] : null;
63923
- const created = unwrapTask(await requiredRemoteRoute(client, "/v1/tasks", () => expectedParentId === null ? client.create("tasks", input) : client.create("tasks", input, { retry: false }), ["PARENT_TASK_NOT_FOUND"]));
64040
+ const created = unwrapTask(await requiredRemoteRoute(client, "/v1/tasks", () => client.create("tasks", input, { retry: false }), ["PARENT_TASK_NOT_FOUND"]));
63924
64041
  if (!created || typeof created.id !== "string" || !created.id.trim()) {
63925
64042
  throw new Error(`REMOTE_API_INCOMPATIBLE: configured Todos authority ${remoteAuthorityBase(client)} returned a task create ` + "response without a stored task id; no success row or local SQLite fallback is permitted");
63926
64043
  }
63927
- if (expectedParentId === null)
63928
- return created;
63929
64044
  const persisted = await cloudGetTask(client, created.id);
63930
64045
  if (!persisted || persisted.id !== created.id || (persisted.parent_id ?? null) !== expectedParentId) {
63931
64046
  throw new Error(`TASK_CREATE_PERSISTENCE_UNVERIFIED: configured Todos authority ${remoteAuthorityBase(client)} accepted ` + `POST /v1/tasks but authoritative GET /v1/tasks/${encodeURIComponent(created.id)} did not return the same ` + "stored task id and parent_id; no success row or local SQLite fallback is permitted");
@@ -1 +1 @@
1
- {"version":3,"file":"authority.d.ts","sourceRoot":"","sources":["../../src/task-manifest/authority.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAsD,MAAM,cAAc,CAAC;AAUjH,OAAO,EAIL,KAAK,yCAAyC,EAC9C,KAAK,uCAAuC,EAC5C,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAC/B,KAAK,iCAAiC,EACtC,KAAK,qCAAqC,EAC1C,KAAK,oCAAoC,EACzC,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,+BAA+B,EAErC,MAAM,YAAY,CAAC;AAuIpB,qBAAa,sCAAuC,YAAW,0BAA0B;IAIrF,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGf,OAAO,EAAE,wBAAwB,EACjC,OAAO,GAAE,iCAAsC;IAK5D,UAAU,IAAI,OAAO,CAAC,2BAA2B,CAAC;IAiBxD,OAAO,CAAC,GAAG;YAQG,aAAa;IAUrB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAMlE,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAO7D,aAAa,CACjB,KAAK,EAAE,qCAAqC,GAC3C,OAAO,CAAC,oCAAoC,CAAC;IA6BhD,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,UAAU,CAAC,KAAK,EAAE,kCAAkC,GAAG,OAAO,CAAC,mCAAmC,CAAC;IAkCzG,OAAO,CAAC,OAAO;CAWhB;AAED,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,uCAAuC,GAC/C,0BAA0B,CAS5B;AAED,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,+BAA+B,EACvC,OAAO,GAAE,yCAA8C,GACtD,0BAA0B,CAY5B;AAED,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"authority.d.ts","sourceRoot":"","sources":["../../src/task-manifest/authority.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAsD,MAAM,cAAc,CAAC;AAUjH,OAAO,EAIL,KAAK,yCAAyC,EAC9C,KAAK,uCAAuC,EAC5C,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAC/B,KAAK,iCAAiC,EACtC,KAAK,qCAAqC,EAC1C,KAAK,oCAAoC,EACzC,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,+BAA+B,EAErC,MAAM,YAAY,CAAC;AAuIpB,qBAAa,sCAAuC,YAAW,0BAA0B;IAIrF,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGf,OAAO,EAAE,wBAAwB,EACjC,OAAO,GAAE,iCAAsC;IAK5D,UAAU,IAAI,OAAO,CAAC,2BAA2B,CAAC;IAkBxD,OAAO,CAAC,GAAG;YAQG,aAAa;IAUrB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAMlE,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAO7D,aAAa,CACjB,KAAK,EAAE,qCAAqC,GAC3C,OAAO,CAAC,oCAAoC,CAAC;IA6BhD,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,UAAU,CAAC,KAAK,EAAE,kCAAkC,GAAG,OAAO,CAAC,mCAAmC,CAAC;IAkCzG,OAAO,CAAC,OAAO;CAWhB;AAED,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,uCAAuC,GAC/C,0BAA0B,CAS5B;AAED,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,+BAA+B,EACvC,OAAO,GAAE,yCAA8C,GACtD,0BAA0B,CAY5B;AAED,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC"}
@@ -5,6 +5,6 @@ export { TodosTaskManifestHttpClient, createTodosTaskManifestHttpClient, handleT
5
5
  export { canonicalDigest as digestTodosTaskManifest, canonicalJson as canonicalTodosTaskManifestJson, deterministicUuid as deterministicTodosTaskManifestId } from "./canonical.js";
6
6
  export { TODOS_TASK_MANIFEST_BOUNDS, parseTodosTaskManifestBindingLookup, parseTodosTaskManifestCompensation, } from "./schema.js";
7
7
  export { postgresTodosTaskManifestSchemaSql, sqliteTodosTaskManifestSchemaSql } from "./schema-sql.js";
8
- export { TODOS_TASK_MANIFEST_ROUTE, TODOS_TASK_MANIFEST_SCHEMA_VERSION, TodosTaskManifestError, } from "./types.js";
8
+ export { TODOS_TASK_MANIFEST_ROUTE, TODOS_TASK_MANIFEST_SCHEMA_VERSION, TodosTaskManifestError, supportsIdempotentOutboxDelivery, } from "./types.js";
9
9
  export type * from "./types.js";
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/task-manifest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sCAAsC,EACtC,wCAAwC,EACxC,sCAAsC,EACtC,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,eAAe,IAAI,uBAAuB,EAAE,aAAa,IAAI,8BAA8B,EAAE,iBAAiB,IAAI,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AACpL,OAAO,EACL,0BAA0B,EAC1B,mCAAmC,EACnC,kCAAkC,GACnC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kCAAkC,EAAE,gCAAgC,EAAE,MAAM,iBAAiB,CAAC;AACvG,OAAO,EACL,yBAAyB,EACzB,kCAAkC,EAClC,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,mBAAmB,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/task-manifest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sCAAsC,EACtC,wCAAwC,EACxC,sCAAsC,EACtC,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,eAAe,IAAI,uBAAuB,EAAE,aAAa,IAAI,8BAA8B,EAAE,iBAAiB,IAAI,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AACpL,OAAO,EACL,0BAA0B,EAC1B,mCAAmC,EACnC,kCAAkC,GACnC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kCAAkC,EAAE,gCAAgC,EAAE,MAAM,iBAAiB,CAAC;AACvG,OAAO,EACL,yBAAyB,EACzB,kCAAkC,EAClC,sBAAsB,EACtB,gCAAgC,GACjC,MAAM,YAAY,CAAC;AACpB,mBAAmB,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/task-manifest/postgres.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAItB,OAAO,EAEL,KAAK,yCAAyC,EAE9C,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAE9B,MAAM,YAAY,CAAC;AA4EpB,qBAAa,gCAAiC,YAAW,wBAAwB;IAQ7E,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,+BAA+B,EACxD,OAAO,GAAE,yCAA8C;YAO3C,YAAY;YAQZ,UAAU;IAclB,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAgI/G,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAUnE,qBAAqB,CAAC,MAAM,EAAE,MAAM;IA4BpC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBzE,UAAU,CACd,KAAK,EAAE,kCAAkC,EACzC,OAAO,EAAE,wBAAwB,EACjC,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,mCAAmC,CAAC;YA8LjC,QAAQ;CAcvB"}
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/task-manifest/postgres.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAItB,OAAO,EAEL,KAAK,yCAAyC,EAE9C,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAE9B,MAAM,YAAY,CAAC;AA4EpB,qBAAa,gCAAiC,YAAW,wBAAwB;IAQ7E,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,+BAA+B,EACxD,OAAO,GAAE,yCAA8C;YAO3C,YAAY;YAQZ,UAAU;IAclB,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAgI/G,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAUnE,qBAAqB,CAAC,MAAM,EAAE,MAAM;IA4BpC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0DzE,UAAU,CACd,KAAK,EAAE,kCAAkC,EACzC,OAAO,EAAE,wBAAwB,EACjC,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,mCAAmC,CAAC;YAsNjC,QAAQ;CAcvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/task-manifest/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAGtB,OAAO,EAGL,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,wBAAwB,EAC9B,MAAM,YAAY,CAAC;AAYpB,qBAAa,8BAA+B,YAAW,wBAAwB;IAI3E,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;gBAGf,EAAE,EAAE,QAAQ,EACZ,QAAQ,SAAY;YAKzB,UAAU;IAuBlB,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAyI/G,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAQnE,qBAAqB,CAAC,MAAM,EAAE,MAAM;IA2BpC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBzE,UAAU,CACd,KAAK,EAAE,kCAAkC,EACzC,OAAO,EAAE,wBAAwB,EACjC,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,mCAAmC,CAAC;IA+K/C,OAAO,CAAC,QAAQ;CAajB"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/task-manifest/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAGtB,OAAO,EAGL,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,wBAAwB,EAC9B,MAAM,YAAY,CAAC;AAYpB,qBAAa,8BAA+B,YAAW,wBAAwB;IAI3E,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;gBAGf,EAAE,EAAE,QAAQ,EACZ,QAAQ,SAAY;YAKzB,UAAU;IAuBlB,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAyI/G,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAQnE,qBAAqB,CAAC,MAAM,EAAE,MAAM;IA2BpC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BzE,UAAU,CACd,KAAK,EAAE,kCAAkC,EACzC,OAAO,EAAE,wBAAwB,EACjC,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,mCAAmC,CAAC;IA+K/C,OAAO,CAAC,QAAQ;CAajB"}
@@ -115,6 +115,7 @@ export interface TodosTaskManifestCapability {
115
115
  deterministic_ids: true;
116
116
  immutable_receipts: true;
117
117
  transactional_outbox: true;
118
+ idempotent_outbox_delivery: true;
118
119
  exact_bounded_readback: true;
119
120
  conditional_compensation: true;
120
121
  transcript_safe: false;
@@ -130,6 +131,7 @@ export interface TodosTaskManifestCapability {
130
131
  response_bytes: number;
131
132
  };
132
133
  }
134
+ export declare function supportsIdempotentOutboxDelivery(capability: unknown): boolean;
133
135
  export interface TodosTaskManifestBindingLookupRequest {
134
136
  authority: "todos";
135
137
  route: typeof TODOS_TASK_MANIFEST_ROUTE;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/task-manifest/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/task-manifest/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAElE,eAAO,MAAM,yBAAyB,EAAG,wBAAiC,CAAC;AAC3E,eAAO,MAAM,kCAAkC,EAAG,CAAU,CAAC;AAE7D,MAAM,MAAM,uBAAuB,GAAG,UAAU,CAAC;AACjD,MAAM,MAAM,yBAAyB,GAAG,YAAY,CAAC;AACrD,MAAM,MAAM,mCAAmC,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,eAAe,GAAG,QAAQ,CAAC;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,mCAAmC,CAAC;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;IAC5D,QAAQ,CAAC,EAAE,wBAAwB,EAAE,CAAC;IACtC,aAAa,CAAC,EAAE,6BAA6B,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC;KAC9C,CAAC;IACF,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,YAAY,CAAC,EAAE,2BAA2B,EAAE,CAAC;IAC7C,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,yBAAyB,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC;IAClB,IAAI,EAAE,OAAO,GAAG,YAAY,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,wBAAwB,CAAC;IAClC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,QAAQ,EAAE,yBAAyB,CAAC;IACpC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kCAAkC;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,mCAAmC;IAClD,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,wBAAwB,CAAC;IAClC,MAAM,EAAE,IAAI,CAAC;IACb,QAAQ,EAAE,yBAAyB,CAAC;CACrC;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,yBAAyB,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,QAAQ,GAAG,YAAY,GAAG,MAAM,CAAC;IAC1C,iBAAiB,EAAE,IAAI,CAAC;IACxB,kBAAkB,EAAE,IAAI,CAAC;IACzB,oBAAoB,EAAE,IAAI,CAAC;IAC3B,0BAA0B,EAAE,IAAI,CAAC;IACjC,sBAAsB,EAAE,IAAI,CAAC;IAC7B,wBAAwB,EAAE,IAAI,CAAC;IAC/B,eAAe,EAAE,KAAK,CAAC;IACvB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,wBAAgB,gCAAgC,CAC9C,UAAU,EAAE,OAAO,GAClB,OAAO,CAIT;AAED,MAAM,WAAW,qCAAqC;IACpD,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,yBAAyB,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,CAAC,CAAC;CACd;AAED,MAAM,WAAW,oCAAoC;IACnD,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,yBAAyB,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,SAAS,GAAG,aAAa,CAAC;CAClC;AAED,MAAM,MAAM,2BAA2B,GACnC,kBAAkB,GAClB,kBAAkB,GAClB,wBAAwB,GACxB,qBAAqB,GACrB,0BAA0B,GAC1B,oBAAoB,GACpB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,0BAA0B;IACzC,UAAU,IAAI,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACnD,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC7D,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACpE,aAAa,CAAC,KAAK,EAAE,qCAAqC,GAAG,OAAO,CAAC,oCAAoC,CAAC,CAAC;IAC3G,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,UAAU,CAAC,KAAK,EAAE,kCAAkC,GAAG,OAAO,CAAC,mCAAmC,CAAC,CAAC;CACrG;AAED,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAClG;AAED,MAAM,WAAW,uCAAwC,SAAQ,iCAAiC;IAChG,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,+BAAgC,SAAQ,wBAAwB;IAC/E,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAClF;AAED,MAAM,WAAW,yCAA0C,SAAQ,iCAAiC;IAClG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,0BAA0B,GAClC,mCAAmC,GACnC,qCAAqC,GACrC,uCAAuC,GACvC,0CAA0C,GAC1C,kCAAkC,GAClC,oCAAoC,GACpC,uCAAuC,GACvC,uCAAuC,GACvC,yCAAyC,GACzC,qCAAqC,GACrC,uCAAuC,GACvC,0CAA0C,GAC1C,2CAA2C,GAC3C,gCAAgC,CAAC;AAErC,qBAAa,sBAAuB,SAAQ,KAAK;IAE7C,QAAQ,CAAC,IAAI,EAAE,0BAA0B;IAEzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAFhC,IAAI,EAAE,0BAA0B,EACzC,OAAO,EAAE,MAAM,EACN,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAKjD;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
@@ -4835,6 +4835,9 @@ init_types();
4835
4835
  // src/task-manifest/types.ts
4836
4836
  var TODOS_TASK_MANIFEST_ROUTE = "todos.task-manifest.v1";
4837
4837
  var TODOS_TASK_MANIFEST_SCHEMA_VERSION = 1;
4838
+ function supportsIdempotentOutboxDelivery(capability) {
4839
+ return capability !== null && typeof capability === "object" && capability["idempotent_outbox_delivery"] === true;
4840
+ }
4838
4841
 
4839
4842
  class TodosTaskManifestError extends Error {
4840
4843
  code;
@@ -5480,10 +5483,27 @@ class SqliteTodosTaskManifestBackend {
5480
5483
  SELECT 1 FROM todos_task_manifest_receipts r
5481
5484
  WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
5482
5485
  AND r.tenant_id = ?
5486
+ AND r.authority = 'todos'
5487
+ AND r.route = 'todos.task-manifest.v1'
5488
+ AND r.schema_version = 1
5489
+ AND r.kind = 'apply'
5483
5490
  )`).run(deliveredAt, outboxId, this.tenantId);
5484
- if (result.changes !== 1) {
5485
- throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
5486
- }
5491
+ if (result.changes === 1)
5492
+ return;
5493
+ const existing = this.db.query(`SELECT o.status
5494
+ FROM todos_task_manifest_outbox o
5495
+ JOIN todos_task_manifest_receipts r
5496
+ ON r.receipt_id = o.apply_receipt_id
5497
+ WHERE r.tenant_id = ?
5498
+ AND r.authority = 'todos'
5499
+ AND r.route = 'todos.task-manifest.v1'
5500
+ AND r.schema_version = 1
5501
+ AND r.kind = 'apply'
5502
+ AND o.id = ?
5503
+ LIMIT 1`).get(this.tenantId, outboxId);
5504
+ if (existing?.status === "delivered")
5505
+ return;
5506
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
5487
5507
  });
5488
5508
  }
5489
5509
  async compensate(input, receipt, compensationReceiptId, requestDigest, now) {
@@ -6419,6 +6439,22 @@ class PostgresTodosTaskManifestBackend {
6419
6439
  async markOutboxDelivered(outboxId, deliveredAt) {
6420
6440
  await this.ensureSchema();
6421
6441
  await this.client.transaction(async (tx) => {
6442
+ const owned = await tx.query(`SELECT r.operation_id
6443
+ FROM todos_task_manifest_outbox o
6444
+ JOIN todos_task_manifest_receipts r
6445
+ ON r.receipt_id = o.apply_receipt_id
6446
+ WHERE r.tenant_id = $1
6447
+ AND r.authority = 'todos'
6448
+ AND r.route = 'todos.task-manifest.v1'
6449
+ AND r.schema_version = 1
6450
+ AND r.kind = 'apply'
6451
+ AND o.id = $2
6452
+ LIMIT 1`, [this.tenantId, outboxId]);
6453
+ const operationId = owned.rows[0]?.operation_id;
6454
+ if (operationId == null) {
6455
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
6456
+ }
6457
+ await tx.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [`${this.service}\x1F${String(operationId)}`]);
6422
6458
  const result = await tx.query(`UPDATE todos_task_manifest_outbox
6423
6459
  SET status = 'delivered', delivered_at = $1, attempts = attempts + 1
6424
6460
  WHERE id = $2 AND status = 'pending'
@@ -6426,10 +6462,28 @@ class PostgresTodosTaskManifestBackend {
6426
6462
  SELECT 1 FROM todos_task_manifest_receipts r
6427
6463
  WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
6428
6464
  AND r.tenant_id = $3
6465
+ AND r.authority = 'todos'
6466
+ AND r.route = 'todos.task-manifest.v1'
6467
+ AND r.schema_version = 1
6468
+ AND r.kind = 'apply'
6429
6469
  )
6430
6470
  RETURNING id`, [deliveredAt, outboxId, this.tenantId]);
6431
- if (!result.rows[0])
6432
- throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
6471
+ if (result.rows[0])
6472
+ return;
6473
+ const existing = await tx.query(`SELECT o.status
6474
+ FROM todos_task_manifest_outbox o
6475
+ JOIN todos_task_manifest_receipts r
6476
+ ON r.receipt_id = o.apply_receipt_id
6477
+ WHERE r.tenant_id = $1
6478
+ AND r.authority = 'todos'
6479
+ AND r.route = 'todos.task-manifest.v1'
6480
+ AND r.schema_version = 1
6481
+ AND r.kind = 'apply'
6482
+ AND o.id = $2
6483
+ LIMIT 1`, [this.tenantId, outboxId]);
6484
+ if (existing.rows[0]?.status === "delivered")
6485
+ return;
6486
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
6433
6487
  });
6434
6488
  }
6435
6489
  async compensate(input, receipt, compensationReceiptId, requestDigest, now) {
@@ -6461,7 +6515,13 @@ class PostgresTodosTaskManifestBackend {
6461
6515
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Graph is not applied");
6462
6516
  const delivered = await tx.query(`SELECT o.id FROM todos_task_manifest_outbox o
6463
6517
  JOIN todos_task_manifest_receipts r ON r.receipt_id = o.apply_receipt_id
6464
- WHERE r.tenant_id = $1 AND o.apply_receipt_id = $2 AND o.status = 'delivered'
6518
+ WHERE r.tenant_id = $1
6519
+ AND r.authority = 'todos'
6520
+ AND r.route = 'todos.task-manifest.v1'
6521
+ AND r.schema_version = 1
6522
+ AND r.kind = 'apply'
6523
+ AND o.apply_receipt_id = $2
6524
+ AND o.status = 'delivered'
6465
6525
  LIMIT 1`, [this.tenantId, input.receipt_id]);
6466
6526
  if (delivered.rows[0])
6467
6527
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: delivered outbox row exists");
@@ -6474,15 +6534,20 @@ class PostgresTodosTaskManifestBackend {
6474
6534
  },
6475
6535
  ...(manifest.effects ?? []).map((effect2) => ({ topic: effect2.topic, payload: effect2.payload }))
6476
6536
  ];
6477
- const outboxRows = await tx.query(`SELECT id, topic, payload, payload_digest, status, attempts, delivered_at
6478
- FROM todos_task_manifest_outbox
6479
- WHERE apply_receipt_id = $1
6537
+ const outboxRows = await tx.query(`SELECT o.id, o.topic, o.payload, o.payload_digest, o.status, o.attempts, o.delivered_at
6538
+ FROM todos_task_manifest_outbox o
6539
+ WHERE o.apply_receipt_id = $1
6480
6540
  AND EXISTS (
6481
6541
  SELECT 1 FROM todos_task_manifest_receipts r
6482
- WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
6542
+ WHERE r.receipt_id = o.apply_receipt_id
6483
6543
  AND r.tenant_id = $2
6544
+ AND r.authority = 'todos'
6545
+ AND r.route = 'todos.task-manifest.v1'
6546
+ AND r.schema_version = 1
6547
+ AND r.kind = 'apply'
6484
6548
  )
6485
- ORDER BY id`, [input.receipt_id, this.tenantId]);
6549
+ ORDER BY o.id
6550
+ FOR UPDATE OF o`, [input.receipt_id, this.tenantId]);
6486
6551
  if (outboxRows.rows.length !== expectedEffects.length) {
6487
6552
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: outbox changed since apply");
6488
6553
  }
@@ -6582,14 +6647,23 @@ class PostgresTodosTaskManifestBackend {
6582
6647
  }
6583
6648
  if (stored.rows.length !== managedIds.length)
6584
6649
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: managed graph is incomplete");
6585
- await tx.query(`UPDATE todos_task_manifest_outbox
6650
+ const cancelled = await tx.query(`UPDATE todos_task_manifest_outbox
6586
6651
  SET status = 'cancelled'
6587
6652
  WHERE apply_receipt_id = $1 AND status = 'pending'
6588
6653
  AND EXISTS (
6589
6654
  SELECT 1 FROM todos_task_manifest_receipts r
6590
6655
  WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
6591
6656
  AND r.tenant_id = $2
6592
- )`, [input.receipt_id, this.tenantId]);
6657
+ AND r.authority = 'todos'
6658
+ AND r.route = 'todos.task-manifest.v1'
6659
+ AND r.schema_version = 1
6660
+ AND r.kind = 'apply'
6661
+ )
6662
+ RETURNING id`, [input.receipt_id, this.tenantId]);
6663
+ const cancelledIds = new Set(cancelled.rows.map((row) => String(row.id)));
6664
+ if (cancelledIds.size !== applyResult.outbox_ids.length || applyResult.outbox_ids.some((id) => !cancelledIds.has(id))) {
6665
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: failed to cancel every expected outbox row");
6666
+ }
6593
6667
  const typedIds = [
6594
6668
  ["dependencies", applyResult.graph.dependency_ids],
6595
6669
  ["comments", applyResult.graph.comment_ids],
@@ -6776,6 +6850,7 @@ class PackageOwnedTodosTaskManifestAuthority {
6776
6850
  deterministic_ids: true,
6777
6851
  immutable_receipts: true,
6778
6852
  transactional_outbox: true,
6853
+ idempotent_outbox_delivery: true,
6779
6854
  exact_bounded_readback: true,
6780
6855
  conditional_compensation: true,
6781
6856
  transcript_safe: false,
@@ -7028,6 +7103,7 @@ function createTodosTaskManifestHttpClient(options) {
7028
7103
  return new TodosTaskManifestHttpClient(options);
7029
7104
  }
7030
7105
  export {
7106
+ supportsIdempotentOutboxDelivery,
7031
7107
  sqliteTodosTaskManifestSchemaSql,
7032
7108
  postgresTodosTaskManifestSchemaSql,
7033
7109
  parseTodosTaskManifestCompensation,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.15.15",
3
+ "version": "0.15.16",
4
4
  "description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",