@askexenow/exe-os 0.9.197 → 0.9.198

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.
@@ -370,12 +370,12 @@ services:
370
370
  EXE_GATEWAY_CONFIG: /data/gateway.json
371
371
  DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}
372
372
  EXE_GATEWAY_PORT: "3100"
373
- EXE_GATEWAY_HOST: "127.0.0.1"
373
+ EXE_GATEWAY_HOST: "0.0.0.0"
374
374
  EXE_GATEWAY_AUTH_TOKEN: ${EXE_GATEWAY_AUTH_TOKEN:?EXE_GATEWAY_AUTH_TOKEN is required}
375
375
  GOTRUE_URL: http://gotrue:9999
376
376
  EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN: ${EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN:?EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN is required}
377
377
  EXE_GATEWAY_WS_RELAY_ENABLED: "true"
378
- EXE_GATEWAY_WS_RELAY_HOST: "127.0.0.1"
378
+ EXE_GATEWAY_WS_RELAY_HOST: "0.0.0.0"
379
379
  EXE_GATEWAY_WS_RELAY_PORT: "3101"
380
380
  EXE_GATEWAY_WS_RELAY_AUTH_TOKEN: ${EXE_GATEWAY_WS_RELAY_AUTH_TOKEN:?EXE_GATEWAY_WS_RELAY_AUTH_TOKEN is required}
381
381
  WHATSAPP_ACCESS_TOKEN: ${WHATSAPP_ACCESS_TOKEN:-}
@@ -623,22 +623,22 @@
623
623
  "breakingChanges": [],
624
624
  "services": {
625
625
  "crm": {
626
- "image": "update.askexe.com/askexe/exe-crm:v0.9.4",
626
+ "image": "update.askexe.com/askexe/exe-crm:v0.9.15",
627
627
  "env": "CRM_IMAGE_TAG",
628
628
  "composeService": "exe-crm"
629
629
  },
630
630
  "wiki": {
631
- "image": "update.askexe.com/askexe/exe-wiki:v0.9.5",
631
+ "image": "update.askexe.com/askexe/exe-wiki:v0.9.11",
632
632
  "env": "WIKI_IMAGE_TAG",
633
633
  "composeService": "exe-wiki"
634
634
  },
635
635
  "exe-os": {
636
- "image": "update.askexe.com/askexe/exe-os:v0.9.185",
636
+ "image": "update.askexe.com/askexe/exe-os:v0.9.159",
637
637
  "env": "EXE_OS_IMAGE_TAG",
638
638
  "composeService": "exe-os"
639
639
  },
640
640
  "gateway": {
641
- "image": "update.askexe.com/askexe/exe-gateway:v0.9.7",
641
+ "image": "update.askexe.com/askexe/exe-gateway:v0.9.8",
642
642
  "env": "GATEWAY_IMAGE_TAG",
643
643
  "composeService": "exe-gateway"
644
644
  },
@@ -648,7 +648,7 @@
648
648
  "composeService": "exe-monitor-agent"
649
649
  },
650
650
  "monitorHub": {
651
- "image": "update.askexe.com/askexe/exe-monitor-hub:v0.9.5",
651
+ "image": "update.askexe.com/askexe/exe-monitor-hub:v0.9.4",
652
652
  "env": "MONITOR_HUB_IMAGE_TAG",
653
653
  "composeService": "exe-monitor-hub"
654
654
  }
@@ -11,7 +11,7 @@ import {
11
11
  patchEnv,
12
12
  readCurrentStackVersion,
13
13
  runStackUpdate
14
- } from "../chunk-T5U27Y4H.js";
14
+ } from "../chunk-M7NGABPF.js";
15
15
  import "../chunk-MVMMULOJ.js";
16
16
  import "../chunk-4GXRETYL.js";
17
17
  import "../chunk-LYH5HE24.js";
@@ -207,7 +207,7 @@ async function main(args) {
207
207
  console.log("[health-gate] Starting rollback...");
208
208
  restorePreDeployBackup();
209
209
  try {
210
- const { rollbackStackUpdate, defaultStackPaths } = await import("../stack-update-PI2TWEGS.js");
210
+ const { rollbackStackUpdate, defaultStackPaths } = await import("../stack-update-C4BAPLXJ.js");
211
211
  const paths = defaultStackPaths();
212
212
  await rollbackStackUpdate({
213
213
  manifestRef: paths.manifestRef,
@@ -1313,6 +1313,42 @@ function reapZombieAgentProcesses(deps) {
1313
1313
  }
1314
1314
  }
1315
1315
  if (hasLiveSession) continue;
1316
+ const coordinatorSessions = [...liveSessions].filter(
1317
+ (s) => isCoordinatorName(s.replace(/^\w+-/, "")) || isExeSession(s)
1318
+ );
1319
+ if (coordinatorSessions.length > 0) {
1320
+ let belongsToCoordinator = false;
1321
+ for (const cs of coordinatorSessions) {
1322
+ try {
1323
+ const panePids = execSync(
1324
+ `tmux list-panes -t ${JSON.stringify(cs)} -F '#{pane_pid}' 2>/dev/null`,
1325
+ { encoding: "utf8", timeout: 3e3 }
1326
+ ).trim().split("\n").map(Number).filter(Boolean);
1327
+ for (const panePid of panePids) {
1328
+ let walk = pid;
1329
+ for (let d = 0; d < 10; d++) {
1330
+ if (walk === panePid) {
1331
+ belongsToCoordinator = true;
1332
+ break;
1333
+ }
1334
+ const p = procMap.get(walk);
1335
+ if (!p || p.ppid <= 1) break;
1336
+ walk = p.ppid;
1337
+ }
1338
+ if (belongsToCoordinator) break;
1339
+ }
1340
+ } catch {
1341
+ }
1342
+ if (belongsToCoordinator) break;
1343
+ }
1344
+ if (belongsToCoordinator) {
1345
+ process.stderr.write(
1346
+ `[zombie-agent-reaper] SKIPPING PID ${pid} \u2014 belongs to coordinator session (${info.args.slice(0, 60)})
1347
+ `
1348
+ );
1349
+ continue;
1350
+ }
1351
+ }
1316
1352
  const rssKb = getRssKb(pid);
1317
1353
  const rssMb = rssKb ? Math.round(rssKb / 1024) : "?";
1318
1354
  const desc = `PID ${pid} (age=${ageSecs}s, RSS=${rssMb}MB, ${info.args.slice(0, 80)})`;
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-AFJWUI3Y.js";
7
7
  import {
8
8
  AUTO_WAKE_MAX_RETRIES
9
- } from "./chunk-7JCK6TXX.js";
9
+ } from "./chunk-62DAMAFL.js";
10
10
  import {
11
11
  getToolCapabilityIndex
12
12
  } from "./chunk-GHCVD7WV.js";
@@ -140,20 +140,20 @@ function createStackUpdatePlan(manifest, envRaw, targetVersion) {
140
140
  breakingChanges: release.breakingChanges ?? []
141
141
  };
142
142
  }
143
- var ASKEXE_GHCR_IMAGE = /^(?:ghcr\.io\/askexe|update\.askexe\.com\/askexe|registry\.askexe\.com\/askexe)\/[a-z0-9._/-]+(?::[^:@$/{]+|@sha256:[a-f0-9]{64})$/i;
143
+ var ASKEXE_GHCR_IMAGE = /^(?:ghcr\.io\/askexe|update\.askexe\.com\/askexe)\/[a-z0-9._/-]+(?::[^:@$/{]+|@sha256:[a-f0-9]{64})$/i;
144
144
  function validatePinnedGhcrImage(image, label) {
145
145
  const trimmed = image.trim().replace(/^['"]|['"]$/g, "");
146
146
  if (!trimmed) return `${label} is empty`;
147
147
  if (trimmed.includes("${")) return null;
148
- if (!trimmed.startsWith("ghcr.io/askexe/") && !trimmed.startsWith("update.askexe.com/askexe/") && !trimmed.startsWith("registry.askexe.com/askexe/")) return `${label} must use ghcr.io/askexe/*, update.askexe.com/askexe/*, or registry.askexe.com/askexe/*, got ${trimmed}`;
148
+ if (!trimmed.startsWith("ghcr.io/askexe/") && !trimmed.startsWith("update.askexe.com/askexe/")) return `${label} must use ghcr.io/askexe/* or update.askexe.com/askexe/*, got ${trimmed}`;
149
149
  if (/:latest(?:$|[\s#])/.test(trimmed)) return `${label} must not use :latest (${trimmed})`;
150
- if (!ASKEXE_GHCR_IMAGE.test(trimmed)) return `${label} must be pinned with an explicit tag or sha256 digest from ghcr.io/askexe or registry.askexe.com/askexe, got ${trimmed}`;
150
+ if (!ASKEXE_GHCR_IMAGE.test(trimmed)) return `${label} must be pinned with an explicit tag or sha256 digest from ghcr.io/askexe or update.askexe.com/askexe, got ${trimmed}`;
151
151
  return null;
152
152
  }
153
153
  function validateComposeImageLiteral(image, label) {
154
154
  const trimmed = image.trim().replace(/^['"]|['"]$/g, "");
155
155
  if (!trimmed) return `${label} is empty`;
156
- if (trimmed.startsWith("ghcr.io/askexe/") || trimmed.startsWith("update.askexe.com/askexe/") || trimmed.startsWith("registry.askexe.com/askexe/")) return validatePinnedGhcrImage(trimmed, label);
156
+ if (trimmed.startsWith("ghcr.io/askexe/") || trimmed.startsWith("update.askexe.com/askexe/")) return validatePinnedGhcrImage(trimmed, label);
157
157
  if (/^(postgres|pgvector\/pgvector|clickhouse\/clickhouse-server|redis|nginx|postgrest\/postgrest|supabase\/gotrue):[^:]+$/i.test(trimmed)) return null;
158
158
  return `${label} uses unsupported non-AskExe image ${trimmed}; customer app images must come from pinned update.askexe.com/askexe or ghcr.io/askexe images`;
159
159
  }
@@ -628,7 +628,7 @@ async function runStackUpdate(options) {
628
628
  const password = rest.join(":");
629
629
  if (username && password) {
630
630
  const sampleImage = Object.values(plan.release.services)[0]?.image ?? "";
631
- const registry = sampleImage.startsWith("update.askexe.com") ? "update.askexe.com" : sampleImage.startsWith("registry.askexe.com") ? "registry.askexe.com" : "ghcr.io";
631
+ const registry = sampleImage.startsWith("update.askexe.com") ? "update.askexe.com" : "ghcr.io";
632
632
  creds = { registry, username, password };
633
633
  console.log(`[stack-update] Using manual registry credentials for ${registry}.`);
634
634
  }
@@ -48,7 +48,7 @@ import {
48
48
  shouldKillIdleSession,
49
49
  shouldKillSession,
50
50
  shouldNudgeEmployee
51
- } from "./chunk-7JCK6TXX.js";
51
+ } from "./chunk-62DAMAFL.js";
52
52
  import "./chunk-WRCETUYE.js";
53
53
  import "./chunk-5RT7IBY4.js";
54
54
  import "./chunk-WP6P3LSI.js";
@@ -215,12 +215,6 @@ Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title
215
215
  `[session-end] WARNING: ${agent.agentId} ended with ${inProgress.length} in_progress task(s): ${titles}
216
216
  `
217
217
  );
218
- let commits = [];
219
- try {
220
- const { getRecentCommits } = await import("../git-task-sweep-GPPNL2DK.js");
221
- commits = getRecentCommits(30);
222
- } catch {
223
- }
224
218
  const autoClosed = [];
225
219
  const leftInProgress = [];
226
220
  for (const row of inProgress) {
@@ -580,19 +580,22 @@ async function loadModel() {
580
580
  } else {
581
581
  process.stderr.write(`[exed] Embed worker failed 3 times \u2014 running without embeddings.
582
582
  `);
583
- try {
584
- if (_storeInitialized) {
585
- const client = getClient();
586
- client.execute(
587
- `INSERT INTO notifications (id, agent_id, event_type, title, body, created_at)
588
- VALUES (lower(hex(randomblob(16))), 'exe', 'embed_failure',
589
- 'Embedding daemon offline \u2014 recall degraded to keyword-only',
590
- 'Embed worker crashed 3 times and will not restart. Semantic search is unavailable. Recall falls back to FTS keyword matching. Fix: check ~/.exe-os/logs/exed-launchd.log for embed worker errors, then restart daemon.',
591
- datetime(''now''))`
592
- );
583
+ void (async () => {
584
+ try {
585
+ if (_storeInitialized) {
586
+ const { getClient: getDbClient } = await import("./database.js");
587
+ const dbClient = getDbClient();
588
+ dbClient.execute(
589
+ `INSERT INTO notifications (id, agent_id, event_type, title, body, created_at)
590
+ VALUES (lower(hex(randomblob(16))), 'exe', 'embed_failure',
591
+ 'Embedding daemon offline \u2014 recall degraded to keyword-only',
592
+ 'Embed worker crashed 3 times and will not restart. Semantic search is unavailable. Recall falls back to FTS keyword matching. Fix: check ~/.exe-os/logs/exed-launchd.log for embed worker errors, then restart daemon.',
593
+ datetime(''now''))`
594
+ );
595
+ }
596
+ } catch {
593
597
  }
594
- } catch {
595
- }
598
+ })();
596
599
  }
597
600
  });
598
601
  } catch (err) {
@@ -798,8 +801,8 @@ async function shutdown() {
798
801
  `);
799
802
  }
800
803
  try {
801
- const { getClient: getClient2 } = await import("./database.js");
802
- const client = getClient2();
804
+ const { getClient } = await import("./database.js");
805
+ const client = getClient();
803
806
  await client.execute("PRAGMA wal_checkpoint(TRUNCATE)");
804
807
  process.stderr.write("[exed] WAL checkpoint complete \u2014 all writes flushed to DB.\n");
805
808
  } catch (e) {
@@ -900,8 +903,8 @@ async function handleDbExecute(socket, requestId, sql, args) {
900
903
  sendResponse(socket, { id: requestId, error: "DB not initialized" });
901
904
  return;
902
905
  }
903
- const { getClient: getClient2 } = await import("./database.js");
904
- const client = getClient2();
906
+ const { getClient } = await import("./database.js");
907
+ const client = getClient();
905
908
  const deserializedArgs = deserializeArgs(args);
906
909
  const result = await client.execute({ sql, args: deserializedArgs });
907
910
  _dbRequestsServed++;
@@ -926,8 +929,8 @@ async function handleDbBatch(socket, requestId, statements, mode) {
926
929
  sendResponse(socket, { id: requestId, error: "DB not initialized" });
927
930
  return;
928
931
  }
929
- const { getClient: getClient2 } = await import("./database.js");
930
- const client = getClient2();
932
+ const { getClient } = await import("./database.js");
933
+ const client = getClient();
931
934
  const stmts = statements.map((s) => ({
932
935
  sql: s.sql,
933
936
  args: deserializeArgs(s.args)
@@ -961,7 +964,7 @@ async function handleIngest(req) {
961
964
  project_name: req.projectName,
962
965
  has_error: req.hasError,
963
966
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
964
- task_id: req.taskId ?? null,
967
+ task_id: req.taskId ?? void 0,
965
968
  confidence: req.confidence,
966
969
  draft: req.draft,
967
970
  trajectory: req.trajectory ? JSON.stringify(req.trajectory) : void 0
@@ -1062,8 +1065,8 @@ async function _writeMemoryRecordInner(entry) {
1062
1065
  `);
1063
1066
  }
1064
1067
  }
1065
- const { getClient: getClient2 } = await import("./database.js");
1066
- const client = getClient2();
1068
+ const { getClient } = await import("./database.js");
1069
+ const client = getClient();
1067
1070
  const hasVector = vectorBlob !== null;
1068
1071
  await client.execute({
1069
1072
  sql: hasVector ? `INSERT OR IGNORE INTO memories
@@ -2171,14 +2174,14 @@ async function startReviewPolling() {
2171
2174
  lastNudgeSent: /* @__PURE__ */ new Map(),
2172
2175
  intervalMs: REVIEW_POLL_INTERVAL_MS
2173
2176
  };
2174
- const { pollReviewNudge, createReviewNudgeRealDeps, loadNudgeState } = await import("../daemon-orchestration-N5GPEP4F.js");
2177
+ const { pollReviewNudge, createReviewNudgeRealDeps, loadNudgeState } = await import("../daemon-orchestration-ZBSS6VZR.js");
2175
2178
  const nudgeState = loadNudgeState();
2176
2179
  const tick = async () => {
2177
2180
  fired("review_polling");
2178
2181
  if (!await ensureStoreForPolling()) return;
2179
2182
  try {
2180
- const { getClient: getClient2 } = await import("./database.js");
2181
- const deps = polling.createRealDeps(getClient2);
2183
+ const { getClient } = await import("./database.js");
2184
+ const deps = polling.createRealDeps(getClient);
2182
2185
  const sent = await polling.pollPendingReviews(deps, state);
2183
2186
  if (sent.length > 0) acted("review_polling");
2184
2187
  for (const s of sent) {
@@ -2186,7 +2189,7 @@ async function startReviewPolling() {
2186
2189
  `);
2187
2190
  }
2188
2191
  try {
2189
- const nudgeDeps = createReviewNudgeRealDeps(getClient2);
2192
+ const nudgeDeps = createReviewNudgeRealDeps(getClient);
2190
2193
  const nudged = await pollReviewNudge(nudgeDeps, nudgeState);
2191
2194
  for (const n of nudged) {
2192
2195
  process.stderr.write(`[exed] Review nudge pushed to idle coordinator: ${n}
@@ -2212,9 +2215,9 @@ function startSessionTTL() {
2212
2215
  fired("session_ttl");
2213
2216
  if (!await ensureStoreForPolling()) return;
2214
2217
  try {
2215
- const { getClient: getClient2 } = await import("./database.js");
2216
- const { checkSessionTTL, createSessionTTLRealDeps } = await import("../daemon-orchestration-N5GPEP4F.js");
2217
- const deps = createSessionTTLRealDeps(getClient2);
2218
+ const { getClient } = await import("./database.js");
2219
+ const { checkSessionTTL, createSessionTTLRealDeps } = await import("../daemon-orchestration-ZBSS6VZR.js");
2220
+ const deps = createSessionTTLRealDeps(getClient);
2218
2221
  const killed = await checkSessionTTL(deps);
2219
2222
  if (killed.length > 0) acted("session_ttl");
2220
2223
  } catch (err) {
@@ -2261,10 +2264,10 @@ function startIdleKill() {
2261
2264
  try {
2262
2265
  const cfg = await getCachedConfig();
2263
2266
  if (!cfg) return;
2264
- const { getClient: getClient2 } = await import("./database.js");
2265
- const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-N5GPEP4F.js");
2267
+ const { getClient } = await import("./database.js");
2268
+ const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-ZBSS6VZR.js");
2266
2269
  const deps = createIdleKillRealDeps(
2267
- getClient2,
2270
+ getClient,
2268
2271
  cfg.sessionLifecycle.idleKillIntercomAckWindowMs
2269
2272
  );
2270
2273
  const killed = await pollIdleKill(deps, _idleTickCounts, {
@@ -2298,8 +2301,8 @@ function startConsolidation() {
2298
2301
  if (!config.consolidationEnabled) return;
2299
2302
  if (!process.env.ANTHROPIC_API_KEY) return;
2300
2303
  if (!await ensureStoreForPolling()) return;
2301
- const { getClient: getClient2 } = await import("./database.js");
2302
- const client = getClient2();
2304
+ const { getClient } = await import("./database.js");
2305
+ const client = getClient();
2303
2306
  const { countUnconsolidated, isUserIdle, runConsolidation } = await import("./consolidation.js");
2304
2307
  const count = await countUnconsolidated(client);
2305
2308
  if (count < 20) {
@@ -2506,8 +2509,8 @@ function startGraphExtraction() {
2506
2509
  if (config.graphRagEnabled === false) return;
2507
2510
  if (!process.env.ANTHROPIC_API_KEY) return;
2508
2511
  if (!await ensureStoreForPolling()) return;
2509
- const { getClient: getClient2 } = await import("./database.js");
2510
- const client = getClient2();
2512
+ const { getClient } = await import("./database.js");
2513
+ const client = getClient();
2511
2514
  const { extractBatch } = await import("../graph-rag-G3EG5Q6L.js");
2512
2515
  const result = await extractBatch(client, 50, config.selfQueryModel);
2513
2516
  if (result.processed > 0) {
@@ -2534,8 +2537,8 @@ async function writeAgentStats() {
2534
2537
  if (!await ensureStoreForPolling()) return;
2535
2538
  try {
2536
2539
  acted("agent_stats");
2537
- const { getClient: getClient2 } = await import("./database.js");
2538
- const client = getClient2();
2540
+ const { getClient } = await import("./database.js");
2541
+ const client = getClient();
2539
2542
  const result = await client.execute({
2540
2543
  sql: `SELECT agent_id,
2541
2544
  COUNT(*) as total,
@@ -2607,8 +2610,8 @@ function startConfidenceDecay() {
2607
2610
  fired("confidence_decay");
2608
2611
  if (!await ensureStoreForPolling()) return;
2609
2612
  try {
2610
- const { getClient: getClient2 } = await import("./database.js");
2611
- const client = getClient2();
2613
+ const { getClient } = await import("./database.js");
2614
+ const client = getClient();
2612
2615
  const result = await client.execute({
2613
2616
  sql: `UPDATE memories
2614
2617
  SET confidence = MAX(0.3, COALESCE(confidence, 0.7) - 0.01)
@@ -2639,8 +2642,8 @@ function startReflectionSweep() {
2639
2642
  fired("reflection_sweep");
2640
2643
  if (!await ensureStoreForPolling()) return;
2641
2644
  try {
2642
- const { getClient: getClient2 } = await import("./database.js");
2643
- const client = getClient2();
2645
+ const { getClient } = await import("./database.js");
2646
+ const client = getClient();
2644
2647
  const agents = await client.execute(
2645
2648
  "SELECT DISTINCT agent_id FROM memory_cards WHERE active = 1 LIMIT 50"
2646
2649
  );
@@ -2749,9 +2752,9 @@ function startSoftDeletePurge() {
2749
2752
  fired("soft_delete_purge");
2750
2753
  if (!await ensureStoreForPolling()) return;
2751
2754
  try {
2752
- const { getClient: getClient2 } = await import("./database.js");
2755
+ const { getClient } = await import("./database.js");
2753
2756
  const { SOFT_DELETE_RETENTION_DAYS } = await import("./database.js");
2754
- const client = getClient2();
2757
+ const client = getClient();
2755
2758
  const cutoffDate = new Date(Date.now() - SOFT_DELETE_RETENTION_DAYS * 24 * 60 * 60 * 1e3).toISOString();
2756
2759
  const result = await client.execute({
2757
2760
  sql: `SELECT COUNT(*) as cnt FROM memories WHERE status = 'deleted' AND deleted_at IS NOT NULL AND deleted_at < ?`,
@@ -2819,7 +2822,7 @@ function startOrphanReaper() {
2819
2822
  const tick = async () => {
2820
2823
  fired("orphan_reaper");
2821
2824
  try {
2822
- const { reapOrphanedMcpProcesses, createOrphanReaperRealDeps } = await import("../daemon-orchestration-N5GPEP4F.js");
2825
+ const { reapOrphanedMcpProcesses, createOrphanReaperRealDeps } = await import("../daemon-orchestration-ZBSS6VZR.js");
2823
2826
  const deps = createOrphanReaperRealDeps();
2824
2827
  const reaped = await reapOrphanedMcpProcesses(deps);
2825
2828
  if (reaped.length > 0) acted("orphan_reaper");
@@ -2843,7 +2846,7 @@ function startZombieAgentReaper() {
2843
2846
  const tick = async () => {
2844
2847
  fired("zombie_agent_reaper");
2845
2848
  try {
2846
- const { reapZombieAgentProcesses, createZombieAgentReaperRealDeps } = await import("../daemon-orchestration-N5GPEP4F.js");
2849
+ const { reapZombieAgentProcesses, createZombieAgentReaperRealDeps } = await import("../daemon-orchestration-ZBSS6VZR.js");
2847
2850
  const deps = createZombieAgentReaperRealDeps();
2848
2851
  const reaped = reapZombieAgentProcesses(deps);
2849
2852
  if (reaped.length > 0) acted("zombie_agent_reaper");
@@ -2866,7 +2869,7 @@ function startWorktreeReaper() {
2866
2869
  const tick = async () => {
2867
2870
  fired("worktree_reaper");
2868
2871
  try {
2869
- const { reapOrphanedWorktrees, createWorktreeReaperRealDeps } = await import("../daemon-orchestration-N5GPEP4F.js");
2872
+ const { reapOrphanedWorktrees, createWorktreeReaperRealDeps } = await import("../daemon-orchestration-ZBSS6VZR.js");
2870
2873
  const deps = await createWorktreeReaperRealDeps();
2871
2874
  const result = await reapOrphanedWorktrees(deps);
2872
2875
  if (result.pruned.length > 0) {
@@ -2896,8 +2899,8 @@ function startWalCheckpoint() {
2896
2899
  fired("wal_checkpoint");
2897
2900
  if (!await ensureStoreForPolling()) return;
2898
2901
  try {
2899
- const { getClient: getClient2 } = await import("./database.js");
2900
- const client = getClient2();
2902
+ const { getClient } = await import("./database.js");
2903
+ const client = getClient();
2901
2904
  await client.execute("PRAGMA wal_checkpoint(TRUNCATE)");
2902
2905
  acted("wal_checkpoint");
2903
2906
  } catch {
@@ -2914,9 +2917,9 @@ function startStuckTaskRelease() {
2914
2917
  fired("stuck_task_release");
2915
2918
  if (!await ensureStoreForPolling()) return;
2916
2919
  try {
2917
- const { getClient: getClient2 } = await import("./database.js");
2918
- const { releaseStuckTasks, createStuckTaskRealDeps } = await import("../daemon-orchestration-N5GPEP4F.js");
2919
- const deps = createStuckTaskRealDeps(getClient2);
2920
+ const { getClient } = await import("./database.js");
2921
+ const { releaseStuckTasks, createStuckTaskRealDeps } = await import("../daemon-orchestration-ZBSS6VZR.js");
2922
+ const deps = createStuckTaskRealDeps(getClient);
2920
2923
  const released = await releaseStuckTasks(deps);
2921
2924
  if (released.length > 0) {
2922
2925
  acted("stuck_task_release");
@@ -2959,7 +2962,7 @@ function startTaskEnforcementScanner() {
2959
2962
  const { runTaskEnforcementTick } = await import("../task-enforcement-QYS2QEEO.js");
2960
2963
  const { getTransport } = await import("./transport.js");
2961
2964
  const { loadAgentConfig } = await import("./agent-config.js");
2962
- const { getClient: getClient2 } = await import("./database.js");
2965
+ const { getClient } = await import("./database.js");
2963
2966
  const { loadEmployeesSync } = await import("./employees.js");
2964
2967
  const { sessionScopeFilter } = await import("../task-scope-OS66ZD7O.js");
2965
2968
  const transport = getTransport();
@@ -2969,7 +2972,7 @@ function startTaskEnforcementScanner() {
2969
2972
  transport,
2970
2973
  agentConfig: loadAgentConfig(),
2971
2974
  employees: loadEmployeesSync(),
2972
- client: await getClient2(),
2975
+ client: await getClient(),
2973
2976
  scopeFilter: sessionScopeFilter(),
2974
2977
  capturePaneAsync,
2975
2978
  paneCache
@@ -3189,8 +3192,8 @@ function startBugAutoFix() {
3189
3192
  const tick = async () => {
3190
3193
  fired("bug_autofix");
3191
3194
  try {
3192
- const { getClient: getClient2 } = await import("./database.js");
3193
- const client = await getClient2();
3195
+ const { getClient } = await import("./database.js");
3196
+ const client = await getClient();
3194
3197
  const result = await client.execute({
3195
3198
  sql: `SELECT id, title, priority, assigned_to, status FROM tasks
3196
3199
  WHERE priority IN ('p0', 'p1')
@@ -3526,8 +3529,8 @@ try {
3526
3529
  try {
3527
3530
  if (!await ensureStoreForPolling()) return;
3528
3531
  const { readdirSync, readFileSync: rfs } = await import("fs");
3529
- const { getClient: getClient2 } = await import("./database.js");
3530
- const client = getClient2();
3532
+ const { getClient } = await import("./database.js");
3533
+ const client = getClient();
3531
3534
  const tasksRoot = path3.join(os2.homedir(), ".exe-os", "tasks");
3532
3535
  let synced = 0;
3533
3536
  const walk = (dir) => {
@@ -3594,9 +3597,9 @@ try {
3594
3597
  fired("intercom_dedup_cleanup");
3595
3598
  try {
3596
3599
  if (!await ensureStoreForPolling()) return;
3597
- const { getClient: getClient2 } = await import("./database.js");
3600
+ const { getClient } = await import("./database.js");
3598
3601
  const { deduplicateIntercomMemories } = await import("./consolidation.js");
3599
- const count = await deduplicateIntercomMemories(getClient2());
3602
+ const count = await deduplicateIntercomMemories(getClient());
3600
3603
  if (count > 0) {
3601
3604
  acted("intercom_dedup_cleanup");
3602
3605
  process.stderr.write(`[exed] Intercom dedup: archived ${count} duplicate intercom memories
@@ -3611,9 +3614,9 @@ try {
3611
3614
  fired("trace_ttl_sweep");
3612
3615
  try {
3613
3616
  if (!await ensureStoreForPolling()) return;
3614
- const { getClient: getClient2 } = await import("./database.js");
3617
+ const { getClient } = await import("./database.js");
3615
3618
  const { sweepExpiredTraces } = await import("./consolidation.js");
3616
- const count = await sweepExpiredTraces(getClient2());
3619
+ const count = await sweepExpiredTraces(getClient());
3617
3620
  if (count > 0) {
3618
3621
  acted("trace_ttl_sweep");
3619
3622
  process.stderr.write(`[exed] Trace TTL: deleted ${count} expired raw tool traces (>7d, importance<7)
@@ -3680,7 +3683,7 @@ try {
3680
3683
  const { createWsClient } = await import("./ws-client.js");
3681
3684
  const { initStore } = await import("./store.js");
3682
3685
  const { sendMessage, deliverLocalMessage, setWsClientSend } = await import("./messaging.js");
3683
- const { getClient: getClient2 } = await import("./database.js");
3686
+ const { getClient } = await import("./database.js");
3684
3687
  await initStore();
3685
3688
  const wsClient = createWsClient({
3686
3689
  endpoint: config.cloud.endpoint.replace(/^https?/, "wss") + "/ws",
@@ -3706,7 +3709,7 @@ try {
3706
3709
  },
3707
3710
  onRegistry: async (devices) => {
3708
3711
  try {
3709
- const client = getClient2();
3712
+ const client = getClient();
3710
3713
  const now = (/* @__PURE__ */ new Date()).toISOString();
3711
3714
  for (const d of devices) {
3712
3715
  await client.execute({
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  registerAllTools
3
- } from "../chunk-4F4SOCKN.js";
3
+ } from "../chunk-CHZMPZJ3.js";
4
4
  import "../chunk-PLNYW6PA.js";
5
5
  import "../chunk-AFJWUI3Y.js";
6
- import "../chunk-7JCK6TXX.js";
6
+ import "../chunk-62DAMAFL.js";
7
7
  import "../chunk-GHCVD7WV.js";
8
8
  import "../chunk-WZTQUBIE.js";
9
9
  import "../chunk-KH5Y6RR4.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "../chunk-V4TZI6EO.js";
4
4
  import {
5
5
  registerAllTools
6
- } from "../chunk-4F4SOCKN.js";
6
+ } from "../chunk-CHZMPZJ3.js";
7
7
  import {
8
8
  initLicenseGate
9
9
  } from "../chunk-PLNYW6PA.js";
@@ -11,7 +11,7 @@ import {
11
11
  startToolTelemetryFlush,
12
12
  wrapServerWithTelemetry
13
13
  } from "../chunk-AFJWUI3Y.js";
14
- import "../chunk-7JCK6TXX.js";
14
+ import "../chunk-62DAMAFL.js";
15
15
  import "../chunk-GHCVD7WV.js";
16
16
  import "../chunk-WZTQUBIE.js";
17
17
  import "../chunk-KH5Y6RR4.js";
@@ -20,7 +20,7 @@ import {
20
20
  runStackUpdate,
21
21
  verifyReleaseHealth,
22
22
  verifyStackManifestSignature
23
- } from "./chunk-T5U27Y4H.js";
23
+ } from "./chunk-M7NGABPF.js";
24
24
  import "./chunk-MVMMULOJ.js";
25
25
  import "./chunk-4GXRETYL.js";
26
26
  import "./chunk-LYH5HE24.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.197",
3
+ "version": "0.9.198",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -1,6 +1,106 @@
1
1
  {
2
- "current": "0.9.197",
2
+ "current": "0.9.198",
3
3
  "notes": {
4
+ "0.9.198": {
5
+ "version": "0.9.198",
6
+ "date": "2026-06-02",
7
+ "features": [
8
+ "consolidate registry.askexe.com → update.askexe.com as primary registry (#51)",
9
+ "nginx /v2/ route for Docker registry proxy on update.askexe.com",
10
+ "consolidate registry into update.askexe.com — license key = pull auth",
11
+ "scale daemon heap to 25% of system RAM, support 10+ coordinators",
12
+ "add query expansion + benchmark results to retrieval platform procedure",
13
+ "3-mode BEAM benchmark — FTS vs FTS+Graph vs Hybrid",
14
+ "wire update.askexe.com — billing schema + non-fatal image credentials",
15
+ "add 'never defer' platform procedure — fix it now or assign it now",
16
+ "BEAM multi-tier support — 100K, 1M, 10M token scales",
17
+ "MemoryAgentBench harness — ICLR 2026 benchmark",
18
+ "support outbox flusher + list_tasks null fix + doctor outbox status",
19
+ "bug report outbox flusher — reports reach AskExe even when daemon is dead",
20
+ "add daily-summary CLI entry point + enable tsup build",
21
+ "add daemon observability platform procedure",
22
+ "add retrieval architecture platform procedure for 8-16GB machines",
23
+ "graceful shutdown warning via intercom 90s before idle kill",
24
+ "upload pre-update snapshot to R2 before every stack-update",
25
+ "encrypted daily VPS backups with R2 cloud upload",
26
+ "conversation history import — parser + MCP tool + CLI",
27
+ "add vps-backup + vps-health-gate scripts with stack-update integration",
28
+ "add update_bug_report + update_feature_request MCP tools",
29
+ "VPS guardrails — Postgres backup cron + post-deploy health gate",
30
+ "co-occurrence edges + graph backfill script",
31
+ "write-time entity/relationship extraction from memory text",
32
+ "parallel retrieval (FTS+graph+embed) with _source attribution"
33
+ ],
34
+ "fixes": [
35
+ "zombie agent reaper never kills coordinator/exe session processes",
36
+ "typecheck errors blocking publish — async embed alert + dead code cleanup",
37
+ "session TTL uses registry registeredAt instead of tmux session_created",
38
+ "CRM auth defaults + benchmark beam.ts updates",
39
+ "enable GoTrue email auth by default in setup template",
40
+ "intercom signal path in packaged source — ships to customers on npm install",
41
+ "intercom signal path + registry consolidated to update.askexe.com",
42
+ "4 customer P2 bugs — CLI passthrough + agent casing + clipboard (#50)",
43
+ "MCP pressure eviction evicts ONE session, not all",
44
+ "GHCR registry escape hatch + feature request 400 payload fix",
45
+ "WS client graceful failure on CF 1101 + capped backoff",
46
+ "3 of 4 customer P2 bugs — CLI passthrough + agent casing + clipboard",
47
+ "remove auto-close on session end (source persisted this time)",
48
+ "parallel Tom isolation — task-scoped branches + multi-instance task lookup",
49
+ "downgrade multi-coordinator hard-fail to warning",
50
+ "daemon RSS reconnect + review push notify + hot_entities timestamp",
51
+ "HYGO stack-update blockers — volume regex + memory_audit --fix",
52
+ "spawn CWD cross-project contamination + identity load ordering",
53
+ "MCP hot-reload checks agent context for COO role, not just env var",
54
+ "eliminate cross-session dispatch bug in create_task",
55
+ "bug/feature report upstream updates — PATCH→POST with action field",
56
+ "strip stale X-Exe-Session from global config + guard against re-adding",
57
+ "BEAM CLaRa — direct JSON response instead of tool_use, bump max_tokens",
58
+ "BEAM CLaRa benchmark — correct endpoint + configurable model",
59
+ "MCP session dedup false positive + BEAM CLaRa benchmark mode"
60
+ ],
61
+ "security": [
62
+ "fix shell injection, SSRF, socket leaks, backup validation",
63
+ "bump v0.9.139 — 2 CRITICAL security fixes, 14 bug fixes, 6 features, customer config preservation",
64
+ "fix 2 CRITICAL + 1 HIGH from post-fix audit",
65
+ "validate X-Agent-Role against roster — prevent privilege escalation",
66
+ "release: stack v0.9.8 — security hardening + Hygo bug fixes",
67
+ "add webhook HMAC-SHA256 validation + disable query param auth in prod",
68
+ "pin GitHub Actions to SHAs, update jose to 6.2.3",
69
+ "harden support intake against abuse and data leakage",
70
+ "bump to v0.9.22 — Codex MCP parity + customer bug fixes + security audit remediation",
71
+ "audit: pre-hygo exe-gateway security report",
72
+ "add SECURITY.md — trust document for pre-install security evaluation",
73
+ "fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
74
+ ],
75
+ "other": [
76
+ "bump to 0.9.198 — coordinator reaper guard",
77
+ "bump to 0.9.197 — TTL fix + registry consolidation + TS fixes",
78
+ "update all manifest images to update.askexe.com + compose + beam tuning",
79
+ "bump to 0.9.196",
80
+ "bump to 0.9.195",
81
+ "bump to 0.9.194",
82
+ "bump to 0.9.193",
83
+ "bump to 0.9.192",
84
+ "bump to 0.9.191",
85
+ "bump to 0.9.189",
86
+ "bump to 0.9.188 — HYGO stack-update blockers fixed",
87
+ "bump to 0.9.187",
88
+ "bump to 0.9.186 — cross-session dispatch fix",
89
+ "release: bump exe-os image to v0.9.185 in stack manifest",
90
+ "bump to 0.9.185",
91
+ "bump to 0.9.184",
92
+ "bump to 0.9.183",
93
+ "bump to 0.9.181 — BEAM 3-mode + query expansion",
94
+ "bump to 0.9.180 — complete worktree isolation",
95
+ "bump to 0.9.179",
96
+ "bump to 0.9.178 — Bob's null fixes merged",
97
+ "bump to 0.9.177",
98
+ "bump to 0.9.176",
99
+ "bump to 0.9.175",
100
+ "bump to 0.9.174 — Bob's daemon hardening merged"
101
+ ],
102
+ "migration_notes": []
103
+ },
4
104
  "0.9.197": {
5
105
  "version": "0.9.197",
6
106
  "date": "2026-06-02",
@@ -406,109 +506,6 @@
406
506
  "If daemon goes down, agents will now fail instead of silently",
407
507
  "exe-daemon.ts kills old embed.pid process and cleans up"
408
508
  ]
409
- },
410
- "0.9.159": {
411
- "version": "0.9.159",
412
- "date": "2026-05-29",
413
- "features": [
414
- "verify-stack post-deploy checks — 8 runtime validations",
415
- "preflight deploy gate + filtered schema + gateway graceful degradation",
416
- "harden /exe-afk as primary monitoring tool, deprecate /loop for orchestration",
417
- "add --judge-model flag to LoCoMo harness",
418
- "dashboard.askexe.com — customer credits dashboard (backend + frontend)",
419
- "config persistence contract — document + enforce what survives stack updates",
420
- "add persona depth to identity — tone, vocabulary, response_style, communication_patterns",
421
- "4 BEAM improvements — o4-mini judge, entity expansion, temporal prompts, contradiction detection",
422
- "DMR 100% + BEAM 35% — full results with Claude Sonnet judge",
423
- "session_scope read paths — search filter + backfill + tests",
424
- "add session_scope filtering to memory read paths + MCP tools + backfill",
425
- "classify prompt memories as conversation type + enrich session-end captures",
426
- "add session_scope column to memories table — schema migration + all write paths",
427
- "fix Codex integration + add --codex to all 4 harnesses",
428
- "add checkpoint/resume support for long LoCoMo runs",
429
- "add Codex GPT-5.5 judge, pre-embedding, expanded retrieval, production prompts",
430
- "stack manifest 0.9.10 — all new images for customer deployment",
431
- "update safety + portable backups + restore",
432
- "complete deployment readiness — all 14 second-pass blind spots fixed",
433
- "production-ready stack — all 15 blind spots fixed",
434
- "blocked task notification — ping dispatcher immediately on status change",
435
- "self-improving skills — usage tracking, success counting, and refinement daemon",
436
- "4 retrieval improvements — query expansion, stop words, contradiction resolution, abstention",
437
- "competitive roadmap — serverless tier, identity depth, self-improving skills, user modeling",
438
- "run database migrations before container swap in stack-update"
439
- ],
440
- "fixes": [
441
- "cloud sync NOT NULL resilience — sqlSafeRequired() defaults + per-record error handling, skip bad rows instead of retry storm",
442
- "auto-close temporal guard — reject commits older than task creation date, raise threshold 0.6→0.8",
443
- "session_scope fallback — listTasks returns unscoped results when scoped query finds 0 after daemon restart",
444
- "orphan task file cleanup safety — 24h threshold (was 1h) + ID-based fallback before deleting",
445
- "blocked task escalation — writeNotification to COO when auto-wake fails 3x and marks task blocked",
446
- "daemon memory cascade — prevent duplicate daemons, reap orphan hooks, cap heap",
447
- "auto-inject timeout on tmux capture-pane to prevent session freeze",
448
- "auto-wake crash loop — filter boot memories + circuit breaker",
449
- "Codex numbered instances use baseAgentName for identity resolution",
450
- "auto-chain project scope + writeNotification on needs_review",
451
- "persist WhatsApp auth in Docker volume — prevent data loss on update",
452
- "wake idle codex sessions on pending tasks",
453
- "fix daemon MCP session heap leak",
454
- "include typescript as runtime dependency",
455
- "remove direct Postgres license validation — CF Worker is the only path",
456
- "gateway stop_grace_period 45s — prevent SIGKILL during message drain",
457
- "filter person names from FTS queries to prevent speaker-prefix pollution",
458
- "DMR retrieval 20% → 100% — stop words, name filtering, speaker fix",
459
- "kill idle Codex/OpenCode sessions instead of sending intercom — enables auto-wake respawn",
460
- "suppress daemon auto-reconnect noise — only log after attempt 2+",
461
- "remove E2EE from bug reports — support intake must be readable server-side",
462
- "support API — verified encrypted bug reports work (HTTP 201)",
463
- "support API accepts encrypted bug reports — prevents HTTP 400",
464
- "Codex agents recheck tasks before stopping — prevents idle-with-open-tasks",
465
- "P0 #13 session_scope in cleanup SELECT + P0 #6 wire review signal files"
466
- ],
467
- "security": [
468
- "fix shell injection, SSRF, socket leaks, backup validation",
469
- "bump v0.9.139 — 2 CRITICAL security fixes, 14 bug fixes, 6 features, customer config preservation",
470
- "fix 2 CRITICAL + 1 HIGH from post-fix audit",
471
- "validate X-Agent-Role against roster — prevent privilege escalation",
472
- "release: stack v0.9.8 — security hardening + Hygo bug fixes",
473
- "add webhook HMAC-SHA256 validation + disable query param auth in prod",
474
- "pin GitHub Actions to SHAs, update jose to 6.2.3",
475
- "harden support intake against abuse and data leakage",
476
- "bump to v0.9.22 — Codex MCP parity + customer bug fixes + security audit remediation",
477
- "audit: pre-hygo exe-gateway security report",
478
- "add SECURITY.md — trust document for pre-install security evaluation",
479
- "fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
480
- ],
481
- "other": [
482
- "bump v0.9.159 — daemon memory cascade fix + session_scope + benchmarks",
483
- "arch: customer onboarding automation — exe-os deploy-customer command",
484
- "arch: Fleet Operations Roadmap — 8 phases for production safety at scale",
485
- "arch: add filtered table pipeline + pre-flight deploy system to roadmap",
486
- "add EXE-OS-STACK.md — complete 6-repo deployment map",
487
- "cache tmux session (5 calls → 1) + offset daemon timers",
488
- "cut agent boot from 4min to <30s — merge Bash blocks + parallel DB queries",
489
- "rename memory schema → graph across codebase",
490
- "unified access control — admin token + GoTrue across all services",
491
- "capture data pipeline spec — raw → filter → wiki + CRM projection",
492
- "bump to v0.9.149 — task lifecycle simplification + review notification fix",
493
- "capture gateway connection observability requirements (2026-05-28)",
494
- "bump to v0.9.146 for publish",
495
- "Windows support architecture — WezTerm + WSL decision (2026-05-27)",
496
- "Merge branch 'tom4-work' — device-scoped behaviors + push-notification fix",
497
- "bump to v0.9.145 for publish",
498
- "revert: keep workflow files unchanged — GitHub OAuth blocks workflow scope",
499
- "stage remaining Yoshi fixes — features + bug cleanup",
500
- "add tests for daemon restart orchestrator module",
501
- "publish v0.9.144 — ESM require() fix + reliable task signals + OAuth 2.1",
502
- "add MCP tool tests for message, cloud-sync, and file-copy",
503
- "add coverage for send_message, cloud_sync, file_copy MCP tools (Track A)",
504
- "Recover MCP sessions after daemon restart",
505
- "publish v0.9.143 — all fixes live",
506
- "publish v0.9.142"
507
- ],
508
- "migration_notes": [
509
- "If daemon goes down, agents will now fail instead of silently",
510
- "exe-daemon.ts kills old embed.pid process and cleans up"
511
- ]
512
509
  }
513
510
  }
514
511
  }