@askexenow/exe-os 0.9.85 → 0.9.87
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/dist/bin/agentic-ontology-backfill.js +50 -14
- package/dist/bin/agentic-reflection-backfill.js +50 -14
- package/dist/bin/agentic-semantic-label.js +50 -14
- package/dist/bin/backfill-conversations.js +50 -14
- package/dist/bin/backfill-responses.js +50 -14
- package/dist/bin/backfill-vectors.js +50 -14
- package/dist/bin/bulk-sync-postgres.js +50 -14
- package/dist/bin/cleanup-stale-review-tasks.js +53 -17
- package/dist/bin/cli.js +339 -81
- package/dist/bin/exe-agent.js +18 -0
- package/dist/bin/exe-assign.js +50 -14
- package/dist/bin/exe-boot.js +75 -39
- package/dist/bin/exe-call.js +18 -0
- package/dist/bin/exe-cloud.js +40 -4
- package/dist/bin/exe-dispatch.js +61 -25
- package/dist/bin/exe-doctor.js +40 -4
- package/dist/bin/exe-export-behaviors.js +50 -14
- package/dist/bin/exe-forget.js +50 -14
- package/dist/bin/exe-gateway.js +65 -29
- package/dist/bin/exe-heartbeat.js +55 -19
- package/dist/bin/exe-kill.js +54 -18
- package/dist/bin/exe-launch-agent.js +58 -22
- package/dist/bin/exe-new-employee.js +33 -2
- package/dist/bin/exe-pending-messages.js +53 -17
- package/dist/bin/exe-pending-notifications.js +53 -17
- package/dist/bin/exe-pending-reviews.js +55 -19
- package/dist/bin/exe-rename.js +52 -16
- package/dist/bin/exe-review.js +50 -14
- package/dist/bin/exe-search.js +58 -22
- package/dist/bin/exe-session-cleanup.js +85 -44
- package/dist/bin/exe-start-codex.js +57 -21
- package/dist/bin/exe-start-opencode.js +55 -19
- package/dist/bin/exe-status.js +62 -26
- package/dist/bin/exe-team.js +50 -14
- package/dist/bin/git-sweep.js +63 -27
- package/dist/bin/graph-backfill.js +50 -14
- package/dist/bin/graph-export.js +50 -14
- package/dist/bin/install.js +9 -0
- package/dist/bin/intercom-check.js +67 -31
- package/dist/bin/scan-tasks.js +63 -27
- package/dist/bin/setup.js +53 -13
- package/dist/bin/shard-migrate.js +50 -14
- package/dist/bin/stack-update.js +59 -2
- package/dist/bin/update.js +1 -1
- package/dist/gateway/index.js +65 -29
- package/dist/hooks/bug-report-worker.js +65 -29
- package/dist/hooks/codex-stop-task-finalizer.js +59 -23
- package/dist/hooks/commit-complete.js +64 -28
- package/dist/hooks/error-recall.js +62 -26
- package/dist/hooks/ingest-worker.js +4 -4
- package/dist/hooks/ingest.js +56 -20
- package/dist/hooks/instructions-loaded.js +50 -14
- package/dist/hooks/notification.js +50 -14
- package/dist/hooks/post-compact.js +50 -14
- package/dist/hooks/post-tool-combined.js +63 -27
- package/dist/hooks/pre-compact.js +61 -25
- package/dist/hooks/pre-tool-use.js +58 -22
- package/dist/hooks/prompt-submit.js +78 -42
- package/dist/hooks/session-end.js +66 -30
- package/dist/hooks/session-start.js +68 -32
- package/dist/hooks/stop.js +53 -17
- package/dist/hooks/subagent-stop.js +50 -14
- package/dist/hooks/summary-worker.js +55 -19
- package/dist/index.js +61 -25
- package/dist/lib/cloud-sync.js +32 -14
- package/dist/lib/database.js +22 -4
- package/dist/lib/db-daemon-client.js +16 -4
- package/dist/lib/db.js +22 -4
- package/dist/lib/device-registry.js +22 -4
- package/dist/lib/embedder.js +16 -4
- package/dist/lib/employee-templates.js +18 -0
- package/dist/lib/exe-daemon-client.js +16 -4
- package/dist/lib/exe-daemon.js +874 -232
- package/dist/lib/hybrid-search.js +58 -22
- package/dist/lib/identity-templates.js +6 -2
- package/dist/lib/schedules.js +53 -17
- package/dist/lib/skill-learning.js +16 -4
- package/dist/lib/store.js +50 -14
- package/dist/lib/tasks.js +16 -4
- package/dist/lib/tmux-routing.js +18 -6
- package/dist/mcp/server.js +809 -200
- package/dist/mcp/tools/create-task.js +24 -8
- package/dist/mcp/tools/update-task.js +18 -6
- package/dist/runtime/index.js +61 -25
- package/dist/tui/App.js +91 -55
- package/package.json +1 -1
|
@@ -1583,7 +1583,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1583
1583
|
});
|
|
1584
1584
|
import net from "net";
|
|
1585
1585
|
import os7 from "os";
|
|
1586
|
-
import { spawn } from "child_process";
|
|
1586
|
+
import { spawn, execSync as execSync5 } from "child_process";
|
|
1587
1587
|
import { randomUUID } from "crypto";
|
|
1588
1588
|
import { existsSync as existsSync9, unlinkSync as unlinkSync4, readFileSync as readFileSync9, openSync, closeSync, statSync } from "fs";
|
|
1589
1589
|
import path10 from "path";
|
|
@@ -1613,6 +1613,14 @@ function handleData(chunk) {
|
|
|
1613
1613
|
}
|
|
1614
1614
|
}
|
|
1615
1615
|
}
|
|
1616
|
+
function isZombie(pid) {
|
|
1617
|
+
try {
|
|
1618
|
+
const state = execSync5(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1619
|
+
return state.startsWith("Z");
|
|
1620
|
+
} catch {
|
|
1621
|
+
return false;
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1616
1624
|
function cleanupStaleFiles() {
|
|
1617
1625
|
if (existsSync9(PID_PATH)) {
|
|
1618
1626
|
try {
|
|
@@ -1620,7 +1628,11 @@ function cleanupStaleFiles() {
|
|
|
1620
1628
|
if (pid > 0) {
|
|
1621
1629
|
try {
|
|
1622
1630
|
process.kill(pid, 0);
|
|
1623
|
-
|
|
1631
|
+
if (!isZombie(pid)) {
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1635
|
+
`);
|
|
1624
1636
|
} catch {
|
|
1625
1637
|
}
|
|
1626
1638
|
}
|
|
@@ -1648,8 +1660,8 @@ function findPackageRoot() {
|
|
|
1648
1660
|
function getAvailableMemoryGB() {
|
|
1649
1661
|
if (process.platform === "darwin") {
|
|
1650
1662
|
try {
|
|
1651
|
-
const { execSync:
|
|
1652
|
-
const vmstat =
|
|
1663
|
+
const { execSync: execSync12 } = __require("child_process");
|
|
1664
|
+
const vmstat = execSync12("vm_stat", { encoding: "utf8" });
|
|
1653
1665
|
const pageSize = 16384;
|
|
1654
1666
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1655
1667
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3639,6 +3651,12 @@ async function disposeDatabase() {
|
|
|
3639
3651
|
clearInterval(_walCheckpointTimer);
|
|
3640
3652
|
_walCheckpointTimer = null;
|
|
3641
3653
|
}
|
|
3654
|
+
if (_client) {
|
|
3655
|
+
try {
|
|
3656
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3657
|
+
} catch {
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3642
3660
|
if (_daemonClient) {
|
|
3643
3661
|
_daemonClient.close();
|
|
3644
3662
|
_daemonClient = null;
|
|
@@ -4177,7 +4195,7 @@ var init_state_bus = __esm({
|
|
|
4177
4195
|
});
|
|
4178
4196
|
|
|
4179
4197
|
// src/lib/project-name.ts
|
|
4180
|
-
import { execSync as
|
|
4198
|
+
import { execSync as execSync6 } from "child_process";
|
|
4181
4199
|
import path15 from "path";
|
|
4182
4200
|
function getProjectName(cwd) {
|
|
4183
4201
|
const dir = cwd ?? process.cwd();
|
|
@@ -4185,7 +4203,7 @@ function getProjectName(cwd) {
|
|
|
4185
4203
|
try {
|
|
4186
4204
|
let repoRoot;
|
|
4187
4205
|
try {
|
|
4188
|
-
const gitCommonDir =
|
|
4206
|
+
const gitCommonDir = execSync6("git rev-parse --path-format=absolute --git-common-dir", {
|
|
4189
4207
|
cwd: dir,
|
|
4190
4208
|
encoding: "utf8",
|
|
4191
4209
|
timeout: 2e3,
|
|
@@ -4193,7 +4211,7 @@ function getProjectName(cwd) {
|
|
|
4193
4211
|
}).trim();
|
|
4194
4212
|
repoRoot = path15.dirname(gitCommonDir);
|
|
4195
4213
|
} catch {
|
|
4196
|
-
repoRoot =
|
|
4214
|
+
repoRoot = execSync6("git rev-parse --show-toplevel", {
|
|
4197
4215
|
cwd: dir,
|
|
4198
4216
|
encoding: "utf8",
|
|
4199
4217
|
timeout: 2e3,
|
|
@@ -4300,7 +4318,7 @@ __export(tasks_crud_exports, {
|
|
|
4300
4318
|
import crypto4 from "crypto";
|
|
4301
4319
|
import path16 from "path";
|
|
4302
4320
|
import os11 from "os";
|
|
4303
|
-
import { execSync as
|
|
4321
|
+
import { execSync as execSync7 } from "child_process";
|
|
4304
4322
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
4305
4323
|
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
|
|
4306
4324
|
async function writeCheckpoint(input2) {
|
|
@@ -4645,14 +4663,14 @@ function isTmuxSessionAlive(identifier) {
|
|
|
4645
4663
|
if (!identifier || identifier === "unknown") return true;
|
|
4646
4664
|
try {
|
|
4647
4665
|
if (identifier.startsWith("%")) {
|
|
4648
|
-
const output =
|
|
4666
|
+
const output = execSync7("tmux list-panes -a -F '#{pane_id}'", {
|
|
4649
4667
|
timeout: 2e3,
|
|
4650
4668
|
encoding: "utf8",
|
|
4651
4669
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4652
4670
|
});
|
|
4653
4671
|
return output.split("\n").some((l) => l.trim() === identifier);
|
|
4654
4672
|
} else {
|
|
4655
|
-
|
|
4673
|
+
execSync7(`tmux has-session -t ${JSON.stringify(identifier)}`, {
|
|
4656
4674
|
timeout: 2e3,
|
|
4657
4675
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4658
4676
|
});
|
|
@@ -4661,7 +4679,7 @@ function isTmuxSessionAlive(identifier) {
|
|
|
4661
4679
|
} catch {
|
|
4662
4680
|
if (identifier.startsWith("%")) return true;
|
|
4663
4681
|
try {
|
|
4664
|
-
|
|
4682
|
+
execSync7("tmux list-sessions", {
|
|
4665
4683
|
timeout: 2e3,
|
|
4666
4684
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4667
4685
|
});
|
|
@@ -4676,12 +4694,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
4676
4694
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
4677
4695
|
try {
|
|
4678
4696
|
const since = new Date(taskCreatedAt).toISOString();
|
|
4679
|
-
const branch =
|
|
4697
|
+
const branch = execSync7(
|
|
4680
4698
|
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
4681
4699
|
{ encoding: "utf8", timeout: 3e3 }
|
|
4682
4700
|
).trim();
|
|
4683
4701
|
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
4684
|
-
const commitCount =
|
|
4702
|
+
const commitCount = execSync7(
|
|
4685
4703
|
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
4686
4704
|
{ encoding: "utf8", timeout: 5e3 }
|
|
4687
4705
|
).trim();
|
|
@@ -6280,7 +6298,7 @@ __export(tmux_routing_exports, {
|
|
|
6280
6298
|
spawnEmployee: () => spawnEmployee,
|
|
6281
6299
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
6282
6300
|
});
|
|
6283
|
-
import { execFileSync as execFileSync2, execSync as
|
|
6301
|
+
import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
|
|
6284
6302
|
import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync9, existsSync as existsSync16, appendFileSync, readdirSync as readdirSync4 } from "fs";
|
|
6285
6303
|
import path20 from "path";
|
|
6286
6304
|
import os12 from "os";
|
|
@@ -7001,7 +7019,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
7001
7019
|
let booted = false;
|
|
7002
7020
|
for (let i = 0; i < 30; i++) {
|
|
7003
7021
|
try {
|
|
7004
|
-
|
|
7022
|
+
execSync8("sleep 0.5");
|
|
7005
7023
|
} catch {
|
|
7006
7024
|
}
|
|
7007
7025
|
try {
|
|
@@ -7113,7 +7131,7 @@ var init_task_scope = __esm({
|
|
|
7113
7131
|
// src/lib/keychain.ts
|
|
7114
7132
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
7115
7133
|
import { existsSync as existsSync18, statSync as statSync3 } from "fs";
|
|
7116
|
-
import { execSync as
|
|
7134
|
+
import { execSync as execSync9 } from "child_process";
|
|
7117
7135
|
import path22 from "path";
|
|
7118
7136
|
import os13 from "os";
|
|
7119
7137
|
function getKeyDir() {
|
|
@@ -7130,13 +7148,13 @@ function linuxSecretAvailable() {
|
|
|
7130
7148
|
if (process.platform !== "linux") return false;
|
|
7131
7149
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
7132
7150
|
try {
|
|
7133
|
-
|
|
7151
|
+
execSync9("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
7134
7152
|
} catch {
|
|
7135
7153
|
linuxSecretAvailability = false;
|
|
7136
7154
|
return false;
|
|
7137
7155
|
}
|
|
7138
7156
|
try {
|
|
7139
|
-
|
|
7157
|
+
execSync9("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
7140
7158
|
linuxSecretAvailability = true;
|
|
7141
7159
|
} catch {
|
|
7142
7160
|
linuxSecretAvailability = false;
|
|
@@ -7160,7 +7178,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
7160
7178
|
if (!nativeKeychainAllowed()) return null;
|
|
7161
7179
|
if (process.platform !== "darwin") return null;
|
|
7162
7180
|
try {
|
|
7163
|
-
return
|
|
7181
|
+
return execSync9(
|
|
7164
7182
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
7165
7183
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
7166
7184
|
).trim();
|
|
@@ -7173,13 +7191,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
7173
7191
|
if (process.platform !== "darwin") return false;
|
|
7174
7192
|
try {
|
|
7175
7193
|
try {
|
|
7176
|
-
|
|
7194
|
+
execSync9(
|
|
7177
7195
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
7178
7196
|
{ timeout: 5e3 }
|
|
7179
7197
|
);
|
|
7180
7198
|
} catch {
|
|
7181
7199
|
}
|
|
7182
|
-
|
|
7200
|
+
execSync9(
|
|
7183
7201
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
7184
7202
|
{ timeout: 5e3 }
|
|
7185
7203
|
);
|
|
@@ -7192,7 +7210,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
7192
7210
|
if (!nativeKeychainAllowed()) return false;
|
|
7193
7211
|
if (process.platform !== "darwin") return false;
|
|
7194
7212
|
try {
|
|
7195
|
-
|
|
7213
|
+
execSync9(
|
|
7196
7214
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
7197
7215
|
{ timeout: 5e3 }
|
|
7198
7216
|
);
|
|
@@ -7204,7 +7222,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
7204
7222
|
function linuxSecretGet(service = SERVICE) {
|
|
7205
7223
|
if (!linuxSecretAvailable()) return null;
|
|
7206
7224
|
try {
|
|
7207
|
-
return
|
|
7225
|
+
return execSync9(
|
|
7208
7226
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7209
7227
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
7210
7228
|
).trim();
|
|
@@ -7215,7 +7233,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
7215
7233
|
function linuxSecretSet(value, service = SERVICE) {
|
|
7216
7234
|
if (!linuxSecretAvailable()) return false;
|
|
7217
7235
|
try {
|
|
7218
|
-
|
|
7236
|
+
execSync9(
|
|
7219
7237
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7220
7238
|
{ timeout: 5e3 }
|
|
7221
7239
|
);
|
|
@@ -7228,7 +7246,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
7228
7246
|
if (!nativeKeychainAllowed()) return false;
|
|
7229
7247
|
if (process.platform !== "linux") return false;
|
|
7230
7248
|
try {
|
|
7231
|
-
|
|
7249
|
+
execSync9(
|
|
7232
7250
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7233
7251
|
{ timeout: 5e3 }
|
|
7234
7252
|
);
|
|
@@ -8110,6 +8128,24 @@ var init_platform_procedures = __esm({
|
|
|
8110
8128
|
priority: "p0",
|
|
8111
8129
|
content: "When an agent encounters a suspected Exe OS bug, update breakage, MCP/tool failure, installer issue, memory/orchestration defect, or customer-local patch need, it MUST use create_bug_report. Do this before or alongside any local workaround so the report reaches AskExe support directly via the customer's license. Do NOT ask the founder for permission to file a required bug report. If create_bug_report is deferred/lazy-loaded, load it and call it. If it is unavailable in the live MCP surface, report 'create_bug_report unavailable in this session' and save a local report in exe/output \u2014 never claim the tool does not exist unless the live MCP surface was checked. If upstream delivery fails, call support_test (MCP) and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues; only ask the founder to run `exe-os support test` if MCP is disconnected/unavailable. Classify first: upstream_bug = reproducible exe-os/platform defect; customer_customization = identity, behavior, procedure, config, branding, workflow preference that belongs in customer-owned layers; emergency_hotfix = temporary local patch. For upstream bugs/emergency hotfixes include version, repro steps, expected/actual, files changed, workaround, and local diff summary. Avoid permanent platform-code patches unless founder approves; if a hotfix is unavoidable, document it in the bug report and re-check after npm update."
|
|
8112
8130
|
},
|
|
8131
|
+
{
|
|
8132
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
8133
|
+
domain: "support",
|
|
8134
|
+
priority: "p1",
|
|
8135
|
+
content: "Once per session (COO boot only, never repeat), call list_my_bug_reports to check if any previously filed bug reports have been fixed by AskExe. If any report has status 'fixed' with a fixed_version, surface it to the founder immediately: '\u{1F527} N bug fix(es) available \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no reports exist or none are fixed, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
8136
|
+
},
|
|
8137
|
+
{
|
|
8138
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
8139
|
+
domain: "support",
|
|
8140
|
+
priority: "p0",
|
|
8141
|
+
content: "When an agent or founder identifies a desired capability that exe-os does not yet provide, the COO (or equivalent coordinator) must decide: is this a local customization (identity, behavior, procedure, config, branding, workflow preference that can be configured in customer-owned layers) or an upstream feature request (a platform capability that requires changes to exe-os code, shipped via npm update)? Local customizations: implement immediately using store_behavior, update_identity, company_procedure, or config changes. Upstream features: use create_feature_request to submit to AskExe. Include use case, business impact, and current workaround. Do NOT ask the founder for permission to file a feature request \u2014 file it proactively when the need is clear."
|
|
8142
|
+
},
|
|
8143
|
+
{
|
|
8144
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
8145
|
+
domain: "support",
|
|
8146
|
+
priority: "p1",
|
|
8147
|
+
content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
8148
|
+
},
|
|
8113
8149
|
// --- Operations ---
|
|
8114
8150
|
{
|
|
8115
8151
|
title: "Managers must supervise deployed workers",
|
|
@@ -9428,11 +9464,11 @@ __export(git_staleness_exports, {
|
|
|
9428
9464
|
detectStaleFiles: () => detectStaleFiles,
|
|
9429
9465
|
recordFileRead: () => recordFileRead
|
|
9430
9466
|
});
|
|
9431
|
-
import { execSync as
|
|
9467
|
+
import { execSync as execSync10 } from "child_process";
|
|
9432
9468
|
import path24 from "path";
|
|
9433
9469
|
function getHeadCommit(cwd) {
|
|
9434
9470
|
try {
|
|
9435
|
-
return
|
|
9471
|
+
return execSync10("git rev-parse --short HEAD", {
|
|
9436
9472
|
cwd,
|
|
9437
9473
|
timeout: GIT_TIMEOUT_MS,
|
|
9438
9474
|
encoding: "utf-8"
|
|
@@ -9495,7 +9531,7 @@ async function detectStaleFiles(agentId, cwd) {
|
|
|
9495
9531
|
const readAt = String(record.read_at ?? "");
|
|
9496
9532
|
if (!filePath || !readAt) continue;
|
|
9497
9533
|
try {
|
|
9498
|
-
const gitSummary =
|
|
9534
|
+
const gitSummary = execSync10(
|
|
9499
9535
|
`git log -1 --oneline --after=${JSON.stringify(readAt)} --format="%h %an: %s" -- ${JSON.stringify(filePath)}`,
|
|
9500
9536
|
{
|
|
9501
9537
|
cwd,
|
|
@@ -9539,7 +9575,7 @@ __export(git_task_sweep_exports, {
|
|
|
9539
9575
|
matchScore: () => matchScore,
|
|
9540
9576
|
sweepTasks: () => sweepTasks
|
|
9541
9577
|
});
|
|
9542
|
-
import { execSync as
|
|
9578
|
+
import { execSync as execSync11 } from "child_process";
|
|
9543
9579
|
function extractKeywords(text) {
|
|
9544
9580
|
return text.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length >= 3 && !STOP_WORDS.has(w));
|
|
9545
9581
|
}
|
|
@@ -9568,7 +9604,7 @@ function matchScore(task, commitMessage, changedFiles) {
|
|
|
9568
9604
|
function getRecentCommits(limit = DEFAULT_COMMIT_LIMIT) {
|
|
9569
9605
|
try {
|
|
9570
9606
|
const SEPARATOR = "<<SEP>>";
|
|
9571
|
-
const output =
|
|
9607
|
+
const output = execSync11(
|
|
9572
9608
|
`git log --format="%h${SEPARATOR}%s${SEPARATOR}%aI" --name-only -n ${limit} -z`,
|
|
9573
9609
|
{ encoding: "utf8", timeout: 1e4 }
|
|
9574
9610
|
);
|
|
@@ -1402,7 +1402,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1402
1402
|
});
|
|
1403
1403
|
import net from "net";
|
|
1404
1404
|
import os4 from "os";
|
|
1405
|
-
import { spawn } from "child_process";
|
|
1405
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
1406
1406
|
import { randomUUID } from "crypto";
|
|
1407
1407
|
import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync5, openSync, closeSync, statSync } from "fs";
|
|
1408
1408
|
import path6 from "path";
|
|
@@ -1432,6 +1432,14 @@ function handleData(chunk) {
|
|
|
1432
1432
|
}
|
|
1433
1433
|
}
|
|
1434
1434
|
}
|
|
1435
|
+
function isZombie(pid) {
|
|
1436
|
+
try {
|
|
1437
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1438
|
+
return state.startsWith("Z");
|
|
1439
|
+
} catch {
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1435
1443
|
function cleanupStaleFiles() {
|
|
1436
1444
|
if (existsSync6(PID_PATH)) {
|
|
1437
1445
|
try {
|
|
@@ -1439,7 +1447,11 @@ function cleanupStaleFiles() {
|
|
|
1439
1447
|
if (pid > 0) {
|
|
1440
1448
|
try {
|
|
1441
1449
|
process.kill(pid, 0);
|
|
1442
|
-
|
|
1450
|
+
if (!isZombie(pid)) {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1454
|
+
`);
|
|
1443
1455
|
} catch {
|
|
1444
1456
|
}
|
|
1445
1457
|
}
|
|
@@ -1467,8 +1479,8 @@ function findPackageRoot() {
|
|
|
1467
1479
|
function getAvailableMemoryGB() {
|
|
1468
1480
|
if (process.platform === "darwin") {
|
|
1469
1481
|
try {
|
|
1470
|
-
const { execSync:
|
|
1471
|
-
const vmstat =
|
|
1482
|
+
const { execSync: execSync11 } = __require("child_process");
|
|
1483
|
+
const vmstat = execSync11("vm_stat", { encoding: "utf8" });
|
|
1472
1484
|
const pageSize = 16384;
|
|
1473
1485
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1474
1486
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3458,6 +3470,12 @@ async function disposeDatabase() {
|
|
|
3458
3470
|
clearInterval(_walCheckpointTimer);
|
|
3459
3471
|
_walCheckpointTimer = null;
|
|
3460
3472
|
}
|
|
3473
|
+
if (_client) {
|
|
3474
|
+
try {
|
|
3475
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3476
|
+
} catch {
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3461
3479
|
if (_daemonClient) {
|
|
3462
3480
|
_daemonClient.close();
|
|
3463
3481
|
_daemonClient = null;
|
|
@@ -3494,7 +3512,7 @@ var init_database = __esm({
|
|
|
3494
3512
|
// src/lib/keychain.ts
|
|
3495
3513
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3496
3514
|
import { existsSync as existsSync7, statSync as statSync2 } from "fs";
|
|
3497
|
-
import { execSync as
|
|
3515
|
+
import { execSync as execSync3 } from "child_process";
|
|
3498
3516
|
import path7 from "path";
|
|
3499
3517
|
import os5 from "os";
|
|
3500
3518
|
function getKeyDir() {
|
|
@@ -3511,13 +3529,13 @@ function linuxSecretAvailable() {
|
|
|
3511
3529
|
if (process.platform !== "linux") return false;
|
|
3512
3530
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3513
3531
|
try {
|
|
3514
|
-
|
|
3532
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3515
3533
|
} catch {
|
|
3516
3534
|
linuxSecretAvailability = false;
|
|
3517
3535
|
return false;
|
|
3518
3536
|
}
|
|
3519
3537
|
try {
|
|
3520
|
-
|
|
3538
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3521
3539
|
linuxSecretAvailability = true;
|
|
3522
3540
|
} catch {
|
|
3523
3541
|
linuxSecretAvailability = false;
|
|
@@ -3541,7 +3559,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
3541
3559
|
if (!nativeKeychainAllowed()) return null;
|
|
3542
3560
|
if (process.platform !== "darwin") return null;
|
|
3543
3561
|
try {
|
|
3544
|
-
return
|
|
3562
|
+
return execSync3(
|
|
3545
3563
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3546
3564
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3547
3565
|
).trim();
|
|
@@ -3554,13 +3572,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
3554
3572
|
if (process.platform !== "darwin") return false;
|
|
3555
3573
|
try {
|
|
3556
3574
|
try {
|
|
3557
|
-
|
|
3575
|
+
execSync3(
|
|
3558
3576
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3559
3577
|
{ timeout: 5e3 }
|
|
3560
3578
|
);
|
|
3561
3579
|
} catch {
|
|
3562
3580
|
}
|
|
3563
|
-
|
|
3581
|
+
execSync3(
|
|
3564
3582
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3565
3583
|
{ timeout: 5e3 }
|
|
3566
3584
|
);
|
|
@@ -3573,7 +3591,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3573
3591
|
if (!nativeKeychainAllowed()) return false;
|
|
3574
3592
|
if (process.platform !== "darwin") return false;
|
|
3575
3593
|
try {
|
|
3576
|
-
|
|
3594
|
+
execSync3(
|
|
3577
3595
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3578
3596
|
{ timeout: 5e3 }
|
|
3579
3597
|
);
|
|
@@ -3585,7 +3603,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3585
3603
|
function linuxSecretGet(service = SERVICE) {
|
|
3586
3604
|
if (!linuxSecretAvailable()) return null;
|
|
3587
3605
|
try {
|
|
3588
|
-
return
|
|
3606
|
+
return execSync3(
|
|
3589
3607
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3590
3608
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3591
3609
|
).trim();
|
|
@@ -3596,7 +3614,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
3596
3614
|
function linuxSecretSet(value, service = SERVICE) {
|
|
3597
3615
|
if (!linuxSecretAvailable()) return false;
|
|
3598
3616
|
try {
|
|
3599
|
-
|
|
3617
|
+
execSync3(
|
|
3600
3618
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3601
3619
|
{ timeout: 5e3 }
|
|
3602
3620
|
);
|
|
@@ -3609,7 +3627,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
3609
3627
|
if (!nativeKeychainAllowed()) return false;
|
|
3610
3628
|
if (process.platform !== "linux") return false;
|
|
3611
3629
|
try {
|
|
3612
|
-
|
|
3630
|
+
execSync3(
|
|
3613
3631
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3614
3632
|
{ timeout: 5e3 }
|
|
3615
3633
|
);
|
|
@@ -4546,6 +4564,24 @@ var init_platform_procedures = __esm({
|
|
|
4546
4564
|
priority: "p0",
|
|
4547
4565
|
content: "When an agent encounters a suspected Exe OS bug, update breakage, MCP/tool failure, installer issue, memory/orchestration defect, or customer-local patch need, it MUST use create_bug_report. Do this before or alongside any local workaround so the report reaches AskExe support directly via the customer's license. Do NOT ask the founder for permission to file a required bug report. If create_bug_report is deferred/lazy-loaded, load it and call it. If it is unavailable in the live MCP surface, report 'create_bug_report unavailable in this session' and save a local report in exe/output \u2014 never claim the tool does not exist unless the live MCP surface was checked. If upstream delivery fails, call support_test (MCP) and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues; only ask the founder to run `exe-os support test` if MCP is disconnected/unavailable. Classify first: upstream_bug = reproducible exe-os/platform defect; customer_customization = identity, behavior, procedure, config, branding, workflow preference that belongs in customer-owned layers; emergency_hotfix = temporary local patch. For upstream bugs/emergency hotfixes include version, repro steps, expected/actual, files changed, workaround, and local diff summary. Avoid permanent platform-code patches unless founder approves; if a hotfix is unavoidable, document it in the bug report and re-check after npm update."
|
|
4548
4566
|
},
|
|
4567
|
+
{
|
|
4568
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
4569
|
+
domain: "support",
|
|
4570
|
+
priority: "p1",
|
|
4571
|
+
content: "Once per session (COO boot only, never repeat), call list_my_bug_reports to check if any previously filed bug reports have been fixed by AskExe. If any report has status 'fixed' with a fixed_version, surface it to the founder immediately: '\u{1F527} N bug fix(es) available \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no reports exist or none are fixed, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
4572
|
+
},
|
|
4573
|
+
{
|
|
4574
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
4575
|
+
domain: "support",
|
|
4576
|
+
priority: "p0",
|
|
4577
|
+
content: "When an agent or founder identifies a desired capability that exe-os does not yet provide, the COO (or equivalent coordinator) must decide: is this a local customization (identity, behavior, procedure, config, branding, workflow preference that can be configured in customer-owned layers) or an upstream feature request (a platform capability that requires changes to exe-os code, shipped via npm update)? Local customizations: implement immediately using store_behavior, update_identity, company_procedure, or config changes. Upstream features: use create_feature_request to submit to AskExe. Include use case, business impact, and current workaround. Do NOT ask the founder for permission to file a feature request \u2014 file it proactively when the need is clear."
|
|
4578
|
+
},
|
|
4579
|
+
{
|
|
4580
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
4581
|
+
domain: "support",
|
|
4582
|
+
priority: "p1",
|
|
4583
|
+
content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
4584
|
+
},
|
|
4549
4585
|
// --- Operations ---
|
|
4550
4586
|
{
|
|
4551
4587
|
title: "Managers must supervise deployed workers",
|
|
@@ -6077,7 +6113,7 @@ __export(project_name_exports, {
|
|
|
6077
6113
|
_resetCache: () => _resetCache,
|
|
6078
6114
|
getProjectName: () => getProjectName
|
|
6079
6115
|
});
|
|
6080
|
-
import { execSync as
|
|
6116
|
+
import { execSync as execSync4 } from "child_process";
|
|
6081
6117
|
import path10 from "path";
|
|
6082
6118
|
function getProjectName(cwd) {
|
|
6083
6119
|
const dir = cwd ?? process.cwd();
|
|
@@ -6085,7 +6121,7 @@ function getProjectName(cwd) {
|
|
|
6085
6121
|
try {
|
|
6086
6122
|
let repoRoot;
|
|
6087
6123
|
try {
|
|
6088
|
-
const gitCommonDir =
|
|
6124
|
+
const gitCommonDir = execSync4("git rev-parse --path-format=absolute --git-common-dir", {
|
|
6089
6125
|
cwd: dir,
|
|
6090
6126
|
encoding: "utf8",
|
|
6091
6127
|
timeout: 2e3,
|
|
@@ -6093,7 +6129,7 @@ function getProjectName(cwd) {
|
|
|
6093
6129
|
}).trim();
|
|
6094
6130
|
repoRoot = path10.dirname(gitCommonDir);
|
|
6095
6131
|
} catch {
|
|
6096
|
-
repoRoot =
|
|
6132
|
+
repoRoot = execSync4("git rev-parse --show-toplevel", {
|
|
6097
6133
|
cwd: dir,
|
|
6098
6134
|
encoding: "utf8",
|
|
6099
6135
|
timeout: 2e3,
|
|
@@ -6127,14 +6163,14 @@ var file_grep_exports = {};
|
|
|
6127
6163
|
__export(file_grep_exports, {
|
|
6128
6164
|
grepProjectFiles: () => grepProjectFiles
|
|
6129
6165
|
});
|
|
6130
|
-
import { execSync as
|
|
6166
|
+
import { execSync as execSync5 } from "child_process";
|
|
6131
6167
|
import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync4, existsSync as existsSync10 } from "fs";
|
|
6132
6168
|
import path11 from "path";
|
|
6133
6169
|
import crypto2 from "crypto";
|
|
6134
6170
|
function hasRipgrep() {
|
|
6135
6171
|
if (_hasRg === null) {
|
|
6136
6172
|
try {
|
|
6137
|
-
|
|
6173
|
+
execSync5("rg --version", { stdio: "ignore", timeout: 2e3 });
|
|
6138
6174
|
_hasRg = true;
|
|
6139
6175
|
} catch {
|
|
6140
6176
|
_hasRg = false;
|
|
@@ -6200,7 +6236,7 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
|
|
|
6200
6236
|
const globs = (patterns ?? DEFAULT_PATTERNS).map((p) => `--glob '${p}'`).join(" ");
|
|
6201
6237
|
const excludes = EXCLUDE_DIRS.map((d) => `--glob '!${d}'`).join(" ");
|
|
6202
6238
|
const cmd = `rg -i -c --hidden --no-config --no-ignore '${pattern.replace(/'/g, "\\'")}' . ${globs} ${excludes} --max-filesize ${MAX_FILE_SIZE} 2>/dev/null || true`;
|
|
6203
|
-
const output =
|
|
6239
|
+
const output = execSync5(cmd, {
|
|
6204
6240
|
cwd: projectRoot,
|
|
6205
6241
|
encoding: "utf8",
|
|
6206
6242
|
timeout: 3e3,
|
|
@@ -6215,12 +6251,12 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
|
|
|
6215
6251
|
const matchCount = parseInt(line.slice(colonIdx + 1));
|
|
6216
6252
|
if (isNaN(matchCount) || matchCount === 0) continue;
|
|
6217
6253
|
try {
|
|
6218
|
-
const firstMatch =
|
|
6254
|
+
const firstMatch = execSync5(
|
|
6219
6255
|
`rg -i -n --hidden '${pattern.replace(/'/g, "\\'")}' '${filePath}' --max-count 1 2>/dev/null | head -1`,
|
|
6220
6256
|
{ cwd: projectRoot, encoding: "utf8", timeout: 1e3 }
|
|
6221
6257
|
).trim();
|
|
6222
6258
|
const lineNum = parseInt(firstMatch.split(":")[0] ?? "1");
|
|
6223
|
-
const totalLines =
|
|
6259
|
+
const totalLines = execSync5(`wc -l < '${filePath}'`, {
|
|
6224
6260
|
cwd: projectRoot,
|
|
6225
6261
|
encoding: "utf8",
|
|
6226
6262
|
timeout: 1e3
|
|
@@ -7571,7 +7607,7 @@ var init_hybrid_search = __esm({
|
|
|
7571
7607
|
});
|
|
7572
7608
|
|
|
7573
7609
|
// src/lib/session-key.ts
|
|
7574
|
-
import { execSync as
|
|
7610
|
+
import { execSync as execSync6 } from "child_process";
|
|
7575
7611
|
function normalizeCommand(command) {
|
|
7576
7612
|
const trimmed = command.trim().toLowerCase();
|
|
7577
7613
|
const parts = trimmed.split(/[\\/]/);
|
|
@@ -7590,7 +7626,7 @@ function resolveRuntimeProcess() {
|
|
|
7590
7626
|
let pid = process.ppid;
|
|
7591
7627
|
for (let i = 0; i < 10; i++) {
|
|
7592
7628
|
try {
|
|
7593
|
-
const info =
|
|
7629
|
+
const info = execSync6(`ps -p ${pid} -o ppid=,comm=`, {
|
|
7594
7630
|
encoding: "utf8",
|
|
7595
7631
|
timeout: 2e3
|
|
7596
7632
|
}).trim();
|
|
@@ -7653,7 +7689,7 @@ var init_agent_context = __esm({
|
|
|
7653
7689
|
|
|
7654
7690
|
// src/lib/active-agent.ts
|
|
7655
7691
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, unlinkSync as unlinkSync3, readdirSync as readdirSync3 } from "fs";
|
|
7656
|
-
import { execSync as
|
|
7692
|
+
import { execSync as execSync7 } from "child_process";
|
|
7657
7693
|
import path12 from "path";
|
|
7658
7694
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
7659
7695
|
if (candidate === baseName) return true;
|
|
@@ -7747,7 +7783,7 @@ function getActiveAgent() {
|
|
|
7747
7783
|
} catch {
|
|
7748
7784
|
}
|
|
7749
7785
|
try {
|
|
7750
|
-
const sessionName =
|
|
7786
|
+
const sessionName = execSync7(
|
|
7751
7787
|
"tmux display-message -p '#{session_name}' 2>/dev/null",
|
|
7752
7788
|
{ encoding: "utf8", timeout: 2e3 }
|
|
7753
7789
|
).trim();
|
|
@@ -7966,7 +8002,7 @@ var init_transport = __esm({
|
|
|
7966
8002
|
});
|
|
7967
8003
|
|
|
7968
8004
|
// src/lib/cc-agent-support.ts
|
|
7969
|
-
import { execSync as
|
|
8005
|
+
import { execSync as execSync8 } from "child_process";
|
|
7970
8006
|
var init_cc_agent_support = __esm({
|
|
7971
8007
|
"src/lib/cc-agent-support.ts"() {
|
|
7972
8008
|
"use strict";
|
|
@@ -8243,7 +8279,7 @@ var catchup_brief_exports = {};
|
|
|
8243
8279
|
__export(catchup_brief_exports, {
|
|
8244
8280
|
buildCatchupBrief: () => buildCatchupBrief
|
|
8245
8281
|
});
|
|
8246
|
-
import { execSync as
|
|
8282
|
+
import { execSync as execSync9 } from "child_process";
|
|
8247
8283
|
function clipText(text, maxChars) {
|
|
8248
8284
|
if (text.length <= maxChars) return text;
|
|
8249
8285
|
if (maxChars <= 1) return "\u2026";
|
|
@@ -8289,7 +8325,7 @@ ${clipText(checkpoint.raw_text, MAX_CHECKPOINT_CHARS)}`
|
|
|
8289
8325
|
} catch {
|
|
8290
8326
|
}
|
|
8291
8327
|
try {
|
|
8292
|
-
const gitLog =
|
|
8328
|
+
const gitLog = execSync9(
|
|
8293
8329
|
`git log --oneline --since=${JSON.stringify(lastTimestamp)} --format="%h %an: %s" | head -10`,
|
|
8294
8330
|
{ cwd, timeout: 3e3, encoding: "utf-8" }
|
|
8295
8331
|
).trim();
|
|
@@ -8367,11 +8403,11 @@ __export(git_staleness_exports, {
|
|
|
8367
8403
|
detectStaleFiles: () => detectStaleFiles,
|
|
8368
8404
|
recordFileRead: () => recordFileRead
|
|
8369
8405
|
});
|
|
8370
|
-
import { execSync as
|
|
8406
|
+
import { execSync as execSync10 } from "child_process";
|
|
8371
8407
|
import path19 from "path";
|
|
8372
8408
|
function getHeadCommit(cwd) {
|
|
8373
8409
|
try {
|
|
8374
|
-
return
|
|
8410
|
+
return execSync10("git rev-parse --short HEAD", {
|
|
8375
8411
|
cwd,
|
|
8376
8412
|
timeout: GIT_TIMEOUT_MS,
|
|
8377
8413
|
encoding: "utf-8"
|
|
@@ -8434,7 +8470,7 @@ async function detectStaleFiles(agentId, cwd) {
|
|
|
8434
8470
|
const readAt = String(record.read_at ?? "");
|
|
8435
8471
|
if (!filePath || !readAt) continue;
|
|
8436
8472
|
try {
|
|
8437
|
-
const gitSummary =
|
|
8473
|
+
const gitSummary = execSync10(
|
|
8438
8474
|
`git log -1 --oneline --after=${JSON.stringify(readAt)} --format="%h %an: %s" -- ${JSON.stringify(filePath)}`,
|
|
8439
8475
|
{
|
|
8440
8476
|
cwd,
|