@askexenow/exe-os 0.9.69 → 0.9.71

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 (79) hide show
  1. package/deploy/stack-manifests/v0.9.json +96 -16
  2. package/dist/bin/agentic-ontology-backfill.js +33 -0
  3. package/dist/bin/agentic-reflection-backfill.js +33 -0
  4. package/dist/bin/agentic-semantic-label.js +33 -0
  5. package/dist/bin/backfill-conversations.js +33 -0
  6. package/dist/bin/backfill-responses.js +33 -0
  7. package/dist/bin/backfill-vectors.js +33 -0
  8. package/dist/bin/bulk-sync-postgres.js +33 -0
  9. package/dist/bin/cleanup-stale-review-tasks.js +33 -0
  10. package/dist/bin/cli.js +1284 -178
  11. package/dist/bin/exe-agent.js +6 -0
  12. package/dist/bin/exe-assign.js +33 -0
  13. package/dist/bin/exe-boot.js +33 -0
  14. package/dist/bin/exe-call.js +6 -0
  15. package/dist/bin/exe-cloud.js +33 -0
  16. package/dist/bin/exe-dispatch.js +33 -0
  17. package/dist/bin/exe-doctor.js +33 -0
  18. package/dist/bin/exe-export-behaviors.js +33 -0
  19. package/dist/bin/exe-forget.js +33 -0
  20. package/dist/bin/exe-gateway.js +178 -110
  21. package/dist/bin/exe-heartbeat.js +33 -0
  22. package/dist/bin/exe-kill.js +33 -0
  23. package/dist/bin/exe-launch-agent.js +33 -0
  24. package/dist/bin/exe-new-employee.js +6 -0
  25. package/dist/bin/exe-pending-messages.js +33 -0
  26. package/dist/bin/exe-pending-notifications.js +33 -0
  27. package/dist/bin/exe-pending-reviews.js +33 -0
  28. package/dist/bin/exe-rename.js +40 -4
  29. package/dist/bin/exe-review.js +33 -0
  30. package/dist/bin/exe-search.js +33 -0
  31. package/dist/bin/exe-session-cleanup.js +33 -0
  32. package/dist/bin/exe-start-codex.js +33 -0
  33. package/dist/bin/exe-start-opencode.js +33 -0
  34. package/dist/bin/exe-status.js +33 -0
  35. package/dist/bin/exe-team.js +33 -0
  36. package/dist/bin/git-sweep.js +33 -0
  37. package/dist/bin/graph-backfill.js +177 -110
  38. package/dist/bin/graph-export.js +33 -0
  39. package/dist/bin/intercom-check.js +33 -0
  40. package/dist/bin/registry-proxy.js +207 -0
  41. package/dist/bin/scan-tasks.js +33 -0
  42. package/dist/bin/setup.js +33 -0
  43. package/dist/bin/shard-migrate.js +33 -0
  44. package/dist/bin/stack-update.js +128 -0
  45. package/dist/gateway/index.js +178 -110
  46. package/dist/hooks/bug-report-worker.js +33 -0
  47. package/dist/hooks/codex-stop-task-finalizer.js +33 -0
  48. package/dist/hooks/commit-complete.js +33 -0
  49. package/dist/hooks/error-recall.js +33 -0
  50. package/dist/hooks/ingest.js +33 -0
  51. package/dist/hooks/instructions-loaded.js +33 -0
  52. package/dist/hooks/notification.js +33 -0
  53. package/dist/hooks/post-compact.js +33 -0
  54. package/dist/hooks/post-tool-combined.js +698 -17
  55. package/dist/hooks/pre-compact.js +33 -0
  56. package/dist/hooks/pre-tool-use.js +33 -0
  57. package/dist/hooks/prompt-submit.js +314 -0
  58. package/dist/hooks/session-end.js +33 -0
  59. package/dist/hooks/session-start.js +33 -0
  60. package/dist/hooks/stop.js +279 -12
  61. package/dist/hooks/subagent-stop.js +33 -0
  62. package/dist/hooks/summary-worker.js +33 -0
  63. package/dist/index.js +178 -110
  64. package/dist/lib/cloud-sync.js +27 -0
  65. package/dist/lib/database.js +27 -0
  66. package/dist/lib/db.js +27 -0
  67. package/dist/lib/device-registry.js +27 -0
  68. package/dist/lib/employee-templates.js +6 -0
  69. package/dist/lib/exe-daemon.js +639 -259
  70. package/dist/lib/hybrid-search.js +33 -0
  71. package/dist/lib/registry-proxy.js +162 -0
  72. package/dist/lib/schedules.js +33 -0
  73. package/dist/lib/store.js +33 -0
  74. package/dist/mcp/server.js +561 -244
  75. package/dist/runtime/index.js +33 -0
  76. package/dist/tui/App.js +33 -0
  77. package/package.json +3 -2
  78. package/stack.release.json +6 -4
  79. package/stack.release.schema.json +89 -18
package/dist/index.js CHANGED
@@ -3246,6 +3246,33 @@ async function ensureSchema() {
3246
3246
  CREATE INDEX IF NOT EXISTS idx_chat_history_session
3247
3247
  ON chat_history(session_id, id);
3248
3248
  `);
3249
+ await client.executeMultiple(`
3250
+ CREATE TABLE IF NOT EXISTS session_events (
3251
+ id TEXT PRIMARY KEY,
3252
+ agent_id TEXT NOT NULL,
3253
+ agent_role TEXT NOT NULL,
3254
+ session_id TEXT NOT NULL,
3255
+ session_scope TEXT,
3256
+ project_name TEXT NOT NULL,
3257
+ event_index INTEGER NOT NULL,
3258
+ event_type TEXT NOT NULL,
3259
+ tool_name TEXT,
3260
+ tool_use_id TEXT,
3261
+ content TEXT NOT NULL,
3262
+ payload_json TEXT,
3263
+ has_error INTEGER NOT NULL DEFAULT 0,
3264
+ created_at TEXT NOT NULL
3265
+ );
3266
+
3267
+ CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
3268
+ ON session_events(agent_id, created_at DESC);
3269
+
3270
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_index
3271
+ ON session_events(session_id, event_index);
3272
+
3273
+ CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
3274
+ ON session_events(session_scope, agent_id, created_at DESC);
3275
+ `);
3249
3276
  await client.executeMultiple(`
3250
3277
  CREATE TABLE IF NOT EXISTS workspaces (
3251
3278
  id TEXT PRIMARY KEY,
@@ -8188,6 +8215,12 @@ var init_platform_procedures = __esm({
8188
8215
  priority: "p0",
8189
8216
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
8190
8217
  },
8218
+ {
8219
+ title: "Code context first for repository orientation",
8220
+ domain: "workflow",
8221
+ priority: "p1",
8222
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
8223
+ },
8191
8224
  {
8192
8225
  title: "Commit discipline \u2014 never leave verified work floating",
8193
8226
  domain: "workflow",
@@ -10149,13 +10182,25 @@ var init_wiki_client = __esm({
10149
10182
 
10150
10183
  // src/lib/code-chunker.ts
10151
10184
  import ts from "typescript";
10185
+ function languageForFile(filePath) {
10186
+ const base = filePath.split(/[\\/]/).pop()?.toLowerCase() ?? "";
10187
+ if (["dockerfile", "makefile", "rakefile", "gemfile"].includes(base)) return base;
10188
+ const ext = base.includes(".") ? base.split(".").pop() : void 0;
10189
+ return ext ? LANGUAGE_BY_EXTENSION[ext] : void 0;
10190
+ }
10152
10191
  function chunkSourceFile(source, fileName = "file.ts") {
10192
+ const language = languageForFile(fileName);
10193
+ if (language === "typescript" || language === "javascript") {
10194
+ return chunkTypeScriptLike(source, fileName);
10195
+ }
10196
+ return chunkGenericSource(source, fileName, language);
10197
+ }
10198
+ function chunkTypeScriptLike(source, fileName) {
10153
10199
  const sourceFile = ts.createSourceFile(
10154
10200
  fileName,
10155
10201
  source,
10156
10202
  ts.ScriptTarget.Latest,
10157
10203
  true,
10158
- // setParentNodes
10159
10204
  fileName.endsWith(".tsx") || fileName.endsWith(".jsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS
10160
10205
  );
10161
10206
  const chunks = [];
@@ -10177,153 +10222,176 @@ function chunkSourceFile(source, fileName = "file.ts") {
10177
10222
  if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) {
10178
10223
  return node.name?.getText(sourceFile) ?? "(anonymous)";
10179
10224
  }
10180
- if (ts.isClassDeclaration(node)) {
10181
- return node.name?.getText(sourceFile) ?? "(anonymous class)";
10182
- }
10183
- if (ts.isInterfaceDeclaration(node)) {
10184
- return node.name.getText(sourceFile);
10185
- }
10186
- if (ts.isTypeAliasDeclaration(node)) {
10187
- return node.name.getText(sourceFile);
10188
- }
10189
- if (ts.isEnumDeclaration(node)) {
10190
- return node.name.getText(sourceFile);
10191
- }
10192
- if (ts.isVariableStatement(node)) {
10193
- const decls = node.declarationList.declarations;
10194
- return decls.map((d) => d.name.getText(sourceFile)).join(", ");
10195
- }
10196
- if (ts.isExportAssignment(node)) {
10197
- return "default export";
10198
- }
10225
+ if (ts.isClassDeclaration(node)) return node.name?.getText(sourceFile) ?? "(anonymous class)";
10226
+ if (ts.isInterfaceDeclaration(node)) return node.name.getText(sourceFile);
10227
+ if (ts.isTypeAliasDeclaration(node)) return node.name.getText(sourceFile);
10228
+ if (ts.isEnumDeclaration(node)) return node.name.getText(sourceFile);
10229
+ if (ts.isVariableStatement(node)) return node.declarationList.declarations.map((d) => d.name.getText(sourceFile)).join(", ");
10230
+ if (ts.isExportAssignment(node)) return "default export";
10199
10231
  return "(unknown)";
10200
10232
  }
10201
10233
  function visitTopLevel(node) {
10202
10234
  if (ts.isImportDeclaration(node)) {
10203
- importLines.push({
10204
- start: getLineNumber(node.getStart(sourceFile)),
10205
- end: getLineNumber(node.getEnd())
10206
- });
10235
+ importLines.push({ start: getLineNumber(node.getStart(sourceFile)), end: getLineNumber(node.getEnd()) });
10207
10236
  return;
10208
10237
  }
10209
10238
  if (ts.isFunctionDeclaration(node)) {
10210
- chunks.push({
10211
- kind: "function",
10212
- name: getName(node),
10213
- text: getNodeText(node),
10214
- startLine: getLineNumber(node.getStart(sourceFile)),
10215
- endLine: getLineNumber(node.getEnd()),
10216
- comment: getLeadingComment(node)
10217
- });
10239
+ chunks.push({ kind: "function", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
10218
10240
  return;
10219
10241
  }
10220
10242
  if (ts.isClassDeclaration(node)) {
10221
- chunks.push({
10222
- kind: "class",
10223
- name: getName(node),
10224
- text: getNodeText(node),
10225
- startLine: getLineNumber(node.getStart(sourceFile)),
10226
- endLine: getLineNumber(node.getEnd()),
10227
- comment: getLeadingComment(node)
10228
- });
10243
+ chunks.push({ kind: "class", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
10229
10244
  return;
10230
10245
  }
10231
- if (ts.isInterfaceDeclaration(node)) {
10232
- chunks.push({
10233
- kind: "type",
10234
- name: getName(node),
10235
- text: getNodeText(node),
10236
- startLine: getLineNumber(node.getStart(sourceFile)),
10237
- endLine: getLineNumber(node.getEnd()),
10238
- comment: getLeadingComment(node)
10239
- });
10240
- return;
10241
- }
10242
- if (ts.isTypeAliasDeclaration(node)) {
10243
- chunks.push({
10244
- kind: "type",
10245
- name: getName(node),
10246
- text: getNodeText(node),
10247
- startLine: getLineNumber(node.getStart(sourceFile)),
10248
- endLine: getLineNumber(node.getEnd()),
10249
- comment: getLeadingComment(node)
10250
- });
10251
- return;
10252
- }
10253
- if (ts.isEnumDeclaration(node)) {
10254
- chunks.push({
10255
- kind: "type",
10256
- name: getName(node),
10257
- text: getNodeText(node),
10258
- startLine: getLineNumber(node.getStart(sourceFile)),
10259
- endLine: getLineNumber(node.getEnd()),
10260
- comment: getLeadingComment(node)
10261
- });
10246
+ if (ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node)) {
10247
+ chunks.push({ kind: "type", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
10262
10248
  return;
10263
10249
  }
10264
10250
  if (ts.isVariableStatement(node)) {
10265
- const decls = node.declarationList.declarations;
10266
- const isFnLike = decls.some(
10267
- (d) => d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer))
10268
- );
10269
- chunks.push({
10270
- kind: isFnLike ? "function" : "variable",
10271
- name: getName(node),
10272
- text: getNodeText(node),
10273
- startLine: getLineNumber(node.getStart(sourceFile)),
10274
- endLine: getLineNumber(node.getEnd()),
10275
- comment: getLeadingComment(node)
10276
- });
10251
+ const isFnLike = node.declarationList.declarations.some((d) => d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer)));
10252
+ chunks.push({ kind: isFnLike ? "function" : "variable", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
10277
10253
  return;
10278
10254
  }
10279
10255
  if (ts.isExportAssignment(node)) {
10280
- chunks.push({
10281
- kind: "export",
10282
- name: "default export",
10283
- text: getNodeText(node),
10284
- startLine: getLineNumber(node.getStart(sourceFile)),
10285
- endLine: getLineNumber(node.getEnd()),
10286
- comment: getLeadingComment(node)
10287
- });
10256
+ chunks.push({ kind: "export", name: "default export", text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
10288
10257
  return;
10289
10258
  }
10290
10259
  if (ts.isExpressionStatement(node)) {
10291
10260
  const text = getNodeText(node);
10292
- if (text.length > 10) {
10293
- chunks.push({
10294
- kind: "other",
10295
- name: text.slice(0, 40).replace(/\n/g, " "),
10296
- text,
10297
- startLine: getLineNumber(node.getStart(sourceFile)),
10298
- endLine: getLineNumber(node.getEnd())
10299
- });
10300
- }
10301
- return;
10261
+ if (text.length > 10) chunks.push({ kind: "other", name: text.slice(0, 40).replace(/\n/g, " "), text, startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()) });
10302
10262
  }
10303
10263
  }
10304
10264
  sourceFile.statements.forEach(visitTopLevel);
10305
10265
  if (importLines.length > 0) {
10306
10266
  const startLine = importLines[0].start;
10307
10267
  const endLine = importLines[importLines.length - 1].end;
10308
- const importText = lines.slice(startLine - 1, endLine).join("\n");
10309
- chunks.unshift({
10310
- kind: "import",
10311
- name: `${importLines.length} imports`,
10312
- text: importText,
10313
- startLine,
10268
+ chunks.unshift({ kind: "import", name: `${importLines.length} imports`, text: lines.slice(startLine - 1, endLine).join("\n"), startLine, endLine });
10269
+ }
10270
+ chunks.sort((a, b) => a.startLine - b.startLine);
10271
+ return chunks.length > 0 ? chunks : chunkByWindows(source, 80);
10272
+ }
10273
+ function chunkGenericSource(source, _fileName, language) {
10274
+ const lines = source.split("\n");
10275
+ if (source.trim().length === 0) return [];
10276
+ if (language && TEXT_LIKE_LANGUAGES.has(language)) return chunkTextLike(lines, language);
10277
+ const chunks = [];
10278
+ const patterns = [
10279
+ { kind: "function", regex: /^\s*(?:async\s+)?def\s+([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
10280
+ { kind: "class", regex: /^\s*class\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
10281
+ { kind: "function", regex: /^\s*(?:pub\s+)?fn\s+([A-Za-z_][\w]*)\s*[<(]/, name: (m) => m[1] },
10282
+ { kind: "class", regex: /^\s*(?:pub\s+)?(?:struct|enum|trait)\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
10283
+ { kind: "function", regex: /^\s*func\s+(?:\([^)]*\)\s*)?([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
10284
+ { kind: "function", regex: /^\s*(?:public|private|protected|static|final|suspend|fun|override|open|internal|export|async|func|function|subroutine)\s+.*?([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
10285
+ { kind: "function", regex: /^\s*function\s+([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
10286
+ { kind: "type", regex: /^\s*(?:interface|type|enum|record|data\s+class|case\s+class|contract|library)\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
10287
+ { kind: "section", regex: /^\s{0,3}#{1,6}\s+(.+)$/, name: (m) => m[1].trim() }
10288
+ ];
10289
+ const starts = [];
10290
+ for (let i = 0; i < lines.length; i++) {
10291
+ const line = lines[i];
10292
+ for (const pattern of patterns) {
10293
+ const match = line.match(pattern.regex);
10294
+ if (match) {
10295
+ starts.push({ line: i + 1, kind: pattern.kind, name: pattern.name(match) });
10296
+ break;
10297
+ }
10298
+ }
10299
+ }
10300
+ if (starts.length === 0) return chunkByWindows(source, 80);
10301
+ for (let i = 0; i < starts.length; i++) {
10302
+ const start = starts[i];
10303
+ const next = starts[i + 1]?.line ?? lines.length + 1;
10304
+ const endLine = Math.max(start.line, next - 1);
10305
+ chunks.push({
10306
+ kind: start.kind,
10307
+ name: start.name,
10308
+ text: lines.slice(start.line - 1, endLine).join("\n"),
10309
+ startLine: start.line,
10314
10310
  endLine
10315
10311
  });
10316
10312
  }
10317
- chunks.sort((a, b) => a.startLine - b.startLine);
10313
+ return chunks;
10314
+ }
10315
+ function chunkTextLike(lines, language) {
10316
+ if (language === "markdown" || language === "mdx") {
10317
+ const starts = lines.map((line, i) => ({ line, i })).filter(({ line }) => /^\s{0,3}#{1,6}\s+/.test(line));
10318
+ if (starts.length > 0) {
10319
+ return starts.map((start, idx) => {
10320
+ const end = starts[idx + 1]?.i ?? lines.length;
10321
+ const title = start.line.replace(/^\s{0,3}#{1,6}\s+/, "").trim();
10322
+ return { kind: "section", name: title, text: lines.slice(start.i, end).join("\n"), startLine: start.i + 1, endLine: end };
10323
+ });
10324
+ }
10325
+ }
10326
+ return chunkByWindows(lines.join("\n"), 80);
10327
+ }
10328
+ function chunkByWindows(source, windowLines) {
10329
+ const lines = source.split("\n");
10330
+ const chunks = [];
10331
+ for (let i = 0; i < lines.length; i += windowLines) {
10332
+ const end = Math.min(lines.length, i + windowLines);
10333
+ const text = lines.slice(i, end).join("\n");
10334
+ if (text.trim()) chunks.push({ kind: "other", name: `lines ${i + 1}-${end}`, text, startLine: i + 1, endLine: end });
10335
+ }
10318
10336
  return chunks;
10319
10337
  }
10320
10338
  function isChunkable(filePath) {
10321
- const ext = filePath.split(".").pop()?.toLowerCase();
10322
- return ext === "ts" || ext === "tsx" || ext === "js" || ext === "jsx";
10339
+ return Boolean(languageForFile(filePath));
10323
10340
  }
10341
+ var LANGUAGE_BY_EXTENSION, TEXT_LIKE_LANGUAGES;
10324
10342
  var init_code_chunker = __esm({
10325
10343
  "src/lib/code-chunker.ts"() {
10326
10344
  "use strict";
10345
+ LANGUAGE_BY_EXTENSION = {
10346
+ c: "c",
10347
+ cc: "cpp",
10348
+ cpp: "cpp",
10349
+ cxx: "cpp",
10350
+ h: "c",
10351
+ hh: "cpp",
10352
+ hpp: "cpp",
10353
+ cs: "csharp",
10354
+ css: "css",
10355
+ scss: "scss",
10356
+ f: "fortran",
10357
+ f90: "fortran",
10358
+ f95: "fortran",
10359
+ go: "go",
10360
+ html: "html",
10361
+ htm: "html",
10362
+ java: "java",
10363
+ js: "javascript",
10364
+ jsx: "javascript",
10365
+ json: "json",
10366
+ kt: "kotlin",
10367
+ kts: "kotlin",
10368
+ lua: "lua",
10369
+ md: "markdown",
10370
+ mdx: "mdx",
10371
+ pas: "pascal",
10372
+ php: "php",
10373
+ py: "python",
10374
+ r: "r",
10375
+ rb: "ruby",
10376
+ rs: "rust",
10377
+ scala: "scala",
10378
+ sc: "scala",
10379
+ sol: "solidity",
10380
+ sql: "sql",
10381
+ svelte: "svelte",
10382
+ swift: "swift",
10383
+ toml: "toml",
10384
+ ts: "typescript",
10385
+ tsx: "typescript",
10386
+ vue: "vue",
10387
+ xml: "xml",
10388
+ yaml: "yaml",
10389
+ yml: "yaml",
10390
+ sh: "shell",
10391
+ bash: "shell",
10392
+ zsh: "shell"
10393
+ };
10394
+ TEXT_LIKE_LANGUAGES = /* @__PURE__ */ new Set(["json", "markdown", "mdx", "toml", "yaml", "xml", "html", "css", "scss", "sql"]);
10327
10395
  }
10328
10396
  });
10329
10397
 
@@ -2160,6 +2160,33 @@ async function ensureSchema() {
2160
2160
  CREATE INDEX IF NOT EXISTS idx_chat_history_session
2161
2161
  ON chat_history(session_id, id);
2162
2162
  `);
2163
+ await client.executeMultiple(`
2164
+ CREATE TABLE IF NOT EXISTS session_events (
2165
+ id TEXT PRIMARY KEY,
2166
+ agent_id TEXT NOT NULL,
2167
+ agent_role TEXT NOT NULL,
2168
+ session_id TEXT NOT NULL,
2169
+ session_scope TEXT,
2170
+ project_name TEXT NOT NULL,
2171
+ event_index INTEGER NOT NULL,
2172
+ event_type TEXT NOT NULL,
2173
+ tool_name TEXT,
2174
+ tool_use_id TEXT,
2175
+ content TEXT NOT NULL,
2176
+ payload_json TEXT,
2177
+ has_error INTEGER NOT NULL DEFAULT 0,
2178
+ created_at TEXT NOT NULL
2179
+ );
2180
+
2181
+ CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
2182
+ ON session_events(agent_id, created_at DESC);
2183
+
2184
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_index
2185
+ ON session_events(session_id, event_index);
2186
+
2187
+ CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
2188
+ ON session_events(session_scope, agent_id, created_at DESC);
2189
+ `);
2163
2190
  await client.executeMultiple(`
2164
2191
  CREATE TABLE IF NOT EXISTS workspaces (
2165
2192
  id TEXT PRIMARY KEY,
@@ -2076,6 +2076,33 @@ async function ensureSchema() {
2076
2076
  CREATE INDEX IF NOT EXISTS idx_chat_history_session
2077
2077
  ON chat_history(session_id, id);
2078
2078
  `);
2079
+ await client.executeMultiple(`
2080
+ CREATE TABLE IF NOT EXISTS session_events (
2081
+ id TEXT PRIMARY KEY,
2082
+ agent_id TEXT NOT NULL,
2083
+ agent_role TEXT NOT NULL,
2084
+ session_id TEXT NOT NULL,
2085
+ session_scope TEXT,
2086
+ project_name TEXT NOT NULL,
2087
+ event_index INTEGER NOT NULL,
2088
+ event_type TEXT NOT NULL,
2089
+ tool_name TEXT,
2090
+ tool_use_id TEXT,
2091
+ content TEXT NOT NULL,
2092
+ payload_json TEXT,
2093
+ has_error INTEGER NOT NULL DEFAULT 0,
2094
+ created_at TEXT NOT NULL
2095
+ );
2096
+
2097
+ CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
2098
+ ON session_events(agent_id, created_at DESC);
2099
+
2100
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_index
2101
+ ON session_events(session_id, event_index);
2102
+
2103
+ CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
2104
+ ON session_events(session_scope, agent_id, created_at DESC);
2105
+ `);
2079
2106
  await client.executeMultiple(`
2080
2107
  CREATE TABLE IF NOT EXISTS workspaces (
2081
2108
  id TEXT PRIMARY KEY,
package/dist/lib/db.js CHANGED
@@ -2076,6 +2076,33 @@ async function ensureSchema() {
2076
2076
  CREATE INDEX IF NOT EXISTS idx_chat_history_session
2077
2077
  ON chat_history(session_id, id);
2078
2078
  `);
2079
+ await client.executeMultiple(`
2080
+ CREATE TABLE IF NOT EXISTS session_events (
2081
+ id TEXT PRIMARY KEY,
2082
+ agent_id TEXT NOT NULL,
2083
+ agent_role TEXT NOT NULL,
2084
+ session_id TEXT NOT NULL,
2085
+ session_scope TEXT,
2086
+ project_name TEXT NOT NULL,
2087
+ event_index INTEGER NOT NULL,
2088
+ event_type TEXT NOT NULL,
2089
+ tool_name TEXT,
2090
+ tool_use_id TEXT,
2091
+ content TEXT NOT NULL,
2092
+ payload_json TEXT,
2093
+ has_error INTEGER NOT NULL DEFAULT 0,
2094
+ created_at TEXT NOT NULL
2095
+ );
2096
+
2097
+ CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
2098
+ ON session_events(agent_id, created_at DESC);
2099
+
2100
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_index
2101
+ ON session_events(session_id, event_index);
2102
+
2103
+ CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
2104
+ ON session_events(session_scope, agent_id, created_at DESC);
2105
+ `);
2079
2106
  await client.executeMultiple(`
2080
2107
  CREATE TABLE IF NOT EXISTS workspaces (
2081
2108
  id TEXT PRIMARY KEY,
@@ -2105,6 +2105,33 @@ async function ensureSchema() {
2105
2105
  CREATE INDEX IF NOT EXISTS idx_chat_history_session
2106
2106
  ON chat_history(session_id, id);
2107
2107
  `);
2108
+ await client.executeMultiple(`
2109
+ CREATE TABLE IF NOT EXISTS session_events (
2110
+ id TEXT PRIMARY KEY,
2111
+ agent_id TEXT NOT NULL,
2112
+ agent_role TEXT NOT NULL,
2113
+ session_id TEXT NOT NULL,
2114
+ session_scope TEXT,
2115
+ project_name TEXT NOT NULL,
2116
+ event_index INTEGER NOT NULL,
2117
+ event_type TEXT NOT NULL,
2118
+ tool_name TEXT,
2119
+ tool_use_id TEXT,
2120
+ content TEXT NOT NULL,
2121
+ payload_json TEXT,
2122
+ has_error INTEGER NOT NULL DEFAULT 0,
2123
+ created_at TEXT NOT NULL
2124
+ );
2125
+
2126
+ CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
2127
+ ON session_events(agent_id, created_at DESC);
2128
+
2129
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_index
2130
+ ON session_events(session_id, event_index);
2131
+
2132
+ CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
2133
+ ON session_events(session_scope, agent_id, created_at DESC);
2134
+ `);
2108
2135
  await client.executeMultiple(`
2109
2136
  CREATE TABLE IF NOT EXISTS workspaces (
2110
2137
  id TEXT PRIMARY KEY,
@@ -237,6 +237,12 @@ var PLATFORM_PROCEDURES = [
237
237
  priority: "p0",
238
238
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
239
239
  },
240
+ {
241
+ title: "Code context first for repository orientation",
242
+ domain: "workflow",
243
+ priority: "p1",
244
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
245
+ },
240
246
  {
241
247
  title: "Commit discipline \u2014 never leave verified work floating",
242
248
  domain: "workflow",