@hasna/todos 0.15.25 → 0.15.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -2123,7 +2123,7 @@ var package_default;
2123
2123
  var init_package = __esm(() => {
2124
2124
  package_default = {
2125
2125
  name: "@hasna/todos",
2126
- version: "0.15.25",
2126
+ version: "0.15.27",
2127
2127
  description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
2128
2128
  type: "module",
2129
2129
  main: "dist/index.js",
@@ -2172,7 +2172,8 @@ var init_package = __esm(() => {
2172
2172
  }
2173
2173
  },
2174
2174
  workspaces: [
2175
- "dashboard"
2175
+ "dashboard",
2176
+ "ai"
2176
2177
  ],
2177
2178
  files: [
2178
2179
  "dist",
@@ -2196,7 +2197,9 @@ var init_package = __esm(() => {
2196
2197
  "verify:release": "bun run scripts/verify-public-release.ts --mode=review",
2197
2198
  "verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
2198
2199
  "verify:attested-container-candidate": "bun run scripts/attested-container-candidate.ts verify",
2199
- "test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts",
2200
+ "test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts scripts/attested-container-compatibility-vector.test.ts",
2201
+ "emit:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts emit",
2202
+ "verify:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts verify",
2200
2203
  "issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
2201
2204
  prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
2202
2205
  postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
@@ -2243,6 +2246,7 @@ var init_package = __esm(() => {
2243
2246
  zod: "^3.24.2"
2244
2247
  },
2245
2248
  overrides: {
2249
+ ajv: "8.20.0",
2246
2250
  "fast-uri": "3.1.2"
2247
2251
  },
2248
2252
  devDependencies: {
@@ -5788,6 +5792,39 @@ async function cloudPrGroupEvents(client, groupId, options = {}) {
5788
5792
  throw new Error(`REMOTE_API_INCOMPATIBLE: ${route} did not return a complete closed authoritative remote event page; ` + "local SQLite fallback is disabled", { cause: error });
5789
5793
  }
5790
5794
  }
5795
+ function unwrapTaskManifestEnvelope(raw, key, route) {
5796
+ if (!raw || typeof raw !== "object" || Array.isArray(raw) || !(key in raw)) {
5797
+ throw new Error(`REMOTE_API_INCOMPATIBLE: ${route} returned a non-authoritative task-manifest response envelope; ` + "local SQLite fallback is disabled");
5798
+ }
5799
+ return raw[key];
5800
+ }
5801
+ async function cloudTaskManifestCapability(client) {
5802
+ const route = "/v1/task-manifest/capability";
5803
+ return unwrapTaskManifestEnvelope(await requiredRemoteRoute(client, route, () => client.transport.get("/task-manifest/capability")), "capability", route);
5804
+ }
5805
+ async function cloudApplyTaskManifest(client, input) {
5806
+ const route = "/v1/task-manifest/apply";
5807
+ return unwrapTaskManifestEnvelope(await requiredRemoteRoute(client, route, () => client.transport.post("/task-manifest/apply", input)), "result", route);
5808
+ }
5809
+ async function cloudReadExactTaskManifest(client, receiptId) {
5810
+ const route = "/v1/task-manifest/read-exact";
5811
+ return unwrapTaskManifestEnvelope(await requiredRemoteRoute(client, route, () => client.transport.post("/task-manifest/read-exact", { receipt_id: receiptId })), "result", route);
5812
+ }
5813
+ async function cloudLookupTaskManifestBinding(client, input) {
5814
+ const route = "/v1/task-manifest/bindings/lookup";
5815
+ return unwrapTaskManifestEnvelope(await requiredRemoteRoute(client, route, () => client.transport.post("/task-manifest/bindings/lookup", input)), "result", route);
5816
+ }
5817
+ async function cloudCompensateTaskManifest(client, input) {
5818
+ const route = "/v1/task-manifest/compensate";
5819
+ return unwrapTaskManifestEnvelope(await requiredRemoteRoute(client, route, () => client.transport.post("/task-manifest/compensate", input)), "result", route);
5820
+ }
5821
+ async function cloudMarkTaskManifestOutboxDelivered(client, outboxId) {
5822
+ const route = "/v1/task-manifest/outbox/delivered";
5823
+ const delivered = unwrapTaskManifestEnvelope(await requiredRemoteRoute(client, route, () => client.transport.post("/task-manifest/outbox/delivered", { outbox_id: outboxId })), "delivered", route);
5824
+ if (delivered !== true) {
5825
+ throw new Error(`REMOTE_API_INCOMPATIBLE: ${route} did not confirm task-manifest outbox delivery; ` + "local SQLite fallback is disabled");
5826
+ }
5827
+ }
5791
5828
  function unwrapTask(raw) {
5792
5829
  if (raw && typeof raw === "object" && "task" in raw) {
5793
5830
  return raw.task;
@@ -7759,6 +7796,7 @@ var init_stage_a = __esm(() => {
7759
7796
  "sync",
7760
7797
  "tag",
7761
7798
  "task",
7799
+ "task-manifest",
7762
7800
  "template-export",
7763
7801
  "template-history",
7764
7802
  "template-import",
@@ -7884,6 +7922,7 @@ var init_stage_a = __esm(() => {
7884
7922
  "task",
7885
7923
  "task-lists",
7886
7924
  "stale-lock-handoff",
7925
+ "task-manifest",
7887
7926
  "template-export",
7888
7927
  "template-import",
7889
7928
  "template-preview",
@@ -46091,6 +46130,13 @@ var init_schema2 = __esm(() => {
46091
46130
  }).strict();
46092
46131
  });
46093
46132
 
46133
+ // src/task-manifest/plan-slug.ts
46134
+ function taskManifestPlanSlug(manifest, planId) {
46135
+ const base = normalizeSlug(manifest.plan.key) || normalizeSlug(manifest.plan.name) || "plan";
46136
+ return `${base}-${planId}`;
46137
+ }
46138
+ var init_plan_slug = () => {};
46139
+
46094
46140
  // src/task-manifest/backend.ts
46095
46141
  function validateTaskManifestBindingLookupRows(rows, tenantId, planId) {
46096
46142
  if (rows.length === 0) {
@@ -46119,6 +46165,67 @@ var init_backend = __esm(() => {
46119
46165
  });
46120
46166
 
46121
46167
  // src/task-manifest/reference-guard.ts
46168
+ function quoteSqliteIdentifier2(value) {
46169
+ return `"${value.replaceAll('"', '""')}"`;
46170
+ }
46171
+ function placeholders3(count) {
46172
+ return Array.from({ length: count }, () => "?").join(",");
46173
+ }
46174
+ function sqliteManagedReferencePredicate(table, field, target, managed) {
46175
+ const taskPlaceholders = placeholders3(managed.task_ids.length);
46176
+ if (table === "tasks" && field === "plan_id" && target === "plans") {
46177
+ return {
46178
+ sql: `id IN (${taskPlaceholders})`,
46179
+ values: managed.task_ids
46180
+ };
46181
+ }
46182
+ if (table === "task_dependencies" && target === "tasks" && (field === "task_id" || field === "depends_on")) {
46183
+ return {
46184
+ sql: `task_id IN (${taskPlaceholders}) AND depends_on IN (${taskPlaceholders})`,
46185
+ values: [...managed.task_ids, ...managed.task_ids]
46186
+ };
46187
+ }
46188
+ if (table === "task_comments" && field === "task_id" && target === "tasks") {
46189
+ return managed.comment_ids.length > 0 ? { sql: `id IN (${placeholders3(managed.comment_ids.length)})`, values: managed.comment_ids } : { sql: "0", values: [] };
46190
+ }
46191
+ if (table === "task_verifications" && field === "task_id" && target === "tasks") {
46192
+ return managed.verification_ids.length > 0 ? { sql: `id IN (${placeholders3(managed.verification_ids.length)})`, values: managed.verification_ids } : { sql: "0", values: [] };
46193
+ }
46194
+ if (table === "task_tags" && field === "task_id" && target === "tasks") {
46195
+ return {
46196
+ sql: `task_id IN (${taskPlaceholders})`,
46197
+ values: managed.task_ids
46198
+ };
46199
+ }
46200
+ return null;
46201
+ }
46202
+ function findSqliteTaskManifestForeignReference(db, managed) {
46203
+ const tables = db.query(`SELECT name FROM sqlite_master
46204
+ WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name`).all();
46205
+ for (const { name: table } of tables) {
46206
+ const foreignKeys = db.query(`PRAGMA foreign_key_list(${quoteSqliteIdentifier2(table)})`).all();
46207
+ for (const foreignKey of foreignKeys) {
46208
+ if (foreignKey.table !== "tasks" && foreignKey.table !== "plans")
46209
+ continue;
46210
+ const target = foreignKey.table;
46211
+ const targetIds = target === "tasks" ? managed.task_ids : [managed.plan_id];
46212
+ const owned = sqliteManagedReferencePredicate(table, foreignKey.from, target, managed);
46213
+ const sql = `SELECT 1 AS found FROM ${quoteSqliteIdentifier2(table)}
46214
+ WHERE ${quoteSqliteIdentifier2(foreignKey.from)} IN (${placeholders3(targetIds.length)})
46215
+ ${owned ? `AND NOT (${owned.sql})` : ""}
46216
+ LIMIT 1`;
46217
+ if (db.query(sql).get(...targetIds, ...owned?.values ?? [])) {
46218
+ return {
46219
+ surface: table,
46220
+ field: foreignKey.from,
46221
+ target,
46222
+ on_delete: foreignKey.on_delete.toUpperCase()
46223
+ };
46224
+ }
46225
+ }
46226
+ }
46227
+ return null;
46228
+ }
46122
46229
  function postgresTaskManifestForeignReferenceSql(tableName) {
46123
46230
  return `SELECT object_type, object_id
46124
46231
  FROM ${tableName}
@@ -46148,6 +46255,89 @@ function postgresTaskManifestForeignReferenceSql(tableName) {
46148
46255
  function sqlString(value) {
46149
46256
  return `'${value.replaceAll("'", "''")}'`;
46150
46257
  }
46258
+ function sqliteTodosTaskManifestSchemaSql() {
46259
+ return `
46260
+ CREATE TABLE IF NOT EXISTS todos_task_manifest_receipts (
46261
+ receipt_id TEXT PRIMARY KEY,
46262
+ tenant_id TEXT NOT NULL,
46263
+ authority TEXT NOT NULL CHECK(authority = 'todos'),
46264
+ route TEXT NOT NULL,
46265
+ schema_version INTEGER NOT NULL CHECK(schema_version = 1),
46266
+ kind TEXT NOT NULL CHECK(kind IN ('apply', 'compensate')),
46267
+ operation_id TEXT NOT NULL,
46268
+ idempotency_key TEXT NOT NULL,
46269
+ request_digest TEXT NOT NULL,
46270
+ result_digest TEXT NOT NULL,
46271
+ binding_version INTEGER NOT NULL,
46272
+ apply_receipt_id TEXT,
46273
+ manifest_json TEXT,
46274
+ result_json TEXT NOT NULL,
46275
+ created_at TEXT NOT NULL,
46276
+ UNIQUE(kind, idempotency_key)
46277
+ );
46278
+ CREATE TABLE IF NOT EXISTS todos_task_manifest_bindings (
46279
+ operation_id TEXT PRIMARY KEY,
46280
+ tenant_id TEXT NOT NULL,
46281
+ idempotency_key TEXT NOT NULL UNIQUE,
46282
+ request_digest TEXT NOT NULL,
46283
+ result_digest TEXT NOT NULL,
46284
+ apply_receipt_id TEXT NOT NULL UNIQUE REFERENCES todos_task_manifest_receipts(receipt_id),
46285
+ manifest_json TEXT NOT NULL,
46286
+ result_json TEXT NOT NULL,
46287
+ state TEXT NOT NULL CHECK(state IN ('applied', 'compensated')),
46288
+ version INTEGER NOT NULL,
46289
+ compensation_receipt_id TEXT,
46290
+ created_at TEXT NOT NULL,
46291
+ updated_at TEXT NOT NULL
46292
+ );
46293
+ CREATE TABLE IF NOT EXISTS todos_task_manifest_outbox (
46294
+ id TEXT PRIMARY KEY,
46295
+ apply_receipt_id TEXT NOT NULL REFERENCES todos_task_manifest_receipts(receipt_id),
46296
+ topic TEXT NOT NULL,
46297
+ payload TEXT NOT NULL,
46298
+ payload_digest TEXT NOT NULL,
46299
+ status TEXT NOT NULL CHECK(status IN ('pending', 'delivered', 'cancelled')),
46300
+ attempts INTEGER NOT NULL DEFAULT 0,
46301
+ created_at TEXT NOT NULL,
46302
+ delivered_at TEXT
46303
+ );
46304
+ CREATE INDEX IF NOT EXISTS idx_todos_task_manifest_outbox_receipt
46305
+ ON todos_task_manifest_outbox(apply_receipt_id, status);
46306
+ CREATE TRIGGER IF NOT EXISTS todos_task_manifest_receipts_immutable_update
46307
+ BEFORE UPDATE ON todos_task_manifest_receipts BEGIN
46308
+ SELECT RAISE(ABORT, 'todos task manifest receipts are immutable');
46309
+ END;
46310
+ CREATE TRIGGER IF NOT EXISTS todos_task_manifest_receipts_immutable_delete
46311
+ BEFORE DELETE ON todos_task_manifest_receipts BEGIN
46312
+ SELECT RAISE(ABORT, 'todos task manifest receipts are immutable');
46313
+ END;
46314
+ `;
46315
+ }
46316
+ function sqliteTableHasColumn(db, tableName, columnName) {
46317
+ const columns = db.query(`PRAGMA table_info("${tableName}")`).all();
46318
+ return columns.some((column) => column.name === columnName);
46319
+ }
46320
+ function ensureSqliteTodosTaskManifestSchema(db, tenantId) {
46321
+ db.exec(sqliteTodosTaskManifestSchemaSql());
46322
+ const tenantDefault = sqlString(tenantId);
46323
+ for (const tableName of [
46324
+ "todos_task_manifest_receipts",
46325
+ "todos_task_manifest_bindings"
46326
+ ]) {
46327
+ if (!sqliteTableHasColumn(db, tableName, "tenant_id")) {
46328
+ db.exec(`ALTER TABLE "${tableName}" ADD COLUMN tenant_id TEXT NOT NULL DEFAULT ${tenantDefault}`);
46329
+ }
46330
+ }
46331
+ db.exec(`
46332
+ CREATE INDEX IF NOT EXISTS idx_todos_task_manifest_receipts_tenant
46333
+ ON todos_task_manifest_receipts(tenant_id, receipt_id, kind);
46334
+ CREATE INDEX IF NOT EXISTS idx_todos_task_manifest_bindings_tenant_plan
46335
+ ON todos_task_manifest_bindings(
46336
+ tenant_id,
46337
+ json_extract(result_json, '$.graph.plan_id')
46338
+ );
46339
+ `);
46340
+ }
46151
46341
  function postgresTodosTaskManifestSchemaSql(tenantId = "default") {
46152
46342
  const tenantDefault = sqlString(tenantId);
46153
46343
  return [
@@ -46224,9 +46414,411 @@ function postgresTodosTaskManifestSchemaSql(tenantId = "default") {
46224
46414
  }
46225
46415
 
46226
46416
  // src/task-manifest/sqlite.ts
46417
+ function fault(faults, point) {
46418
+ if (faults.points.has(point))
46419
+ throw new Error(`Injected task-manifest fault at ${point}`);
46420
+ }
46421
+ function parseApplyResult(value, duplicate) {
46422
+ return { ...JSON.parse(value), duplicate };
46423
+ }
46424
+
46425
+ class SqliteTodosTaskManifestBackend {
46426
+ db;
46427
+ tenantId;
46428
+ kind = "sqlite";
46429
+ constructor(db, tenantId = "default") {
46430
+ this.db = db;
46431
+ this.tenantId = tenantId;
46432
+ ensureSqliteTodosTaskManifestSchema(db, tenantId);
46433
+ }
46434
+ async serialized(run) {
46435
+ const previous = sqliteTails.get(this.db) ?? Promise.resolve();
46436
+ let release;
46437
+ const current = new Promise((resolve17) => {
46438
+ release = resolve17;
46439
+ });
46440
+ const tail = previous.then(() => current);
46441
+ sqliteTails.set(this.db, tail);
46442
+ await previous;
46443
+ try {
46444
+ this.db.exec("BEGIN IMMEDIATE");
46445
+ try {
46446
+ const result = run();
46447
+ this.db.exec("COMMIT");
46448
+ return result;
46449
+ } catch (error) {
46450
+ this.db.exec("ROLLBACK");
46451
+ throw error;
46452
+ }
46453
+ } finally {
46454
+ release();
46455
+ if (sqliteTails.get(this.db) === tail)
46456
+ sqliteTails.delete(this.db);
46457
+ }
46458
+ }
46459
+ async apply(input, faults) {
46460
+ return this.serialized(() => {
46461
+ const { manifest } = input;
46462
+ const binding = this.db.query("SELECT * FROM todos_task_manifest_bindings WHERE tenant_id = ? AND operation_id = ? LIMIT 1").get(this.tenantId, manifest.operation_id);
46463
+ if (binding) {
46464
+ if (binding["idempotency_key"] !== manifest.idempotency_key || binding["request_digest"] !== input.request_digest) {
46465
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_IDEMPOTENCY_CONFLICT", "Operation is already bound to a different request");
46466
+ }
46467
+ if (binding["state"] !== "applied") {
46468
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", "Operation was already compensated");
46469
+ }
46470
+ return parseApplyResult(String(binding["result_json"]), true);
46471
+ }
46472
+ const idempotency = this.db.query("SELECT operation_id, request_digest FROM todos_task_manifest_bindings WHERE tenant_id = ? AND idempotency_key = ? LIMIT 1").get(this.tenantId, manifest.idempotency_key);
46473
+ if (idempotency)
46474
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_IDEMPOTENCY_CONFLICT", "Idempotency key is already used by another operation");
46475
+ if (manifest.if_binding_version !== undefined && manifest.if_binding_version !== 0) {
46476
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_CAS_CONFLICT", "New manifest binding version must be 0");
46477
+ }
46478
+ if (!this.db.query("SELECT 1 AS found FROM projects WHERE id = ? LIMIT 1").get(manifest.project_id)) {
46479
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_FOREIGN_REFERENCE", "Project does not exist");
46480
+ }
46481
+ if (manifest.task_list_id && !this.db.query("SELECT 1 AS found FROM task_lists WHERE id = ? AND project_id = ? LIMIT 1").get(manifest.task_list_id, manifest.project_id)) {
46482
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_FOREIGN_REFERENCE", "Task list does not belong to the project");
46483
+ }
46484
+ const allIds = [input.graph.plan_id, ...Object.values(input.graph.task_ids), ...input.graph.comment_ids, ...input.graph.verification_ids];
46485
+ for (const id of allIds) {
46486
+ for (const table of ["plans", "tasks", "task_comments", "task_verifications"]) {
46487
+ if (this.db.query(`SELECT 1 AS found FROM ${table} WHERE id = ? LIMIT 1`).get(id)) {
46488
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Deterministic id already exists: ${id}`);
46489
+ }
46490
+ }
46491
+ }
46492
+ this.db.query(`INSERT INTO plans (id, project_id, name, description, status, task_list_id, slug, created_at, updated_at)
46493
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.graph.plan_id, manifest.project_id, manifest.plan.name, manifest.plan.description ?? null, manifest.plan.status ?? "active", manifest.task_list_id ?? null, taskManifestPlanSlug(manifest, input.graph.plan_id), input.now, input.now);
46494
+ fault(faults, "after_plan_write");
46495
+ for (const task2 of manifest.tasks) {
46496
+ const taskId = input.graph.task_ids[task2.key];
46497
+ this.db.query(`INSERT INTO tasks (
46498
+ id, project_id, title, description, status, priority, assigned_to, tags, metadata,
46499
+ version, plan_id, task_list_id, created_at, updated_at, created_by
46500
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?)`).run(taskId, manifest.project_id, task2.title, task2.description ?? null, task2.status ?? "pending", task2.priority ?? "medium", task2.assigned_to ?? null, JSON.stringify(task2.tags ?? []), canonicalJson2(task2.metadata ?? {}), input.graph.plan_id, manifest.task_list_id ?? null, input.now, input.now, task2.created_by ?? null);
46501
+ for (const tag of [...new Set(task2.tags ?? [])].sort()) {
46502
+ this.db.query("INSERT INTO task_tags (task_id, tag) VALUES (?, ?)").run(taskId, tag);
46503
+ }
46504
+ }
46505
+ fault(faults, "after_task_write");
46506
+ for (const edge of manifest.dependencies ?? []) {
46507
+ this.db.query("INSERT INTO task_dependencies (task_id, depends_on) VALUES (?, ?)").run(input.graph.task_ids[edge.task], input.graph.task_ids[edge.depends_on]);
46508
+ }
46509
+ fault(faults, "after_dependency_write");
46510
+ let commentIndex = 0;
46511
+ for (const task2 of manifest.tasks)
46512
+ for (const comment2 of task2.comments ?? []) {
46513
+ this.db.query(`INSERT INTO task_comments (id, task_id, agent_id, session_id, content, created_at, type, progress_pct)
46514
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(input.graph.comment_ids[commentIndex++], input.graph.task_ids[task2.key], comment2.agent_id ?? null, comment2.session_id ?? null, comment2.content, input.now, comment2.type ?? "comment", comment2.progress_pct ?? null);
46515
+ }
46516
+ fault(faults, "after_comment_write");
46517
+ let verificationIndex = 0;
46518
+ for (const task2 of manifest.tasks)
46519
+ for (const verification2 of task2.verifications ?? []) {
46520
+ this.db.query(`INSERT INTO task_verifications (
46521
+ id, task_id, command, status, output_summary, artifact_path, agent_id, run_at, created_at
46522
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.graph.verification_ids[verificationIndex++], input.graph.task_ids[task2.key], verification2.command, verification2.status ?? "unknown", verification2.output_summary ?? null, verification2.artifact_path ?? null, verification2.agent_id ?? null, input.now, input.now);
46523
+ }
46524
+ fault(faults, "after_verification_write");
46525
+ const readback = this.readback(input.graph);
46526
+ const expected = {
46527
+ plans: 1,
46528
+ tasks: manifest.tasks.length,
46529
+ dependencies: manifest.dependencies?.length ?? 0,
46530
+ comments: input.graph.comment_ids.length,
46531
+ verifications: input.graph.verification_ids.length,
46532
+ complete: true
46533
+ };
46534
+ if (canonicalJson2(readback) !== canonicalJson2(expected)) {
46535
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_READBACK_MISMATCH", "Exact graph readback did not match", { expected, readback });
46536
+ }
46537
+ const receipt = {
46538
+ receipt_id: input.receipt_id,
46539
+ authority: "todos",
46540
+ route: "todos.task-manifest.v1",
46541
+ schema_version: 1,
46542
+ kind: "apply",
46543
+ operation_id: manifest.operation_id,
46544
+ idempotency_key: manifest.idempotency_key,
46545
+ request_digest: input.request_digest,
46546
+ result_digest: input.result_digest,
46547
+ binding_version: 1,
46548
+ apply_receipt_id: null,
46549
+ created_at: input.now
46550
+ };
46551
+ const result = {
46552
+ duplicate: false,
46553
+ receipt,
46554
+ graph: input.graph,
46555
+ readback,
46556
+ outbox_ids: input.outbox.map((entry2) => entry2.id),
46557
+ result_digest: input.result_digest
46558
+ };
46559
+ const resultJson2 = canonicalJson2(result);
46560
+ const manifestJson = canonicalJson2(manifest);
46561
+ this.db.query(`INSERT INTO todos_task_manifest_receipts (
46562
+ receipt_id, tenant_id, authority, route, schema_version, kind, operation_id, idempotency_key,
46563
+ request_digest, result_digest, binding_version, apply_receipt_id, manifest_json, result_json, created_at
46564
+ ) VALUES (?, ?, 'todos', 'todos.task-manifest.v1', 1, 'apply', ?, ?, ?, ?, 1, NULL, ?, ?, ?)`).run(input.receipt_id, this.tenantId, manifest.operation_id, manifest.idempotency_key, input.request_digest, input.result_digest, manifestJson, resultJson2, input.now);
46565
+ for (const entry2 of input.outbox) {
46566
+ this.db.query(`INSERT INTO todos_task_manifest_outbox (
46567
+ id, apply_receipt_id, topic, payload, payload_digest, status, created_at
46568
+ ) VALUES (?, ?, ?, ?, ?, 'pending', ?)`).run(entry2.id, input.receipt_id, entry2.topic, canonicalJson2(entry2.payload), entry2.digest, input.now);
46569
+ }
46570
+ fault(faults, "after_outbox_write");
46571
+ this.db.query(`INSERT INTO todos_task_manifest_bindings (
46572
+ operation_id, tenant_id, idempotency_key, request_digest, result_digest, apply_receipt_id,
46573
+ manifest_json, result_json, state, version, created_at, updated_at
46574
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'applied', 1, ?, ?)`).run(manifest.operation_id, this.tenantId, manifest.idempotency_key, input.request_digest, input.result_digest, input.receipt_id, manifestJson, resultJson2, input.now, input.now);
46575
+ fault(faults, "after_receipt_write");
46576
+ return result;
46577
+ });
46578
+ }
46579
+ async readExact(receiptId3) {
46580
+ const row = this.db.query("SELECT result_json FROM todos_task_manifest_receipts WHERE tenant_id = ? AND receipt_id = ? AND kind = 'apply' LIMIT 1").get(this.tenantId, receiptId3);
46581
+ if (!row)
46582
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_RECEIPT_NOT_FOUND", `Apply receipt not found: ${receiptId3}`);
46583
+ return parseApplyResult(row.result_json, false);
46584
+ }
46585
+ async lookupBindingByPlanId(planId) {
46586
+ const rows = this.db.query(`
46587
+ SELECT
46588
+ b.apply_receipt_id AS apply_receipt_id,
46589
+ b.state AS state,
46590
+ b.version AS binding_version,
46591
+ b.tenant_id AS binding_tenant_id,
46592
+ b.operation_id AS binding_operation_id,
46593
+ json_extract(b.result_json, '$.graph.plan_id') AS binding_plan_id,
46594
+ r.tenant_id AS receipt_tenant_id,
46595
+ r.authority AS receipt_authority,
46596
+ r.route AS receipt_route,
46597
+ r.schema_version AS receipt_schema_version,
46598
+ r.kind AS receipt_kind,
46599
+ r.operation_id AS receipt_operation_id,
46600
+ json_extract(r.result_json, '$.graph.plan_id') AS receipt_plan_id
46601
+ FROM todos_task_manifest_bindings b
46602
+ LEFT JOIN todos_task_manifest_receipts r
46603
+ ON r.receipt_id = b.apply_receipt_id
46604
+ AND r.tenant_id = b.tenant_id
46605
+ WHERE b.tenant_id = ?
46606
+ AND json_extract(b.result_json, '$.graph.plan_id') = ?
46607
+ LIMIT 2
46608
+ `).all(this.tenantId, planId);
46609
+ return validateTaskManifestBindingLookupRows(rows, this.tenantId, planId);
46610
+ }
46611
+ async markOutboxDelivered(outboxId, deliveredAt) {
46612
+ await this.serialized(() => {
46613
+ const result = this.db.query(`UPDATE todos_task_manifest_outbox
46614
+ SET status = 'delivered', delivered_at = ?, attempts = attempts + 1
46615
+ WHERE id = ? AND status = 'pending'
46616
+ AND EXISTS (
46617
+ SELECT 1 FROM todos_task_manifest_receipts r
46618
+ WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
46619
+ AND r.tenant_id = ?
46620
+ AND r.authority = 'todos'
46621
+ AND r.route = 'todos.task-manifest.v1'
46622
+ AND r.schema_version = 1
46623
+ AND r.kind = 'apply'
46624
+ )`).run(deliveredAt, outboxId, this.tenantId);
46625
+ if (result.changes === 1)
46626
+ return;
46627
+ const existing = this.db.query(`SELECT o.status
46628
+ FROM todos_task_manifest_outbox o
46629
+ JOIN todos_task_manifest_receipts r
46630
+ ON r.receipt_id = o.apply_receipt_id
46631
+ WHERE r.tenant_id = ?
46632
+ AND r.authority = 'todos'
46633
+ AND r.route = 'todos.task-manifest.v1'
46634
+ AND r.schema_version = 1
46635
+ AND r.kind = 'apply'
46636
+ AND o.id = ?
46637
+ LIMIT 1`).get(this.tenantId, outboxId);
46638
+ if (existing?.status === "delivered")
46639
+ return;
46640
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
46641
+ });
46642
+ }
46643
+ async compensate(input, receipt, compensationReceiptId, requestDigest, now4) {
46644
+ return this.serialized(() => {
46645
+ const existing = this.db.query(`SELECT apply_receipt_id, request_digest, result_json
46646
+ FROM todos_task_manifest_receipts
46647
+ WHERE tenant_id = ? AND kind = 'compensate' AND idempotency_key = ?
46648
+ LIMIT 1`).get(this.tenantId, input.idempotency_key);
46649
+ if (existing) {
46650
+ if (existing.apply_receipt_id !== input.receipt_id || existing.request_digest !== requestDigest) {
46651
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_IDEMPOTENCY_CONFLICT", "Compensation idempotency key is already used");
46652
+ }
46653
+ return { ...JSON.parse(existing.result_json), duplicate: true };
46654
+ }
46655
+ const row = this.db.query("SELECT * FROM todos_task_manifest_receipts WHERE tenant_id = ? AND receipt_id = ? AND kind = 'apply' LIMIT 1").get(this.tenantId, input.receipt_id);
46656
+ if (!row)
46657
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_RECEIPT_NOT_FOUND", "Apply receipt not found");
46658
+ const binding = this.db.query("SELECT * FROM todos_task_manifest_bindings WHERE tenant_id = ? AND operation_id = ? LIMIT 1").get(this.tenantId, String(row["operation_id"]));
46659
+ if (!binding || Number(binding["version"]) !== input.if_binding_version) {
46660
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_CAS_CONFLICT", "Binding version changed before compensation");
46661
+ }
46662
+ if (binding["state"] !== "applied")
46663
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Graph is not in applied state");
46664
+ const delivered = this.db.query(`SELECT o.id FROM todos_task_manifest_outbox o
46665
+ JOIN todos_task_manifest_receipts r ON r.receipt_id = o.apply_receipt_id
46666
+ WHERE r.tenant_id = ? AND o.apply_receipt_id = ? AND o.status = 'delivered'
46667
+ LIMIT 1`).get(this.tenantId, input.receipt_id);
46668
+ if (delivered)
46669
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: delivered outbox row exists");
46670
+ const applyResult = parseApplyResult(String(row["result_json"]), false);
46671
+ const manifest = JSON.parse(String(row["manifest_json"]));
46672
+ const expectedEffects = [
46673
+ {
46674
+ topic: "todos.task-manifest.applied",
46675
+ payload: { operation_id: manifest.operation_id, project_id: manifest.project_id }
46676
+ },
46677
+ ...(manifest.effects ?? []).map((effect2) => ({ topic: effect2.topic, payload: effect2.payload }))
46678
+ ];
46679
+ const storedOutbox = this.db.query(`SELECT id, topic, payload, payload_digest, status, attempts, delivered_at
46680
+ FROM todos_task_manifest_outbox
46681
+ WHERE apply_receipt_id = ?
46682
+ AND EXISTS (
46683
+ SELECT 1 FROM todos_task_manifest_receipts r
46684
+ WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
46685
+ AND r.tenant_id = ?
46686
+ )
46687
+ ORDER BY id`).all(input.receipt_id, this.tenantId);
46688
+ if (storedOutbox.length !== expectedEffects.length) {
46689
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: outbox changed since apply");
46690
+ }
46691
+ const outboxById = new Map(storedOutbox.map((entry2) => [String(entry2["id"]), entry2]));
46692
+ for (const [index, expectedEffect] of expectedEffects.entries()) {
46693
+ const stored = outboxById.get(applyResult.outbox_ids[index]);
46694
+ const expectedPayload = canonicalJson2(expectedEffect.payload);
46695
+ if (!stored || stored["topic"] !== expectedEffect.topic || stored["payload"] !== expectedPayload || stored["payload_digest"] !== canonicalDigest(expectedEffect) || stored["status"] !== "pending" || Number(stored["attempts"]) !== 0 || stored["delivered_at"] !== null) {
46696
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: outbox changed since apply");
46697
+ }
46698
+ }
46699
+ const taskIds = Object.values(applyResult.graph.task_ids);
46700
+ const placeholders4 = taskIds.map(() => "?").join(",");
46701
+ const foreignReference = findSqliteTaskManifestForeignReference(this.db, {
46702
+ plan_id: applyResult.graph.plan_id,
46703
+ task_ids: taskIds,
46704
+ dependency_ids: applyResult.graph.dependency_ids,
46705
+ comment_ids: applyResult.graph.comment_ids,
46706
+ verification_ids: applyResult.graph.verification_ids
46707
+ });
46708
+ if (foreignReference) {
46709
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", `Compensation refused: foreign reference at ${foreignReference.surface}.${foreignReference.field} would be changed by ${foreignReference.on_delete}`, { ...foreignReference });
46710
+ }
46711
+ const actualReadback = this.readback(applyResult.graph);
46712
+ if (canonicalJson2(actualReadback) !== canonicalJson2(applyResult.readback)) {
46713
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: graph changed since apply", { actualReadback });
46714
+ }
46715
+ const plan = this.db.query("SELECT project_id, name, description, status, task_list_id, slug FROM plans WHERE id = ? LIMIT 1").get(applyResult.graph.plan_id);
46716
+ if (!plan || plan["project_id"] !== manifest.project_id || plan["name"] !== manifest.plan.name || plan["description"] !== (manifest.plan.description ?? null) || plan["status"] !== (manifest.plan.status ?? "active") || plan["task_list_id"] !== (manifest.task_list_id ?? null) || plan["slug"] !== taskManifestPlanSlug(manifest, applyResult.graph.plan_id)) {
46717
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: plan changed since apply");
46718
+ }
46719
+ for (const task2 of manifest.tasks) {
46720
+ const stored = this.db.query("SELECT title, description, status, priority, assigned_to, tags, metadata, created_by FROM tasks WHERE id = ? LIMIT 1").get(applyResult.graph.task_ids[task2.key]);
46721
+ if (!stored || stored["title"] !== task2.title || stored["description"] !== (task2.description ?? null) || stored["status"] !== (task2.status ?? "pending") || stored["priority"] !== (task2.priority ?? "medium") || stored["assigned_to"] !== (task2.assigned_to ?? null) || stored["tags"] !== JSON.stringify(task2.tags ?? []) || stored["metadata"] !== canonicalJson2(task2.metadata ?? {}) || stored["created_by"] !== (task2.created_by ?? null)) {
46722
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", `Compensation refused: task ${task2.key} changed since apply`);
46723
+ }
46724
+ const storedTags = this.db.query("SELECT tag FROM task_tags WHERE task_id = ? ORDER BY tag").all(applyResult.graph.task_ids[task2.key]).map((row2) => row2.tag);
46725
+ const expectedTags = [...new Set(task2.tags ?? [])].sort();
46726
+ if (canonicalJson2(storedTags) !== canonicalJson2(expectedTags)) {
46727
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", `Compensation refused: task ${task2.key} tags changed since apply`);
46728
+ }
46729
+ }
46730
+ const storedDependencies = this.db.query(`SELECT task_id, depends_on FROM task_dependencies
46731
+ WHERE task_id IN (${placeholders4}) AND depends_on IN (${placeholders4}) ORDER BY task_id, depends_on`).all(...taskIds, ...taskIds);
46732
+ const expectedDependencies = (manifest.dependencies ?? []).map((edge) => ({
46733
+ task_id: applyResult.graph.task_ids[edge.task],
46734
+ depends_on: applyResult.graph.task_ids[edge.depends_on]
46735
+ })).sort((left, right) => left.task_id.localeCompare(right.task_id) || left.depends_on.localeCompare(right.depends_on));
46736
+ if (canonicalJson2(storedDependencies) !== canonicalJson2(expectedDependencies)) {
46737
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: dependencies changed since apply");
46738
+ }
46739
+ let expectedCommentIndex = 0;
46740
+ for (const task2 of manifest.tasks)
46741
+ for (const comment2 of task2.comments ?? []) {
46742
+ const stored = this.db.query(`SELECT task_id, agent_id, session_id, content, type, progress_pct
46743
+ FROM task_comments WHERE id = ? LIMIT 1`).get(applyResult.graph.comment_ids[expectedCommentIndex]);
46744
+ const expected = {
46745
+ task_id: applyResult.graph.task_ids[task2.key],
46746
+ agent_id: comment2.agent_id ?? null,
46747
+ session_id: comment2.session_id ?? null,
46748
+ content: comment2.content,
46749
+ type: comment2.type ?? "comment",
46750
+ progress_pct: comment2.progress_pct ?? null
46751
+ };
46752
+ if (!stored || canonicalJson2(stored) !== canonicalJson2(expected)) {
46753
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: comment changed since apply");
46754
+ }
46755
+ expectedCommentIndex += 1;
46756
+ }
46757
+ let expectedVerificationIndex = 0;
46758
+ for (const task2 of manifest.tasks)
46759
+ for (const verification2 of task2.verifications ?? []) {
46760
+ const stored = this.db.query(`SELECT task_id, command, status, output_summary, artifact_path, agent_id
46761
+ FROM task_verifications WHERE id = ? LIMIT 1`).get(applyResult.graph.verification_ids[expectedVerificationIndex]);
46762
+ const expected = {
46763
+ task_id: applyResult.graph.task_ids[task2.key],
46764
+ command: verification2.command,
46765
+ status: verification2.status ?? "unknown",
46766
+ output_summary: verification2.output_summary ?? null,
46767
+ artifact_path: verification2.artifact_path ?? null,
46768
+ agent_id: verification2.agent_id ?? null
46769
+ };
46770
+ if (!stored || canonicalJson2(stored) !== canonicalJson2(expected)) {
46771
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: verification changed since apply");
46772
+ }
46773
+ expectedVerificationIndex += 1;
46774
+ }
46775
+ this.db.query(`UPDATE todos_task_manifest_outbox
46776
+ SET status = 'cancelled'
46777
+ WHERE apply_receipt_id = ? AND status = 'pending'
46778
+ AND EXISTS (
46779
+ SELECT 1 FROM todos_task_manifest_receipts r
46780
+ WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
46781
+ AND r.tenant_id = ?
46782
+ )`).run(input.receipt_id, this.tenantId);
46783
+ for (const table of ["task_tags", "task_dependencies", "task_comments", "task_verifications"]) {
46784
+ const column = table === "task_dependencies" ? "task_id" : "task_id";
46785
+ this.db.query(`DELETE FROM ${table} WHERE ${column} IN (${placeholders4})`).run(...taskIds);
46786
+ }
46787
+ this.db.query(`DELETE FROM tasks WHERE id IN (${placeholders4})`).run(...taskIds);
46788
+ this.db.query("DELETE FROM plans WHERE id = ?").run(applyResult.graph.plan_id);
46789
+ const readback = this.readback(applyResult.graph);
46790
+ const result = { duplicate: false, receipt, absent: true, readback };
46791
+ const resultJson2 = canonicalJson2(result);
46792
+ this.db.query(`INSERT INTO todos_task_manifest_receipts (
46793
+ receipt_id, tenant_id, authority, route, schema_version, kind, operation_id, idempotency_key,
46794
+ request_digest, result_digest, binding_version, apply_receipt_id, manifest_json, result_json, created_at
46795
+ ) VALUES (?, ?, 'todos', 'todos.task-manifest.v1', 1, 'compensate', ?, ?, ?, ?, ?, ?, NULL, ?, ?)`).run(compensationReceiptId, this.tenantId, receipt.operation_id, input.idempotency_key, requestDigest, receipt.result_digest, receipt.binding_version, input.receipt_id, resultJson2, now4);
46796
+ const updated = this.db.query(`UPDATE todos_task_manifest_bindings SET state = 'compensated', version = ?, compensation_receipt_id = ?, updated_at = ?
46797
+ WHERE tenant_id = ? AND operation_id = ? AND state = 'applied' AND version = ?`).run(receipt.binding_version, compensationReceiptId, now4, this.tenantId, receipt.operation_id, input.if_binding_version);
46798
+ if (updated.changes !== 1) {
46799
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_CAS_CONFLICT", "Binding changed during compensation");
46800
+ }
46801
+ return result;
46802
+ });
46803
+ }
46804
+ readback(graph) {
46805
+ const taskIds = Object.values(graph.task_ids);
46806
+ const placeholders4 = taskIds.map(() => "?").join(",");
46807
+ const count = (sql, ...values) => Number(this.db.query(sql).get(...values).count);
46808
+ return {
46809
+ plans: count("SELECT count(*) AS count FROM plans WHERE id = ?", graph.plan_id),
46810
+ tasks: count(`SELECT count(*) AS count FROM tasks WHERE id IN (${placeholders4})`, ...taskIds),
46811
+ dependencies: count(`SELECT count(*) AS count FROM task_dependencies WHERE task_id IN (${placeholders4}) AND depends_on IN (${placeholders4})`, ...taskIds, ...taskIds),
46812
+ comments: count(`SELECT count(*) AS count FROM task_comments WHERE id IN (${graph.comment_ids.map(() => "?").join(",") || "NULL"})`, ...graph.comment_ids),
46813
+ verifications: count(`SELECT count(*) AS count FROM task_verifications WHERE id IN (${graph.verification_ids.map(() => "?").join(",") || "NULL"})`, ...graph.verification_ids),
46814
+ complete: true
46815
+ };
46816
+ }
46817
+ }
46227
46818
  var sqliteTails;
46228
46819
  var init_sqlite2 = __esm(() => {
46229
46820
  init_canonical();
46821
+ init_plan_slug();
46230
46822
  init_backend();
46231
46823
  init_types5();
46232
46824
  sqliteTails = new WeakMap;
@@ -46245,7 +46837,7 @@ function parseJson2(value) {
46245
46837
  function timestamp2(value) {
46246
46838
  return value instanceof Date ? value.toISOString() : new Date(String(value)).toISOString();
46247
46839
  }
46248
- function fault(faults, point) {
46840
+ function fault2(faults, point) {
46249
46841
  if (faults.points.has(point))
46250
46842
  throw new Error(`Injected task-manifest fault at ${point}`);
46251
46843
  }
@@ -46327,7 +46919,7 @@ function taskPayload(manifest, task2, taskId, planId, now4) {
46327
46919
  function planPayload(input) {
46328
46920
  return {
46329
46921
  id: input.graph.plan_id,
46330
- slug: null,
46922
+ slug: taskManifestPlanSlug(input.manifest, input.graph.plan_id),
46331
46923
  project_id: input.manifest.project_id,
46332
46924
  task_list_id: input.manifest.task_list_id ?? null,
46333
46925
  agent_id: null,
@@ -46340,7 +46932,7 @@ function planPayload(input) {
46340
46932
  synced_at: null
46341
46933
  };
46342
46934
  }
46343
- function placeholders3(start, count) {
46935
+ function placeholders4(start, count) {
46344
46936
  return Array.from({ length: count }, (_, index) => `$${start + index}`).join(",");
46345
46937
  }
46346
46938
 
@@ -46414,15 +47006,15 @@ class PostgresTodosTaskManifestBackend {
46414
47006
  }
46415
47007
  const objectIds = [input.graph.plan_id, ...Object.values(input.graph.task_ids), ...input.graph.comment_ids, ...input.graph.verification_ids, ...input.graph.dependency_ids];
46416
47008
  const conflict = await tx.query(`SELECT object_id FROM ${this.tableName}
46417
- WHERE service = $1 AND object_id IN (${placeholders3(2, objectIds.length)}) LIMIT 1`, [this.service, ...objectIds]);
47009
+ WHERE service = $1 AND object_id IN (${placeholders4(2, objectIds.length)}) LIMIT 1`, [this.service, ...objectIds]);
46418
47010
  if (conflict.rows[0])
46419
47011
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", "A deterministic graph id already exists");
46420
47012
  await this.insertSync(tx, "plans", input.graph.plan_id, planPayload(input), input.now);
46421
- fault(faults, "after_plan_write");
47013
+ fault2(faults, "after_plan_write");
46422
47014
  for (const task2 of manifest.tasks) {
46423
47015
  await this.insertSync(tx, "tasks", input.graph.task_ids[task2.key], taskPayload(manifest, task2, input.graph.task_ids[task2.key], input.graph.plan_id, input.now), input.now);
46424
47016
  }
46425
- fault(faults, "after_task_write");
47017
+ fault2(faults, "after_task_write");
46426
47018
  for (const [index, edge] of (manifest.dependencies ?? []).entries()) {
46427
47019
  await this.insertSync(tx, "dependencies", input.graph.dependency_ids[index], {
46428
47020
  id: input.graph.dependency_ids[index],
@@ -46432,7 +47024,7 @@ class PostgresTodosTaskManifestBackend {
46432
47024
  updated_at: input.now
46433
47025
  }, input.now);
46434
47026
  }
46435
- fault(faults, "after_dependency_write");
47027
+ fault2(faults, "after_dependency_write");
46436
47028
  let commentIndex = 0;
46437
47029
  for (const task2 of manifest.tasks)
46438
47030
  for (const comment2 of task2.comments ?? []) {
@@ -46448,7 +47040,7 @@ class PostgresTodosTaskManifestBackend {
46448
47040
  created_at: input.now
46449
47041
  }, input.now);
46450
47042
  }
46451
- fault(faults, "after_comment_write");
47043
+ fault2(faults, "after_comment_write");
46452
47044
  let verificationIndex = 0;
46453
47045
  for (const task2 of manifest.tasks)
46454
47046
  for (const verification2 of task2.verifications ?? []) {
@@ -46466,7 +47058,7 @@ class PostgresTodosTaskManifestBackend {
46466
47058
  updated_at: input.now
46467
47059
  }, input.now);
46468
47060
  }
46469
- fault(faults, "after_verification_write");
47061
+ fault2(faults, "after_verification_write");
46470
47062
  const readback = await this.readback(tx, input.graph);
46471
47063
  const expected = {
46472
47064
  plans: 1,
@@ -46529,7 +47121,7 @@ class PostgresTodosTaskManifestBackend {
46529
47121
  input.now
46530
47122
  ]);
46531
47123
  }
46532
- fault(faults, "after_outbox_write");
47124
+ fault2(faults, "after_outbox_write");
46533
47125
  await tx.query(`INSERT INTO todos_task_manifest_bindings (
46534
47126
  operation_id, tenant_id, idempotency_key, request_digest, result_digest, apply_receipt_id,
46535
47127
  manifest_json, result_json, state, version, created_at, updated_at
@@ -46544,7 +47136,7 @@ class PostgresTodosTaskManifestBackend {
46544
47136
  resultJson2,
46545
47137
  input.now
46546
47138
  ]);
46547
- fault(faults, "after_receipt_write");
47139
+ fault2(faults, "after_receipt_write");
46548
47140
  return result;
46549
47141
  });
46550
47142
  }
@@ -46784,7 +47376,7 @@ class PostgresTodosTaskManifestBackend {
46784
47376
  }
46785
47377
  const managedIds = [...expectedPayloads.keys()];
46786
47378
  const stored = await tx.query(`SELECT object_type, object_id, payload FROM ${this.tableName}
46787
- WHERE service = $1 AND object_id IN (${placeholders3(2, managedIds.length)})`, [this.service, ...managedIds]);
47379
+ WHERE service = $1 AND object_id IN (${placeholders4(2, managedIds.length)})`, [this.service, ...managedIds]);
46788
47380
  for (const row of stored.rows) {
46789
47381
  const expected = expectedPayloads.get(String(row["object_id"]));
46790
47382
  if (!expected || expected.type !== row["object_type"] || expected.payload !== canonicalJson2(parseJson2(row["payload"]))) {
@@ -46821,7 +47413,7 @@ class PostgresTodosTaskManifestBackend {
46821
47413
  if (!ids.length)
46822
47414
  continue;
46823
47415
  await tx.query(`DELETE FROM ${this.tableName} WHERE service = $1 AND object_type = $2
46824
- AND object_id IN (${placeholders3(3, ids.length)})`, [this.service, objectType2, ...ids]);
47416
+ AND object_id IN (${placeholders4(3, ids.length)})`, [this.service, objectType2, ...ids]);
46825
47417
  }
46826
47418
  const readback = await this.readback(tx, applyResult.graph);
46827
47419
  const result = { duplicate: false, receipt, absent: true, readback };
@@ -46861,7 +47453,7 @@ class PostgresTodosTaskManifestBackend {
46861
47453
  return 0;
46862
47454
  const result = await tx.query(`SELECT count(*) AS count FROM ${this.tableName}
46863
47455
  WHERE service = $1 AND object_type = $2 AND deleted_at IS NULL
46864
- AND object_id IN (${placeholders3(3, ids.length)})`, [this.service, objectType2, ...ids]);
47456
+ AND object_id IN (${placeholders4(3, ids.length)})`, [this.service, objectType2, ...ids]);
46865
47457
  return Number(result.rows[0]?.count ?? 0);
46866
47458
  };
46867
47459
  return {
@@ -46876,6 +47468,7 @@ class PostgresTodosTaskManifestBackend {
46876
47468
  }
46877
47469
  var init_postgres3 = __esm(() => {
46878
47470
  init_canonical();
47471
+ init_plan_slug();
46879
47472
  init_backend();
46880
47473
  init_postgres_sync();
46881
47474
  init_types5();
@@ -47078,6 +47671,13 @@ class PackageOwnedTodosTaskManifestAuthority {
47078
47671
  return result;
47079
47672
  }
47080
47673
  }
47674
+ function createSqliteTodosTaskManifestAuthority(options) {
47675
+ if (!options?.database) {
47676
+ throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_ATOMICITY_UNAVAILABLE", "An explicit SQLite Database is required");
47677
+ }
47678
+ const tenantId = resolveTenantId(options.tenantId);
47679
+ return new PackageOwnedTodosTaskManifestAuthority(new SqliteTodosTaskManifestBackend(options.database, tenantId), { ...options, tenantId });
47680
+ }
47081
47681
  function createPostgresTodosTaskManifestAuthority(client, options = {}) {
47082
47682
  if (!client || typeof client.transaction !== "function") {
47083
47683
  throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_ATOMICITY_UNAVAILABLE", "An authoritative PostgreSQL transaction(callback) client is required");
@@ -49404,7 +50004,7 @@ __export(exports_openapi, {
49404
50004
  buildV1OpenApiDocument: () => buildV1OpenApiDocument
49405
50005
  });
49406
50006
  function buildV1OpenApiDocument(version = getPackageVersion()) {
49407
- return {
50007
+ return structuredClone({
49408
50008
  openapi: "3.1.0",
49409
50009
  info: {
49410
50010
  title: "Todos V1 API",
@@ -49419,6 +50019,9 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
49419
50019
  schemas: {
49420
50020
  Task: taskSchema,
49421
50021
  Project: projectSchema,
50022
+ TaskManifestBounds: taskManifestBoundsSchema,
50023
+ TaskManifestCapability: taskManifestCapabilitySchema,
50024
+ TaskManifestCapabilityResponse: taskManifestCapabilityResponseSchema,
49422
50025
  TaskManifestBindingLookupRequest: taskManifestBindingLookupRequestSchema,
49423
50026
  TaskManifestBindingLookupResult: taskManifestBindingLookupResultSchema,
49424
50027
  TaskManifestBindingLookupResponse: taskManifestBindingLookupResponseSchema,
@@ -50418,6 +51021,23 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
50418
51021
  },
50419
51022
  security: [{ apiKey: [] }],
50420
51023
  paths: {
51024
+ "/v1/task-manifest/capability": {
51025
+ get: {
51026
+ operationId: "getTaskManifestCapability",
51027
+ summary: "Read the current task-manifest authority capability and tenant",
51028
+ responses: {
51029
+ "200": {
51030
+ content: {
51031
+ "application/json": {
51032
+ schema: { $ref: "#/components/schemas/TaskManifestCapabilityResponse" }
51033
+ }
51034
+ }
51035
+ },
51036
+ "401": { content: { "application/json": { schema: { $ref: "#/components/schemas/ErrorResponse" } } } },
51037
+ "503": { content: { "application/json": { schema: { $ref: "#/components/schemas/ErrorResponse" } } } }
51038
+ }
51039
+ }
51040
+ },
50421
51041
  "/v1/task-manifest/bindings/lookup": {
50422
51042
  post: {
50423
51043
  operationId: "lookupTaskManifestBinding",
@@ -51276,9 +51896,9 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
51276
51896
  }
51277
51897
  }
51278
51898
  }
51279
- };
51899
+ });
51280
51900
  }
51281
- var taskSchema, projectSchema, taskManifestBindingLookupRequestSchema, taskManifestBindingLookupResultSchema, taskManifestBindingLookupResponseSchema, taskListSchema, projectTaskListEnsureReceiptSchema, projectTaskListEnsureResultSchema, projectTaskListRollbackResultSchema, taskCommentSchema, staleLockHandoffInputSchema, staleLockHandoffReceiptSchema, taskGitRefSchema, planSchema, planProjectLinkReceiptSchema, planProjectLinkResultSchema, planProjectLinkRollbackResultSchema, templateTaskSchema, templateSchema, templateVariableSchema, createTemplateTaskInputSchema;
51901
+ var taskSchema, taskManifestBoundsSchema, taskManifestCapabilitySchema, taskManifestCapabilityResponseSchema, projectSchema, taskManifestBindingLookupRequestSchema, taskManifestBindingLookupResultSchema, taskManifestBindingLookupResponseSchema, taskListSchema, projectTaskListEnsureReceiptSchema, projectTaskListEnsureResultSchema, projectTaskListRollbackResultSchema, taskCommentSchema, staleLockHandoffInputSchema, staleLockHandoffReceiptSchema, taskGitRefSchema, planSchema, planProjectLinkReceiptSchema, planProjectLinkResultSchema, planProjectLinkRollbackResultSchema, templateTaskSchema, templateSchema, templateVariableSchema, createTemplateTaskInputSchema;
51282
51902
  var init_openapi = __esm(() => {
51283
51903
  init_package_version();
51284
51904
  init_types();
@@ -51304,6 +51924,74 @@ var init_openapi = __esm(() => {
51304
51924
  updated_at: { type: "string" }
51305
51925
  }
51306
51926
  };
51927
+ taskManifestBoundsSchema = {
51928
+ type: "object",
51929
+ additionalProperties: false,
51930
+ required: [
51931
+ "tasks",
51932
+ "dependencies",
51933
+ "comments",
51934
+ "verifications",
51935
+ "effects",
51936
+ "metadata_fields",
51937
+ "effect_payload_fields",
51938
+ "request_bytes",
51939
+ "response_bytes"
51940
+ ],
51941
+ properties: {
51942
+ tasks: { type: "integer", minimum: 1 },
51943
+ dependencies: { type: "integer", minimum: 1 },
51944
+ comments: { type: "integer", minimum: 1 },
51945
+ verifications: { type: "integer", minimum: 1 },
51946
+ effects: { type: "integer", minimum: 1 },
51947
+ metadata_fields: { type: "integer", minimum: 1 },
51948
+ effect_payload_fields: { type: "integer", minimum: 1 },
51949
+ request_bytes: { type: "integer", minimum: 1 },
51950
+ response_bytes: { type: "integer", minimum: 1 }
51951
+ }
51952
+ };
51953
+ taskManifestCapabilitySchema = {
51954
+ type: "object",
51955
+ additionalProperties: false,
51956
+ required: [
51957
+ "authority",
51958
+ "route",
51959
+ "schema_version",
51960
+ "tenant_id",
51961
+ "backend",
51962
+ "deterministic_ids",
51963
+ "immutable_receipts",
51964
+ "transactional_outbox",
51965
+ "idempotent_outbox_delivery",
51966
+ "exact_bounded_readback",
51967
+ "conditional_compensation",
51968
+ "transcript_safe",
51969
+ "bounds"
51970
+ ],
51971
+ properties: {
51972
+ authority: { type: "string", enum: ["todos"] },
51973
+ route: { type: "string", enum: ["todos.task-manifest.v1"] },
51974
+ schema_version: { type: "integer", enum: [1] },
51975
+ tenant_id: { type: "string", minLength: 1, maxLength: 200 },
51976
+ backend: { type: "string", enum: ["sqlite", "postgresql", "http"] },
51977
+ deterministic_ids: { type: "boolean", enum: [true] },
51978
+ immutable_receipts: { type: "boolean", enum: [true] },
51979
+ transactional_outbox: { type: "boolean", enum: [true] },
51980
+ idempotent_outbox_delivery: { type: "boolean", enum: [true] },
51981
+ exact_bounded_readback: { type: "boolean", enum: [true] },
51982
+ conditional_compensation: { type: "boolean", enum: [true] },
51983
+ transcript_safe: { type: "boolean", enum: [false] },
51984
+ bounds: { $ref: "#/components/schemas/TaskManifestBounds" }
51985
+ }
51986
+ };
51987
+ taskManifestCapabilityResponseSchema = {
51988
+ type: "object",
51989
+ additionalProperties: false,
51990
+ required: ["capability"],
51991
+ properties: {
51992
+ capability: { $ref: "#/components/schemas/TaskManifestCapability" }
51993
+ }
51994
+ };
51307
51995
  projectSchema = {
51308
51996
  type: "object",
51309
51997
  properties: {
@@ -60189,18 +60877,18 @@ function createSessionRecoveryHandoff(input, db) {
60189
60877
  LIMIT ?
60190
60878
  `).all(...params, limit);
60191
60879
  const taskIds = tasks.map((task2) => task2.id);
60192
- const placeholders4 = taskIds.map(() => "?").join(",");
60880
+ const placeholders5 = taskIds.map(() => "?").join(",");
60193
60881
  const files = taskIds.length ? d.query(`
60194
60882
  SELECT DISTINCT path
60195
60883
  FROM task_files
60196
- WHERE task_id IN (${placeholders4}) AND status != 'removed'
60884
+ WHERE task_id IN (${placeholders5}) AND status != 'removed'
60197
60885
  ORDER BY updated_at DESC, path
60198
60886
  LIMIT ?
60199
60887
  `).all(...taskIds, limit).map((row) => row.path) : [];
60200
60888
  const runs = taskIds.length ? d.query(`
60201
60889
  SELECT id
60202
60890
  FROM task_runs
60203
- WHERE task_id IN (${placeholders4})
60891
+ WHERE task_id IN (${placeholders5})
60204
60892
  ORDER BY started_at DESC, created_at DESC
60205
60893
  LIMIT ?
60206
60894
  `).all(...taskIds, limit).map((row) => row.id) : [];
@@ -69771,8 +70459,8 @@ function findPath(sourceId, targetId, opts, db) {
69771
70459
  let sql = "SELECT * FROM kg_edges WHERE source_id = ?";
69772
70460
  const params = [current.id];
69773
70461
  if (opts?.relation_types && opts.relation_types.length > 0) {
69774
- const placeholders4 = opts.relation_types.map(() => "?").join(",");
69775
- sql += ` AND relation_type IN (${placeholders4})`;
70462
+ const placeholders5 = opts.relation_types.map(() => "?").join(",");
70463
+ sql += ` AND relation_type IN (${placeholders5})`;
69776
70464
  params.push(...opts.relation_types);
69777
70465
  }
69778
70466
  const edges = d.query(sql).all(...params).map(rowToEdge);
@@ -69807,8 +70495,8 @@ function getImpactAnalysis(entityId, opts, db) {
69807
70495
  let sql = "SELECT * FROM kg_edges WHERE source_id = ?";
69808
70496
  const params = [current.id];
69809
70497
  if (opts?.relation_types && opts.relation_types.length > 0) {
69810
- const placeholders4 = opts.relation_types.map(() => "?").join(",");
69811
- sql += ` AND relation_type IN (${placeholders4})`;
70498
+ const placeholders5 = opts.relation_types.map(() => "?").join(",");
70499
+ sql += ` AND relation_type IN (${placeholders5})`;
69812
70500
  params.push(...opts.relation_types);
69813
70501
  }
69814
70502
  const edges = d.query(sql).all(...params).map(rowToEdge);
@@ -90970,6 +91658,156 @@ var init_pr_group_commands = __esm(() => {
90970
91658
  init_helpers();
90971
91659
  });
90972
91660
 
91661
+ // src/cli/commands/task-manifest-commands.ts
91662
+ var exports_task_manifest_commands = {};
91663
+ __export(exports_task_manifest_commands, {
91664
+ registerTaskManifestCommands: () => registerTaskManifestCommands
91665
+ });
91666
+ import chalk32 from "chalk";
91667
+ import { readFileSync as readFileSync26 } from "fs";
91668
+ function globalOptions11(program2) {
91669
+ const command = program2;
91670
+ return command.optsWithGlobals?.() ?? program2.opts();
91671
+ }
91672
+ function jsonRequested(program2, opts) {
91673
+ return opts.json === true || globalOptions11(program2)["json"] === true;
91674
+ }
91675
+ function parseJsonFile(path) {
91676
+ try {
91677
+ return JSON.parse(readFileSync26(path, "utf8"));
91678
+ } catch (error2) {
91679
+ throw new Error(`task-manifest input must be a readable JSON file: ${error2 instanceof Error ? error2.message : String(error2)}`);
91680
+ }
91681
+ }
91682
+ function parseInteger2(value, label, min) {
91683
+ const parsed = Number(value);
91684
+ if (!Number.isSafeInteger(parsed) || parsed < min) {
91685
+ throw new Error(`${label} must be an integer >= ${min}`);
91686
+ }
91687
+ return parsed;
91688
+ }
91689
+ async function localAuthority(tenantId) {
91690
+ return createSqliteTodosTaskManifestAuthority({
91691
+ database: getDatabase(),
91692
+ ...tenantId ? { tenantId } : {}
91693
+ });
91694
+ }
91695
+ async function currentTenantId(remote, authority, explicit) {
91696
+ if (explicit)
91697
+ return explicit;
91698
+ const capability = remote ? await cloudTaskManifestCapability(remote) : await authority.capability();
91699
+ return capability.tenant_id;
91700
+ }
91701
+ function registerTaskManifestCommands(program2) {
91702
+ const taskManifest = program2.command("task-manifest").description("Apply and inspect package-owned task-manifest safe mutations");
91703
+ taskManifest.command("capability").description("Show the current task-manifest authority capability").option("-j, --json", "Output as JSON").option("--tenant-id <id>", "Tenant id for local SQLite authority").action(async (opts) => {
91704
+ try {
91705
+ const remote = getTodosCloudClient();
91706
+ const result = remote ? await cloudTaskManifestCapability(remote) : await (await localAuthority(opts.tenantId)).capability();
91707
+ if (jsonRequested(program2, opts)) {
91708
+ output({ capability: result }, true);
91709
+ return;
91710
+ }
91711
+ console.log(`${chalk32.bold(result.route)} tenant=${result.tenant_id} backend=${result.backend}`);
91712
+ } catch (error2) {
91713
+ handleError(error2);
91714
+ }
91715
+ });
91716
+ taskManifest.command("apply").description("Apply a task-manifest JSON file exactly once by operation/idempotency key").requiredOption("--file <path>", "Task manifest JSON file").option("-j, --json", "Output as JSON").option("--tenant-id <id>", "Tenant id for local SQLite authority").action(async (opts) => {
91717
+ try {
91718
+ const manifest = parseJsonFile(opts.file);
91719
+ const remote = getTodosCloudClient();
91720
+ const result = remote ? await cloudApplyTaskManifest(remote, manifest) : await (await localAuthority(opts.tenantId)).apply(manifest);
91721
+ if (jsonRequested(program2, opts)) {
91722
+ output({ result }, true);
91723
+ return;
91724
+ }
91725
+ console.log(`${result.duplicate ? "duplicate" : "applied"} receipt=${result.receipt.receipt_id}`);
91726
+ console.log(`plan=${result.graph.plan_id} tasks=${Object.keys(result.graph.task_ids).length}`);
91727
+ } catch (error2) {
91728
+ handleError(error2);
91729
+ }
91730
+ });
91731
+ taskManifest.command("read-exact <receipt-id>").description("Read one immutable task-manifest apply receipt by full receipt id").option("-j, --json", "Output as JSON").option("--tenant-id <id>", "Tenant id for local SQLite authority").action(async (receiptId3, opts) => {
91732
+ try {
91733
+ const remote = getTodosCloudClient();
91734
+ const result = remote ? await cloudReadExactTaskManifest(remote, receiptId3) : await (await localAuthority(opts.tenantId)).readExact(receiptId3);
91735
+ if (jsonRequested(program2, opts)) {
91736
+ output({ result }, true);
91737
+ return;
91738
+ }
91739
+ console.log(`receipt=${result.receipt.receipt_id} duplicate=${String(result.duplicate)}`);
91740
+ console.log(`readback=${JSON.stringify(result.readback)}`);
91741
+ } catch (error2) {
91742
+ handleError(error2);
91743
+ }
91744
+ });
91745
+ taskManifest.command("lookup").description("Recover one exact managed apply receipt from a full plan id").requiredOption("--plan-id <uuid>", "Full managed plan UUID").option("--tenant-id <id>", "Authority tenant id; defaults to capability tenant").option("-j, --json", "Output as JSON").action(async (opts) => {
91746
+ try {
91747
+ const remote = getTodosCloudClient();
91748
+ const authority = remote ? null : await localAuthority(opts.tenantId);
91749
+ const tenantId = await currentTenantId(remote, authority, opts.tenantId);
91750
+ const request = {
91751
+ authority: "todos",
91752
+ route: TODOS_TASK_MANIFEST_ROUTE,
91753
+ schema_version: TODOS_TASK_MANIFEST_SCHEMA_VERSION,
91754
+ tenant_id: tenantId,
91755
+ plan_id: opts.planId,
91756
+ max_items: 1
91757
+ };
91758
+ const result = remote ? await cloudLookupTaskManifestBinding(remote, request) : await authority.lookupBinding(request);
91759
+ if (jsonRequested(program2, opts)) {
91760
+ output({ result }, true);
91761
+ return;
91762
+ }
91763
+ console.log(`plan=${result.plan_id} receipt=${result.apply_receipt_id} state=${result.state}`);
91764
+ } catch (error2) {
91765
+ handleError(error2);
91766
+ }
91767
+ });
91768
+ taskManifest.command("compensate").description("Compensate an untouched task-manifest graph with CAS protection").requiredOption("--receipt-id <uuid>", "Full apply receipt UUID").requiredOption("--idempotency-key <key>", "Stable compensation idempotency key").requiredOption("--if-binding-version <n>", "Expected current binding version").option("-j, --json", "Output as JSON").option("--tenant-id <id>", "Tenant id for local SQLite authority").action(async (opts) => {
91769
+ try {
91770
+ const request = {
91771
+ receipt_id: opts.receiptId,
91772
+ idempotency_key: opts.idempotencyKey,
91773
+ if_binding_version: parseInteger2(opts.ifBindingVersion, "--if-binding-version", 1)
91774
+ };
91775
+ const remote = getTodosCloudClient();
91776
+ const result = remote ? await cloudCompensateTaskManifest(remote, request) : await (await localAuthority(opts.tenantId)).compensate(request);
91777
+ if (jsonRequested(program2, opts)) {
91778
+ output({ result }, true);
91779
+ return;
91780
+ }
91781
+ console.log(`${result.duplicate ? "duplicate" : "compensated"} receipt=${result.receipt.receipt_id}`);
91782
+ console.log(`absent=${String(result.absent)} readback=${JSON.stringify(result.readback)}`);
91783
+ } catch (error2) {
91784
+ handleError(error2);
91785
+ }
91786
+ });
91787
+ taskManifest.command("outbox-delivered <outbox-id>").description("Mark one task-manifest outbox effect delivered").option("-j, --json", "Output as JSON").option("--tenant-id <id>", "Tenant id for local SQLite authority").action(async (outboxId, opts) => {
91788
+ try {
91789
+ const remote = getTodosCloudClient();
91790
+ if (remote)
91791
+ await cloudMarkTaskManifestOutboxDelivered(remote, outboxId);
91792
+ else
91793
+ await (await localAuthority(opts.tenantId)).markOutboxDelivered(outboxId);
91794
+ if (jsonRequested(program2, opts)) {
91795
+ output({ delivered: true }, true);
91796
+ return;
91797
+ }
91798
+ console.log(`delivered=${outboxId}`);
91799
+ } catch (error2) {
91800
+ handleError(error2);
91801
+ }
91802
+ });
91803
+ }
91804
+ var init_task_manifest_commands = __esm(() => {
91805
+ init_database();
91806
+ init_task_manifest();
91807
+ init_cloud_router();
91808
+ init_helpers();
91809
+ });
91810
+
90973
91811
  // src/lib/cli-help.ts
90974
91812
  function optionEntry(option) {
90975
91813
  return {
@@ -91233,7 +92071,7 @@ var exports_help_commands = {};
91233
92071
  __export(exports_help_commands, {
91234
92072
  registerHelpCommands: () => registerHelpCommands
91235
92073
  });
91236
- function globalOptions11(program2) {
92074
+ function globalOptions12(program2) {
91237
92075
  const command = program2;
91238
92076
  return command.optsWithGlobals?.() ?? program2.opts();
91239
92077
  }
@@ -91252,7 +92090,7 @@ function registerHelpCommands(program2, route = "local", remoteCapabilities = ne
91252
92090
  });
91253
92091
  program2.command("manual").description("Print the complete local CLI manual").option("--format <format>", "markdown or json", "markdown").option("-j, --json", "Output as JSON").action((opts) => {
91254
92092
  try {
91255
- const globalOpts = globalOptions11(program2);
92093
+ const globalOpts = globalOptions12(program2);
91256
92094
  const manual = createCliManual(program2, {
91257
92095
  isCommandVisible: (command) => isTodosCliCommandVisibleForRoute(command, route, remoteCapabilities),
91258
92096
  localOnly: route === "local"
@@ -91387,6 +92225,7 @@ var [
91387
92225
  { registerStorageCommands: registerStorageCommands2 },
91388
92226
  { registerScaleHardeningCommands: registerScaleHardeningCommands2 },
91389
92227
  { registerPrGroupCommands: registerPrGroupCommands2 },
92228
+ { registerTaskManifestCommands: registerTaskManifestCommands2 },
91390
92229
  { registerHelpCommands: registerHelpCommands2 }
91391
92230
  ] = await Promise.all([
91392
92231
  Promise.resolve().then(() => (init_helpers(), exports_helpers)),
@@ -91420,6 +92259,7 @@ var [
91420
92259
  Promise.resolve().then(() => (init_storage_commands(), exports_storage_commands)),
91421
92260
  Promise.resolve().then(() => (init_scale_hardening_commands(), exports_scale_hardening_commands)),
91422
92261
  Promise.resolve().then(() => (init_pr_group_commands(), exports_pr_group_commands)),
92262
+ Promise.resolve().then(() => (init_task_manifest_commands(), exports_task_manifest_commands)),
91423
92263
  Promise.resolve().then(() => (init_help_commands(), exports_help_commands))
91424
92264
  ]);
91425
92265
  registerTaskCommands2(program2);
@@ -91452,6 +92292,7 @@ registerLocalBackupCommands2(program2);
91452
92292
  registerStorageCommands2(program2);
91453
92293
  registerScaleHardeningCommands2(program2);
91454
92294
  registerPrGroupCommands2(program2);
92295
+ registerTaskManifestCommands2(program2);
91455
92296
  await registerOptionalEventsCommands(program2);
91456
92297
  registerHelpCommands2(program2, authority.route, remoteCommandCapabilities);
91457
92298
  applyTodosCliHelpVisibility(program2, authority.route, remoteCommandCapabilities);