@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
@@ -4088,7 +4088,7 @@ async function tryKeytar() {
4088
4088
  }
4089
4089
  function deriveMachineKey() {
4090
4090
  try {
4091
- const crypto21 = __require("crypto");
4091
+ const crypto22 = __require("crypto");
4092
4092
  const material = [
4093
4093
  os6.hostname(),
4094
4094
  os6.userInfo().username,
@@ -4097,7 +4097,7 @@ function deriveMachineKey() {
4097
4097
  // Machine ID on Linux (stable across reboots)
4098
4098
  process.platform === "linux" ? readMachineId() : ""
4099
4099
  ].join("|");
4100
- return crypto21.createHash("sha256").update(material).digest();
4100
+ return crypto22.createHash("sha256").update(material).digest();
4101
4101
  } catch {
4102
4102
  return null;
4103
4103
  }
@@ -4111,9 +4111,9 @@ function readMachineId() {
4111
4111
  }
4112
4112
  }
4113
4113
  function encryptWithMachineKey(plaintext, machineKey) {
4114
- const crypto21 = __require("crypto");
4115
- const iv = crypto21.randomBytes(12);
4116
- const cipher = crypto21.createCipheriv("aes-256-gcm", machineKey, iv);
4114
+ const crypto22 = __require("crypto");
4115
+ const iv = crypto22.randomBytes(12);
4116
+ const cipher = crypto22.createCipheriv("aes-256-gcm", machineKey, iv);
4117
4117
  let encrypted = cipher.update(plaintext, "utf-8", "base64");
4118
4118
  encrypted += cipher.final("base64");
4119
4119
  const authTag = cipher.getAuthTag().toString("base64");
@@ -4122,13 +4122,13 @@ function encryptWithMachineKey(plaintext, machineKey) {
4122
4122
  function decryptWithMachineKey(encrypted, machineKey) {
4123
4123
  if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
4124
4124
  try {
4125
- const crypto21 = __require("crypto");
4125
+ const crypto22 = __require("crypto");
4126
4126
  const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
4127
4127
  if (parts.length !== 3) return null;
4128
4128
  const [ivB64, tagB64, cipherB64] = parts;
4129
4129
  const iv = Buffer.from(ivB64, "base64");
4130
4130
  const authTag = Buffer.from(tagB64, "base64");
4131
- const decipher = crypto21.createDecipheriv("aes-256-gcm", machineKey, iv);
4131
+ const decipher = crypto22.createDecipheriv("aes-256-gcm", machineKey, iv);
4132
4132
  decipher.setAuthTag(authTag);
4133
4133
  let decrypted = decipher.update(cipherB64, "base64", "utf-8");
4134
4134
  decrypted += decipher.final("utf-8");
@@ -4408,6 +4408,12 @@ var init_platform_procedures = __esm({
4408
4408
  priority: "p0",
4409
4409
  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."
4410
4410
  },
4411
+ {
4412
+ title: "Customer patch triage \u2014 upstream bug vs customization",
4413
+ domain: "support",
4414
+ priority: "p0",
4415
+ 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."
4416
+ },
4411
4417
  // --- Operations ---
4412
4418
  {
4413
4419
  title: "Managers must supervise deployed workers",
@@ -4476,7 +4482,7 @@ var init_platform_procedures = __esm({
4476
4482
  title: "MCP tools \u2014 identity, behavior, and decisions",
4477
4483
  domain: "tool-use",
4478
4484
  priority: "p1",
4479
- 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."
4485
+ 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."
4480
4486
  },
4481
4487
  {
4482
4488
  title: "MCP tools \u2014 communication and messaging",
@@ -5602,8 +5608,8 @@ async function embedDirect(text3) {
5602
5608
  const llamaCpp = await import("node-llama-cpp");
5603
5609
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
5604
5610
  const { existsSync: existsSync40 } = await import("fs");
5605
- const path53 = await import("path");
5606
- const modelPath = path53.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
5611
+ const path54 = await import("path");
5612
+ const modelPath = path54.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
5607
5613
  if (!existsSync40(modelPath)) {
5608
5614
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
5609
5615
  }
@@ -6681,10 +6687,10 @@ async function hybridSearch(queryText, agentId, options) {
6681
6687
  };
6682
6688
  try {
6683
6689
  const fs = await import("fs");
6684
- const path53 = await import("path");
6690
+ const path54 = await import("path");
6685
6691
  const os23 = await import("os");
6686
- const logPath = path53.join(os23.homedir(), ".exe-os", "search-quality.jsonl");
6687
- fs.mkdirSync(path53.dirname(logPath), { recursive: true });
6692
+ const logPath = path54.join(os23.homedir(), ".exe-os", "search-quality.jsonl");
6693
+ fs.mkdirSync(path54.dirname(logPath), { recursive: true });
6688
6694
  fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
6689
6695
  } catch {
6690
6696
  }
@@ -8302,8 +8308,8 @@ __export(wiki_client_exports, {
8302
8308
  listDocuments: () => listDocuments,
8303
8309
  listWorkspaces: () => listWorkspaces
8304
8310
  });
8305
- async function wikiFetch(config2, path53, method = "GET", body) {
8306
- const url = `${config2.baseUrl}/api/v1${path53}`;
8311
+ async function wikiFetch(config2, path54, method = "GET", body) {
8312
+ const url = `${config2.baseUrl}/api/v1${path54}`;
8307
8313
  const headers = {
8308
8314
  Authorization: `Bearer ${config2.apiKey}`,
8309
8315
  "Content-Type": "application/json"
@@ -8336,7 +8342,7 @@ async function wikiFetch(config2, path53, method = "GET", body) {
8336
8342
  }
8337
8343
  }
8338
8344
  if (!response.ok) {
8339
- throw new Error(`Wiki API ${method} ${path53}: ${response.status} ${response.statusText}`);
8345
+ throw new Error(`Wiki API ${method} ${path54}: ${response.status} ${response.statusText}`);
8340
8346
  }
8341
8347
  return response.json();
8342
8348
  } finally {
@@ -18747,9 +18753,9 @@ var init_hostinger_api = __esm({
18747
18753
  }
18748
18754
  this.lastRequestTime = Date.now();
18749
18755
  }
18750
- async request(method, path53, body) {
18756
+ async request(method, path54, body) {
18751
18757
  await this.rateLimit();
18752
- const url = `${this.baseUrl}${path53}`;
18758
+ const url = `${this.baseUrl}${path54}`;
18753
18759
  const headers = {
18754
18760
  Authorization: `Bearer ${this.apiKey}`,
18755
18761
  "Content-Type": "application/json",
@@ -18818,8 +18824,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
18818
18824
  }
18819
18825
  return envelope.result;
18820
18826
  }
18821
- function buildUrl(zoneId, path53 = "/dns_records", query) {
18822
- const normalizedPath = path53.startsWith("/") ? path53 : `/${path53}`;
18827
+ function buildUrl(zoneId, path54 = "/dns_records", query) {
18828
+ const normalizedPath = path54.startsWith("/") ? path54 : `/${path54}`;
18823
18829
  const url = new URL(
18824
18830
  `${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
18825
18831
  );
@@ -21146,12 +21152,12 @@ function registerExportGraph(server) {
21146
21152
  }
21147
21153
  const html = await exportGraphHTML(client);
21148
21154
  const fs = await import("fs");
21149
- const path53 = await import("path");
21155
+ const path54 = await import("path");
21150
21156
  const os23 = await import("os");
21151
- const outDir = path53.join(os23.homedir(), ".exe-os", "exports");
21157
+ const outDir = path54.join(os23.homedir(), ".exe-os", "exports");
21152
21158
  fs.mkdirSync(outDir, { recursive: true });
21153
21159
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
21154
- const filePath = path53.join(outDir, `graph-${timestamp}.html`);
21160
+ const filePath = path54.join(outDir, `graph-${timestamp}.html`);
21155
21161
  fs.writeFileSync(filePath, html, "utf-8");
21156
21162
  return {
21157
21163
  content: [
@@ -26794,6 +26800,225 @@ var init_activate_license = __esm({
26794
26800
  }
26795
26801
  });
26796
26802
 
26803
+ // src/mcp/tools/create-bug-report.ts
26804
+ import { z as z82 } from "zod";
26805
+ import crypto19 from "crypto";
26806
+ import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
26807
+ import path49 from "path";
26808
+ function slugify2(input) {
26809
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "bug-report";
26810
+ }
26811
+ function formatList(items) {
26812
+ if (!items || items.length === 0) return "- Not provided";
26813
+ return items.map((item) => `- ${item}`).join("\n");
26814
+ }
26815
+ function section(title, body) {
26816
+ return `## ${title}
26817
+
26818
+ ${body?.trim() || "Not provided"}`;
26819
+ }
26820
+ function buildMarkdown(input) {
26821
+ return [
26822
+ `# Bug Report \u2014 ${input.title}`,
26823
+ "",
26824
+ `id: ${input.id}`,
26825
+ `classification: ${input.classification}`,
26826
+ `severity: ${input.severity}`,
26827
+ `filed_by: ${input.agentId} (${input.agentRole})`,
26828
+ `package_version: ${input.packageVersion}`,
26829
+ `project: ${input.projectName ?? "unknown"}`,
26830
+ `created_at: ${(/* @__PURE__ */ new Date()).toISOString()}`,
26831
+ "",
26832
+ section("Summary", input.summary),
26833
+ section("Customer impact", input.customerImpact),
26834
+ "## Reproduction steps",
26835
+ "",
26836
+ formatList(input.reproductionSteps),
26837
+ "",
26838
+ section("Expected behavior", input.expected),
26839
+ section("Actual behavior", input.actual),
26840
+ "## Files changed / suspected",
26841
+ "",
26842
+ formatList(input.filesChanged),
26843
+ "",
26844
+ section("Local workaround / hotfix", input.workaround),
26845
+ section("Local patch diff", input.localPatchDiff)
26846
+ ].join("\n");
26847
+ }
26848
+ async function maybeSendUpstream(payload) {
26849
+ const config2 = await loadConfig();
26850
+ const endpoint = config2.support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT;
26851
+ const token = config2.support?.bugReportToken || process.env.EXE_BUG_REPORT_TOKEN;
26852
+ if (!endpoint) {
26853
+ return "not_configured";
26854
+ }
26855
+ try {
26856
+ const parsed = new URL(endpoint);
26857
+ if (parsed.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(parsed.hostname)) {
26858
+ return "failed: insecure endpoint rejected";
26859
+ }
26860
+ const response = await fetch(parsed, {
26861
+ method: "POST",
26862
+ headers: {
26863
+ "content-type": "application/json",
26864
+ ...token ? { authorization: `Bearer ${token}` } : {}
26865
+ },
26866
+ body: JSON.stringify(payload),
26867
+ signal: AbortSignal.timeout(1e4)
26868
+ });
26869
+ if (!response.ok) return `failed: HTTP ${response.status}`;
26870
+ return "sent";
26871
+ } catch (err) {
26872
+ return `failed: ${err instanceof Error ? err.message : String(err)}`;
26873
+ }
26874
+ }
26875
+ function registerCreateBugReport(server) {
26876
+ server.registerTool(
26877
+ "create_bug_report",
26878
+ {
26879
+ title: "Create Bug Report",
26880
+ 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.",
26881
+ inputSchema: {
26882
+ title: z82.string().min(3).describe("Short descriptive title"),
26883
+ classification: CLASSIFICATION.describe(
26884
+ "upstream_bug = platform defect; customer_customization = local preference; emergency_hotfix = temporary local patch; unclear = needs maintainer triage"
26885
+ ),
26886
+ severity: SEVERITY.default("p2").describe("p0 critical \u2192 p3 low"),
26887
+ summary: z82.string().min(10).describe("What happened and why it matters"),
26888
+ customer_impact: z82.string().optional().describe("How this affects the customer/founder"),
26889
+ reproduction_steps: z82.array(z82.string()).optional().describe("Steps to reproduce"),
26890
+ expected: z82.string().optional().describe("Expected behavior"),
26891
+ actual: z82.string().optional().describe("Actual behavior"),
26892
+ files_changed: z82.array(z82.string()).optional().describe("Files changed or suspected"),
26893
+ workaround: z82.string().optional().describe("Temporary local workaround/hotfix, if any"),
26894
+ local_patch_diff: z82.string().optional().describe("Small local diff or patch summary"),
26895
+ package_version: z82.string().optional().describe("Installed @askexenow/exe-os version"),
26896
+ project_name: z82.string().optional().describe("Project/customer context"),
26897
+ send_upstream: z82.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
26898
+ }
26899
+ },
26900
+ async ({
26901
+ title,
26902
+ classification,
26903
+ severity,
26904
+ summary,
26905
+ customer_impact,
26906
+ reproduction_steps,
26907
+ expected,
26908
+ actual,
26909
+ files_changed,
26910
+ workaround,
26911
+ local_patch_diff,
26912
+ package_version,
26913
+ project_name,
26914
+ send_upstream
26915
+ }) => {
26916
+ const { agentId, agentRole } = getActiveAgent();
26917
+ const id = crypto19.randomUUID();
26918
+ const version = package_version ?? "unknown";
26919
+ const markdown = buildMarkdown({
26920
+ id,
26921
+ title,
26922
+ classification,
26923
+ severity,
26924
+ agentId,
26925
+ agentRole,
26926
+ packageVersion: version,
26927
+ summary,
26928
+ customerImpact: customer_impact,
26929
+ expected,
26930
+ actual,
26931
+ workaround,
26932
+ localPatchDiff: local_patch_diff,
26933
+ reproductionSteps: reproduction_steps,
26934
+ filesChanged: files_changed,
26935
+ projectName: project_name
26936
+ });
26937
+ const outDir = path49.join(EXE_AI_DIR, "bug-reports");
26938
+ await mkdir6(outDir, { recursive: true });
26939
+ const reportPath = path49.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
26940
+ await writeFile7(reportPath, markdown, "utf-8");
26941
+ let vector = null;
26942
+ try {
26943
+ vector = await embed(markdown);
26944
+ } catch {
26945
+ vector = null;
26946
+ }
26947
+ await writeMemory({
26948
+ id,
26949
+ agent_id: agentId,
26950
+ agent_role: agentRole,
26951
+ session_id: process.env.SESSION_ID ?? "manual",
26952
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
26953
+ tool_name: "create_bug_report",
26954
+ project_name: project_name ?? "support",
26955
+ has_error: classification === "upstream_bug" || classification === "emergency_hotfix",
26956
+ raw_text: markdown,
26957
+ vector,
26958
+ source_path: reportPath,
26959
+ source_type: "bug_report",
26960
+ memory_type: "bug_report",
26961
+ tier: 1,
26962
+ importance: severity === "p0" ? 10 : severity === "p1" ? 9 : 7,
26963
+ intent: "report",
26964
+ domain: "support",
26965
+ file_paths: files_changed ? JSON.stringify(files_changed) : null
26966
+ });
26967
+ await flushBatch();
26968
+ const upstreamStatus = send_upstream ? await maybeSendUpstream({
26969
+ id,
26970
+ title,
26971
+ classification,
26972
+ severity,
26973
+ summary,
26974
+ customer_impact,
26975
+ reproduction_steps,
26976
+ expected,
26977
+ actual,
26978
+ files_changed,
26979
+ workaround,
26980
+ local_patch_diff,
26981
+ package_version: version,
26982
+ project_name,
26983
+ agent_id: agentId,
26984
+ agent_role: agentRole,
26985
+ report_path: reportPath,
26986
+ markdown
26987
+ }) : "skipped";
26988
+ return {
26989
+ content: [
26990
+ {
26991
+ type: "text",
26992
+ text: `Bug report created.
26993
+ ID: ${id}
26994
+ Classification: ${classification}
26995
+ Local report: ${reportPath}
26996
+ Memory stored: ${id}
26997
+ Upstream status: ${upstreamStatus}`
26998
+ }
26999
+ ]
27000
+ };
27001
+ }
27002
+ );
27003
+ }
27004
+ var CLASSIFICATION, SEVERITY;
27005
+ var init_create_bug_report = __esm({
27006
+ "src/mcp/tools/create-bug-report.ts"() {
27007
+ "use strict";
27008
+ init_embedder();
27009
+ init_active_agent();
27010
+ init_config();
27011
+ init_store();
27012
+ CLASSIFICATION = z82.enum([
27013
+ "upstream_bug",
27014
+ "customer_customization",
27015
+ "emergency_hotfix",
27016
+ "unclear"
27017
+ ]);
27018
+ SEVERITY = z82.enum(["p0", "p1", "p2", "p3"]);
27019
+ }
27020
+ });
27021
+
26797
27022
  // src/mcp/tool-gates.ts
26798
27023
  function isToolAllowed(registerFnName) {
26799
27024
  const role = process.env.AGENT_ROLE;
@@ -26855,6 +27080,7 @@ var init_tool_gates = __esm({
26855
27080
  registerBehavior: "core",
26856
27081
  registerStoreDecision: "core",
26857
27082
  registerGetDecision: "core",
27083
+ registerCreateBugReport: "core",
26858
27084
  registerIdentity: "core",
26859
27085
  registerGetIdentity: "core",
26860
27086
  registerUpdateIdentity: "core",
@@ -26887,6 +27113,7 @@ var init_tool_gates = __esm({
26887
27113
  registerExportGraph: "graph-write",
26888
27114
  // wiki
26889
27115
  registerWiki: "wiki",
27116
+ registerCreateWikiPage: "wiki",
26890
27117
  registerListWikiPages: "wiki",
26891
27118
  registerGetWikiPage: "wiki",
26892
27119
  // crm
@@ -27060,6 +27287,7 @@ function registerAllTools(server) {
27060
27287
  }
27061
27288
  gate("registerStoreDecision", registerStoreDecision);
27062
27289
  gate("registerGetDecision", registerGetDecision);
27290
+ gate("registerCreateBugReport", registerCreateBugReport);
27063
27291
  gate("registerGetAgentSpend", registerGetAgentSpend);
27064
27292
  gate("registerGetGraphStats", registerGetGraphStats);
27065
27293
  gate("registerGetEntityNeighbors", registerGetEntityNeighbors);
@@ -27181,6 +27409,7 @@ var init_register_tools = __esm({
27181
27409
  init_list_licenses();
27182
27410
  init_activate_license();
27183
27411
  init_query_company_brain();
27412
+ init_create_bug_report();
27184
27413
  init_tool_gates();
27185
27414
  }
27186
27415
  });
@@ -27406,7 +27635,7 @@ __export(task_enforcement_exports, {
27406
27635
  sendNudge: () => sendNudge
27407
27636
  });
27408
27637
  import { writeFileSync as writeFileSync22 } from "fs";
27409
- import path49 from "path";
27638
+ import path50 from "path";
27410
27639
  function writeAuditEntry(entry) {
27411
27640
  try {
27412
27641
  const line = JSON.stringify(entry) + "\n";
@@ -27581,7 +27810,7 @@ var init_task_enforcement = __esm({
27581
27810
  "What do you need?"
27582
27811
  ];
27583
27812
  MANAGER_ROLES = ["COO", "CTO"];
27584
- AUDIT_LOG_PATH = path49.join(
27813
+ AUDIT_LOG_PATH = path50.join(
27585
27814
  process.env.HOME ?? process.env.USERPROFILE ?? "/tmp",
27586
27815
  ".exe-os",
27587
27816
  "enforcement-audit.jsonl"
@@ -27599,9 +27828,9 @@ __export(update_check_exports, {
27599
27828
  });
27600
27829
  import { execSync as execSync15 } from "child_process";
27601
27830
  import { readFileSync as readFileSync31 } from "fs";
27602
- import path50 from "path";
27831
+ import path51 from "path";
27603
27832
  function getLocalVersion(packageRoot) {
27604
- const pkgPath = path50.join(packageRoot, "package.json");
27833
+ const pkgPath = path51.join(packageRoot, "package.json");
27605
27834
  const pkg = JSON.parse(readFileSync31(pkgPath, "utf-8"));
27606
27835
  return pkg.version;
27607
27836
  }
@@ -27645,16 +27874,16 @@ __export(ws_auth_exports, {
27645
27874
  deriveWsAuthToken: () => deriveWsAuthToken,
27646
27875
  hashAuthToken: () => hashAuthToken
27647
27876
  });
27648
- import crypto19 from "crypto";
27877
+ import crypto20 from "crypto";
27649
27878
  function deriveWsAuthToken(masterKey) {
27650
- return Buffer.from(crypto19.hkdfSync("sha256", masterKey, "", WS_AUTH_HKDF_INFO, 32));
27879
+ return Buffer.from(crypto20.hkdfSync("sha256", masterKey, "", WS_AUTH_HKDF_INFO, 32));
27651
27880
  }
27652
27881
  function deriveOrgId(masterKey) {
27653
- const raw = Buffer.from(crypto19.hkdfSync("sha256", masterKey, "", ORG_ID_HKDF_INFO, 32));
27654
- return crypto19.createHash("sha256").update(raw).digest("hex").slice(0, 32);
27882
+ const raw = Buffer.from(crypto20.hkdfSync("sha256", masterKey, "", ORG_ID_HKDF_INFO, 32));
27883
+ return crypto20.createHash("sha256").update(raw).digest("hex").slice(0, 32);
27655
27884
  }
27656
27885
  function hashAuthToken(token) {
27657
- return crypto19.createHash("sha256").update(token).digest("hex");
27886
+ return crypto20.createHash("sha256").update(token).digest("hex");
27658
27887
  }
27659
27888
  var WS_AUTH_HKDF_INFO, ORG_ID_HKDF_INFO;
27660
27889
  var init_ws_auth = __esm({
@@ -27672,10 +27901,10 @@ __export(device_registry_exports, {
27672
27901
  resolveTargetDevice: () => resolveTargetDevice,
27673
27902
  setFriendlyName: () => setFriendlyName
27674
27903
  });
27675
- import crypto20 from "crypto";
27904
+ import crypto21 from "crypto";
27676
27905
  import os21 from "os";
27677
27906
  import { readFileSync as readFileSync32, writeFileSync as writeFileSync23, mkdirSync as mkdirSync18, existsSync as existsSync38 } from "fs";
27678
- import path51 from "path";
27907
+ import path52 from "path";
27679
27908
  function getDeviceInfo() {
27680
27909
  if (existsSync38(DEVICE_JSON_PATH)) {
27681
27910
  try {
@@ -27689,11 +27918,11 @@ function getDeviceInfo() {
27689
27918
  }
27690
27919
  const hostname = os21.hostname();
27691
27920
  const info = {
27692
- deviceId: crypto20.randomUUID(),
27921
+ deviceId: crypto21.randomUUID(),
27693
27922
  friendlyName: hostname.replace(/\./g, "-").toLowerCase(),
27694
27923
  hostname
27695
27924
  };
27696
- mkdirSync18(path51.dirname(DEVICE_JSON_PATH), { recursive: true });
27925
+ mkdirSync18(path52.dirname(DEVICE_JSON_PATH), { recursive: true });
27697
27926
  writeFileSync23(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
27698
27927
  return info;
27699
27928
  }
@@ -27734,7 +27963,7 @@ var init_device_registry = __esm({
27734
27963
  "src/lib/device-registry.ts"() {
27735
27964
  "use strict";
27736
27965
  init_config();
27737
- DEVICE_JSON_PATH = path51.join(EXE_AI_DIR, "device.json");
27966
+ DEVICE_JSON_PATH = path52.join(EXE_AI_DIR, "device.json");
27738
27967
  }
27739
27968
  });
27740
27969
 
@@ -27951,7 +28180,7 @@ import net2 from "net";
27951
28180
  import { createServer as createHttpServer } from "http";
27952
28181
  import { randomUUID as randomUUID9 } from "crypto";
27953
28182
  import { writeFileSync as writeFileSync24, unlinkSync as unlinkSync13, mkdirSync as mkdirSync19, existsSync as existsSync39, readFileSync as readFileSync33, chmodSync as chmodSync2 } from "fs";
27954
- import path52 from "path";
28183
+ import path53 from "path";
27955
28184
 
27956
28185
  // src/lib/orchestration-metrics.ts
27957
28186
  init_config();
@@ -28023,8 +28252,8 @@ function initMetrics() {
28023
28252
 
28024
28253
  // src/lib/exe-daemon.ts
28025
28254
  init_memory_write_governor();
28026
- var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path52.join(EXE_AI_DIR, "exed.sock");
28027
- var PID_PATH3 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path52.join(EXE_AI_DIR, "exed.pid");
28255
+ var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path53.join(EXE_AI_DIR, "exed.sock");
28256
+ var PID_PATH3 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path53.join(EXE_AI_DIR, "exed.pid");
28028
28257
  var MODEL_FILE = "jina-embeddings-v5-small-q4_k_m.gguf";
28029
28258
  var IDLE_TIMEOUT_MS2 = 15 * 60 * 1e3;
28030
28259
  var REVIEW_POLL_INTERVAL_MS = 60 * 1e3;
@@ -28052,7 +28281,7 @@ function enqueue(queue, entry) {
28052
28281
  queue.push(entry);
28053
28282
  }
28054
28283
  async function loadModel() {
28055
- const modelPath = path52.join(MODELS_DIR, MODEL_FILE);
28284
+ const modelPath = path53.join(MODELS_DIR, MODEL_FILE);
28056
28285
  if (!existsSync39(modelPath)) {
28057
28286
  process.stderr.write(`[exed] No model at ${modelPath} \u2014 running without embeddings (VPS mode).
28058
28287
  `);
@@ -28451,14 +28680,14 @@ function startMemoryQueueDrain() {
28451
28680
  `);
28452
28681
  }
28453
28682
  function startServer() {
28454
- mkdirSync19(path52.dirname(SOCKET_PATH2), { recursive: true });
28683
+ mkdirSync19(path53.dirname(SOCKET_PATH2), { recursive: true });
28455
28684
  try {
28456
- chmodSync2(path52.dirname(SOCKET_PATH2), 448);
28685
+ chmodSync2(path53.dirname(SOCKET_PATH2), 448);
28457
28686
  } catch {
28458
28687
  }
28459
28688
  _daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV2] ?? null);
28460
28689
  for (const oldFile of ["embed.sock", "embed.pid"]) {
28461
- const oldPath = path52.join(path52.dirname(SOCKET_PATH2), oldFile);
28690
+ const oldPath = path53.join(path53.dirname(SOCKET_PATH2), oldFile);
28462
28691
  try {
28463
28692
  if (oldFile.endsWith(".pid")) {
28464
28693
  const pid = parseInt(readFileSync33(oldPath, "utf8").trim(), 10);
@@ -28934,7 +29163,7 @@ function startGraphExtraction() {
28934
29163
  `);
28935
29164
  }
28936
29165
  var AGENT_STATS_INTERVAL_MS = 60 * 1e3;
28937
- var AGENT_STATS_PATH = path52.join(EXE_AI_DIR, "agent-stats.json");
29166
+ var AGENT_STATS_PATH = path53.join(EXE_AI_DIR, "agent-stats.json");
28938
29167
  async function writeAgentStats() {
28939
29168
  fired("agent_stats");
28940
29169
  if (!await ensureStoreForPolling()) return;
@@ -29111,11 +29340,11 @@ function startIntercomQueueDrain() {
29111
29340
  const hasInProgressTask = (session) => {
29112
29341
  try {
29113
29342
  const { baseAgentName: ban } = (init_employees(), __toCommonJS(employees_exports));
29114
- const path53 = __require("path");
29343
+ const path54 = __require("path");
29115
29344
  const { existsSync: existsSync40 } = __require("fs");
29116
29345
  const os23 = __require("os");
29117
29346
  const agent = ban(session.split("-")[0] ?? session);
29118
- const markerPath = path53.join(os23.homedir(), ".exe-os", "session-cache", `current-task-${agent}.json`);
29347
+ const markerPath = path54.join(os23.homedir(), ".exe-os", "session-cache", `current-task-${agent}.json`);
29119
29348
  return existsSync40(markerPath);
29120
29349
  } catch {
29121
29350
  return false;
@@ -3644,6 +3644,12 @@ var init_platform_procedures = __esm({
3644
3644
  priority: "p0",
3645
3645
  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."
3646
3646
  },
3647
+ {
3648
+ title: "Customer patch triage \u2014 upstream bug vs customization",
3649
+ domain: "support",
3650
+ priority: "p0",
3651
+ 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."
3652
+ },
3647
3653
  // --- Operations ---
3648
3654
  {
3649
3655
  title: "Managers must supervise deployed workers",
@@ -3712,7 +3718,7 @@ var init_platform_procedures = __esm({
3712
3718
  title: "MCP tools \u2014 identity, behavior, and decisions",
3713
3719
  domain: "tool-use",
3714
3720
  priority: "p1",
3715
- 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."
3721
+ 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."
3716
3722
  },
3717
3723
  {
3718
3724
  title: "MCP tools \u2014 communication and messaging",
@@ -3006,6 +3006,12 @@ var init_platform_procedures = __esm({
3006
3006
  priority: "p0",
3007
3007
  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."
3008
3008
  },
3009
+ {
3010
+ title: "Customer patch triage \u2014 upstream bug vs customization",
3011
+ domain: "support",
3012
+ priority: "p0",
3013
+ 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."
3014
+ },
3009
3015
  // --- Operations ---
3010
3016
  {
3011
3017
  title: "Managers must supervise deployed workers",
@@ -3074,7 +3080,7 @@ var init_platform_procedures = __esm({
3074
3080
  title: "MCP tools \u2014 identity, behavior, and decisions",
3075
3081
  domain: "tool-use",
3076
3082
  priority: "p1",
3077
- 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."
3083
+ 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."
3078
3084
  },
3079
3085
  {
3080
3086
  title: "MCP tools \u2014 communication and messaging",
package/dist/lib/store.js CHANGED
@@ -3006,6 +3006,12 @@ var init_platform_procedures = __esm({
3006
3006
  priority: "p0",
3007
3007
  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."
3008
3008
  },
3009
+ {
3010
+ title: "Customer patch triage \u2014 upstream bug vs customization",
3011
+ domain: "support",
3012
+ priority: "p0",
3013
+ 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."
3014
+ },
3009
3015
  // --- Operations ---
3010
3016
  {
3011
3017
  title: "Managers must supervise deployed workers",
@@ -3074,7 +3080,7 @@ var init_platform_procedures = __esm({
3074
3080
  title: "MCP tools \u2014 identity, behavior, and decisions",
3075
3081
  domain: "tool-use",
3076
3082
  priority: "p1",
3077
- 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."
3083
+ 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."
3078
3084
  },
3079
3085
  {
3080
3086
  title: "MCP tools \u2014 communication and messaging",