@askexenow/exe-os 0.8.65 → 0.8.69

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 (54) hide show
  1. package/dist/bin/cleanup-stale-review-tasks.js +8 -7
  2. package/dist/bin/cli.js +204 -120
  3. package/dist/bin/exe-assign.js +11 -10
  4. package/dist/bin/exe-boot.js +83 -78
  5. package/dist/bin/exe-call.js +33 -1
  6. package/dist/bin/exe-cloud.js +3 -2
  7. package/dist/bin/exe-dispatch.js +31 -30
  8. package/dist/bin/exe-gateway.js +33 -32
  9. package/dist/bin/exe-heartbeat.js +21 -20
  10. package/dist/bin/exe-launch-agent.js +84 -19
  11. package/dist/bin/exe-link.js +16 -11
  12. package/dist/bin/exe-new-employee.js +20 -19
  13. package/dist/bin/exe-pending-messages.js +7 -6
  14. package/dist/bin/exe-pending-reviews.js +16 -15
  15. package/dist/bin/exe-rename.js +12 -11
  16. package/dist/bin/exe-review.js +4 -3
  17. package/dist/bin/exe-session-cleanup.js +20 -19
  18. package/dist/bin/exe-settings.js +3 -2
  19. package/dist/bin/exe-status.js +16 -15
  20. package/dist/bin/exe-team.js +4 -3
  21. package/dist/bin/git-sweep.js +31 -30
  22. package/dist/bin/install.js +284 -113
  23. package/dist/bin/scan-tasks.js +33 -32
  24. package/dist/bin/setup.js +114 -30
  25. package/dist/gateway/index.js +32 -31
  26. package/dist/hooks/bug-report-worker.js +58 -26
  27. package/dist/hooks/commit-complete.js +31 -30
  28. package/dist/hooks/ingest-worker.js +58 -57
  29. package/dist/hooks/post-compact.js +10 -9
  30. package/dist/hooks/pre-compact.js +31 -30
  31. package/dist/hooks/pre-tool-use.js +46 -14
  32. package/dist/hooks/prompt-ingest-worker.js +15 -14
  33. package/dist/hooks/prompt-submit.js +15 -14
  34. package/dist/hooks/response-ingest-worker.js +8 -7
  35. package/dist/hooks/session-end.js +14 -13
  36. package/dist/hooks/session-start.js +10 -9
  37. package/dist/hooks/stop.js +10 -9
  38. package/dist/hooks/subagent-stop.js +10 -9
  39. package/dist/hooks/summary-worker.js +41 -36
  40. package/dist/index.js +43 -42
  41. package/dist/lib/cloud-sync.js +16 -11
  42. package/dist/lib/employees.js +33 -1
  43. package/dist/lib/exe-daemon.js +56 -55
  44. package/dist/lib/messaging.js +9 -8
  45. package/dist/lib/tasks.js +27 -26
  46. package/dist/lib/tmux-routing.js +29 -28
  47. package/dist/mcp/server.js +94 -62
  48. package/dist/mcp/tools/create-task.js +60 -28
  49. package/dist/mcp/tools/list-tasks.js +10 -9
  50. package/dist/mcp/tools/send-message.js +11 -10
  51. package/dist/mcp/tools/update-task.js +21 -20
  52. package/dist/runtime/index.js +31 -30
  53. package/dist/tui/App.js +67 -35
  54. package/package.json +1 -1
@@ -1,29 +1,13 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/adapters/claude/installer.ts
4
- import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
5
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync, copyFileSync, mkdirSync as mkdirSync2 } from "fs";
6
- import path4 from "path";
7
- import os3 from "os";
8
- import { execSync as execSync2 } from "child_process";
9
- import { fileURLToPath } from "url";
10
-
11
- // src/lib/agent-symlinks.ts
12
- import os2 from "os";
13
- import path3 from "path";
14
- import {
15
- existsSync as existsSync3,
16
- lstatSync,
17
- mkdirSync,
18
- readlinkSync as readlinkSync2,
19
- symlinkSync as symlinkSync2
20
- } from "fs";
21
-
22
- // src/lib/employees.ts
23
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
24
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2 } from "fs";
25
- import { execSync } from "child_process";
26
- import path2 from "path";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
27
11
 
28
12
  // src/lib/config.ts
29
13
  import { readFile, writeFile, mkdir, chmod } from "fs/promises";
@@ -46,78 +30,119 @@ function resolveDataDir() {
46
30
  }
47
31
  return newDir;
48
32
  }
49
- var EXE_AI_DIR = resolveDataDir();
50
- var DB_PATH = path.join(EXE_AI_DIR, "memories.db");
51
- var MODELS_DIR = path.join(EXE_AI_DIR, "models");
52
- var CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
53
- var LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
54
- var CURRENT_CONFIG_VERSION = 1;
55
- var DEFAULT_CONFIG = {
56
- config_version: CURRENT_CONFIG_VERSION,
57
- dbPath: DB_PATH,
58
- modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
59
- embeddingDim: 1024,
60
- batchSize: 20,
61
- flushIntervalMs: 1e4,
62
- autoIngestion: true,
63
- autoRetrieval: true,
64
- searchMode: "hybrid",
65
- hookSearchMode: "hybrid",
66
- fileGrepEnabled: true,
67
- splashEffect: true,
68
- consolidationEnabled: true,
69
- consolidationIntervalMs: 6 * 60 * 60 * 1e3,
70
- consolidationModel: "claude-haiku-4-5-20251001",
71
- consolidationMaxCallsPerRun: 20,
72
- selfQueryRouter: true,
73
- selfQueryModel: "claude-haiku-4-5-20251001",
74
- rerankerEnabled: true,
75
- scalingRoadmap: {
76
- rerankerAutoTrigger: {
77
- enabled: true,
78
- broadQueryMinCardinality: 5e4,
79
- fetchTopK: 150,
80
- returnTopK: 5
81
- }
82
- },
83
- graphRagEnabled: true,
84
- wikiEnabled: false,
85
- wikiUrl: "",
86
- wikiApiKey: "",
87
- wikiSyncIntervalMs: 30 * 60 * 1e3,
88
- wikiWorkspaceMapping: {
89
- exe: "Executive",
90
- yoshi: "Engineering",
91
- mari: "Marketing",
92
- tom: "Engineering",
93
- sasha: "Production"
94
- },
95
- wikiAutoUpdate: true,
96
- wikiAutoUpdateThreshold: 0.5,
97
- wikiAutoUpdateCreateNew: true,
98
- skillLearning: true,
99
- skillThreshold: 3,
100
- skillModel: "claude-haiku-4-5-20251001",
101
- exeHeartbeat: {
102
- enabled: true,
103
- intervalSeconds: 60,
104
- staleInProgressThresholdHours: 2
105
- },
106
- sessionLifecycle: {
107
- idleKillEnabled: true,
108
- idleKillTicksRequired: 3,
109
- idleKillIntercomAckWindowMs: 1e4,
110
- maxAutoInstances: 10
111
- },
112
- autoUpdate: {
113
- checkOnBoot: true,
114
- autoInstall: false,
115
- checkIntervalMs: 24 * 60 * 60 * 1e3
33
+ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG;
34
+ var init_config = __esm({
35
+ "src/lib/config.ts"() {
36
+ "use strict";
37
+ EXE_AI_DIR = resolveDataDir();
38
+ DB_PATH = path.join(EXE_AI_DIR, "memories.db");
39
+ MODELS_DIR = path.join(EXE_AI_DIR, "models");
40
+ CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
41
+ LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
42
+ CURRENT_CONFIG_VERSION = 1;
43
+ DEFAULT_CONFIG = {
44
+ config_version: CURRENT_CONFIG_VERSION,
45
+ dbPath: DB_PATH,
46
+ modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
47
+ embeddingDim: 1024,
48
+ batchSize: 20,
49
+ flushIntervalMs: 1e4,
50
+ autoIngestion: true,
51
+ autoRetrieval: true,
52
+ searchMode: "hybrid",
53
+ hookSearchMode: "hybrid",
54
+ fileGrepEnabled: true,
55
+ splashEffect: true,
56
+ consolidationEnabled: true,
57
+ consolidationIntervalMs: 6 * 60 * 60 * 1e3,
58
+ consolidationModel: "claude-haiku-4-5-20251001",
59
+ consolidationMaxCallsPerRun: 20,
60
+ selfQueryRouter: true,
61
+ selfQueryModel: "claude-haiku-4-5-20251001",
62
+ rerankerEnabled: true,
63
+ scalingRoadmap: {
64
+ rerankerAutoTrigger: {
65
+ enabled: true,
66
+ broadQueryMinCardinality: 5e4,
67
+ fetchTopK: 150,
68
+ returnTopK: 5
69
+ }
70
+ },
71
+ graphRagEnabled: true,
72
+ wikiEnabled: false,
73
+ wikiUrl: "",
74
+ wikiApiKey: "",
75
+ wikiSyncIntervalMs: 30 * 60 * 1e3,
76
+ wikiWorkspaceMapping: {
77
+ exe: "Executive",
78
+ yoshi: "Engineering",
79
+ mari: "Marketing",
80
+ tom: "Engineering",
81
+ sasha: "Production"
82
+ },
83
+ wikiAutoUpdate: true,
84
+ wikiAutoUpdateThreshold: 0.5,
85
+ wikiAutoUpdateCreateNew: true,
86
+ skillLearning: true,
87
+ skillThreshold: 3,
88
+ skillModel: "claude-haiku-4-5-20251001",
89
+ exeHeartbeat: {
90
+ enabled: true,
91
+ intervalSeconds: 60,
92
+ staleInProgressThresholdHours: 2
93
+ },
94
+ sessionLifecycle: {
95
+ idleKillEnabled: true,
96
+ idleKillTicksRequired: 3,
97
+ idleKillIntercomAckWindowMs: 1e4,
98
+ maxAutoInstances: 10
99
+ },
100
+ autoUpdate: {
101
+ checkOnBoot: true,
102
+ autoInstall: false,
103
+ checkIntervalMs: 24 * 60 * 60 * 1e3
104
+ }
105
+ };
116
106
  }
117
- };
107
+ });
118
108
 
119
109
  // src/lib/employees.ts
120
- var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
110
+ var employees_exports = {};
111
+ __export(employees_exports, {
112
+ EMPLOYEES_PATH: () => EMPLOYEES_PATH,
113
+ addEmployee: () => addEmployee,
114
+ getEmployee: () => getEmployee,
115
+ getEmployeeByRole: () => getEmployeeByRole,
116
+ getEmployeeNamesByRole: () => getEmployeeNamesByRole,
117
+ hasRole: () => hasRole,
118
+ isMultiInstance: () => isMultiInstance,
119
+ loadEmployees: () => loadEmployees,
120
+ loadEmployeesSync: () => loadEmployeesSync,
121
+ normalizeRosterCase: () => normalizeRosterCase,
122
+ registerBinSymlinks: () => registerBinSymlinks,
123
+ saveEmployees: () => saveEmployees,
124
+ validateEmployeeName: () => validateEmployeeName
125
+ });
126
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
127
+ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
128
+ import { execSync } from "child_process";
129
+ import path2 from "path";
130
+ import os2 from "os";
131
+ function validateEmployeeName(name) {
132
+ if (!name) {
133
+ return { valid: false, error: "Name is required" };
134
+ }
135
+ if (name.length > 32) {
136
+ return { valid: false, error: "Name must be 32 characters or fewer" };
137
+ }
138
+ if (!/^[a-z][a-z0-9]*$/.test(name)) {
139
+ return {
140
+ valid: false,
141
+ error: "Name must start with a letter and contain only lowercase alphanumeric characters"
142
+ };
143
+ }
144
+ return { valid: true };
145
+ }
121
146
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
122
147
  if (!existsSync2(employeesPath)) {
123
148
  return [];
@@ -129,8 +154,146 @@ async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
129
154
  return [];
130
155
  }
131
156
  }
157
+ async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
158
+ await mkdir2(path2.dirname(employeesPath), { recursive: true });
159
+ await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
160
+ }
161
+ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
162
+ if (!existsSync2(employeesPath)) return [];
163
+ try {
164
+ return JSON.parse(readFileSync2(employeesPath, "utf-8"));
165
+ } catch {
166
+ return [];
167
+ }
168
+ }
169
+ function getEmployee(employees, name) {
170
+ return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
171
+ }
172
+ function getEmployeeByRole(employees, role) {
173
+ const lower = role.toLowerCase();
174
+ return employees.find((e) => e.role.toLowerCase() === lower);
175
+ }
176
+ function getEmployeeNamesByRole(employees, role) {
177
+ const lower = role.toLowerCase();
178
+ return employees.filter((e) => e.role.toLowerCase() === lower).map((e) => e.name);
179
+ }
180
+ function hasRole(agentName, role) {
181
+ const employees = loadEmployeesSync();
182
+ const emp = getEmployee(employees, agentName);
183
+ return emp ? emp.role.toLowerCase() === role.toLowerCase() : false;
184
+ }
185
+ function isMultiInstance(agentName, employees) {
186
+ const roster = employees ?? loadEmployeesSync();
187
+ const emp = getEmployee(roster, agentName);
188
+ if (!emp) return false;
189
+ return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
190
+ }
191
+ function addEmployee(employees, employee) {
192
+ const normalized = { ...employee, name: employee.name.toLowerCase() };
193
+ if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
194
+ throw new Error(`Employee '${normalized.name}' already exists`);
195
+ }
196
+ return [...employees, normalized];
197
+ }
198
+ async function normalizeRosterCase(rosterPath) {
199
+ const employees = await loadEmployees(rosterPath);
200
+ let changed = false;
201
+ for (const emp of employees) {
202
+ if (emp.name !== emp.name.toLowerCase()) {
203
+ const oldName = emp.name;
204
+ emp.name = emp.name.toLowerCase();
205
+ changed = true;
206
+ try {
207
+ const identityDir = path2.join(os2.homedir(), ".exe-os", "identity");
208
+ const oldPath = path2.join(identityDir, `${oldName}.md`);
209
+ const newPath = path2.join(identityDir, `${emp.name}.md`);
210
+ if (existsSync2(oldPath) && !existsSync2(newPath)) {
211
+ renameSync2(oldPath, newPath);
212
+ } else if (existsSync2(oldPath) && oldPath !== newPath) {
213
+ const content = readFileSync2(oldPath, "utf-8");
214
+ writeFileSync(newPath, content, "utf-8");
215
+ if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
216
+ unlinkSync(oldPath);
217
+ }
218
+ }
219
+ } catch {
220
+ }
221
+ }
222
+ }
223
+ if (changed) {
224
+ await saveEmployees(employees, rosterPath);
225
+ }
226
+ return changed;
227
+ }
228
+ function findExeBin() {
229
+ try {
230
+ return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
231
+ } catch {
232
+ return null;
233
+ }
234
+ }
235
+ function registerBinSymlinks(name) {
236
+ const created = [];
237
+ const skipped = [];
238
+ const errors = [];
239
+ const exeBinPath = findExeBin();
240
+ if (!exeBinPath) {
241
+ errors.push("Could not find 'exe-os' in PATH");
242
+ return { created, skipped, errors };
243
+ }
244
+ const binDir = path2.dirname(exeBinPath);
245
+ let target;
246
+ try {
247
+ target = readlinkSync(exeBinPath);
248
+ } catch {
249
+ errors.push("Could not read 'exe' symlink");
250
+ return { created, skipped, errors };
251
+ }
252
+ for (const suffix of ["", "-opencode"]) {
253
+ const linkName = `${name}${suffix}`;
254
+ const linkPath = path2.join(binDir, linkName);
255
+ if (existsSync2(linkPath)) {
256
+ skipped.push(linkName);
257
+ continue;
258
+ }
259
+ try {
260
+ symlinkSync(target, linkPath);
261
+ created.push(linkName);
262
+ } catch (err) {
263
+ errors.push(`${linkName}: ${err instanceof Error ? err.message : String(err)}`);
264
+ }
265
+ }
266
+ return { created, skipped, errors };
267
+ }
268
+ var EMPLOYEES_PATH, MULTI_INSTANCE_ROLES;
269
+ var init_employees = __esm({
270
+ "src/lib/employees.ts"() {
271
+ "use strict";
272
+ init_config();
273
+ EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
274
+ MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
275
+ }
276
+ });
277
+
278
+ // src/adapters/claude/installer.ts
279
+ import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
280
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, copyFileSync, mkdirSync as mkdirSync2 } from "fs";
281
+ import path4 from "path";
282
+ import os4 from "os";
283
+ import { execSync as execSync2 } from "child_process";
284
+ import { fileURLToPath } from "url";
132
285
 
133
286
  // src/lib/agent-symlinks.ts
287
+ init_employees();
288
+ import os3 from "os";
289
+ import path3 from "path";
290
+ import {
291
+ existsSync as existsSync3,
292
+ lstatSync,
293
+ mkdirSync,
294
+ readlinkSync as readlinkSync2,
295
+ symlinkSync as symlinkSync2
296
+ } from "fs";
134
297
  function claudeAgentsDir(homeDir) {
135
298
  return path3.join(homeDir, ".claude", "agents");
136
299
  }
@@ -140,7 +303,7 @@ function identitySourcePath(homeDir, agentId) {
140
303
  function claudeAgentLinkPath(homeDir, agentId) {
141
304
  return path3.join(claudeAgentsDir(homeDir), `${agentId}.md`);
142
305
  }
143
- function ensureAgentSymlink(agentId, homeDir = os2.homedir()) {
306
+ function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
144
307
  const target = identitySourcePath(homeDir, agentId);
145
308
  const link = claudeAgentLinkPath(homeDir, agentId);
146
309
  mkdirSync(claudeAgentsDir(homeDir), { recursive: true });
@@ -178,7 +341,7 @@ function ensureAgentSymlink(agentId, homeDir = os2.homedir()) {
178
341
  }
179
342
  return { agentId, action: "created", target, link };
180
343
  }
181
- async function ensureAllAgentSymlinks(homeDir = os2.homedir()) {
344
+ async function ensureAllAgentSymlinks(homeDir = os3.homedir()) {
182
345
  const employees = await loadEmployees();
183
346
  return employees.map((emp) => ensureAgentSymlink(emp.name, homeDir));
184
347
  }
@@ -218,7 +381,7 @@ function resolvePackageRoot() {
218
381
  }
219
382
  return path4.resolve(path4.dirname(thisFile), "..", "..", "..");
220
383
  }
221
- async function copySlashCommands(packageRoot, homeDir = os3.homedir()) {
384
+ async function copySlashCommands(packageRoot, homeDir = os4.homedir()) {
222
385
  let copied = 0;
223
386
  let skipped = 0;
224
387
  const skillsBase = path4.join(homeDir, ".claude", "skills");
@@ -271,7 +434,7 @@ name: ${skillName}
271
434
  await writeFile3(destPath, content);
272
435
  return true;
273
436
  }
274
- async function registerMcpServer(packageRoot, homeDir = os3.homedir()) {
437
+ async function registerMcpServer(packageRoot, homeDir = os4.homedir()) {
275
438
  const claudeJsonPath = path4.join(homeDir, ".claude.json");
276
439
  let claudeJson = {};
277
440
  if (existsSync4(claudeJsonPath)) {
@@ -303,7 +466,7 @@ async function registerMcpServer(packageRoot, homeDir = os3.homedir()) {
303
466
  await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
304
467
  return true;
305
468
  }
306
- async function mergeHooks(packageRoot, homeDir = os3.homedir()) {
469
+ async function mergeHooks(packageRoot, homeDir = os4.homedir()) {
307
470
  const settingsPath = path4.join(homeDir, ".claude", "settings.json");
308
471
  let settings = {};
309
472
  if (existsSync4(settingsPath)) {
@@ -631,7 +794,7 @@ async function runInstaller(homeDir) {
631
794
  `Hooks: ${hookResult.added} added, ${hookResult.skipped} unchanged
632
795
  `
633
796
  );
634
- const resolvedHome = homeDir ?? os3.homedir();
797
+ const resolvedHome = homeDir ?? os4.homedir();
635
798
  const exeWorkspace = path4.join(resolvedHome, "exe");
636
799
  if (!existsSync4(exeWorkspace)) {
637
800
  try {
@@ -660,7 +823,7 @@ exe-os installed successfully.
660
823
  `);
661
824
  }
662
825
  function setupTmux(home) {
663
- const homeDir = home ?? os3.homedir();
826
+ const homeDir = home ?? os4.homedir();
664
827
  const exeDir = path4.join(homeDir, ".exe-os");
665
828
  const exeTmuxConf = path4.join(exeDir, "tmux.conf");
666
829
  const userTmuxConf = path4.join(homeDir, ".tmux.conf");
@@ -683,11 +846,11 @@ function setupTmux(home) {
683
846
  process.stderr.write(`exe-os: backed up existing tmux config to ${backupPath}
684
847
  `);
685
848
  }
686
- writeFileSync(userTmuxConf, `${sourceLine}
849
+ writeFileSync2(userTmuxConf, `${sourceLine}
687
850
  ${existing}`);
688
851
  }
689
852
  } else {
690
- writeFileSync(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
853
+ writeFileSync2(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
691
854
  ${sourceLine}
692
855
  `);
693
856
  }
@@ -711,7 +874,7 @@ function summarizeSymlinkResults(results) {
711
874
  }
712
875
 
713
876
  // src/bin/install.ts
714
- import { existsSync as existsSync6, readFileSync as readFileSync5, unlinkSync as unlinkSync2, readdirSync as readdirSync2, openSync, closeSync } from "fs";
877
+ import { existsSync as existsSync6, readFileSync as readFileSync5, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
715
878
  import { spawn, execSync as execSync3 } from "child_process";
716
879
  import path6 from "path";
717
880
  import { homedir as homedir2 } from "os";
@@ -720,11 +883,11 @@ import { homedir as homedir2 } from "os";
720
883
  import {
721
884
  existsSync as existsSync5,
722
885
  readFileSync as readFileSync4,
723
- writeFileSync as writeFileSync2,
886
+ writeFileSync as writeFileSync3,
724
887
  mkdirSync as mkdirSync3,
725
888
  chmodSync,
726
889
  readdirSync,
727
- unlinkSync
890
+ unlinkSync as unlinkSync2
728
891
  } from "fs";
729
892
  import path5 from "path";
730
893
  import { homedir } from "os";
@@ -741,7 +904,7 @@ function generateSessionWrappers(packageRoot, homeDir) {
741
904
  ];
742
905
  for (const src of candidates) {
743
906
  if (existsSync5(src)) {
744
- writeFileSync2(exeStartDst, readFileSync4(src));
907
+ writeFileSync3(exeStartDst, readFileSync4(src));
745
908
  chmodSync(exeStartDst, 493);
746
909
  break;
747
910
  }
@@ -762,7 +925,7 @@ function generateSessionWrappers(packageRoot, homeDir) {
762
925
  try {
763
926
  const content = readFileSync4(fPath, "utf8");
764
927
  if (content.includes("exe-start")) {
765
- unlinkSync(fPath);
928
+ unlinkSync2(fPath);
766
929
  }
767
930
  } catch {
768
931
  }
@@ -776,7 +939,7 @@ exec "${exeStartDst}" "$0" "$@"
776
939
  for (const emp of employees) {
777
940
  for (let n = 1; n <= MAX_N; n++) {
778
941
  const wrapperPath = path5.join(binDir, `${emp.name}${n}`);
779
- writeFileSync2(wrapperPath, wrapperContent);
942
+ writeFileSync3(wrapperPath, wrapperContent);
780
943
  chmodSync(wrapperPath, 493);
781
944
  created++;
782
945
  }
@@ -812,7 +975,7 @@ export PATH="${binDir}:$PATH"
812
975
  if (content.includes(".exe-os/bin")) {
813
976
  return false;
814
977
  }
815
- writeFileSync2(profilePath, content + exportLine);
978
+ writeFileSync3(profilePath, content + exportLine);
816
979
  return true;
817
980
  } catch {
818
981
  continue;
@@ -836,7 +999,7 @@ function restartDaemon() {
836
999
  }
837
1000
  }
838
1001
  try {
839
- unlinkSync2(pidPath);
1002
+ unlinkSync3(pidPath);
840
1003
  } catch {
841
1004
  }
842
1005
  }
@@ -873,7 +1036,7 @@ function restartDaemon() {
873
1036
  if (existsSync6(wpDir)) {
874
1037
  for (const f of readdirSync2(wpDir)) {
875
1038
  try {
876
- unlinkSync2(path6.join(wpDir, f));
1039
+ unlinkSync3(path6.join(wpDir, f));
877
1040
  } catch {
878
1041
  }
879
1042
  }
@@ -881,7 +1044,7 @@ function restartDaemon() {
881
1044
  } catch {
882
1045
  }
883
1046
  try {
884
- unlinkSync2(sockPath);
1047
+ unlinkSync3(sockPath);
885
1048
  } catch {
886
1049
  }
887
1050
  try {
@@ -944,6 +1107,14 @@ if (args.includes("--commands-only")) {
944
1107
  try {
945
1108
  await runInstaller();
946
1109
  setupTmux();
1110
+ try {
1111
+ const { normalizeRosterCase: normalizeRosterCase2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
1112
+ const changed = await normalizeRosterCase2();
1113
+ if (changed) {
1114
+ process.stderr.write("exe-os: normalized employee names to lowercase\n");
1115
+ }
1116
+ } catch {
1117
+ }
947
1118
  try {
948
1119
  const pkgRoot = resolvePackageRoot();
949
1120
  const wrapResult = generateSessionWrappers(pkgRoot);