@askexenow/exe-os 0.9.39 → 0.9.41

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 (65) hide show
  1. package/dist/bin/backfill-conversations.js +7 -1
  2. package/dist/bin/backfill-responses.js +7 -1
  3. package/dist/bin/backfill-vectors.js +7 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +7 -1
  5. package/dist/bin/cli.js +43 -4
  6. package/dist/bin/exe-agent.js +7 -1
  7. package/dist/bin/exe-assign.js +7 -1
  8. package/dist/bin/exe-boot.js +7 -1
  9. package/dist/bin/exe-call.js +7 -1
  10. package/dist/bin/exe-dispatch.js +7 -1
  11. package/dist/bin/exe-doctor.js +7 -1
  12. package/dist/bin/exe-export-behaviors.js +7 -1
  13. package/dist/bin/exe-forget.js +7 -1
  14. package/dist/bin/exe-gateway.js +7 -1
  15. package/dist/bin/exe-heartbeat.js +7 -1
  16. package/dist/bin/exe-kill.js +7 -1
  17. package/dist/bin/exe-launch-agent.js +7 -1
  18. package/dist/bin/exe-new-employee.js +7 -1
  19. package/dist/bin/exe-pending-messages.js +7 -1
  20. package/dist/bin/exe-pending-notifications.js +7 -1
  21. package/dist/bin/exe-pending-reviews.js +7 -1
  22. package/dist/bin/exe-rename.js +7 -1
  23. package/dist/bin/exe-review.js +7 -1
  24. package/dist/bin/exe-search.js +7 -1
  25. package/dist/bin/exe-session-cleanup.js +7 -1
  26. package/dist/bin/exe-start-codex.js +7 -1
  27. package/dist/bin/exe-start-opencode.js +7 -1
  28. package/dist/bin/exe-status.js +7 -1
  29. package/dist/bin/exe-team.js +7 -1
  30. package/dist/bin/git-sweep.js +7 -1
  31. package/dist/bin/graph-backfill.js +7 -1
  32. package/dist/bin/graph-export.js +7 -1
  33. package/dist/bin/intercom-check.js +7 -1
  34. package/dist/bin/scan-tasks.js +7 -1
  35. package/dist/bin/setup.js +7 -1
  36. package/dist/bin/shard-migrate.js +7 -1
  37. package/dist/bin/update.js +36 -3
  38. package/dist/gateway/index.js +7 -1
  39. package/dist/hooks/bug-report-worker.js +7 -1
  40. package/dist/hooks/codex-stop-task-finalizer.js +7 -1
  41. package/dist/hooks/commit-complete.js +7 -1
  42. package/dist/hooks/error-recall.js +7 -1
  43. package/dist/hooks/ingest.js +7 -1
  44. package/dist/hooks/instructions-loaded.js +7 -1
  45. package/dist/hooks/notification.js +7 -1
  46. package/dist/hooks/post-compact.js +7 -1
  47. package/dist/hooks/post-tool-combined.js +7 -1
  48. package/dist/hooks/pre-compact.js +7 -1
  49. package/dist/hooks/pre-tool-use.js +7 -1
  50. package/dist/hooks/prompt-submit.js +7 -1
  51. package/dist/hooks/session-end.js +7 -1
  52. package/dist/hooks/session-start.js +7 -1
  53. package/dist/hooks/stop.js +7 -1
  54. package/dist/hooks/subagent-stop.js +7 -1
  55. package/dist/hooks/summary-worker.js +7 -1
  56. package/dist/index.js +7 -1
  57. package/dist/lib/employee-templates.js +7 -1
  58. package/dist/lib/exe-daemon.js +276 -47
  59. package/dist/lib/hybrid-search.js +7 -1
  60. package/dist/lib/schedules.js +7 -1
  61. package/dist/lib/store.js +7 -1
  62. package/dist/mcp/server.js +251 -29
  63. package/dist/runtime/index.js +7 -1
  64. package/dist/tui/App.js +7 -1
  65. package/package.json +2 -2
@@ -850,8 +850,8 @@ async function embedDirect(text3) {
850
850
  const llamaCpp = await import("node-llama-cpp");
851
851
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
852
852
  const { existsSync: existsSync35 } = await import("fs");
853
- const path46 = await import("path");
854
- const modelPath = path46.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
853
+ const path47 = await import("path");
854
+ const modelPath = path47.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
855
855
  if (!existsSync35(modelPath)) {
856
856
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
857
857
  }
@@ -3340,7 +3340,7 @@ async function tryKeytar() {
3340
3340
  }
3341
3341
  function deriveMachineKey() {
3342
3342
  try {
3343
- const crypto18 = __require("crypto");
3343
+ const crypto19 = __require("crypto");
3344
3344
  const material = [
3345
3345
  os5.hostname(),
3346
3346
  os5.userInfo().username,
@@ -3349,7 +3349,7 @@ function deriveMachineKey() {
3349
3349
  // Machine ID on Linux (stable across reboots)
3350
3350
  process.platform === "linux" ? readMachineId() : ""
3351
3351
  ].join("|");
3352
- return crypto18.createHash("sha256").update(material).digest();
3352
+ return crypto19.createHash("sha256").update(material).digest();
3353
3353
  } catch {
3354
3354
  return null;
3355
3355
  }
@@ -3363,9 +3363,9 @@ function readMachineId() {
3363
3363
  }
3364
3364
  }
3365
3365
  function encryptWithMachineKey(plaintext, machineKey) {
3366
- const crypto18 = __require("crypto");
3367
- const iv = crypto18.randomBytes(12);
3368
- const cipher = crypto18.createCipheriv("aes-256-gcm", machineKey, iv);
3366
+ const crypto19 = __require("crypto");
3367
+ const iv = crypto19.randomBytes(12);
3368
+ const cipher = crypto19.createCipheriv("aes-256-gcm", machineKey, iv);
3369
3369
  let encrypted = cipher.update(plaintext, "utf-8", "base64");
3370
3370
  encrypted += cipher.final("base64");
3371
3371
  const authTag = cipher.getAuthTag().toString("base64");
@@ -3374,13 +3374,13 @@ function encryptWithMachineKey(plaintext, machineKey) {
3374
3374
  function decryptWithMachineKey(encrypted, machineKey) {
3375
3375
  if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3376
3376
  try {
3377
- const crypto18 = __require("crypto");
3377
+ const crypto19 = __require("crypto");
3378
3378
  const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3379
3379
  if (parts.length !== 3) return null;
3380
3380
  const [ivB64, tagB64, cipherB64] = parts;
3381
3381
  const iv = Buffer.from(ivB64, "base64");
3382
3382
  const authTag = Buffer.from(tagB64, "base64");
3383
- const decipher = crypto18.createDecipheriv("aes-256-gcm", machineKey, iv);
3383
+ const decipher = crypto19.createDecipheriv("aes-256-gcm", machineKey, iv);
3384
3384
  decipher.setAuthTag(authTag);
3385
3385
  let decrypted = decipher.update(cipherB64, "base64", "utf-8");
3386
3386
  decrypted += decipher.final("utf-8");
@@ -4204,6 +4204,12 @@ var init_platform_procedures = __esm({
4204
4204
  priority: "p0",
4205
4205
  content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
4206
4206
  },
4207
+ {
4208
+ title: "Customer patch triage \u2014 upstream bug vs customization",
4209
+ domain: "support",
4210
+ priority: "p0",
4211
+ content: "Before editing platform code for a customer issue, classify it. Upstream bug = reproducible exe-os/platform defect; call create_bug_report with repro/version/workaround and avoid permanent local patches unless founder approves. Customer customization = identity, behavior, procedure, config, branding, workflow; store it in customer-owned layers, not platform code. Emergency hotfix = temporary only; document files/diff and re-check after npm update."
4212
+ },
4207
4213
  // --- Operations ---
4208
4214
  {
4209
4215
  title: "Managers must supervise deployed workers",
@@ -4272,7 +4278,7 @@ var init_platform_procedures = __esm({
4272
4278
  title: "MCP tools \u2014 identity, behavior, and decisions",
4273
4279
  domain: "tool-use",
4274
4280
  priority: "p1",
4275
- 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."
4281
+ 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: classify/file upstream bugs, customer customizations, and emergency hotfixes."
4276
4282
  },
4277
4283
  {
4278
4284
  title: "MCP tools \u2014 communication and messaging",
@@ -6262,10 +6268,10 @@ async function hybridSearch(queryText, agentId, options) {
6262
6268
  };
6263
6269
  try {
6264
6270
  const fs = await import("fs");
6265
- const path46 = await import("path");
6271
+ const path47 = await import("path");
6266
6272
  const os20 = await import("os");
6267
- const logPath = path46.join(os20.homedir(), ".exe-os", "search-quality.jsonl");
6268
- fs.mkdirSync(path46.dirname(logPath), { recursive: true });
6273
+ const logPath = path47.join(os20.homedir(), ".exe-os", "search-quality.jsonl");
6274
+ fs.mkdirSync(path47.dirname(logPath), { recursive: true });
6269
6275
  fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
6270
6276
  } catch {
6271
6277
  }
@@ -7548,8 +7554,8 @@ __export(wiki_client_exports, {
7548
7554
  listDocuments: () => listDocuments,
7549
7555
  listWorkspaces: () => listWorkspaces
7550
7556
  });
7551
- async function wikiFetch(config2, path46, method = "GET", body) {
7552
- const url = `${config2.baseUrl}/api/v1${path46}`;
7557
+ async function wikiFetch(config2, path47, method = "GET", body) {
7558
+ const url = `${config2.baseUrl}/api/v1${path47}`;
7553
7559
  const headers = {
7554
7560
  Authorization: `Bearer ${config2.apiKey}`,
7555
7561
  "Content-Type": "application/json"
@@ -7582,7 +7588,7 @@ async function wikiFetch(config2, path46, method = "GET", body) {
7582
7588
  }
7583
7589
  }
7584
7590
  if (!response.ok) {
7585
- throw new Error(`Wiki API ${method} ${path46}: ${response.status} ${response.statusText}`);
7591
+ throw new Error(`Wiki API ${method} ${path47}: ${response.status} ${response.statusText}`);
7586
7592
  }
7587
7593
  return response.json();
7588
7594
  } finally {
@@ -12728,7 +12734,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12728
12734
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12729
12735
  import { spawn as spawn4 } from "child_process";
12730
12736
  import { existsSync as existsSync34, openSync as openSync3, mkdirSync as mkdirSync18, closeSync as closeSync3, readFileSync as readFileSync28 } from "fs";
12731
- import path45 from "path";
12737
+ import path46 from "path";
12732
12738
  import os19 from "os";
12733
12739
  import { fileURLToPath as fileURLToPath5 } from "url";
12734
12740
 
@@ -17839,9 +17845,9 @@ var HostingerApiClient = class {
17839
17845
  }
17840
17846
  this.lastRequestTime = Date.now();
17841
17847
  }
17842
- async request(method, path46, body) {
17848
+ async request(method, path47, body) {
17843
17849
  await this.rateLimit();
17844
- const url = `${this.baseUrl}${path46}`;
17850
+ const url = `${this.baseUrl}${path47}`;
17845
17851
  const headers = {
17846
17852
  Authorization: `Bearer ${this.apiKey}`,
17847
17853
  "Content-Type": "application/json",
@@ -17914,8 +17920,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
17914
17920
  }
17915
17921
  return envelope.result;
17916
17922
  }
17917
- function buildUrl(zoneId, path46 = "/dns_records", query) {
17918
- const normalizedPath = path46.startsWith("/") ? path46 : `/${path46}`;
17923
+ function buildUrl(zoneId, path47 = "/dns_records", query) {
17924
+ const normalizedPath = path47.startsWith("/") ? path47 : `/${path47}`;
17919
17925
  const url = new URL(
17920
17926
  `${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
17921
17927
  );
@@ -20121,12 +20127,12 @@ function registerExportGraph(server2) {
20121
20127
  }
20122
20128
  const html = await exportGraphHTML(client);
20123
20129
  const fs = await import("fs");
20124
- const path46 = await import("path");
20130
+ const path47 = await import("path");
20125
20131
  const os20 = await import("os");
20126
- const outDir = path46.join(os20.homedir(), ".exe-os", "exports");
20132
+ const outDir = path47.join(os20.homedir(), ".exe-os", "exports");
20127
20133
  fs.mkdirSync(outDir, { recursive: true });
20128
20134
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
20129
- const filePath = path46.join(outDir, `graph-${timestamp}.html`);
20135
+ const filePath = path47.join(outDir, `graph-${timestamp}.html`);
20130
20136
  fs.writeFileSync(filePath, html, "utf-8");
20131
20137
  return {
20132
20138
  content: [
@@ -24166,6 +24172,219 @@ Key saved to ~/.exe-os/license.key. Device ID: ${deviceId}`);
24166
24172
  );
24167
24173
  }
24168
24174
 
24175
+ // src/mcp/tools/create-bug-report.ts
24176
+ init_embedder();
24177
+ init_active_agent();
24178
+ init_config();
24179
+ init_store();
24180
+ import { z as z82 } from "zod";
24181
+ import crypto18 from "crypto";
24182
+ import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
24183
+ import path45 from "path";
24184
+ var CLASSIFICATION = z82.enum([
24185
+ "upstream_bug",
24186
+ "customer_customization",
24187
+ "emergency_hotfix",
24188
+ "unclear"
24189
+ ]);
24190
+ var SEVERITY = z82.enum(["p0", "p1", "p2", "p3"]);
24191
+ function slugify2(input) {
24192
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "bug-report";
24193
+ }
24194
+ function formatList(items) {
24195
+ if (!items || items.length === 0) return "- Not provided";
24196
+ return items.map((item) => `- ${item}`).join("\n");
24197
+ }
24198
+ function section(title, body) {
24199
+ return `## ${title}
24200
+
24201
+ ${body?.trim() || "Not provided"}`;
24202
+ }
24203
+ function buildMarkdown(input) {
24204
+ return [
24205
+ `# Bug Report \u2014 ${input.title}`,
24206
+ "",
24207
+ `id: ${input.id}`,
24208
+ `classification: ${input.classification}`,
24209
+ `severity: ${input.severity}`,
24210
+ `filed_by: ${input.agentId} (${input.agentRole})`,
24211
+ `package_version: ${input.packageVersion}`,
24212
+ `project: ${input.projectName ?? "unknown"}`,
24213
+ `created_at: ${(/* @__PURE__ */ new Date()).toISOString()}`,
24214
+ "",
24215
+ section("Summary", input.summary),
24216
+ section("Customer impact", input.customerImpact),
24217
+ "## Reproduction steps",
24218
+ "",
24219
+ formatList(input.reproductionSteps),
24220
+ "",
24221
+ section("Expected behavior", input.expected),
24222
+ section("Actual behavior", input.actual),
24223
+ "## Files changed / suspected",
24224
+ "",
24225
+ formatList(input.filesChanged),
24226
+ "",
24227
+ section("Local workaround / hotfix", input.workaround),
24228
+ section("Local patch diff", input.localPatchDiff)
24229
+ ].join("\n");
24230
+ }
24231
+ async function maybeSendUpstream(payload) {
24232
+ const config2 = await loadConfig();
24233
+ const endpoint = config2.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT;
24234
+ const token = config2.support?.bugReportToken || process.env.EXE_BUG_REPORT_TOKEN;
24235
+ if (!endpoint) {
24236
+ return "not_configured";
24237
+ }
24238
+ try {
24239
+ const parsed = new URL(endpoint);
24240
+ if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
24241
+ return "failed: insecure endpoint rejected";
24242
+ }
24243
+ const response = await fetch(parsed, {
24244
+ method: "POST",
24245
+ headers: {
24246
+ "content-type": "application/json",
24247
+ ...token ? { authorization: `Bearer ${token}` } : {}
24248
+ },
24249
+ body: JSON.stringify(payload),
24250
+ signal: AbortSignal.timeout(1e4)
24251
+ });
24252
+ if (!response.ok) return `failed: HTTP ${response.status}`;
24253
+ return "sent";
24254
+ } catch (err) {
24255
+ return `failed: ${err instanceof Error ? err.message : String(err)}`;
24256
+ }
24257
+ }
24258
+ function registerCreateBugReport(server2) {
24259
+ server2.registerTool(
24260
+ "create_bug_report",
24261
+ {
24262
+ title: "Create Bug Report",
24263
+ description: "Classify and file an exe-os issue as upstream_bug, customer_customization, emergency_hotfix, or unclear. Writes a local report, stores memory, and optionally sends to AskExe support when a support endpoint is configured.",
24264
+ inputSchema: {
24265
+ title: z82.string().min(3).describe("Short descriptive title"),
24266
+ classification: CLASSIFICATION.describe(
24267
+ "upstream_bug = platform defect; customer_customization = local preference; emergency_hotfix = temporary local patch; unclear = needs maintainer triage"
24268
+ ),
24269
+ severity: SEVERITY.default("p2").describe("p0 critical \u2192 p3 low"),
24270
+ summary: z82.string().min(10).describe("What happened and why it matters"),
24271
+ customer_impact: z82.string().optional().describe("How this affects the customer/founder"),
24272
+ reproduction_steps: z82.array(z82.string()).optional().describe("Steps to reproduce"),
24273
+ expected: z82.string().optional().describe("Expected behavior"),
24274
+ actual: z82.string().optional().describe("Actual behavior"),
24275
+ files_changed: z82.array(z82.string()).optional().describe("Files changed or suspected"),
24276
+ workaround: z82.string().optional().describe("Temporary local workaround/hotfix, if any"),
24277
+ local_patch_diff: z82.string().optional().describe("Small local diff or patch summary"),
24278
+ package_version: z82.string().optional().describe("Installed @askexenow/exe-os version"),
24279
+ project_name: z82.string().optional().describe("Project/customer context"),
24280
+ send_upstream: z82.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
24281
+ }
24282
+ },
24283
+ async ({
24284
+ title,
24285
+ classification,
24286
+ severity,
24287
+ summary,
24288
+ customer_impact,
24289
+ reproduction_steps,
24290
+ expected,
24291
+ actual,
24292
+ files_changed,
24293
+ workaround,
24294
+ local_patch_diff,
24295
+ package_version,
24296
+ project_name,
24297
+ send_upstream
24298
+ }) => {
24299
+ const { agentId, agentRole } = getActiveAgent();
24300
+ const id = crypto18.randomUUID();
24301
+ const version = package_version ?? "unknown";
24302
+ const markdown = buildMarkdown({
24303
+ id,
24304
+ title,
24305
+ classification,
24306
+ severity,
24307
+ agentId,
24308
+ agentRole,
24309
+ packageVersion: version,
24310
+ summary,
24311
+ customerImpact: customer_impact,
24312
+ expected,
24313
+ actual,
24314
+ workaround,
24315
+ localPatchDiff: local_patch_diff,
24316
+ reproductionSteps: reproduction_steps,
24317
+ filesChanged: files_changed,
24318
+ projectName: project_name
24319
+ });
24320
+ const outDir = path45.join(EXE_AI_DIR, "bug-reports");
24321
+ await mkdir6(outDir, { recursive: true });
24322
+ const reportPath = path45.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
24323
+ await writeFile7(reportPath, markdown, "utf-8");
24324
+ let vector = null;
24325
+ try {
24326
+ vector = await embed(markdown);
24327
+ } catch {
24328
+ vector = null;
24329
+ }
24330
+ await writeMemory({
24331
+ id,
24332
+ agent_id: agentId,
24333
+ agent_role: agentRole,
24334
+ session_id: process.env.SESSION_ID ?? "manual",
24335
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
24336
+ tool_name: "create_bug_report",
24337
+ project_name: project_name ?? "support",
24338
+ has_error: classification === "upstream_bug" || classification === "emergency_hotfix",
24339
+ raw_text: markdown,
24340
+ vector,
24341
+ source_path: reportPath,
24342
+ source_type: "bug_report",
24343
+ memory_type: "bug_report",
24344
+ tier: 1,
24345
+ importance: severity === "p0" ? 10 : severity === "p1" ? 9 : 7,
24346
+ intent: "report",
24347
+ domain: "support",
24348
+ file_paths: files_changed ? JSON.stringify(files_changed) : null
24349
+ });
24350
+ await flushBatch();
24351
+ const upstreamStatus = send_upstream ? await maybeSendUpstream({
24352
+ id,
24353
+ title,
24354
+ classification,
24355
+ severity,
24356
+ summary,
24357
+ customer_impact,
24358
+ reproduction_steps,
24359
+ expected,
24360
+ actual,
24361
+ files_changed,
24362
+ workaround,
24363
+ local_patch_diff,
24364
+ package_version: version,
24365
+ project_name,
24366
+ agent_id: agentId,
24367
+ agent_role: agentRole,
24368
+ report_path: reportPath,
24369
+ markdown
24370
+ }) : "skipped";
24371
+ return {
24372
+ content: [
24373
+ {
24374
+ type: "text",
24375
+ text: `Bug report created.
24376
+ ID: ${id}
24377
+ Classification: ${classification}
24378
+ Local report: ${reportPath}
24379
+ Memory stored: ${id}
24380
+ Upstream status: ${upstreamStatus}`
24381
+ }
24382
+ ]
24383
+ };
24384
+ }
24385
+ );
24386
+ }
24387
+
24169
24388
  // src/mcp/tool-gates.ts
24170
24389
  var TOOL_GATES = {
24171
24390
  core: [],
@@ -24214,6 +24433,7 @@ var TOOL_CATEGORIES = {
24214
24433
  registerBehavior: "core",
24215
24434
  registerStoreDecision: "core",
24216
24435
  registerGetDecision: "core",
24436
+ registerCreateBugReport: "core",
24217
24437
  registerIdentity: "core",
24218
24438
  registerGetIdentity: "core",
24219
24439
  registerUpdateIdentity: "core",
@@ -24246,6 +24466,7 @@ var TOOL_CATEGORIES = {
24246
24466
  registerExportGraph: "graph-write",
24247
24467
  // wiki
24248
24468
  registerWiki: "wiki",
24469
+ registerCreateWikiPage: "wiki",
24249
24470
  registerListWikiPages: "wiki",
24250
24471
  registerGetWikiPage: "wiki",
24251
24472
  // crm
@@ -24422,6 +24643,7 @@ function registerAllTools(server2) {
24422
24643
  }
24423
24644
  gate("registerStoreDecision", registerStoreDecision);
24424
24645
  gate("registerGetDecision", registerGetDecision);
24646
+ gate("registerCreateBugReport", registerCreateBugReport);
24425
24647
  gate("registerGetAgentSpend", registerGetAgentSpend);
24426
24648
  gate("registerGetGraphStats", registerGetGraphStats);
24427
24649
  gate("registerGetEntityNeighbors", registerGetEntityNeighbors);
@@ -24575,7 +24797,7 @@ try {
24575
24797
  }
24576
24798
  }, 3e4);
24577
24799
  _ppidWatchdog.unref();
24578
- const MCP_VERSION_PATH = path45.join(os19.homedir(), ".exe-os", "mcp-version");
24800
+ const MCP_VERSION_PATH = path46.join(os19.homedir(), ".exe-os", "mcp-version");
24579
24801
  let _currentMcpVersion = null;
24580
24802
  try {
24581
24803
  _currentMcpVersion = existsSync34(MCP_VERSION_PATH) ? readFileSync28(MCP_VERSION_PATH, "utf8").trim() : null;
@@ -24617,14 +24839,14 @@ try {
24617
24839
  `
24618
24840
  );
24619
24841
  const thisFile = fileURLToPath5(import.meta.url);
24620
- const backfillPath = path45.resolve(
24621
- path45.dirname(thisFile),
24842
+ const backfillPath = path46.resolve(
24843
+ path46.dirname(thisFile),
24622
24844
  "../bin/backfill-vectors.js"
24623
24845
  );
24624
24846
  if (existsSync34(backfillPath)) {
24625
24847
  const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
24626
- const logPath = path45.join(exeDir, "workers.log");
24627
- mkdirSync18(path45.dirname(logPath), { recursive: true });
24848
+ const logPath = path46.join(exeDir, "workers.log");
24849
+ mkdirSync18(path46.dirname(logPath), { recursive: true });
24628
24850
  let logFd = "ignore";
24629
24851
  try {
24630
24852
  logFd = openSync3(logPath, "a");
@@ -7390,6 +7390,12 @@ var init_platform_procedures = __esm({
7390
7390
  priority: "p0",
7391
7391
  content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
7392
7392
  },
7393
+ {
7394
+ title: "Customer patch triage \u2014 upstream bug vs customization",
7395
+ domain: "support",
7396
+ priority: "p0",
7397
+ content: "Before editing platform code for a customer issue, classify it. Upstream bug = reproducible exe-os/platform defect; call create_bug_report with repro/version/workaround and avoid permanent local patches unless founder approves. Customer customization = identity, behavior, procedure, config, branding, workflow; store it in customer-owned layers, not platform code. Emergency hotfix = temporary only; document files/diff and re-check after npm update."
7398
+ },
7393
7399
  // --- Operations ---
7394
7400
  {
7395
7401
  title: "Managers must supervise deployed workers",
@@ -7458,7 +7464,7 @@ var init_platform_procedures = __esm({
7458
7464
  title: "MCP tools \u2014 identity, behavior, and decisions",
7459
7465
  domain: "tool-use",
7460
7466
  priority: "p1",
7461
- 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."
7467
+ 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: classify/file upstream bugs, customer customizations, and emergency hotfixes."
7462
7468
  },
7463
7469
  {
7464
7470
  title: "MCP tools \u2014 communication and messaging",
package/dist/tui/App.js CHANGED
@@ -8556,6 +8556,12 @@ var init_platform_procedures = __esm({
8556
8556
  priority: "p0",
8557
8557
  content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
8558
8558
  },
8559
+ {
8560
+ title: "Customer patch triage \u2014 upstream bug vs customization",
8561
+ domain: "support",
8562
+ priority: "p0",
8563
+ content: "Before editing platform code for a customer issue, classify it. Upstream bug = reproducible exe-os/platform defect; call create_bug_report with repro/version/workaround and avoid permanent local patches unless founder approves. Customer customization = identity, behavior, procedure, config, branding, workflow; store it in customer-owned layers, not platform code. Emergency hotfix = temporary only; document files/diff and re-check after npm update."
8564
+ },
8559
8565
  // --- Operations ---
8560
8566
  {
8561
8567
  title: "Managers must supervise deployed workers",
@@ -8624,7 +8630,7 @@ var init_platform_procedures = __esm({
8624
8630
  title: "MCP tools \u2014 identity, behavior, and decisions",
8625
8631
  domain: "tool-use",
8626
8632
  priority: "p1",
8627
- 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."
8633
+ 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: classify/file upstream bugs, customer customizations, and emergency hotfixes."
8628
8634
  },
8629
8635
  {
8630
8636
  title: "MCP tools \u2014 communication and messaging",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.39",
3
+ "version": "0.9.41",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -71,7 +71,7 @@
71
71
  "typecheck": "tsc --noEmit",
72
72
  "build": "tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/assets/ghostty.conf dist/assets/ && cp src/assets/statusline-command.sh dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh",
73
73
  "deploy": "node dist/bin/pre-build-guard.js 2>/dev/null; (kill $(cat ~/.exe-os/exed.pid 2>/dev/null) 2>/dev/null; pgrep -f exe-daemon.js | xargs kill 2>/dev/null; true) && tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/assets/ghostty.conf dist/assets/ && cp src/assets/statusline-command.sh dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh && npm install -g . && node dist/bin/install.js --global && echo '[exe-os] Deploy complete. Run /mcp in active sessions to reconnect.'",
74
- "postinstall": "node dist/bin/install.js --global 2>/dev/null || true",
74
+ "postinstall": "node dist/bin/install.js --commands-only 2>/dev/null || true",
75
75
  "prepublishOnly": "npm run typecheck && npm run build && node dist/bin/customer-readiness.js",
76
76
  "test:publish": "npx vitest run --maxWorkers=4 --exclude 'tests/tui/**' --exclude 'tests/lib/tmux-routing.test.ts' --exclude 'tests/lib/intercom-routing.test.ts' --exclude 'tests/gateway/**' --exclude 'tests/installer/setup-wizard.test.ts' --exclude 'tests/mcp/ingest-document.test.ts' --exclude 'tests/lib/hybrid-search.test.ts' --exclude 'tests/lib/worker-gate.test.ts'",
77
77
  "benchmark:longmemeval": "npx tsx tests/benchmarks/longmemeval.ts"