@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.
- package/deploy/compose/docker-compose.yml +2 -2
- package/deploy/stack-manifests/v0.9.json +5 -5
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/{chunk-7JCK6TXX.js → chunk-62DAMAFL.js} +36 -0
- package/dist/{chunk-4F4SOCKN.js → chunk-CHZMPZJ3.js} +1 -1
- package/dist/{chunk-T5U27Y4H.js → chunk-M7NGABPF.js} +5 -5
- package/dist/{daemon-orchestration-N5GPEP4F.js → daemon-orchestration-ZBSS6VZR.js} +1 -1
- package/dist/hooks/session-end.js +0 -6
- package/dist/lib/exe-daemon.js +66 -63
- package/dist/mcp/register-tools.js +2 -2
- package/dist/mcp/server.js +2 -2
- package/dist/{stack-update-PI2TWEGS.js → stack-update-C4BAPLXJ.js} +1 -1
- package/package.json +1 -1
- package/release-notes.json +101 -104
|
@@ -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: "
|
|
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: "
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
}
|
package/dist/bin/stack-update.js
CHANGED
|
@@ -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-
|
|
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)})`;
|
|
@@ -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
|
|
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/")
|
|
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
|
|
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/")
|
|
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" :
|
|
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
|
}
|
|
@@ -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) {
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -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
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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
|
-
}
|
|
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
|
|
802
|
-
const client =
|
|
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
|
|
904
|
-
const client =
|
|
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
|
|
930
|
-
const client =
|
|
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 ??
|
|
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
|
|
1066
|
-
const client =
|
|
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-
|
|
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
|
|
2181
|
-
const deps = polling.createRealDeps(
|
|
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(
|
|
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
|
|
2216
|
-
const { checkSessionTTL, createSessionTTLRealDeps } = await import("../daemon-orchestration-
|
|
2217
|
-
const deps = createSessionTTLRealDeps(
|
|
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
|
|
2265
|
-
const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-
|
|
2267
|
+
const { getClient } = await import("./database.js");
|
|
2268
|
+
const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-ZBSS6VZR.js");
|
|
2266
2269
|
const deps = createIdleKillRealDeps(
|
|
2267
|
-
|
|
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
|
|
2302
|
-
const client =
|
|
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
|
|
2510
|
-
const client =
|
|
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
|
|
2538
|
-
const client =
|
|
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
|
|
2611
|
-
const client =
|
|
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
|
|
2643
|
-
const client =
|
|
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
|
|
2755
|
+
const { getClient } = await import("./database.js");
|
|
2753
2756
|
const { SOFT_DELETE_RETENTION_DAYS } = await import("./database.js");
|
|
2754
|
-
const client =
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
2900
|
-
const client =
|
|
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
|
|
2918
|
-
const { releaseStuckTasks, createStuckTaskRealDeps } = await import("../daemon-orchestration-
|
|
2919
|
-
const deps = createStuckTaskRealDeps(
|
|
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
|
|
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
|
|
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
|
|
3193
|
-
const client = await
|
|
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
|
|
3530
|
-
const client =
|
|
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
|
|
3600
|
+
const { getClient } = await import("./database.js");
|
|
3598
3601
|
const { deduplicateIntercomMemories } = await import("./consolidation.js");
|
|
3599
|
-
const count = await deduplicateIntercomMemories(
|
|
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
|
|
3617
|
+
const { getClient } = await import("./database.js");
|
|
3615
3618
|
const { sweepExpiredTraces } = await import("./consolidation.js");
|
|
3616
|
-
const count = await sweepExpiredTraces(
|
|
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
|
|
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 =
|
|
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-
|
|
3
|
+
} from "../chunk-CHZMPZJ3.js";
|
|
4
4
|
import "../chunk-PLNYW6PA.js";
|
|
5
5
|
import "../chunk-AFJWUI3Y.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-62DAMAFL.js";
|
|
7
7
|
import "../chunk-GHCVD7WV.js";
|
|
8
8
|
import "../chunk-WZTQUBIE.js";
|
|
9
9
|
import "../chunk-KH5Y6RR4.js";
|
package/dist/mcp/server.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../chunk-V4TZI6EO.js";
|
|
4
4
|
import {
|
|
5
5
|
registerAllTools
|
|
6
|
-
} from "../chunk-
|
|
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-
|
|
14
|
+
import "../chunk-62DAMAFL.js";
|
|
15
15
|
import "../chunk-GHCVD7WV.js";
|
|
16
16
|
import "../chunk-WZTQUBIE.js";
|
|
17
17
|
import "../chunk-KH5Y6RR4.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
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",
|
package/release-notes.json
CHANGED
|
@@ -1,6 +1,106 @@
|
|
|
1
1
|
{
|
|
2
|
-
"current": "0.9.
|
|
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
|
}
|