engrm 0.4.36 → 0.4.37

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.
package/README.md CHANGED
@@ -288,6 +288,25 @@ How to use it:
288
288
  - `load_recall_item` opens an exact handoff, thread, chat, or memory key returned by the index
289
289
  - `repair_recall` is the repair step when continuity is still thin, hook-only, or under-captured
290
290
 
291
+ ### Explicit Save Protocol
292
+
293
+ When something should be remembered on purpose, do not wait for an end-of-session
294
+ digest if an explicit write is more appropriate.
295
+
296
+ Use:
297
+
298
+ - `save_observation`
299
+ - direct durable memory write for a bugfix, decision, discovery, pattern,
300
+ feature, or change
301
+ - `create_handoff` / `refresh_handoff`
302
+ - preserve the active thread for another device or a later session
303
+ - `capture_openclaw_content`
304
+ - save OpenClaw-style research, posting, outcomes, and next actions as
305
+ reusable memory
306
+
307
+ Automatic session digests are a safety net.
308
+ They are not the only path for preserving important work.
309
+
291
310
  ### Thin Tools, Thick Memory
292
311
 
293
312
  Engrm now has a real thin-tool layer, not just a plugin spec.
@@ -3225,7 +3225,7 @@ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync
3225
3225
  import { join as join3 } from "node:path";
3226
3226
  import { homedir } from "node:os";
3227
3227
  var STATE_PATH = join3(homedir(), ".engrm", "config-fingerprint.json");
3228
- var CLIENT_VERSION = "0.4.36";
3228
+ var CLIENT_VERSION = "0.4.37";
3229
3229
  function hashFile(filePath) {
3230
3230
  try {
3231
3231
  if (!existsSync3(filePath))
@@ -3087,7 +3087,7 @@ function buildBeacon(db, config, sessionId, metrics) {
3087
3087
  sentinel_used: valueSignals.security_findings_count > 0,
3088
3088
  risk_score: riskScore,
3089
3089
  stacks_detected: stacks,
3090
- client_version: "0.4.36",
3090
+ client_version: "0.4.37",
3091
3091
  context_observations_injected: metrics?.contextObsInjected ?? 0,
3092
3092
  context_total_available: metrics?.contextTotalAvailable ?? 0,
3093
3093
  recall_attempts: metrics?.recallAttempts ?? 0,
package/dist/server.js CHANGED
@@ -16392,11 +16392,13 @@ function mergeResults(ftsResults, vecResults, limit) {
16392
16392
  return Array.from(scores.entries()).map(([id, score]) => ({ id, score })).sort((a, b) => b.score - a.score).slice(0, limit);
16393
16393
  }
16394
16394
  function sanitizeFtsQuery(query) {
16395
- let safe = query.replace(/[{}()[\]^~*:]/g, " ");
16396
- safe = safe.replace(/\s+/g, " ").trim();
16397
- if (!safe)
16395
+ const normalized = String(query ?? "").normalize("NFKC").replace(/[^\p{L}\p{N}_\s]+/gu, " ").replace(/\s+/g, " ").trim();
16396
+ if (!normalized)
16397
+ return "";
16398
+ const terms = normalized.split(" ").map((term) => term.trim()).filter(Boolean).slice(0, 16);
16399
+ if (terms.length === 0)
16398
16400
  return "";
16399
- return safe;
16401
+ return terms.map((term) => `"${term}"`).join(" ");
16400
16402
  }
16401
16403
 
16402
16404
  // src/tools/recent-chat.ts
@@ -22871,9 +22873,9 @@ process.on("SIGTERM", () => {
22871
22873
  });
22872
22874
  var server = new McpServer({
22873
22875
  name: "engrm",
22874
- version: "0.4.36"
22876
+ version: "0.4.37"
22875
22877
  });
22876
- server.tool("save_observation", "Save an observation to memory", {
22878
+ server.tool("save_observation", "Directly save a durable memory item now. Use this when something should be remembered on purpose instead of waiting for an end-of-session digest.", {
22877
22879
  type: exports_external.enum([
22878
22880
  "bugfix",
22879
22881
  "discovery",
@@ -23170,7 +23172,7 @@ Findings: ${findingSummary}` : ""}`
23170
23172
  ]
23171
23173
  };
23172
23174
  });
23173
- server.tool("capture_openclaw_content", "Capture OpenClaw content, research, and follow-up work as durable memory. Best for preserving posted outcomes, discoveries, and next actions.", {
23175
+ server.tool("capture_openclaw_content", "Directly save OpenClaw content, research, and follow-up work as durable memory. Best for preserving posted outcomes, discoveries, and next actions during or right after the run.", {
23174
23176
  title: exports_external.string().optional().describe("Short content, campaign, or research title."),
23175
23177
  posted: exports_external.array(exports_external.string()).optional().describe("Concrete posted items or shipped content outcomes."),
23176
23178
  researched: exports_external.array(exports_external.string()).optional().describe("Research or discovery items worth retaining."),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "engrm",
3
- "version": "0.4.36",
3
+ "version": "0.4.37",
4
4
  "description": "Shared memory across devices, sessions, and agents, with thin MCP tools for durable capture and live continuity",
5
5
  "mcpName": "io.github.dr12hes/engrm",
6
6
  "type": "module",