@askexenow/exe-os 0.9.60 → 0.9.62

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 (106) hide show
  1. package/deploy/stack-manifests/v0.9.json +62 -13
  2. package/dist/bin/backfill-conversations.js +282 -7
  3. package/dist/bin/backfill-responses.js +282 -7
  4. package/dist/bin/backfill-vectors.js +119 -7
  5. package/dist/bin/cc-doctor.js +376 -0
  6. package/dist/bin/cleanup-stale-review-tasks.js +282 -7
  7. package/dist/bin/cli.js +455 -77
  8. package/dist/bin/customer-readiness.js +33 -0
  9. package/dist/bin/exe-agent-config.js +2 -2
  10. package/dist/bin/exe-agent.js +3 -3
  11. package/dist/bin/exe-assign.js +282 -7
  12. package/dist/bin/exe-boot.js +125 -13
  13. package/dist/bin/exe-call.js +3 -3
  14. package/dist/bin/exe-cloud.js +2 -2
  15. package/dist/bin/exe-dispatch.js +282 -7
  16. package/dist/bin/exe-doctor.js +119 -7
  17. package/dist/bin/exe-export-behaviors.js +282 -7
  18. package/dist/bin/exe-forget.js +336 -7
  19. package/dist/bin/exe-gateway.js +282 -7
  20. package/dist/bin/exe-heartbeat.js +284 -9
  21. package/dist/bin/exe-kill.js +282 -7
  22. package/dist/bin/exe-launch-agent.js +282 -7
  23. package/dist/bin/exe-link.js +121 -9
  24. package/dist/bin/exe-new-employee.js +50 -21
  25. package/dist/bin/exe-pending-messages.js +282 -7
  26. package/dist/bin/exe-pending-notifications.js +282 -7
  27. package/dist/bin/exe-pending-reviews.js +282 -7
  28. package/dist/bin/exe-rename.js +282 -7
  29. package/dist/bin/exe-review.js +282 -7
  30. package/dist/bin/exe-search.js +306 -8
  31. package/dist/bin/exe-session-cleanup.js +282 -7
  32. package/dist/bin/exe-settings.js +2 -2
  33. package/dist/bin/exe-start-codex.js +326 -21
  34. package/dist/bin/exe-start-opencode.js +304 -10
  35. package/dist/bin/exe-status.js +282 -7
  36. package/dist/bin/exe-team.js +282 -7
  37. package/dist/bin/git-sweep.js +282 -7
  38. package/dist/bin/graph-backfill.js +282 -7
  39. package/dist/bin/graph-export.js +282 -7
  40. package/dist/bin/install.js +58 -33
  41. package/dist/bin/intercom-check.js +282 -7
  42. package/dist/bin/pre-build-guard.js +98 -0
  43. package/dist/bin/scan-tasks.js +282 -7
  44. package/dist/bin/setup.js +122 -10
  45. package/dist/bin/shard-migrate.js +282 -7
  46. package/dist/bin/stack-update.js +79 -11
  47. package/dist/bin/update.js +2 -2
  48. package/dist/gateway/index.js +288 -13
  49. package/dist/hooks/bug-report-worker.js +282 -7
  50. package/dist/hooks/codex-stop-task-finalizer.js +282 -7
  51. package/dist/hooks/commit-complete.js +282 -7
  52. package/dist/hooks/error-recall.js +306 -8
  53. package/dist/hooks/exe-heartbeat-hook.js +2 -2
  54. package/dist/hooks/ingest-worker.js +2 -2
  55. package/dist/hooks/ingest.js +282 -7
  56. package/dist/hooks/instructions-loaded.js +282 -7
  57. package/dist/hooks/notification.js +282 -7
  58. package/dist/hooks/post-compact.js +282 -7
  59. package/dist/hooks/post-tool-combined.js +306 -8
  60. package/dist/hooks/pre-compact.js +282 -7
  61. package/dist/hooks/pre-tool-use.js +282 -7
  62. package/dist/hooks/prompt-submit.js +306 -8
  63. package/dist/hooks/session-end.js +282 -7
  64. package/dist/hooks/session-start.js +308 -10
  65. package/dist/hooks/stop.js +282 -7
  66. package/dist/hooks/subagent-stop.js +282 -7
  67. package/dist/hooks/summary-worker.js +125 -13
  68. package/dist/index.js +288 -13
  69. package/dist/lib/agent-config.js +2 -2
  70. package/dist/lib/cloud-sync.js +121 -9
  71. package/dist/lib/config.js +2 -2
  72. package/dist/lib/consolidation.js +2 -2
  73. package/dist/lib/database.js +115 -3
  74. package/dist/lib/db-daemon-client.js +2 -2
  75. package/dist/lib/db.js +115 -3
  76. package/dist/lib/device-registry.js +115 -3
  77. package/dist/lib/embedder.js +2 -2
  78. package/dist/lib/employee-templates.js +3 -3
  79. package/dist/lib/employees.js +2 -2
  80. package/dist/lib/exe-daemon-client.js +2 -2
  81. package/dist/lib/exe-daemon.js +339 -31
  82. package/dist/lib/hybrid-search.js +306 -8
  83. package/dist/lib/identity.js +2 -2
  84. package/dist/lib/license.js +2 -2
  85. package/dist/lib/messaging.js +2 -2
  86. package/dist/lib/reminders.js +2 -2
  87. package/dist/lib/schedules.js +119 -7
  88. package/dist/lib/skill-learning.js +2 -2
  89. package/dist/lib/store.js +282 -7
  90. package/dist/lib/task-router.js +2 -2
  91. package/dist/lib/tasks.js +2 -2
  92. package/dist/lib/tmux-routing.js +2 -2
  93. package/dist/lib/token-spend.js +2 -2
  94. package/dist/mcp/server.js +339 -31
  95. package/dist/mcp/tools/complete-reminder.js +2 -2
  96. package/dist/mcp/tools/create-reminder.js +2 -2
  97. package/dist/mcp/tools/create-task.js +2 -2
  98. package/dist/mcp/tools/deactivate-behavior.js +2 -2
  99. package/dist/mcp/tools/list-reminders.js +2 -2
  100. package/dist/mcp/tools/list-tasks.js +2 -2
  101. package/dist/mcp/tools/send-message.js +2 -2
  102. package/dist/mcp/tools/update-task.js +2 -2
  103. package/dist/runtime/index.js +282 -7
  104. package/dist/tui/App.js +290 -15
  105. package/package.json +3 -2
  106. package/stack.release.json +23 -7
@@ -562,8 +562,8 @@ var init_config = __esm({
562
562
  rerankerAutoTrigger: {
563
563
  enabled: true,
564
564
  broadQueryMinCardinality: 5e4,
565
- fetchTopK: 150,
566
- returnTopK: 5
565
+ fetchTopK: 200,
566
+ returnTopK: 20
567
567
  }
568
568
  },
569
569
  graphRagEnabled: true,
@@ -3095,7 +3095,7 @@ async function ensureSchema() {
3095
3095
  ON session_kills(agent_id);
3096
3096
  `);
3097
3097
  await client.execute(`
3098
- CREATE TABLE IF NOT EXISTS global_procedures (
3098
+ CREATE TABLE IF NOT EXISTS company_procedures (
3099
3099
  id TEXT PRIMARY KEY,
3100
3100
  title TEXT NOT NULL,
3101
3101
  content TEXT NOT NULL,
@@ -3106,6 +3106,73 @@ async function ensureSchema() {
3106
3106
  updated_at TEXT NOT NULL
3107
3107
  )
3108
3108
  `);
3109
+ const legacyProcedureObject = await client.execute({
3110
+ sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
3111
+ args: []
3112
+ });
3113
+ const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
3114
+ if (legacyProcedureType === "table") {
3115
+ await client.execute(`
3116
+ INSERT OR IGNORE INTO company_procedures
3117
+ (id, title, content, priority, domain, active, created_at, updated_at)
3118
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3119
+ FROM global_procedures
3120
+ `);
3121
+ await client.executeMultiple(`
3122
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
3123
+ AFTER INSERT ON global_procedures
3124
+ BEGIN
3125
+ INSERT OR IGNORE INTO company_procedures
3126
+ (id, title, content, priority, domain, active, created_at, updated_at)
3127
+ VALUES
3128
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3129
+ END;
3130
+
3131
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
3132
+ AFTER UPDATE ON global_procedures
3133
+ BEGIN
3134
+ UPDATE company_procedures
3135
+ SET title = NEW.title,
3136
+ content = NEW.content,
3137
+ priority = NEW.priority,
3138
+ domain = NEW.domain,
3139
+ active = NEW.active,
3140
+ created_at = NEW.created_at,
3141
+ updated_at = NEW.updated_at
3142
+ WHERE id = OLD.id;
3143
+ END;
3144
+ `);
3145
+ } else {
3146
+ await client.execute(`
3147
+ CREATE VIEW IF NOT EXISTS global_procedures AS
3148
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3149
+ FROM company_procedures
3150
+ `);
3151
+ await client.executeMultiple(`
3152
+ CREATE TRIGGER IF NOT EXISTS global_procedures_insert
3153
+ INSTEAD OF INSERT ON global_procedures
3154
+ BEGIN
3155
+ INSERT INTO company_procedures
3156
+ (id, title, content, priority, domain, active, created_at, updated_at)
3157
+ VALUES
3158
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3159
+ END;
3160
+
3161
+ CREATE TRIGGER IF NOT EXISTS global_procedures_update
3162
+ INSTEAD OF UPDATE ON global_procedures
3163
+ BEGIN
3164
+ UPDATE company_procedures
3165
+ SET title = NEW.title,
3166
+ content = NEW.content,
3167
+ priority = NEW.priority,
3168
+ domain = NEW.domain,
3169
+ active = NEW.active,
3170
+ created_at = NEW.created_at,
3171
+ updated_at = NEW.updated_at
3172
+ WHERE id = OLD.id;
3173
+ END;
3174
+ `);
3175
+ }
3109
3176
  await client.executeMultiple(`
3110
3177
  CREATE TABLE IF NOT EXISTS conversations (
3111
3178
  id TEXT PRIMARY KEY,
@@ -3245,6 +3312,51 @@ async function ensureSchema() {
3245
3312
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
3246
3313
  END;
3247
3314
  `);
3315
+ await client.executeMultiple(`
3316
+ CREATE TABLE IF NOT EXISTS memory_cards (
3317
+ id TEXT PRIMARY KEY,
3318
+ memory_id TEXT NOT NULL,
3319
+ agent_id TEXT NOT NULL,
3320
+ session_id TEXT NOT NULL,
3321
+ project_name TEXT,
3322
+ timestamp TEXT NOT NULL,
3323
+ card_type TEXT NOT NULL,
3324
+ subject TEXT,
3325
+ predicate TEXT,
3326
+ object TEXT,
3327
+ content TEXT NOT NULL,
3328
+ source_ref TEXT,
3329
+ confidence REAL DEFAULT 0.6,
3330
+ active INTEGER DEFAULT 1,
3331
+ created_at TEXT NOT NULL
3332
+ );
3333
+
3334
+ CREATE INDEX IF NOT EXISTS idx_memory_cards_agent
3335
+ ON memory_cards(agent_id, active, timestamp);
3336
+
3337
+ CREATE INDEX IF NOT EXISTS idx_memory_cards_memory
3338
+ ON memory_cards(memory_id);
3339
+
3340
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_cards_fts
3341
+ USING fts5(content, subject, predicate, object, content='memory_cards', content_rowid='rowid');
3342
+
3343
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ai AFTER INSERT ON memory_cards BEGIN
3344
+ INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
3345
+ VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
3346
+ END;
3347
+
3348
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ad AFTER DELETE ON memory_cards BEGIN
3349
+ INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
3350
+ VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
3351
+ END;
3352
+
3353
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_au AFTER UPDATE ON memory_cards BEGIN
3354
+ INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
3355
+ VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
3356
+ INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
3357
+ VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
3358
+ END;
3359
+ `);
3248
3360
  try {
3249
3361
  await client.execute({
3250
3362
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
@@ -7640,7 +7752,7 @@ var init_platform_procedures = __esm({
7640
7752
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
7641
7753
  domain: "tool-use",
7642
7754
  priority: "p1",
7643
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
7755
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
7644
7756
  }
7645
7757
  ];
7646
7758
  PLATFORM_PROCEDURE_TITLES = new Set(
@@ -7661,7 +7773,7 @@ import { randomUUID as randomUUID3 } from "crypto";
7661
7773
  async function loadGlobalProcedures() {
7662
7774
  const client = getClient();
7663
7775
  const result = await client.execute({
7664
- sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
7776
+ sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
7665
7777
  args: []
7666
7778
  });
7667
7779
  const allRows = result.rows;
@@ -7690,7 +7802,7 @@ async function storeGlobalProcedure(input) {
7690
7802
  const now = (/* @__PURE__ */ new Date()).toISOString();
7691
7803
  const client = getClient();
7692
7804
  await client.execute({
7693
- sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
7805
+ sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
7694
7806
  VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
7695
7807
  args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
7696
7808
  });
@@ -7701,7 +7813,7 @@ async function deactivateGlobalProcedure(id) {
7701
7813
  const now = (/* @__PURE__ */ new Date()).toISOString();
7702
7814
  const client = getClient();
7703
7815
  const result = await client.execute({
7704
- sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
7816
+ sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
7705
7817
  args: [now, id]
7706
7818
  });
7707
7819
  await loadGlobalProcedures();
@@ -7720,6 +7832,164 @@ ${p.content}`).join("\n\n");
7720
7832
  }
7721
7833
  });
7722
7834
 
7835
+ // src/lib/memory-cards.ts
7836
+ var memory_cards_exports = {};
7837
+ __export(memory_cards_exports, {
7838
+ extractMemoryCards: () => extractMemoryCards,
7839
+ insertMemoryCardsForBatch: () => insertMemoryCardsForBatch,
7840
+ searchMemoryCards: () => searchMemoryCards
7841
+ });
7842
+ import { createHash as createHash2 } from "crypto";
7843
+ function stableId(memoryId, type, content) {
7844
+ return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
7845
+ }
7846
+ function cleanText(text) {
7847
+ return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
7848
+ }
7849
+ function splitSentences(text) {
7850
+ return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
7851
+ }
7852
+ function inferCardType(sentence, toolName) {
7853
+ const lower = sentence.toLowerCase();
7854
+ if (toolName === "store_decision" || /\b(decided|decision|adr|approved|rejected)\b/.test(lower)) return "decision";
7855
+ if (/\b(prefers|preference|likes|dislikes|wants|doesn't want|does not want)\b/.test(lower)) return "preference";
7856
+ if (/\b(changed|updated|replaced|now|no longer|instead|supersedes)\b/.test(lower)) return "belief_update";
7857
+ if (toolName && ["Read", "Write", "Edit", "Bash"].includes(toolName)) return "code";
7858
+ if (/\b(meeting|deadline|shipped|launched|completed|failed|blocked|assigned|created)\b/.test(lower)) return "event";
7859
+ return "fact";
7860
+ }
7861
+ function extractSubject(sentence, agentId) {
7862
+ const explicit = sentence.match(/\b([A-Z][a-zA-Z0-9_-]{2,}(?:\s+[A-Z][a-zA-Z0-9_-]{2,})?)\b/);
7863
+ return explicit?.[1] ?? agentId;
7864
+ }
7865
+ function predicateFor(type) {
7866
+ switch (type) {
7867
+ case "preference":
7868
+ return "prefers";
7869
+ case "belief_update":
7870
+ return "updated";
7871
+ case "decision":
7872
+ return "decided";
7873
+ case "event":
7874
+ return "happened";
7875
+ case "code":
7876
+ return "implemented";
7877
+ default:
7878
+ return "states";
7879
+ }
7880
+ }
7881
+ function extractMemoryCards(row) {
7882
+ const sentences = splitSentences(row.raw_text);
7883
+ const cards = [];
7884
+ for (const sentence of sentences) {
7885
+ const type = inferCardType(sentence, row.tool_name);
7886
+ const subject = extractSubject(sentence, row.agent_id);
7887
+ const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
7888
+ cards.push({
7889
+ id: stableId(row.id, type, content),
7890
+ memory_id: row.id,
7891
+ agent_id: row.agent_id,
7892
+ session_id: row.session_id,
7893
+ project_name: row.project_name ?? null,
7894
+ timestamp: row.timestamp,
7895
+ card_type: type,
7896
+ subject,
7897
+ predicate: predicateFor(type),
7898
+ object: content,
7899
+ content,
7900
+ source_ref: row.id,
7901
+ confidence: type === "fact" ? 0.55 : 0.65
7902
+ });
7903
+ if (cards.length >= MAX_CARDS_PER_MEMORY) break;
7904
+ }
7905
+ return cards;
7906
+ }
7907
+ async function insertMemoryCardsForBatch(rows) {
7908
+ const cards = rows.flatMap(extractMemoryCards);
7909
+ if (cards.length === 0) return 0;
7910
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7911
+ const client = getClient();
7912
+ const stmts = cards.map((card) => ({
7913
+ sql: `INSERT OR IGNORE INTO memory_cards
7914
+ (id, memory_id, agent_id, session_id, project_name, timestamp, card_type,
7915
+ subject, predicate, object, content, source_ref, confidence, active, created_at)
7916
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)`,
7917
+ args: [
7918
+ card.id,
7919
+ card.memory_id,
7920
+ card.agent_id,
7921
+ card.session_id,
7922
+ card.project_name,
7923
+ card.timestamp,
7924
+ card.card_type,
7925
+ card.subject,
7926
+ card.predicate,
7927
+ card.object,
7928
+ card.content,
7929
+ card.source_ref,
7930
+ card.confidence,
7931
+ now
7932
+ ]
7933
+ }));
7934
+ await client.batch(stmts, "write");
7935
+ return cards.length;
7936
+ }
7937
+ function buildMatchExpr(queryText) {
7938
+ const terms = queryText.toLowerCase().split(/\s+/).filter((t) => t.length >= 3).map((t) => t.replace(/[^a-z0-9_]/g, "")).filter((t) => t.length >= 3).slice(0, 12);
7939
+ if (terms.length === 0) return null;
7940
+ return terms.map((t) => `${t}*`).join(terms.length >= 3 ? " AND " : " OR ");
7941
+ }
7942
+ async function searchMemoryCards(queryText, agentId, options) {
7943
+ const limit = options?.limit ?? 10;
7944
+ const matchExpr = buildMatchExpr(queryText);
7945
+ if (!matchExpr) return [];
7946
+ let sql = `SELECT c.id, c.memory_id, c.agent_id, c.session_id, c.project_name,
7947
+ c.timestamp, c.card_type, c.content, c.source_ref, c.confidence
7948
+ FROM memory_cards c
7949
+ JOIN memory_cards_fts fts ON c.rowid = fts.rowid
7950
+ WHERE memory_cards_fts MATCH ?
7951
+ AND c.agent_id = ?
7952
+ AND COALESCE(c.active, 1) = 1`;
7953
+ const args = [matchExpr, agentId];
7954
+ if (options?.projectName) {
7955
+ sql += ` AND c.project_name = ?`;
7956
+ args.push(options.projectName);
7957
+ }
7958
+ if (options?.since) {
7959
+ sql += ` AND c.timestamp >= ?`;
7960
+ args.push(options.since);
7961
+ }
7962
+ sql += ` ORDER BY rank LIMIT ?`;
7963
+ args.push(limit);
7964
+ const result = await getClient().execute({ sql, args });
7965
+ return result.rows.map((row) => ({
7966
+ id: `card:${String(row.id)}`,
7967
+ agent_id: String(row.agent_id),
7968
+ agent_role: "memory_card",
7969
+ session_id: String(row.session_id),
7970
+ timestamp: String(row.timestamp),
7971
+ tool_name: `memory_card:${String(row.card_type)}`,
7972
+ project_name: row.project_name == null ? "" : String(row.project_name),
7973
+ has_error: false,
7974
+ raw_text: `[${String(row.card_type)}] ${String(row.content)}
7975
+ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
7976
+ vector: [],
7977
+ importance: 6,
7978
+ status: "active",
7979
+ confidence: Number(row.confidence ?? 0.6),
7980
+ last_accessed: String(row.timestamp)
7981
+ }));
7982
+ }
7983
+ var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
7984
+ var init_memory_cards = __esm({
7985
+ "src/lib/memory-cards.ts"() {
7986
+ "use strict";
7987
+ init_database();
7988
+ MAX_CARDS_PER_MEMORY = 6;
7989
+ MAX_SENTENCE_CHARS = 360;
7990
+ }
7991
+ });
7992
+
7723
7993
  // src/lib/store.ts
7724
7994
  var store_exports = {};
7725
7995
  __export(store_exports, {
@@ -8058,6 +8328,11 @@ async function flushBatch() {
8058
8328
  const globalClient = getClient();
8059
8329
  const globalStmts = batch.map(buildStmt);
8060
8330
  await globalClient.batch(globalStmts, "write");
8331
+ try {
8332
+ const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
8333
+ await insertMemoryCardsForBatch2(batch);
8334
+ } catch {
8335
+ }
8061
8336
  schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
8062
8337
  _pendingRecords.splice(0, batch.length);
8063
8338
  try {
package/dist/bin/setup.js CHANGED
@@ -247,8 +247,8 @@ var init_config = __esm({
247
247
  rerankerAutoTrigger: {
248
248
  enabled: true,
249
249
  broadQueryMinCardinality: 5e4,
250
- fetchTopK: 150,
251
- returnTopK: 5
250
+ fetchTopK: 200,
251
+ returnTopK: 20
252
252
  }
253
253
  },
254
254
  graphRagEnabled: true,
@@ -3742,7 +3742,7 @@ async function ensureSchema() {
3742
3742
  ON session_kills(agent_id);
3743
3743
  `);
3744
3744
  await client.execute(`
3745
- CREATE TABLE IF NOT EXISTS global_procedures (
3745
+ CREATE TABLE IF NOT EXISTS company_procedures (
3746
3746
  id TEXT PRIMARY KEY,
3747
3747
  title TEXT NOT NULL,
3748
3748
  content TEXT NOT NULL,
@@ -3753,6 +3753,73 @@ async function ensureSchema() {
3753
3753
  updated_at TEXT NOT NULL
3754
3754
  )
3755
3755
  `);
3756
+ const legacyProcedureObject = await client.execute({
3757
+ sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
3758
+ args: []
3759
+ });
3760
+ const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
3761
+ if (legacyProcedureType === "table") {
3762
+ await client.execute(`
3763
+ INSERT OR IGNORE INTO company_procedures
3764
+ (id, title, content, priority, domain, active, created_at, updated_at)
3765
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3766
+ FROM global_procedures
3767
+ `);
3768
+ await client.executeMultiple(`
3769
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
3770
+ AFTER INSERT ON global_procedures
3771
+ BEGIN
3772
+ INSERT OR IGNORE INTO company_procedures
3773
+ (id, title, content, priority, domain, active, created_at, updated_at)
3774
+ VALUES
3775
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3776
+ END;
3777
+
3778
+ CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
3779
+ AFTER UPDATE ON global_procedures
3780
+ BEGIN
3781
+ UPDATE company_procedures
3782
+ SET title = NEW.title,
3783
+ content = NEW.content,
3784
+ priority = NEW.priority,
3785
+ domain = NEW.domain,
3786
+ active = NEW.active,
3787
+ created_at = NEW.created_at,
3788
+ updated_at = NEW.updated_at
3789
+ WHERE id = OLD.id;
3790
+ END;
3791
+ `);
3792
+ } else {
3793
+ await client.execute(`
3794
+ CREATE VIEW IF NOT EXISTS global_procedures AS
3795
+ SELECT id, title, content, priority, domain, active, created_at, updated_at
3796
+ FROM company_procedures
3797
+ `);
3798
+ await client.executeMultiple(`
3799
+ CREATE TRIGGER IF NOT EXISTS global_procedures_insert
3800
+ INSTEAD OF INSERT ON global_procedures
3801
+ BEGIN
3802
+ INSERT INTO company_procedures
3803
+ (id, title, content, priority, domain, active, created_at, updated_at)
3804
+ VALUES
3805
+ (NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
3806
+ END;
3807
+
3808
+ CREATE TRIGGER IF NOT EXISTS global_procedures_update
3809
+ INSTEAD OF UPDATE ON global_procedures
3810
+ BEGIN
3811
+ UPDATE company_procedures
3812
+ SET title = NEW.title,
3813
+ content = NEW.content,
3814
+ priority = NEW.priority,
3815
+ domain = NEW.domain,
3816
+ active = NEW.active,
3817
+ created_at = NEW.created_at,
3818
+ updated_at = NEW.updated_at
3819
+ WHERE id = OLD.id;
3820
+ END;
3821
+ `);
3822
+ }
3756
3823
  await client.executeMultiple(`
3757
3824
  CREATE TABLE IF NOT EXISTS conversations (
3758
3825
  id TEXT PRIMARY KEY,
@@ -3892,6 +3959,51 @@ async function ensureSchema() {
3892
3959
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
3893
3960
  END;
3894
3961
  `);
3962
+ await client.executeMultiple(`
3963
+ CREATE TABLE IF NOT EXISTS memory_cards (
3964
+ id TEXT PRIMARY KEY,
3965
+ memory_id TEXT NOT NULL,
3966
+ agent_id TEXT NOT NULL,
3967
+ session_id TEXT NOT NULL,
3968
+ project_name TEXT,
3969
+ timestamp TEXT NOT NULL,
3970
+ card_type TEXT NOT NULL,
3971
+ subject TEXT,
3972
+ predicate TEXT,
3973
+ object TEXT,
3974
+ content TEXT NOT NULL,
3975
+ source_ref TEXT,
3976
+ confidence REAL DEFAULT 0.6,
3977
+ active INTEGER DEFAULT 1,
3978
+ created_at TEXT NOT NULL
3979
+ );
3980
+
3981
+ CREATE INDEX IF NOT EXISTS idx_memory_cards_agent
3982
+ ON memory_cards(agent_id, active, timestamp);
3983
+
3984
+ CREATE INDEX IF NOT EXISTS idx_memory_cards_memory
3985
+ ON memory_cards(memory_id);
3986
+
3987
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_cards_fts
3988
+ USING fts5(content, subject, predicate, object, content='memory_cards', content_rowid='rowid');
3989
+
3990
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ai AFTER INSERT ON memory_cards BEGIN
3991
+ INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
3992
+ VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
3993
+ END;
3994
+
3995
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ad AFTER DELETE ON memory_cards BEGIN
3996
+ INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
3997
+ VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
3998
+ END;
3999
+
4000
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_au AFTER UPDATE ON memory_cards BEGIN
4001
+ INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
4002
+ VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
4003
+ INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
4004
+ VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
4005
+ END;
4006
+ `);
3895
4007
  try {
3896
4008
  await client.execute({
3897
4009
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
@@ -4815,12 +4927,12 @@ async function cloudSync(config) {
4815
4927
  try {
4816
4928
  await cloudPushGlobalProcedures(config);
4817
4929
  } catch (err) {
4818
- logError(`[cloud-sync] Global procedures push: ${err instanceof Error ? err.message : String(err)}`);
4930
+ logError(`[cloud-sync] Company procedures push: ${err instanceof Error ? err.message : String(err)}`);
4819
4931
  }
4820
4932
  try {
4821
4933
  await cloudPullGlobalProcedures(config);
4822
4934
  } catch (err) {
4823
- logError(`[cloud-sync] Global procedures pull: ${err instanceof Error ? err.message : String(err)}`);
4935
+ logError(`[cloud-sync] Company procedures pull: ${err instanceof Error ? err.message : String(err)}`);
4824
4936
  }
4825
4937
  const countRows = async (sql) => {
4826
4938
  try {
@@ -5229,12 +5341,12 @@ async function cloudPullBlob(route, config) {
5229
5341
  }
5230
5342
  async function cloudPushGlobalProcedures(config) {
5231
5343
  const client = getClient();
5232
- const result = await client.execute("SELECT * FROM global_procedures LIMIT 1000");
5344
+ const result = await client.execute("SELECT * FROM company_procedures LIMIT 1000");
5233
5345
  const rows = result.rows;
5234
5346
  const { ok } = await cloudPushBlob(
5235
5347
  "/sync/push-global-procedures",
5236
5348
  rows,
5237
- "last_global_procedures_push_version",
5349
+ "last_company_procedures_push_version",
5238
5350
  config
5239
5351
  );
5240
5352
  return ok;
@@ -5247,7 +5359,7 @@ async function cloudPullGlobalProcedures(config) {
5247
5359
  if (!remoteProcs || remoteProcs.length === 0) return { pulled: 0 };
5248
5360
  const client = getClient();
5249
5361
  const stmts = remoteProcs.map((p) => ({
5250
- sql: `INSERT INTO global_procedures
5362
+ sql: `INSERT INTO company_procedures
5251
5363
  (id, title, content, priority, domain, active, created_at, updated_at)
5252
5364
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
5253
5365
  ON CONFLICT(id) DO UPDATE SET
@@ -5257,7 +5369,7 @@ async function cloudPullGlobalProcedures(config) {
5257
5369
  domain = excluded.domain,
5258
5370
  active = excluded.active,
5259
5371
  updated_at = excluded.updated_at
5260
- WHERE excluded.updated_at > global_procedures.updated_at`,
5372
+ WHERE excluded.updated_at > company_procedures.updated_at`,
5261
5373
  args: [
5262
5374
  sqlSafe(p.id),
5263
5375
  sqlSafe(p.title),
@@ -5820,7 +5932,7 @@ var init_platform_procedures = __esm({
5820
5932
  title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
5821
5933
  domain: "tool-use",
5822
5934
  priority: "p1",
5823
- content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
5935
+ content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
5824
5936
  }
5825
5937
  ];
5826
5938
  PLATFORM_PROCEDURE_TITLES = new Set(