@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
@@ -1860,7 +1860,15 @@ function getClient() {
1860
1860
  if (!_resilientClient) {
1861
1861
  return _adapterClient;
1862
1862
  }
1863
- return _resilientClient;
1863
+ if (process.env.EXE_DB_READONLY === "1") {
1864
+ return _resilientClient;
1865
+ }
1866
+ process.stderr.write(
1867
+ "[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"
1868
+ );
1869
+ throw new Error(
1870
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1871
+ );
1864
1872
  }
1865
1873
  async function initDaemonClient() {
1866
1874
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4548,12 +4556,6 @@ var init_platform_procedures = __esm({
4548
4556
  priority: "p0",
4549
4557
  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."
4550
4558
  },
4551
- {
4552
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4553
- domain: "workflow",
4554
- priority: "p0",
4555
- 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."
4556
- },
4557
4559
  {
4558
4560
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4559
4561
  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",
@@ -1919,7 +1919,15 @@ function getClient() {
1919
1919
  if (!_resilientClient) {
1920
1920
  return _adapterClient;
1921
1921
  }
1922
- return _resilientClient;
1922
+ if (process.env.EXE_DB_READONLY === "1") {
1923
+ return _resilientClient;
1924
+ }
1925
+ process.stderr.write(
1926
+ "[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"
1927
+ );
1928
+ throw new Error(
1929
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1930
+ );
1923
1931
  }
1924
1932
  async function initDaemonClient() {
1925
1933
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4607,12 +4615,6 @@ var init_platform_procedures = __esm({
4607
4615
  priority: "p0",
4608
4616
  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."
4609
4617
  },
4610
- {
4611
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4612
- domain: "workflow",
4613
- priority: "p0",
4614
- 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."
4615
- },
4616
4618
  {
4617
4619
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4618
4620
  domain: "architecture",
@@ -470,7 +470,15 @@ function getClient() {
470
470
  if (!_resilientClient) {
471
471
  return _adapterClient;
472
472
  }
473
- return _resilientClient;
473
+ if (process.env.EXE_DB_READONLY === "1") {
474
+ return _resilientClient;
475
+ }
476
+ process.stderr.write(
477
+ "[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"
478
+ );
479
+ throw new Error(
480
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
481
+ );
474
482
  }
475
483
  var _debugDb, _resilientClient, _daemonClient, _adapterClient, DB_LOCK_PATH;
476
484
  var init_database = __esm({
@@ -2824,12 +2832,6 @@ var PLATFORM_PROCEDURES = [
2824
2832
  priority: "p0",
2825
2833
  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."
2826
2834
  },
2827
- {
2828
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
2829
- domain: "workflow",
2830
- priority: "p0",
2831
- 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."
2832
- },
2833
2835
  {
2834
2836
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
2835
2837
  domain: "architecture",
@@ -1831,7 +1831,15 @@ function getClient() {
1831
1831
  if (!_resilientClient) {
1832
1832
  return _adapterClient;
1833
1833
  }
1834
- return _resilientClient;
1834
+ if (process.env.EXE_DB_READONLY === "1") {
1835
+ return _resilientClient;
1836
+ }
1837
+ process.stderr.write(
1838
+ "[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"
1839
+ );
1840
+ throw new Error(
1841
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1842
+ );
1835
1843
  }
1836
1844
  async function initDaemonClient() {
1837
1845
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4990,12 +4998,6 @@ var init_platform_procedures = __esm({
4990
4998
  priority: "p0",
4991
4999
  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."
4992
5000
  },
4993
- {
4994
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4995
- domain: "workflow",
4996
- priority: "p0",
4997
- 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."
4998
- },
4999
5001
  {
5000
5002
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
5001
5003
  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;
@@ -5056,12 +5064,6 @@ var init_platform_procedures = __esm({
5056
5064
  priority: "p0",
5057
5065
  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."
5058
5066
  },
5059
- {
5060
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
5061
- domain: "workflow",
5062
- priority: "p0",
5063
- 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."
5064
- },
5065
5067
  {
5066
5068
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
5067
5069
  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;
@@ -5095,12 +5103,6 @@ var init_platform_procedures = __esm({
5095
5103
  priority: "p0",
5096
5104
  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."
5097
5105
  },
5098
- {
5099
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
5100
- domain: "workflow",
5101
- priority: "p0",
5102
- 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."
5103
- },
5104
5106
  {
5105
5107
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
5106
5108
  domain: "architecture",
@@ -1676,7 +1676,15 @@ function getClient() {
1676
1676
  if (!_resilientClient) {
1677
1677
  return _adapterClient;
1678
1678
  }
1679
- return _resilientClient;
1679
+ if (process.env.EXE_DB_READONLY === "1") {
1680
+ return _resilientClient;
1681
+ }
1682
+ process.stderr.write(
1683
+ "[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"
1684
+ );
1685
+ throw new Error(
1686
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1687
+ );
1680
1688
  }
1681
1689
  async function initDaemonClient() {
1682
1690
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3343,12 +3351,6 @@ var init_platform_procedures = __esm({
3343
3351
  priority: "p0",
3344
3352
  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."
3345
3353
  },
3346
- {
3347
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3348
- domain: "workflow",
3349
- priority: "p0",
3350
- 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."
3351
- },
3352
3354
  {
3353
3355
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3354
3356
  domain: "architecture",
@@ -1835,7 +1835,15 @@ function getClient() {
1835
1835
  if (!_resilientClient) {
1836
1836
  return _adapterClient;
1837
1837
  }
1838
- return _resilientClient;
1838
+ if (process.env.EXE_DB_READONLY === "1") {
1839
+ return _resilientClient;
1840
+ }
1841
+ process.stderr.write(
1842
+ "[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"
1843
+ );
1844
+ throw new Error(
1845
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1846
+ );
1839
1847
  }
1840
1848
  async function initDaemonClient() {
1841
1849
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4523,12 +4531,6 @@ var init_platform_procedures = __esm({
4523
4531
  priority: "p0",
4524
4532
  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."
4525
4533
  },
4526
- {
4527
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4528
- domain: "workflow",
4529
- priority: "p0",
4530
- 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."
4531
- },
4532
4534
  {
4533
4535
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4534
4536
  domain: "architecture",
@@ -1820,7 +1820,15 @@ function getClient() {
1820
1820
  if (!_resilientClient) {
1821
1821
  return _adapterClient;
1822
1822
  }
1823
- return _resilientClient;
1823
+ if (process.env.EXE_DB_READONLY === "1") {
1824
+ return _resilientClient;
1825
+ }
1826
+ process.stderr.write(
1827
+ "[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"
1828
+ );
1829
+ throw new Error(
1830
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1831
+ );
1824
1832
  }
1825
1833
  async function initDaemonClient() {
1826
1834
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4508,12 +4516,6 @@ var init_platform_procedures = __esm({
4508
4516
  priority: "p0",
4509
4517
  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."
4510
4518
  },
4511
- {
4512
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4513
- domain: "workflow",
4514
- priority: "p0",
4515
- 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."
4516
- },
4517
4519
  {
4518
4520
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4519
4521
  domain: "architecture",
@@ -7303,7 +7305,32 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
7303
7305
  sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
7304
7306
  sql += ` ORDER BY rank LIMIT ?`;
7305
7307
  args.push(limit);
7306
- const result = await client.execute({ sql, args });
7308
+ let result;
7309
+ try {
7310
+ result = await client.execute({ sql, args });
7311
+ } catch (ftsErr) {
7312
+ const msg = ftsErr instanceof Error ? ftsErr.message : String(ftsErr);
7313
+ if (msg.includes("fts5") || msg.includes("FTS") || msg.includes("database disk image is malformed")) {
7314
+ process.stderr.write(
7315
+ `[hybrid-search] FTS5 corruption detected during query: ${msg}
7316
+ [hybrid-search] Attempting auto-rebuild of memories_fts index...
7317
+ `
7318
+ );
7319
+ try {
7320
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
7321
+ process.stderr.write("[hybrid-search] FTS5 index rebuilt successfully \u2014 retrying query.\n");
7322
+ result = await client.execute({ sql, args });
7323
+ } catch (rebuildErr) {
7324
+ process.stderr.write(
7325
+ `[hybrid-search] FTS5 rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
7326
+ `
7327
+ );
7328
+ return [];
7329
+ }
7330
+ } else {
7331
+ throw ftsErr;
7332
+ }
7333
+ }
7307
7334
  return result.rows.map((row) => ({
7308
7335
  id: row.id,
7309
7336
  agent_id: row.agent_id,
@@ -1864,7 +1864,15 @@ function getClient() {
1864
1864
  if (!_resilientClient) {
1865
1865
  return _adapterClient;
1866
1866
  }
1867
- return _resilientClient;
1867
+ if (process.env.EXE_DB_READONLY === "1") {
1868
+ return _resilientClient;
1869
+ }
1870
+ process.stderr.write(
1871
+ "[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"
1872
+ );
1873
+ throw new Error(
1874
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1875
+ );
1868
1876
  }
1869
1877
  async function initDaemonClient() {
1870
1878
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4552,12 +4560,6 @@ var init_platform_procedures = __esm({
4552
4560
  priority: "p0",
4553
4561
  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."
4554
4562
  },
4555
- {
4556
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4557
- domain: "workflow",
4558
- priority: "p0",
4559
- 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."
4560
- },
4561
4563
  {
4562
4564
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4563
4565
  domain: "architecture",
@@ -1693,7 +1693,15 @@ function getClient() {
1693
1693
  if (!_resilientClient) {
1694
1694
  return _adapterClient;
1695
1695
  }
1696
- return _resilientClient;
1696
+ if (process.env.EXE_DB_READONLY === "1") {
1697
+ return _resilientClient;
1698
+ }
1699
+ process.stderr.write(
1700
+ "[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"
1701
+ );
1702
+ throw new Error(
1703
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1704
+ );
1697
1705
  }
1698
1706
  async function initDaemonClient() {
1699
1707
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3824,12 +3832,6 @@ var init_platform_procedures = __esm({
3824
3832
  priority: "p0",
3825
3833
  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."
3826
3834
  },
3827
- {
3828
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3829
- domain: "workflow",
3830
- priority: "p0",
3831
- 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."
3832
- },
3833
3835
  {
3834
3836
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3835
3837
  domain: "architecture",
@@ -1693,7 +1693,15 @@ function getClient() {
1693
1693
  if (!_resilientClient) {
1694
1694
  return _adapterClient;
1695
1695
  }
1696
- return _resilientClient;
1696
+ if (process.env.EXE_DB_READONLY === "1") {
1697
+ return _resilientClient;
1698
+ }
1699
+ process.stderr.write(
1700
+ "[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"
1701
+ );
1702
+ throw new Error(
1703
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1704
+ );
1697
1705
  }
1698
1706
  async function initDaemonClient() {
1699
1707
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -3824,12 +3832,6 @@ var init_platform_procedures = __esm({
3824
3832
  priority: "p0",
3825
3833
  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."
3826
3834
  },
3827
- {
3828
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
3829
- domain: "workflow",
3830
- priority: "p0",
3831
- 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."
3832
- },
3833
3835
  {
3834
3836
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
3835
3837
  domain: "architecture",
@@ -1843,7 +1843,15 @@ function getClient() {
1843
1843
  if (!_resilientClient) {
1844
1844
  return _adapterClient;
1845
1845
  }
1846
- return _resilientClient;
1846
+ if (process.env.EXE_DB_READONLY === "1") {
1847
+ return _resilientClient;
1848
+ }
1849
+ process.stderr.write(
1850
+ "[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"
1851
+ );
1852
+ throw new Error(
1853
+ "Daemon not running. Direct SQLite writes are blocked to prevent FTS5 corruption. Restart daemon or set EXE_DB_READONLY=1 for read-only access."
1854
+ );
1847
1855
  }
1848
1856
  async function initDaemonClient() {
1849
1857
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
@@ -4531,12 +4539,6 @@ var init_platform_procedures = __esm({
4531
4539
  priority: "p0",
4532
4540
  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."
4533
4541
  },
4534
- {
4535
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
4536
- domain: "workflow",
4537
- priority: "p0",
4538
- 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."
4539
- },
4540
4542
  {
4541
4543
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
4542
4544
  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",
@@ -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;
@@ -8279,12 +8287,6 @@ var init_platform_procedures = __esm({
8279
8287
  priority: "p0",
8280
8288
  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."
8281
8289
  },
8282
- {
8283
- title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
8284
- domain: "workflow",
8285
- priority: "p0",
8286
- 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."
8287
- },
8288
8290
  {
8289
8291
  title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
8290
8292
  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",
@@ -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",