@askexenow/exe-os 0.9.105 → 0.9.106

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +9 -7
  2. package/dist/bin/agentic-reflection-backfill.js +9 -7
  3. package/dist/bin/agentic-semantic-label.js +9 -7
  4. package/dist/bin/backfill-conversations.js +9 -7
  5. package/dist/bin/backfill-responses.js +9 -7
  6. package/dist/bin/backfill-vectors.js +9 -7
  7. package/dist/bin/bulk-sync-postgres.js +9 -7
  8. package/dist/bin/cleanup-stale-review-tasks.js +9 -7
  9. package/dist/bin/cli.js +9 -7
  10. package/dist/bin/exe-agent.js +0 -6
  11. package/dist/bin/exe-assign.js +9 -7
  12. package/dist/bin/exe-boot.js +9 -7
  13. package/dist/bin/exe-call.js +0 -6
  14. package/dist/bin/exe-cloud.js +9 -7
  15. package/dist/bin/exe-dispatch.js +9 -7
  16. package/dist/bin/exe-doctor.js +9 -7
  17. package/dist/bin/exe-export-behaviors.js +9 -7
  18. package/dist/bin/exe-forget.js +35 -8
  19. package/dist/bin/exe-gateway.js +9 -7
  20. package/dist/bin/exe-heartbeat.js +9 -7
  21. package/dist/bin/exe-kill.js +9 -7
  22. package/dist/bin/exe-launch-agent.js +9 -7
  23. package/dist/bin/exe-new-employee.js +9 -7
  24. package/dist/bin/exe-pending-messages.js +9 -7
  25. package/dist/bin/exe-pending-notifications.js +9 -7
  26. package/dist/bin/exe-pending-reviews.js +9 -7
  27. package/dist/bin/exe-rename.js +9 -7
  28. package/dist/bin/exe-review.js +9 -7
  29. package/dist/bin/exe-search.js +35 -8
  30. package/dist/bin/exe-session-cleanup.js +9 -7
  31. package/dist/bin/exe-start-codex.js +9 -7
  32. package/dist/bin/exe-start-opencode.js +9 -7
  33. package/dist/bin/exe-status.js +9 -7
  34. package/dist/bin/exe-team.js +9 -7
  35. package/dist/bin/git-sweep.js +9 -7
  36. package/dist/bin/graph-backfill.js +9 -7
  37. package/dist/bin/graph-export.js +9 -7
  38. package/dist/bin/intercom-check.js +9 -7
  39. package/dist/bin/pre-publish.js +0 -6
  40. package/dist/bin/scan-tasks.js +9 -7
  41. package/dist/bin/setup.js +9 -7
  42. package/dist/bin/shard-migrate.js +9 -7
  43. package/dist/gateway/index.js +9 -7
  44. package/dist/hooks/bug-report-worker.js +9 -7
  45. package/dist/hooks/codex-stop-task-finalizer.js +9 -7
  46. package/dist/hooks/commit-complete.js +9 -7
  47. package/dist/hooks/error-recall.js +35 -8
  48. package/dist/hooks/ingest.js +9 -7
  49. package/dist/hooks/instructions-loaded.js +9 -7
  50. package/dist/hooks/notification.js +9 -7
  51. package/dist/hooks/post-compact.js +9 -7
  52. package/dist/hooks/post-tool-combined.js +35 -8
  53. package/dist/hooks/pre-compact.js +9 -7
  54. package/dist/hooks/pre-tool-use.js +9 -7
  55. package/dist/hooks/prompt-submit.js +35 -8
  56. package/dist/hooks/session-end.js +9 -7
  57. package/dist/hooks/session-start.js +35 -8
  58. package/dist/hooks/stop.js +9 -7
  59. package/dist/hooks/subagent-stop.js +9 -7
  60. package/dist/hooks/summary-worker.js +9 -7
  61. package/dist/index.js +9 -7
  62. package/dist/lib/cloud-sync.js +9 -1
  63. package/dist/lib/database.js +9 -1
  64. package/dist/lib/db.js +9 -1
  65. package/dist/lib/device-registry.js +9 -1
  66. package/dist/lib/employee-templates.js +0 -6
  67. package/dist/lib/exe-daemon.js +35 -8
  68. package/dist/lib/hybrid-search.js +35 -8
  69. package/dist/lib/identity.js +9 -1
  70. package/dist/lib/messaging.js +9 -1
  71. package/dist/lib/reminders.js +9 -1
  72. package/dist/lib/schedules.js +9 -7
  73. package/dist/lib/skill-learning.js +9 -1
  74. package/dist/lib/store.js +9 -7
  75. package/dist/lib/tasks.js +9 -1
  76. package/dist/lib/tmux-routing.js +9 -1
  77. package/dist/lib/token-spend.js +9 -1
  78. package/dist/mcp/server.js +35 -8
  79. package/dist/mcp/tools/complete-reminder.js +9 -1
  80. package/dist/mcp/tools/create-reminder.js +9 -1
  81. package/dist/mcp/tools/create-task.js +9 -1
  82. package/dist/mcp/tools/deactivate-behavior.js +9 -1
  83. package/dist/mcp/tools/list-reminders.js +9 -1
  84. package/dist/mcp/tools/list-tasks.js +9 -1
  85. package/dist/mcp/tools/send-message.js +9 -1
  86. package/dist/mcp/tools/update-task.js +9 -1
  87. package/dist/runtime/index.js +9 -7
  88. package/dist/tui/App.js +9 -7
  89. package/package.json +1 -1
@@ -1606,7 +1606,15 @@ function getClient() {
1606
1606
  if (!_resilientClient) {
1607
1607
  return _adapterClient;
1608
1608
  }
1609
- return _resilientClient;
1609
+ if (process.env.EXE_DB_READONLY === "1") {
1610
+ return _resilientClient;
1611
+ }
1612
+ process.stderr.write(
1613
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1614
+ );
1615
+ throw new Error(
1616
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1617
+ );
1610
1618
  }
1611
1619
  async function initDaemonClient() {
1612
1620
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3737,12 +3745,6 @@ var init_platform_procedures = __esm({
3737
3745
  priority: "p0",
3738
3746
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3739
3747
  },
3740
- {
3741
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3742
- domain: "workflow",
3743
- priority: "p0",
3744
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3745
- },
3746
3748
  {
3747
3749
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3748
3750
  domain: "architecture",
@@ -1606,7 +1606,15 @@ function getClient() {
1606
1606
  if (!_resilientClient) {
1607
1607
  return _adapterClient;
1608
1608
  }
1609
- return _resilientClient;
1609
+ if (process.env.EXE_DB_READONLY === "1") {
1610
+ return _resilientClient;
1611
+ }
1612
+ process.stderr.write(
1613
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1614
+ );
1615
+ throw new Error(
1616
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1617
+ );
1610
1618
  }
1611
1619
  async function initDaemonClient() {
1612
1620
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3737,12 +3745,6 @@ var init_platform_procedures = __esm({
3737
3745
  priority: "p0",
3738
3746
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3739
3747
  },
3740
- {
3741
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3742
- domain: "workflow",
3743
- priority: "p0",
3744
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3745
- },
3746
3748
  {
3747
3749
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3748
3750
  domain: "architecture",
@@ -1606,7 +1606,15 @@ function getClient() {
1606
1606
  if (!_resilientClient) {
1607
1607
  return _adapterClient;
1608
1608
  }
1609
- return _resilientClient;
1609
+ if (process.env.EXE_DB_READONLY === "1") {
1610
+ return _resilientClient;
1611
+ }
1612
+ process.stderr.write(
1613
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1614
+ );
1615
+ throw new Error(
1616
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1617
+ );
1610
1618
  }
1611
1619
  async function initDaemonClient() {
1612
1620
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3737,12 +3745,6 @@ var init_platform_procedures = __esm({
3737
3745
  priority: "p0",
3738
3746
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3739
3747
  },
3740
- {
3741
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3742
- domain: "workflow",
3743
- priority: "p0",
3744
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3745
- },
3746
3748
  {
3747
3749
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3748
3750
  domain: "architecture",
@@ -1746,7 +1746,15 @@ function getClient() {
1746
1746
  if (!_resilientClient) {
1747
1747
  return _adapterClient;
1748
1748
  }
1749
- return _resilientClient;
1749
+ if (process.env.EXE_DB_READONLY === "1") {
1750
+ return _resilientClient;
1751
+ }
1752
+ process.stderr.write(
1753
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1754
+ );
1755
+ throw new Error(
1756
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1757
+ );
1750
1758
  }
1751
1759
  async function initDaemonClient() {
1752
1760
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3877,12 +3885,6 @@ var init_platform_procedures = __esm({
3877
3885
  priority: "p0",
3878
3886
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3879
3887
  },
3880
- {
3881
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3882
- domain: "workflow",
3883
- priority: "p0",
3884
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3885
- },
3886
3888
  {
3887
3889
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3888
3890
  domain: "architecture",
@@ -1746,7 +1746,15 @@ function getClient() {
1746
1746
  if (!_resilientClient) {
1747
1747
  return _adapterClient;
1748
1748
  }
1749
- return _resilientClient;
1749
+ if (process.env.EXE_DB_READONLY === "1") {
1750
+ return _resilientClient;
1751
+ }
1752
+ process.stderr.write(
1753
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1754
+ );
1755
+ throw new Error(
1756
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1757
+ );
1750
1758
  }
1751
1759
  async function initDaemonClient() {
1752
1760
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3877,12 +3885,6 @@ var init_platform_procedures = __esm({
3877
3885
  priority: "p0",
3878
3886
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3879
3887
  },
3880
- {
3881
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3882
- domain: "workflow",
3883
- priority: "p0",
3884
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3885
- },
3886
3888
  {
3887
3889
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3888
3890
  domain: "architecture",
@@ -1742,7 +1742,15 @@ function getClient() {
1742
1742
  if (!_resilientClient) {
1743
1743
  return _adapterClient;
1744
1744
  }
1745
- return _resilientClient;
1745
+ if (process.env.EXE_DB_READONLY === "1") {
1746
+ return _resilientClient;
1747
+ }
1748
+ process.stderr.write(
1749
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1750
+ );
1751
+ throw new Error(
1752
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1753
+ );
1746
1754
  }
1747
1755
  async function initDaemonClient() {
1748
1756
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3873,12 +3881,6 @@ var init_platform_procedures = __esm({
3873
3881
  priority: "p0",
3874
3882
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3875
3883
  },
3876
- {
3877
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3878
- domain: "workflow",
3879
- priority: "p0",
3880
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3881
- },
3882
3884
  {
3883
3885
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3884
3886
  domain: "architecture",
@@ -1606,7 +1606,15 @@ function getClient() {
1606
1606
  if (!_resilientClient) {
1607
1607
  return _adapterClient;
1608
1608
  }
1609
- return _resilientClient;
1609
+ if (process.env.EXE_DB_READONLY === "1") {
1610
+ return _resilientClient;
1611
+ }
1612
+ process.stderr.write(
1613
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1614
+ );
1615
+ throw new Error(
1616
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1617
+ );
1610
1618
  }
1611
1619
  async function initDaemonClient() {
1612
1620
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4045,12 +4053,6 @@ var init_platform_procedures = __esm({
4045
4053
  priority: "p0",
4046
4054
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
4047
4055
  },
4048
- {
4049
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4050
- domain: "workflow",
4051
- priority: "p0",
4052
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
4053
- },
4054
4056
  {
4055
4057
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4056
4058
  domain: "architecture",
@@ -1832,7 +1832,15 @@ function getClient() {
1832
1832
  if (!_resilientClient) {
1833
1833
  return _adapterClient;
1834
1834
  }
1835
- return _resilientClient;
1835
+ if (process.env.EXE_DB_READONLY === "1") {
1836
+ return _resilientClient;
1837
+ }
1838
+ process.stderr.write(
1839
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1840
+ );
1841
+ throw new Error(
1842
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1843
+ );
1836
1844
  }
1837
1845
  async function initDaemonClient() {
1838
1846
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4520,12 +4528,6 @@ var init_platform_procedures = __esm({
4520
4528
  priority: "p0",
4521
4529
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
4522
4530
  },
4523
- {
4524
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4525
- domain: "workflow",
4526
- priority: "p0",
4527
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
4528
- },
4529
4531
  {
4530
4532
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4531
4533
  domain: "architecture",
package/dist/bin/cli.js CHANGED
@@ -4487,7 +4487,15 @@ function getClient() {
4487
4487
  if (!_resilientClient) {
4488
4488
  return _adapterClient;
4489
4489
  }
4490
- return _resilientClient;
4490
+ if (process.env.EXE_DB_READONLY === "1") {
4491
+ return _resilientClient;
4492
+ }
4493
+ process.stderr.write(
4494
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
4495
+ );
4496
+ throw new Error(
4497
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
4498
+ );
4491
4499
  }
4492
4500
  async function initDaemonClient() {
4493
4501
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -9226,12 +9234,6 @@ var init_platform_procedures = __esm({
9226
9234
  priority: "p0",
9227
9235
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
9228
9236
  },
9229
- {
9230
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
9231
- domain: "workflow",
9232
- priority: "p0",
9233
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
9234
- },
9235
9237
  {
9236
9238
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
9237
9239
  domain: "architecture",
@@ -1511,12 +1511,6 @@ var PLATFORM_PROCEDURES = [
1511
1511
  priority: "p0",
1512
1512
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
1513
1513
  },
1514
- {
1515
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
1516
- domain: "workflow",
1517
- priority: "p0",
1518
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
1519
- },
1520
1514
  {
1521
1515
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
1522
1516
  domain: "architecture",
@@ -1756,7 +1756,15 @@ function getClient() {
1756
1756
  if (!_resilientClient) {
1757
1757
  return _adapterClient;
1758
1758
  }
1759
- return _resilientClient;
1759
+ if (process.env.EXE_DB_READONLY === "1") {
1760
+ return _resilientClient;
1761
+ }
1762
+ process.stderr.write(
1763
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1764
+ );
1765
+ throw new Error(
1766
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1767
+ );
1760
1768
  }
1761
1769
  async function initDaemonClient() {
1762
1770
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3887,12 +3895,6 @@ var init_platform_procedures = __esm({
3887
3895
  priority: "p0",
3888
3896
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3889
3897
  },
3890
- {
3891
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3892
- domain: "workflow",
3893
- priority: "p0",
3894
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3895
- },
3896
3898
  {
3897
3899
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3898
3900
  domain: "architecture",
@@ -1908,7 +1908,15 @@ function getClient() {
1908
1908
  if (!_resilientClient) {
1909
1909
  return _adapterClient;
1910
1910
  }
1911
- return _resilientClient;
1911
+ if (process.env.EXE_DB_READONLY === "1") {
1912
+ return _resilientClient;
1913
+ }
1914
+ process.stderr.write(
1915
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1916
+ );
1917
+ throw new Error(
1918
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1919
+ );
1912
1920
  }
1913
1921
  async function initDaemonClient() {
1914
1922
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3575,12 +3583,6 @@ var init_platform_procedures = __esm({
3575
3583
  priority: "p0",
3576
3584
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
3577
3585
  },
3578
- {
3579
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3580
- domain: "workflow",
3581
- priority: "p0",
3582
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
3583
- },
3584
3586
  {
3585
3587
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3586
3588
  domain: "architecture",
@@ -448,12 +448,6 @@ var init_platform_procedures = __esm({
448
448
  priority: "p0",
449
449
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
450
450
  },
451
- {
452
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
453
- domain: "workflow",
454
- priority: "p0",
455
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
456
- },
457
451
  {
458
452
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
459
453
  domain: "architecture",
@@ -2344,7 +2344,15 @@ function getClient() {
2344
2344
  if (!_resilientClient) {
2345
2345
  return _adapterClient;
2346
2346
  }
2347
- return _resilientClient;
2347
+ if (process.env.EXE_DB_READONLY === "1") {
2348
+ return _resilientClient;
2349
+ }
2350
+ process.stderr.write(
2351
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
2352
+ );
2353
+ throw new Error(
2354
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
2355
+ );
2348
2356
  }
2349
2357
  async function initDaemonClient() {
2350
2358
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -7035,12 +7043,6 @@ var init_platform_procedures = __esm({
7035
7043
  priority: "p0",
7036
7044
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
7037
7045
  },
7038
- {
7039
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
7040
- domain: "workflow",
7041
- priority: "p0",
7042
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
7043
- },
7044
7046
  {
7045
7047
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
7046
7048
  domain: "architecture",
@@ -2410,7 +2410,15 @@ function getClient() {
2410
2410
  if (!_resilientClient) {
2411
2411
  return _adapterClient;
2412
2412
  }
2413
- return _resilientClient;
2413
+ if (process.env.EXE_DB_READONLY === "1") {
2414
+ return _resilientClient;
2415
+ }
2416
+ process.stderr.write(
2417
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
2418
+ );
2419
+ throw new Error(
2420
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
2421
+ );
2414
2422
  }
2415
2423
  async function initDaemonClient() {
2416
2424
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -8329,12 +8337,6 @@ var init_platform_procedures = __esm({
8329
8337
  priority: "p0",
8330
8338
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
8331
8339
  },
8332
- {
8333
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
8334
- domain: "workflow",
8335
- priority: "p0",
8336
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
8337
- },
8338
8340
  {
8339
8341
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
8340
8342
  domain: "architecture",
@@ -2932,7 +2932,15 @@ function getClient() {
2932
2932
  if (!_resilientClient) {
2933
2933
  return _adapterClient;
2934
2934
  }
2935
- return _resilientClient;
2935
+ if (process.env.EXE_DB_READONLY === "1") {
2936
+ return _resilientClient;
2937
+ }
2938
+ process.stderr.write(
2939
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
2940
+ );
2941
+ throw new Error(
2942
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
2943
+ );
2936
2944
  }
2937
2945
  async function initDaemonClient() {
2938
2946
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4848,12 +4856,6 @@ var init_platform_procedures = __esm({
4848
4856
  priority: "p0",
4849
4857
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
4850
4858
  },
4851
- {
4852
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4853
- domain: "workflow",
4854
- priority: "p0",
4855
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
4856
- },
4857
4859
  {
4858
4860
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4859
4861
  domain: "architecture",
@@ -1897,7 +1897,15 @@ function getClient() {
1897
1897
  if (!_resilientClient) {
1898
1898
  return _adapterClient;
1899
1899
  }
1900
- return _resilientClient;
1900
+ if (process.env.EXE_DB_READONLY === "1") {
1901
+ return _resilientClient;
1902
+ }
1903
+ process.stderr.write(
1904
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1905
+ );
1906
+ throw new Error(
1907
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1908
+ );
1901
1909
  }
1902
1910
  async function initDaemonClient() {
1903
1911
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4585,12 +4593,6 @@ var init_platform_procedures = __esm({
4585
4593
  priority: "p0",
4586
4594
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
4587
4595
  },
4588
- {
4589
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4590
- domain: "workflow",
4591
- priority: "p0",
4592
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
4593
- },
4594
4596
  {
4595
4597
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4596
4598
  domain: "architecture",
@@ -1821,7 +1821,15 @@ function getClient() {
1821
1821
  if (!_resilientClient) {
1822
1822
  return _adapterClient;
1823
1823
  }
1824
- return _resilientClient;
1824
+ if (process.env.EXE_DB_READONLY === "1") {
1825
+ return _resilientClient;
1826
+ }
1827
+ process.stderr.write(
1828
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
1829
+ );
1830
+ throw new Error(
1831
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1832
+ );
1825
1833
  }
1826
1834
  async function initDaemonClient() {
1827
1835
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4509,12 +4517,6 @@ var init_platform_procedures = __esm({
4509
4517
  priority: "p0",
4510
4518
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
4511
4519
  },
4512
- {
4513
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4514
- domain: "workflow",
4515
- priority: "p0",
4516
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
4517
- },
4518
4520
  {
4519
4521
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4520
4522
  domain: "architecture",
@@ -5981,7 +5983,32 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
5981
5983
  sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
5982
5984
  sql += ` ORDER BY rank LIMIT ?`;
5983
5985
  args.push(limit);
5984
- const result = await client.execute({ sql, args });
5986
+ let result;
5987
+ try {
5988
+ result = await client.execute({ sql, args });
5989
+ } catch (ftsErr) {
5990
+ const msg = ftsErr instanceof Error ? ftsErr.message : String(ftsErr);
5991
+ if (msg.includes("fts5") || msg.includes("FTS") || msg.includes("database disk image is malformed")) {
5992
+ process.stderr.write(
5993
+ `[hybrid-search] FTS5 corruption detected during query: ${msg}
5994
+ [hybrid-search] Attempting auto-rebuild of memories_fts index...
5995
+ `
5996
+ );
5997
+ try {
5998
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
5999
+ process.stderr.write("[hybrid-search] FTS5 index rebuilt successfully \u2014 retrying query.\n");
6000
+ result = await client.execute({ sql, args });
6001
+ } catch (rebuildErr) {
6002
+ process.stderr.write(
6003
+ `[hybrid-search] FTS5 rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
6004
+ `
6005
+ );
6006
+ return [];
6007
+ }
6008
+ } else {
6009
+ throw ftsErr;
6010
+ }
6011
+ }
5985
6012
  return result.rows.map((row) => ({
5986
6013
  id: row.id,
5987
6014
  agent_id: row.agent_id,
@@ -2492,7 +2492,15 @@ function getClient() {
2492
2492
  if (!_resilientClient) {
2493
2493
  return _adapterClient;
2494
2494
  }
2495
- return _resilientClient;
2495
+ if (process.env.EXE_DB_READONLY === "1") {
2496
+ return _resilientClient;
2497
+ }
2498
+ process.stderr.write(
2499
+ "[database] ERROR: Daemon is not running \u2014 refusing direct SQLite write access.\n[database] Direct writes bypass the single-writer gate and corrupt FTS5 indexes.\n[database] Restart the daemon: kill $(cat ~/.exe-os/exed.pid) && exe-os update\n[database] Or set EXE_DB_READONLY=1 if you only need read access.\n"
2500
+ );
2501
+ throw new Error(
2502
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
2503
+ );
2496
2504
  }
2497
2505
  async function initDaemonClient() {
2498
2506
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -5193,12 +5201,6 @@ var init_platform_procedures = __esm({
5193
5201
  priority: "p0",
5194
5202
  content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
5195
5203
  },
5196
- {
5197
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
5198
- domain: "workflow",
5199
- priority: "p0",
5200
- content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
5201
- },
5202
5204
  {
5203
5205
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
5204
5206
  domain: "architecture",