@askexenow/exe-os 0.9.77 → 0.9.79

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +2 -2
  2. package/dist/bin/agentic-reflection-backfill.js +2 -2
  3. package/dist/bin/agentic-semantic-label.js +2 -2
  4. package/dist/bin/backfill-conversations.js +2 -2
  5. package/dist/bin/backfill-responses.js +2 -2
  6. package/dist/bin/backfill-vectors.js +2 -2
  7. package/dist/bin/bulk-sync-postgres.js +2 -2
  8. package/dist/bin/cleanup-stale-review-tasks.js +2 -2
  9. package/dist/bin/cli.js +839 -528
  10. package/dist/bin/customer-readiness.js +19 -0
  11. package/dist/bin/exe-agent.js +2 -2
  12. package/dist/bin/exe-assign.js +2 -2
  13. package/dist/bin/exe-boot.js +2 -2
  14. package/dist/bin/exe-call.js +2 -2
  15. package/dist/bin/exe-cloud.js +2 -2
  16. package/dist/bin/exe-dispatch.js +2 -2
  17. package/dist/bin/exe-doctor.js +2 -2
  18. package/dist/bin/exe-export-behaviors.js +2 -2
  19. package/dist/bin/exe-forget.js +2 -2
  20. package/dist/bin/exe-gateway.js +158 -16
  21. package/dist/bin/exe-heartbeat.js +2 -2
  22. package/dist/bin/exe-kill.js +2 -2
  23. package/dist/bin/exe-launch-agent.js +2 -2
  24. package/dist/bin/exe-new-employee.js +2 -2
  25. package/dist/bin/exe-pending-messages.js +2 -2
  26. package/dist/bin/exe-pending-notifications.js +2 -2
  27. package/dist/bin/exe-pending-reviews.js +2 -2
  28. package/dist/bin/exe-rename.js +2 -2
  29. package/dist/bin/exe-review.js +2 -2
  30. package/dist/bin/exe-search.js +2 -2
  31. package/dist/bin/exe-session-cleanup.js +2 -2
  32. package/dist/bin/exe-start-codex.js +2 -2
  33. package/dist/bin/exe-start-opencode.js +2 -2
  34. package/dist/bin/exe-status.js +2 -2
  35. package/dist/bin/exe-support.js +537 -0
  36. package/dist/bin/exe-team.js +2 -2
  37. package/dist/bin/git-sweep.js +2 -2
  38. package/dist/bin/graph-backfill.js +2 -2
  39. package/dist/bin/graph-export.js +2 -2
  40. package/dist/bin/intercom-check.js +2 -2
  41. package/dist/bin/scan-tasks.js +2 -2
  42. package/dist/bin/setup.js +3 -2
  43. package/dist/bin/shard-migrate.js +2 -2
  44. package/dist/bin/update.js +9 -0
  45. package/dist/gateway/index.js +2 -2
  46. package/dist/hooks/bug-report-worker.js +2 -2
  47. package/dist/hooks/codex-stop-task-finalizer.js +2 -2
  48. package/dist/hooks/commit-complete.js +2 -2
  49. package/dist/hooks/error-recall.js +2 -2
  50. package/dist/hooks/ingest.js +2 -2
  51. package/dist/hooks/instructions-loaded.js +2 -2
  52. package/dist/hooks/notification.js +2 -2
  53. package/dist/hooks/post-compact.js +2 -2
  54. package/dist/hooks/post-tool-combined.js +2 -2
  55. package/dist/hooks/pre-compact.js +2 -2
  56. package/dist/hooks/pre-tool-use.js +2 -2
  57. package/dist/hooks/prompt-submit.js +2 -2
  58. package/dist/hooks/session-end.js +2 -2
  59. package/dist/hooks/session-start.js +2 -2
  60. package/dist/hooks/stop.js +2 -2
  61. package/dist/hooks/subagent-stop.js +2 -2
  62. package/dist/hooks/summary-worker.js +2 -2
  63. package/dist/index.js +2 -2
  64. package/dist/lib/employee-templates.js +2 -2
  65. package/dist/lib/exe-daemon.js +28 -16
  66. package/dist/lib/hybrid-search.js +2 -2
  67. package/dist/lib/schedules.js +2 -2
  68. package/dist/lib/store.js +2 -2
  69. package/dist/mcp/server.js +27 -15
  70. package/dist/runtime/index.js +2 -2
  71. package/dist/tui/App.js +2 -2
  72. package/package.json +1 -1
@@ -0,0 +1,537 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/bin/exe-support.ts
4
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
5
+ import path3 from "path";
6
+ import { randomUUID as randomUUID2 } from "crypto";
7
+
8
+ // src/lib/config.ts
9
+ import { readFile, writeFile } from "fs/promises";
10
+ import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
11
+ import path from "path";
12
+ import os from "os";
13
+
14
+ // src/lib/secure-files.ts
15
+ import { chmodSync, existsSync, mkdirSync } from "fs";
16
+ import { chmod, mkdir } from "fs/promises";
17
+ var PRIVATE_DIR_MODE = 448;
18
+ var PRIVATE_FILE_MODE = 384;
19
+ async function ensurePrivateDir(dirPath) {
20
+ await mkdir(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
21
+ try {
22
+ await chmod(dirPath, PRIVATE_DIR_MODE);
23
+ } catch {
24
+ }
25
+ }
26
+ async function enforcePrivateFile(filePath) {
27
+ try {
28
+ await chmod(filePath, PRIVATE_FILE_MODE);
29
+ } catch {
30
+ }
31
+ }
32
+
33
+ // src/lib/config.ts
34
+ function resolveDataDir() {
35
+ if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
36
+ if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
37
+ const newDir = path.join(os.homedir(), ".exe-os");
38
+ const legacyDir = path.join(os.homedir(), ".exe-mem");
39
+ if (!existsSync2(newDir) && existsSync2(legacyDir)) {
40
+ try {
41
+ renameSync(legacyDir, newDir);
42
+ process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
43
+ `);
44
+ } catch {
45
+ return legacyDir;
46
+ }
47
+ }
48
+ return newDir;
49
+ }
50
+ var EXE_AI_DIR = resolveDataDir();
51
+ var DB_PATH = path.join(EXE_AI_DIR, "memories.db");
52
+ var MODELS_DIR = path.join(EXE_AI_DIR, "models");
53
+ var CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
54
+ var LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
55
+ var CURRENT_CONFIG_VERSION = 1;
56
+ var DEFAULT_CONFIG = {
57
+ config_version: CURRENT_CONFIG_VERSION,
58
+ dbPath: DB_PATH,
59
+ modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
60
+ embeddingDim: 1024,
61
+ batchSize: 20,
62
+ flushIntervalMs: 1e4,
63
+ autoIngestion: true,
64
+ autoRetrieval: true,
65
+ searchMode: "hybrid",
66
+ hookSearchMode: "hybrid",
67
+ fileGrepEnabled: true,
68
+ splashEffect: true,
69
+ consolidationEnabled: true,
70
+ consolidationIntervalMs: 6 * 60 * 60 * 1e3,
71
+ consolidationModel: "claude-haiku-4-5-20251001",
72
+ consolidationMaxCallsPerRun: 20,
73
+ selfQueryRouter: true,
74
+ selfQueryModel: "claude-haiku-4-5-20251001",
75
+ rerankerEnabled: true,
76
+ scalingRoadmap: {
77
+ rerankerAutoTrigger: {
78
+ enabled: true,
79
+ broadQueryMinCardinality: 5e4,
80
+ fetchTopK: 200,
81
+ returnTopK: 20
82
+ }
83
+ },
84
+ graphRagEnabled: true,
85
+ wikiEnabled: false,
86
+ wikiUrl: "",
87
+ wikiApiKey: "",
88
+ wikiSyncIntervalMs: 30 * 60 * 1e3,
89
+ wikiWorkspaceMapping: {},
90
+ wikiAutoUpdate: true,
91
+ wikiAutoUpdateThreshold: 0.5,
92
+ wikiAutoUpdateCreateNew: true,
93
+ skillLearning: true,
94
+ skillThreshold: 3,
95
+ skillModel: "claude-haiku-4-5-20251001",
96
+ exeHeartbeat: {
97
+ enabled: true,
98
+ intervalSeconds: 60,
99
+ staleInProgressThresholdHours: 2
100
+ },
101
+ sessionLifecycle: {
102
+ idleKillEnabled: true,
103
+ idleKillTicksRequired: 3,
104
+ idleKillIntercomAckWindowMs: 1e4,
105
+ maxAutoInstances: 10
106
+ },
107
+ autoUpdate: {
108
+ checkOnBoot: true,
109
+ autoInstall: false,
110
+ checkIntervalMs: 24 * 60 * 60 * 1e3
111
+ },
112
+ support: {
113
+ bugReportEndpoint: "https://askexe.com/v1/support/bug-reports"
114
+ },
115
+ orchestration: {
116
+ phase: "phase_1_coo",
117
+ phaseSetBy: "default"
118
+ }
119
+ };
120
+ function migrateLegacyConfig(raw) {
121
+ if ("r2" in raw) {
122
+ process.stderr.write(
123
+ "[exe-os] Warning: config.json contains deprecated 'r2' field from v1.0. R2 sync has been replaced in v1.1. The 'r2' field will be ignored.\n"
124
+ );
125
+ delete raw.r2;
126
+ }
127
+ if ("syncIntervalMs" in raw) {
128
+ delete raw.syncIntervalMs;
129
+ }
130
+ return raw;
131
+ }
132
+ var CONFIG_MIGRATIONS = [
133
+ {
134
+ from: 0,
135
+ to: 1,
136
+ migrate: (cfg) => {
137
+ cfg.config_version = 1;
138
+ return cfg;
139
+ }
140
+ }
141
+ ];
142
+ function migrateConfig(raw) {
143
+ const fromVersion = typeof raw.config_version === "number" ? raw.config_version : 0;
144
+ let currentVersion = fromVersion;
145
+ let migrated = false;
146
+ if (currentVersion > CURRENT_CONFIG_VERSION) {
147
+ return { config: raw, migrated: false, fromVersion };
148
+ }
149
+ for (const migration of CONFIG_MIGRATIONS) {
150
+ if (currentVersion === migration.from && migration.to <= CURRENT_CONFIG_VERSION) {
151
+ raw = migration.migrate(raw);
152
+ currentVersion = migration.to;
153
+ migrated = true;
154
+ }
155
+ }
156
+ return { config: raw, migrated, fromVersion };
157
+ }
158
+ function normalizeScalingRoadmap(raw) {
159
+ const defaultAuto = DEFAULT_CONFIG.scalingRoadmap.rerankerAutoTrigger;
160
+ const userRoadmap = raw.scalingRoadmap ?? {};
161
+ const userAuto = userRoadmap.rerankerAutoTrigger ?? {};
162
+ if (userAuto.enabled === void 0 && raw.rerankerEnabled !== void 0) {
163
+ userAuto.enabled = raw.rerankerEnabled;
164
+ }
165
+ raw.scalingRoadmap = {
166
+ ...userRoadmap,
167
+ rerankerAutoTrigger: { ...defaultAuto, ...userAuto }
168
+ };
169
+ }
170
+ function normalizeSessionLifecycle(raw) {
171
+ const defaultSL = DEFAULT_CONFIG.sessionLifecycle;
172
+ const userSL = raw.sessionLifecycle ?? {};
173
+ raw.sessionLifecycle = { ...defaultSL, ...userSL };
174
+ }
175
+ function normalizeAutoUpdate(raw) {
176
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
177
+ const userAU = raw.autoUpdate ?? {};
178
+ raw.autoUpdate = { ...defaultAU, ...userAU };
179
+ }
180
+ function normalizeOrchestration(raw) {
181
+ const defaultOrg = DEFAULT_CONFIG.orchestration;
182
+ const userOrg = raw.orchestration ?? {};
183
+ raw.orchestration = { ...defaultOrg, ...userOrg };
184
+ }
185
+ async function loadConfig() {
186
+ const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
187
+ await ensurePrivateDir(dir);
188
+ const configPath = path.join(dir, "config.json");
189
+ if (!existsSync2(configPath)) {
190
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
191
+ }
192
+ const raw = await readFile(configPath, "utf-8");
193
+ try {
194
+ let parsed = JSON.parse(raw);
195
+ parsed = migrateLegacyConfig(parsed);
196
+ const { config: migratedCfg, migrated, fromVersion } = migrateConfig(parsed);
197
+ if (migrated) {
198
+ process.stderr.write(`[exe-os] Config migrated from v${fromVersion} to v${migratedCfg.config_version}
199
+ `);
200
+ try {
201
+ await writeFile(configPath, JSON.stringify(migratedCfg, null, 2) + "\n");
202
+ await enforcePrivateFile(configPath);
203
+ } catch {
204
+ }
205
+ }
206
+ normalizeScalingRoadmap(migratedCfg);
207
+ normalizeSessionLifecycle(migratedCfg);
208
+ normalizeAutoUpdate(migratedCfg);
209
+ normalizeOrchestration(migratedCfg);
210
+ const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
211
+ if (config.dbPath.startsWith("~")) {
212
+ config.dbPath = config.dbPath.replace(/^~/, os.homedir());
213
+ }
214
+ const envDbPath = path.join(dir, "memories.db");
215
+ if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
216
+ config.dbPath = envDbPath;
217
+ }
218
+ return config;
219
+ } catch {
220
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
221
+ }
222
+ }
223
+
224
+ // src/lib/license.ts
225
+ import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
226
+ import { randomUUID } from "crypto";
227
+ import { createRequire } from "module";
228
+ import { pathToFileURL } from "url";
229
+ import os2 from "os";
230
+ import path2 from "path";
231
+ import { jwtVerify, importSPKI } from "jose";
232
+ var LICENSE_PATH = path2.join(EXE_AI_DIR, "license.key");
233
+ var CACHE_PATH = path2.join(EXE_AI_DIR, "license-cache.json");
234
+ var DEVICE_ID_PATH = path2.join(EXE_AI_DIR, "device-id");
235
+ function loadLicense() {
236
+ try {
237
+ if (!existsSync3(LICENSE_PATH)) return null;
238
+ return readFileSync2(LICENSE_PATH, "utf8").trim();
239
+ } catch {
240
+ return null;
241
+ }
242
+ }
243
+ function readCachedLicenseToken() {
244
+ try {
245
+ if (!existsSync3(CACHE_PATH)) return null;
246
+ const raw = JSON.parse(readFileSync2(CACHE_PATH, "utf8"));
247
+ return typeof raw.token === "string" ? raw.token : null;
248
+ } catch {
249
+ return null;
250
+ }
251
+ }
252
+
253
+ // src/bin/exe-support.ts
254
+ var DEFAULT_BUG_ENDPOINT = "https://askexe.com/v1/support/bug-reports";
255
+ var DEFAULT_ADMIN_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
256
+ async function main(argv = process.argv.slice(2)) {
257
+ const command = argv[0] && !argv[0].startsWith("--") ? argv[0] : "health";
258
+ const json = argv.includes("--json");
259
+ const project = getArg(argv, "--project") ?? "support-smoke";
260
+ if (command === "help" || argv.includes("--help") || argv.includes("-h")) {
261
+ printHelp();
262
+ return;
263
+ }
264
+ if (command === "health") {
265
+ const result = await runHealth();
266
+ output(result, json, "health");
267
+ process.exitCode = hasFailures(result) ? 1 : 0;
268
+ return;
269
+ }
270
+ if (command === "test") {
271
+ const result = await runTest(project);
272
+ output(result, json, "test");
273
+ process.exitCode = hasFailures(result) ? 1 : 0;
274
+ return;
275
+ }
276
+ console.error("Usage: exe-os support health|test [--project <name>] [--json]");
277
+ process.exitCode = 1;
278
+ }
279
+ async function runHealth() {
280
+ const checks = [];
281
+ const endpoints = await resolveEndpoints();
282
+ checks.push(checkLocalWrite());
283
+ checks.push({
284
+ check: "license_key_present",
285
+ level: loadLicense() ? "pass" : "fail",
286
+ detail: loadLicense() ? "license.key found" : "missing ~/.exe-os/license.key; run exe-os setup or exe-os cloud setup",
287
+ next: loadLicense() ? void 0 : "Run `exe-os setup` or ask AskExe for the customer license key."
288
+ });
289
+ checks.push({
290
+ check: "license_token_cached",
291
+ level: readCachedLicenseToken() ? "pass" : "warn",
292
+ detail: readCachedLicenseToken() ? "cached license token found" : "no cached token yet; support can still use license.key",
293
+ next: readCachedLicenseToken() ? void 0 : "This is OK if license.key exists. It refreshes after cloud/license validation."
294
+ });
295
+ try {
296
+ const res = await fetch(endpoints.healthEndpoint, { method: "GET", signal: AbortSignal.timeout(1e4) });
297
+ const body = await safeJson(res);
298
+ checks.push({
299
+ check: "support_health_endpoint",
300
+ level: res.ok && body?.status !== "down" ? "pass" : "fail",
301
+ detail: `${res.status} ${body?.status ?? res.statusText}`,
302
+ next: res.ok ? void 0 : "Check internet access, DNS, or AskExe support status."
303
+ });
304
+ for (const remote of body?.checks ?? []) {
305
+ const name = remote.name ?? "unknown";
306
+ checks.push({
307
+ check: `server_${name}`,
308
+ level: remote.ok === true ? "pass" : name === "admin_inbox_configured" ? "warn" : "fail",
309
+ detail: remote.detail ?? (remote.ok ? "ok" : "failed"),
310
+ next: remote.ok ? void 0 : "AskExe must fix this server-side."
311
+ });
312
+ }
313
+ } catch (err) {
314
+ checks.push({
315
+ check: "support_health_endpoint",
316
+ level: "fail",
317
+ detail: err instanceof Error ? err.message : String(err),
318
+ next: "Check internet access, then run `exe-os support health` again."
319
+ });
320
+ }
321
+ return checks;
322
+ }
323
+ async function runTest(project) {
324
+ const checks = await runHealth();
325
+ const endpoints = await resolveEndpoints();
326
+ const licenseKey = loadLicense();
327
+ const licenseToken = readCachedLicenseToken();
328
+ const id = randomUUID2();
329
+ const version = readPackageVersion();
330
+ const reportPath = writeLocalTestReport(id, project, version);
331
+ checks.push({ check: "local_report_file", level: "pass", detail: reportPath });
332
+ if (!licenseKey && !licenseToken) {
333
+ checks.push({
334
+ check: "upstream_post",
335
+ level: "fail",
336
+ detail: "not sent because this device has no license key/token",
337
+ next: "Run `exe-os setup` or ask AskExe to provision this customer device."
338
+ });
339
+ return checks;
340
+ }
341
+ const payload = {
342
+ id,
343
+ title: `TEST \u2014 ${project} support intake (${version})`,
344
+ classification: "unclear",
345
+ severity: "p3",
346
+ summary: "Synthetic exe-os support intake smoke test. Safe to close.",
347
+ customer_impact: "No customer impact; diagnostic only.",
348
+ reproduction_steps: ["Run exe-os support test"],
349
+ expected: "The report reaches AskExe support intake and can be triaged.",
350
+ actual: "Smoke test submitted by exe-os support test.",
351
+ package_version: `@askexenow/exe-os@${version}`,
352
+ project_name: project,
353
+ agent_id: "support-test",
354
+ agent_role: "diagnostic",
355
+ report_path: reportPath,
356
+ markdown: readFileSync3(reportPath, "utf8")
357
+ };
358
+ try {
359
+ const headers = { "content-type": "application/json" };
360
+ if (licenseKey) headers["x-exe-license-key"] = licenseKey;
361
+ if (licenseToken) headers["x-exe-license-token"] = licenseToken;
362
+ const res = await fetch(endpoints.bugEndpoint, {
363
+ method: "POST",
364
+ headers,
365
+ body: JSON.stringify(payload),
366
+ signal: AbortSignal.timeout(15e3)
367
+ });
368
+ const data = await safeJson(res);
369
+ checks.push({
370
+ check: "upstream_post",
371
+ level: res.ok ? "pass" : "fail",
372
+ detail: res.ok ? `sent id=${String(data?.id ?? id)}` : summarizeHttpFailure(res.status, data),
373
+ next: res.ok ? void 0 : nextForPostFailure(res.status)
374
+ });
375
+ if (res.ok) {
376
+ checks.push(await maybeCloseAdmin(String(data?.id ?? id), endpoints.adminEndpoint, version));
377
+ }
378
+ } catch (err) {
379
+ checks.push({
380
+ check: "upstream_post",
381
+ level: "fail",
382
+ detail: err instanceof Error ? err.message : String(err),
383
+ next: "Check internet access, then run `exe-os support test` again."
384
+ });
385
+ }
386
+ return checks;
387
+ }
388
+ async function resolveEndpoints() {
389
+ const config = await loadConfig();
390
+ const bugEndpoint = process.env.EXE_SUPPORT_BUG_REPORT_ENDPOINT ?? config.support?.bugReportEndpoint ?? DEFAULT_BUG_ENDPOINT;
391
+ const healthEndpoint = process.env.EXE_SUPPORT_HEALTH_ENDPOINT ?? bugEndpoint.replace(/\/bug-reports\/?$/, "/health");
392
+ const adminEndpoint = process.env.ASKEXE_SUPPORT_ADMIN_ENDPOINT ?? process.env.EXE_SUPPORT_ADMIN_ENDPOINT ?? DEFAULT_ADMIN_ENDPOINT;
393
+ return { bugEndpoint, healthEndpoint, adminEndpoint };
394
+ }
395
+ function checkLocalWrite() {
396
+ const dir = path3.join(EXE_AI_DIR, "bug-reports");
397
+ const testPath = path3.join(dir, ".support-write-test");
398
+ try {
399
+ mkdirSync3(dir, { recursive: true, mode: 448 });
400
+ writeFileSync2(testPath, "ok\n", { mode: 384 });
401
+ unlinkSync(testPath);
402
+ return { check: "local_bug_report_dir_writable", level: "pass", detail: dir };
403
+ } catch (err) {
404
+ return {
405
+ check: "local_bug_report_dir_writable",
406
+ level: "fail",
407
+ detail: err instanceof Error ? err.message : String(err),
408
+ next: "Fix permissions on ~/.exe-os or rerun setup on a writable user account."
409
+ };
410
+ }
411
+ }
412
+ function writeLocalTestReport(id, project, version) {
413
+ const dir = path3.join(EXE_AI_DIR, "bug-reports");
414
+ mkdirSync3(dir, { recursive: true, mode: 448 });
415
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
416
+ const filePath = path3.join(dir, `${date}-support-intake-test-${id.slice(0, 8)}.md`);
417
+ writeFileSync2(filePath, `# TEST \u2014 ${project} support intake
418
+
419
+ Report ID: ${id}
420
+ Package: @askexenow/exe-os@${version}
421
+
422
+ Synthetic smoke test from \`exe-os support test\`. Safe to close.
423
+ `, { mode: 384 });
424
+ return filePath;
425
+ }
426
+ async function maybeCloseAdmin(id, adminEndpoint, version) {
427
+ const token = process.env.ASKEXE_SUPPORT_ADMIN_TOKEN ?? process.env.EXE_SUPPORT_ADMIN_TOKEN;
428
+ if (!token) {
429
+ return { check: "askexe_admin_autoclose", level: "warn", detail: "skipped; admin token is AskExe-only" };
430
+ }
431
+ try {
432
+ const res = await fetch(`${adminEndpoint}/${encodeURIComponent(id)}`, {
433
+ method: "PATCH",
434
+ headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
435
+ body: JSON.stringify({
436
+ status: "closed",
437
+ triage_notes: "Auto-closed synthetic support smoke test.",
438
+ fixed_version: version
439
+ }),
440
+ signal: AbortSignal.timeout(1e4)
441
+ });
442
+ return {
443
+ check: "askexe_admin_autoclose",
444
+ level: res.ok ? "pass" : "warn",
445
+ detail: res.ok ? "closed" : `${res.status} ${await res.text()}`,
446
+ next: res.ok ? void 0 : "Report was sent; AskExe can close the smoke report manually."
447
+ };
448
+ } catch (err) {
449
+ return {
450
+ check: "askexe_admin_autoclose",
451
+ level: "warn",
452
+ detail: err instanceof Error ? err.message : String(err),
453
+ next: "Report was sent; AskExe can close the smoke report manually."
454
+ };
455
+ }
456
+ }
457
+ function readPackageVersion() {
458
+ let dir = path3.dirname(new URL(import.meta.url).pathname);
459
+ for (let i = 0; i < 6; i++) {
460
+ const pkg = path3.join(dir, "package.json");
461
+ try {
462
+ const parsed = JSON.parse(readFileSync3(pkg, "utf8"));
463
+ if (parsed.version) return parsed.version;
464
+ } catch {
465
+ }
466
+ dir = path3.dirname(dir);
467
+ }
468
+ return "unknown";
469
+ }
470
+ async function safeJson(res) {
471
+ try {
472
+ return await res.json();
473
+ } catch {
474
+ return null;
475
+ }
476
+ }
477
+ function getArg(argv, name) {
478
+ const idx = argv.indexOf(name);
479
+ if (idx >= 0) return argv[idx + 1];
480
+ const prefix = `${name}=`;
481
+ const found = argv.find((arg) => arg.startsWith(prefix));
482
+ return found?.slice(prefix.length);
483
+ }
484
+ function hasFailures(rows) {
485
+ return rows.some((row) => row.level === "fail");
486
+ }
487
+ function summarizeHttpFailure(status, data) {
488
+ const error = data?.error;
489
+ return `${status} ${error?.message ?? JSON.stringify(data)}`;
490
+ }
491
+ function nextForPostFailure(status) {
492
+ if (status === 401) return "License credentials were not sent. Run `exe-os support health` and check license_key_present.";
493
+ if (status === 403) return "License is valid locally but not accepted by support intake. AskExe must check server-side license provisioning.";
494
+ if (status >= 500) return "AskExe support intake is unhealthy server-side. Try again shortly and report the local file path.";
495
+ return "Run `exe-os support health`; if it passes, send this output to AskExe.";
496
+ }
497
+ function printHelp() {
498
+ console.log(`
499
+ exe-os support
500
+
501
+ Customer-safe diagnostics for AskExe bug-report intake.
502
+
503
+ Commands:
504
+ exe-os support health Check local setup + AskExe support server health
505
+ exe-os support test --project hygo Send a safe smoke report end-to-end
506
+
507
+ What success means:
508
+ health = this device looks ready
509
+ test = AskExe received a real report from this device
510
+ `);
511
+ }
512
+ function output(rows, json, command) {
513
+ if (json) {
514
+ console.log(JSON.stringify({ ok: !hasFailures(rows), checks: rows }, null, 2));
515
+ return;
516
+ }
517
+ console.log(`
518
+ exe-os support ${command}
519
+ `);
520
+ for (const row of rows) {
521
+ const icon = row.level === "pass" ? "\u2705" : row.level === "warn" ? "\u26A0\uFE0F " : "\u274C";
522
+ console.log(`${icon} ${row.check}: ${row.detail}`);
523
+ if (row.next) console.log(` \u2192 ${row.next}`);
524
+ }
525
+ console.log("");
526
+ if (hasFailures(rows)) {
527
+ console.log("Result: not ready. Fix the failed item(s), then rerun this command.");
528
+ } else if (rows.some((row) => row.level === "warn")) {
529
+ console.log("Result: ready with warnings. Bug reports can be sent; warnings are informational unless AskExe asked for stricter validation.");
530
+ } else {
531
+ console.log(command === "test" ? "Result: ready. AskExe received the test report." : "Result: ready. Run `exe-os support test --project <customer>` for an end-to-end send test.");
532
+ }
533
+ console.log("");
534
+ }
535
+ export {
536
+ main
537
+ };
@@ -4145,7 +4145,7 @@ var init_platform_procedures = __esm({
4145
4145
  title: "Customer patch triage \u2014 upstream bug vs customization",
4146
4146
  domain: "support",
4147
4147
  priority: "p0",
4148
- 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. 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."
4148
+ 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, run `exe-os support test` and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues. 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."
4149
4149
  },
4150
4150
  // --- Operations ---
4151
4151
  {
@@ -4227,7 +4227,7 @@ var init_platform_procedures = __esm({
4227
4227
  title: "MCP tools \u2014 identity, behavior, and decisions",
4228
4228
  domain: "tool-use",
4229
4229
  priority: "p1",
4230
- content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only."
4230
+ content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only. If a customer-side agent cannot send upstream, run `exe-os support test` from the terminal to verify local file write, license auth, support endpoint health, and upstream POST."
4231
4231
  },
4232
4232
  {
4233
4233
  title: "MCP tools \u2014 communication and messaging",
@@ -7850,7 +7850,7 @@ var init_platform_procedures = __esm({
7850
7850
  title: "Customer patch triage \u2014 upstream bug vs customization",
7851
7851
  domain: "support",
7852
7852
  priority: "p0",
7853
- 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. 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."
7853
+ 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, run `exe-os support test` and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues. 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."
7854
7854
  },
7855
7855
  // --- Operations ---
7856
7856
  {
@@ -7932,7 +7932,7 @@ var init_platform_procedures = __esm({
7932
7932
  title: "MCP tools \u2014 identity, behavior, and decisions",
7933
7933
  domain: "tool-use",
7934
7934
  priority: "p1",
7935
- content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only."
7935
+ content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only. If a customer-side agent cannot send upstream, run `exe-os support test` from the terminal to verify local file write, license auth, support endpoint health, and upstream POST."
7936
7936
  },
7937
7937
  {
7938
7938
  title: "MCP tools \u2014 communication and messaging",
@@ -3362,7 +3362,7 @@ var init_platform_procedures = __esm({
3362
3362
  title: "Customer patch triage \u2014 upstream bug vs customization",
3363
3363
  domain: "support",
3364
3364
  priority: "p0",
3365
- 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. 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."
3365
+ 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, run `exe-os support test` and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues. 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."
3366
3366
  },
3367
3367
  // --- Operations ---
3368
3368
  {
@@ -3444,7 +3444,7 @@ var init_platform_procedures = __esm({
3444
3444
  title: "MCP tools \u2014 identity, behavior, and decisions",
3445
3445
  domain: "tool-use",
3446
3446
  priority: "p1",
3447
- content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only."
3447
+ content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only. If a customer-side agent cannot send upstream, run `exe-os support test` from the terminal to verify local file write, license auth, support endpoint health, and upstream POST."
3448
3448
  },
3449
3449
  {
3450
3450
  title: "MCP tools \u2014 communication and messaging",
@@ -4134,7 +4134,7 @@ var init_platform_procedures = __esm({
4134
4134
  title: "Customer patch triage \u2014 upstream bug vs customization",
4135
4135
  domain: "support",
4136
4136
  priority: "p0",
4137
- 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. 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."
4137
+ 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, run `exe-os support test` and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues. 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."
4138
4138
  },
4139
4139
  // --- Operations ---
4140
4140
  {
@@ -4216,7 +4216,7 @@ var init_platform_procedures = __esm({
4216
4216
  title: "MCP tools \u2014 identity, behavior, and decisions",
4217
4217
  domain: "tool-use",
4218
4218
  priority: "p1",
4219
- content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only."
4219
+ content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only. If a customer-side agent cannot send upstream, run `exe-os support test` from the terminal to verify local file write, license auth, support endpoint health, and upstream POST."
4220
4220
  },
4221
4221
  {
4222
4222
  title: "MCP tools \u2014 communication and messaging",
@@ -4243,7 +4243,7 @@ var init_platform_procedures = __esm({
4243
4243
  title: "Customer patch triage \u2014 upstream bug vs customization",
4244
4244
  domain: "support",
4245
4245
  priority: "p0",
4246
- 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. 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."
4246
+ 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, run `exe-os support test` and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues. 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."
4247
4247
  },
4248
4248
  // --- Operations ---
4249
4249
  {
@@ -4325,7 +4325,7 @@ var init_platform_procedures = __esm({
4325
4325
  title: "MCP tools \u2014 identity, behavior, and decisions",
4326
4326
  domain: "tool-use",
4327
4327
  priority: "p1",
4328
- content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only."
4328
+ content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only. If a customer-side agent cannot send upstream, run `exe-os support test` from the terminal to verify local file write, license auth, support endpoint health, and upstream POST."
4329
4329
  },
4330
4330
  {
4331
4331
  title: "MCP tools \u2014 communication and messaging",