@askexenow/exe-os 0.8.57 → 0.8.58

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/bin/cli.js CHANGED
@@ -13713,13 +13713,20 @@ async function cleanupOrphanedReviews() {
13713
13713
  const client = getClient();
13714
13714
  const now = (/* @__PURE__ */ new Date()).toISOString();
13715
13715
  const r1 = await client.execute({
13716
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
13717
- WHERE status = 'needs_review'
13716
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
13717
+ WHERE status IN ('open', 'needs_review', 'in_progress')
13718
13718
  AND assigned_by = 'system'
13719
13719
  AND title LIKE 'Review:%'
13720
13720
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
13721
13721
  args: [now]
13722
13722
  });
13723
+ const r1b = await client.execute({
13724
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
13725
+ WHERE status IN ('open', 'needs_review')
13726
+ AND title LIKE 'Review:%completed%'
13727
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
13728
+ args: [now]
13729
+ });
13723
13730
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
13724
13731
  const r2 = await client.execute({
13725
13732
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -13728,10 +13735,10 @@ async function cleanupOrphanedReviews() {
13728
13735
  AND updated_at < ?`,
13729
13736
  args: [now, staleThreshold]
13730
13737
  });
13731
- const total = r1.rowsAffected + r2.rowsAffected;
13738
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
13732
13739
  if (total > 0) {
13733
13740
  process.stderr.write(
13734
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
13741
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
13735
13742
  `
13736
13743
  );
13737
13744
  }
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/bin/customer-readiness.ts
4
+ import { readFileSync, existsSync } from "fs";
5
+ import { execSync } from "child_process";
6
+ import path from "path";
7
+ import { fileURLToPath } from "url";
8
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ var ROOT = path.resolve(__dirname, "../..");
10
+ var pass = 0;
11
+ var fail = 0;
12
+ function test(name, fn) {
13
+ try {
14
+ const result = fn();
15
+ if (result === true || result === "pass") {
16
+ console.log(` \x1B[32m\u2713\x1B[0m ${name}`);
17
+ pass++;
18
+ } else {
19
+ console.log(` \x1B[31m\u2717\x1B[0m ${name}: ${result}`);
20
+ fail++;
21
+ }
22
+ } catch (err) {
23
+ console.log(` \x1B[31m\u2717\x1B[0m ${name}: ${err instanceof Error ? err.message : String(err)}`);
24
+ fail++;
25
+ }
26
+ }
27
+ function readSrc(relPath) {
28
+ return readFileSync(path.join(ROOT, relPath), "utf8");
29
+ }
30
+ console.log("\n\x1B[1mCustomer Readiness Gate\x1B[0m\n");
31
+ test("Mode 1 detection \u2014 bare exe-os shows guidance, not TUI", () => {
32
+ const cli = readSrc("src/bin/cli.ts");
33
+ if (!cli.includes("Mode 1 detected")) return "cli.ts missing Mode 1 detection";
34
+ if (!cli.includes("hasClaudeCode")) return "cli.ts missing Claude Code check";
35
+ return true;
36
+ });
37
+ test("Review orphans \u2014 no createTaskCore in review generation", () => {
38
+ const review = readSrc("src/lib/tasks-review.ts");
39
+ if (review.includes("createTaskCore(")) return "createTaskCore still called \u2014 will create orphan tasks";
40
+ return true;
41
+ });
42
+ test("Cloud sync \u2014 sqlSafe() protects all cloudPull functions", () => {
43
+ const sync = readSrc("src/lib/cloud-sync.ts");
44
+ if (!sync.includes("function sqlSafe")) return "sqlSafe() helper missing";
45
+ const count = (sync.match(/sqlSafe\(/g) || []).length;
46
+ if (count < 20) return `Only ${count} sqlSafe() usages (expected 20+)`;
47
+ return true;
48
+ });
49
+ test("Session scoping \u2014 task-scope.ts helper exists", () => {
50
+ if (!existsSync(path.join(ROOT, "src/lib/task-scope.ts"))) return "task-scope.ts missing";
51
+ const scope = readSrc("src/lib/task-scope.ts");
52
+ if (!scope.includes("sessionScopeFilter")) return "sessionScopeFilter not exported";
53
+ return true;
54
+ });
55
+ test("Session scoping \u2014 all task query files import scope helper", () => {
56
+ const taskFiles = execSync(
57
+ `grep -rl "FROM tasks" src/ --include="*.ts" --include="*.tsx"`,
58
+ { encoding: "utf8", cwd: ROOT }
59
+ ).trim().split("\n").filter(Boolean);
60
+ const exempt = ["close-task.ts", "tasks-review.ts", "tasks.ts", "cloud-sync.ts", "task-scope.ts", "database.ts"];
61
+ const unscoped = [];
62
+ for (const f of taskFiles) {
63
+ const basename = path.basename(f);
64
+ if (exempt.some((e) => basename === e)) continue;
65
+ const content = readFileSync(path.join(ROOT, f), "utf8");
66
+ if (!content.includes("task-scope") && !content.includes("sessionScopeFilter") && !content.includes("intentionally unscoped")) {
67
+ unscoped.push(f);
68
+ }
69
+ }
70
+ if (unscoped.length > 0) return `${unscoped.length} files missing scope: ${unscoped.slice(0, 3).join(", ")}`;
71
+ return true;
72
+ });
73
+ test("Platform procedures \u2014 shipped as code (not DB only)", () => {
74
+ const procs = readSrc("src/lib/platform-procedures.ts");
75
+ const count = (procs.match(/title:/g) || []).length;
76
+ if (count < 13) return `Only ${count} procedures (expected 13+)`;
77
+ if (!procs.includes("PLATFORM_PROCEDURE_TITLES")) return "Missing dedup set";
78
+ return true;
79
+ });
80
+ test("Platform procedures \u2014 customer procedures stay in DB", () => {
81
+ const global = readSrc("src/lib/global-procedures.ts");
82
+ if (!global.includes("PLATFORM_PROCEDURE_TITLES")) return "Not filtering platform titles from DB";
83
+ if (!global.includes("_platformCache")) return "No platform cache";
84
+ if (!global.includes("_customerCache")) return "No customer cache separation";
85
+ return true;
86
+ });
87
+ test("Backfill exclusive lock \u2014 only 1 backfill at a time", () => {
88
+ const gate = readSrc("src/lib/worker-gate.ts");
89
+ if (!gate.includes("tryAcquireBackfillLock")) return "Missing backfill lock";
90
+ if (!gate.includes("backfill.lock")) return "Missing lockfile path";
91
+ const bf = readSrc("src/bin/backfill-vectors.ts");
92
+ if (!bf.includes("tryAcquireBackfillLock")) return "backfill-vectors.ts not using lock";
93
+ return true;
94
+ });
95
+ test("Daemon restart \u2014 uses SIGKILL + kills orphans", () => {
96
+ const install = readSrc("src/bin/install.ts");
97
+ if (!install.includes("SIGKILL")) return "Still using SIGTERM";
98
+ if (!install.includes("pgrep")) return "No orphan kill via pgrep";
99
+ return true;
100
+ });
101
+ test("License self-heal \u2014 update mirrors cloud.apiKey to license.key", () => {
102
+ const update = readSrc("src/bin/update.ts");
103
+ if (!update.includes("mirrorLicenseKey")) return "update.ts missing license self-heal";
104
+ return true;
105
+ });
106
+ test("Golden path \u2014 orchestration model documented", () => {
107
+ if (!existsSync(path.join(ROOT, ".planning/ARCHITECTURE.md"))) return "ARCHITECTURE.md missing";
108
+ const arch = readFileSync(path.join(ROOT, ".planning/ARCHITECTURE.md"), "utf8");
109
+ if (!arch.includes("Orchestration Model")) return "Golden path section missing";
110
+ if (!arch.includes("create_task") || !arch.includes("Dispatch")) return "Dispatch rule missing";
111
+ return true;
112
+ });
113
+ test("No hardcoded 'yoshi'/'mari' in runtime task routing", () => {
114
+ const router = readSrc("src/lib/task-router.ts");
115
+ if (router.includes('"yoshi"') || router.includes("'yoshi'")) return "Hardcoded 'yoshi' in task-router.ts";
116
+ if (router.includes('"mari"') || router.includes("'mari'")) return "Hardcoded 'mari' in task-router.ts";
117
+ return true;
118
+ });
119
+ console.log(`
120
+ \x1B[1m${pass + fail} tests: ${pass} passed, ${fail} failed\x1B[0m
121
+ `);
122
+ if (fail > 0) {
123
+ console.log("\x1B[31mCustomer readiness gate FAILED \u2014 do not publish.\x1B[0m\n");
124
+ process.exit(1);
125
+ } else {
126
+ console.log("\x1B[32mCustomer readiness gate PASSED \u2014 safe to publish.\x1B[0m\n");
127
+ }
@@ -3501,13 +3501,20 @@ async function cleanupOrphanedReviews() {
3501
3501
  const client = getClient();
3502
3502
  const now = (/* @__PURE__ */ new Date()).toISOString();
3503
3503
  const r1 = await client.execute({
3504
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
3505
- WHERE status = 'needs_review'
3504
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
3505
+ WHERE status IN ('open', 'needs_review', 'in_progress')
3506
3506
  AND assigned_by = 'system'
3507
3507
  AND title LIKE 'Review:%'
3508
3508
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
3509
3509
  args: [now]
3510
3510
  });
3511
+ const r1b = await client.execute({
3512
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
3513
+ WHERE status IN ('open', 'needs_review')
3514
+ AND title LIKE 'Review:%completed%'
3515
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
3516
+ args: [now]
3517
+ });
3511
3518
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
3512
3519
  const r2 = await client.execute({
3513
3520
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -3516,10 +3523,10 @@ async function cleanupOrphanedReviews() {
3516
3523
  AND updated_at < ?`,
3517
3524
  args: [now, staleThreshold]
3518
3525
  });
3519
- const total = r1.rowsAffected + r2.rowsAffected;
3526
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
3520
3527
  if (total > 0) {
3521
3528
  process.stderr.write(
3522
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
3529
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
3523
3530
  `
3524
3531
  );
3525
3532
  }
@@ -5666,13 +5666,20 @@ async function cleanupOrphanedReviews() {
5666
5666
  const client = getClient();
5667
5667
  const now = (/* @__PURE__ */ new Date()).toISOString();
5668
5668
  const r1 = await client.execute({
5669
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
5670
- WHERE status = 'needs_review'
5669
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
5670
+ WHERE status IN ('open', 'needs_review', 'in_progress')
5671
5671
  AND assigned_by = 'system'
5672
5672
  AND title LIKE 'Review:%'
5673
5673
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
5674
5674
  args: [now]
5675
5675
  });
5676
+ const r1b = await client.execute({
5677
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
5678
+ WHERE status IN ('open', 'needs_review')
5679
+ AND title LIKE 'Review:%completed%'
5680
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
5681
+ args: [now]
5682
+ });
5676
5683
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
5677
5684
  const r2 = await client.execute({
5678
5685
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -5681,10 +5688,10 @@ async function cleanupOrphanedReviews() {
5681
5688
  AND updated_at < ?`,
5682
5689
  args: [now, staleThreshold]
5683
5690
  });
5684
- const total = r1.rowsAffected + r2.rowsAffected;
5691
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
5685
5692
  if (total > 0) {
5686
5693
  process.stderr.write(
5687
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
5694
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
5688
5695
  `
5689
5696
  );
5690
5697
  }
@@ -1787,13 +1787,20 @@ async function cleanupOrphanedReviews() {
1787
1787
  const client = getClient();
1788
1788
  const now = (/* @__PURE__ */ new Date()).toISOString();
1789
1789
  const r1 = await client.execute({
1790
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
1791
- WHERE status = 'needs_review'
1790
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
1791
+ WHERE status IN ('open', 'needs_review', 'in_progress')
1792
1792
  AND assigned_by = 'system'
1793
1793
  AND title LIKE 'Review:%'
1794
1794
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
1795
1795
  args: [now]
1796
1796
  });
1797
+ const r1b = await client.execute({
1798
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
1799
+ WHERE status IN ('open', 'needs_review')
1800
+ AND title LIKE 'Review:%completed%'
1801
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
1802
+ args: [now]
1803
+ });
1797
1804
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
1798
1805
  const r2 = await client.execute({
1799
1806
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -1802,10 +1809,10 @@ async function cleanupOrphanedReviews() {
1802
1809
  AND updated_at < ?`,
1803
1810
  args: [now, staleThreshold]
1804
1811
  });
1805
- const total = r1.rowsAffected + r2.rowsAffected;
1812
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
1806
1813
  if (total > 0) {
1807
1814
  process.stderr.write(
1808
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
1815
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
1809
1816
  `
1810
1817
  );
1811
1818
  }
@@ -2675,13 +2675,20 @@ async function cleanupOrphanedReviews() {
2675
2675
  const client = getClient();
2676
2676
  const now = (/* @__PURE__ */ new Date()).toISOString();
2677
2677
  const r1 = await client.execute({
2678
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2679
- WHERE status = 'needs_review'
2678
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2679
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2680
2680
  AND assigned_by = 'system'
2681
2681
  AND title LIKE 'Review:%'
2682
2682
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2683
2683
  args: [now]
2684
2684
  });
2685
+ const r1b = await client.execute({
2686
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2687
+ WHERE status IN ('open', 'needs_review')
2688
+ AND title LIKE 'Review:%completed%'
2689
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2690
+ args: [now]
2691
+ });
2685
2692
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2686
2693
  const r2 = await client.execute({
2687
2694
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2690,10 +2697,10 @@ async function cleanupOrphanedReviews() {
2690
2697
  AND updated_at < ?`,
2691
2698
  args: [now, staleThreshold]
2692
2699
  });
2693
- const total = r1.rowsAffected + r2.rowsAffected;
2700
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2694
2701
  if (total > 0) {
2695
2702
  process.stderr.write(
2696
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2703
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2697
2704
  `
2698
2705
  );
2699
2706
  }
@@ -2201,13 +2201,20 @@ async function cleanupOrphanedReviews() {
2201
2201
  const client = getClient();
2202
2202
  const now = (/* @__PURE__ */ new Date()).toISOString();
2203
2203
  const r1 = await client.execute({
2204
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2205
- WHERE status = 'needs_review'
2204
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2205
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2206
2206
  AND assigned_by = 'system'
2207
2207
  AND title LIKE 'Review:%'
2208
2208
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2209
2209
  args: [now]
2210
2210
  });
2211
+ const r1b = await client.execute({
2212
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2213
+ WHERE status IN ('open', 'needs_review')
2214
+ AND title LIKE 'Review:%completed%'
2215
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2216
+ args: [now]
2217
+ });
2211
2218
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2212
2219
  const r2 = await client.execute({
2213
2220
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2216,10 +2223,10 @@ async function cleanupOrphanedReviews() {
2216
2223
  AND updated_at < ?`,
2217
2224
  args: [now, staleThreshold]
2218
2225
  });
2219
- const total = r1.rowsAffected + r2.rowsAffected;
2226
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2220
2227
  if (total > 0) {
2221
2228
  process.stderr.write(
2222
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2229
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2223
2230
  `
2224
2231
  );
2225
2232
  }
@@ -2186,13 +2186,20 @@ async function cleanupOrphanedReviews() {
2186
2186
  const client = getClient();
2187
2187
  const now = (/* @__PURE__ */ new Date()).toISOString();
2188
2188
  const r1 = await client.execute({
2189
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2190
- WHERE status = 'needs_review'
2189
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2190
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2191
2191
  AND assigned_by = 'system'
2192
2192
  AND title LIKE 'Review:%'
2193
2193
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2194
2194
  args: [now]
2195
2195
  });
2196
+ const r1b = await client.execute({
2197
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2198
+ WHERE status IN ('open', 'needs_review')
2199
+ AND title LIKE 'Review:%completed%'
2200
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2201
+ args: [now]
2202
+ });
2196
2203
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2197
2204
  const r2 = await client.execute({
2198
2205
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2201,10 +2208,10 @@ async function cleanupOrphanedReviews() {
2201
2208
  AND updated_at < ?`,
2202
2209
  args: [now, staleThreshold]
2203
2210
  });
2204
- const total = r1.rowsAffected + r2.rowsAffected;
2211
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2205
2212
  if (total > 0) {
2206
2213
  process.stderr.write(
2207
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2214
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2208
2215
  `
2209
2216
  );
2210
2217
  }
@@ -4084,13 +4084,20 @@ async function cleanupOrphanedReviews() {
4084
4084
  const client = getClient();
4085
4085
  const now = (/* @__PURE__ */ new Date()).toISOString();
4086
4086
  const r1 = await client.execute({
4087
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
4088
- WHERE status = 'needs_review'
4087
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
4088
+ WHERE status IN ('open', 'needs_review', 'in_progress')
4089
4089
  AND assigned_by = 'system'
4090
4090
  AND title LIKE 'Review:%'
4091
4091
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
4092
4092
  args: [now]
4093
4093
  });
4094
+ const r1b = await client.execute({
4095
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
4096
+ WHERE status IN ('open', 'needs_review')
4097
+ AND title LIKE 'Review:%completed%'
4098
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
4099
+ args: [now]
4100
+ });
4094
4101
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
4095
4102
  const r2 = await client.execute({
4096
4103
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -4099,10 +4106,10 @@ async function cleanupOrphanedReviews() {
4099
4106
  AND updated_at < ?`,
4100
4107
  args: [now, staleThreshold]
4101
4108
  });
4102
- const total = r1.rowsAffected + r2.rowsAffected;
4109
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
4103
4110
  if (total > 0) {
4104
4111
  process.stderr.write(
4105
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
4112
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
4106
4113
  `
4107
4114
  );
4108
4115
  }
@@ -3647,13 +3647,20 @@ async function cleanupOrphanedReviews() {
3647
3647
  const client = getClient();
3648
3648
  const now = (/* @__PURE__ */ new Date()).toISOString();
3649
3649
  const r1 = await client.execute({
3650
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
3651
- WHERE status = 'needs_review'
3650
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
3651
+ WHERE status IN ('open', 'needs_review', 'in_progress')
3652
3652
  AND assigned_by = 'system'
3653
3653
  AND title LIKE 'Review:%'
3654
3654
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
3655
3655
  args: [now]
3656
3656
  });
3657
+ const r1b = await client.execute({
3658
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
3659
+ WHERE status IN ('open', 'needs_review')
3660
+ AND title LIKE 'Review:%completed%'
3661
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
3662
+ args: [now]
3663
+ });
3657
3664
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
3658
3665
  const r2 = await client.execute({
3659
3666
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -3662,10 +3669,10 @@ async function cleanupOrphanedReviews() {
3662
3669
  AND updated_at < ?`,
3663
3670
  args: [now, staleThreshold]
3664
3671
  });
3665
- const total = r1.rowsAffected + r2.rowsAffected;
3672
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
3666
3673
  if (total > 0) {
3667
3674
  process.stderr.write(
3668
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
3675
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
3669
3676
  `
3670
3677
  );
3671
3678
  }
@@ -2200,13 +2200,20 @@ async function cleanupOrphanedReviews() {
2200
2200
  const client = getClient();
2201
2201
  const now = (/* @__PURE__ */ new Date()).toISOString();
2202
2202
  const r1 = await client.execute({
2203
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2204
- WHERE status = 'needs_review'
2203
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2204
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2205
2205
  AND assigned_by = 'system'
2206
2206
  AND title LIKE 'Review:%'
2207
2207
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2208
2208
  args: [now]
2209
2209
  });
2210
+ const r1b = await client.execute({
2211
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2212
+ WHERE status IN ('open', 'needs_review')
2213
+ AND title LIKE 'Review:%completed%'
2214
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2215
+ args: [now]
2216
+ });
2210
2217
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2211
2218
  const r2 = await client.execute({
2212
2219
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2215,10 +2222,10 @@ async function cleanupOrphanedReviews() {
2215
2222
  AND updated_at < ?`,
2216
2223
  args: [now, staleThreshold]
2217
2224
  });
2218
- const total = r1.rowsAffected + r2.rowsAffected;
2225
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2219
2226
  if (total > 0) {
2220
2227
  process.stderr.write(
2221
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2228
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2222
2229
  `
2223
2230
  );
2224
2231
  }
@@ -4286,13 +4286,20 @@ async function cleanupOrphanedReviews() {
4286
4286
  const client = getClient();
4287
4287
  const now = (/* @__PURE__ */ new Date()).toISOString();
4288
4288
  const r1 = await client.execute({
4289
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
4290
- WHERE status = 'needs_review'
4289
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
4290
+ WHERE status IN ('open', 'needs_review', 'in_progress')
4291
4291
  AND assigned_by = 'system'
4292
4292
  AND title LIKE 'Review:%'
4293
4293
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
4294
4294
  args: [now]
4295
4295
  });
4296
+ const r1b = await client.execute({
4297
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
4298
+ WHERE status IN ('open', 'needs_review')
4299
+ AND title LIKE 'Review:%completed%'
4300
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
4301
+ args: [now]
4302
+ });
4296
4303
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
4297
4304
  const r2 = await client.execute({
4298
4305
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -4301,10 +4308,10 @@ async function cleanupOrphanedReviews() {
4301
4308
  AND updated_at < ?`,
4302
4309
  args: [now, staleThreshold]
4303
4310
  });
4304
- const total = r1.rowsAffected + r2.rowsAffected;
4311
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
4305
4312
  if (total > 0) {
4306
4313
  process.stderr.write(
4307
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
4314
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
4308
4315
  `
4309
4316
  );
4310
4317
  }
@@ -2185,13 +2185,20 @@ async function cleanupOrphanedReviews() {
2185
2185
  const client = getClient();
2186
2186
  const now = (/* @__PURE__ */ new Date()).toISOString();
2187
2187
  const r1 = await client.execute({
2188
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2189
- WHERE status = 'needs_review'
2188
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2189
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2190
2190
  AND assigned_by = 'system'
2191
2191
  AND title LIKE 'Review:%'
2192
2192
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2193
2193
  args: [now]
2194
2194
  });
2195
+ const r1b = await client.execute({
2196
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2197
+ WHERE status IN ('open', 'needs_review')
2198
+ AND title LIKE 'Review:%completed%'
2199
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2200
+ args: [now]
2201
+ });
2195
2202
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2196
2203
  const r2 = await client.execute({
2197
2204
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2200,10 +2207,10 @@ async function cleanupOrphanedReviews() {
2200
2207
  AND updated_at < ?`,
2201
2208
  args: [now, staleThreshold]
2202
2209
  });
2203
- const total = r1.rowsAffected + r2.rowsAffected;
2210
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2204
2211
  if (total > 0) {
2205
2212
  process.stderr.write(
2206
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2213
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2207
2214
  `
2208
2215
  );
2209
2216
  }
@@ -4205,13 +4205,20 @@ async function cleanupOrphanedReviews() {
4205
4205
  const client = getClient();
4206
4206
  const now = (/* @__PURE__ */ new Date()).toISOString();
4207
4207
  const r1 = await client.execute({
4208
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
4209
- WHERE status = 'needs_review'
4208
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
4209
+ WHERE status IN ('open', 'needs_review', 'in_progress')
4210
4210
  AND assigned_by = 'system'
4211
4211
  AND title LIKE 'Review:%'
4212
4212
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
4213
4213
  args: [now]
4214
4214
  });
4215
+ const r1b = await client.execute({
4216
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
4217
+ WHERE status IN ('open', 'needs_review')
4218
+ AND title LIKE 'Review:%completed%'
4219
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
4220
+ args: [now]
4221
+ });
4215
4222
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
4216
4223
  const r2 = await client.execute({
4217
4224
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -4220,10 +4227,10 @@ async function cleanupOrphanedReviews() {
4220
4227
  AND updated_at < ?`,
4221
4228
  args: [now, staleThreshold]
4222
4229
  });
4223
- const total = r1.rowsAffected + r2.rowsAffected;
4230
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
4224
4231
  if (total > 0) {
4225
4232
  process.stderr.write(
4226
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
4233
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
4227
4234
  `
4228
4235
  );
4229
4236
  }
package/dist/index.js CHANGED
@@ -2315,13 +2315,20 @@ async function cleanupOrphanedReviews() {
2315
2315
  const client = getClient();
2316
2316
  const now = (/* @__PURE__ */ new Date()).toISOString();
2317
2317
  const r1 = await client.execute({
2318
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2319
- WHERE status = 'needs_review'
2318
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2319
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2320
2320
  AND assigned_by = 'system'
2321
2321
  AND title LIKE 'Review:%'
2322
2322
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2323
2323
  args: [now]
2324
2324
  });
2325
+ const r1b = await client.execute({
2326
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2327
+ WHERE status IN ('open', 'needs_review')
2328
+ AND title LIKE 'Review:%completed%'
2329
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2330
+ args: [now]
2331
+ });
2325
2332
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2326
2333
  const r2 = await client.execute({
2327
2334
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2330,10 +2337,10 @@ async function cleanupOrphanedReviews() {
2330
2337
  AND updated_at < ?`,
2331
2338
  args: [now, staleThreshold]
2332
2339
  });
2333
- const total = r1.rowsAffected + r2.rowsAffected;
2340
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2334
2341
  if (total > 0) {
2335
2342
  process.stderr.write(
2336
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2343
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2337
2344
  `
2338
2345
  );
2339
2346
  }
@@ -2475,13 +2475,20 @@ async function cleanupOrphanedReviews() {
2475
2475
  const client = getClient();
2476
2476
  const now = (/* @__PURE__ */ new Date()).toISOString();
2477
2477
  const r1 = await client.execute({
2478
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2479
- WHERE status = 'needs_review'
2478
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2479
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2480
2480
  AND assigned_by = 'system'
2481
2481
  AND title LIKE 'Review:%'
2482
2482
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2483
2483
  args: [now]
2484
2484
  });
2485
+ const r1b = await client.execute({
2486
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2487
+ WHERE status IN ('open', 'needs_review')
2488
+ AND title LIKE 'Review:%completed%'
2489
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2490
+ args: [now]
2491
+ });
2485
2492
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2486
2493
  const r2 = await client.execute({
2487
2494
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2490,10 +2497,10 @@ async function cleanupOrphanedReviews() {
2490
2497
  AND updated_at < ?`,
2491
2498
  args: [now, staleThreshold]
2492
2499
  });
2493
- const total = r1.rowsAffected + r2.rowsAffected;
2500
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2494
2501
  if (total > 0) {
2495
2502
  process.stderr.write(
2496
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2503
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2497
2504
  `
2498
2505
  );
2499
2506
  }
package/dist/lib/tasks.js CHANGED
@@ -2237,13 +2237,20 @@ async function cleanupOrphanedReviews() {
2237
2237
  const client = getClient();
2238
2238
  const now = (/* @__PURE__ */ new Date()).toISOString();
2239
2239
  const r1 = await client.execute({
2240
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2241
- WHERE status = 'needs_review'
2240
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2241
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2242
2242
  AND assigned_by = 'system'
2243
2243
  AND title LIKE 'Review:%'
2244
2244
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2245
2245
  args: [now]
2246
2246
  });
2247
+ const r1b = await client.execute({
2248
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2249
+ WHERE status IN ('open', 'needs_review')
2250
+ AND title LIKE 'Review:%completed%'
2251
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2252
+ args: [now]
2253
+ });
2247
2254
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2248
2255
  const r2 = await client.execute({
2249
2256
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2252,10 +2259,10 @@ async function cleanupOrphanedReviews() {
2252
2259
  AND updated_at < ?`,
2253
2260
  args: [now, staleThreshold]
2254
2261
  });
2255
- const total = r1.rowsAffected + r2.rowsAffected;
2262
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2256
2263
  if (total > 0) {
2257
2264
  process.stderr.write(
2258
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2265
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2259
2266
  `
2260
2267
  );
2261
2268
  }
@@ -1304,13 +1304,20 @@ async function cleanupOrphanedReviews() {
1304
1304
  const client = getClient();
1305
1305
  const now = (/* @__PURE__ */ new Date()).toISOString();
1306
1306
  const r1 = await client.execute({
1307
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
1308
- WHERE status = 'needs_review'
1307
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
1308
+ WHERE status IN ('open', 'needs_review', 'in_progress')
1309
1309
  AND assigned_by = 'system'
1310
1310
  AND title LIKE 'Review:%'
1311
1311
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
1312
1312
  args: [now]
1313
1313
  });
1314
+ const r1b = await client.execute({
1315
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
1316
+ WHERE status IN ('open', 'needs_review')
1317
+ AND title LIKE 'Review:%completed%'
1318
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
1319
+ args: [now]
1320
+ });
1314
1321
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
1315
1322
  const r2 = await client.execute({
1316
1323
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -1319,10 +1326,10 @@ async function cleanupOrphanedReviews() {
1319
1326
  AND updated_at < ?`,
1320
1327
  args: [now, staleThreshold]
1321
1328
  });
1322
- const total = r1.rowsAffected + r2.rowsAffected;
1329
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
1323
1330
  if (total > 0) {
1324
1331
  process.stderr.write(
1325
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
1332
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
1326
1333
  `
1327
1334
  );
1328
1335
  }
@@ -5684,13 +5684,20 @@ async function cleanupOrphanedReviews() {
5684
5684
  const client = getClient();
5685
5685
  const now = (/* @__PURE__ */ new Date()).toISOString();
5686
5686
  const r1 = await client.execute({
5687
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
5688
- WHERE status = 'needs_review'
5687
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
5688
+ WHERE status IN ('open', 'needs_review', 'in_progress')
5689
5689
  AND assigned_by = 'system'
5690
5690
  AND title LIKE 'Review:%'
5691
5691
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
5692
5692
  args: [now]
5693
5693
  });
5694
+ const r1b = await client.execute({
5695
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
5696
+ WHERE status IN ('open', 'needs_review')
5697
+ AND title LIKE 'Review:%completed%'
5698
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
5699
+ args: [now]
5700
+ });
5694
5701
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
5695
5702
  const r2 = await client.execute({
5696
5703
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -5699,10 +5706,10 @@ async function cleanupOrphanedReviews() {
5699
5706
  AND updated_at < ?`,
5700
5707
  args: [now, staleThreshold]
5701
5708
  });
5702
- const total = r1.rowsAffected + r2.rowsAffected;
5709
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
5703
5710
  if (total > 0) {
5704
5711
  process.stderr.write(
5705
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
5712
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
5706
5713
  `
5707
5714
  );
5708
5715
  }
@@ -2401,13 +2401,20 @@ async function cleanupOrphanedReviews() {
2401
2401
  const client = getClient();
2402
2402
  const now = (/* @__PURE__ */ new Date()).toISOString();
2403
2403
  const r1 = await client.execute({
2404
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2405
- WHERE status = 'needs_review'
2404
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2405
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2406
2406
  AND assigned_by = 'system'
2407
2407
  AND title LIKE 'Review:%'
2408
2408
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2409
2409
  args: [now]
2410
2410
  });
2411
+ const r1b = await client.execute({
2412
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2413
+ WHERE status IN ('open', 'needs_review')
2414
+ AND title LIKE 'Review:%completed%'
2415
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2416
+ args: [now]
2417
+ });
2411
2418
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2412
2419
  const r2 = await client.execute({
2413
2420
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2416,10 +2423,10 @@ async function cleanupOrphanedReviews() {
2416
2423
  AND updated_at < ?`,
2417
2424
  args: [now, staleThreshold]
2418
2425
  });
2419
- const total = r1.rowsAffected + r2.rowsAffected;
2426
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2420
2427
  if (total > 0) {
2421
2428
  process.stderr.write(
2422
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2429
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2423
2430
  `
2424
2431
  );
2425
2432
  }
@@ -2256,13 +2256,20 @@ async function cleanupOrphanedReviews() {
2256
2256
  const client = getClient();
2257
2257
  const now = (/* @__PURE__ */ new Date()).toISOString();
2258
2258
  const r1 = await client.execute({
2259
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2260
- WHERE status = 'needs_review'
2259
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2260
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2261
2261
  AND assigned_by = 'system'
2262
2262
  AND title LIKE 'Review:%'
2263
2263
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2264
2264
  args: [now]
2265
2265
  });
2266
+ const r1b = await client.execute({
2267
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2268
+ WHERE status IN ('open', 'needs_review')
2269
+ AND title LIKE 'Review:%completed%'
2270
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2271
+ args: [now]
2272
+ });
2266
2273
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2267
2274
  const r2 = await client.execute({
2268
2275
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2271,10 +2278,10 @@ async function cleanupOrphanedReviews() {
2271
2278
  AND updated_at < ?`,
2272
2279
  args: [now, staleThreshold]
2273
2280
  });
2274
- const total = r1.rowsAffected + r2.rowsAffected;
2281
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2275
2282
  if (total > 0) {
2276
2283
  process.stderr.write(
2277
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2284
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2278
2285
  `
2279
2286
  );
2280
2287
  }
package/dist/tui/App.js CHANGED
@@ -2735,13 +2735,20 @@ async function cleanupOrphanedReviews() {
2735
2735
  const client = getClient();
2736
2736
  const now = (/* @__PURE__ */ new Date()).toISOString();
2737
2737
  const r1 = await client.execute({
2738
- sql: `UPDATE tasks SET status = 'done', updated_at = ?
2739
- WHERE status = 'needs_review'
2738
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2739
+ WHERE status IN ('open', 'needs_review', 'in_progress')
2740
2740
  AND assigned_by = 'system'
2741
2741
  AND title LIKE 'Review:%'
2742
2742
  AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
2743
2743
  args: [now]
2744
2744
  });
2745
+ const r1b = await client.execute({
2746
+ sql: `UPDATE tasks SET status = 'cancelled', updated_at = ?
2747
+ WHERE status IN ('open', 'needs_review')
2748
+ AND title LIKE 'Review:%completed%'
2749
+ AND (parent_task_id IS NULL OR parent_task_id NOT IN (SELECT id FROM tasks WHERE status IN ('open', 'in_progress', 'needs_review', 'blocked')))`,
2750
+ args: [now]
2751
+ });
2745
2752
  const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
2746
2753
  const r2 = await client.execute({
2747
2754
  sql: `UPDATE tasks SET status = 'done', updated_at = ?
@@ -2750,10 +2757,10 @@ async function cleanupOrphanedReviews() {
2750
2757
  AND updated_at < ?`,
2751
2758
  args: [now, staleThreshold]
2752
2759
  });
2753
- const total = r1.rowsAffected + r2.rowsAffected;
2760
+ const total = r1.rowsAffected + (r1b?.rowsAffected ?? 0) + r2.rowsAffected;
2754
2761
  if (total > 0) {
2755
2762
  process.stderr.write(
2756
- `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
2763
+ `[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r1b?.rowsAffected ?? 0} orphan + ${r2.rowsAffected} stale
2757
2764
  `
2758
2765
  );
2759
2766
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.8.57",
3
+ "version": "0.8.58",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "CC-BY-NC-4.0",
6
6
  "type": "module",
@@ -68,7 +68,7 @@
68
68
  "build": "tsup",
69
69
  "deploy": "node dist/bin/pre-build-guard.js 2>/dev/null; tsup && npm install -g . && node dist/bin/install.js --global && echo '[exe-os] Deploy complete. MCP servers will auto-reconnect on next tool call.'",
70
70
  "postinstall": "node dist/bin/install.js --global 2>/dev/null || true",
71
- "prepublishOnly": "npm run typecheck && npm run build && npx vitest run --maxWorkers=4 --exclude 'tests/tui/**' --exclude 'tests/lib/tmux-routing.test.ts' --exclude 'tests/lib/intercom-routing.test.ts' --exclude 'tests/gateway/**' --exclude 'tests/installer/setup-wizard.test.ts' --exclude 'tests/mcp/ingest-document.test.ts' --exclude 'tests/lib/hybrid-search.test.ts' --exclude 'tests/lib/worker-gate.test.ts'",
71
+ "prepublishOnly": "npm run typecheck && npm run build && node dist/bin/customer-readiness.js && npx vitest run --maxWorkers=4 --exclude 'tests/tui/**' --exclude 'tests/lib/tmux-routing.test.ts' --exclude 'tests/lib/intercom-routing.test.ts' --exclude 'tests/gateway/**' --exclude 'tests/installer/setup-wizard.test.ts' --exclude 'tests/mcp/ingest-document.test.ts' --exclude 'tests/lib/hybrid-search.test.ts' --exclude 'tests/lib/worker-gate.test.ts'",
72
72
  "benchmark:longmemeval": "npx tsx tests/benchmarks/longmemeval.ts"
73
73
  },
74
74
  "dependencies": {