@askexenow/exe-os 0.9.6 → 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 +668 -37
  5. package/dist/bin/cli.js +1399 -607
  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 +795 -155
  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 +703 -72
  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 +1064 -273
  17. package/dist/bin/exe-heartbeat.js +676 -45
  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 +845 -152
  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 +668 -37
  33. package/dist/bin/exe-team.js +635 -13
  34. package/dist/bin/git-sweep.js +731 -91
  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 +735 -95
  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 +1038 -247
  43. package/dist/hooks/bug-report-worker.js +902 -172
  44. package/dist/hooks/commit-complete.js +729 -89
  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 +851 -158
  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 +685 -45
  52. package/dist/hooks/pre-compact.js +729 -89
  53. package/dist/hooks/pre-tool-use.js +883 -127
  54. package/dist/hooks/prompt-ingest-worker.js +758 -83
  55. package/dist/hooks/prompt-submit.js +1071 -321
  56. package/dist/hooks/response-ingest-worker.js +758 -83
  57. package/dist/hooks/session-end.js +732 -92
  58. package/dist/hooks/session-start.js +1042 -209
  59. package/dist/hooks/stop.js +691 -51
  60. package/dist/hooks/subagent-stop.js +685 -45
  61. package/dist/hooks/summary-worker.js +827 -134
  62. package/dist/index.js +1026 -234
  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 +905 -164
  73. package/dist/lib/hybrid-search.js +771 -88
  74. package/dist/lib/identity.js +27 -7
  75. package/dist/lib/messaging.js +66 -30
  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 +109 -73
  82. package/dist/lib/tmux-routing.js +98 -62
  83. package/dist/lib/token-spend.js +26 -6
  84. package/dist/mcp/server.js +1807 -472
  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 +301 -166
  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 +206 -40
  91. package/dist/mcp/tools/send-message.js +69 -33
  92. package/dist/mcp/tools/update-task.js +86 -50
  93. package/dist/runtime/index.js +731 -91
  94. package/dist/tui/App.js +864 -125
  95. package/package.json +3 -2
@@ -780,7 +780,7 @@ function isMultiInstance(agentName, employees) {
780
780
  if (!emp) return false;
781
781
  return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
782
782
  }
783
- var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES;
783
+ var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES, IDENTITY_DIR;
784
784
  var init_employees = __esm({
785
785
  "src/lib/employees.ts"() {
786
786
  "use strict";
@@ -789,16 +789,601 @@ var init_employees = __esm({
789
789
  DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
790
790
  COORDINATOR_ROLE = "COO";
791
791
  MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
792
+ IDENTITY_DIR = path5.join(EXE_AI_DIR, "identity");
793
+ }
794
+ });
795
+
796
+ // src/lib/database-adapter.ts
797
+ import os5 from "os";
798
+ import path6 from "path";
799
+ import { createRequire } from "module";
800
+ import { pathToFileURL } from "url";
801
+ function quotedIdentifier(identifier) {
802
+ return `"${identifier.replace(/"/g, '""')}"`;
803
+ }
804
+ function unqualifiedTableName(name) {
805
+ const raw = name.trim().replace(/^"|"$/g, "");
806
+ const parts = raw.split(".");
807
+ return parts[parts.length - 1].replace(/^"|"$/g, "").toLowerCase();
808
+ }
809
+ function stripTrailingSemicolon(sql) {
810
+ return sql.trim().replace(/;+\s*$/u, "");
811
+ }
812
+ function appendClause(sql, clause) {
813
+ const trimmed = stripTrailingSemicolon(sql);
814
+ const returningMatch = /\sRETURNING\b[\s\S]*$/iu.exec(trimmed);
815
+ if (!returningMatch) {
816
+ return `${trimmed}${clause}`;
817
+ }
818
+ const idx = returningMatch.index;
819
+ return `${trimmed.slice(0, idx)}${clause}${trimmed.slice(idx)}`;
820
+ }
821
+ function normalizeStatement(stmt) {
822
+ if (typeof stmt === "string") {
823
+ return { kind: "positional", sql: stmt, args: [] };
824
+ }
825
+ const sql = stmt.sql;
826
+ if (Array.isArray(stmt.args) || stmt.args === void 0) {
827
+ return { kind: "positional", sql, args: stmt.args ?? [] };
828
+ }
829
+ return { kind: "named", sql, args: stmt.args };
830
+ }
831
+ function rewriteBooleanLiterals(sql) {
832
+ let out = sql;
833
+ for (const column of BOOLEAN_COLUMN_NAMES) {
834
+ const scoped = `((?:\\b[a-z_][a-z0-9_]*\\.)?${column})`;
835
+ out = out.replace(new RegExp(`${scoped}\\s*=\\s*0\\b`, "giu"), "$1 = FALSE");
836
+ out = out.replace(new RegExp(`${scoped}\\s*=\\s*1\\b`, "giu"), "$1 = TRUE");
837
+ out = out.replace(new RegExp(`${scoped}\\s*!=\\s*0\\b`, "giu"), "$1 != FALSE");
838
+ out = out.replace(new RegExp(`${scoped}\\s*!=\\s*1\\b`, "giu"), "$1 != TRUE");
839
+ out = out.replace(new RegExp(`${scoped}\\s*<>\\s*0\\b`, "giu"), "$1 <> FALSE");
840
+ out = out.replace(new RegExp(`${scoped}\\s*<>\\s*1\\b`, "giu"), "$1 <> TRUE");
841
+ }
842
+ return out;
843
+ }
844
+ function rewriteInsertOrIgnore(sql) {
845
+ if (!/^\s*INSERT\s+OR\s+IGNORE\s+INTO\b/iu.test(sql)) {
846
+ return sql;
847
+ }
848
+ const replaced = sql.replace(/^\s*INSERT\s+OR\s+IGNORE\s+INTO\b/iu, "INSERT INTO");
849
+ return /\bON\s+CONFLICT\b/iu.test(replaced) ? replaced : appendClause(replaced, " ON CONFLICT DO NOTHING");
850
+ }
851
+ function rewriteInsertOrReplace(sql) {
852
+ const match = /^\s*INSERT\s+OR\s+REPLACE\s+INTO\s+([A-Za-z0-9_."]+)\s*\(([^)]+)\)([\s\S]*)$/iu.exec(sql);
853
+ if (!match) {
854
+ return sql;
855
+ }
856
+ const rawTable = match[1];
857
+ const rawColumns = match[2];
858
+ const remainder = match[3];
859
+ const tableName = unqualifiedTableName(rawTable);
860
+ const conflictKeys = UPSERT_KEYS[tableName];
861
+ if (!conflictKeys?.length) {
862
+ return sql;
863
+ }
864
+ const columns = rawColumns.split(",").map((col) => col.trim().replace(/^"|"$/g, ""));
865
+ const updateColumns = columns.filter((col) => !conflictKeys.includes(col));
866
+ const conflictTarget = conflictKeys.map(quotedIdentifier).join(", ");
867
+ const updateClause = updateColumns.length === 0 ? " DO NOTHING" : ` DO UPDATE SET ${updateColumns.map((col) => `${quotedIdentifier(col)} = EXCLUDED.${quotedIdentifier(col)}`).join(", ")}`;
868
+ return `INSERT INTO ${rawTable} (${rawColumns})${appendClause(remainder, ` ON CONFLICT (${conflictTarget})${updateClause}`)}`;
869
+ }
870
+ function rewriteSql(sql) {
871
+ let out = sql;
872
+ out = out.replace(/\bdatetime\(\s*['"]now['"]\s*\)/giu, "CURRENT_TIMESTAMP");
873
+ out = out.replace(/\bvector32\s*\(\s*\?\s*\)/giu, "?");
874
+ out = rewriteBooleanLiterals(out);
875
+ out = rewriteInsertOrReplace(out);
876
+ out = rewriteInsertOrIgnore(out);
877
+ return stripTrailingSemicolon(out);
878
+ }
879
+ function toBoolean(value) {
880
+ if (value === null || value === void 0) return value;
881
+ if (typeof value === "boolean") return value;
882
+ if (typeof value === "number") return value !== 0;
883
+ if (typeof value === "bigint") return value !== 0n;
884
+ if (typeof value === "string") {
885
+ const normalized = value.trim().toLowerCase();
886
+ if (normalized === "0" || normalized === "false") return false;
887
+ if (normalized === "1" || normalized === "true") return true;
888
+ }
889
+ return Boolean(value);
890
+ }
891
+ function countQuestionMarks(sql, end) {
892
+ let count = 0;
893
+ let inSingle = false;
894
+ let inDouble = false;
895
+ let inLineComment = false;
896
+ let inBlockComment = false;
897
+ for (let i = 0; i < end; i++) {
898
+ const ch = sql[i];
899
+ const next = sql[i + 1];
900
+ if (inLineComment) {
901
+ if (ch === "\n") inLineComment = false;
902
+ continue;
903
+ }
904
+ if (inBlockComment) {
905
+ if (ch === "*" && next === "/") {
906
+ inBlockComment = false;
907
+ i += 1;
908
+ }
909
+ continue;
910
+ }
911
+ if (!inSingle && !inDouble && ch === "-" && next === "-") {
912
+ inLineComment = true;
913
+ i += 1;
914
+ continue;
915
+ }
916
+ if (!inSingle && !inDouble && ch === "/" && next === "*") {
917
+ inBlockComment = true;
918
+ i += 1;
919
+ continue;
920
+ }
921
+ if (!inDouble && ch === "'" && sql[i - 1] !== "\\") {
922
+ inSingle = !inSingle;
923
+ continue;
924
+ }
925
+ if (!inSingle && ch === '"' && sql[i - 1] !== "\\") {
926
+ inDouble = !inDouble;
927
+ continue;
928
+ }
929
+ if (!inSingle && !inDouble && ch === "?") {
930
+ count += 1;
931
+ }
932
+ }
933
+ return count;
934
+ }
935
+ function findBooleanPlaceholderIndexes(sql) {
936
+ const indexes = /* @__PURE__ */ new Set();
937
+ for (const column of BOOLEAN_COLUMN_NAMES) {
938
+ const pattern = new RegExp(`(?:\\b[a-z_][a-z0-9_]*\\.)?${column}\\s*=\\s*\\?`, "giu");
939
+ for (const match of sql.matchAll(pattern)) {
940
+ const matchText = match[0];
941
+ const qIndex = match.index + matchText.lastIndexOf("?");
942
+ indexes.add(countQuestionMarks(sql, qIndex + 1));
943
+ }
944
+ }
945
+ return indexes;
946
+ }
947
+ function coerceInsertBooleanArgs(sql, args2) {
948
+ const match = /^\s*INSERT(?:\s+OR\s+(?:IGNORE|REPLACE))?\s+INTO\s+([A-Za-z0-9_."]+)\s*\(([^)]+)\)/iu.exec(sql);
949
+ if (!match) return;
950
+ const rawTable = match[1];
951
+ const rawColumns = match[2];
952
+ const boolColumns = BOOLEAN_COLUMNS_BY_TABLE[unqualifiedTableName(rawTable)];
953
+ if (!boolColumns?.size) return;
954
+ const columns = rawColumns.split(",").map((col) => col.trim().replace(/^"|"$/g, ""));
955
+ for (const [index, column] of columns.entries()) {
956
+ if (boolColumns.has(column) && index < args2.length) {
957
+ args2[index] = toBoolean(args2[index]);
958
+ }
959
+ }
960
+ }
961
+ function coerceUpdateBooleanArgs(sql, args2) {
962
+ const match = /^\s*UPDATE\s+([A-Za-z0-9_."]+)\s+SET\s+([\s\S]+?)(?:\s+WHERE\b|$)/iu.exec(sql);
963
+ if (!match) return;
964
+ const rawTable = match[1];
965
+ const setClause = match[2];
966
+ const boolColumns = BOOLEAN_COLUMNS_BY_TABLE[unqualifiedTableName(rawTable)];
967
+ if (!boolColumns?.size) return;
968
+ const assignments = setClause.split(",");
969
+ let placeholderIndex = 0;
970
+ for (const assignment of assignments) {
971
+ if (!assignment.includes("?")) continue;
972
+ placeholderIndex += 1;
973
+ const colMatch = /^\s*(?:[A-Za-z_][A-Za-z0-9_]*\.)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*\?/iu.exec(assignment);
974
+ if (colMatch && boolColumns.has(colMatch[1])) {
975
+ args2[placeholderIndex - 1] = toBoolean(args2[placeholderIndex - 1]);
976
+ }
977
+ }
978
+ }
979
+ function coerceBooleanArgs(sql, args2) {
980
+ const nextArgs = [...args2];
981
+ coerceInsertBooleanArgs(sql, nextArgs);
982
+ coerceUpdateBooleanArgs(sql, nextArgs);
983
+ const placeholderIndexes = findBooleanPlaceholderIndexes(sql);
984
+ for (const index of placeholderIndexes) {
985
+ if (index > 0 && index <= nextArgs.length) {
986
+ nextArgs[index - 1] = toBoolean(nextArgs[index - 1]);
987
+ }
988
+ }
989
+ return nextArgs;
990
+ }
991
+ function convertQuestionMarksToDollarParams(sql) {
992
+ let out = "";
993
+ let placeholder = 0;
994
+ let inSingle = false;
995
+ let inDouble = false;
996
+ let inLineComment = false;
997
+ let inBlockComment = false;
998
+ for (let i = 0; i < sql.length; i++) {
999
+ const ch = sql[i];
1000
+ const next = sql[i + 1];
1001
+ if (inLineComment) {
1002
+ out += ch;
1003
+ if (ch === "\n") inLineComment = false;
1004
+ continue;
1005
+ }
1006
+ if (inBlockComment) {
1007
+ out += ch;
1008
+ if (ch === "*" && next === "/") {
1009
+ out += next;
1010
+ inBlockComment = false;
1011
+ i += 1;
1012
+ }
1013
+ continue;
1014
+ }
1015
+ if (!inSingle && !inDouble && ch === "-" && next === "-") {
1016
+ out += ch + next;
1017
+ inLineComment = true;
1018
+ i += 1;
1019
+ continue;
1020
+ }
1021
+ if (!inSingle && !inDouble && ch === "/" && next === "*") {
1022
+ out += ch + next;
1023
+ inBlockComment = true;
1024
+ i += 1;
1025
+ continue;
1026
+ }
1027
+ if (!inDouble && ch === "'" && sql[i - 1] !== "\\") {
1028
+ inSingle = !inSingle;
1029
+ out += ch;
1030
+ continue;
1031
+ }
1032
+ if (!inSingle && ch === '"' && sql[i - 1] !== "\\") {
1033
+ inDouble = !inDouble;
1034
+ out += ch;
1035
+ continue;
1036
+ }
1037
+ if (!inSingle && !inDouble && ch === "?") {
1038
+ placeholder += 1;
1039
+ out += `$${placeholder}`;
1040
+ continue;
1041
+ }
1042
+ out += ch;
1043
+ }
1044
+ return out;
1045
+ }
1046
+ function translateStatementForPostgres(stmt) {
1047
+ const normalized = normalizeStatement(stmt);
1048
+ if (normalized.kind === "named") {
1049
+ throw new Error("Named SQL parameters are not supported by the Prisma adapter.");
1050
+ }
1051
+ const rewrittenSql = rewriteSql(normalized.sql);
1052
+ const coercedArgs = coerceBooleanArgs(rewrittenSql, normalized.args);
1053
+ return {
1054
+ sql: convertQuestionMarksToDollarParams(rewrittenSql),
1055
+ args: coercedArgs
1056
+ };
1057
+ }
1058
+ function shouldBypassPostgres(stmt) {
1059
+ const normalized = normalizeStatement(stmt);
1060
+ if (normalized.kind === "named") {
1061
+ return true;
1062
+ }
1063
+ return IMMEDIATE_FALLBACK_PATTERNS.some((pattern) => pattern.test(normalized.sql));
1064
+ }
1065
+ function shouldFallbackOnError(error) {
1066
+ const message = error instanceof Error ? error.message : String(error);
1067
+ return /42P01|42883|42601|does not exist|syntax error|not supported|Named SQL parameters are not supported/iu.test(message);
1068
+ }
1069
+ function isReadQuery(sql) {
1070
+ const trimmed = sql.trimStart();
1071
+ return /^(SELECT|WITH|SHOW|EXPLAIN|VALUES)\b/iu.test(trimmed) || /\bRETURNING\b/iu.test(trimmed);
1072
+ }
1073
+ function buildRow(row, columns) {
1074
+ const values = columns.map((column) => row[column]);
1075
+ return Object.assign(values, row);
1076
+ }
1077
+ function buildResultSet(rows, rowsAffected = 0) {
1078
+ const columns = rows[0] ? Object.keys(rows[0]) : [];
1079
+ const resultRows = rows.map((row) => buildRow(row, columns));
1080
+ return {
1081
+ columns,
1082
+ columnTypes: columns.map(() => ""),
1083
+ rows: resultRows,
1084
+ rowsAffected,
1085
+ lastInsertRowid: void 0,
1086
+ toJSON() {
1087
+ return {
1088
+ columns,
1089
+ columnTypes: columns.map(() => ""),
1090
+ rows,
1091
+ rowsAffected,
1092
+ lastInsertRowid: void 0
1093
+ };
1094
+ }
1095
+ };
1096
+ }
1097
+ async function loadPrismaClient() {
1098
+ if (!prismaClientPromise) {
1099
+ prismaClientPromise = (async () => {
1100
+ const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
1101
+ if (explicitPath) {
1102
+ const module2 = await import(pathToFileURL(explicitPath).href);
1103
+ const PrismaClient2 = module2.PrismaClient ?? module2.default?.PrismaClient;
1104
+ if (!PrismaClient2) {
1105
+ throw new Error(`No PrismaClient export found at ${explicitPath}`);
1106
+ }
1107
+ return new PrismaClient2();
1108
+ }
1109
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path6.join(os5.homedir(), "exe-db");
1110
+ const requireFromExeDb = createRequire(path6.join(exeDbRoot, "package.json"));
1111
+ const prismaEntry = requireFromExeDb.resolve("@prisma/client");
1112
+ const module = await import(pathToFileURL(prismaEntry).href);
1113
+ const PrismaClient = module.PrismaClient ?? module.default?.PrismaClient;
1114
+ if (!PrismaClient) {
1115
+ throw new Error(`No PrismaClient export found in ${prismaEntry}`);
1116
+ }
1117
+ return new PrismaClient();
1118
+ })();
1119
+ }
1120
+ return prismaClientPromise;
1121
+ }
1122
+ async function ensureCompatibilityViews(prisma) {
1123
+ if (!compatibilityBootstrapPromise) {
1124
+ compatibilityBootstrapPromise = (async () => {
1125
+ for (const mapping of VIEW_MAPPINGS) {
1126
+ const relation = mapping.source.replace(/"/g, "");
1127
+ const rows = await prisma.$queryRawUnsafe(
1128
+ "SELECT to_regclass($1) AS regclass",
1129
+ relation
1130
+ );
1131
+ if (!rows[0]?.regclass) {
1132
+ continue;
1133
+ }
1134
+ await prisma.$executeRawUnsafe(
1135
+ `CREATE OR REPLACE VIEW public.${quotedIdentifier(mapping.view)} AS SELECT * FROM ${mapping.source}`
1136
+ );
1137
+ }
1138
+ })();
1139
+ }
1140
+ return compatibilityBootstrapPromise;
1141
+ }
1142
+ async function executeOnPrisma(executor, stmt) {
1143
+ const translated = translateStatementForPostgres(stmt);
1144
+ if (isReadQuery(translated.sql)) {
1145
+ const rows = await executor.$queryRawUnsafe(
1146
+ translated.sql,
1147
+ ...translated.args
1148
+ );
1149
+ return buildResultSet(rows, /\bRETURNING\b/iu.test(translated.sql) ? rows.length : 0);
1150
+ }
1151
+ const rowsAffected = await executor.$executeRawUnsafe(translated.sql, ...translated.args);
1152
+ return buildResultSet([], rowsAffected);
1153
+ }
1154
+ function splitSqlStatements(sql) {
1155
+ const parts = [];
1156
+ let current = "";
1157
+ let inSingle = false;
1158
+ let inDouble = false;
1159
+ let inLineComment = false;
1160
+ let inBlockComment = false;
1161
+ for (let i = 0; i < sql.length; i++) {
1162
+ const ch = sql[i];
1163
+ const next = sql[i + 1];
1164
+ if (inLineComment) {
1165
+ current += ch;
1166
+ if (ch === "\n") inLineComment = false;
1167
+ continue;
1168
+ }
1169
+ if (inBlockComment) {
1170
+ current += ch;
1171
+ if (ch === "*" && next === "/") {
1172
+ current += next;
1173
+ inBlockComment = false;
1174
+ i += 1;
1175
+ }
1176
+ continue;
1177
+ }
1178
+ if (!inSingle && !inDouble && ch === "-" && next === "-") {
1179
+ current += ch + next;
1180
+ inLineComment = true;
1181
+ i += 1;
1182
+ continue;
1183
+ }
1184
+ if (!inSingle && !inDouble && ch === "/" && next === "*") {
1185
+ current += ch + next;
1186
+ inBlockComment = true;
1187
+ i += 1;
1188
+ continue;
1189
+ }
1190
+ if (!inDouble && ch === "'" && sql[i - 1] !== "\\") {
1191
+ inSingle = !inSingle;
1192
+ current += ch;
1193
+ continue;
1194
+ }
1195
+ if (!inSingle && ch === '"' && sql[i - 1] !== "\\") {
1196
+ inDouble = !inDouble;
1197
+ current += ch;
1198
+ continue;
1199
+ }
1200
+ if (!inSingle && !inDouble && ch === ";") {
1201
+ if (current.trim()) {
1202
+ parts.push(current.trim());
1203
+ }
1204
+ current = "";
1205
+ continue;
1206
+ }
1207
+ current += ch;
1208
+ }
1209
+ if (current.trim()) {
1210
+ parts.push(current.trim());
1211
+ }
1212
+ return parts;
1213
+ }
1214
+ async function createPrismaDbAdapter(fallbackClient) {
1215
+ const prisma = await loadPrismaClient();
1216
+ await ensureCompatibilityViews(prisma);
1217
+ let closed = false;
1218
+ let adapter;
1219
+ const fallbackExecute = async (stmt, error) => {
1220
+ if (!fallbackClient) {
1221
+ if (error) throw error;
1222
+ throw new Error("No fallback SQLite client is available for this Prisma-routed query.");
1223
+ }
1224
+ if (error) {
1225
+ process.stderr.write(
1226
+ `[database-adapter] Falling back to SQLite: ${error instanceof Error ? error.message : String(error)}
1227
+ `
1228
+ );
1229
+ }
1230
+ return fallbackClient.execute(stmt);
1231
+ };
1232
+ adapter = {
1233
+ async execute(stmt) {
1234
+ if (shouldBypassPostgres(stmt)) {
1235
+ return fallbackExecute(stmt);
1236
+ }
1237
+ try {
1238
+ return await executeOnPrisma(prisma, stmt);
1239
+ } catch (error) {
1240
+ if (shouldFallbackOnError(error)) {
1241
+ return fallbackExecute(stmt, error);
1242
+ }
1243
+ throw error;
1244
+ }
1245
+ },
1246
+ async batch(stmts, mode) {
1247
+ if (stmts.some((stmt) => shouldBypassPostgres(stmt))) {
1248
+ if (!fallbackClient) {
1249
+ throw new Error("Cannot batch unsupported SQLite-only statements without a fallback client.");
1250
+ }
1251
+ return fallbackClient.batch(stmts, mode);
1252
+ }
1253
+ try {
1254
+ if (prisma.$transaction) {
1255
+ return await prisma.$transaction(async (tx) => {
1256
+ const results2 = [];
1257
+ for (const stmt of stmts) {
1258
+ results2.push(await executeOnPrisma(tx, stmt));
1259
+ }
1260
+ return results2;
1261
+ });
1262
+ }
1263
+ const results = [];
1264
+ for (const stmt of stmts) {
1265
+ results.push(await executeOnPrisma(prisma, stmt));
1266
+ }
1267
+ return results;
1268
+ } catch (error) {
1269
+ if (fallbackClient && shouldFallbackOnError(error)) {
1270
+ process.stderr.write(
1271
+ `[database-adapter] Falling back batch to SQLite: ${error instanceof Error ? error.message : String(error)}
1272
+ `
1273
+ );
1274
+ return fallbackClient.batch(stmts, mode);
1275
+ }
1276
+ throw error;
1277
+ }
1278
+ },
1279
+ async migrate(stmts) {
1280
+ if (fallbackClient) {
1281
+ return fallbackClient.migrate(stmts);
1282
+ }
1283
+ return adapter.batch(stmts, "deferred");
1284
+ },
1285
+ async transaction(mode) {
1286
+ if (!fallbackClient) {
1287
+ throw new Error("Interactive transactions are only supported on the SQLite fallback client.");
1288
+ }
1289
+ return fallbackClient.transaction(mode);
1290
+ },
1291
+ async executeMultiple(sql) {
1292
+ if (fallbackClient && shouldBypassPostgres(sql)) {
1293
+ return fallbackClient.executeMultiple(sql);
1294
+ }
1295
+ for (const statement of splitSqlStatements(sql)) {
1296
+ await adapter.execute(statement);
1297
+ }
1298
+ },
1299
+ async sync() {
1300
+ if (fallbackClient) {
1301
+ return fallbackClient.sync();
1302
+ }
1303
+ return { frame_no: 0, frames_synced: 0 };
1304
+ },
1305
+ close() {
1306
+ closed = true;
1307
+ prismaClientPromise = null;
1308
+ compatibilityBootstrapPromise = null;
1309
+ void prisma.$disconnect?.();
1310
+ },
1311
+ get closed() {
1312
+ return closed;
1313
+ },
1314
+ get protocol() {
1315
+ return "prisma-postgres";
1316
+ }
1317
+ };
1318
+ return adapter;
1319
+ }
1320
+ var VIEW_MAPPINGS, UPSERT_KEYS, BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES, IMMEDIATE_FALLBACK_PATTERNS, prismaClientPromise, compatibilityBootstrapPromise;
1321
+ var init_database_adapter = __esm({
1322
+ "src/lib/database-adapter.ts"() {
1323
+ "use strict";
1324
+ VIEW_MAPPINGS = [
1325
+ { view: "memories", source: "memory.memory_records" },
1326
+ { view: "tasks", source: "memory.tasks" },
1327
+ { view: "behaviors", source: "memory.behaviors" },
1328
+ { view: "entities", source: "memory.entities" },
1329
+ { view: "relationships", source: "memory.relationships" },
1330
+ { view: "entity_memories", source: "memory.entity_memories" },
1331
+ { view: "entity_aliases", source: "memory.entity_aliases" },
1332
+ { view: "notifications", source: "memory.notifications" },
1333
+ { view: "messages", source: "memory.messages" },
1334
+ { view: "users", source: "wiki.users" },
1335
+ { view: "workspaces", source: "wiki.workspaces" },
1336
+ { view: "workspace_users", source: "wiki.workspace_users" },
1337
+ { view: "documents", source: "wiki.workspace_documents" },
1338
+ { view: "chats", source: "wiki.workspace_chats" }
1339
+ ];
1340
+ UPSERT_KEYS = {
1341
+ memories: ["id"],
1342
+ tasks: ["id"],
1343
+ behaviors: ["id"],
1344
+ entities: ["id"],
1345
+ relationships: ["id"],
1346
+ entity_aliases: ["alias"],
1347
+ notifications: ["id"],
1348
+ messages: ["id"],
1349
+ users: ["id"],
1350
+ workspaces: ["id"],
1351
+ workspace_users: ["id"],
1352
+ documents: ["id"],
1353
+ chats: ["id"]
1354
+ };
1355
+ BOOLEAN_COLUMNS_BY_TABLE = {
1356
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
1357
+ behaviors: /* @__PURE__ */ new Set(["active"]),
1358
+ notifications: /* @__PURE__ */ new Set(["read"]),
1359
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
1360
+ };
1361
+ BOOLEAN_COLUMN_NAMES = new Set(
1362
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
1363
+ );
1364
+ IMMEDIATE_FALLBACK_PATTERNS = [
1365
+ /\bPRAGMA\b/i,
1366
+ /\bsqlite_master\b/i,
1367
+ /(?:^|[.\s])(?:memories|conversations|entities)_fts\b/i,
1368
+ /\bMATCH\b/i,
1369
+ /\bvector_distance_cos\s*\(/i,
1370
+ /\bjson_extract\s*\(/i,
1371
+ /\bjulianday\s*\(/i,
1372
+ /\bstrftime\s*\(/i,
1373
+ /\blast_insert_rowid\s*\(/i
1374
+ ];
1375
+ prismaClientPromise = null;
1376
+ compatibilityBootstrapPromise = null;
792
1377
  }
793
1378
  });
794
1379
 
795
1380
  // src/lib/exe-daemon-client.ts
796
1381
  import net from "net";
797
- import os5 from "os";
1382
+ import os6 from "os";
798
1383
  import { spawn } from "child_process";
799
1384
  import { randomUUID } from "crypto";
800
1385
  import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
801
- import path6 from "path";
1386
+ import path7 from "path";
802
1387
  import { fileURLToPath } from "url";
803
1388
  function handleData(chunk) {
804
1389
  _buffer += chunk.toString();
@@ -849,17 +1434,17 @@ function cleanupStaleFiles() {
849
1434
  }
850
1435
  }
851
1436
  function findPackageRoot() {
852
- let dir = path6.dirname(fileURLToPath(import.meta.url));
853
- const { root } = path6.parse(dir);
1437
+ let dir = path7.dirname(fileURLToPath(import.meta.url));
1438
+ const { root } = path7.parse(dir);
854
1439
  while (dir !== root) {
855
- if (existsSync6(path6.join(dir, "package.json"))) return dir;
856
- dir = path6.dirname(dir);
1440
+ if (existsSync6(path7.join(dir, "package.json"))) return dir;
1441
+ dir = path7.dirname(dir);
857
1442
  }
858
1443
  return null;
859
1444
  }
860
1445
  function spawnDaemon() {
861
- const freeGB = os5.freemem() / (1024 * 1024 * 1024);
862
- const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
1446
+ const freeGB = os6.freemem() / (1024 * 1024 * 1024);
1447
+ const totalGB = os6.totalmem() / (1024 * 1024 * 1024);
863
1448
  if (totalGB <= 8) {
864
1449
  process.stderr.write(
865
1450
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
@@ -879,7 +1464,7 @@ function spawnDaemon() {
879
1464
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
880
1465
  return;
881
1466
  }
882
- const daemonPath = path6.join(pkgRoot, "dist", "lib", "exe-daemon.js");
1467
+ const daemonPath = path7.join(pkgRoot, "dist", "lib", "exe-daemon.js");
883
1468
  if (!existsSync6(daemonPath)) {
884
1469
  process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
885
1470
  `);
@@ -888,7 +1473,7 @@ function spawnDaemon() {
888
1473
  const resolvedPath = daemonPath;
889
1474
  process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
890
1475
  `);
891
- const logPath = path6.join(path6.dirname(SOCKET_PATH), "exed.log");
1476
+ const logPath = path7.join(path7.dirname(SOCKET_PATH), "exed.log");
892
1477
  let stderrFd = "ignore";
893
1478
  try {
894
1479
  stderrFd = openSync(logPath, "a");
@@ -1035,9 +1620,9 @@ var init_exe_daemon_client = __esm({
1035
1620
  "src/lib/exe-daemon-client.ts"() {
1036
1621
  "use strict";
1037
1622
  init_config();
1038
- SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path6.join(EXE_AI_DIR, "exed.sock");
1039
- PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path6.join(EXE_AI_DIR, "exed.pid");
1040
- SPAWN_LOCK_PATH = path6.join(EXE_AI_DIR, "exed-spawn.lock");
1623
+ SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path7.join(EXE_AI_DIR, "exed.sock");
1624
+ PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path7.join(EXE_AI_DIR, "exed.pid");
1625
+ SPAWN_LOCK_PATH = path7.join(EXE_AI_DIR, "exed-spawn.lock");
1041
1626
  SPAWN_LOCK_STALE_MS = 3e4;
1042
1627
  CONNECT_TIMEOUT_MS = 15e3;
1043
1628
  REQUEST_TIMEOUT_MS = 3e4;
@@ -1119,7 +1704,7 @@ __export(db_daemon_client_exports, {
1119
1704
  createDaemonDbClient: () => createDaemonDbClient,
1120
1705
  initDaemonDbClient: () => initDaemonDbClient
1121
1706
  });
1122
- function normalizeStatement(stmt) {
1707
+ function normalizeStatement2(stmt) {
1123
1708
  if (typeof stmt === "string") {
1124
1709
  return { sql: stmt, args: [] };
1125
1710
  }
@@ -1143,7 +1728,7 @@ function createDaemonDbClient(fallbackClient) {
1143
1728
  if (!_useDaemon || !isClientConnected()) {
1144
1729
  return fallbackClient.execute(stmt);
1145
1730
  }
1146
- const { sql, args: args2 } = normalizeStatement(stmt);
1731
+ const { sql, args: args2 } = normalizeStatement2(stmt);
1147
1732
  const response = await sendDaemonRequest({
1148
1733
  type: "db-execute",
1149
1734
  sql,
@@ -1168,7 +1753,7 @@ function createDaemonDbClient(fallbackClient) {
1168
1753
  if (!_useDaemon || !isClientConnected()) {
1169
1754
  return fallbackClient.batch(stmts, mode);
1170
1755
  }
1171
- const statements = stmts.map(normalizeStatement);
1756
+ const statements = stmts.map(normalizeStatement2);
1172
1757
  const response = await sendDaemonRequest({
1173
1758
  type: "db-batch",
1174
1759
  statements,
@@ -1263,6 +1848,18 @@ __export(database_exports, {
1263
1848
  });
1264
1849
  import { createClient } from "@libsql/client";
1265
1850
  async function initDatabase(config) {
1851
+ if (_walCheckpointTimer) {
1852
+ clearInterval(_walCheckpointTimer);
1853
+ _walCheckpointTimer = null;
1854
+ }
1855
+ if (_daemonClient) {
1856
+ _daemonClient.close();
1857
+ _daemonClient = null;
1858
+ }
1859
+ if (_adapterClient && _adapterClient !== _resilientClient) {
1860
+ _adapterClient.close();
1861
+ }
1862
+ _adapterClient = null;
1266
1863
  if (_client) {
1267
1864
  _client.close();
1268
1865
  _client = null;
@@ -1276,6 +1873,7 @@ async function initDatabase(config) {
1276
1873
  }
1277
1874
  _client = createClient(opts);
1278
1875
  _resilientClient = wrapWithRetry(_client);
1876
+ _adapterClient = _resilientClient;
1279
1877
  _client.execute("PRAGMA busy_timeout = 30000").catch(() => {
1280
1878
  });
1281
1879
  _client.execute("PRAGMA journal_mode = WAL").catch(() => {
@@ -1286,14 +1884,20 @@ async function initDatabase(config) {
1286
1884
  });
1287
1885
  }, 3e4);
1288
1886
  _walCheckpointTimer.unref();
1887
+ if (process.env.DATABASE_URL) {
1888
+ _adapterClient = await createPrismaDbAdapter(_resilientClient);
1889
+ }
1289
1890
  }
1290
1891
  function isInitialized() {
1291
- return _client !== null;
1892
+ return _adapterClient !== null || _client !== null;
1292
1893
  }
1293
1894
  function getClient() {
1294
- if (!_resilientClient) {
1895
+ if (!_adapterClient) {
1295
1896
  throw new Error("Database client not initialized. Call initDatabase() first.");
1296
1897
  }
1898
+ if (process.env.DATABASE_URL) {
1899
+ return _adapterClient;
1900
+ }
1297
1901
  if (process.env.EXE_IS_DAEMON === "1") {
1298
1902
  return _resilientClient;
1299
1903
  }
@@ -1303,6 +1907,7 @@ function getClient() {
1303
1907
  return _resilientClient;
1304
1908
  }
1305
1909
  async function initDaemonClient() {
1910
+ if (process.env.DATABASE_URL) return;
1306
1911
  if (process.env.EXE_IS_DAEMON === "1") return;
1307
1912
  if (!_resilientClient) return;
1308
1913
  try {
@@ -2247,26 +2852,36 @@ async function ensureSchema() {
2247
2852
  }
2248
2853
  }
2249
2854
  async function disposeDatabase() {
2855
+ if (_walCheckpointTimer) {
2856
+ clearInterval(_walCheckpointTimer);
2857
+ _walCheckpointTimer = null;
2858
+ }
2250
2859
  if (_daemonClient) {
2251
2860
  _daemonClient.close();
2252
2861
  _daemonClient = null;
2253
2862
  }
2863
+ if (_adapterClient && _adapterClient !== _resilientClient) {
2864
+ _adapterClient.close();
2865
+ }
2866
+ _adapterClient = null;
2254
2867
  if (_client) {
2255
2868
  _client.close();
2256
2869
  _client = null;
2257
2870
  _resilientClient = null;
2258
2871
  }
2259
2872
  }
2260
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, initTurso, disposeTurso;
2873
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
2261
2874
  var init_database = __esm({
2262
2875
  "src/lib/database.ts"() {
2263
2876
  "use strict";
2264
2877
  init_db_retry();
2265
2878
  init_employees();
2879
+ init_database_adapter();
2266
2880
  _client = null;
2267
2881
  _resilientClient = null;
2268
2882
  _walCheckpointTimer = null;
2269
2883
  _daemonClient = null;
2884
+ _adapterClient = null;
2270
2885
  initTurso = initDatabase;
2271
2886
  disposeTurso = disposeDatabase;
2272
2887
  }
@@ -2275,16 +2890,16 @@ var init_database = __esm({
2275
2890
  // src/lib/license.ts
2276
2891
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
2277
2892
  import { randomUUID as randomUUID2 } from "crypto";
2278
- import path7 from "path";
2893
+ import path8 from "path";
2279
2894
  import { jwtVerify, importSPKI } from "jose";
2280
2895
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, PLAN_LIMITS;
2281
2896
  var init_license = __esm({
2282
2897
  "src/lib/license.ts"() {
2283
2898
  "use strict";
2284
2899
  init_config();
2285
- LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
2286
- CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
2287
- DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
2900
+ LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
2901
+ CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
2902
+ DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
2288
2903
  PLAN_LIMITS = {
2289
2904
  free: { devices: 1, employees: 1, memories: 5e3 },
2290
2905
  pro: { devices: 3, employees: 5, memories: 1e5 },
@@ -2297,7 +2912,7 @@ var init_license = __esm({
2297
2912
 
2298
2913
  // src/lib/plan-limits.ts
2299
2914
  import { readFileSync as readFileSync8, existsSync as existsSync8 } from "fs";
2300
- import path8 from "path";
2915
+ import path9 from "path";
2301
2916
  function getLicenseSync() {
2302
2917
  try {
2303
2918
  if (!existsSync8(CACHE_PATH2)) return freeLicense();
@@ -2369,14 +2984,14 @@ var init_plan_limits = __esm({
2369
2984
  this.name = "PlanLimitError";
2370
2985
  }
2371
2986
  };
2372
- CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
2987
+ CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
2373
2988
  }
2374
2989
  });
2375
2990
 
2376
2991
  // src/lib/notifications.ts
2377
2992
  import crypto from "crypto";
2378
- import path9 from "path";
2379
- import os6 from "os";
2993
+ import path10 from "path";
2994
+ import os7 from "os";
2380
2995
  import {
2381
2996
  readFileSync as readFileSync9,
2382
2997
  readdirSync,
@@ -2532,8 +3147,8 @@ __export(tasks_crud_exports, {
2532
3147
  writeCheckpoint: () => writeCheckpoint
2533
3148
  });
2534
3149
  import crypto3 from "crypto";
2535
- import path10 from "path";
2536
- import os7 from "os";
3150
+ import path11 from "path";
3151
+ import os8 from "os";
2537
3152
  import { execSync as execSync4 } from "child_process";
2538
3153
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
2539
3154
  import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
@@ -2711,8 +3326,8 @@ ${laneWarning}` : laneWarning;
2711
3326
  }
2712
3327
  if (input.baseDir) {
2713
3328
  try {
2714
- await mkdir3(path10.join(input.baseDir, "exe", "output"), { recursive: true });
2715
- await mkdir3(path10.join(input.baseDir, "exe", "research"), { recursive: true });
3329
+ await mkdir3(path11.join(input.baseDir, "exe", "output"), { recursive: true });
3330
+ await mkdir3(path11.join(input.baseDir, "exe", "research"), { recursive: true });
2716
3331
  await ensureArchitectureDoc(input.baseDir, input.projectName);
2717
3332
  await ensureGitignoreExe(input.baseDir);
2718
3333
  } catch {
@@ -2748,9 +3363,9 @@ ${laneWarning}` : laneWarning;
2748
3363
  });
2749
3364
  if (input.baseDir) {
2750
3365
  try {
2751
- const EXE_OS_DIR = path10.join(os7.homedir(), ".exe-os");
2752
- const mdPath = path10.join(EXE_OS_DIR, taskFile);
2753
- const mdDir = path10.dirname(mdPath);
3366
+ const EXE_OS_DIR = path11.join(os8.homedir(), ".exe-os");
3367
+ const mdPath = path11.join(EXE_OS_DIR, taskFile);
3368
+ const mdDir = path11.dirname(mdPath);
2754
3369
  if (!existsSync10(mdDir)) await mkdir3(mdDir, { recursive: true });
2755
3370
  const reviewer = input.reviewer ?? input.assignedBy;
2756
3371
  const mdContent = `# ${input.title}
@@ -3051,7 +3666,7 @@ async function deleteTaskCore(taskId, _baseDir) {
3051
3666
  return { taskFile, assignedTo, assignedBy, taskSlug };
3052
3667
  }
3053
3668
  async function ensureArchitectureDoc(baseDir, projectName2) {
3054
- const archPath = path10.join(baseDir, "exe", "ARCHITECTURE.md");
3669
+ const archPath = path11.join(baseDir, "exe", "ARCHITECTURE.md");
3055
3670
  try {
3056
3671
  if (existsSync10(archPath)) return;
3057
3672
  const template = [
@@ -3086,7 +3701,7 @@ async function ensureArchitectureDoc(baseDir, projectName2) {
3086
3701
  }
3087
3702
  }
3088
3703
  async function ensureGitignoreExe(baseDir) {
3089
- const gitignorePath = path10.join(baseDir, ".gitignore");
3704
+ const gitignorePath = path11.join(baseDir, ".gitignore");
3090
3705
  try {
3091
3706
  if (existsSync10(gitignorePath)) {
3092
3707
  const content = readFileSync10(gitignorePath, "utf-8");
@@ -3120,13 +3735,13 @@ var init_tasks_crud = __esm({
3120
3735
  });
3121
3736
 
3122
3737
  // src/lib/tasks-review.ts
3123
- import path11 from "path";
3738
+ import path12 from "path";
3124
3739
  import { existsSync as existsSync11, readdirSync as readdirSync2, unlinkSync as unlinkSync4 } from "fs";
3125
3740
  async function countPendingReviews(sessionScope) {
3126
3741
  const client = getClient();
3127
3742
  if (sessionScope) {
3128
3743
  const result2 = await client.execute({
3129
- sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND (session_scope = ? OR session_scope IS NULL)",
3744
+ sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND session_scope = ?",
3130
3745
  args: [sessionScope]
3131
3746
  });
3132
3747
  return Number(result2.rows[0]?.cnt) || 0;
@@ -3302,11 +3917,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
3302
3917
  );
3303
3918
  }
3304
3919
  try {
3305
- const cacheDir = path11.join(EXE_AI_DIR, "session-cache");
3920
+ const cacheDir = path12.join(EXE_AI_DIR, "session-cache");
3306
3921
  if (existsSync11(cacheDir)) {
3307
3922
  for (const f of readdirSync2(cacheDir)) {
3308
3923
  if (f.startsWith("review-notified-")) {
3309
- unlinkSync4(path11.join(cacheDir, f));
3924
+ unlinkSync4(path12.join(cacheDir, f));
3310
3925
  }
3311
3926
  }
3312
3927
  }
@@ -3327,7 +3942,7 @@ var init_tasks_review = __esm({
3327
3942
  });
3328
3943
 
3329
3944
  // src/lib/tasks-chain.ts
3330
- import path12 from "path";
3945
+ import path13 from "path";
3331
3946
  import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
3332
3947
  async function cascadeUnblock(taskId, baseDir, now) {
3333
3948
  const client = getClient();
@@ -3344,7 +3959,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
3344
3959
  });
3345
3960
  for (const ur of unblockedRows.rows) {
3346
3961
  try {
3347
- const ubFile = path12.join(baseDir, String(ur.task_file));
3962
+ const ubFile = path13.join(baseDir, String(ur.task_file));
3348
3963
  let ubContent = await readFile3(ubFile, "utf-8");
3349
3964
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
3350
3965
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -3413,7 +4028,7 @@ var init_tasks_chain = __esm({
3413
4028
 
3414
4029
  // src/lib/project-name.ts
3415
4030
  import { execSync as execSync5 } from "child_process";
3416
- import path13 from "path";
4031
+ import path14 from "path";
3417
4032
  function getProjectName(cwd) {
3418
4033
  const dir = cwd ?? process.cwd();
3419
4034
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -3426,7 +4041,7 @@ function getProjectName(cwd) {
3426
4041
  timeout: 2e3,
3427
4042
  stdio: ["pipe", "pipe", "pipe"]
3428
4043
  }).trim();
3429
- repoRoot = path13.dirname(gitCommonDir);
4044
+ repoRoot = path14.dirname(gitCommonDir);
3430
4045
  } catch {
3431
4046
  repoRoot = execSync5("git rev-parse --show-toplevel", {
3432
4047
  cwd: dir,
@@ -3435,11 +4050,11 @@ function getProjectName(cwd) {
3435
4050
  stdio: ["pipe", "pipe", "pipe"]
3436
4051
  }).trim();
3437
4052
  }
3438
- _cached2 = path13.basename(repoRoot);
4053
+ _cached2 = path14.basename(repoRoot);
3439
4054
  _cachedCwd = dir;
3440
4055
  return _cached2;
3441
4056
  } catch {
3442
- _cached2 = path13.basename(dir);
4057
+ _cached2 = path14.basename(dir);
3443
4058
  _cachedCwd = dir;
3444
4059
  return _cached2;
3445
4060
  }
@@ -3912,7 +4527,7 @@ __export(tasks_exports, {
3912
4527
  updateTaskStatus: () => updateTaskStatus,
3913
4528
  writeCheckpoint: () => writeCheckpoint
3914
4529
  });
3915
- import path14 from "path";
4530
+ import path15 from "path";
3916
4531
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, unlinkSync as unlinkSync5 } from "fs";
3917
4532
  async function createTask(input) {
3918
4533
  const result = await createTaskCore(input);
@@ -3932,8 +4547,8 @@ async function updateTask(input) {
3932
4547
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
3933
4548
  try {
3934
4549
  const agent = String(row.assigned_to);
3935
- const cacheDir = path14.join(EXE_AI_DIR, "session-cache");
3936
- const cachePath = path14.join(cacheDir, `current-task-${agent}.json`);
4550
+ const cacheDir = path15.join(EXE_AI_DIR, "session-cache");
4551
+ const cachePath = path15.join(cacheDir, `current-task-${agent}.json`);
3937
4552
  if (input.status === "in_progress") {
3938
4553
  mkdirSync5(cacheDir, { recursive: true });
3939
4554
  writeFileSync6(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
@@ -4404,12 +5019,12 @@ __export(tmux_routing_exports, {
4404
5019
  });
4405
5020
  import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
4406
5021
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync12, appendFileSync, readdirSync as readdirSync3 } from "fs";
4407
- import path15 from "path";
4408
- import os8 from "os";
5022
+ import path16 from "path";
5023
+ import os9 from "os";
4409
5024
  import { fileURLToPath as fileURLToPath2 } from "url";
4410
5025
  import { unlinkSync as unlinkSync6 } from "fs";
4411
5026
  function spawnLockPath(sessionName) {
4412
- return path15.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
5027
+ return path16.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
4413
5028
  }
4414
5029
  function isProcessAlive(pid) {
4415
5030
  try {
@@ -4446,8 +5061,8 @@ function releaseSpawnLock2(sessionName) {
4446
5061
  function resolveBehaviorsExporterScript() {
4447
5062
  try {
4448
5063
  const thisFile = fileURLToPath2(import.meta.url);
4449
- const scriptPath = path15.join(
4450
- path15.dirname(thisFile),
5064
+ const scriptPath = path16.join(
5065
+ path16.dirname(thisFile),
4451
5066
  "..",
4452
5067
  "bin",
4453
5068
  "exe-export-behaviors.js"
@@ -4522,7 +5137,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
4522
5137
  mkdirSync6(SESSION_CACHE, { recursive: true });
4523
5138
  }
4524
5139
  const rootExe = extractRootExe(parentExe) ?? parentExe;
4525
- const filePath = path15.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
5140
+ const filePath = path16.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
4526
5141
  writeFileSync7(filePath, JSON.stringify({
4527
5142
  parentExe: rootExe,
4528
5143
  dispatchedBy: dispatchedBy || rootExe,
@@ -4531,7 +5146,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
4531
5146
  }
4532
5147
  function getParentExe(sessionKey) {
4533
5148
  try {
4534
- const data = JSON.parse(readFileSync11(path15.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
5149
+ const data = JSON.parse(readFileSync11(path16.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
4535
5150
  return data.parentExe || null;
4536
5151
  } catch {
4537
5152
  return null;
@@ -4540,7 +5155,7 @@ function getParentExe(sessionKey) {
4540
5155
  function getDispatchedBy(sessionKey) {
4541
5156
  try {
4542
5157
  const data = JSON.parse(readFileSync11(
4543
- path15.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
5158
+ path16.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
4544
5159
  "utf8"
4545
5160
  ));
4546
5161
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -4551,15 +5166,24 @@ function getDispatchedBy(sessionKey) {
4551
5166
  function resolveExeSession() {
4552
5167
  const mySession = getMySession();
4553
5168
  if (!mySession) return null;
5169
+ const fromSessionName = extractRootExe(mySession);
4554
5170
  try {
4555
5171
  const key = getSessionKey();
4556
5172
  const parentExe = getParentExe(key);
4557
5173
  if (parentExe) {
4558
- return extractRootExe(parentExe) ?? parentExe;
5174
+ const fromCache = extractRootExe(parentExe) ?? parentExe;
5175
+ if (fromSessionName && fromCache !== fromSessionName) {
5176
+ process.stderr.write(
5177
+ `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
5178
+ `
5179
+ );
5180
+ return fromSessionName;
5181
+ }
5182
+ return fromCache;
4559
5183
  }
4560
5184
  } catch {
4561
5185
  }
4562
- return extractRootExe(mySession) ?? mySession;
5186
+ return fromSessionName ?? mySession;
4563
5187
  }
4564
5188
  function isEmployeeAlive(sessionName) {
4565
5189
  return getTransport().isAlive(sessionName);
@@ -4717,7 +5341,7 @@ function sendIntercom(targetSession) {
4717
5341
  try {
4718
5342
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
4719
5343
  const agent = baseAgentName(rawAgent);
4720
- const markerPath = path15.join(SESSION_CACHE, `current-task-${agent}.json`);
5344
+ const markerPath = path16.join(SESSION_CACHE, `current-task-${agent}.json`);
4721
5345
  if (existsSync12(markerPath)) {
4722
5346
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
4723
5347
  return "debounced";
@@ -4727,7 +5351,7 @@ function sendIntercom(targetSession) {
4727
5351
  try {
4728
5352
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
4729
5353
  const agent = baseAgentName(rawAgent);
4730
- const taskDir = path15.join(process.cwd(), "exe", agent);
5354
+ const taskDir = path16.join(process.cwd(), "exe", agent);
4731
5355
  if (existsSync12(taskDir)) {
4732
5356
  const files = readdirSync3(taskDir).filter(
4733
5357
  (f) => f.endsWith(".md") && f !== "DONE.txt"
@@ -4861,8 +5485,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4861
5485
  const transport = getTransport();
4862
5486
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
4863
5487
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
4864
- const logDir = path15.join(os8.homedir(), ".exe-os", "session-logs");
4865
- const logFile = path15.join(logDir, `${instanceLabel}-${Date.now()}.log`);
5488
+ const logDir = path16.join(os9.homedir(), ".exe-os", "session-logs");
5489
+ const logFile = path16.join(logDir, `${instanceLabel}-${Date.now()}.log`);
4866
5490
  if (!existsSync12(logDir)) {
4867
5491
  mkdirSync6(logDir, { recursive: true });
4868
5492
  }
@@ -4870,14 +5494,14 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4870
5494
  let cleanupSuffix = "";
4871
5495
  try {
4872
5496
  const thisFile = fileURLToPath2(import.meta.url);
4873
- const cleanupScript = path15.join(path15.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
5497
+ const cleanupScript = path16.join(path16.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
4874
5498
  if (existsSync12(cleanupScript)) {
4875
5499
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
4876
5500
  }
4877
5501
  } catch {
4878
5502
  }
4879
5503
  try {
4880
- const claudeJsonPath = path15.join(os8.homedir(), ".claude.json");
5504
+ const claudeJsonPath = path16.join(os9.homedir(), ".claude.json");
4881
5505
  let claudeJson = {};
4882
5506
  try {
4883
5507
  claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
@@ -4892,10 +5516,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4892
5516
  } catch {
4893
5517
  }
4894
5518
  try {
4895
- const settingsDir = path15.join(os8.homedir(), ".claude", "projects");
5519
+ const settingsDir = path16.join(os9.homedir(), ".claude", "projects");
4896
5520
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
4897
- const projSettingsDir = path15.join(settingsDir, normalizedKey);
4898
- const settingsPath = path15.join(projSettingsDir, "settings.json");
5521
+ const projSettingsDir = path16.join(settingsDir, normalizedKey);
5522
+ const settingsPath = path16.join(projSettingsDir, "settings.json");
4899
5523
  let settings = {};
4900
5524
  try {
4901
5525
  settings = JSON.parse(readFileSync11(settingsPath, "utf8"));
@@ -4942,8 +5566,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4942
5566
  let behaviorsFlag = "";
4943
5567
  let legacyFallbackWarned = false;
4944
5568
  if (!useExeAgent && !useBinSymlink) {
4945
- const identityPath = path15.join(
4946
- os8.homedir(),
5569
+ const identityPath = path16.join(
5570
+ os9.homedir(),
4947
5571
  ".exe-os",
4948
5572
  "identity",
4949
5573
  `${employeeName}.md`
@@ -4958,7 +5582,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4958
5582
  }
4959
5583
  const behaviorsFile = exportBehaviorsSync(
4960
5584
  employeeName,
4961
- path15.basename(spawnCwd),
5585
+ path16.basename(spawnCwd),
4962
5586
  sessionName
4963
5587
  );
4964
5588
  if (behaviorsFile) {
@@ -4973,9 +5597,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4973
5597
  }
4974
5598
  let sessionContextFlag = "";
4975
5599
  try {
4976
- const ctxDir = path15.join(os8.homedir(), ".exe-os", "session-cache");
5600
+ const ctxDir = path16.join(os9.homedir(), ".exe-os", "session-cache");
4977
5601
  mkdirSync6(ctxDir, { recursive: true });
4978
- const ctxFile = path15.join(ctxDir, `session-context-${sessionName}.md`);
5602
+ const ctxFile = path16.join(ctxDir, `session-context-${sessionName}.md`);
4979
5603
  const ctxContent = [
4980
5604
  `## Session Context`,
4981
5605
  `You are running in tmux session: ${sessionName}.`,
@@ -5059,7 +5683,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5059
5683
  transport.pipeLog(sessionName, logFile);
5060
5684
  try {
5061
5685
  const mySession = getMySession();
5062
- const dispatchInfo = path15.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
5686
+ const dispatchInfo = path16.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
5063
5687
  writeFileSync7(dispatchInfo, JSON.stringify({
5064
5688
  dispatchedBy: mySession,
5065
5689
  rootExe: exeSession,
@@ -5134,15 +5758,15 @@ var init_tmux_routing = __esm({
5134
5758
  init_intercom_queue();
5135
5759
  init_plan_limits();
5136
5760
  init_employees();
5137
- SPAWN_LOCK_DIR = path15.join(os8.homedir(), ".exe-os", "spawn-locks");
5138
- SESSION_CACHE = path15.join(os8.homedir(), ".exe-os", "session-cache");
5761
+ SPAWN_LOCK_DIR = path16.join(os9.homedir(), ".exe-os", "spawn-locks");
5762
+ SESSION_CACHE = path16.join(os9.homedir(), ".exe-os", "session-cache");
5139
5763
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
5140
5764
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
5141
5765
  VERIFY_PANE_LINES = 200;
5142
5766
  INTERCOM_DEBOUNCE_MS = 3e4;
5143
5767
  CODEX_DEBOUNCE_MS = 12e4;
5144
- INTERCOM_LOG2 = path15.join(os8.homedir(), ".exe-os", "intercom.log");
5145
- DEBOUNCE_FILE = path15.join(SESSION_CACHE, "intercom-debounce.json");
5768
+ INTERCOM_LOG2 = path16.join(os9.homedir(), ".exe-os", "intercom.log");
5769
+ DEBOUNCE_FILE = path16.join(SESSION_CACHE, "intercom-debounce.json");
5146
5770
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
5147
5771
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
5148
5772
  }
@@ -5184,13 +5808,13 @@ var init_memory = __esm({
5184
5808
  // src/lib/keychain.ts
5185
5809
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
5186
5810
  import { existsSync as existsSync13 } from "fs";
5187
- import path16 from "path";
5188
- import os9 from "os";
5811
+ import path17 from "path";
5812
+ import os10 from "os";
5189
5813
  function getKeyDir() {
5190
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path16.join(os9.homedir(), ".exe-os");
5814
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path17.join(os10.homedir(), ".exe-os");
5191
5815
  }
5192
5816
  function getKeyPath() {
5193
- return path16.join(getKeyDir(), "master.key");
5817
+ return path17.join(getKeyDir(), "master.key");
5194
5818
  }
5195
5819
  async function tryKeytar() {
5196
5820
  try {
@@ -5213,7 +5837,7 @@ async function getMasterKey() {
5213
5837
  const keyPath = getKeyPath();
5214
5838
  if (!existsSync13(keyPath)) {
5215
5839
  process.stderr.write(
5216
- `[keychain] Key not found at ${keyPath} (HOME=${os9.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
5840
+ `[keychain] Key not found at ${keyPath} (HOME=${os10.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
5217
5841
  `
5218
5842
  );
5219
5843
  return null;
@@ -5251,7 +5875,7 @@ __export(shard_manager_exports, {
5251
5875
  listShards: () => listShards,
5252
5876
  shardExists: () => shardExists
5253
5877
  });
5254
- import path17 from "path";
5878
+ import path18 from "path";
5255
5879
  import { existsSync as existsSync14, mkdirSync as mkdirSync7, readdirSync as readdirSync4 } from "fs";
5256
5880
  import { createClient as createClient2 } from "@libsql/client";
5257
5881
  function initShardManager(encryptionKey) {
@@ -5277,7 +5901,7 @@ function getShardClient(projectName2) {
5277
5901
  }
5278
5902
  const cached = _shards.get(safeName);
5279
5903
  if (cached) return cached;
5280
- const dbPath = path17.join(SHARDS_DIR, `${safeName}.db`);
5904
+ const dbPath = path18.join(SHARDS_DIR, `${safeName}.db`);
5281
5905
  const client = createClient2({
5282
5906
  url: `file:${dbPath}`,
5283
5907
  encryptionKey: _encryptionKey
@@ -5287,7 +5911,7 @@ function getShardClient(projectName2) {
5287
5911
  }
5288
5912
  function shardExists(projectName2) {
5289
5913
  const safeName = projectName2.replace(/[^a-zA-Z0-9_-]/g, "_");
5290
- return existsSync14(path17.join(SHARDS_DIR, `${safeName}.db`));
5914
+ return existsSync14(path18.join(SHARDS_DIR, `${safeName}.db`));
5291
5915
  }
5292
5916
  function listShards() {
5293
5917
  if (!existsSync14(SHARDS_DIR)) return [];
@@ -5364,7 +5988,23 @@ async function ensureShardSchema(client) {
5364
5988
  // MS-11: draft staging, MS-6a: memory_type, MS-7: trajectory
5365
5989
  "ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0",
5366
5990
  "ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'",
5367
- "ALTER TABLE memories ADD COLUMN trajectory TEXT"
5991
+ "ALTER TABLE memories ADD COLUMN trajectory TEXT",
5992
+ // Metadata enrichment columns (must match database.ts)
5993
+ "ALTER TABLE memories ADD COLUMN intent TEXT",
5994
+ "ALTER TABLE memories ADD COLUMN outcome TEXT",
5995
+ "ALTER TABLE memories ADD COLUMN domain TEXT",
5996
+ "ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
5997
+ "ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
5998
+ "ALTER TABLE memories ADD COLUMN chain_position TEXT",
5999
+ "ALTER TABLE memories ADD COLUMN review_status TEXT",
6000
+ "ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
6001
+ "ALTER TABLE memories ADD COLUMN file_paths TEXT",
6002
+ "ALTER TABLE memories ADD COLUMN commit_hash TEXT",
6003
+ "ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
6004
+ "ALTER TABLE memories ADD COLUMN token_cost REAL",
6005
+ "ALTER TABLE memories ADD COLUMN audience TEXT",
6006
+ "ALTER TABLE memories ADD COLUMN language_type TEXT",
6007
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
5368
6008
  ]) {
5369
6009
  try {
5370
6010
  await client.execute(col);
@@ -5476,7 +6116,7 @@ var init_shard_manager = __esm({
5476
6116
  "src/lib/shard-manager.ts"() {
5477
6117
  "use strict";
5478
6118
  init_config();
5479
- SHARDS_DIR = path17.join(EXE_AI_DIR, "shards");
6119
+ SHARDS_DIR = path18.join(EXE_AI_DIR, "shards");
5480
6120
  _shards = /* @__PURE__ */ new Map();
5481
6121
  _encryptionKey = null;
5482
6122
  _shardingEnabled = false;
@@ -6445,13 +7085,13 @@ async function sweepTasks(projectName2, options = {}) {
6445
7085
  }
6446
7086
 
6447
7087
  // src/bin/git-sweep.ts
6448
- import path18 from "path";
7088
+ import path19 from "path";
6449
7089
  var args = process.argv.slice(2);
6450
7090
  var dryRun = args.includes("--dry-run");
6451
7091
  var projectIdx = args.indexOf("--project");
6452
7092
  var limitIdx = args.indexOf("--limit");
6453
7093
  var staleIdx = args.indexOf("--stale");
6454
- var projectName = projectIdx >= 0 ? args[projectIdx + 1] : process.cwd().split(path18.sep).pop();
7094
+ var projectName = projectIdx >= 0 ? args[projectIdx + 1] : process.cwd().split(path19.sep).pop();
6455
7095
  var commitLimit = limitIdx >= 0 ? Number(args[limitIdx + 1]) : void 0;
6456
7096
  var staleMinutes = staleIdx >= 0 ? Number(args[staleIdx + 1]) : void 0;
6457
7097
  async function main() {