@askexenow/exe-os 0.9.7 → 0.9.8

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 (95) hide show
  1. package/dist/bin/backfill-conversations.js +754 -79
  2. package/dist/bin/backfill-responses.js +752 -77
  3. package/dist/bin/backfill-vectors.js +752 -77
  4. package/dist/bin/cleanup-stale-review-tasks.js +657 -35
  5. package/dist/bin/cli.js +1388 -605
  6. package/dist/bin/exe-agent-config.js +123 -95
  7. package/dist/bin/exe-agent.js +41 -25
  8. package/dist/bin/exe-assign.js +732 -57
  9. package/dist/bin/exe-boot.js +784 -153
  10. package/dist/bin/exe-call.js +209 -138
  11. package/dist/bin/exe-cloud.js +35 -12
  12. package/dist/bin/exe-dispatch.js +692 -70
  13. package/dist/bin/exe-doctor.js +648 -26
  14. package/dist/bin/exe-export-behaviors.js +650 -20
  15. package/dist/bin/exe-forget.js +635 -13
  16. package/dist/bin/exe-gateway.js +1053 -271
  17. package/dist/bin/exe-heartbeat.js +665 -43
  18. package/dist/bin/exe-kill.js +646 -16
  19. package/dist/bin/exe-launch-agent.js +887 -97
  20. package/dist/bin/exe-link.js +658 -43
  21. package/dist/bin/exe-new-employee.js +378 -177
  22. package/dist/bin/exe-pending-messages.js +656 -34
  23. package/dist/bin/exe-pending-notifications.js +635 -13
  24. package/dist/bin/exe-pending-reviews.js +659 -37
  25. package/dist/bin/exe-rename.js +645 -30
  26. package/dist/bin/exe-review.js +635 -13
  27. package/dist/bin/exe-search.js +771 -88
  28. package/dist/bin/exe-session-cleanup.js +834 -150
  29. package/dist/bin/exe-settings.js +127 -91
  30. package/dist/bin/exe-start-codex.js +729 -94
  31. package/dist/bin/exe-start-opencode.js +717 -82
  32. package/dist/bin/exe-status.js +657 -35
  33. package/dist/bin/exe-team.js +635 -13
  34. package/dist/bin/git-sweep.js +720 -89
  35. package/dist/bin/graph-backfill.js +643 -13
  36. package/dist/bin/graph-export.js +646 -16
  37. package/dist/bin/install.js +596 -193
  38. package/dist/bin/scan-tasks.js +724 -93
  39. package/dist/bin/setup.js +1038 -210
  40. package/dist/bin/shard-migrate.js +645 -15
  41. package/dist/bin/wiki-sync.js +646 -16
  42. package/dist/gateway/index.js +1027 -245
  43. package/dist/hooks/bug-report-worker.js +891 -170
  44. package/dist/hooks/commit-complete.js +718 -87
  45. package/dist/hooks/error-recall.js +776 -93
  46. package/dist/hooks/exe-heartbeat-hook.js +85 -71
  47. package/dist/hooks/ingest-worker.js +840 -156
  48. package/dist/hooks/ingest.js +90 -73
  49. package/dist/hooks/instructions-loaded.js +669 -38
  50. package/dist/hooks/notification.js +661 -30
  51. package/dist/hooks/post-compact.js +674 -43
  52. package/dist/hooks/pre-compact.js +718 -87
  53. package/dist/hooks/pre-tool-use.js +872 -125
  54. package/dist/hooks/prompt-ingest-worker.js +758 -83
  55. package/dist/hooks/prompt-submit.js +1060 -319
  56. package/dist/hooks/response-ingest-worker.js +758 -83
  57. package/dist/hooks/session-end.js +721 -90
  58. package/dist/hooks/session-start.js +1031 -207
  59. package/dist/hooks/stop.js +680 -49
  60. package/dist/hooks/subagent-stop.js +674 -43
  61. package/dist/hooks/summary-worker.js +816 -132
  62. package/dist/index.js +1015 -232
  63. package/dist/lib/cloud-sync.js +663 -48
  64. package/dist/lib/consolidation.js +26 -3
  65. package/dist/lib/database.js +626 -18
  66. package/dist/lib/db.js +2261 -0
  67. package/dist/lib/device-registry.js +640 -25
  68. package/dist/lib/embedder.js +96 -43
  69. package/dist/lib/employee-templates.js +16 -0
  70. package/dist/lib/employees.js +259 -83
  71. package/dist/lib/exe-daemon-client.js +101 -63
  72. package/dist/lib/exe-daemon.js +894 -162
  73. package/dist/lib/hybrid-search.js +771 -88
  74. package/dist/lib/identity.js +27 -7
  75. package/dist/lib/messaging.js +55 -28
  76. package/dist/lib/reminders.js +21 -1
  77. package/dist/lib/schedules.js +636 -14
  78. package/dist/lib/skill-learning.js +21 -1
  79. package/dist/lib/store.js +643 -13
  80. package/dist/lib/task-router.js +82 -71
  81. package/dist/lib/tasks.js +98 -71
  82. package/dist/lib/tmux-routing.js +87 -60
  83. package/dist/lib/token-spend.js +26 -6
  84. package/dist/mcp/server.js +1784 -458
  85. package/dist/mcp/tools/complete-reminder.js +21 -1
  86. package/dist/mcp/tools/create-reminder.js +21 -1
  87. package/dist/mcp/tools/create-task.js +290 -164
  88. package/dist/mcp/tools/deactivate-behavior.js +24 -4
  89. package/dist/mcp/tools/list-reminders.js +21 -1
  90. package/dist/mcp/tools/list-tasks.js +195 -38
  91. package/dist/mcp/tools/send-message.js +58 -31
  92. package/dist/mcp/tools/update-task.js +75 -48
  93. package/dist/runtime/index.js +720 -89
  94. package/dist/tui/App.js +853 -123
  95. package/package.json +3 -2
@@ -368,7 +368,7 @@ function registerBinSymlinks(name) {
368
368
  }
369
369
  return { created, skipped, errors };
370
370
  }
371
- var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES;
371
+ var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES, IDENTITY_DIR;
372
372
  var init_employees = __esm({
373
373
  "src/lib/employees.ts"() {
374
374
  "use strict";
@@ -377,6 +377,7 @@ var init_employees = __esm({
377
377
  DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
378
378
  COORDINATOR_ROLE = "COO";
379
379
  MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
380
+ IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
380
381
  }
381
382
  });
382
383
 
@@ -435,13 +436,597 @@ var init_db_retry = __esm({
435
436
  }
436
437
  });
437
438
 
439
+ // src/lib/database-adapter.ts
440
+ import os3 from "os";
441
+ import path3 from "path";
442
+ import { createRequire } from "module";
443
+ import { pathToFileURL } from "url";
444
+ function quotedIdentifier(identifier) {
445
+ return `"${identifier.replace(/"/g, '""')}"`;
446
+ }
447
+ function unqualifiedTableName(name) {
448
+ const raw = name.trim().replace(/^"|"$/g, "");
449
+ const parts = raw.split(".");
450
+ return parts[parts.length - 1].replace(/^"|"$/g, "").toLowerCase();
451
+ }
452
+ function stripTrailingSemicolon(sql) {
453
+ return sql.trim().replace(/;+\s*$/u, "");
454
+ }
455
+ function appendClause(sql, clause) {
456
+ const trimmed = stripTrailingSemicolon(sql);
457
+ const returningMatch = /\sRETURNING\b[\s\S]*$/iu.exec(trimmed);
458
+ if (!returningMatch) {
459
+ return `${trimmed}${clause}`;
460
+ }
461
+ const idx = returningMatch.index;
462
+ return `${trimmed.slice(0, idx)}${clause}${trimmed.slice(idx)}`;
463
+ }
464
+ function normalizeStatement(stmt) {
465
+ if (typeof stmt === "string") {
466
+ return { kind: "positional", sql: stmt, args: [] };
467
+ }
468
+ const sql = stmt.sql;
469
+ if (Array.isArray(stmt.args) || stmt.args === void 0) {
470
+ return { kind: "positional", sql, args: stmt.args ?? [] };
471
+ }
472
+ return { kind: "named", sql, args: stmt.args };
473
+ }
474
+ function rewriteBooleanLiterals(sql) {
475
+ let out = sql;
476
+ for (const column of BOOLEAN_COLUMN_NAMES) {
477
+ const scoped = `((?:\\b[a-z_][a-z0-9_]*\\.)?${column})`;
478
+ out = out.replace(new RegExp(`${scoped}\\s*=\\s*0\\b`, "giu"), "$1 = FALSE");
479
+ out = out.replace(new RegExp(`${scoped}\\s*=\\s*1\\b`, "giu"), "$1 = TRUE");
480
+ out = out.replace(new RegExp(`${scoped}\\s*!=\\s*0\\b`, "giu"), "$1 != FALSE");
481
+ out = out.replace(new RegExp(`${scoped}\\s*!=\\s*1\\b`, "giu"), "$1 != TRUE");
482
+ out = out.replace(new RegExp(`${scoped}\\s*<>\\s*0\\b`, "giu"), "$1 <> FALSE");
483
+ out = out.replace(new RegExp(`${scoped}\\s*<>\\s*1\\b`, "giu"), "$1 <> TRUE");
484
+ }
485
+ return out;
486
+ }
487
+ function rewriteInsertOrIgnore(sql) {
488
+ if (!/^\s*INSERT\s+OR\s+IGNORE\s+INTO\b/iu.test(sql)) {
489
+ return sql;
490
+ }
491
+ const replaced = sql.replace(/^\s*INSERT\s+OR\s+IGNORE\s+INTO\b/iu, "INSERT INTO");
492
+ return /\bON\s+CONFLICT\b/iu.test(replaced) ? replaced : appendClause(replaced, " ON CONFLICT DO NOTHING");
493
+ }
494
+ function rewriteInsertOrReplace(sql) {
495
+ const match = /^\s*INSERT\s+OR\s+REPLACE\s+INTO\s+([A-Za-z0-9_."]+)\s*\(([^)]+)\)([\s\S]*)$/iu.exec(sql);
496
+ if (!match) {
497
+ return sql;
498
+ }
499
+ const rawTable = match[1];
500
+ const rawColumns = match[2];
501
+ const remainder = match[3];
502
+ const tableName = unqualifiedTableName(rawTable);
503
+ const conflictKeys = UPSERT_KEYS[tableName];
504
+ if (!conflictKeys?.length) {
505
+ return sql;
506
+ }
507
+ const columns = rawColumns.split(",").map((col) => col.trim().replace(/^"|"$/g, ""));
508
+ const updateColumns = columns.filter((col) => !conflictKeys.includes(col));
509
+ const conflictTarget = conflictKeys.map(quotedIdentifier).join(", ");
510
+ const updateClause = updateColumns.length === 0 ? " DO NOTHING" : ` DO UPDATE SET ${updateColumns.map((col) => `${quotedIdentifier(col)} = EXCLUDED.${quotedIdentifier(col)}`).join(", ")}`;
511
+ return `INSERT INTO ${rawTable} (${rawColumns})${appendClause(remainder, ` ON CONFLICT (${conflictTarget})${updateClause}`)}`;
512
+ }
513
+ function rewriteSql(sql) {
514
+ let out = sql;
515
+ out = out.replace(/\bdatetime\(\s*['"]now['"]\s*\)/giu, "CURRENT_TIMESTAMP");
516
+ out = out.replace(/\bvector32\s*\(\s*\?\s*\)/giu, "?");
517
+ out = rewriteBooleanLiterals(out);
518
+ out = rewriteInsertOrReplace(out);
519
+ out = rewriteInsertOrIgnore(out);
520
+ return stripTrailingSemicolon(out);
521
+ }
522
+ function toBoolean(value) {
523
+ if (value === null || value === void 0) return value;
524
+ if (typeof value === "boolean") return value;
525
+ if (typeof value === "number") return value !== 0;
526
+ if (typeof value === "bigint") return value !== 0n;
527
+ if (typeof value === "string") {
528
+ const normalized = value.trim().toLowerCase();
529
+ if (normalized === "0" || normalized === "false") return false;
530
+ if (normalized === "1" || normalized === "true") return true;
531
+ }
532
+ return Boolean(value);
533
+ }
534
+ function countQuestionMarks(sql, end) {
535
+ let count = 0;
536
+ let inSingle = false;
537
+ let inDouble = false;
538
+ let inLineComment = false;
539
+ let inBlockComment = false;
540
+ for (let i = 0; i < end; i++) {
541
+ const ch = sql[i];
542
+ const next = sql[i + 1];
543
+ if (inLineComment) {
544
+ if (ch === "\n") inLineComment = false;
545
+ continue;
546
+ }
547
+ if (inBlockComment) {
548
+ if (ch === "*" && next === "/") {
549
+ inBlockComment = false;
550
+ i += 1;
551
+ }
552
+ continue;
553
+ }
554
+ if (!inSingle && !inDouble && ch === "-" && next === "-") {
555
+ inLineComment = true;
556
+ i += 1;
557
+ continue;
558
+ }
559
+ if (!inSingle && !inDouble && ch === "/" && next === "*") {
560
+ inBlockComment = true;
561
+ i += 1;
562
+ continue;
563
+ }
564
+ if (!inDouble && ch === "'" && sql[i - 1] !== "\\") {
565
+ inSingle = !inSingle;
566
+ continue;
567
+ }
568
+ if (!inSingle && ch === '"' && sql[i - 1] !== "\\") {
569
+ inDouble = !inDouble;
570
+ continue;
571
+ }
572
+ if (!inSingle && !inDouble && ch === "?") {
573
+ count += 1;
574
+ }
575
+ }
576
+ return count;
577
+ }
578
+ function findBooleanPlaceholderIndexes(sql) {
579
+ const indexes = /* @__PURE__ */ new Set();
580
+ for (const column of BOOLEAN_COLUMN_NAMES) {
581
+ const pattern = new RegExp(`(?:\\b[a-z_][a-z0-9_]*\\.)?${column}\\s*=\\s*\\?`, "giu");
582
+ for (const match of sql.matchAll(pattern)) {
583
+ const matchText = match[0];
584
+ const qIndex = match.index + matchText.lastIndexOf("?");
585
+ indexes.add(countQuestionMarks(sql, qIndex + 1));
586
+ }
587
+ }
588
+ return indexes;
589
+ }
590
+ function coerceInsertBooleanArgs(sql, args) {
591
+ const match = /^\s*INSERT(?:\s+OR\s+(?:IGNORE|REPLACE))?\s+INTO\s+([A-Za-z0-9_."]+)\s*\(([^)]+)\)/iu.exec(sql);
592
+ if (!match) return;
593
+ const rawTable = match[1];
594
+ const rawColumns = match[2];
595
+ const boolColumns = BOOLEAN_COLUMNS_BY_TABLE[unqualifiedTableName(rawTable)];
596
+ if (!boolColumns?.size) return;
597
+ const columns = rawColumns.split(",").map((col) => col.trim().replace(/^"|"$/g, ""));
598
+ for (const [index, column] of columns.entries()) {
599
+ if (boolColumns.has(column) && index < args.length) {
600
+ args[index] = toBoolean(args[index]);
601
+ }
602
+ }
603
+ }
604
+ function coerceUpdateBooleanArgs(sql, args) {
605
+ const match = /^\s*UPDATE\s+([A-Za-z0-9_."]+)\s+SET\s+([\s\S]+?)(?:\s+WHERE\b|$)/iu.exec(sql);
606
+ if (!match) return;
607
+ const rawTable = match[1];
608
+ const setClause = match[2];
609
+ const boolColumns = BOOLEAN_COLUMNS_BY_TABLE[unqualifiedTableName(rawTable)];
610
+ if (!boolColumns?.size) return;
611
+ const assignments = setClause.split(",");
612
+ let placeholderIndex = 0;
613
+ for (const assignment of assignments) {
614
+ if (!assignment.includes("?")) continue;
615
+ placeholderIndex += 1;
616
+ const colMatch = /^\s*(?:[A-Za-z_][A-Za-z0-9_]*\.)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*\?/iu.exec(assignment);
617
+ if (colMatch && boolColumns.has(colMatch[1])) {
618
+ args[placeholderIndex - 1] = toBoolean(args[placeholderIndex - 1]);
619
+ }
620
+ }
621
+ }
622
+ function coerceBooleanArgs(sql, args) {
623
+ const nextArgs = [...args];
624
+ coerceInsertBooleanArgs(sql, nextArgs);
625
+ coerceUpdateBooleanArgs(sql, nextArgs);
626
+ const placeholderIndexes = findBooleanPlaceholderIndexes(sql);
627
+ for (const index of placeholderIndexes) {
628
+ if (index > 0 && index <= nextArgs.length) {
629
+ nextArgs[index - 1] = toBoolean(nextArgs[index - 1]);
630
+ }
631
+ }
632
+ return nextArgs;
633
+ }
634
+ function convertQuestionMarksToDollarParams(sql) {
635
+ let out = "";
636
+ let placeholder = 0;
637
+ let inSingle = false;
638
+ let inDouble = false;
639
+ let inLineComment = false;
640
+ let inBlockComment = false;
641
+ for (let i = 0; i < sql.length; i++) {
642
+ const ch = sql[i];
643
+ const next = sql[i + 1];
644
+ if (inLineComment) {
645
+ out += ch;
646
+ if (ch === "\n") inLineComment = false;
647
+ continue;
648
+ }
649
+ if (inBlockComment) {
650
+ out += ch;
651
+ if (ch === "*" && next === "/") {
652
+ out += next;
653
+ inBlockComment = false;
654
+ i += 1;
655
+ }
656
+ continue;
657
+ }
658
+ if (!inSingle && !inDouble && ch === "-" && next === "-") {
659
+ out += ch + next;
660
+ inLineComment = true;
661
+ i += 1;
662
+ continue;
663
+ }
664
+ if (!inSingle && !inDouble && ch === "/" && next === "*") {
665
+ out += ch + next;
666
+ inBlockComment = true;
667
+ i += 1;
668
+ continue;
669
+ }
670
+ if (!inDouble && ch === "'" && sql[i - 1] !== "\\") {
671
+ inSingle = !inSingle;
672
+ out += ch;
673
+ continue;
674
+ }
675
+ if (!inSingle && ch === '"' && sql[i - 1] !== "\\") {
676
+ inDouble = !inDouble;
677
+ out += ch;
678
+ continue;
679
+ }
680
+ if (!inSingle && !inDouble && ch === "?") {
681
+ placeholder += 1;
682
+ out += `$${placeholder}`;
683
+ continue;
684
+ }
685
+ out += ch;
686
+ }
687
+ return out;
688
+ }
689
+ function translateStatementForPostgres(stmt) {
690
+ const normalized = normalizeStatement(stmt);
691
+ if (normalized.kind === "named") {
692
+ throw new Error("Named SQL parameters are not supported by the Prisma adapter.");
693
+ }
694
+ const rewrittenSql = rewriteSql(normalized.sql);
695
+ const coercedArgs = coerceBooleanArgs(rewrittenSql, normalized.args);
696
+ return {
697
+ sql: convertQuestionMarksToDollarParams(rewrittenSql),
698
+ args: coercedArgs
699
+ };
700
+ }
701
+ function shouldBypassPostgres(stmt) {
702
+ const normalized = normalizeStatement(stmt);
703
+ if (normalized.kind === "named") {
704
+ return true;
705
+ }
706
+ return IMMEDIATE_FALLBACK_PATTERNS.some((pattern) => pattern.test(normalized.sql));
707
+ }
708
+ function shouldFallbackOnError(error) {
709
+ const message = error instanceof Error ? error.message : String(error);
710
+ return /42P01|42883|42601|does not exist|syntax error|not supported|Named SQL parameters are not supported/iu.test(message);
711
+ }
712
+ function isReadQuery(sql) {
713
+ const trimmed = sql.trimStart();
714
+ return /^(SELECT|WITH|SHOW|EXPLAIN|VALUES)\b/iu.test(trimmed) || /\bRETURNING\b/iu.test(trimmed);
715
+ }
716
+ function buildRow(row, columns) {
717
+ const values = columns.map((column) => row[column]);
718
+ return Object.assign(values, row);
719
+ }
720
+ function buildResultSet(rows, rowsAffected = 0) {
721
+ const columns = rows[0] ? Object.keys(rows[0]) : [];
722
+ const resultRows = rows.map((row) => buildRow(row, columns));
723
+ return {
724
+ columns,
725
+ columnTypes: columns.map(() => ""),
726
+ rows: resultRows,
727
+ rowsAffected,
728
+ lastInsertRowid: void 0,
729
+ toJSON() {
730
+ return {
731
+ columns,
732
+ columnTypes: columns.map(() => ""),
733
+ rows,
734
+ rowsAffected,
735
+ lastInsertRowid: void 0
736
+ };
737
+ }
738
+ };
739
+ }
740
+ async function loadPrismaClient() {
741
+ if (!prismaClientPromise) {
742
+ prismaClientPromise = (async () => {
743
+ const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
744
+ if (explicitPath) {
745
+ const module2 = await import(pathToFileURL(explicitPath).href);
746
+ const PrismaClient2 = module2.PrismaClient ?? module2.default?.PrismaClient;
747
+ if (!PrismaClient2) {
748
+ throw new Error(`No PrismaClient export found at ${explicitPath}`);
749
+ }
750
+ return new PrismaClient2();
751
+ }
752
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path3.join(os3.homedir(), "exe-db");
753
+ const requireFromExeDb = createRequire(path3.join(exeDbRoot, "package.json"));
754
+ const prismaEntry = requireFromExeDb.resolve("@prisma/client");
755
+ const module = await import(pathToFileURL(prismaEntry).href);
756
+ const PrismaClient = module.PrismaClient ?? module.default?.PrismaClient;
757
+ if (!PrismaClient) {
758
+ throw new Error(`No PrismaClient export found in ${prismaEntry}`);
759
+ }
760
+ return new PrismaClient();
761
+ })();
762
+ }
763
+ return prismaClientPromise;
764
+ }
765
+ async function ensureCompatibilityViews(prisma) {
766
+ if (!compatibilityBootstrapPromise) {
767
+ compatibilityBootstrapPromise = (async () => {
768
+ for (const mapping of VIEW_MAPPINGS) {
769
+ const relation = mapping.source.replace(/"/g, "");
770
+ const rows = await prisma.$queryRawUnsafe(
771
+ "SELECT to_regclass($1) AS regclass",
772
+ relation
773
+ );
774
+ if (!rows[0]?.regclass) {
775
+ continue;
776
+ }
777
+ await prisma.$executeRawUnsafe(
778
+ `CREATE OR REPLACE VIEW public.${quotedIdentifier(mapping.view)} AS SELECT * FROM ${mapping.source}`
779
+ );
780
+ }
781
+ })();
782
+ }
783
+ return compatibilityBootstrapPromise;
784
+ }
785
+ async function executeOnPrisma(executor, stmt) {
786
+ const translated = translateStatementForPostgres(stmt);
787
+ if (isReadQuery(translated.sql)) {
788
+ const rows = await executor.$queryRawUnsafe(
789
+ translated.sql,
790
+ ...translated.args
791
+ );
792
+ return buildResultSet(rows, /\bRETURNING\b/iu.test(translated.sql) ? rows.length : 0);
793
+ }
794
+ const rowsAffected = await executor.$executeRawUnsafe(translated.sql, ...translated.args);
795
+ return buildResultSet([], rowsAffected);
796
+ }
797
+ function splitSqlStatements(sql) {
798
+ const parts = [];
799
+ let current = "";
800
+ let inSingle = false;
801
+ let inDouble = false;
802
+ let inLineComment = false;
803
+ let inBlockComment = false;
804
+ for (let i = 0; i < sql.length; i++) {
805
+ const ch = sql[i];
806
+ const next = sql[i + 1];
807
+ if (inLineComment) {
808
+ current += ch;
809
+ if (ch === "\n") inLineComment = false;
810
+ continue;
811
+ }
812
+ if (inBlockComment) {
813
+ current += ch;
814
+ if (ch === "*" && next === "/") {
815
+ current += next;
816
+ inBlockComment = false;
817
+ i += 1;
818
+ }
819
+ continue;
820
+ }
821
+ if (!inSingle && !inDouble && ch === "-" && next === "-") {
822
+ current += ch + next;
823
+ inLineComment = true;
824
+ i += 1;
825
+ continue;
826
+ }
827
+ if (!inSingle && !inDouble && ch === "/" && next === "*") {
828
+ current += ch + next;
829
+ inBlockComment = true;
830
+ i += 1;
831
+ continue;
832
+ }
833
+ if (!inDouble && ch === "'" && sql[i - 1] !== "\\") {
834
+ inSingle = !inSingle;
835
+ current += ch;
836
+ continue;
837
+ }
838
+ if (!inSingle && ch === '"' && sql[i - 1] !== "\\") {
839
+ inDouble = !inDouble;
840
+ current += ch;
841
+ continue;
842
+ }
843
+ if (!inSingle && !inDouble && ch === ";") {
844
+ if (current.trim()) {
845
+ parts.push(current.trim());
846
+ }
847
+ current = "";
848
+ continue;
849
+ }
850
+ current += ch;
851
+ }
852
+ if (current.trim()) {
853
+ parts.push(current.trim());
854
+ }
855
+ return parts;
856
+ }
857
+ async function createPrismaDbAdapter(fallbackClient) {
858
+ const prisma = await loadPrismaClient();
859
+ await ensureCompatibilityViews(prisma);
860
+ let closed = false;
861
+ let adapter;
862
+ const fallbackExecute = async (stmt, error) => {
863
+ if (!fallbackClient) {
864
+ if (error) throw error;
865
+ throw new Error("No fallback SQLite client is available for this Prisma-routed query.");
866
+ }
867
+ if (error) {
868
+ process.stderr.write(
869
+ `[database-adapter] Falling back to SQLite: ${error instanceof Error ? error.message : String(error)}
870
+ `
871
+ );
872
+ }
873
+ return fallbackClient.execute(stmt);
874
+ };
875
+ adapter = {
876
+ async execute(stmt) {
877
+ if (shouldBypassPostgres(stmt)) {
878
+ return fallbackExecute(stmt);
879
+ }
880
+ try {
881
+ return await executeOnPrisma(prisma, stmt);
882
+ } catch (error) {
883
+ if (shouldFallbackOnError(error)) {
884
+ return fallbackExecute(stmt, error);
885
+ }
886
+ throw error;
887
+ }
888
+ },
889
+ async batch(stmts, mode) {
890
+ if (stmts.some((stmt) => shouldBypassPostgres(stmt))) {
891
+ if (!fallbackClient) {
892
+ throw new Error("Cannot batch unsupported SQLite-only statements without a fallback client.");
893
+ }
894
+ return fallbackClient.batch(stmts, mode);
895
+ }
896
+ try {
897
+ if (prisma.$transaction) {
898
+ return await prisma.$transaction(async (tx) => {
899
+ const results2 = [];
900
+ for (const stmt of stmts) {
901
+ results2.push(await executeOnPrisma(tx, stmt));
902
+ }
903
+ return results2;
904
+ });
905
+ }
906
+ const results = [];
907
+ for (const stmt of stmts) {
908
+ results.push(await executeOnPrisma(prisma, stmt));
909
+ }
910
+ return results;
911
+ } catch (error) {
912
+ if (fallbackClient && shouldFallbackOnError(error)) {
913
+ process.stderr.write(
914
+ `[database-adapter] Falling back batch to SQLite: ${error instanceof Error ? error.message : String(error)}
915
+ `
916
+ );
917
+ return fallbackClient.batch(stmts, mode);
918
+ }
919
+ throw error;
920
+ }
921
+ },
922
+ async migrate(stmts) {
923
+ if (fallbackClient) {
924
+ return fallbackClient.migrate(stmts);
925
+ }
926
+ return adapter.batch(stmts, "deferred");
927
+ },
928
+ async transaction(mode) {
929
+ if (!fallbackClient) {
930
+ throw new Error("Interactive transactions are only supported on the SQLite fallback client.");
931
+ }
932
+ return fallbackClient.transaction(mode);
933
+ },
934
+ async executeMultiple(sql) {
935
+ if (fallbackClient && shouldBypassPostgres(sql)) {
936
+ return fallbackClient.executeMultiple(sql);
937
+ }
938
+ for (const statement of splitSqlStatements(sql)) {
939
+ await adapter.execute(statement);
940
+ }
941
+ },
942
+ async sync() {
943
+ if (fallbackClient) {
944
+ return fallbackClient.sync();
945
+ }
946
+ return { frame_no: 0, frames_synced: 0 };
947
+ },
948
+ close() {
949
+ closed = true;
950
+ prismaClientPromise = null;
951
+ compatibilityBootstrapPromise = null;
952
+ void prisma.$disconnect?.();
953
+ },
954
+ get closed() {
955
+ return closed;
956
+ },
957
+ get protocol() {
958
+ return "prisma-postgres";
959
+ }
960
+ };
961
+ return adapter;
962
+ }
963
+ var VIEW_MAPPINGS, UPSERT_KEYS, BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES, IMMEDIATE_FALLBACK_PATTERNS, prismaClientPromise, compatibilityBootstrapPromise;
964
+ var init_database_adapter = __esm({
965
+ "src/lib/database-adapter.ts"() {
966
+ "use strict";
967
+ VIEW_MAPPINGS = [
968
+ { view: "memories", source: "memory.memory_records" },
969
+ { view: "tasks", source: "memory.tasks" },
970
+ { view: "behaviors", source: "memory.behaviors" },
971
+ { view: "entities", source: "memory.entities" },
972
+ { view: "relationships", source: "memory.relationships" },
973
+ { view: "entity_memories", source: "memory.entity_memories" },
974
+ { view: "entity_aliases", source: "memory.entity_aliases" },
975
+ { view: "notifications", source: "memory.notifications" },
976
+ { view: "messages", source: "memory.messages" },
977
+ { view: "users", source: "wiki.users" },
978
+ { view: "workspaces", source: "wiki.workspaces" },
979
+ { view: "workspace_users", source: "wiki.workspace_users" },
980
+ { view: "documents", source: "wiki.workspace_documents" },
981
+ { view: "chats", source: "wiki.workspace_chats" }
982
+ ];
983
+ UPSERT_KEYS = {
984
+ memories: ["id"],
985
+ tasks: ["id"],
986
+ behaviors: ["id"],
987
+ entities: ["id"],
988
+ relationships: ["id"],
989
+ entity_aliases: ["alias"],
990
+ notifications: ["id"],
991
+ messages: ["id"],
992
+ users: ["id"],
993
+ workspaces: ["id"],
994
+ workspace_users: ["id"],
995
+ documents: ["id"],
996
+ chats: ["id"]
997
+ };
998
+ BOOLEAN_COLUMNS_BY_TABLE = {
999
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
1000
+ behaviors: /* @__PURE__ */ new Set(["active"]),
1001
+ notifications: /* @__PURE__ */ new Set(["read"]),
1002
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
1003
+ };
1004
+ BOOLEAN_COLUMN_NAMES = new Set(
1005
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
1006
+ );
1007
+ IMMEDIATE_FALLBACK_PATTERNS = [
1008
+ /\bPRAGMA\b/i,
1009
+ /\bsqlite_master\b/i,
1010
+ /(?:^|[.\s])(?:memories|conversations|entities)_fts\b/i,
1011
+ /\bMATCH\b/i,
1012
+ /\bvector_distance_cos\s*\(/i,
1013
+ /\bjson_extract\s*\(/i,
1014
+ /\bjulianday\s*\(/i,
1015
+ /\bstrftime\s*\(/i,
1016
+ /\blast_insert_rowid\s*\(/i
1017
+ ];
1018
+ prismaClientPromise = null;
1019
+ compatibilityBootstrapPromise = null;
1020
+ }
1021
+ });
1022
+
438
1023
  // src/lib/exe-daemon-client.ts
439
1024
  import net from "net";
440
- import os3 from "os";
1025
+ import os4 from "os";
441
1026
  import { spawn } from "child_process";
442
1027
  import { randomUUID } from "crypto";
443
1028
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
444
- import path3 from "path";
1029
+ import path4 from "path";
445
1030
  import { fileURLToPath } from "url";
446
1031
  function handleData(chunk) {
447
1032
  _buffer += chunk.toString();
@@ -492,17 +1077,17 @@ function cleanupStaleFiles() {
492
1077
  }
493
1078
  }
494
1079
  function findPackageRoot() {
495
- let dir = path3.dirname(fileURLToPath(import.meta.url));
496
- const { root } = path3.parse(dir);
1080
+ let dir = path4.dirname(fileURLToPath(import.meta.url));
1081
+ const { root } = path4.parse(dir);
497
1082
  while (dir !== root) {
498
- if (existsSync3(path3.join(dir, "package.json"))) return dir;
499
- dir = path3.dirname(dir);
1083
+ if (existsSync3(path4.join(dir, "package.json"))) return dir;
1084
+ dir = path4.dirname(dir);
500
1085
  }
501
1086
  return null;
502
1087
  }
503
1088
  function spawnDaemon() {
504
- const freeGB = os3.freemem() / (1024 * 1024 * 1024);
505
- const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
1089
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
1090
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
506
1091
  if (totalGB <= 8) {
507
1092
  process.stderr.write(
508
1093
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
@@ -522,7 +1107,7 @@ function spawnDaemon() {
522
1107
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
523
1108
  return;
524
1109
  }
525
- const daemonPath = path3.join(pkgRoot, "dist", "lib", "exe-daemon.js");
1110
+ const daemonPath = path4.join(pkgRoot, "dist", "lib", "exe-daemon.js");
526
1111
  if (!existsSync3(daemonPath)) {
527
1112
  process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
528
1113
  `);
@@ -531,7 +1116,7 @@ function spawnDaemon() {
531
1116
  const resolvedPath = daemonPath;
532
1117
  process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
533
1118
  `);
534
- const logPath = path3.join(path3.dirname(SOCKET_PATH), "exed.log");
1119
+ const logPath = path4.join(path4.dirname(SOCKET_PATH), "exed.log");
535
1120
  let stderrFd = "ignore";
536
1121
  try {
537
1122
  stderrFd = openSync(logPath, "a");
@@ -678,9 +1263,9 @@ var init_exe_daemon_client = __esm({
678
1263
  "src/lib/exe-daemon-client.ts"() {
679
1264
  "use strict";
680
1265
  init_config();
681
- SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path3.join(EXE_AI_DIR, "exed.sock");
682
- PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path3.join(EXE_AI_DIR, "exed.pid");
683
- SPAWN_LOCK_PATH = path3.join(EXE_AI_DIR, "exed-spawn.lock");
1266
+ SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path4.join(EXE_AI_DIR, "exed.sock");
1267
+ PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path4.join(EXE_AI_DIR, "exed.pid");
1268
+ SPAWN_LOCK_PATH = path4.join(EXE_AI_DIR, "exed-spawn.lock");
684
1269
  SPAWN_LOCK_STALE_MS = 3e4;
685
1270
  CONNECT_TIMEOUT_MS = 15e3;
686
1271
  REQUEST_TIMEOUT_MS = 3e4;
@@ -762,7 +1347,7 @@ __export(db_daemon_client_exports, {
762
1347
  createDaemonDbClient: () => createDaemonDbClient,
763
1348
  initDaemonDbClient: () => initDaemonDbClient
764
1349
  });
765
- function normalizeStatement(stmt) {
1350
+ function normalizeStatement2(stmt) {
766
1351
  if (typeof stmt === "string") {
767
1352
  return { sql: stmt, args: [] };
768
1353
  }
@@ -786,7 +1371,7 @@ function createDaemonDbClient(fallbackClient) {
786
1371
  if (!_useDaemon || !isClientConnected()) {
787
1372
  return fallbackClient.execute(stmt);
788
1373
  }
789
- const { sql, args } = normalizeStatement(stmt);
1374
+ const { sql, args } = normalizeStatement2(stmt);
790
1375
  const response = await sendDaemonRequest({
791
1376
  type: "db-execute",
792
1377
  sql,
@@ -811,7 +1396,7 @@ function createDaemonDbClient(fallbackClient) {
811
1396
  if (!_useDaemon || !isClientConnected()) {
812
1397
  return fallbackClient.batch(stmts, mode);
813
1398
  }
814
- const statements = stmts.map(normalizeStatement);
1399
+ const statements = stmts.map(normalizeStatement2);
815
1400
  const response = await sendDaemonRequest({
816
1401
  type: "db-batch",
817
1402
  statements,
@@ -906,6 +1491,18 @@ __export(database_exports, {
906
1491
  });
907
1492
  import { createClient } from "@libsql/client";
908
1493
  async function initDatabase(config) {
1494
+ if (_walCheckpointTimer) {
1495
+ clearInterval(_walCheckpointTimer);
1496
+ _walCheckpointTimer = null;
1497
+ }
1498
+ if (_daemonClient) {
1499
+ _daemonClient.close();
1500
+ _daemonClient = null;
1501
+ }
1502
+ if (_adapterClient && _adapterClient !== _resilientClient) {
1503
+ _adapterClient.close();
1504
+ }
1505
+ _adapterClient = null;
909
1506
  if (_client) {
910
1507
  _client.close();
911
1508
  _client = null;
@@ -919,6 +1516,7 @@ async function initDatabase(config) {
919
1516
  }
920
1517
  _client = createClient(opts);
921
1518
  _resilientClient = wrapWithRetry(_client);
1519
+ _adapterClient = _resilientClient;
922
1520
  _client.execute("PRAGMA busy_timeout = 30000").catch(() => {
923
1521
  });
924
1522
  _client.execute("PRAGMA journal_mode = WAL").catch(() => {
@@ -929,14 +1527,20 @@ async function initDatabase(config) {
929
1527
  });
930
1528
  }, 3e4);
931
1529
  _walCheckpointTimer.unref();
1530
+ if (process.env.DATABASE_URL) {
1531
+ _adapterClient = await createPrismaDbAdapter(_resilientClient);
1532
+ }
932
1533
  }
933
1534
  function isInitialized() {
934
- return _client !== null;
1535
+ return _adapterClient !== null || _client !== null;
935
1536
  }
936
1537
  function getClient() {
937
- if (!_resilientClient) {
1538
+ if (!_adapterClient) {
938
1539
  throw new Error("Database client not initialized. Call initDatabase() first.");
939
1540
  }
1541
+ if (process.env.DATABASE_URL) {
1542
+ return _adapterClient;
1543
+ }
940
1544
  if (process.env.EXE_IS_DAEMON === "1") {
941
1545
  return _resilientClient;
942
1546
  }
@@ -946,6 +1550,7 @@ function getClient() {
946
1550
  return _resilientClient;
947
1551
  }
948
1552
  async function initDaemonClient() {
1553
+ if (process.env.DATABASE_URL) return;
949
1554
  if (process.env.EXE_IS_DAEMON === "1") return;
950
1555
  if (!_resilientClient) return;
951
1556
  try {
@@ -1890,26 +2495,36 @@ async function ensureSchema() {
1890
2495
  }
1891
2496
  }
1892
2497
  async function disposeDatabase() {
2498
+ if (_walCheckpointTimer) {
2499
+ clearInterval(_walCheckpointTimer);
2500
+ _walCheckpointTimer = null;
2501
+ }
1893
2502
  if (_daemonClient) {
1894
2503
  _daemonClient.close();
1895
2504
  _daemonClient = null;
1896
2505
  }
2506
+ if (_adapterClient && _adapterClient !== _resilientClient) {
2507
+ _adapterClient.close();
2508
+ }
2509
+ _adapterClient = null;
1897
2510
  if (_client) {
1898
2511
  _client.close();
1899
2512
  _client = null;
1900
2513
  _resilientClient = null;
1901
2514
  }
1902
2515
  }
1903
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, initTurso, disposeTurso;
2516
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
1904
2517
  var init_database = __esm({
1905
2518
  "src/lib/database.ts"() {
1906
2519
  "use strict";
1907
2520
  init_db_retry();
1908
2521
  init_employees();
2522
+ init_database_adapter();
1909
2523
  _client = null;
1910
2524
  _resilientClient = null;
1911
2525
  _walCheckpointTimer = null;
1912
2526
  _daemonClient = null;
2527
+ _adapterClient = null;
1913
2528
  initTurso = initDatabase;
1914
2529
  disposeTurso = disposeDatabase;
1915
2530
  }
@@ -2120,13 +2735,13 @@ __export(keychain_exports, {
2120
2735
  });
2121
2736
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2122
2737
  import { existsSync as existsSync4 } from "fs";
2123
- import path4 from "path";
2124
- import os4 from "os";
2738
+ import path5 from "path";
2739
+ import os5 from "os";
2125
2740
  function getKeyDir() {
2126
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
2741
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os5.homedir(), ".exe-os");
2127
2742
  }
2128
2743
  function getKeyPath() {
2129
- return path4.join(getKeyDir(), "master.key");
2744
+ return path5.join(getKeyDir(), "master.key");
2130
2745
  }
2131
2746
  async function tryKeytar() {
2132
2747
  try {
@@ -2149,7 +2764,7 @@ async function getMasterKey() {
2149
2764
  const keyPath = getKeyPath();
2150
2765
  if (!existsSync4(keyPath)) {
2151
2766
  process.stderr.write(
2152
- `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2767
+ `[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2153
2768
  `
2154
2769
  );
2155
2770
  return null;
@@ -2300,7 +2915,7 @@ __export(shard_manager_exports, {
2300
2915
  listShards: () => listShards,
2301
2916
  shardExists: () => shardExists
2302
2917
  });
2303
- import path5 from "path";
2918
+ import path6 from "path";
2304
2919
  import { existsSync as existsSync5, mkdirSync, readdirSync } from "fs";
2305
2920
  import { createClient as createClient2 } from "@libsql/client";
2306
2921
  function initShardManager(encryptionKey) {
@@ -2326,7 +2941,7 @@ function getShardClient(projectName) {
2326
2941
  }
2327
2942
  const cached = _shards.get(safeName);
2328
2943
  if (cached) return cached;
2329
- const dbPath = path5.join(SHARDS_DIR, `${safeName}.db`);
2944
+ const dbPath = path6.join(SHARDS_DIR, `${safeName}.db`);
2330
2945
  const client = createClient2({
2331
2946
  url: `file:${dbPath}`,
2332
2947
  encryptionKey: _encryptionKey
@@ -2336,7 +2951,7 @@ function getShardClient(projectName) {
2336
2951
  }
2337
2952
  function shardExists(projectName) {
2338
2953
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2339
- return existsSync5(path5.join(SHARDS_DIR, `${safeName}.db`));
2954
+ return existsSync5(path6.join(SHARDS_DIR, `${safeName}.db`));
2340
2955
  }
2341
2956
  function listShards() {
2342
2957
  if (!existsSync5(SHARDS_DIR)) return [];
@@ -2413,7 +3028,23 @@ async function ensureShardSchema(client) {
2413
3028
  // MS-11: draft staging, MS-6a: memory_type, MS-7: trajectory
2414
3029
  "ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0",
2415
3030
  "ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'",
2416
- "ALTER TABLE memories ADD COLUMN trajectory TEXT"
3031
+ "ALTER TABLE memories ADD COLUMN trajectory TEXT",
3032
+ // Metadata enrichment columns (must match database.ts)
3033
+ "ALTER TABLE memories ADD COLUMN intent TEXT",
3034
+ "ALTER TABLE memories ADD COLUMN outcome TEXT",
3035
+ "ALTER TABLE memories ADD COLUMN domain TEXT",
3036
+ "ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
3037
+ "ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
3038
+ "ALTER TABLE memories ADD COLUMN chain_position TEXT",
3039
+ "ALTER TABLE memories ADD COLUMN review_status TEXT",
3040
+ "ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
3041
+ "ALTER TABLE memories ADD COLUMN file_paths TEXT",
3042
+ "ALTER TABLE memories ADD COLUMN commit_hash TEXT",
3043
+ "ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
3044
+ "ALTER TABLE memories ADD COLUMN token_cost REAL",
3045
+ "ALTER TABLE memories ADD COLUMN audience TEXT",
3046
+ "ALTER TABLE memories ADD COLUMN language_type TEXT",
3047
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
2417
3048
  ]) {
2418
3049
  try {
2419
3050
  await client.execute(col);
@@ -2525,7 +3156,7 @@ var init_shard_manager = __esm({
2525
3156
  "src/lib/shard-manager.ts"() {
2526
3157
  "use strict";
2527
3158
  init_config();
2528
- SHARDS_DIR = path5.join(EXE_AI_DIR, "shards");
3159
+ SHARDS_DIR = path6.join(EXE_AI_DIR, "shards");
2529
3160
  _shards = /* @__PURE__ */ new Map();
2530
3161
  _encryptionKey = null;
2531
3162
  _shardingEnabled = false;
@@ -2633,10 +3264,10 @@ __export(session_registry_exports, {
2633
3264
  });
2634
3265
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync6 } from "fs";
2635
3266
  import { execSync as execSync2 } from "child_process";
2636
- import path6 from "path";
2637
- import os5 from "os";
3267
+ import path7 from "path";
3268
+ import os6 from "os";
2638
3269
  function registerSession(entry) {
2639
- const dir = path6.dirname(REGISTRY_PATH);
3270
+ const dir = path7.dirname(REGISTRY_PATH);
2640
3271
  if (!existsSync6(dir)) {
2641
3272
  mkdirSync2(dir, { recursive: true });
2642
3273
  }
@@ -2680,7 +3311,7 @@ var REGISTRY_PATH;
2680
3311
  var init_session_registry = __esm({
2681
3312
  "src/lib/session-registry.ts"() {
2682
3313
  "use strict";
2683
- REGISTRY_PATH = path6.join(os5.homedir(), ".exe-os", "session-registry.json");
3314
+ REGISTRY_PATH = path7.join(os6.homedir(), ".exe-os", "session-registry.json");
2684
3315
  }
2685
3316
  });
2686
3317
 
@@ -2961,7 +3592,7 @@ var init_runtime_table = __esm({
2961
3592
 
2962
3593
  // src/lib/agent-config.ts
2963
3594
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
2964
- import path7 from "path";
3595
+ import path8 from "path";
2965
3596
  function loadAgentConfig() {
2966
3597
  if (!existsSync7(AGENT_CONFIG_PATH)) return {};
2967
3598
  try {
@@ -2984,7 +3615,7 @@ var init_agent_config = __esm({
2984
3615
  "use strict";
2985
3616
  init_config();
2986
3617
  init_runtime_table();
2987
- AGENT_CONFIG_PATH = path7.join(EXE_AI_DIR, "agent-config.json");
3618
+ AGENT_CONFIG_PATH = path8.join(EXE_AI_DIR, "agent-config.json");
2988
3619
  DEFAULT_MODELS = {
2989
3620
  claude: "claude-opus-4",
2990
3621
  codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
@@ -3003,10 +3634,10 @@ __export(intercom_queue_exports, {
3003
3634
  readQueue: () => readQueue
3004
3635
  });
3005
3636
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
3006
- import path8 from "path";
3007
- import os6 from "os";
3637
+ import path9 from "path";
3638
+ import os7 from "os";
3008
3639
  function ensureDir() {
3009
- const dir = path8.dirname(QUEUE_PATH);
3640
+ const dir = path9.dirname(QUEUE_PATH);
3010
3641
  if (!existsSync8(dir)) mkdirSync4(dir, { recursive: true });
3011
3642
  }
3012
3643
  function readQueue() {
@@ -3112,10 +3743,10 @@ var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
3112
3743
  var init_intercom_queue = __esm({
3113
3744
  "src/lib/intercom-queue.ts"() {
3114
3745
  "use strict";
3115
- QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
3746
+ QUEUE_PATH = path9.join(os7.homedir(), ".exe-os", "intercom-queue.json");
3116
3747
  MAX_RETRIES2 = 5;
3117
3748
  TTL_MS = 60 * 60 * 1e3;
3118
- INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
3749
+ INTERCOM_LOG = path9.join(os7.homedir(), ".exe-os", "intercom.log");
3119
3750
  }
3120
3751
  });
3121
3752
 
@@ -3138,7 +3769,7 @@ __export(license_exports, {
3138
3769
  });
3139
3770
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync9, mkdirSync as mkdirSync5 } from "fs";
3140
3771
  import { randomUUID as randomUUID3 } from "crypto";
3141
- import path9 from "path";
3772
+ import path10 from "path";
3142
3773
  import { jwtVerify, importSPKI } from "jose";
3143
3774
  async function fetchRetry(url, init) {
3144
3775
  try {
@@ -3149,7 +3780,7 @@ async function fetchRetry(url, init) {
3149
3780
  }
3150
3781
  }
3151
3782
  function loadDeviceId() {
3152
- const deviceJsonPath = path9.join(EXE_AI_DIR, "device.json");
3783
+ const deviceJsonPath = path10.join(EXE_AI_DIR, "device.json");
3153
3784
  try {
3154
3785
  if (existsSync9(deviceJsonPath)) {
3155
3786
  const data = JSON.parse(readFileSync7(deviceJsonPath, "utf8"));
@@ -3314,7 +3945,7 @@ async function checkLicense() {
3314
3945
  let key = loadLicense();
3315
3946
  if (!key) {
3316
3947
  try {
3317
- const configPath = path9.join(EXE_AI_DIR, "config.json");
3948
+ const configPath = path10.join(EXE_AI_DIR, "config.json");
3318
3949
  if (existsSync9(configPath)) {
3319
3950
  const raw = JSON.parse(readFileSync7(configPath, "utf8"));
3320
3951
  const cloud = raw.cloud;
@@ -3475,9 +4106,9 @@ var init_license = __esm({
3475
4106
  "src/lib/license.ts"() {
3476
4107
  "use strict";
3477
4108
  init_config();
3478
- LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
3479
- CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
3480
- DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
4109
+ LICENSE_PATH = path10.join(EXE_AI_DIR, "license.key");
4110
+ CACHE_PATH = path10.join(EXE_AI_DIR, "license-cache.json");
4111
+ DEVICE_ID_PATH = path10.join(EXE_AI_DIR, "device-id");
3481
4112
  API_BASE = "https://askexe.com/cloud";
3482
4113
  RETRY_DELAY_MS = 500;
3483
4114
  LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
@@ -3508,7 +4139,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
3508
4139
 
3509
4140
  // src/lib/plan-limits.ts
3510
4141
  import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
3511
- import path10 from "path";
4142
+ import path11 from "path";
3512
4143
  function getLicenseSync() {
3513
4144
  try {
3514
4145
  if (!existsSync10(CACHE_PATH2)) return freeLicense();
@@ -3580,14 +4211,14 @@ var init_plan_limits = __esm({
3580
4211
  this.name = "PlanLimitError";
3581
4212
  }
3582
4213
  };
3583
- CACHE_PATH2 = path10.join(EXE_AI_DIR, "license-cache.json");
4214
+ CACHE_PATH2 = path11.join(EXE_AI_DIR, "license-cache.json");
3584
4215
  }
3585
4216
  });
3586
4217
 
3587
4218
  // src/lib/notifications.ts
3588
4219
  import crypto from "crypto";
3589
- import path11 from "path";
3590
- import os7 from "os";
4220
+ import path12 from "path";
4221
+ import os8 from "os";
3591
4222
  import {
3592
4223
  readFileSync as readFileSync9,
3593
4224
  readdirSync as readdirSync2,
@@ -3705,8 +4336,8 @@ async function markDoneTaskNotificationsAsRead() {
3705
4336
  }
3706
4337
  }
3707
4338
  async function migrateJsonNotifications() {
3708
- const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path11.join(os7.homedir(), ".exe-os");
3709
- const notifDir = path11.join(base, "notifications");
4339
+ const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path12.join(os8.homedir(), ".exe-os");
4340
+ const notifDir = path12.join(base, "notifications");
3710
4341
  if (!existsSync11(notifDir)) return 0;
3711
4342
  let migrated = 0;
3712
4343
  try {
@@ -3715,7 +4346,7 @@ async function migrateJsonNotifications() {
3715
4346
  const client = getClient();
3716
4347
  for (const file of files) {
3717
4348
  try {
3718
- const filePath = path11.join(notifDir, file);
4349
+ const filePath = path12.join(notifDir, file);
3719
4350
  const data = JSON.parse(readFileSync9(filePath, "utf8"));
3720
4351
  await client.execute({
3721
4352
  sql: `INSERT OR IGNORE INTO notifications (id, agent_id, agent_role, event, project, summary, task_file, read, created_at)
@@ -3863,8 +4494,8 @@ var init_session_kill_telemetry = __esm({
3863
4494
 
3864
4495
  // src/lib/tasks-crud.ts
3865
4496
  import crypto3 from "crypto";
3866
- import path12 from "path";
3867
- import os8 from "os";
4497
+ import path13 from "path";
4498
+ import os9 from "os";
3868
4499
  import { execSync as execSync5 } from "child_process";
3869
4500
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
3870
4501
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
@@ -4042,8 +4673,8 @@ ${laneWarning}` : laneWarning;
4042
4673
  }
4043
4674
  if (input.baseDir) {
4044
4675
  try {
4045
- await mkdir4(path12.join(input.baseDir, "exe", "output"), { recursive: true });
4046
- await mkdir4(path12.join(input.baseDir, "exe", "research"), { recursive: true });
4676
+ await mkdir4(path13.join(input.baseDir, "exe", "output"), { recursive: true });
4677
+ await mkdir4(path13.join(input.baseDir, "exe", "research"), { recursive: true });
4047
4678
  await ensureArchitectureDoc(input.baseDir, input.projectName);
4048
4679
  await ensureGitignoreExe(input.baseDir);
4049
4680
  } catch {
@@ -4079,9 +4710,9 @@ ${laneWarning}` : laneWarning;
4079
4710
  });
4080
4711
  if (input.baseDir) {
4081
4712
  try {
4082
- const EXE_OS_DIR = path12.join(os8.homedir(), ".exe-os");
4083
- const mdPath = path12.join(EXE_OS_DIR, taskFile);
4084
- const mdDir = path12.dirname(mdPath);
4713
+ const EXE_OS_DIR = path13.join(os9.homedir(), ".exe-os");
4714
+ const mdPath = path13.join(EXE_OS_DIR, taskFile);
4715
+ const mdDir = path13.dirname(mdPath);
4085
4716
  if (!existsSync12(mdDir)) await mkdir4(mdDir, { recursive: true });
4086
4717
  const reviewer = input.reviewer ?? input.assignedBy;
4087
4718
  const mdContent = `# ${input.title}
@@ -4382,7 +5013,7 @@ async function deleteTaskCore(taskId, _baseDir) {
4382
5013
  return { taskFile, assignedTo, assignedBy, taskSlug };
4383
5014
  }
4384
5015
  async function ensureArchitectureDoc(baseDir, projectName) {
4385
- const archPath = path12.join(baseDir, "exe", "ARCHITECTURE.md");
5016
+ const archPath = path13.join(baseDir, "exe", "ARCHITECTURE.md");
4386
5017
  try {
4387
5018
  if (existsSync12(archPath)) return;
4388
5019
  const template = [
@@ -4417,7 +5048,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
4417
5048
  }
4418
5049
  }
4419
5050
  async function ensureGitignoreExe(baseDir) {
4420
- const gitignorePath = path12.join(baseDir, ".gitignore");
5051
+ const gitignorePath = path13.join(baseDir, ".gitignore");
4421
5052
  try {
4422
5053
  if (existsSync12(gitignorePath)) {
4423
5054
  const content = readFileSync10(gitignorePath, "utf-8");
@@ -4451,13 +5082,13 @@ var init_tasks_crud = __esm({
4451
5082
  });
4452
5083
 
4453
5084
  // src/lib/tasks-review.ts
4454
- import path13 from "path";
5085
+ import path14 from "path";
4455
5086
  import { existsSync as existsSync13, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
4456
5087
  async function countPendingReviews(sessionScope) {
4457
5088
  const client = getClient();
4458
5089
  if (sessionScope) {
4459
5090
  const result2 = await client.execute({
4460
- sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND (session_scope = ? OR session_scope IS NULL)",
5091
+ sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND session_scope = ?",
4461
5092
  args: [sessionScope]
4462
5093
  });
4463
5094
  return Number(result2.rows[0]?.cnt) || 0;
@@ -4633,11 +5264,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
4633
5264
  );
4634
5265
  }
4635
5266
  try {
4636
- const cacheDir = path13.join(EXE_AI_DIR, "session-cache");
5267
+ const cacheDir = path14.join(EXE_AI_DIR, "session-cache");
4637
5268
  if (existsSync13(cacheDir)) {
4638
5269
  for (const f of readdirSync3(cacheDir)) {
4639
5270
  if (f.startsWith("review-notified-")) {
4640
- unlinkSync4(path13.join(cacheDir, f));
5271
+ unlinkSync4(path14.join(cacheDir, f));
4641
5272
  }
4642
5273
  }
4643
5274
  }
@@ -4658,7 +5289,7 @@ var init_tasks_review = __esm({
4658
5289
  });
4659
5290
 
4660
5291
  // src/lib/tasks-chain.ts
4661
- import path14 from "path";
5292
+ import path15 from "path";
4662
5293
  import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
4663
5294
  async function cascadeUnblock(taskId, baseDir, now) {
4664
5295
  const client = getClient();
@@ -4675,7 +5306,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
4675
5306
  });
4676
5307
  for (const ur of unblockedRows.rows) {
4677
5308
  try {
4678
- const ubFile = path14.join(baseDir, String(ur.task_file));
5309
+ const ubFile = path15.join(baseDir, String(ur.task_file));
4679
5310
  let ubContent = await readFile4(ubFile, "utf-8");
4680
5311
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
4681
5312
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -4749,7 +5380,7 @@ __export(project_name_exports, {
4749
5380
  getProjectName: () => getProjectName
4750
5381
  });
4751
5382
  import { execSync as execSync6 } from "child_process";
4752
- import path15 from "path";
5383
+ import path16 from "path";
4753
5384
  function getProjectName(cwd) {
4754
5385
  const dir = cwd ?? process.cwd();
4755
5386
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -4762,7 +5393,7 @@ function getProjectName(cwd) {
4762
5393
  timeout: 2e3,
4763
5394
  stdio: ["pipe", "pipe", "pipe"]
4764
5395
  }).trim();
4765
- repoRoot = path15.dirname(gitCommonDir);
5396
+ repoRoot = path16.dirname(gitCommonDir);
4766
5397
  } catch {
4767
5398
  repoRoot = execSync6("git rev-parse --show-toplevel", {
4768
5399
  cwd: dir,
@@ -4771,11 +5402,11 @@ function getProjectName(cwd) {
4771
5402
  stdio: ["pipe", "pipe", "pipe"]
4772
5403
  }).trim();
4773
5404
  }
4774
- _cached2 = path15.basename(repoRoot);
5405
+ _cached2 = path16.basename(repoRoot);
4775
5406
  _cachedCwd = dir;
4776
5407
  return _cached2;
4777
5408
  } catch {
4778
- _cached2 = path15.basename(dir);
5409
+ _cached2 = path16.basename(dir);
4779
5410
  _cachedCwd = dir;
4780
5411
  return _cached2;
4781
5412
  }
@@ -5252,7 +5883,7 @@ __export(tasks_exports, {
5252
5883
  updateTaskStatus: () => updateTaskStatus,
5253
5884
  writeCheckpoint: () => writeCheckpoint
5254
5885
  });
5255
- import path16 from "path";
5886
+ import path17 from "path";
5256
5887
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5 } from "fs";
5257
5888
  async function createTask(input) {
5258
5889
  const result = await createTaskCore(input);
@@ -5272,8 +5903,8 @@ async function updateTask(input) {
5272
5903
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
5273
5904
  try {
5274
5905
  const agent = String(row.assigned_to);
5275
- const cacheDir = path16.join(EXE_AI_DIR, "session-cache");
5276
- const cachePath = path16.join(cacheDir, `current-task-${agent}.json`);
5906
+ const cacheDir = path17.join(EXE_AI_DIR, "session-cache");
5907
+ const cachePath = path17.join(cacheDir, `current-task-${agent}.json`);
5277
5908
  if (input.status === "in_progress") {
5278
5909
  mkdirSync6(cacheDir, { recursive: true });
5279
5910
  writeFileSync6(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
@@ -5744,12 +6375,12 @@ __export(tmux_routing_exports, {
5744
6375
  });
5745
6376
  import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
5746
6377
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, existsSync as existsSync14, appendFileSync, readdirSync as readdirSync4 } from "fs";
5747
- import path17 from "path";
5748
- import os9 from "os";
6378
+ import path18 from "path";
6379
+ import os10 from "os";
5749
6380
  import { fileURLToPath as fileURLToPath2 } from "url";
5750
6381
  import { unlinkSync as unlinkSync6 } from "fs";
5751
6382
  function spawnLockPath(sessionName) {
5752
- return path17.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
6383
+ return path18.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
5753
6384
  }
5754
6385
  function isProcessAlive(pid) {
5755
6386
  try {
@@ -5786,8 +6417,8 @@ function releaseSpawnLock2(sessionName) {
5786
6417
  function resolveBehaviorsExporterScript() {
5787
6418
  try {
5788
6419
  const thisFile = fileURLToPath2(import.meta.url);
5789
- const scriptPath = path17.join(
5790
- path17.dirname(thisFile),
6420
+ const scriptPath = path18.join(
6421
+ path18.dirname(thisFile),
5791
6422
  "..",
5792
6423
  "bin",
5793
6424
  "exe-export-behaviors.js"
@@ -5862,7 +6493,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
5862
6493
  mkdirSync7(SESSION_CACHE, { recursive: true });
5863
6494
  }
5864
6495
  const rootExe = extractRootExe(parentExe) ?? parentExe;
5865
- const filePath = path17.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
6496
+ const filePath = path18.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
5866
6497
  writeFileSync7(filePath, JSON.stringify({
5867
6498
  parentExe: rootExe,
5868
6499
  dispatchedBy: dispatchedBy || rootExe,
@@ -5871,7 +6502,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
5871
6502
  }
5872
6503
  function getParentExe(sessionKey) {
5873
6504
  try {
5874
- const data = JSON.parse(readFileSync11(path17.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
6505
+ const data = JSON.parse(readFileSync11(path18.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
5875
6506
  return data.parentExe || null;
5876
6507
  } catch {
5877
6508
  return null;
@@ -5880,7 +6511,7 @@ function getParentExe(sessionKey) {
5880
6511
  function getDispatchedBy(sessionKey) {
5881
6512
  try {
5882
6513
  const data = JSON.parse(readFileSync11(
5883
- path17.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
6514
+ path18.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
5884
6515
  "utf8"
5885
6516
  ));
5886
6517
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -6066,7 +6697,7 @@ function sendIntercom(targetSession) {
6066
6697
  try {
6067
6698
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
6068
6699
  const agent = baseAgentName(rawAgent);
6069
- const markerPath = path17.join(SESSION_CACHE, `current-task-${agent}.json`);
6700
+ const markerPath = path18.join(SESSION_CACHE, `current-task-${agent}.json`);
6070
6701
  if (existsSync14(markerPath)) {
6071
6702
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
6072
6703
  return "debounced";
@@ -6076,7 +6707,7 @@ function sendIntercom(targetSession) {
6076
6707
  try {
6077
6708
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
6078
6709
  const agent = baseAgentName(rawAgent);
6079
- const taskDir = path17.join(process.cwd(), "exe", agent);
6710
+ const taskDir = path18.join(process.cwd(), "exe", agent);
6080
6711
  if (existsSync14(taskDir)) {
6081
6712
  const files = readdirSync4(taskDir).filter(
6082
6713
  (f) => f.endsWith(".md") && f !== "DONE.txt"
@@ -6210,8 +6841,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6210
6841
  const transport = getTransport();
6211
6842
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
6212
6843
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
6213
- const logDir = path17.join(os9.homedir(), ".exe-os", "session-logs");
6214
- const logFile = path17.join(logDir, `${instanceLabel}-${Date.now()}.log`);
6844
+ const logDir = path18.join(os10.homedir(), ".exe-os", "session-logs");
6845
+ const logFile = path18.join(logDir, `${instanceLabel}-${Date.now()}.log`);
6215
6846
  if (!existsSync14(logDir)) {
6216
6847
  mkdirSync7(logDir, { recursive: true });
6217
6848
  }
@@ -6219,14 +6850,14 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6219
6850
  let cleanupSuffix = "";
6220
6851
  try {
6221
6852
  const thisFile = fileURLToPath2(import.meta.url);
6222
- const cleanupScript = path17.join(path17.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
6853
+ const cleanupScript = path18.join(path18.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
6223
6854
  if (existsSync14(cleanupScript)) {
6224
6855
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
6225
6856
  }
6226
6857
  } catch {
6227
6858
  }
6228
6859
  try {
6229
- const claudeJsonPath = path17.join(os9.homedir(), ".claude.json");
6860
+ const claudeJsonPath = path18.join(os10.homedir(), ".claude.json");
6230
6861
  let claudeJson = {};
6231
6862
  try {
6232
6863
  claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
@@ -6241,10 +6872,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6241
6872
  } catch {
6242
6873
  }
6243
6874
  try {
6244
- const settingsDir = path17.join(os9.homedir(), ".claude", "projects");
6875
+ const settingsDir = path18.join(os10.homedir(), ".claude", "projects");
6245
6876
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
6246
- const projSettingsDir = path17.join(settingsDir, normalizedKey);
6247
- const settingsPath = path17.join(projSettingsDir, "settings.json");
6877
+ const projSettingsDir = path18.join(settingsDir, normalizedKey);
6878
+ const settingsPath = path18.join(projSettingsDir, "settings.json");
6248
6879
  let settings = {};
6249
6880
  try {
6250
6881
  settings = JSON.parse(readFileSync11(settingsPath, "utf8"));
@@ -6291,8 +6922,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6291
6922
  let behaviorsFlag = "";
6292
6923
  let legacyFallbackWarned = false;
6293
6924
  if (!useExeAgent && !useBinSymlink) {
6294
- const identityPath = path17.join(
6295
- os9.homedir(),
6925
+ const identityPath = path18.join(
6926
+ os10.homedir(),
6296
6927
  ".exe-os",
6297
6928
  "identity",
6298
6929
  `${employeeName}.md`
@@ -6307,7 +6938,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6307
6938
  }
6308
6939
  const behaviorsFile = exportBehaviorsSync(
6309
6940
  employeeName,
6310
- path17.basename(spawnCwd),
6941
+ path18.basename(spawnCwd),
6311
6942
  sessionName
6312
6943
  );
6313
6944
  if (behaviorsFile) {
@@ -6322,9 +6953,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6322
6953
  }
6323
6954
  let sessionContextFlag = "";
6324
6955
  try {
6325
- const ctxDir = path17.join(os9.homedir(), ".exe-os", "session-cache");
6956
+ const ctxDir = path18.join(os10.homedir(), ".exe-os", "session-cache");
6326
6957
  mkdirSync7(ctxDir, { recursive: true });
6327
- const ctxFile = path17.join(ctxDir, `session-context-${sessionName}.md`);
6958
+ const ctxFile = path18.join(ctxDir, `session-context-${sessionName}.md`);
6328
6959
  const ctxContent = [
6329
6960
  `## Session Context`,
6330
6961
  `You are running in tmux session: ${sessionName}.`,
@@ -6408,7 +7039,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6408
7039
  transport.pipeLog(sessionName, logFile);
6409
7040
  try {
6410
7041
  const mySession = getMySession();
6411
- const dispatchInfo = path17.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
7042
+ const dispatchInfo = path18.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
6412
7043
  writeFileSync7(dispatchInfo, JSON.stringify({
6413
7044
  dispatchedBy: mySession,
6414
7045
  rootExe: exeSession,
@@ -6483,15 +7114,15 @@ var init_tmux_routing = __esm({
6483
7114
  init_intercom_queue();
6484
7115
  init_plan_limits();
6485
7116
  init_employees();
6486
- SPAWN_LOCK_DIR = path17.join(os9.homedir(), ".exe-os", "spawn-locks");
6487
- SESSION_CACHE = path17.join(os9.homedir(), ".exe-os", "session-cache");
7117
+ SPAWN_LOCK_DIR = path18.join(os10.homedir(), ".exe-os", "spawn-locks");
7118
+ SESSION_CACHE = path18.join(os10.homedir(), ".exe-os", "session-cache");
6488
7119
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
6489
7120
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
6490
7121
  VERIFY_PANE_LINES = 200;
6491
7122
  INTERCOM_DEBOUNCE_MS = 3e4;
6492
7123
  CODEX_DEBOUNCE_MS = 12e4;
6493
- INTERCOM_LOG2 = path17.join(os9.homedir(), ".exe-os", "intercom.log");
6494
- DEBOUNCE_FILE = path17.join(SESSION_CACHE, "intercom-debounce.json");
7124
+ INTERCOM_LOG2 = path18.join(os10.homedir(), ".exe-os", "intercom.log");
7125
+ DEBOUNCE_FILE = path18.join(SESSION_CACHE, "intercom-debounce.json");
6495
7126
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
6496
7127
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
6497
7128
  }
@@ -6549,12 +7180,12 @@ __export(worker_gate_exports, {
6549
7180
  tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
6550
7181
  });
6551
7182
  import { readdirSync as readdirSync6, writeFileSync as writeFileSync9, unlinkSync as unlinkSync8, mkdirSync as mkdirSync9, existsSync as existsSync15 } from "fs";
6552
- import path19 from "path";
7183
+ import path20 from "path";
6553
7184
  function tryAcquireWorkerSlot() {
6554
7185
  try {
6555
7186
  mkdirSync9(WORKER_PID_DIR, { recursive: true });
6556
7187
  const reservationId = `res-${process.pid}-${Date.now()}`;
6557
- const reservationPath = path19.join(WORKER_PID_DIR, `${reservationId}.pid`);
7188
+ const reservationPath = path20.join(WORKER_PID_DIR, `${reservationId}.pid`);
6558
7189
  writeFileSync9(reservationPath, String(process.pid));
6559
7190
  const files = readdirSync6(WORKER_PID_DIR);
6560
7191
  let alive = 0;
@@ -6572,7 +7203,7 @@ function tryAcquireWorkerSlot() {
6572
7203
  alive++;
6573
7204
  } catch {
6574
7205
  try {
6575
- unlinkSync8(path19.join(WORKER_PID_DIR, f));
7206
+ unlinkSync8(path20.join(WORKER_PID_DIR, f));
6576
7207
  } catch {
6577
7208
  }
6578
7209
  }
@@ -6596,13 +7227,13 @@ function tryAcquireWorkerSlot() {
6596
7227
  function registerWorkerPid(pid) {
6597
7228
  try {
6598
7229
  mkdirSync9(WORKER_PID_DIR, { recursive: true });
6599
- writeFileSync9(path19.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
7230
+ writeFileSync9(path20.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
6600
7231
  } catch {
6601
7232
  }
6602
7233
  }
6603
7234
  function cleanupWorkerPid() {
6604
7235
  try {
6605
- unlinkSync8(path19.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
7236
+ unlinkSync8(path20.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
6606
7237
  } catch {
6607
7238
  }
6608
7239
  }
@@ -6642,9 +7273,9 @@ var init_worker_gate = __esm({
6642
7273
  "src/lib/worker-gate.ts"() {
6643
7274
  "use strict";
6644
7275
  init_config();
6645
- WORKER_PID_DIR = path19.join(EXE_AI_DIR, "worker-pids");
7276
+ WORKER_PID_DIR = path20.join(EXE_AI_DIR, "worker-pids");
6646
7277
  MAX_CONCURRENT_WORKERS = 3;
6647
- BACKFILL_LOCK = path19.join(WORKER_PID_DIR, "backfill.lock");
7278
+ BACKFILL_LOCK = path20.join(WORKER_PID_DIR, "backfill.lock");
6648
7279
  }
6649
7280
  });
6650
7281
 
@@ -6747,7 +7378,7 @@ __export(crdt_sync_exports, {
6747
7378
  });
6748
7379
  import * as Y from "yjs";
6749
7380
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync16, mkdirSync as mkdirSync10, unlinkSync as unlinkSync9 } from "fs";
6750
- import path20 from "path";
7381
+ import path21 from "path";
6751
7382
  import { homedir } from "os";
6752
7383
  function getStatePath() {
6753
7384
  return _statePathOverride ?? DEFAULT_STATE_PATH;
@@ -6903,7 +7534,7 @@ function persistState() {
6903
7534
  if (!doc) return;
6904
7535
  try {
6905
7536
  const sp = getStatePath();
6906
- const dir = path20.dirname(sp);
7537
+ const dir = path21.dirname(sp);
6907
7538
  if (!existsSync16(dir)) mkdirSync10(dir, { recursive: true });
6908
7539
  const state = Y.encodeStateAsUpdate(doc);
6909
7540
  writeFileSync10(sp, Buffer.from(state));
@@ -6947,7 +7578,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
6947
7578
  var init_crdt_sync = __esm({
6948
7579
  "src/lib/crdt-sync.ts"() {
6949
7580
  "use strict";
6950
- DEFAULT_STATE_PATH = path20.join(homedir(), ".exe-os", "crdt-state.bin");
7581
+ DEFAULT_STATE_PATH = path21.join(homedir(), ".exe-os", "crdt-state.bin");
6951
7582
  _statePathOverride = null;
6952
7583
  doc = null;
6953
7584
  }
@@ -6983,14 +7614,14 @@ __export(cloud_sync_exports, {
6983
7614
  });
6984
7615
  import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, existsSync as existsSync17, readdirSync as readdirSync7, mkdirSync as mkdirSync11, appendFileSync as appendFileSync2, unlinkSync as unlinkSync10, openSync as openSync2, closeSync as closeSync2 } from "fs";
6985
7616
  import crypto7 from "crypto";
6986
- import path21 from "path";
7617
+ import path22 from "path";
6987
7618
  import { homedir as homedir2 } from "os";
6988
7619
  function sqlSafe(v) {
6989
7620
  return v === void 0 ? null : v;
6990
7621
  }
6991
7622
  function logError(msg) {
6992
7623
  try {
6993
- const logPath = path21.join(homedir2(), ".exe-os", "workers.log");
7624
+ const logPath = path22.join(homedir2(), ".exe-os", "workers.log");
6994
7625
  appendFileSync2(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
6995
7626
  `);
6996
7627
  } catch {
@@ -7385,7 +8016,7 @@ async function cloudSync(config) {
7385
8016
  try {
7386
8017
  const employees = await loadEmployees();
7387
8018
  rosterResult.employees = employees.length;
7388
- const idDir = path21.join(EXE_AI_DIR, "identity");
8019
+ const idDir = path22.join(EXE_AI_DIR, "identity");
7389
8020
  if (existsSync17(idDir)) {
7390
8021
  rosterResult.identities = readdirSync7(idDir).filter((f) => f.endsWith(".md")).length;
7391
8022
  }
@@ -7426,9 +8057,9 @@ function consumeRosterDeletions() {
7426
8057
  }
7427
8058
  }
7428
8059
  function buildRosterBlob(paths) {
7429
- const rosterPath = paths?.rosterPath ?? path21.join(EXE_AI_DIR, "exe-employees.json");
7430
- const identityDir = paths?.identityDir ?? path21.join(EXE_AI_DIR, "identity");
7431
- const configPath = paths?.configPath ?? path21.join(EXE_AI_DIR, "config.json");
8060
+ const rosterPath = paths?.rosterPath ?? path22.join(EXE_AI_DIR, "exe-employees.json");
8061
+ const identityDir = paths?.identityDir ?? path22.join(EXE_AI_DIR, "identity");
8062
+ const configPath = paths?.configPath ?? path22.join(EXE_AI_DIR, "config.json");
7432
8063
  let roster = [];
7433
8064
  if (existsSync17(rosterPath)) {
7434
8065
  try {
@@ -7440,7 +8071,7 @@ function buildRosterBlob(paths) {
7440
8071
  if (existsSync17(identityDir)) {
7441
8072
  for (const file of readdirSync7(identityDir).filter((f) => f.endsWith(".md"))) {
7442
8073
  try {
7443
- identities[file] = readFileSync14(path21.join(identityDir, file), "utf-8");
8074
+ identities[file] = readFileSync14(path22.join(identityDir, file), "utf-8");
7444
8075
  } catch {
7445
8076
  }
7446
8077
  }
@@ -7453,7 +8084,7 @@ function buildRosterBlob(paths) {
7453
8084
  }
7454
8085
  }
7455
8086
  let agentConfig;
7456
- const agentConfigPath = path21.join(EXE_AI_DIR, "agent-config.json");
8087
+ const agentConfigPath = path22.join(EXE_AI_DIR, "agent-config.json");
7457
8088
  if (existsSync17(agentConfigPath)) {
7458
8089
  try {
7459
8090
  agentConfig = JSON.parse(readFileSync14(agentConfigPath, "utf-8"));
@@ -7532,7 +8163,7 @@ async function cloudPullRoster(config) {
7532
8163
  }
7533
8164
  }
7534
8165
  function mergeConfig(remoteConfig, configPath) {
7535
- const cfgPath = configPath ?? path21.join(EXE_AI_DIR, "config.json");
8166
+ const cfgPath = configPath ?? path22.join(EXE_AI_DIR, "config.json");
7536
8167
  let local = {};
7537
8168
  if (existsSync17(cfgPath)) {
7538
8169
  try {
@@ -7541,14 +8172,14 @@ function mergeConfig(remoteConfig, configPath) {
7541
8172
  }
7542
8173
  }
7543
8174
  const merged = { ...remoteConfig, ...local };
7544
- const dir = path21.dirname(cfgPath);
8175
+ const dir = path22.dirname(cfgPath);
7545
8176
  if (!existsSync17(dir)) mkdirSync11(dir, { recursive: true });
7546
8177
  writeFileSync11(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
7547
8178
  }
7548
8179
  async function mergeRosterFromRemote(remote, paths) {
7549
8180
  return withRosterLock(async () => {
7550
8181
  const rosterPath = paths?.rosterPath ?? void 0;
7551
- const identityDir = paths?.identityDir ?? path21.join(EXE_AI_DIR, "identity");
8182
+ const identityDir = paths?.identityDir ?? path22.join(EXE_AI_DIR, "identity");
7552
8183
  const localEmployees = await loadEmployees(rosterPath);
7553
8184
  const localNames = new Set(localEmployees.map((e) => e.name));
7554
8185
  let added = 0;
@@ -7570,7 +8201,7 @@ async function mergeRosterFromRemote(remote, paths) {
7570
8201
  const remoteIdentity = remote.identities[matchedKey];
7571
8202
  if (remoteIdentity) {
7572
8203
  if (!existsSync17(identityDir)) mkdirSync11(identityDir, { recursive: true });
7573
- const idPath = path21.join(identityDir, `${remoteEmp.name}.md`);
8204
+ const idPath = path22.join(identityDir, `${remoteEmp.name}.md`);
7574
8205
  let localIdentity = null;
7575
8206
  try {
7576
8207
  localIdentity = existsSync17(idPath) ? readFileSync14(idPath, "utf-8") : null;
@@ -7603,7 +8234,7 @@ async function mergeRosterFromRemote(remote, paths) {
7603
8234
  }
7604
8235
  if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
7605
8236
  try {
7606
- const agentConfigPath = path21.join(EXE_AI_DIR, "agent-config.json");
8237
+ const agentConfigPath = path22.join(EXE_AI_DIR, "agent-config.json");
7607
8238
  let local = {};
7608
8239
  if (existsSync17(agentConfigPath)) {
7609
8240
  try {
@@ -8050,9 +8681,9 @@ var init_cloud_sync = __esm({
8050
8681
  LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
8051
8682
  FETCH_TIMEOUT_MS = 3e4;
8052
8683
  PUSH_BATCH_SIZE = 5e3;
8053
- ROSTER_LOCK_PATH = path21.join(EXE_AI_DIR, "roster-merge.lock");
8684
+ ROSTER_LOCK_PATH = path22.join(EXE_AI_DIR, "roster-merge.lock");
8054
8685
  LOCK_STALE_MS = 3e4;
8055
- ROSTER_DELETIONS_PATH = path21.join(EXE_AI_DIR, "roster-deletions.json");
8686
+ ROSTER_DELETIONS_PATH = path22.join(EXE_AI_DIR, "roster-deletions.json");
8056
8687
  }
8057
8688
  });
8058
8689
 
@@ -8234,10 +8865,10 @@ var init_schedules = __esm({
8234
8865
 
8235
8866
  // src/bin/exe-boot.ts
8236
8867
  init_employees();
8237
- import path22 from "path";
8868
+ import path23 from "path";
8238
8869
  import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
8239
8870
  import { existsSync as existsSync18, readFileSync as readFileSync15, readdirSync as readdirSync8, unlinkSync as unlinkSync11 } from "fs";
8240
- import os10 from "os";
8871
+ import os11 from "os";
8241
8872
 
8242
8873
  // src/lib/employee-templates.ts
8243
8874
  init_global_procedures();
@@ -8741,11 +9372,11 @@ init_session_key();
8741
9372
  init_employees();
8742
9373
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7, readdirSync as readdirSync5 } from "fs";
8743
9374
  import { execSync as execSync8 } from "child_process";
8744
- import path18 from "path";
8745
- var CACHE_DIR = path18.join(EXE_AI_DIR, "session-cache");
9375
+ import path19 from "path";
9376
+ var CACHE_DIR = path19.join(EXE_AI_DIR, "session-cache");
8746
9377
  var STALE_MS = 24 * 60 * 60 * 1e3;
8747
9378
  function getMarkerPath() {
8748
- return path18.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
9379
+ return path19.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
8749
9380
  }
8750
9381
  function writeActiveAgent(agentId, agentRole) {
8751
9382
  try {
@@ -8760,11 +9391,11 @@ function writeActiveAgent(agentId, agentRole) {
8760
9391
  function cleanupSessionMarkers() {
8761
9392
  const key = getSessionKey();
8762
9393
  try {
8763
- unlinkSync7(path18.join(CACHE_DIR, `active-agent-${key}.json`));
9394
+ unlinkSync7(path19.join(CACHE_DIR, `active-agent-${key}.json`));
8764
9395
  } catch {
8765
9396
  }
8766
9397
  try {
8767
- unlinkSync7(path18.join(CACHE_DIR, "active-agent-undefined.json"));
9398
+ unlinkSync7(path19.join(CACHE_DIR, "active-agent-undefined.json"));
8768
9399
  } catch {
8769
9400
  }
8770
9401
  }
@@ -8854,7 +9485,7 @@ async function boot(options) {
8854
9485
  const employeeDirs = entries.filter((e) => e.isDirectory() && !["output", "research"].includes(e.name));
8855
9486
  for (const dir of employeeDirs) {
8856
9487
  const employee = dir.name;
8857
- const taskDir = path22.join(exeDir, employee);
9488
+ const taskDir = path23.join(exeDir, employee);
8858
9489
  let files;
8859
9490
  try {
8860
9491
  files = readdirSync9(taskDir).filter((f) => f.endsWith(".md"));
@@ -8865,7 +9496,7 @@ async function boot(options) {
8865
9496
  const taskFilePath = `exe/${employee}/${file}`;
8866
9497
  let content;
8867
9498
  try {
8868
- content = readFs(path22.join(taskDir, file), "utf8");
9499
+ content = readFs(path23.join(taskDir, file), "utf8");
8869
9500
  } catch {
8870
9501
  continue;
8871
9502
  }
@@ -8951,12 +9582,12 @@ async function boot(options) {
8951
9582
  }
8952
9583
  try {
8953
9584
  for (const reviewDirName of /* @__PURE__ */ new Set(["exe", coordinatorName])) {
8954
- const reviewDir = path22.join(process.cwd(), "exe", reviewDirName);
9585
+ const reviewDir = path23.join(process.cwd(), "exe", reviewDirName);
8955
9586
  if (existsSync18(reviewDir)) {
8956
9587
  for (const f of readdirSync8(reviewDir)) {
8957
9588
  if (f.startsWith("review-") && f.endsWith(".md")) {
8958
9589
  try {
8959
- unlinkSync11(path22.join(reviewDir, f));
9590
+ unlinkSync11(path23.join(reviewDir, f));
8960
9591
  } catch {
8961
9592
  }
8962
9593
  }
@@ -9002,7 +9633,7 @@ async function boot(options) {
9002
9633
  });
9003
9634
  const taskFile = String(r.task_file);
9004
9635
  try {
9005
- const filePath = path22.join(process.cwd(), taskFile);
9636
+ const filePath = path23.join(process.cwd(), taskFile);
9006
9637
  if (existsSync18(filePath)) {
9007
9638
  let content = readFileSync15(filePath, "utf8");
9008
9639
  content = content.replace(/\*\*Status:\*\* needs_review/, "**Status:** done");
@@ -9501,8 +10132,8 @@ async function boot(options) {
9501
10132
  })()
9502
10133
  ]);
9503
10134
  try {
9504
- const configPath = path22.join(
9505
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os10.homedir(), ".exe-os"),
10135
+ const configPath = path23.join(
10136
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path23.join(os11.homedir(), ".exe-os"),
9506
10137
  "config.json"
9507
10138
  );
9508
10139
  if (existsSync18(configPath)) {
@@ -9512,7 +10143,7 @@ async function boot(options) {
9512
10143
  } catch {
9513
10144
  }
9514
10145
  try {
9515
- const backfillFlagPath = path22.join(EXE_AI_DIR, "session-cache", "needs-backfill");
10146
+ const backfillFlagPath = path23.join(EXE_AI_DIR, "session-cache", "needs-backfill");
9516
10147
  const isBackfillNeeded = () => existsSync18(backfillFlagPath);
9517
10148
  const coverageResult = await client.execute({
9518
10149
  sql: `SELECT COUNT(*) as total,
@@ -9535,7 +10166,7 @@ async function boot(options) {
9535
10166
  let daemonRunning = false;
9536
10167
  let daemonUptime;
9537
10168
  let daemonRequestsServed;
9538
- const socketPath = path22.join(EXE_AI_DIR, "exed.sock");
10169
+ const socketPath = path23.join(EXE_AI_DIR, "exed.sock");
9539
10170
  if (existsSync18(socketPath)) {
9540
10171
  try {
9541
10172
  const net2 = await import("net");
@@ -9578,7 +10209,7 @@ async function boot(options) {
9578
10209
  }
9579
10210
  }
9580
10211
  if (!daemonRunning) {
9581
- const pidPath = path22.join(EXE_AI_DIR, "exed.pid");
10212
+ const pidPath = path23.join(EXE_AI_DIR, "exed.pid");
9582
10213
  if (existsSync18(pidPath)) {
9583
10214
  try {
9584
10215
  const pid = parseInt(readFileSync15(pidPath, "utf8").trim(), 10);
@@ -9592,7 +10223,7 @@ async function boot(options) {
9592
10223
  }
9593
10224
  if (nullCount === 0) {
9594
10225
  try {
9595
- const flagPath = path22.join(EXE_AI_DIR, "session-cache", "needs-backfill");
10226
+ const flagPath = path23.join(EXE_AI_DIR, "session-cache", "needs-backfill");
9596
10227
  if (existsSync18(flagPath)) {
9597
10228
  const { unlinkSync: unlinkSync12 } = await import("fs");
9598
10229
  unlinkSync12(flagPath);
@@ -9619,10 +10250,10 @@ async function boot(options) {
9619
10250
  const { spawn: spawn2 } = await import("child_process");
9620
10251
  const { fileURLToPath: fileURLToPath4 } = await import("url");
9621
10252
  const thisFile = fileURLToPath4(import.meta.url);
9622
- const backfillPath = path22.resolve(path22.dirname(thisFile), "backfill-vectors.js");
10253
+ const backfillPath = path23.resolve(path23.dirname(thisFile), "backfill-vectors.js");
9623
10254
  if (existsSync18(backfillPath)) {
9624
10255
  const { openSync: openSync3, closeSync: closeSync3 } = await import("fs");
9625
- const workerLogPath = path22.join(EXE_AI_DIR, "workers.log");
10256
+ const workerLogPath = path23.join(EXE_AI_DIR, "workers.log");
9626
10257
  let stderrFd = "ignore";
9627
10258
  try {
9628
10259
  stderrFd = openSync3(workerLogPath, "a");
@@ -9652,7 +10283,7 @@ async function boot(options) {
9652
10283
  const criticalBinaries = ["backfill-vectors.js", "scan-tasks.js"];
9653
10284
  const missing = [];
9654
10285
  for (const bin of criticalBinaries) {
9655
- const binPath = path22.resolve(path22.dirname(thisFile), bin);
10286
+ const binPath = path23.resolve(path23.dirname(thisFile), bin);
9656
10287
  if (!existsSync18(binPath)) {
9657
10288
  missing.push(`dist/bin/${bin}`);
9658
10289
  }
@@ -9682,7 +10313,7 @@ async function boot(options) {
9682
10313
  console.log(brief);
9683
10314
  return;
9684
10315
  }
9685
- const sessionDir = path22.join(EXE_AI_DIR, "sessions", coordinatorName);
10316
+ const sessionDir = path23.join(EXE_AI_DIR, "sessions", coordinatorName);
9686
10317
  await mkdir5(sessionDir, { recursive: true });
9687
10318
  const claudeMdContent = `${getSessionPrompt(coordinatorEmployee.systemPrompt)}
9688
10319
 
@@ -9691,7 +10322,7 @@ async function boot(options) {
9691
10322
  # Status Brief
9692
10323
 
9693
10324
  ${brief}`;
9694
- await writeFile6(path22.join(sessionDir, "CLAUDE.md"), claudeMdContent, "utf-8");
10325
+ await writeFile6(path23.join(sessionDir, "CLAUDE.md"), claudeMdContent, "utf-8");
9695
10326
  const unread = await readUnreadNotifications();
9696
10327
  if (unread.length > 0) {
9697
10328
  console.log(`\u{1F4EC} ${unread.length} unread notification${unread.length === 1 ? "" : "s"}`);
@@ -9700,8 +10331,8 @@ ${brief}`;
9700
10331
  await cleanupOldNotifications();
9701
10332
  console.log(brief);
9702
10333
  try {
9703
- const configPath2 = path22.join(
9704
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os10.homedir(), ".exe-os"),
10334
+ const configPath2 = path23.join(
10335
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path23.join(os11.homedir(), ".exe-os"),
9705
10336
  "config.json"
9706
10337
  );
9707
10338
  if (existsSync18(configPath2)) {