@askexenow/exe-os 0.9.65 → 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 +2263 -1203
  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 +93 -5
  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 +287 -176
  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 +389 -155
  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 +172 -77
  64. package/dist/index.js +24 -0
  65. package/dist/lib/agent-config.js +4 -0
  66. package/dist/lib/cloud-sync.js +27 -4
  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 +1058 -453
  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 +1022 -425
  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
package/dist/bin/setup.js CHANGED
@@ -139,6 +139,11 @@ function normalizeAutoUpdate(raw) {
139
139
  const userAU = raw.autoUpdate ?? {};
140
140
  raw.autoUpdate = { ...defaultAU, ...userAU };
141
141
  }
142
+ function normalizeOrchestration(raw) {
143
+ const defaultOrg = DEFAULT_CONFIG.orchestration;
144
+ const userOrg = raw.orchestration ?? {};
145
+ raw.orchestration = { ...defaultOrg, ...userOrg };
146
+ }
142
147
  async function loadConfig() {
143
148
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
144
149
  await ensurePrivateDir(dir);
@@ -163,6 +168,7 @@ async function loadConfig() {
163
168
  normalizeScalingRoadmap(migratedCfg);
164
169
  normalizeSessionLifecycle(migratedCfg);
165
170
  normalizeAutoUpdate(migratedCfg);
171
+ normalizeOrchestration(migratedCfg);
166
172
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
167
173
  if (config.dbPath.startsWith("~")) {
168
174
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -186,6 +192,7 @@ function loadConfigSync() {
186
192
  normalizeScalingRoadmap(migratedCfg);
187
193
  normalizeSessionLifecycle(migratedCfg);
188
194
  normalizeAutoUpdate(migratedCfg);
195
+ normalizeOrchestration(migratedCfg);
189
196
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
190
197
  } catch {
191
198
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
@@ -207,6 +214,7 @@ async function loadConfigFrom(configPath) {
207
214
  normalizeScalingRoadmap(migratedCfg);
208
215
  normalizeSessionLifecycle(migratedCfg);
209
216
  normalizeAutoUpdate(migratedCfg);
217
+ normalizeOrchestration(migratedCfg);
210
218
  return { ...DEFAULT_CONFIG, ...migratedCfg };
211
219
  } catch {
212
220
  return { ...DEFAULT_CONFIG };
@@ -278,6 +286,10 @@ var init_config = __esm({
278
286
  checkOnBoot: true,
279
287
  autoInstall: false,
280
288
  checkIntervalMs: 24 * 60 * 60 * 1e3
289
+ },
290
+ orchestration: {
291
+ phase: "phase_1_coo",
292
+ phaseSetBy: "default"
281
293
  }
282
294
  };
283
295
  CONFIG_MIGRATIONS = [
@@ -415,8 +427,8 @@ function deriveMachineKey() {
415
427
  }
416
428
  function readMachineId() {
417
429
  try {
418
- const { readFileSync: readFileSync13 } = __require("fs");
419
- return readFileSync13("/etc/machine-id", "utf-8").trim();
430
+ const { readFileSync: readFileSync14 } = __require("fs");
431
+ return readFileSync14("/etc/machine-id", "utf-8").trim();
420
432
  } catch {
421
433
  return "";
422
434
  }
@@ -1129,10 +1141,10 @@ async function disposeEmbedder() {
1129
1141
  async function embedDirect(text) {
1130
1142
  const llamaCpp = await import("node-llama-cpp");
1131
1143
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
1132
- const { existsSync: existsSync17 } = await import("fs");
1133
- const path17 = await import("path");
1134
- const modelPath = path17.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
1135
- if (!existsSync17(modelPath)) {
1144
+ const { existsSync: existsSync18 } = await import("fs");
1145
+ const path18 = await import("path");
1146
+ const modelPath = path18.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
1147
+ if (!existsSync18(modelPath)) {
1136
1148
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
1137
1149
  }
1138
1150
  const llama = await llamaCpp.getLlama();
@@ -4503,8 +4515,10 @@ var init_db_backup = __esm({
4503
4515
  // src/lib/cloud-sync.ts
4504
4516
  var cloud_sync_exports = {};
4505
4517
  __export(cloud_sync_exports, {
4518
+ CLOUD_RELINK_REQUIRED_MESSAGE: () => CLOUD_RELINK_REQUIRED_MESSAGE,
4506
4519
  assertSecureEndpoint: () => assertSecureEndpoint,
4507
4520
  buildRosterBlob: () => buildRosterBlob,
4521
+ clearCloudRelinkRequired: () => clearCloudRelinkRequired,
4508
4522
  cloudPull: () => cloudPull,
4509
4523
  cloudPullBehaviors: () => cloudPullBehaviors,
4510
4524
  cloudPullBlob: () => cloudPullBlob,
@@ -4524,6 +4538,7 @@ __export(cloud_sync_exports, {
4524
4538
  cloudPushRoster: () => cloudPushRoster,
4525
4539
  cloudPushTasks: () => cloudPushTasks,
4526
4540
  cloudSync: () => cloudSync,
4541
+ getCloudRelinkRequired: () => getCloudRelinkRequired,
4527
4542
  mergeConfig: () => mergeConfig,
4528
4543
  mergeRosterFromRemote: () => mergeRosterFromRemote,
4529
4544
  pushToPostgres: () => pushToPostgres,
@@ -4757,6 +4772,24 @@ async function cloudPull(sinceVersion, config) {
4757
4772
  return { records: [], maxVersion: sinceVersion };
4758
4773
  }
4759
4774
  }
4775
+ async function getCloudRelinkRequired(client = getClient()) {
4776
+ try {
4777
+ await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
4778
+ const relink = await client.execute("SELECT value FROM sync_meta WHERE key = 'cloud_relink_required' LIMIT 1");
4779
+ return String(relink.rows[0]?.value ?? "") === "1";
4780
+ } catch {
4781
+ return false;
4782
+ }
4783
+ }
4784
+ async function clearCloudRelinkRequired(client = getClient()) {
4785
+ await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
4786
+ await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relink_required', '0')");
4787
+ await client.execute({
4788
+ sql: "INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relinked_at', ?)",
4789
+ args: [(/* @__PURE__ */ new Date()).toISOString()]
4790
+ });
4791
+ await client.execute("DELETE FROM sync_meta WHERE key IN ('last_cloud_pull_version', 'last_cloud_push_version')");
4792
+ }
4760
4793
  async function cloudSync(config) {
4761
4794
  if (!isSyncCryptoInitialized()) {
4762
4795
  try {
@@ -4778,10 +4811,7 @@ async function cloudSync(config) {
4778
4811
  throw new Error("[cloud-sync] Database not initialized. Call initStore() before cloudSync().");
4779
4812
  }
4780
4813
  try {
4781
- const relink = await client.execute("SELECT value FROM sync_meta WHERE key = 'cloud_relink_required' LIMIT 1");
4782
- if (String(relink.rows[0]?.value ?? "") === "1") {
4783
- throw new Error("[cloud-sync] Paused after key rotation. Re-link/reupload cloud sync with the new recovery phrase before syncing.");
4784
- }
4814
+ if (await getCloudRelinkRequired(client)) throw new Error(CLOUD_RELINK_REQUIRED_MESSAGE);
4785
4815
  } catch (err) {
4786
4816
  const msg = err instanceof Error ? err.message : String(err);
4787
4817
  if (msg.includes("Paused after key rotation")) throw err;
@@ -5713,7 +5743,7 @@ async function cloudPullDocuments(config) {
5713
5743
  }
5714
5744
  return { pulled };
5715
5745
  }
5716
- var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, ROSTER_DELETIONS_PATH;
5746
+ var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, CLOUD_RELINK_REQUIRED_MESSAGE, ROSTER_DELETIONS_PATH;
5717
5747
  var init_cloud_sync = __esm({
5718
5748
  "src/lib/cloud-sync.ts"() {
5719
5749
  "use strict";
@@ -5732,43 +5762,194 @@ var init_cloud_sync = __esm({
5732
5762
  LOCK_STALE_MS = 3e4;
5733
5763
  _pgPromise = null;
5734
5764
  _pgFailed = false;
5765
+ CLOUD_RELINK_REQUIRED_MESSAGE = "[cloud-sync] Paused after key rotation. Run `exe-os cloud relink --dry-run` for the safe relink checklist.";
5735
5766
  ROSTER_DELETIONS_PATH = path12.join(EXE_AI_DIR, "roster-deletions.json");
5736
5767
  }
5737
5768
  });
5738
5769
 
5770
+ // src/lib/key-backup-status.ts
5771
+ var key_backup_status_exports = {};
5772
+ __export(key_backup_status_exports, {
5773
+ getKeyBackupStatus: () => getKeyBackupStatus,
5774
+ keyBackupMarkerPath: () => keyBackupMarkerPath,
5775
+ markKeyBackupConfirmed: () => markKeyBackupConfirmed
5776
+ });
5777
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
5778
+ import path13 from "path";
5779
+ function keyBackupMarkerPath() {
5780
+ return path13.join(EXE_AI_DIR, "key-backup-confirmed.json");
5781
+ }
5782
+ function getKeyBackupStatus() {
5783
+ const marker = keyBackupMarkerPath();
5784
+ if (!existsSync13(marker)) return { exists: false };
5785
+ try {
5786
+ const parsed = JSON.parse(readFileSync9(marker, "utf8"));
5787
+ return {
5788
+ exists: true,
5789
+ confirmedAt: parsed.confirmedAt,
5790
+ source: parsed.source
5791
+ };
5792
+ } catch {
5793
+ return { exists: true };
5794
+ }
5795
+ }
5796
+ function markKeyBackupConfirmed(source) {
5797
+ mkdirSync6(EXE_AI_DIR, { recursive: true, mode: 448 });
5798
+ writeFileSync7(
5799
+ keyBackupMarkerPath(),
5800
+ JSON.stringify({ confirmedAt: (/* @__PURE__ */ new Date()).toISOString(), source }, null, 2) + "\n",
5801
+ { mode: 384 }
5802
+ );
5803
+ }
5804
+ var init_key_backup_status = __esm({
5805
+ "src/lib/key-backup-status.ts"() {
5806
+ "use strict";
5807
+ init_config();
5808
+ }
5809
+ });
5810
+
5811
+ // src/lib/orchestration-phase.ts
5812
+ var orchestration_phase_exports = {};
5813
+ __export(orchestration_phase_exports, {
5814
+ ORCHESTRATION_PHASES: () => ORCHESTRATION_PHASES,
5815
+ applyDefaultOrchestrationPhase: () => applyDefaultOrchestrationPhase,
5816
+ getConfigOrchestrationPhase: () => getConfigOrchestrationPhase,
5817
+ getOrchestrationPhaseInfo: () => getOrchestrationPhaseInfo,
5818
+ loadOrchestrationPhase: () => loadOrchestrationPhase,
5819
+ normalizeOrchestrationPhase: () => normalizeOrchestrationPhase,
5820
+ phaseReminderLine: () => phaseReminderLine,
5821
+ setOrchestrationPhase: () => setOrchestrationPhase
5822
+ });
5823
+ function normalizeOrchestrationPhase(input) {
5824
+ if (typeof input !== "string") return "phase_1_coo";
5825
+ const normalized = input.trim().toLowerCase().replace(/\s+/g, "_");
5826
+ if (["1", "phase1", "phase_1", "coo", "coo_mode", "chief_of_staff", "phase_1_coo"].includes(normalized)) {
5827
+ return "phase_1_coo";
5828
+ }
5829
+ if (["2", "phase2", "phase_2", "executives", "executive", "executive_bench", "phase_2_executives"].includes(normalized)) {
5830
+ return "phase_2_executives";
5831
+ }
5832
+ if (["3", "phase3", "phase_3", "parallel", "parallel_org", "parallel_execution", "phase_3_parallel_org"].includes(normalized)) {
5833
+ return "phase_3_parallel_org";
5834
+ }
5835
+ if (ORCHESTRATION_PHASES.includes(normalized)) return normalized;
5836
+ return "phase_1_coo";
5837
+ }
5838
+ function getOrchestrationPhaseInfo(phase) {
5839
+ return PHASE_INFO[normalizeOrchestrationPhase(phase)];
5840
+ }
5841
+ function getConfigOrchestrationPhase(config) {
5842
+ const orchestration = config.orchestration;
5843
+ return normalizeOrchestrationPhase(orchestration?.phase);
5844
+ }
5845
+ function applyDefaultOrchestrationPhase(config) {
5846
+ if (!config.orchestration) {
5847
+ config.orchestration = {
5848
+ phase: "phase_1_coo",
5849
+ phaseSetAt: (/* @__PURE__ */ new Date()).toISOString(),
5850
+ phaseSetBy: "setup-default"
5851
+ };
5852
+ return config;
5853
+ }
5854
+ if (!config.orchestration.phase) {
5855
+ config.orchestration = {
5856
+ ...config.orchestration,
5857
+ phase: "phase_1_coo",
5858
+ phaseSetAt: config.orchestration.phaseSetAt ?? (/* @__PURE__ */ new Date()).toISOString(),
5859
+ phaseSetBy: config.orchestration.phaseSetBy ?? "setup-default"
5860
+ };
5861
+ }
5862
+ return config;
5863
+ }
5864
+ async function loadOrchestrationPhase() {
5865
+ const config = await loadConfig();
5866
+ return getOrchestrationPhaseInfo(config.orchestration?.phase);
5867
+ }
5868
+ async function setOrchestrationPhase(phaseInput, setBy = "user") {
5869
+ const config = await loadConfig();
5870
+ const phase = normalizeOrchestrationPhase(phaseInput);
5871
+ config.orchestration = {
5872
+ ...config.orchestration ?? {},
5873
+ phase,
5874
+ phaseSetAt: (/* @__PURE__ */ new Date()).toISOString(),
5875
+ phaseSetBy: setBy
5876
+ };
5877
+ await saveConfig(config);
5878
+ return getOrchestrationPhaseInfo(phase);
5879
+ }
5880
+ function phaseReminderLine(phase) {
5881
+ const info = getOrchestrationPhaseInfo(phase);
5882
+ return `${info.shortLabel}: ${info.focus}. ${info.nextSuggestion}`;
5883
+ }
5884
+ var ORCHESTRATION_PHASES, PHASE_INFO;
5885
+ var init_orchestration_phase = __esm({
5886
+ "src/lib/orchestration-phase.ts"() {
5887
+ "use strict";
5888
+ init_config();
5889
+ ORCHESTRATION_PHASES = [
5890
+ "phase_1_coo",
5891
+ "phase_2_executives",
5892
+ "phase_3_parallel_org"
5893
+ ];
5894
+ PHASE_INFO = {
5895
+ phase_1_coo: {
5896
+ phase: "phase_1_coo",
5897
+ shortLabel: "Phase 1 \u2014 COO mode",
5898
+ label: "Phase 1 \u2014 COO / Chief of Staff mode",
5899
+ focus: "building company context before delegation",
5900
+ nextSuggestion: "Unlock executives when technical, marketing, ops, legal, or finance work repeats."
5901
+ },
5902
+ phase_2_executives: {
5903
+ phase: "phase_2_executives",
5904
+ shortLabel: "Phase 2 \u2014 Executive bench",
5905
+ label: "Phase 2 \u2014 Executive bench",
5906
+ focus: "COO works with domain executives like CTO/CMO before specialist fan-out",
5907
+ nextSuggestion: "Unlock parallel execution when review gates, permissions, and workflows are ready."
5908
+ },
5909
+ phase_3_parallel_org: {
5910
+ phase: "phase_3_parallel_org",
5911
+ shortLabel: "Phase 3 \u2014 Parallel org",
5912
+ label: "Phase 3 \u2014 Parallel execution org",
5913
+ focus: "executives can delegate to specialists in parallel with review gates",
5914
+ nextSuggestion: "Keep review/CI/permission gates healthy; downgrade anytime if you want simpler COO-only mode."
5915
+ }
5916
+ };
5917
+ }
5918
+ });
5919
+
5739
5920
  // src/lib/preferences.ts
5740
5921
  var preferences_exports = {};
5741
5922
  __export(preferences_exports, {
5742
5923
  loadPreferences: () => loadPreferences,
5743
5924
  savePreferences: () => savePreferences
5744
5925
  });
5745
- import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
5746
- import path13 from "path";
5926
+ import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
5927
+ import path14 from "path";
5747
5928
  import os7 from "os";
5748
5929
  function loadPreferences(homeDir = os7.homedir()) {
5749
- const configPath = path13.join(homeDir, ".exe-os", "config.json");
5750
- if (!existsSync13(configPath)) return {};
5930
+ const configPath = path14.join(homeDir, ".exe-os", "config.json");
5931
+ if (!existsSync14(configPath)) return {};
5751
5932
  try {
5752
- const config = JSON.parse(readFileSync9(configPath, "utf-8"));
5933
+ const config = JSON.parse(readFileSync10(configPath, "utf-8"));
5753
5934
  return config.preferences ?? {};
5754
5935
  } catch {
5755
5936
  return {};
5756
5937
  }
5757
5938
  }
5758
5939
  function savePreferences(prefs, homeDir = os7.homedir()) {
5759
- const configDir = path13.join(homeDir, ".exe-os");
5760
- const configPath = path13.join(configDir, "config.json");
5940
+ const configDir = path14.join(homeDir, ".exe-os");
5941
+ const configPath = path14.join(configDir, "config.json");
5761
5942
  ensurePrivateDirSync(configDir);
5762
5943
  let config = {};
5763
- if (existsSync13(configPath)) {
5944
+ if (existsSync14(configPath)) {
5764
5945
  try {
5765
- config = JSON.parse(readFileSync9(configPath, "utf-8"));
5946
+ config = JSON.parse(readFileSync10(configPath, "utf-8"));
5766
5947
  } catch {
5767
5948
  config = {};
5768
5949
  }
5769
5950
  }
5770
5951
  config.preferences = prefs;
5771
- writeFileSync7(configPath, JSON.stringify(config, null, 2) + "\n");
5952
+ writeFileSync8(configPath, JSON.stringify(config, null, 2) + "\n");
5772
5953
  enforcePrivateFileSync(configPath);
5773
5954
  }
5774
5955
  var init_preferences = __esm({
@@ -5816,6 +5997,12 @@ var init_platform_procedures = __esm({
5816
5997
  priority: "p0",
5817
5998
  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."
5818
5999
  },
6000
+ {
6001
+ title: "Customer orchestration maturity \u2014 recommend, never trap",
6002
+ domain: "workflow",
6003
+ priority: "p1",
6004
+ 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."
6005
+ },
5819
6006
  {
5820
6007
  title: "Single dispatch path \u2014 create_task only",
5821
6008
  domain: "workflow",
@@ -5874,6 +6061,12 @@ var init_platform_procedures = __esm({
5874
6061
  priority: "p0",
5875
6062
  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."
5876
6063
  },
6064
+ {
6065
+ title: "Commit discipline \u2014 never leave verified work floating",
6066
+ domain: "workflow",
6067
+ priority: "p1",
6068
+ 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."
6069
+ },
5877
6070
  {
5878
6071
  title: "Desktop and TUI are the same product",
5879
6072
  domain: "architecture",
@@ -6641,17 +6834,17 @@ __export(identity_exports, {
6641
6834
  listIdentities: () => listIdentities,
6642
6835
  updateIdentity: () => updateIdentity
6643
6836
  });
6644
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
6837
+ import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
6645
6838
  import { readdirSync as readdirSync3 } from "fs";
6646
- import path14 from "path";
6839
+ import path15 from "path";
6647
6840
  import { createHash as createHash2 } from "crypto";
6648
6841
  function ensureDir() {
6649
- if (!existsSync14(IDENTITY_DIR2)) {
6650
- mkdirSync6(IDENTITY_DIR2, { recursive: true });
6842
+ if (!existsSync15(IDENTITY_DIR2)) {
6843
+ mkdirSync7(IDENTITY_DIR2, { recursive: true });
6651
6844
  }
6652
6845
  }
6653
6846
  function identityPath(agentId) {
6654
- return path14.join(IDENTITY_DIR2, `${agentId}.md`);
6847
+ return path15.join(IDENTITY_DIR2, `${agentId}.md`);
6655
6848
  }
6656
6849
  function sanitizeIdentityBody(body) {
6657
6850
  return body.replace(/<!--[\s\S]*?-->/g, "").trim();
@@ -6695,8 +6888,8 @@ function contentHash(content) {
6695
6888
  }
6696
6889
  function getIdentity(agentId) {
6697
6890
  const filePath = identityPath(agentId);
6698
- if (!existsSync14(filePath)) return null;
6699
- const raw = readFileSync10(filePath, "utf-8");
6891
+ if (!existsSync15(filePath)) return null;
6892
+ const raw = readFileSync11(filePath, "utf-8");
6700
6893
  const { frontmatter, body } = parseFrontmatter(raw);
6701
6894
  return {
6702
6895
  agentId,
@@ -6710,7 +6903,7 @@ async function updateIdentity(agentId, content, updatedBy) {
6710
6903
  ensureDir();
6711
6904
  const filePath = identityPath(agentId);
6712
6905
  const hash = contentHash(content);
6713
- writeFileSync8(filePath, content, "utf-8");
6906
+ writeFileSync9(filePath, content, "utf-8");
6714
6907
  try {
6715
6908
  const client = getClient();
6716
6909
  await client.execute({
@@ -6768,7 +6961,7 @@ var init_identity = __esm({
6768
6961
  "use strict";
6769
6962
  init_config();
6770
6963
  init_database();
6771
- IDENTITY_DIR2 = path14.join(EXE_AI_DIR, "identity");
6964
+ IDENTITY_DIR2 = path15.join(EXE_AI_DIR, "identity");
6772
6965
  }
6773
6966
  });
6774
6967
 
@@ -7319,36 +7512,36 @@ __export(session_wrappers_exports, {
7319
7512
  generateSessionWrappers: () => generateSessionWrappers
7320
7513
  });
7321
7514
  import {
7322
- existsSync as existsSync15,
7323
- readFileSync as readFileSync11,
7324
- writeFileSync as writeFileSync9,
7325
- mkdirSync as mkdirSync7,
7515
+ existsSync as existsSync16,
7516
+ readFileSync as readFileSync12,
7517
+ writeFileSync as writeFileSync10,
7518
+ mkdirSync as mkdirSync8,
7326
7519
  chmodSync as chmodSync2,
7327
7520
  readdirSync as readdirSync4,
7328
7521
  unlinkSync as unlinkSync7
7329
7522
  } from "fs";
7330
- import path15 from "path";
7523
+ import path16 from "path";
7331
7524
  import { homedir as homedir3 } from "os";
7332
7525
  function generateSessionWrappers(packageRoot, homeDir) {
7333
7526
  const home = homeDir ?? homedir3();
7334
- const binDir = path15.join(home, ".exe-os", "bin");
7335
- const rosterPath = path15.join(home, ".exe-os", "exe-employees.json");
7336
- mkdirSync7(binDir, { recursive: true });
7337
- const exeStartDst = path15.join(binDir, "exe-start");
7527
+ const binDir = path16.join(home, ".exe-os", "bin");
7528
+ const rosterPath = path16.join(home, ".exe-os", "exe-employees.json");
7529
+ mkdirSync8(binDir, { recursive: true });
7530
+ const exeStartDst = path16.join(binDir, "exe-start");
7338
7531
  const candidates = [
7339
- path15.join(packageRoot, "dist", "bin", "exe-start.sh"),
7340
- path15.join(packageRoot, "src", "bin", "exe-start.sh")
7532
+ path16.join(packageRoot, "dist", "bin", "exe-start.sh"),
7533
+ path16.join(packageRoot, "src", "bin", "exe-start.sh")
7341
7534
  ];
7342
7535
  for (const src of candidates) {
7343
- if (existsSync15(src)) {
7344
- writeFileSync9(exeStartDst, readFileSync11(src));
7536
+ if (existsSync16(src)) {
7537
+ writeFileSync10(exeStartDst, readFileSync12(src));
7345
7538
  chmodSync2(exeStartDst, 493);
7346
7539
  break;
7347
7540
  }
7348
7541
  }
7349
7542
  let employees = [];
7350
7543
  try {
7351
- employees = JSON.parse(readFileSync11(rosterPath, "utf8"));
7544
+ employees = JSON.parse(readFileSync12(rosterPath, "utf8"));
7352
7545
  } catch {
7353
7546
  return { created: 0, pathConfigured: false };
7354
7547
  }
@@ -7358,9 +7551,9 @@ function generateSessionWrappers(packageRoot, homeDir) {
7358
7551
  try {
7359
7552
  for (const f of readdirSync4(binDir)) {
7360
7553
  if (f === "exe-start") continue;
7361
- const fPath = path15.join(binDir, f);
7554
+ const fPath = path16.join(binDir, f);
7362
7555
  try {
7363
- const content = readFileSync11(fPath, "utf8");
7556
+ const content = readFileSync12(fPath, "utf8");
7364
7557
  if (content.includes("exe-start")) {
7365
7558
  unlinkSync7(fPath);
7366
7559
  }
@@ -7375,34 +7568,34 @@ exec "${exeStartDst}" "$0" "$@"
7375
7568
  `;
7376
7569
  for (const emp of employees) {
7377
7570
  for (let n = 1; n <= MAX_N; n++) {
7378
- const wrapperPath = path15.join(binDir, `${emp.name}${n}`);
7379
- writeFileSync9(wrapperPath, wrapperContent);
7571
+ const wrapperPath = path16.join(binDir, `${emp.name}${n}`);
7572
+ writeFileSync10(wrapperPath, wrapperContent);
7380
7573
  chmodSync2(wrapperPath, 493);
7381
7574
  created++;
7382
- const codexPath = path15.join(binDir, `${emp.name}${n}-codex`);
7383
- writeFileSync9(codexPath, wrapperContent);
7575
+ const codexPath = path16.join(binDir, `${emp.name}${n}-codex`);
7576
+ writeFileSync10(codexPath, wrapperContent);
7384
7577
  chmodSync2(codexPath, 493);
7385
7578
  created++;
7386
7579
  }
7387
7580
  }
7388
7581
  const codexLauncherCandidates = [
7389
- path15.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
7390
- path15.join(packageRoot, "src", "bin", "exe-start-codex.ts")
7582
+ path16.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
7583
+ path16.join(packageRoot, "src", "bin", "exe-start-codex.ts")
7391
7584
  ];
7392
7585
  let codexLauncher = null;
7393
7586
  for (const c of codexLauncherCandidates) {
7394
- if (existsSync15(c)) {
7587
+ if (existsSync16(c)) {
7395
7588
  codexLauncher = c;
7396
7589
  break;
7397
7590
  }
7398
7591
  }
7399
7592
  if (codexLauncher) {
7400
7593
  for (const emp of employees) {
7401
- const wrapperPath = path15.join(binDir, `${emp.name}-codex`);
7594
+ const wrapperPath = path16.join(binDir, `${emp.name}-codex`);
7402
7595
  const content = `#!/bin/bash
7403
7596
  exec node "${codexLauncher}" --agent ${emp.name} "$@"
7404
7597
  `;
7405
- writeFileSync9(wrapperPath, content);
7598
+ writeFileSync10(wrapperPath, content);
7406
7599
  chmodSync2(wrapperPath, 493);
7407
7600
  created++;
7408
7601
  }
@@ -7421,24 +7614,24 @@ export PATH="${binDir}:$PATH"
7421
7614
  const shell = process.env.SHELL ?? "/bin/bash";
7422
7615
  const profilePaths = [];
7423
7616
  if (shell.includes("zsh")) {
7424
- profilePaths.push(path15.join(home, ".zshrc"));
7617
+ profilePaths.push(path16.join(home, ".zshrc"));
7425
7618
  } else if (shell.includes("bash")) {
7426
- profilePaths.push(path15.join(home, ".bashrc"));
7427
- profilePaths.push(path15.join(home, ".bash_profile"));
7619
+ profilePaths.push(path16.join(home, ".bashrc"));
7620
+ profilePaths.push(path16.join(home, ".bash_profile"));
7428
7621
  } else {
7429
- profilePaths.push(path15.join(home, ".profile"));
7622
+ profilePaths.push(path16.join(home, ".profile"));
7430
7623
  }
7431
7624
  for (const profilePath of profilePaths) {
7432
7625
  try {
7433
7626
  let content = "";
7434
7627
  try {
7435
- content = readFileSync11(profilePath, "utf8");
7628
+ content = readFileSync12(profilePath, "utf8");
7436
7629
  } catch {
7437
7630
  }
7438
7631
  if (content.includes(".exe-os/bin")) {
7439
7632
  return false;
7440
7633
  }
7441
- writeFileSync9(profilePath, content + exportLine);
7634
+ writeFileSync10(profilePath, content + exportLine);
7442
7635
  return true;
7443
7636
  } catch {
7444
7637
  continue;
@@ -7458,9 +7651,9 @@ var init_session_wrappers = __esm({
7458
7651
  init_config();
7459
7652
  init_keychain();
7460
7653
  import crypto4 from "crypto";
7461
- import { existsSync as existsSync16, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync10, unlinkSync as unlinkSync8 } from "fs";
7654
+ import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync13, writeFileSync as writeFileSync11, unlinkSync as unlinkSync8 } from "fs";
7462
7655
  import os8 from "os";
7463
- import path16 from "path";
7656
+ import path17 from "path";
7464
7657
  import { createInterface } from "readline";
7465
7658
 
7466
7659
  // src/lib/model-downloader.ts
@@ -7552,32 +7745,32 @@ async function fileHash(filePath) {
7552
7745
 
7553
7746
  // src/lib/setup-wizard.ts
7554
7747
  function findPackageRoot2() {
7555
- let dir = path16.dirname(new URL(import.meta.url).pathname);
7556
- const root = path16.parse(dir).root;
7748
+ let dir = path17.dirname(new URL(import.meta.url).pathname);
7749
+ const root = path17.parse(dir).root;
7557
7750
  while (dir !== root) {
7558
- const pkgPath = path16.join(dir, "package.json");
7559
- if (existsSync16(pkgPath)) {
7751
+ const pkgPath = path17.join(dir, "package.json");
7752
+ if (existsSync17(pkgPath)) {
7560
7753
  try {
7561
- const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
7754
+ const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
7562
7755
  if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
7563
7756
  } catch {
7564
7757
  }
7565
7758
  }
7566
- dir = path16.dirname(dir);
7759
+ dir = path17.dirname(dir);
7567
7760
  }
7568
7761
  return null;
7569
7762
  }
7570
- var SETUP_STATE_PATH = path16.join(os8.homedir(), ".exe-os", "setup-state.json");
7763
+ var SETUP_STATE_PATH = path17.join(os8.homedir(), ".exe-os", "setup-state.json");
7571
7764
  function loadSetupState() {
7572
7765
  try {
7573
- return JSON.parse(readFileSync12(SETUP_STATE_PATH, "utf8"));
7766
+ return JSON.parse(readFileSync13(SETUP_STATE_PATH, "utf8"));
7574
7767
  } catch {
7575
7768
  return { completedSteps: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
7576
7769
  }
7577
7770
  }
7578
7771
  function saveSetupState(state) {
7579
- mkdirSync8(path16.dirname(SETUP_STATE_PATH), { recursive: true });
7580
- writeFileSync10(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
7772
+ mkdirSync9(path17.dirname(SETUP_STATE_PATH), { recursive: true });
7773
+ writeFileSync11(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
7581
7774
  }
7582
7775
  function clearSetupState() {
7583
7776
  try {
@@ -7627,8 +7820,8 @@ async function validateModel(log) {
7627
7820
  if (totalGB <= 8 || isLowMemory()) {
7628
7821
  log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
7629
7822
  log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
7630
- const modelPath = path16.join(MODELS_DIR, LOCAL_FILENAME);
7631
- if (existsSync16(modelPath)) {
7823
+ const modelPath = path17.join(MODELS_DIR, LOCAL_FILENAME);
7824
+ if (existsSync17(modelPath)) {
7632
7825
  const { statSync: statSync4 } = await import("fs");
7633
7826
  const size = statSync4(modelPath).size;
7634
7827
  if (size > 300 * 1e6) {
@@ -7659,10 +7852,10 @@ async function runSetupWizard(opts = {}) {
7659
7852
  log("");
7660
7853
  log("=== exe-os Setup ===");
7661
7854
  log("");
7662
- log("Is this a new installation or pairing with an existing device?");
7855
+ log("What are you setting up?");
7663
7856
  log("");
7664
- log(" [1] New installation (first device)");
7665
- log(" [2] Pair with existing device (I have a 24-word phrase)");
7857
+ log(" [1] First device / brand new Exe OS memory");
7858
+ log(" [2] Another device / I already have a 24-word recovery phrase");
7666
7859
  log("");
7667
7860
  const installType = await ask(rl, "Choice (1/2): ");
7668
7861
  let isPairing = false;
@@ -7671,16 +7864,20 @@ async function runSetupWizard(opts = {}) {
7671
7864
  isPairing = true;
7672
7865
  log("");
7673
7866
  const { importMnemonic: importMnemonic2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
7674
- const mnemonic = await ask(rl, "Paste your 24-word recovery phrase: ");
7867
+ log("On your existing device, open Terminal and run:");
7868
+ log(" exe-os cloud link --show-full");
7869
+ log("Then copy the 24-word phrase here.");
7870
+ log("");
7871
+ const mnemonic = await ask(rl, "Paste the 24-word recovery phrase: ");
7675
7872
  try {
7676
7873
  const key = await importMnemonic2(mnemonic);
7677
7874
  await setMasterKey(key);
7678
7875
  log("Master key imported and stored securely.");
7679
7876
  log("");
7680
- log("Enter the API key from your existing device.");
7681
- log("(Find it in ~/.exe-os/config.json under cloud.apiKey, or ask your team lead.)");
7877
+ log("Now paste the Cloud API key from that same `exe-os cloud link --show-full` output.");
7878
+ log("It starts with: exe_sk_");
7682
7879
  log("");
7683
- const apiKey = await ask(rl, "API key (exe_sk_...): ");
7880
+ const apiKey = await ask(rl, "Cloud API key (starts with exe_sk_): ");
7684
7881
  if (apiKey && apiKey.startsWith("exe_sk_")) {
7685
7882
  const cloudEndpoint = "https://askexe.com/cloud";
7686
7883
  const cloudCfg = { apiKey, endpoint: cloudEndpoint };
@@ -7719,7 +7916,7 @@ async function runSetupWizard(opts = {}) {
7719
7916
  if (state.completedSteps.length > 0) {
7720
7917
  log(`Resuming setup from step ${Math.max(...state.completedSteps) + 1}...`);
7721
7918
  }
7722
- if (existsSync16(LEGACY_LANCE_PATH)) {
7919
+ if (existsSync17(LEGACY_LANCE_PATH)) {
7723
7920
  log("\u26A0 Found v1.0 LanceDB at ~/.exe-os/local.lance");
7724
7921
  log(" v1.1 uses libSQL (SQLite). Your existing memories are not automatically migrated.");
7725
7922
  log(" The old directory will not be modified or deleted.");
@@ -7743,14 +7940,22 @@ async function runSetupWizard(opts = {}) {
7743
7940
  log("");
7744
7941
  log(" " + mnemonic);
7745
7942
  log("");
7746
- log(" SAVE THIS NOW. Write it down or store it in your password");
7747
- log(" manager. This phrase is the ONLY way to decrypt your memories");
7748
- log(" if you lose this computer. We cannot recover it for you.");
7943
+ log(" SAVE THIS NOW before continuing.");
7944
+ log(" Best: put it in your password manager, or write it down and keep it safe.");
7945
+ log(" This phrase is the ONLY way to decrypt your memories if you lose this computer.");
7946
+ log(" We cannot recover it for you.");
7749
7947
  log("");
7750
7948
  log(" Like a Bitcoin wallet \u2014 lose the phrase, lose everything.");
7751
7949
  log("=============================================================");
7752
7950
  log("");
7753
- await ask(rl, "Press Enter after you've saved your recovery phrase...");
7951
+ const confirmation = await ask(rl, 'Type "I SAVED MY RECOVERY PHRASE" after you have saved it: ');
7952
+ if (confirmation !== "I SAVED MY RECOVERY PHRASE") {
7953
+ throw new Error(
7954
+ "Setup cancelled: recovery phrase was not confirmed. Save the 24-word phrase before continuing \u2014 it is required to recover encrypted memories."
7955
+ );
7956
+ }
7957
+ const { markKeyBackupConfirmed: markKeyBackupConfirmed2 } = await Promise.resolve().then(() => (init_key_backup_status(), key_backup_status_exports));
7958
+ markKeyBackupConfirmed2("setup-wizard");
7754
7959
  }
7755
7960
  state.completedSteps.push(1);
7756
7961
  saveSetupState(state);
@@ -7897,13 +8102,15 @@ async function runSetupWizard(opts = {}) {
7897
8102
  if (cloudConfig) {
7898
8103
  config.cloud = cloudConfig;
7899
8104
  }
8105
+ const { applyDefaultOrchestrationPhase: applyDefaultOrchestrationPhase2 } = await Promise.resolve().then(() => (init_orchestration_phase(), orchestration_phase_exports));
8106
+ applyDefaultOrchestrationPhase2(config);
7900
8107
  await saveConfig(config);
7901
8108
  log("");
7902
8109
  try {
7903
- const claudeJsonPath = path16.join(os8.homedir(), ".claude.json");
8110
+ const claudeJsonPath = path17.join(os8.homedir(), ".claude.json");
7904
8111
  let claudeJson = {};
7905
8112
  try {
7906
- claudeJson = JSON.parse(readFileSync12(claudeJsonPath, "utf8"));
8113
+ claudeJson = JSON.parse(readFileSync13(claudeJsonPath, "utf8"));
7907
8114
  } catch {
7908
8115
  }
7909
8116
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -7912,7 +8119,7 @@ async function runSetupWizard(opts = {}) {
7912
8119
  if (!projects[dir]) projects[dir] = {};
7913
8120
  projects[dir].hasTrustDialogAccepted = true;
7914
8121
  }
7915
- writeFileSync10(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
8122
+ writeFileSync11(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
7916
8123
  } catch {
7917
8124
  }
7918
8125
  state.completedSteps.push(5);
@@ -7926,7 +8133,7 @@ async function runSetupWizard(opts = {}) {
7926
8133
  const prefs = { ...existingPrefs };
7927
8134
  log("=== Config Defaults ===");
7928
8135
  log("");
7929
- const ghosttyDetected = existsSync16(path16.join(os8.homedir(), ".config", "ghostty")) || existsSync16(path16.join(os8.homedir(), "Library", "Application Support", "com.mitchellh.ghostty"));
8136
+ const ghosttyDetected = existsSync17(path17.join(os8.homedir(), ".config", "ghostty")) || existsSync17(path17.join(os8.homedir(), "Library", "Application Support", "com.mitchellh.ghostty"));
7930
8137
  if (ghosttyDetected) {
7931
8138
  const ghosttyAnswer = await ask(rl, "Detected Ghostty terminal. Use exe-os Ghostty defaults? (Y/n) ");
7932
8139
  prefs.ghostty = ghosttyAnswer.toLowerCase() !== "n";
@@ -7973,7 +8180,7 @@ async function runSetupWizard(opts = {}) {
7973
8180
  let missingIdentities = [];
7974
8181
  for (const emp of roster) {
7975
8182
  const idPath = identityPath2(emp.name);
7976
- if (!existsSync16(idPath)) {
8183
+ if (!existsSync17(idPath)) {
7977
8184
  missingIdentities.push(emp.name);
7978
8185
  }
7979
8186
  }
@@ -8005,7 +8212,7 @@ async function runSetupWizard(opts = {}) {
8005
8212
  }
8006
8213
  missingIdentities = [];
8007
8214
  for (const emp of roster) {
8008
- if (!existsSync16(identityPath2(emp.name))) {
8215
+ if (!existsSync17(identityPath2(emp.name))) {
8009
8216
  missingIdentities.push(emp.name);
8010
8217
  }
8011
8218
  }
@@ -8064,9 +8271,9 @@ async function runSetupWizard(opts = {}) {
8064
8271
  const cooIdentityContent = getIdentityTemplate("coo");
8065
8272
  if (cooIdentityContent) {
8066
8273
  const cooIdPath = identityPath2(cooName);
8067
- mkdirSync8(path16.dirname(cooIdPath), { recursive: true });
8274
+ mkdirSync9(path17.dirname(cooIdPath), { recursive: true });
8068
8275
  const replaced = cooIdentityContent.replace(/agent_id:\s*exe/g, `agent_id: ${cooName}`).replace(/\$\{agent_id\}/g, cooName);
8069
- writeFileSync10(cooIdPath, replaced, "utf-8");
8276
+ writeFileSync11(cooIdPath, replaced, "utf-8");
8070
8277
  }
8071
8278
  registerBinSymlinks2(cooName);
8072
8279
  createdEmployees.push({ name: cooName, role: "COO" });
@@ -8117,7 +8324,8 @@ async function runSetupWizard(opts = {}) {
8117
8324
  }
8118
8325
  if (!isLicensed) {
8119
8326
  log("");
8120
- log("You're all set. Your COO handles everything from here.");
8327
+ log("You're all set. You're starting in Phase 1: COO / Chief of Staff mode.");
8328
+ log("Your COO will learn your company context first. You can unlock executives later anytime.");
8121
8329
  log("When you're ready for specialists, add a license key at askexe.com.");
8122
8330
  log("");
8123
8331
  log(`Type your COO's name to start: /${cooName}`);
@@ -8132,67 +8340,89 @@ async function runSetupWizard(opts = {}) {
8132
8340
  }
8133
8341
  if (!state.completedSteps.includes(8)) {
8134
8342
  let employees = await loadEmployees2(EMPLOYEES_PATH2).catch(() => []);
8135
- log("=== Hire Your Team ===");
8343
+ log("=== Orchestration Phase ===");
8136
8344
  log("");
8137
- log("Your COO coordinates specialists. Each one stays focused on");
8138
- log("their domain \u2014 no context switching, no competing priorities.");
8345
+ log("Recommended default: Phase 1 \u2014 COO / Chief of Staff mode.");
8346
+ log("Start with one-on-one conversations so your COO learns your company,");
8347
+ log("vision, priorities, constraints, and operating style before delegating.");
8139
8348
  log("");
8140
- const ctoTemplate = getTemplateByRole2("CTO");
8141
- const ctoDefault = ctoTemplate?.name ?? "cto";
8142
- log(` CTO \u2014 engineering, architecture, code reviews (default: ${ctoDefault})`);
8143
- const cmoTemplate = getTemplateByRole2("CMO");
8144
- const cmoDefault = cmoTemplate?.name ?? "cmo";
8145
- log(` CMO \u2014 design, brand, content, marketing (default: ${cmoDefault})`);
8349
+ log("You can jump ahead now if you want. This is a suggestion, not a blocker.");
8146
8350
  log("");
8147
- const ctoNameInput = await ask(rl, `Name your CTO (default: ${ctoDefault}): `);
8148
- const ctoName = (ctoNameInput || ctoDefault).toLowerCase();
8149
- if (!employees.some((e) => e.name === ctoName)) {
8150
- const ctoEmployee = {
8151
- name: ctoName,
8152
- role: "CTO",
8153
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
8154
- templateName: ctoDefault,
8155
- templateVersion: 1
8156
- };
8157
- employees = addEmployee2(employees, ctoEmployee);
8158
- await saveEmployees2(employees, EMPLOYEES_PATH2);
8159
- }
8160
- const ctoIdentityContent = getIdentityTemplate("cto");
8161
- if (ctoIdentityContent) {
8162
- const ctoIdPath = identityPath2(ctoName);
8163
- mkdirSync8(path16.dirname(ctoIdPath), { recursive: true });
8164
- const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
8165
- writeFileSync10(ctoIdPath, replaced, "utf-8");
8166
- }
8167
- registerBinSymlinks2(ctoName);
8168
- createdEmployees.push({ name: ctoName, role: "CTO" });
8169
- log(`Created ${ctoName} (CTO)`);
8170
- const cmoNameInput = await ask(rl, `Name your CMO (default: ${cmoDefault}): `);
8171
- const cmoName = (cmoNameInput || cmoDefault).toLowerCase();
8172
- if (!employees.some((e) => e.name === cmoName)) {
8173
- const cmoEmployee = {
8174
- name: cmoName,
8175
- role: "CMO",
8176
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
8177
- templateName: cmoDefault,
8178
- templateVersion: 1
8179
- };
8180
- employees = addEmployee2(employees, cmoEmployee);
8181
- await saveEmployees2(employees, EMPLOYEES_PATH2);
8182
- }
8183
- const cmoIdentityContent = getIdentityTemplate("cmo");
8184
- if (cmoIdentityContent) {
8185
- const cmoIdPath = identityPath2(cmoName);
8186
- mkdirSync8(path16.dirname(cmoIdPath), { recursive: true });
8187
- const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
8188
- writeFileSync10(cmoIdPath, replaced, "utf-8");
8189
- }
8190
- registerBinSymlinks2(cmoName);
8191
- createdEmployees.push({ name: cmoName, role: "CMO" });
8192
- log(`Created ${cmoName} (CMO)`);
8351
+ log(" Phase 1: COO only \u2014 build company context first");
8352
+ log(" Phase 2: Executive bench \u2014 add CTO/CMO for repeated domain work");
8353
+ log(" Phase 3: Parallel org \u2014 specialists execute in parallel with reviews");
8193
8354
  log("");
8194
- state.completedSteps.push(8);
8195
- saveSetupState(state);
8355
+ const unlockExecutives = (await ask(rl, "Unlock Phase 2 executives now? (y/N): ")).toLowerCase() === "y";
8356
+ const { setOrchestrationPhase: setOrchestrationPhase2 } = await Promise.resolve().then(() => (init_orchestration_phase(), orchestration_phase_exports));
8357
+ if (!unlockExecutives) {
8358
+ await setOrchestrationPhase2("phase_1_coo", "setup-wizard");
8359
+ log("");
8360
+ log("Starting in Phase 1. Your executive templates are available when you're ready.");
8361
+ log("Later: run `exe-os org unlock executives` to move to Phase 2.");
8362
+ state.completedSteps.push(8);
8363
+ saveSetupState(state);
8364
+ } else {
8365
+ await setOrchestrationPhase2("phase_2_executives", "setup-wizard");
8366
+ log("");
8367
+ log("Phase 2 enabled. Let's name your executive bench.");
8368
+ log("");
8369
+ const ctoTemplate = getTemplateByRole2("CTO");
8370
+ const ctoDefault = ctoTemplate?.name ?? "cto";
8371
+ log(` CTO \u2014 engineering, architecture, code reviews (default: ${ctoDefault})`);
8372
+ const cmoTemplate = getTemplateByRole2("CMO");
8373
+ const cmoDefault = cmoTemplate?.name ?? "cmo";
8374
+ log(` CMO \u2014 design, brand, content, marketing (default: ${cmoDefault})`);
8375
+ log("");
8376
+ const ctoNameInput = await ask(rl, `Name your CTO (default: ${ctoDefault}): `);
8377
+ const ctoName = (ctoNameInput || ctoDefault).toLowerCase();
8378
+ if (!employees.some((e) => e.name === ctoName)) {
8379
+ const ctoEmployee = {
8380
+ name: ctoName,
8381
+ role: "CTO",
8382
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
8383
+ templateName: ctoDefault,
8384
+ templateVersion: 1
8385
+ };
8386
+ employees = addEmployee2(employees, ctoEmployee);
8387
+ await saveEmployees2(employees, EMPLOYEES_PATH2);
8388
+ }
8389
+ const ctoIdentityContent = getIdentityTemplate("cto");
8390
+ if (ctoIdentityContent) {
8391
+ const ctoIdPath = identityPath2(ctoName);
8392
+ mkdirSync9(path17.dirname(ctoIdPath), { recursive: true });
8393
+ const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
8394
+ writeFileSync11(ctoIdPath, replaced, "utf-8");
8395
+ }
8396
+ registerBinSymlinks2(ctoName);
8397
+ createdEmployees.push({ name: ctoName, role: "CTO" });
8398
+ log(`Created ${ctoName} (CTO)`);
8399
+ const cmoNameInput = await ask(rl, `Name your CMO (default: ${cmoDefault}): `);
8400
+ const cmoName = (cmoNameInput || cmoDefault).toLowerCase();
8401
+ if (!employees.some((e) => e.name === cmoName)) {
8402
+ const cmoEmployee = {
8403
+ name: cmoName,
8404
+ role: "CMO",
8405
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
8406
+ templateName: cmoDefault,
8407
+ templateVersion: 1
8408
+ };
8409
+ employees = addEmployee2(employees, cmoEmployee);
8410
+ await saveEmployees2(employees, EMPLOYEES_PATH2);
8411
+ }
8412
+ const cmoIdentityContent = getIdentityTemplate("cmo");
8413
+ if (cmoIdentityContent) {
8414
+ const cmoIdPath = identityPath2(cmoName);
8415
+ mkdirSync9(path17.dirname(cmoIdPath), { recursive: true });
8416
+ const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
8417
+ writeFileSync11(cmoIdPath, replaced, "utf-8");
8418
+ }
8419
+ registerBinSymlinks2(cmoName);
8420
+ createdEmployees.push({ name: cmoName, role: "CMO" });
8421
+ log(`Created ${cmoName} (CMO)`);
8422
+ log("");
8423
+ state.completedSteps.push(8);
8424
+ saveSetupState(state);
8425
+ }
8196
8426
  } else {
8197
8427
  log("Step 8 already complete \u2014 skipping.");
8198
8428
  }
@@ -8207,7 +8437,7 @@ async function runSetupWizard(opts = {}) {
8207
8437
  log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
8208
8438
  }
8209
8439
  if (wrapResult.pathConfigured) {
8210
- const binDir = path16.join(os8.homedir(), ".exe-os", "bin");
8440
+ const binDir = path17.join(os8.homedir(), ".exe-os", "bin");
8211
8441
  process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
8212
8442
  pathJustConfigured = true;
8213
8443
  }
@@ -8250,7 +8480,7 @@ async function runSetupWizard(opts = {}) {
8250
8480
  const pkgRoot2 = findPackageRoot2();
8251
8481
  if (pkgRoot2) {
8252
8482
  try {
8253
- version = JSON.parse(readFileSync12(path16.join(pkgRoot2, "package.json"), "utf-8")).version;
8483
+ version = JSON.parse(readFileSync13(path17.join(pkgRoot2, "package.json"), "utf-8")).version;
8254
8484
  } catch {
8255
8485
  }
8256
8486
  }
@@ -8264,6 +8494,10 @@ async function runSetupWizard(opts = {}) {
8264
8494
  log("");
8265
8495
  log("=== Next Steps ===");
8266
8496
  log("");
8497
+ log(" Recommended start: Phase 1 \u2014 talk to your COO first");
8498
+ log(" Check/change phase: exe-os org phase");
8499
+ log(" Unlock executives later: exe-os org unlock executives");
8500
+ log("");
8267
8501
  log(` cd into a project folder: cd ~/my-project`);
8268
8502
  log(` Launch your COO: ${cooName}1`);
8269
8503
  if (pathJustConfigured) {