@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
@@ -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 config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
177
183
  if (config.dbPath.startsWith("~")) {
178
184
  config.dbPath = config.dbPath.replace(/^~/, os.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: path.join(dir, "memories.db"), ...migratedCfg };
200
207
  } catch {
201
208
  return { ...DEFAULT_CONFIG, dbPath: path.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 = [
@@ -6934,15 +6946,15 @@ var init_task_scope = __esm({
6934
6946
 
6935
6947
  // src/lib/keychain.ts
6936
6948
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
6937
- import { existsSync as existsSync17 } from "fs";
6949
+ import { existsSync as existsSync18 } from "fs";
6938
6950
  import { execSync as execSync8 } from "child_process";
6939
- import path21 from "path";
6951
+ import path22 from "path";
6940
6952
  import os13 from "os";
6941
6953
  function getKeyDir() {
6942
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path21.join(os13.homedir(), ".exe-os");
6954
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os13.homedir(), ".exe-os");
6943
6955
  }
6944
6956
  function getKeyPath() {
6945
- return path21.join(getKeyDir(), "master.key");
6957
+ return path22.join(getKeyDir(), "master.key");
6946
6958
  }
6947
6959
  function macKeychainGet() {
6948
6960
  if (process.platform !== "darwin") return null;
@@ -7090,7 +7102,7 @@ async function getMasterKey() {
7090
7102
  }
7091
7103
  }
7092
7104
  const keyPath = getKeyPath();
7093
- if (!existsSync17(keyPath)) {
7105
+ if (!existsSync18(keyPath)) {
7094
7106
  process.stderr.write(
7095
7107
  `[keychain] Key not found at ${keyPath} (HOME=${os13.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
7096
7108
  `
@@ -7364,12 +7376,12 @@ __export(shard_manager_exports, {
7364
7376
  listShards: () => listShards,
7365
7377
  shardExists: () => shardExists
7366
7378
  });
7367
- import path22 from "path";
7368
- import { existsSync as existsSync18, mkdirSync as mkdirSync10, readdirSync as readdirSync5, renameSync as renameSync4, statSync as statSync2 } from "fs";
7379
+ import path23 from "path";
7380
+ import { existsSync as existsSync19, mkdirSync as mkdirSync10, readdirSync as readdirSync5, renameSync as renameSync5, statSync as statSync3 } from "fs";
7369
7381
  import { createClient as createClient2 } from "@libsql/client";
7370
7382
  function initShardManager(encryptionKey) {
7371
7383
  _encryptionKey = encryptionKey;
7372
- if (!existsSync18(SHARDS_DIR)) {
7384
+ if (!existsSync19(SHARDS_DIR)) {
7373
7385
  mkdirSync10(SHARDS_DIR, { recursive: true });
7374
7386
  }
7375
7387
  _shardingEnabled = true;
@@ -7399,7 +7411,7 @@ function getShardClient(projectName) {
7399
7411
  while (_shards.size >= MAX_OPEN_SHARDS) {
7400
7412
  evictLRU();
7401
7413
  }
7402
- const dbPath = path22.join(SHARDS_DIR, `${safeName}.db`);
7414
+ const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
7403
7415
  const client = createClient2({
7404
7416
  url: `file:${dbPath}`,
7405
7417
  encryptionKey: _encryptionKey
@@ -7410,13 +7422,13 @@ function getShardClient(projectName) {
7410
7422
  }
7411
7423
  function shardExists(projectName) {
7412
7424
  const safeName = safeShardName(projectName);
7413
- return existsSync18(path22.join(SHARDS_DIR, `${safeName}.db`));
7425
+ return existsSync19(path23.join(SHARDS_DIR, `${safeName}.db`));
7414
7426
  }
7415
7427
  function safeShardName(projectName) {
7416
7428
  return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
7417
7429
  }
7418
7430
  function listShards() {
7419
- if (!existsSync18(SHARDS_DIR)) return [];
7431
+ if (!existsSync19(SHARDS_DIR)) return [];
7420
7432
  return readdirSync5(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
7421
7433
  }
7422
7434
  async function auditShardHealth(options = {}) {
@@ -7428,8 +7440,8 @@ async function auditShardHealth(options = {}) {
7428
7440
  const names = listShards();
7429
7441
  const shards = [];
7430
7442
  for (const name of names) {
7431
- const dbPath = path22.join(SHARDS_DIR, `${name}.db`);
7432
- const stat = statSync2(dbPath);
7443
+ const dbPath = path23.join(SHARDS_DIR, `${name}.db`);
7444
+ const stat = statSync3(dbPath);
7433
7445
  const item = {
7434
7446
  name,
7435
7447
  path: dbPath,
@@ -7463,8 +7475,8 @@ async function auditShardHealth(options = {}) {
7463
7475
  _shards.delete(name);
7464
7476
  _shardLastAccess.delete(name);
7465
7477
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7466
- const archivedPath = path22.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
7467
- renameSync4(dbPath, archivedPath);
7478
+ const archivedPath = path23.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
7479
+ renameSync5(dbPath, archivedPath);
7468
7480
  item.archivedPath = archivedPath;
7469
7481
  }
7470
7482
  } finally {
@@ -7680,12 +7692,12 @@ async function getReadyShardClient(projectName) {
7680
7692
  client.close();
7681
7693
  _shards.delete(safeName);
7682
7694
  _shardLastAccess.delete(safeName);
7683
- const dbPath = path22.join(SHARDS_DIR, `${safeName}.db`);
7684
- if (existsSync18(dbPath)) {
7685
- const stat = statSync2(dbPath);
7695
+ const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
7696
+ if (existsSync19(dbPath)) {
7697
+ const stat = statSync3(dbPath);
7686
7698
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7687
- const archivedPath = path22.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
7688
- renameSync4(dbPath, archivedPath);
7699
+ const archivedPath = path23.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
7700
+ renameSync5(dbPath, archivedPath);
7689
7701
  process.stderr.write(
7690
7702
  `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
7691
7703
  `
@@ -7752,7 +7764,7 @@ var init_shard_manager = __esm({
7752
7764
  "src/lib/shard-manager.ts"() {
7753
7765
  "use strict";
7754
7766
  init_config();
7755
- SHARDS_DIR = path22.join(EXE_AI_DIR, "shards");
7767
+ SHARDS_DIR = path23.join(EXE_AI_DIR, "shards");
7756
7768
  SHARD_IDLE_MS = 5 * 60 * 1e3;
7757
7769
  MAX_OPEN_SHARDS = 10;
7758
7770
  EVICTION_INTERVAL_MS = 60 * 1e3;
@@ -7802,6 +7814,12 @@ var init_platform_procedures = __esm({
7802
7814
  priority: "p0",
7803
7815
  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."
7804
7816
  },
7817
+ {
7818
+ title: "Customer orchestration maturity \u2014 recommend, never trap",
7819
+ domain: "workflow",
7820
+ priority: "p1",
7821
+ 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."
7822
+ },
7805
7823
  {
7806
7824
  title: "Single dispatch path \u2014 create_task only",
7807
7825
  domain: "workflow",
@@ -7860,6 +7878,12 @@ var init_platform_procedures = __esm({
7860
7878
  priority: "p0",
7861
7879
  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."
7862
7880
  },
7881
+ {
7882
+ title: "Commit discipline \u2014 never leave verified work floating",
7883
+ domain: "workflow",
7884
+ priority: "p1",
7885
+ 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."
7886
+ },
7863
7887
  {
7864
7888
  title: "Desktop and TUI are the same product",
7865
7889
  domain: "architecture",
@@ -8867,78 +8891,6 @@ var init_fast_db_init = __esm({
8867
8891
  }
8868
8892
  });
8869
8893
 
8870
- // src/lib/memory-queue.ts
8871
- import { appendFileSync as appendFileSync2, readFileSync as readFileSync15, renameSync as renameSync5, unlinkSync as unlinkSync9, existsSync as existsSync19, statSync as statSync3 } from "fs";
8872
- import path23 from "path";
8873
- function enqueueMemory(entry) {
8874
- appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
8875
- }
8876
- var QUEUE_PATH2, PROCESSING_PATH, TTL_MS2;
8877
- var init_memory_queue = __esm({
8878
- "src/lib/memory-queue.ts"() {
8879
- "use strict";
8880
- init_config();
8881
- QUEUE_PATH2 = path23.join(EXE_AI_DIR, "memory-queue.jsonl");
8882
- PROCESSING_PATH = QUEUE_PATH2 + ".processing";
8883
- TTL_MS2 = 24 * 60 * 60 * 1e3;
8884
- }
8885
- });
8886
-
8887
- // src/lib/memory-queue-client.ts
8888
- var memory_queue_client_exports = {};
8889
- __export(memory_queue_client_exports, {
8890
- batchWriteMemoryViaDaemon: () => batchWriteMemoryViaDaemon,
8891
- writeMemoryViaDaemon: () => writeMemoryViaDaemon
8892
- });
8893
- async function writeMemoryViaDaemon(entry) {
8894
- if (process.env.EXE_IS_DAEMON === "1") {
8895
- enqueueMemory(entry);
8896
- return false;
8897
- }
8898
- if (!isClientConnected()) {
8899
- enqueueMemory(entry);
8900
- return false;
8901
- }
8902
- try {
8903
- const response = await sendDaemonRequest({
8904
- type: "write-memory",
8905
- entry
8906
- });
8907
- if (response.ok) return true;
8908
- enqueueMemory(entry);
8909
- return false;
8910
- } catch {
8911
- enqueueMemory(entry);
8912
- return false;
8913
- }
8914
- }
8915
- async function batchWriteMemoryViaDaemon(entries) {
8916
- if (entries.length === 0) return 0;
8917
- if (process.env.EXE_IS_DAEMON === "1" || !isClientConnected()) {
8918
- for (const entry of entries) enqueueMemory(entry);
8919
- return 0;
8920
- }
8921
- try {
8922
- const response = await sendDaemonRequest({
8923
- type: "batch-write-memory",
8924
- entries
8925
- });
8926
- if (response.ok) return response.count ?? entries.length;
8927
- for (const entry of entries) enqueueMemory(entry);
8928
- return 0;
8929
- } catch {
8930
- for (const entry of entries) enqueueMemory(entry);
8931
- return 0;
8932
- }
8933
- }
8934
- var init_memory_queue_client = __esm({
8935
- "src/lib/memory-queue-client.ts"() {
8936
- "use strict";
8937
- init_exe_daemon_client();
8938
- init_memory_queue();
8939
- }
8940
- });
8941
-
8942
8894
  // src/lib/git-staleness.ts
8943
8895
  var git_staleness_exports = {};
8944
8896
  __export(git_staleness_exports, {
@@ -9486,6 +9438,119 @@ function buildAutoCheckpoint(input2) {
9486
9438
  };
9487
9439
  }
9488
9440
 
9441
+ // src/lib/memory-queue-client.ts
9442
+ init_exe_daemon_client();
9443
+
9444
+ // src/lib/memory-queue.ts
9445
+ init_config();
9446
+ import { appendFileSync as appendFileSync2, readFileSync as readFileSync15, renameSync as renameSync4, unlinkSync as unlinkSync9, existsSync as existsSync17, statSync as statSync2 } from "fs";
9447
+ import path21 from "path";
9448
+ var QUEUE_PATH2 = path21.join(EXE_AI_DIR, "memory-queue.jsonl");
9449
+ var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
9450
+ var TTL_MS2 = 24 * 60 * 60 * 1e3;
9451
+ function enqueueMemory(entry) {
9452
+ appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
9453
+ }
9454
+
9455
+ // src/lib/memory-queue-client.ts
9456
+ async function writeMemoryViaDaemon(entry) {
9457
+ if (process.env.EXE_IS_DAEMON === "1") {
9458
+ enqueueMemory(entry);
9459
+ return false;
9460
+ }
9461
+ if (!isClientConnected()) {
9462
+ enqueueMemory(entry);
9463
+ return false;
9464
+ }
9465
+ try {
9466
+ const response = await sendDaemonRequest({
9467
+ type: "write-memory",
9468
+ entry
9469
+ });
9470
+ if (response.ok) return true;
9471
+ enqueueMemory(entry);
9472
+ return false;
9473
+ } catch {
9474
+ enqueueMemory(entry);
9475
+ return false;
9476
+ }
9477
+ }
9478
+
9479
+ // src/lib/checkpoint-orchestrator.ts
9480
+ function toolNameForReason(reason) {
9481
+ switch (reason) {
9482
+ case "periodic":
9483
+ return "auto-summary";
9484
+ case "session-end":
9485
+ return "SessionEnd";
9486
+ case "pre-compact":
9487
+ return "pre-compact-hook";
9488
+ case "capacity-signal":
9489
+ return "auto-checkpoint";
9490
+ }
9491
+ }
9492
+ function importanceForReason(reason, override) {
9493
+ if (override !== void 0) return override;
9494
+ switch (reason) {
9495
+ case "periodic":
9496
+ return 7;
9497
+ case "session-end":
9498
+ case "pre-compact":
9499
+ case "capacity-signal":
9500
+ return 8;
9501
+ }
9502
+ }
9503
+ function buildContinuityCheckpoint(input2) {
9504
+ const { checkpointText, decisionTexts } = buildAutoCheckpoint({
9505
+ agentId: input2.agentId,
9506
+ agentRole: input2.agentRole,
9507
+ sessionId: input2.sessionId,
9508
+ projectName: input2.projectName,
9509
+ reason: input2.reason,
9510
+ memories: input2.memories ?? [],
9511
+ tasks: input2.tasks ?? [],
9512
+ maxSamples: input2.maxSamples
9513
+ });
9514
+ const extra = input2.extraSections?.filter((section) => section.trim().length > 0) ?? [];
9515
+ return {
9516
+ checkpointText: extra.length > 0 ? `${checkpointText}
9517
+
9518
+ ${extra.join("\n\n")}` : checkpointText,
9519
+ decisionTexts
9520
+ };
9521
+ }
9522
+ async function writeContinuityCheckpoint(input2) {
9523
+ const result = buildContinuityCheckpoint(input2);
9524
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9525
+ await writeMemoryViaDaemon({
9526
+ raw_text: result.checkpointText,
9527
+ agent_id: input2.agentId,
9528
+ agent_role: input2.agentRole,
9529
+ session_id: input2.sessionId,
9530
+ tool_name: toolNameForReason(input2.reason),
9531
+ project_name: input2.projectName,
9532
+ timestamp: now,
9533
+ importance: importanceForReason(input2.reason, input2.importance),
9534
+ task_id: input2.taskId,
9535
+ memory_type: "checkpoint"
9536
+ });
9537
+ const decisionLimit = input2.reason === "periodic" ? 3 : 5;
9538
+ for (const decisionText of result.decisionTexts.slice(0, decisionLimit)) {
9539
+ await writeMemoryViaDaemon({
9540
+ raw_text: decisionText,
9541
+ agent_id: input2.agentId,
9542
+ agent_role: input2.agentRole,
9543
+ session_id: input2.sessionId,
9544
+ tool_name: "auto-decision",
9545
+ project_name: input2.projectName,
9546
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9547
+ importance: 8,
9548
+ memory_type: "decision"
9549
+ });
9550
+ }
9551
+ return result;
9552
+ }
9553
+
9489
9554
  // src/adapters/claude/hooks/session-end.ts
9490
9555
  if (!process.env.AGENT_ID) {
9491
9556
  process.env.AGENT_ID = "default";
@@ -9535,7 +9600,7 @@ Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title
9535
9600
  ORDER BY priority ASC, updated_at DESC LIMIT 10`,
9536
9601
  args: [agent.agentId, ...seScope.args]
9537
9602
  });
9538
- const { checkpointText, decisionTexts } = buildAutoCheckpoint({
9603
+ await writeContinuityCheckpoint({
9539
9604
  agentId: agent.agentId,
9540
9605
  agentRole: agent.agentRole,
9541
9606
  sessionId: data.session_id,
@@ -9543,35 +9608,9 @@ Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title
9543
9608
  reason: "session-end",
9544
9609
  memories: recent.rows,
9545
9610
  tasks: taskRows.rows,
9546
- maxSamples: 12
9611
+ maxSamples: 12,
9612
+ extraSections: orphanInfo ? [`## Session-End Warnings${orphanInfo}`] : []
9547
9613
  });
9548
- const { writeMemoryViaDaemon: writeMemoryViaDaemon2 } = await Promise.resolve().then(() => (init_memory_queue_client(), memory_queue_client_exports));
9549
- await writeMemoryViaDaemon2({
9550
- raw_text: `${checkpointText}${orphanInfo ? `
9551
-
9552
- ## Session-End Warnings${orphanInfo}` : ""}`,
9553
- agent_id: agent.agentId,
9554
- agent_role: agent.agentRole,
9555
- session_id: data.session_id,
9556
- tool_name: "SessionEnd",
9557
- project_name: projectName,
9558
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9559
- importance: 8,
9560
- memory_type: "checkpoint"
9561
- });
9562
- for (const decisionText of decisionTexts.slice(0, 5)) {
9563
- await writeMemoryViaDaemon2({
9564
- raw_text: decisionText,
9565
- agent_id: agent.agentId,
9566
- agent_role: agent.agentRole,
9567
- session_id: data.session_id,
9568
- tool_name: "auto-decision",
9569
- project_name: projectName,
9570
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9571
- importance: 8,
9572
- memory_type: "decision"
9573
- });
9574
- }
9575
9614
  try {
9576
9615
  const { clearSessionFileReads: clearSessionFileReads2 } = await Promise.resolve().then(() => (init_git_staleness(), git_staleness_exports));
9577
9616
  await clearSessionFileReads2(data.session_id);
@@ -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 config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
177
183
  if (config.dbPath.startsWith("~")) {
178
184
  config.dbPath = config.dbPath.replace(/^~/, os.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: path.join(dir, "memories.db"), ...migratedCfg };
200
207
  } catch {
201
208
  return { ...DEFAULT_CONFIG, dbPath: path.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 = [
@@ -4238,6 +4250,12 @@ var init_platform_procedures = __esm({
4238
4250
  priority: "p0",
4239
4251
  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."
4240
4252
  },
4253
+ {
4254
+ title: "Customer orchestration maturity \u2014 recommend, never trap",
4255
+ domain: "workflow",
4256
+ priority: "p1",
4257
+ 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."
4258
+ },
4241
4259
  {
4242
4260
  title: "Single dispatch path \u2014 create_task only",
4243
4261
  domain: "workflow",
@@ -4296,6 +4314,12 @@ var init_platform_procedures = __esm({
4296
4314
  priority: "p0",
4297
4315
  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."
4298
4316
  },
4317
+ {
4318
+ title: "Commit discipline \u2014 never leave verified work floating",
4319
+ domain: "workflow",
4320
+ priority: "p1",
4321
+ 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."
4322
+ },
4299
4323
  {
4300
4324
  title: "Desktop and TUI are the same product",
4301
4325
  domain: "architecture",
@@ -8055,6 +8079,115 @@ var init_identity = __esm({
8055
8079
  }
8056
8080
  });
8057
8081
 
8082
+ // src/lib/orchestration-phase.ts
8083
+ var orchestration_phase_exports = {};
8084
+ __export(orchestration_phase_exports, {
8085
+ ORCHESTRATION_PHASES: () => ORCHESTRATION_PHASES,
8086
+ applyDefaultOrchestrationPhase: () => applyDefaultOrchestrationPhase,
8087
+ getConfigOrchestrationPhase: () => getConfigOrchestrationPhase,
8088
+ getOrchestrationPhaseInfo: () => getOrchestrationPhaseInfo,
8089
+ loadOrchestrationPhase: () => loadOrchestrationPhase,
8090
+ normalizeOrchestrationPhase: () => normalizeOrchestrationPhase,
8091
+ phaseReminderLine: () => phaseReminderLine,
8092
+ setOrchestrationPhase: () => setOrchestrationPhase
8093
+ });
8094
+ function normalizeOrchestrationPhase(input2) {
8095
+ if (typeof input2 !== "string") return "phase_1_coo";
8096
+ const normalized = input2.trim().toLowerCase().replace(/\s+/g, "_");
8097
+ if (["1", "phase1", "phase_1", "coo", "coo_mode", "chief_of_staff", "phase_1_coo"].includes(normalized)) {
8098
+ return "phase_1_coo";
8099
+ }
8100
+ if (["2", "phase2", "phase_2", "executives", "executive", "executive_bench", "phase_2_executives"].includes(normalized)) {
8101
+ return "phase_2_executives";
8102
+ }
8103
+ if (["3", "phase3", "phase_3", "parallel", "parallel_org", "parallel_execution", "phase_3_parallel_org"].includes(normalized)) {
8104
+ return "phase_3_parallel_org";
8105
+ }
8106
+ if (ORCHESTRATION_PHASES.includes(normalized)) return normalized;
8107
+ return "phase_1_coo";
8108
+ }
8109
+ function getOrchestrationPhaseInfo(phase) {
8110
+ return PHASE_INFO[normalizeOrchestrationPhase(phase)];
8111
+ }
8112
+ function getConfigOrchestrationPhase(config) {
8113
+ const orchestration = config.orchestration;
8114
+ return normalizeOrchestrationPhase(orchestration?.phase);
8115
+ }
8116
+ function applyDefaultOrchestrationPhase(config) {
8117
+ if (!config.orchestration) {
8118
+ config.orchestration = {
8119
+ phase: "phase_1_coo",
8120
+ phaseSetAt: (/* @__PURE__ */ new Date()).toISOString(),
8121
+ phaseSetBy: "setup-default"
8122
+ };
8123
+ return config;
8124
+ }
8125
+ if (!config.orchestration.phase) {
8126
+ config.orchestration = {
8127
+ ...config.orchestration,
8128
+ phase: "phase_1_coo",
8129
+ phaseSetAt: config.orchestration.phaseSetAt ?? (/* @__PURE__ */ new Date()).toISOString(),
8130
+ phaseSetBy: config.orchestration.phaseSetBy ?? "setup-default"
8131
+ };
8132
+ }
8133
+ return config;
8134
+ }
8135
+ async function loadOrchestrationPhase() {
8136
+ const config = await loadConfig();
8137
+ return getOrchestrationPhaseInfo(config.orchestration?.phase);
8138
+ }
8139
+ async function setOrchestrationPhase(phaseInput, setBy = "user") {
8140
+ const config = await loadConfig();
8141
+ const phase = normalizeOrchestrationPhase(phaseInput);
8142
+ config.orchestration = {
8143
+ ...config.orchestration ?? {},
8144
+ phase,
8145
+ phaseSetAt: (/* @__PURE__ */ new Date()).toISOString(),
8146
+ phaseSetBy: setBy
8147
+ };
8148
+ await saveConfig(config);
8149
+ return getOrchestrationPhaseInfo(phase);
8150
+ }
8151
+ function phaseReminderLine(phase) {
8152
+ const info = getOrchestrationPhaseInfo(phase);
8153
+ return `${info.shortLabel}: ${info.focus}. ${info.nextSuggestion}`;
8154
+ }
8155
+ var ORCHESTRATION_PHASES, PHASE_INFO;
8156
+ var init_orchestration_phase = __esm({
8157
+ "src/lib/orchestration-phase.ts"() {
8158
+ "use strict";
8159
+ init_config();
8160
+ ORCHESTRATION_PHASES = [
8161
+ "phase_1_coo",
8162
+ "phase_2_executives",
8163
+ "phase_3_parallel_org"
8164
+ ];
8165
+ PHASE_INFO = {
8166
+ phase_1_coo: {
8167
+ phase: "phase_1_coo",
8168
+ shortLabel: "Phase 1 \u2014 COO mode",
8169
+ label: "Phase 1 \u2014 COO / Chief of Staff mode",
8170
+ focus: "building company context before delegation",
8171
+ nextSuggestion: "Unlock executives when technical, marketing, ops, legal, or finance work repeats."
8172
+ },
8173
+ phase_2_executives: {
8174
+ phase: "phase_2_executives",
8175
+ shortLabel: "Phase 2 \u2014 Executive bench",
8176
+ label: "Phase 2 \u2014 Executive bench",
8177
+ focus: "COO works with domain executives like CTO/CMO before specialist fan-out",
8178
+ nextSuggestion: "Unlock parallel execution when review gates, permissions, and workflows are ready."
8179
+ },
8180
+ phase_3_parallel_org: {
8181
+ phase: "phase_3_parallel_org",
8182
+ shortLabel: "Phase 3 \u2014 Parallel org",
8183
+ label: "Phase 3 \u2014 Parallel execution org",
8184
+ focus: "executives can delegate to specialists in parallel with review gates",
8185
+ nextSuggestion: "Keep review/CI/permission gates healthy; downgrade anytime if you want simpler COO-only mode."
8186
+ }
8187
+ };
8188
+ }
8189
+ });
8190
+
8058
8191
  // src/adapters/claude/hooks/session-start.ts
8059
8192
  init_config();
8060
8193
  import path21 from "path";
@@ -8236,6 +8369,15 @@ You are **${title}**${role ? ` (${role})` : ""}. ${firstLine}
8236
8369
  } catch {
8237
8370
  }
8238
8371
  }
8372
+ try {
8373
+ const { loadOrchestrationPhase: loadOrchestrationPhase2 } = await Promise.resolve().then(() => (init_orchestration_phase(), orchestration_phase_exports));
8374
+ const phase = await loadOrchestrationPhase2();
8375
+ additionalContext += `## Orchestration Phase
8376
+ ${phase.label}. Focus: ${phase.focus}. This is guidance, not a blocker; the user can switch phases anytime. ${phase.nextSuggestion}
8377
+
8378
+ `;
8379
+ } catch {
8380
+ }
8239
8381
  if (memories.length > 0) {
8240
8382
  const brief = memories.map(
8241
8383
  (m) => `[${m.timestamp}] ${m.tool_name}: ${m.raw_text.slice(0, 200)}`