@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
package/dist/bin/exe-cloud.js
CHANGED
|
@@ -1531,7 +1531,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1531
1531
|
});
|
|
1532
1532
|
import net from "net";
|
|
1533
1533
|
import os5 from "os";
|
|
1534
|
-
import { spawn } from "child_process";
|
|
1534
|
+
import { spawn, execSync as execSync3 } from "child_process";
|
|
1535
1535
|
import { randomUUID } from "crypto";
|
|
1536
1536
|
import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync as statSync2 } from "fs";
|
|
1537
1537
|
import path6 from "path";
|
|
@@ -1561,6 +1561,14 @@ function handleData(chunk) {
|
|
|
1561
1561
|
}
|
|
1562
1562
|
}
|
|
1563
1563
|
}
|
|
1564
|
+
function isZombie(pid) {
|
|
1565
|
+
try {
|
|
1566
|
+
const state = execSync3(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1567
|
+
return state.startsWith("Z");
|
|
1568
|
+
} catch {
|
|
1569
|
+
return false;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1564
1572
|
function cleanupStaleFiles() {
|
|
1565
1573
|
if (existsSync6(PID_PATH)) {
|
|
1566
1574
|
try {
|
|
@@ -1568,7 +1576,11 @@ function cleanupStaleFiles() {
|
|
|
1568
1576
|
if (pid > 0) {
|
|
1569
1577
|
try {
|
|
1570
1578
|
process.kill(pid, 0);
|
|
1571
|
-
|
|
1579
|
+
if (!isZombie(pid)) {
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1583
|
+
`);
|
|
1572
1584
|
} catch {
|
|
1573
1585
|
}
|
|
1574
1586
|
}
|
|
@@ -1596,8 +1608,8 @@ function findPackageRoot() {
|
|
|
1596
1608
|
function getAvailableMemoryGB() {
|
|
1597
1609
|
if (process.platform === "darwin") {
|
|
1598
1610
|
try {
|
|
1599
|
-
const { execSync:
|
|
1600
|
-
const vmstat =
|
|
1611
|
+
const { execSync: execSync4 } = __require("child_process");
|
|
1612
|
+
const vmstat = execSync4("vm_stat", { encoding: "utf8" });
|
|
1601
1613
|
const pageSize = 16384;
|
|
1602
1614
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1603
1615
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3552,6 +3564,12 @@ async function disposeDatabase() {
|
|
|
3552
3564
|
clearInterval(_walCheckpointTimer);
|
|
3553
3565
|
_walCheckpointTimer = null;
|
|
3554
3566
|
}
|
|
3567
|
+
if (_client) {
|
|
3568
|
+
try {
|
|
3569
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3570
|
+
} catch {
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3555
3573
|
if (_daemonClient) {
|
|
3556
3574
|
_daemonClient.close();
|
|
3557
3575
|
_daemonClient = null;
|
|
@@ -6520,6 +6538,24 @@ var init_platform_procedures = __esm({
|
|
|
6520
6538
|
priority: "p0",
|
|
6521
6539
|
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."
|
|
6522
6540
|
},
|
|
6541
|
+
{
|
|
6542
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
6543
|
+
domain: "support",
|
|
6544
|
+
priority: "p1",
|
|
6545
|
+
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."
|
|
6546
|
+
},
|
|
6547
|
+
{
|
|
6548
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
6549
|
+
domain: "support",
|
|
6550
|
+
priority: "p0",
|
|
6551
|
+
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."
|
|
6552
|
+
},
|
|
6553
|
+
{
|
|
6554
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
6555
|
+
domain: "support",
|
|
6556
|
+
priority: "p1",
|
|
6557
|
+
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."
|
|
6558
|
+
},
|
|
6523
6559
|
// --- Operations ---
|
|
6524
6560
|
{
|
|
6525
6561
|
title: "Managers must supervise deployed workers",
|
package/dist/bin/exe-dispatch.js
CHANGED
|
@@ -1581,7 +1581,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1581
1581
|
});
|
|
1582
1582
|
import net from "net";
|
|
1583
1583
|
import os6 from "os";
|
|
1584
|
-
import { spawn } from "child_process";
|
|
1584
|
+
import { spawn, execSync as execSync4 } from "child_process";
|
|
1585
1585
|
import { randomUUID } from "crypto";
|
|
1586
1586
|
import { existsSync as existsSync8, unlinkSync as unlinkSync2, readFileSync as readFileSync7, openSync, closeSync, statSync } from "fs";
|
|
1587
1587
|
import path8 from "path";
|
|
@@ -1611,6 +1611,14 @@ function handleData(chunk) {
|
|
|
1611
1611
|
}
|
|
1612
1612
|
}
|
|
1613
1613
|
}
|
|
1614
|
+
function isZombie(pid) {
|
|
1615
|
+
try {
|
|
1616
|
+
const state = execSync4(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1617
|
+
return state.startsWith("Z");
|
|
1618
|
+
} catch {
|
|
1619
|
+
return false;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1614
1622
|
function cleanupStaleFiles() {
|
|
1615
1623
|
if (existsSync8(PID_PATH)) {
|
|
1616
1624
|
try {
|
|
@@ -1618,7 +1626,11 @@ function cleanupStaleFiles() {
|
|
|
1618
1626
|
if (pid > 0) {
|
|
1619
1627
|
try {
|
|
1620
1628
|
process.kill(pid, 0);
|
|
1621
|
-
|
|
1629
|
+
if (!isZombie(pid)) {
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1633
|
+
`);
|
|
1622
1634
|
} catch {
|
|
1623
1635
|
}
|
|
1624
1636
|
}
|
|
@@ -1646,8 +1658,8 @@ function findPackageRoot() {
|
|
|
1646
1658
|
function getAvailableMemoryGB() {
|
|
1647
1659
|
if (process.platform === "darwin") {
|
|
1648
1660
|
try {
|
|
1649
|
-
const { execSync:
|
|
1650
|
-
const vmstat =
|
|
1661
|
+
const { execSync: execSync9 } = __require("child_process");
|
|
1662
|
+
const vmstat = execSync9("vm_stat", { encoding: "utf8" });
|
|
1651
1663
|
const pageSize = 16384;
|
|
1652
1664
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1653
1665
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3637,6 +3649,12 @@ async function disposeDatabase() {
|
|
|
3637
3649
|
clearInterval(_walCheckpointTimer);
|
|
3638
3650
|
_walCheckpointTimer = null;
|
|
3639
3651
|
}
|
|
3652
|
+
if (_client) {
|
|
3653
|
+
try {
|
|
3654
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3655
|
+
} catch {
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3640
3658
|
if (_daemonClient) {
|
|
3641
3659
|
_daemonClient.close();
|
|
3642
3660
|
_daemonClient = null;
|
|
@@ -4018,7 +4036,7 @@ var init_state_bus = __esm({
|
|
|
4018
4036
|
});
|
|
4019
4037
|
|
|
4020
4038
|
// src/lib/project-name.ts
|
|
4021
|
-
import { execSync as
|
|
4039
|
+
import { execSync as execSync5 } from "child_process";
|
|
4022
4040
|
import path13 from "path";
|
|
4023
4041
|
function getProjectName(cwd) {
|
|
4024
4042
|
const dir = cwd ?? process.cwd();
|
|
@@ -4026,7 +4044,7 @@ function getProjectName(cwd) {
|
|
|
4026
4044
|
try {
|
|
4027
4045
|
let repoRoot;
|
|
4028
4046
|
try {
|
|
4029
|
-
const gitCommonDir =
|
|
4047
|
+
const gitCommonDir = execSync5("git rev-parse --path-format=absolute --git-common-dir", {
|
|
4030
4048
|
cwd: dir,
|
|
4031
4049
|
encoding: "utf8",
|
|
4032
4050
|
timeout: 2e3,
|
|
@@ -4034,7 +4052,7 @@ function getProjectName(cwd) {
|
|
|
4034
4052
|
}).trim();
|
|
4035
4053
|
repoRoot = path13.dirname(gitCommonDir);
|
|
4036
4054
|
} catch {
|
|
4037
|
-
repoRoot =
|
|
4055
|
+
repoRoot = execSync5("git rev-parse --show-toplevel", {
|
|
4038
4056
|
cwd: dir,
|
|
4039
4057
|
encoding: "utf8",
|
|
4040
4058
|
timeout: 2e3,
|
|
@@ -4125,7 +4143,7 @@ var init_session_scope = __esm({
|
|
|
4125
4143
|
import crypto4 from "crypto";
|
|
4126
4144
|
import path14 from "path";
|
|
4127
4145
|
import os10 from "os";
|
|
4128
|
-
import { execSync as
|
|
4146
|
+
import { execSync as execSync6 } from "child_process";
|
|
4129
4147
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
4130
4148
|
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
4131
4149
|
async function writeCheckpoint(input) {
|
|
@@ -4470,14 +4488,14 @@ function isTmuxSessionAlive(identifier) {
|
|
|
4470
4488
|
if (!identifier || identifier === "unknown") return true;
|
|
4471
4489
|
try {
|
|
4472
4490
|
if (identifier.startsWith("%")) {
|
|
4473
|
-
const output =
|
|
4491
|
+
const output = execSync6("tmux list-panes -a -F '#{pane_id}'", {
|
|
4474
4492
|
timeout: 2e3,
|
|
4475
4493
|
encoding: "utf8",
|
|
4476
4494
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4477
4495
|
});
|
|
4478
4496
|
return output.split("\n").some((l) => l.trim() === identifier);
|
|
4479
4497
|
} else {
|
|
4480
|
-
|
|
4498
|
+
execSync6(`tmux has-session -t ${JSON.stringify(identifier)}`, {
|
|
4481
4499
|
timeout: 2e3,
|
|
4482
4500
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4483
4501
|
});
|
|
@@ -4486,7 +4504,7 @@ function isTmuxSessionAlive(identifier) {
|
|
|
4486
4504
|
} catch {
|
|
4487
4505
|
if (identifier.startsWith("%")) return true;
|
|
4488
4506
|
try {
|
|
4489
|
-
|
|
4507
|
+
execSync6("tmux list-sessions", {
|
|
4490
4508
|
timeout: 2e3,
|
|
4491
4509
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4492
4510
|
});
|
|
@@ -4501,12 +4519,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
4501
4519
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
4502
4520
|
try {
|
|
4503
4521
|
const since = new Date(taskCreatedAt).toISOString();
|
|
4504
|
-
const branch =
|
|
4522
|
+
const branch = execSync6(
|
|
4505
4523
|
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
4506
4524
|
{ encoding: "utf8", timeout: 3e3 }
|
|
4507
4525
|
).trim();
|
|
4508
4526
|
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
4509
|
-
const commitCount =
|
|
4527
|
+
const commitCount = execSync6(
|
|
4510
4528
|
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
4511
4529
|
{ encoding: "utf8", timeout: 5e3 }
|
|
4512
4530
|
).trim();
|
|
@@ -6105,7 +6123,7 @@ __export(tmux_routing_exports, {
|
|
|
6105
6123
|
spawnEmployee: () => spawnEmployee,
|
|
6106
6124
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
6107
6125
|
});
|
|
6108
|
-
import { execFileSync as execFileSync2, execSync as
|
|
6126
|
+
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
6109
6127
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync15, appendFileSync, readdirSync as readdirSync3 } from "fs";
|
|
6110
6128
|
import path18 from "path";
|
|
6111
6129
|
import os11 from "os";
|
|
@@ -6826,7 +6844,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
|
|
|
6826
6844
|
let booted = false;
|
|
6827
6845
|
for (let i = 0; i < 30; i++) {
|
|
6828
6846
|
try {
|
|
6829
|
-
|
|
6847
|
+
execSync7("sleep 0.5");
|
|
6830
6848
|
} catch {
|
|
6831
6849
|
}
|
|
6832
6850
|
try {
|
|
@@ -6905,7 +6923,7 @@ var init_tmux_routing = __esm({
|
|
|
6905
6923
|
// src/lib/keychain.ts
|
|
6906
6924
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6907
6925
|
import { existsSync as existsSync16, statSync as statSync2 } from "fs";
|
|
6908
|
-
import { execSync as
|
|
6926
|
+
import { execSync as execSync8 } from "child_process";
|
|
6909
6927
|
import path19 from "path";
|
|
6910
6928
|
import os12 from "os";
|
|
6911
6929
|
function getKeyDir() {
|
|
@@ -6922,13 +6940,13 @@ function linuxSecretAvailable() {
|
|
|
6922
6940
|
if (process.platform !== "linux") return false;
|
|
6923
6941
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
6924
6942
|
try {
|
|
6925
|
-
|
|
6943
|
+
execSync8("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
6926
6944
|
} catch {
|
|
6927
6945
|
linuxSecretAvailability = false;
|
|
6928
6946
|
return false;
|
|
6929
6947
|
}
|
|
6930
6948
|
try {
|
|
6931
|
-
|
|
6949
|
+
execSync8("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
6932
6950
|
linuxSecretAvailability = true;
|
|
6933
6951
|
} catch {
|
|
6934
6952
|
linuxSecretAvailability = false;
|
|
@@ -6952,7 +6970,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
6952
6970
|
if (!nativeKeychainAllowed()) return null;
|
|
6953
6971
|
if (process.platform !== "darwin") return null;
|
|
6954
6972
|
try {
|
|
6955
|
-
return
|
|
6973
|
+
return execSync8(
|
|
6956
6974
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
6957
6975
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
6958
6976
|
).trim();
|
|
@@ -6965,13 +6983,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
6965
6983
|
if (process.platform !== "darwin") return false;
|
|
6966
6984
|
try {
|
|
6967
6985
|
try {
|
|
6968
|
-
|
|
6986
|
+
execSync8(
|
|
6969
6987
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
6970
6988
|
{ timeout: 5e3 }
|
|
6971
6989
|
);
|
|
6972
6990
|
} catch {
|
|
6973
6991
|
}
|
|
6974
|
-
|
|
6992
|
+
execSync8(
|
|
6975
6993
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
6976
6994
|
{ timeout: 5e3 }
|
|
6977
6995
|
);
|
|
@@ -6984,7 +7002,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
6984
7002
|
if (!nativeKeychainAllowed()) return false;
|
|
6985
7003
|
if (process.platform !== "darwin") return false;
|
|
6986
7004
|
try {
|
|
6987
|
-
|
|
7005
|
+
execSync8(
|
|
6988
7006
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
6989
7007
|
{ timeout: 5e3 }
|
|
6990
7008
|
);
|
|
@@ -6996,7 +7014,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
6996
7014
|
function linuxSecretGet(service = SERVICE) {
|
|
6997
7015
|
if (!linuxSecretAvailable()) return null;
|
|
6998
7016
|
try {
|
|
6999
|
-
return
|
|
7017
|
+
return execSync8(
|
|
7000
7018
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7001
7019
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
7002
7020
|
).trim();
|
|
@@ -7007,7 +7025,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
7007
7025
|
function linuxSecretSet(value, service = SERVICE) {
|
|
7008
7026
|
if (!linuxSecretAvailable()) return false;
|
|
7009
7027
|
try {
|
|
7010
|
-
|
|
7028
|
+
execSync8(
|
|
7011
7029
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7012
7030
|
{ timeout: 5e3 }
|
|
7013
7031
|
);
|
|
@@ -7020,7 +7038,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
7020
7038
|
if (!nativeKeychainAllowed()) return false;
|
|
7021
7039
|
if (process.platform !== "linux") return false;
|
|
7022
7040
|
try {
|
|
7023
|
-
|
|
7041
|
+
execSync8(
|
|
7024
7042
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7025
7043
|
{ timeout: 5e3 }
|
|
7026
7044
|
);
|
|
@@ -7902,6 +7920,24 @@ var init_platform_procedures = __esm({
|
|
|
7902
7920
|
priority: "p0",
|
|
7903
7921
|
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."
|
|
7904
7922
|
},
|
|
7923
|
+
{
|
|
7924
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
7925
|
+
domain: "support",
|
|
7926
|
+
priority: "p1",
|
|
7927
|
+
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."
|
|
7928
|
+
},
|
|
7929
|
+
{
|
|
7930
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
7931
|
+
domain: "support",
|
|
7932
|
+
priority: "p0",
|
|
7933
|
+
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."
|
|
7934
|
+
},
|
|
7935
|
+
{
|
|
7936
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
7937
|
+
domain: "support",
|
|
7938
|
+
priority: "p1",
|
|
7939
|
+
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."
|
|
7940
|
+
},
|
|
7905
7941
|
// --- Operations ---
|
|
7906
7942
|
{
|
|
7907
7943
|
title: "Managers must supervise deployed workers",
|
package/dist/bin/exe-doctor.js
CHANGED
|
@@ -2035,7 +2035,7 @@ __export(exe_daemon_client_exports, {
|
|
|
2035
2035
|
});
|
|
2036
2036
|
import net from "net";
|
|
2037
2037
|
import os5 from "os";
|
|
2038
|
-
import { spawn } from "child_process";
|
|
2038
|
+
import { spawn, execSync as execSync3 } from "child_process";
|
|
2039
2039
|
import { randomUUID } from "crypto";
|
|
2040
2040
|
import { existsSync as existsSync9, unlinkSync as unlinkSync3, readFileSync as readFileSync5, openSync, closeSync, statSync as statSync3 } from "fs";
|
|
2041
2041
|
import path9 from "path";
|
|
@@ -2065,6 +2065,14 @@ function handleData(chunk) {
|
|
|
2065
2065
|
}
|
|
2066
2066
|
}
|
|
2067
2067
|
}
|
|
2068
|
+
function isZombie(pid) {
|
|
2069
|
+
try {
|
|
2070
|
+
const state = execSync3(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
2071
|
+
return state.startsWith("Z");
|
|
2072
|
+
} catch {
|
|
2073
|
+
return false;
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2068
2076
|
function cleanupStaleFiles() {
|
|
2069
2077
|
if (existsSync9(PID_PATH)) {
|
|
2070
2078
|
try {
|
|
@@ -2072,7 +2080,11 @@ function cleanupStaleFiles() {
|
|
|
2072
2080
|
if (pid > 0) {
|
|
2073
2081
|
try {
|
|
2074
2082
|
process.kill(pid, 0);
|
|
2075
|
-
|
|
2083
|
+
if (!isZombie(pid)) {
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
2087
|
+
`);
|
|
2076
2088
|
} catch {
|
|
2077
2089
|
}
|
|
2078
2090
|
}
|
|
@@ -2100,8 +2112,8 @@ function findPackageRoot() {
|
|
|
2100
2112
|
function getAvailableMemoryGB() {
|
|
2101
2113
|
if (process.platform === "darwin") {
|
|
2102
2114
|
try {
|
|
2103
|
-
const { execSync:
|
|
2104
|
-
const vmstat =
|
|
2115
|
+
const { execSync: execSync4 } = __require("child_process");
|
|
2116
|
+
const vmstat = execSync4("vm_stat", { encoding: "utf8" });
|
|
2105
2117
|
const pageSize = 16384;
|
|
2106
2118
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
2107
2119
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -4091,6 +4103,12 @@ async function disposeDatabase() {
|
|
|
4091
4103
|
clearInterval(_walCheckpointTimer);
|
|
4092
4104
|
_walCheckpointTimer = null;
|
|
4093
4105
|
}
|
|
4106
|
+
if (_client) {
|
|
4107
|
+
try {
|
|
4108
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
4109
|
+
} catch {
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4094
4112
|
if (_daemonClient) {
|
|
4095
4113
|
_daemonClient.close();
|
|
4096
4114
|
_daemonClient = null;
|
|
@@ -4456,6 +4474,24 @@ var init_platform_procedures = __esm({
|
|
|
4456
4474
|
priority: "p0",
|
|
4457
4475
|
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."
|
|
4458
4476
|
},
|
|
4477
|
+
{
|
|
4478
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
4479
|
+
domain: "support",
|
|
4480
|
+
priority: "p1",
|
|
4481
|
+
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."
|
|
4482
|
+
},
|
|
4483
|
+
{
|
|
4484
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
4485
|
+
domain: "support",
|
|
4486
|
+
priority: "p0",
|
|
4487
|
+
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."
|
|
4488
|
+
},
|
|
4489
|
+
{
|
|
4490
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
4491
|
+
domain: "support",
|
|
4492
|
+
priority: "p1",
|
|
4493
|
+
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."
|
|
4494
|
+
},
|
|
4459
4495
|
// --- Operations ---
|
|
4460
4496
|
{
|
|
4461
4497
|
title: "Managers must supervise deployed workers",
|
|
@@ -1068,7 +1068,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1068
1068
|
});
|
|
1069
1069
|
import net from "net";
|
|
1070
1070
|
import os4 from "os";
|
|
1071
|
-
import { spawn } from "child_process";
|
|
1071
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
1072
1072
|
import { randomUUID } from "crypto";
|
|
1073
1073
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
1074
1074
|
import path5 from "path";
|
|
@@ -1098,6 +1098,14 @@ function handleData(chunk) {
|
|
|
1098
1098
|
}
|
|
1099
1099
|
}
|
|
1100
1100
|
}
|
|
1101
|
+
function isZombie(pid) {
|
|
1102
|
+
try {
|
|
1103
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1104
|
+
return state.startsWith("Z");
|
|
1105
|
+
} catch {
|
|
1106
|
+
return false;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1101
1109
|
function cleanupStaleFiles() {
|
|
1102
1110
|
if (existsSync5(PID_PATH)) {
|
|
1103
1111
|
try {
|
|
@@ -1105,7 +1113,11 @@ function cleanupStaleFiles() {
|
|
|
1105
1113
|
if (pid > 0) {
|
|
1106
1114
|
try {
|
|
1107
1115
|
process.kill(pid, 0);
|
|
1108
|
-
|
|
1116
|
+
if (!isZombie(pid)) {
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1120
|
+
`);
|
|
1109
1121
|
} catch {
|
|
1110
1122
|
}
|
|
1111
1123
|
}
|
|
@@ -1133,8 +1145,8 @@ function findPackageRoot() {
|
|
|
1133
1145
|
function getAvailableMemoryGB() {
|
|
1134
1146
|
if (process.platform === "darwin") {
|
|
1135
1147
|
try {
|
|
1136
|
-
const { execSync:
|
|
1137
|
-
const vmstat =
|
|
1148
|
+
const { execSync: execSync4 } = __require("child_process");
|
|
1149
|
+
const vmstat = execSync4("vm_stat", { encoding: "utf8" });
|
|
1138
1150
|
const pageSize = 16384;
|
|
1139
1151
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1140
1152
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3124,6 +3136,12 @@ async function disposeDatabase() {
|
|
|
3124
3136
|
clearInterval(_walCheckpointTimer);
|
|
3125
3137
|
_walCheckpointTimer = null;
|
|
3126
3138
|
}
|
|
3139
|
+
if (_client) {
|
|
3140
|
+
try {
|
|
3141
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3142
|
+
} catch {
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3127
3145
|
if (_daemonClient) {
|
|
3128
3146
|
_daemonClient.close();
|
|
3129
3147
|
_daemonClient = null;
|
|
@@ -3160,7 +3178,7 @@ var init_database = __esm({
|
|
|
3160
3178
|
// src/lib/keychain.ts
|
|
3161
3179
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3162
3180
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3163
|
-
import { execSync as
|
|
3181
|
+
import { execSync as execSync3 } from "child_process";
|
|
3164
3182
|
import path6 from "path";
|
|
3165
3183
|
import os5 from "os";
|
|
3166
3184
|
function getKeyDir() {
|
|
@@ -3177,13 +3195,13 @@ function linuxSecretAvailable() {
|
|
|
3177
3195
|
if (process.platform !== "linux") return false;
|
|
3178
3196
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3179
3197
|
try {
|
|
3180
|
-
|
|
3198
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3181
3199
|
} catch {
|
|
3182
3200
|
linuxSecretAvailability = false;
|
|
3183
3201
|
return false;
|
|
3184
3202
|
}
|
|
3185
3203
|
try {
|
|
3186
|
-
|
|
3204
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3187
3205
|
linuxSecretAvailability = true;
|
|
3188
3206
|
} catch {
|
|
3189
3207
|
linuxSecretAvailability = false;
|
|
@@ -3207,7 +3225,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
3207
3225
|
if (!nativeKeychainAllowed()) return null;
|
|
3208
3226
|
if (process.platform !== "darwin") return null;
|
|
3209
3227
|
try {
|
|
3210
|
-
return
|
|
3228
|
+
return execSync3(
|
|
3211
3229
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3212
3230
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3213
3231
|
).trim();
|
|
@@ -3220,13 +3238,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
3220
3238
|
if (process.platform !== "darwin") return false;
|
|
3221
3239
|
try {
|
|
3222
3240
|
try {
|
|
3223
|
-
|
|
3241
|
+
execSync3(
|
|
3224
3242
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3225
3243
|
{ timeout: 5e3 }
|
|
3226
3244
|
);
|
|
3227
3245
|
} catch {
|
|
3228
3246
|
}
|
|
3229
|
-
|
|
3247
|
+
execSync3(
|
|
3230
3248
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3231
3249
|
{ timeout: 5e3 }
|
|
3232
3250
|
);
|
|
@@ -3239,7 +3257,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3239
3257
|
if (!nativeKeychainAllowed()) return false;
|
|
3240
3258
|
if (process.platform !== "darwin") return false;
|
|
3241
3259
|
try {
|
|
3242
|
-
|
|
3260
|
+
execSync3(
|
|
3243
3261
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3244
3262
|
{ timeout: 5e3 }
|
|
3245
3263
|
);
|
|
@@ -3251,7 +3269,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3251
3269
|
function linuxSecretGet(service = SERVICE) {
|
|
3252
3270
|
if (!linuxSecretAvailable()) return null;
|
|
3253
3271
|
try {
|
|
3254
|
-
return
|
|
3272
|
+
return execSync3(
|
|
3255
3273
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3256
3274
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3257
3275
|
).trim();
|
|
@@ -3262,7 +3280,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
3262
3280
|
function linuxSecretSet(value, service = SERVICE) {
|
|
3263
3281
|
if (!linuxSecretAvailable()) return false;
|
|
3264
3282
|
try {
|
|
3265
|
-
|
|
3283
|
+
execSync3(
|
|
3266
3284
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3267
3285
|
{ timeout: 5e3 }
|
|
3268
3286
|
);
|
|
@@ -3275,7 +3293,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
3275
3293
|
if (!nativeKeychainAllowed()) return false;
|
|
3276
3294
|
if (process.platform !== "linux") return false;
|
|
3277
3295
|
try {
|
|
3278
|
-
|
|
3296
|
+
execSync3(
|
|
3279
3297
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3280
3298
|
{ timeout: 5e3 }
|
|
3281
3299
|
);
|
|
@@ -4212,6 +4230,24 @@ var init_platform_procedures = __esm({
|
|
|
4212
4230
|
priority: "p0",
|
|
4213
4231
|
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."
|
|
4214
4232
|
},
|
|
4233
|
+
{
|
|
4234
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
4235
|
+
domain: "support",
|
|
4236
|
+
priority: "p1",
|
|
4237
|
+
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."
|
|
4238
|
+
},
|
|
4239
|
+
{
|
|
4240
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
4241
|
+
domain: "support",
|
|
4242
|
+
priority: "p0",
|
|
4243
|
+
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."
|
|
4244
|
+
},
|
|
4245
|
+
{
|
|
4246
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
4247
|
+
domain: "support",
|
|
4248
|
+
priority: "p1",
|
|
4249
|
+
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."
|
|
4250
|
+
},
|
|
4215
4251
|
// --- Operations ---
|
|
4216
4252
|
{
|
|
4217
4253
|
title: "Managers must supervise deployed workers",
|