@askexenow/exe-os 0.9.64 → 0.9.66

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 (105) hide show
  1. package/deploy/stack-manifests/v0.9.json +4 -4
  2. package/dist/bin/backfill-conversations.js +22 -0
  3. package/dist/bin/backfill-responses.js +22 -0
  4. package/dist/bin/backfill-vectors.js +22 -0
  5. package/dist/bin/cleanup-stale-review-tasks.js +22 -0
  6. package/dist/bin/cli.js +2280 -1199
  7. package/dist/bin/exe-agent-config.js +4 -0
  8. package/dist/bin/exe-agent.js +16 -0
  9. package/dist/bin/exe-assign.js +22 -0
  10. package/dist/bin/exe-boot.js +116 -7
  11. package/dist/bin/exe-call.js +16 -0
  12. package/dist/bin/exe-cloud.js +6671 -464
  13. package/dist/bin/exe-dispatch.js +24 -0
  14. package/dist/bin/exe-doctor.js +2845 -1223
  15. package/dist/bin/exe-export-behaviors.js +24 -0
  16. package/dist/bin/exe-forget.js +22 -0
  17. package/dist/bin/exe-gateway.js +24 -0
  18. package/dist/bin/exe-heartbeat.js +23 -0
  19. package/dist/bin/exe-kill.js +22 -0
  20. package/dist/bin/exe-launch-agent.js +24 -0
  21. package/dist/bin/exe-link.js +310 -178
  22. package/dist/bin/exe-new-employee.js +127 -1
  23. package/dist/bin/exe-pending-messages.js +22 -0
  24. package/dist/bin/exe-pending-notifications.js +22 -0
  25. package/dist/bin/exe-pending-reviews.js +22 -0
  26. package/dist/bin/exe-rename.js +22 -0
  27. package/dist/bin/exe-review.js +22 -0
  28. package/dist/bin/exe-search.js +24 -0
  29. package/dist/bin/exe-session-cleanup.js +24 -0
  30. package/dist/bin/exe-settings.js +10 -0
  31. package/dist/bin/exe-start-codex.js +135 -1
  32. package/dist/bin/exe-start-opencode.js +149 -1
  33. package/dist/bin/exe-status.js +22 -0
  34. package/dist/bin/exe-team.js +22 -0
  35. package/dist/bin/git-sweep.js +24 -0
  36. package/dist/bin/graph-backfill.js +22 -0
  37. package/dist/bin/graph-export.js +22 -0
  38. package/dist/bin/install.js +115 -1
  39. package/dist/bin/intercom-check.js +24 -0
  40. package/dist/bin/scan-tasks.js +24 -0
  41. package/dist/bin/setup.js +412 -157
  42. package/dist/bin/shard-migrate.js +22 -0
  43. package/dist/bin/update.js +4 -0
  44. package/dist/gateway/index.js +24 -0
  45. package/dist/hooks/bug-report-worker.js +135 -42
  46. package/dist/hooks/codex-stop-task-finalizer.js +24 -0
  47. package/dist/hooks/commit-complete.js +24 -0
  48. package/dist/hooks/error-recall.js +24 -0
  49. package/dist/hooks/exe-heartbeat-hook.js +4 -0
  50. package/dist/hooks/ingest-worker.js +4 -0
  51. package/dist/hooks/ingest.js +23 -0
  52. package/dist/hooks/instructions-loaded.js +22 -0
  53. package/dist/hooks/notification.js +22 -0
  54. package/dist/hooks/post-compact.js +22 -0
  55. package/dist/hooks/post-tool-combined.js +24 -0
  56. package/dist/hooks/pre-compact.js +260 -109
  57. package/dist/hooks/pre-tool-use.js +22 -0
  58. package/dist/hooks/prompt-submit.js +24 -0
  59. package/dist/hooks/session-end.js +161 -122
  60. package/dist/hooks/session-start.js +142 -0
  61. package/dist/hooks/stop.js +23 -0
  62. package/dist/hooks/subagent-stop.js +22 -0
  63. package/dist/hooks/summary-worker.js +195 -79
  64. package/dist/index.js +24 -0
  65. package/dist/lib/agent-config.js +4 -0
  66. package/dist/lib/cloud-sync.js +50 -6
  67. package/dist/lib/config.js +12 -0
  68. package/dist/lib/consolidation.js +4 -0
  69. package/dist/lib/database.js +4 -0
  70. package/dist/lib/db-daemon-client.js +4 -0
  71. package/dist/lib/db.js +4 -0
  72. package/dist/lib/device-registry.js +4 -0
  73. package/dist/lib/embedder.js +12 -0
  74. package/dist/lib/employee-templates.js +16 -0
  75. package/dist/lib/employees.js +4 -0
  76. package/dist/lib/exe-daemon-client.js +4 -0
  77. package/dist/lib/exe-daemon.js +1144 -480
  78. package/dist/lib/hybrid-search.js +24 -0
  79. package/dist/lib/identity.js +4 -0
  80. package/dist/lib/license.js +4 -0
  81. package/dist/lib/messaging.js +4 -0
  82. package/dist/lib/reminders.js +4 -0
  83. package/dist/lib/schedules.js +22 -0
  84. package/dist/lib/skill-learning.js +12 -0
  85. package/dist/lib/status-brief.js +39 -0
  86. package/dist/lib/store.js +22 -0
  87. package/dist/lib/task-router.js +4 -0
  88. package/dist/lib/tasks.js +12 -0
  89. package/dist/lib/tmux-routing.js +12 -0
  90. package/dist/lib/token-spend.js +4 -0
  91. package/dist/mcp/server.js +1045 -427
  92. package/dist/mcp/tools/complete-reminder.js +4 -0
  93. package/dist/mcp/tools/create-reminder.js +4 -0
  94. package/dist/mcp/tools/create-task.js +12 -0
  95. package/dist/mcp/tools/deactivate-behavior.js +4 -0
  96. package/dist/mcp/tools/list-reminders.js +4 -0
  97. package/dist/mcp/tools/list-tasks.js +4 -0
  98. package/dist/mcp/tools/send-message.js +4 -0
  99. package/dist/mcp/tools/update-task.js +12 -0
  100. package/dist/runtime/index.js +24 -0
  101. package/dist/tui/App.js +24 -0
  102. package/package.json +3 -2
  103. package/src/commands/exe/cloud.md +15 -8
  104. package/src/commands/exe/link.md +7 -6
  105. package/stack.release.json +2 -2
@@ -134,6 +134,11 @@ function normalizeAutoUpdate(raw) {
134
134
  const userAU = raw.autoUpdate ?? {};
135
135
  raw.autoUpdate = { ...defaultAU, ...userAU };
136
136
  }
137
+ function normalizeOrchestration(raw) {
138
+ const defaultOrg = DEFAULT_CONFIG.orchestration;
139
+ const userOrg = raw.orchestration ?? {};
140
+ raw.orchestration = { ...defaultOrg, ...userOrg };
141
+ }
137
142
  async function loadConfig() {
138
143
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
139
144
  await ensurePrivateDir(dir);
@@ -158,6 +163,7 @@ async function loadConfig() {
158
163
  normalizeScalingRoadmap(migratedCfg);
159
164
  normalizeSessionLifecycle(migratedCfg);
160
165
  normalizeAutoUpdate(migratedCfg);
166
+ normalizeOrchestration(migratedCfg);
161
167
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
162
168
  if (config.dbPath.startsWith("~")) {
163
169
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -181,6 +187,7 @@ function loadConfigSync() {
181
187
  normalizeScalingRoadmap(migratedCfg);
182
188
  normalizeSessionLifecycle(migratedCfg);
183
189
  normalizeAutoUpdate(migratedCfg);
190
+ normalizeOrchestration(migratedCfg);
184
191
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
185
192
  } catch {
186
193
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
@@ -252,6 +259,10 @@ var init_config = __esm({
252
259
  checkOnBoot: true,
253
260
  autoInstall: false,
254
261
  checkIntervalMs: 24 * 60 * 60 * 1e3
262
+ },
263
+ orchestration: {
264
+ phase: "phase_1_coo",
265
+ phaseSetBy: "default"
255
266
  }
256
267
  };
257
268
  CONFIG_MIGRATIONS = [
@@ -4304,6 +4315,12 @@ var init_platform_procedures = __esm({
4304
4315
  priority: "p0",
4305
4316
  content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4306
4317
  },
4318
+ {
4319
+ title: "Customer orchestration maturity \u2014 recommend, never trap",
4320
+ domain: "workflow",
4321
+ priority: "p1",
4322
+ content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
4323
+ },
4307
4324
  {
4308
4325
  title: "Single dispatch path \u2014 create_task only",
4309
4326
  domain: "workflow",
@@ -4362,6 +4379,12 @@ var init_platform_procedures = __esm({
4362
4379
  priority: "p0",
4363
4380
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4364
4381
  },
4382
+ {
4383
+ title: "Commit discipline \u2014 never leave verified work floating",
4384
+ domain: "workflow",
4385
+ priority: "p1",
4386
+ content: "After any code-change batch passes typecheck/tests/build, run git status, summarize changed files, and commit with a clear message before ending the session. If work must remain uncommitted for review/dogfood, explicitly say so, list the files, and state the blocker. Never imply work is complete while verified changes are still floating locally."
4387
+ },
4365
4388
  {
4366
4389
  title: "Desktop and TUI are the same product",
4367
4390
  domain: "architecture",
@@ -134,6 +134,11 @@ function normalizeAutoUpdate(raw) {
134
134
  const userAU = raw.autoUpdate ?? {};
135
135
  raw.autoUpdate = { ...defaultAU, ...userAU };
136
136
  }
137
+ function normalizeOrchestration(raw) {
138
+ const defaultOrg = DEFAULT_CONFIG.orchestration;
139
+ const userOrg = raw.orchestration ?? {};
140
+ raw.orchestration = { ...defaultOrg, ...userOrg };
141
+ }
137
142
  async function loadConfig() {
138
143
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
139
144
  await ensurePrivateDir(dir);
@@ -158,6 +163,7 @@ async function loadConfig() {
158
163
  normalizeScalingRoadmap(migratedCfg);
159
164
  normalizeSessionLifecycle(migratedCfg);
160
165
  normalizeAutoUpdate(migratedCfg);
166
+ normalizeOrchestration(migratedCfg);
161
167
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
162
168
  if (config.dbPath.startsWith("~")) {
163
169
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -233,6 +239,10 @@ var init_config = __esm({
233
239
  checkOnBoot: true,
234
240
  autoInstall: false,
235
241
  checkIntervalMs: 24 * 60 * 60 * 1e3
242
+ },
243
+ orchestration: {
244
+ phase: "phase_1_coo",
245
+ phaseSetBy: "default"
236
246
  }
237
247
  };
238
248
  CONFIG_MIGRATIONS = [
@@ -4285,6 +4295,12 @@ var init_platform_procedures = __esm({
4285
4295
  priority: "p0",
4286
4296
  content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4287
4297
  },
4298
+ {
4299
+ title: "Customer orchestration maturity \u2014 recommend, never trap",
4300
+ domain: "workflow",
4301
+ priority: "p1",
4302
+ content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
4303
+ },
4288
4304
  {
4289
4305
  title: "Single dispatch path \u2014 create_task only",
4290
4306
  domain: "workflow",
@@ -4343,6 +4359,12 @@ var init_platform_procedures = __esm({
4343
4359
  priority: "p0",
4344
4360
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4345
4361
  },
4362
+ {
4363
+ title: "Commit discipline \u2014 never leave verified work floating",
4364
+ domain: "workflow",
4365
+ priority: "p1",
4366
+ content: "After any code-change batch passes typecheck/tests/build, run git status, summarize changed files, and commit with a clear message before ending the session. If work must remain uncommitted for review/dogfood, explicitly say so, list the files, and state the blocker. Never imply work is complete while verified changes are still floating locally."
4367
+ },
4346
4368
  {
4347
4369
  title: "Desktop and TUI are the same product",
4348
4370
  domain: "architecture",
@@ -213,6 +213,11 @@ function normalizeAutoUpdate(raw) {
213
213
  const userAU = raw.autoUpdate ?? {};
214
214
  raw.autoUpdate = { ...defaultAU, ...userAU };
215
215
  }
216
+ function normalizeOrchestration(raw) {
217
+ const defaultOrg = DEFAULT_CONFIG.orchestration;
218
+ const userOrg = raw.orchestration ?? {};
219
+ raw.orchestration = { ...defaultOrg, ...userOrg };
220
+ }
216
221
  async function loadConfig() {
217
222
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
218
223
  await ensurePrivateDir(dir);
@@ -237,6 +242,7 @@ async function loadConfig() {
237
242
  normalizeScalingRoadmap(migratedCfg);
238
243
  normalizeSessionLifecycle(migratedCfg);
239
244
  normalizeAutoUpdate(migratedCfg);
245
+ normalizeOrchestration(migratedCfg);
240
246
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
241
247
  if (config.dbPath.startsWith("~")) {
242
248
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -260,6 +266,7 @@ function loadConfigSync() {
260
266
  normalizeScalingRoadmap(migratedCfg);
261
267
  normalizeSessionLifecycle(migratedCfg);
262
268
  normalizeAutoUpdate(migratedCfg);
269
+ normalizeOrchestration(migratedCfg);
263
270
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
264
271
  } catch {
265
272
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
@@ -281,6 +288,7 @@ async function loadConfigFrom(configPath) {
281
288
  normalizeScalingRoadmap(migratedCfg);
282
289
  normalizeSessionLifecycle(migratedCfg);
283
290
  normalizeAutoUpdate(migratedCfg);
291
+ normalizeOrchestration(migratedCfg);
284
292
  return { ...DEFAULT_CONFIG, ...migratedCfg };
285
293
  } catch {
286
294
  return { ...DEFAULT_CONFIG };
@@ -352,6 +360,10 @@ var init_config = __esm({
352
360
  checkOnBoot: true,
353
361
  autoInstall: false,
354
362
  checkIntervalMs: 24 * 60 * 60 * 1e3
363
+ },
364
+ orchestration: {
365
+ phase: "phase_1_coo",
366
+ phaseSetBy: "default"
355
367
  }
356
368
  };
357
369
  CONFIG_MIGRATIONS = [
@@ -3803,6 +3815,12 @@ var init_platform_procedures = __esm({
3803
3815
  priority: "p0",
3804
3816
  content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
3805
3817
  },
3818
+ {
3819
+ title: "Customer orchestration maturity \u2014 recommend, never trap",
3820
+ domain: "workflow",
3821
+ priority: "p1",
3822
+ content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
3823
+ },
3806
3824
  {
3807
3825
  title: "Single dispatch path \u2014 create_task only",
3808
3826
  domain: "workflow",
@@ -3861,6 +3879,12 @@ var init_platform_procedures = __esm({
3861
3879
  priority: "p0",
3862
3880
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
3863
3881
  },
3882
+ {
3883
+ title: "Commit discipline \u2014 never leave verified work floating",
3884
+ domain: "workflow",
3885
+ priority: "p1",
3886
+ content: "After any code-change batch passes typecheck/tests/build, run git status, summarize changed files, and commit with a clear message before ending the session. If work must remain uncommitted for review/dogfood, explicitly say so, list the files, and state the blocker. Never imply work is complete while verified changes are still floating locally."
3887
+ },
3864
3888
  {
3865
3889
  title: "Desktop and TUI are the same product",
3866
3890
  domain: "architecture",
@@ -5638,8 +5662,10 @@ var init_db_backup = __esm({
5638
5662
  // src/lib/cloud-sync.ts
5639
5663
  var cloud_sync_exports = {};
5640
5664
  __export(cloud_sync_exports, {
5665
+ CLOUD_RELINK_REQUIRED_MESSAGE: () => CLOUD_RELINK_REQUIRED_MESSAGE,
5641
5666
  assertSecureEndpoint: () => assertSecureEndpoint,
5642
5667
  buildRosterBlob: () => buildRosterBlob,
5668
+ clearCloudRelinkRequired: () => clearCloudRelinkRequired,
5643
5669
  cloudPull: () => cloudPull,
5644
5670
  cloudPullBehaviors: () => cloudPullBehaviors,
5645
5671
  cloudPullBlob: () => cloudPullBlob,
@@ -5659,6 +5685,7 @@ __export(cloud_sync_exports, {
5659
5685
  cloudPushRoster: () => cloudPushRoster,
5660
5686
  cloudPushTasks: () => cloudPushTasks,
5661
5687
  cloudSync: () => cloudSync,
5688
+ getCloudRelinkRequired: () => getCloudRelinkRequired,
5662
5689
  mergeConfig: () => mergeConfig,
5663
5690
  mergeRosterFromRemote: () => mergeRosterFromRemote,
5664
5691
  pushToPostgres: () => pushToPostgres,
@@ -5679,31 +5706,43 @@ function logError(msg) {
5679
5706
  } catch {
5680
5707
  }
5681
5708
  }
5709
+ function isTruthyEnv(value) {
5710
+ return /^(1|true|yes|on)$/i.test(value ?? "");
5711
+ }
5682
5712
  function loadPgClient() {
5683
5713
  if (_pgFailed) return null;
5684
- const postgresUrl = process.env.DATABASE_URL;
5685
5714
  const configPath = path20.join(EXE_AI_DIR, "config.json");
5686
5715
  let cloudPostgresUrl;
5716
+ let configEnabled = false;
5687
5717
  try {
5688
5718
  if (existsSync19(configPath)) {
5689
5719
  const cfg = JSON.parse(readFileSync13(configPath, "utf8"));
5690
5720
  cloudPostgresUrl = cfg.cloud?.postgresUrl;
5691
- if (cfg.cloud?.syncToPostgres === false) {
5692
- _pgFailed = true;
5693
- return null;
5694
- }
5721
+ configEnabled = cfg.cloud?.syncToPostgres === true;
5695
5722
  }
5696
5723
  } catch {
5697
5724
  }
5698
- const url = postgresUrl || cloudPostgresUrl;
5725
+ const envEnabled = isTruthyEnv(process.env.EXE_CLOUD_SYNC_TO_POSTGRES);
5726
+ if (!envEnabled && !configEnabled) {
5727
+ return null;
5728
+ }
5729
+ const url = process.env.DATABASE_URL || cloudPostgresUrl;
5699
5730
  if (!url) {
5700
5731
  _pgFailed = true;
5701
5732
  return null;
5702
5733
  }
5703
5734
  if (!_pgPromise) {
5704
5735
  _pgPromise = (async () => {
5736
+ if (!process.env.DATABASE_URL) process.env.DATABASE_URL = url;
5705
5737
  const { createRequire: createRequire3 } = await import("module");
5706
5738
  const { pathToFileURL: pathToFileURL3 } = await import("url");
5739
+ const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
5740
+ if (explicitPath) {
5741
+ const mod2 = await import(pathToFileURL3(explicitPath).href);
5742
+ const Ctor2 = mod2.PrismaClient ?? mod2.default?.PrismaClient;
5743
+ if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
5744
+ return new Ctor2();
5745
+ }
5707
5746
  const exeDbRoot = process.env.EXE_DB_ROOT ?? path20.join(homedir2(), "exe-db");
5708
5747
  const req = createRequire3(path20.join(exeDbRoot, "package.json"));
5709
5748
  const entry = req.resolve("@prisma/client");
@@ -5880,6 +5919,24 @@ async function cloudPull(sinceVersion, config) {
5880
5919
  return { records: [], maxVersion: sinceVersion };
5881
5920
  }
5882
5921
  }
5922
+ async function getCloudRelinkRequired(client = getClient()) {
5923
+ try {
5924
+ await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
5925
+ const relink = await client.execute("SELECT value FROM sync_meta WHERE key = 'cloud_relink_required' LIMIT 1");
5926
+ return String(relink.rows[0]?.value ?? "") === "1";
5927
+ } catch {
5928
+ return false;
5929
+ }
5930
+ }
5931
+ async function clearCloudRelinkRequired(client = getClient()) {
5932
+ await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
5933
+ await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relink_required', '0')");
5934
+ await client.execute({
5935
+ sql: "INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relinked_at', ?)",
5936
+ args: [(/* @__PURE__ */ new Date()).toISOString()]
5937
+ });
5938
+ await client.execute("DELETE FROM sync_meta WHERE key IN ('last_cloud_pull_version', 'last_cloud_push_version')");
5939
+ }
5883
5940
  async function cloudSync(config) {
5884
5941
  if (!isSyncCryptoInitialized()) {
5885
5942
  try {
@@ -5900,6 +5957,12 @@ async function cloudSync(config) {
5900
5957
  } catch {
5901
5958
  throw new Error("[cloud-sync] Database not initialized. Call initStore() before cloudSync().");
5902
5959
  }
5960
+ try {
5961
+ if (await getCloudRelinkRequired(client)) throw new Error(CLOUD_RELINK_REQUIRED_MESSAGE);
5962
+ } catch (err) {
5963
+ const msg = err instanceof Error ? err.message : String(err);
5964
+ if (msg.includes("Paused after key rotation")) throw err;
5965
+ }
5903
5966
  try {
5904
5967
  const { getRawClient: getRawClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
5905
5968
  await getRawClient2().execute("PRAGMA wal_checkpoint(PASSIVE)");
@@ -6827,7 +6890,7 @@ async function cloudPullDocuments(config) {
6827
6890
  }
6828
6891
  return { pulled };
6829
6892
  }
6830
- var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, ROSTER_DELETIONS_PATH;
6893
+ var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, CLOUD_RELINK_REQUIRED_MESSAGE, ROSTER_DELETIONS_PATH;
6831
6894
  var init_cloud_sync = __esm({
6832
6895
  "src/lib/cloud-sync.ts"() {
6833
6896
  "use strict";
@@ -6846,6 +6909,7 @@ var init_cloud_sync = __esm({
6846
6909
  LOCK_STALE_MS = 3e4;
6847
6910
  _pgPromise = null;
6848
6911
  _pgFailed = false;
6912
+ CLOUD_RELINK_REQUIRED_MESSAGE = "[cloud-sync] Paused after key rotation. Run `exe-os cloud relink --dry-run` for the safe relink checklist.";
6849
6913
  ROSTER_DELETIONS_PATH = path20.join(EXE_AI_DIR, "roster-deletions.json");
6850
6914
  }
6851
6915
  });
@@ -6952,46 +7016,6 @@ function vectorToBlob(vector) {
6952
7016
  // src/adapters/claude/hooks/summary-worker.ts
6953
7017
  init_database();
6954
7018
  init_notifications();
6955
-
6956
- // src/lib/memory-queue-client.ts
6957
- init_exe_daemon_client();
6958
-
6959
- // src/lib/memory-queue.ts
6960
- init_config();
6961
- import { appendFileSync as appendFileSync2, readFileSync as readFileSync11, renameSync as renameSync5, unlinkSync as unlinkSync4, existsSync as existsSync15, statSync as statSync3 } from "fs";
6962
- import path16 from "path";
6963
- var QUEUE_PATH2 = path16.join(EXE_AI_DIR, "memory-queue.jsonl");
6964
- var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
6965
- var TTL_MS2 = 24 * 60 * 60 * 1e3;
6966
- function enqueueMemory(entry) {
6967
- appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
6968
- }
6969
-
6970
- // src/lib/memory-queue-client.ts
6971
- async function writeMemoryViaDaemon(entry) {
6972
- if (process.env.EXE_IS_DAEMON === "1") {
6973
- enqueueMemory(entry);
6974
- return false;
6975
- }
6976
- if (!isClientConnected()) {
6977
- enqueueMemory(entry);
6978
- return false;
6979
- }
6980
- try {
6981
- const response = await sendDaemonRequest({
6982
- type: "write-memory",
6983
- entry
6984
- });
6985
- if (response.ok) return true;
6986
- enqueueMemory(entry);
6987
- return false;
6988
- } catch {
6989
- enqueueMemory(entry);
6990
- return false;
6991
- }
6992
- }
6993
-
6994
- // src/adapters/claude/hooks/summary-worker.ts
6995
7019
  init_task_scope();
6996
7020
  init_employees();
6997
7021
  import { execSync as execSync5 } from "child_process";
@@ -7078,6 +7102,119 @@ function buildAutoCheckpoint(input) {
7078
7102
  };
7079
7103
  }
7080
7104
 
7105
+ // src/lib/memory-queue-client.ts
7106
+ init_exe_daemon_client();
7107
+
7108
+ // src/lib/memory-queue.ts
7109
+ init_config();
7110
+ import { appendFileSync as appendFileSync2, readFileSync as readFileSync11, renameSync as renameSync5, unlinkSync as unlinkSync4, existsSync as existsSync15, statSync as statSync3 } from "fs";
7111
+ import path16 from "path";
7112
+ var QUEUE_PATH2 = path16.join(EXE_AI_DIR, "memory-queue.jsonl");
7113
+ var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
7114
+ var TTL_MS2 = 24 * 60 * 60 * 1e3;
7115
+ function enqueueMemory(entry) {
7116
+ appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
7117
+ }
7118
+
7119
+ // src/lib/memory-queue-client.ts
7120
+ async function writeMemoryViaDaemon(entry) {
7121
+ if (process.env.EXE_IS_DAEMON === "1") {
7122
+ enqueueMemory(entry);
7123
+ return false;
7124
+ }
7125
+ if (!isClientConnected()) {
7126
+ enqueueMemory(entry);
7127
+ return false;
7128
+ }
7129
+ try {
7130
+ const response = await sendDaemonRequest({
7131
+ type: "write-memory",
7132
+ entry
7133
+ });
7134
+ if (response.ok) return true;
7135
+ enqueueMemory(entry);
7136
+ return false;
7137
+ } catch {
7138
+ enqueueMemory(entry);
7139
+ return false;
7140
+ }
7141
+ }
7142
+
7143
+ // src/lib/checkpoint-orchestrator.ts
7144
+ function toolNameForReason(reason) {
7145
+ switch (reason) {
7146
+ case "periodic":
7147
+ return "auto-summary";
7148
+ case "session-end":
7149
+ return "SessionEnd";
7150
+ case "pre-compact":
7151
+ return "pre-compact-hook";
7152
+ case "capacity-signal":
7153
+ return "auto-checkpoint";
7154
+ }
7155
+ }
7156
+ function importanceForReason(reason, override) {
7157
+ if (override !== void 0) return override;
7158
+ switch (reason) {
7159
+ case "periodic":
7160
+ return 7;
7161
+ case "session-end":
7162
+ case "pre-compact":
7163
+ case "capacity-signal":
7164
+ return 8;
7165
+ }
7166
+ }
7167
+ function buildContinuityCheckpoint(input) {
7168
+ const { checkpointText, decisionTexts } = buildAutoCheckpoint({
7169
+ agentId: input.agentId,
7170
+ agentRole: input.agentRole,
7171
+ sessionId: input.sessionId,
7172
+ projectName: input.projectName,
7173
+ reason: input.reason,
7174
+ memories: input.memories ?? [],
7175
+ tasks: input.tasks ?? [],
7176
+ maxSamples: input.maxSamples
7177
+ });
7178
+ const extra = input.extraSections?.filter((section) => section.trim().length > 0) ?? [];
7179
+ return {
7180
+ checkpointText: extra.length > 0 ? `${checkpointText}
7181
+
7182
+ ${extra.join("\n\n")}` : checkpointText,
7183
+ decisionTexts
7184
+ };
7185
+ }
7186
+ async function writeContinuityCheckpoint(input) {
7187
+ const result = buildContinuityCheckpoint(input);
7188
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7189
+ await writeMemoryViaDaemon({
7190
+ raw_text: result.checkpointText,
7191
+ agent_id: input.agentId,
7192
+ agent_role: input.agentRole,
7193
+ session_id: input.sessionId,
7194
+ tool_name: toolNameForReason(input.reason),
7195
+ project_name: input.projectName,
7196
+ timestamp: now,
7197
+ importance: importanceForReason(input.reason, input.importance),
7198
+ task_id: input.taskId,
7199
+ memory_type: "checkpoint"
7200
+ });
7201
+ const decisionLimit = input.reason === "periodic" ? 3 : 5;
7202
+ for (const decisionText of result.decisionTexts.slice(0, decisionLimit)) {
7203
+ await writeMemoryViaDaemon({
7204
+ raw_text: decisionText,
7205
+ agent_id: input.agentId,
7206
+ agent_role: input.agentRole,
7207
+ session_id: input.sessionId,
7208
+ tool_name: "auto-decision",
7209
+ project_name: input.projectName,
7210
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7211
+ importance: 8,
7212
+ memory_type: "decision"
7213
+ });
7214
+ }
7215
+ return result;
7216
+ }
7217
+
7081
7218
  // src/adapters/claude/hooks/summary-worker.ts
7082
7219
  async function main() {
7083
7220
  const agentId = process.env.AGENT_ID ?? "default";
@@ -7136,15 +7273,8 @@ async function main() {
7136
7273
  taskRows = tasks.rows;
7137
7274
  } catch {
7138
7275
  }
7139
- const { checkpointText: summaryText, decisionTexts } = buildAutoCheckpoint({
7140
- agentId,
7141
- agentRole,
7142
- sessionId: `auto-summary-${Date.now()}`,
7143
- projectName: primaryProject,
7144
- reason: "periodic",
7145
- memories: result.rows,
7146
- tasks: taskRows
7147
- });
7276
+ const summarySessionId = `auto-summary-${Date.now()}`;
7277
+ let summaryText = "";
7148
7278
  let limitReached = false;
7149
7279
  try {
7150
7280
  const { assertMemoryLimit: assertMemoryLimit2 } = await Promise.resolve().then(() => (init_plan_limits(), plan_limits_exports));
@@ -7162,30 +7292,16 @@ async function main() {
7162
7292
  }
7163
7293
  if (limitReached) {
7164
7294
  } else {
7165
- await writeMemoryViaDaemon({
7166
- raw_text: summaryText,
7167
- agent_id: agentId,
7168
- agent_role: agentRole,
7169
- session_id: `auto-summary-${Date.now()}`,
7170
- tool_name: "auto-summary",
7171
- project_name: primaryProject,
7172
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7173
- importance: 7,
7174
- memory_type: "checkpoint"
7295
+ const checkpointResult = await writeContinuityCheckpoint({
7296
+ agentId,
7297
+ agentRole,
7298
+ sessionId: summarySessionId,
7299
+ projectName: primaryProject,
7300
+ reason: "periodic",
7301
+ memories: result.rows,
7302
+ tasks: taskRows
7175
7303
  });
7176
- for (const decisionText of decisionTexts.slice(0, 3)) {
7177
- await writeMemoryViaDaemon({
7178
- raw_text: decisionText,
7179
- agent_id: agentId,
7180
- agent_role: agentRole,
7181
- session_id: `auto-decision-${Date.now()}`,
7182
- tool_name: "auto-decision",
7183
- project_name: primaryProject,
7184
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7185
- importance: 8,
7186
- memory_type: "decision"
7187
- });
7188
- }
7304
+ summaryText = checkpointResult.checkpointText;
7189
7305
  if (!canCoordinate(agentId, agentRole)) {
7190
7306
  let totalErrors = 0;
7191
7307
  for (const [, data] of projects) {
package/dist/index.js CHANGED
@@ -149,6 +149,11 @@ function normalizeAutoUpdate(raw) {
149
149
  const userAU = raw.autoUpdate ?? {};
150
150
  raw.autoUpdate = { ...defaultAU, ...userAU };
151
151
  }
152
+ function normalizeOrchestration(raw) {
153
+ const defaultOrg = DEFAULT_CONFIG.orchestration;
154
+ const userOrg = raw.orchestration ?? {};
155
+ raw.orchestration = { ...defaultOrg, ...userOrg };
156
+ }
152
157
  async function loadConfig() {
153
158
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
154
159
  await ensurePrivateDir(dir);
@@ -173,6 +178,7 @@ async function loadConfig() {
173
178
  normalizeScalingRoadmap(migratedCfg);
174
179
  normalizeSessionLifecycle(migratedCfg);
175
180
  normalizeAutoUpdate(migratedCfg);
181
+ normalizeOrchestration(migratedCfg);
176
182
  const config2 = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
177
183
  if (config2.dbPath.startsWith("~")) {
178
184
  config2.dbPath = config2.dbPath.replace(/^~/, os2.homedir());
@@ -196,6 +202,7 @@ function loadConfigSync() {
196
202
  normalizeScalingRoadmap(migratedCfg);
197
203
  normalizeSessionLifecycle(migratedCfg);
198
204
  normalizeAutoUpdate(migratedCfg);
205
+ normalizeOrchestration(migratedCfg);
199
206
  return { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
200
207
  } catch {
201
208
  return { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db") };
@@ -217,6 +224,7 @@ async function loadConfigFrom(configPath) {
217
224
  normalizeScalingRoadmap(migratedCfg);
218
225
  normalizeSessionLifecycle(migratedCfg);
219
226
  normalizeAutoUpdate(migratedCfg);
227
+ normalizeOrchestration(migratedCfg);
220
228
  return { ...DEFAULT_CONFIG, ...migratedCfg };
221
229
  } catch {
222
230
  return { ...DEFAULT_CONFIG };
@@ -288,6 +296,10 @@ var init_config = __esm({
288
296
  checkOnBoot: true,
289
297
  autoInstall: false,
290
298
  checkIntervalMs: 24 * 60 * 60 * 1e3
299
+ },
300
+ orchestration: {
301
+ phase: "phase_1_coo",
302
+ phaseSetBy: "default"
291
303
  }
292
304
  };
293
305
  CONFIG_MIGRATIONS = [
@@ -7891,6 +7903,12 @@ var init_platform_procedures = __esm({
7891
7903
  priority: "p0",
7892
7904
  content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
7893
7905
  },
7906
+ {
7907
+ title: "Customer orchestration maturity \u2014 recommend, never trap",
7908
+ domain: "workflow",
7909
+ priority: "p1",
7910
+ content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
7911
+ },
7894
7912
  {
7895
7913
  title: "Single dispatch path \u2014 create_task only",
7896
7914
  domain: "workflow",
@@ -7949,6 +7967,12 @@ var init_platform_procedures = __esm({
7949
7967
  priority: "p0",
7950
7968
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
7951
7969
  },
7970
+ {
7971
+ title: "Commit discipline \u2014 never leave verified work floating",
7972
+ domain: "workflow",
7973
+ priority: "p1",
7974
+ content: "After any code-change batch passes typecheck/tests/build, run git status, summarize changed files, and commit with a clear message before ending the session. If work must remain uncommitted for review/dogfood, explicitly say so, list the files, and state the blocker. Never imply work is complete while verified changes are still floating locally."
7975
+ },
7952
7976
  {
7953
7977
  title: "Desktop and TUI are the same product",
7954
7978
  domain: "architecture",
@@ -105,6 +105,10 @@ var DEFAULT_CONFIG = {
105
105
  checkOnBoot: true,
106
106
  autoInstall: false,
107
107
  checkIntervalMs: 24 * 60 * 60 * 1e3
108
+ },
109
+ orchestration: {
110
+ phase: "phase_1_coo",
111
+ phaseSetBy: "default"
108
112
  }
109
113
  };
110
114