@remnic/plugin-openclaw 9.3.729 → 9.3.730

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/dist/index.js CHANGED
@@ -352,6 +352,14 @@ function registerTools(api, orchestrator) {
352
352
  source === "memory_store" ? "legacy_tool" : "strict_explicit"
353
353
  );
354
354
  const result = await persistExplicitCapture(orchestrator, candidate, source);
355
+ if (result.tombstoneBlocked) {
356
+ orchestrator.requestQmdMaintenanceForTool(maintenanceReason);
357
+ return toolResult(
358
+ `Memory queued for review (tombstone-blocked): ${result.id}${candidate.namespace ? ` (namespace: ${candidate.namespace})` : ""} \u2014 no active copy was created.
359
+
360
+ Content: ${candidate.content}`
361
+ );
362
+ }
355
363
  if (!result.duplicateOf && orchestrator.config.queryAwareIndexingEnabled && indexesExist(orchestrator.config.memoryDir)) {
356
364
  const storage = await orchestrator.getStorage(candidate.namespace);
357
365
  const mem = await storage.getMemoryById(result.id).catch(() => null);
@@ -1487,24 +1495,35 @@ NOTE: You did not provide sessionKey; under concurrency this may not match your
1487
1495
  }
1488
1496
  const outputMemoryIds = [];
1489
1497
  let appliedMessage = "";
1498
+ let queuedForReview = false;
1490
1499
  switch (action) {
1491
1500
  case "store_episode": {
1492
- const createdId = await storage.writeMemory(normalizedCategory ?? "fact", contentValue, {
1501
+ const { id: createdId, tombstoneBlocked } = await storage.writeMemory(normalizedCategory ?? "fact", contentValue, {
1493
1502
  actor: "tool.memory_action_apply",
1494
1503
  source: "memory_action_apply",
1495
1504
  memoryKind: "episode"
1496
1505
  });
1497
1506
  outputMemoryIds.push(createdId);
1498
- appliedMessage = `Applied memory action: action=${action}, memoryId=${createdId}, namespace=${ns}.`;
1507
+ if (tombstoneBlocked) {
1508
+ queuedForReview = true;
1509
+ appliedMessage = `Memory action queued for review: action=${action}, memoryId=${createdId}, namespace=${ns} (tombstone-blocked \u2014 no active copy created).`;
1510
+ } else {
1511
+ appliedMessage = `Applied memory action: action=${action}, memoryId=${createdId}, namespace=${ns}.`;
1512
+ }
1499
1513
  break;
1500
1514
  }
1501
1515
  case "store_note": {
1502
- const createdId = await storage.writeMemory(normalizedCategory ?? "fact", contentValue, {
1516
+ const { id: createdId, tombstoneBlocked } = await storage.writeMemory(normalizedCategory ?? "fact", contentValue, {
1503
1517
  actor: "tool.memory_action_apply",
1504
1518
  source: "memory_action_apply"
1505
1519
  });
1506
1520
  outputMemoryIds.push(createdId);
1507
- appliedMessage = `Applied memory action: action=${action}, memoryId=${createdId}, namespace=${ns}.`;
1521
+ if (tombstoneBlocked) {
1522
+ queuedForReview = true;
1523
+ appliedMessage = `Memory action queued for review: action=${action}, memoryId=${createdId}, namespace=${ns} (tombstone-blocked \u2014 no active copy created).`;
1524
+ } else {
1525
+ appliedMessage = `Applied memory action: action=${action}, memoryId=${createdId}, namespace=${ns}.`;
1526
+ }
1508
1527
  break;
1509
1528
  }
1510
1529
  case "update_note": {
@@ -1548,13 +1567,18 @@ NOTE: You did not provide sessionKey; under concurrency this may not match your
1548
1567
  break;
1549
1568
  }
1550
1569
  case "summarize_node": {
1551
- const createdId = await storage.writeMemory(normalizedCategory ?? "fact", contentValue, {
1570
+ const { id: createdId, tombstoneBlocked } = await storage.writeMemory(normalizedCategory ?? "fact", contentValue, {
1552
1571
  actor: "tool.memory_action_apply",
1553
1572
  source: "memory_action_apply",
1554
1573
  sourceMemoryId: memoryIdValue
1555
1574
  });
1556
1575
  outputMemoryIds.push(createdId);
1557
- appliedMessage = `Applied memory action: action=${action}, memoryId=${createdId}, namespace=${ns}.`;
1576
+ if (tombstoneBlocked) {
1577
+ queuedForReview = true;
1578
+ appliedMessage = `Memory action queued for review: action=${action}, memoryId=${createdId}, namespace=${ns} (tombstone-blocked \u2014 no active copy created).`;
1579
+ } else {
1580
+ appliedMessage = `Applied memory action: action=${action}, memoryId=${createdId}, namespace=${ns}.`;
1581
+ }
1558
1582
  break;
1559
1583
  }
1560
1584
  case "discard": {
@@ -1621,10 +1645,18 @@ NOTE: You did not provide sessionKey; under concurrency this may not match your
1621
1645
  orchestrator.requestQmdMaintenanceForTool(`memory_action_apply.${action}`);
1622
1646
  const wrote = await orchestrator.appendMemoryActionEvent({
1623
1647
  ...structuredEvent,
1624
- outcome: "applied",
1625
- status: "applied",
1648
+ // #1645 (review thread Yhp): a tombstone-blocked write is NOT an
1649
+ // active application — record it as skipped with the blocked id so an
1650
+ // agent action that re-stores retired content is not reported as a
1651
+ // successful active write (recall will not use it).
1652
+ outcome: queuedForReview ? "skipped" : "applied",
1653
+ // #1645 (review thread yGr): status must agree with outcome — a
1654
+ // blocked write is not "applied"; "rejected" reflects that the
1655
+ // tombstone gate refused the active write (row is pending_review).
1656
+ status: queuedForReview ? "rejected" : "applied",
1626
1657
  dryRun: false,
1627
- outputMemoryIds
1658
+ outputMemoryIds,
1659
+ ...queuedForReview ? { reason: "tombstone-blocked: write landed pending_review, no active copy created" } : {}
1628
1660
  });
1629
1661
  if (!wrote) {
1630
1662
  return toolResult(`${appliedMessage} Telemetry write failed (fail-open).`);
@@ -1894,7 +1926,7 @@ Best for:
1894
1926
  return toolResult(`Memory not found in ${srcNs}: ${memoryId}`);
1895
1927
  }
1896
1928
  const dst = await orchestrator.getStorage(dstNs);
1897
- const newId = await dst.writeMemory(mem.frontmatter.category, mem.content, {
1929
+ const { id: newId, tombstoneBlocked } = await dst.writeMemory(mem.frontmatter.category, mem.content, {
1898
1930
  confidence: mem.frontmatter.confidence,
1899
1931
  tags: Array.from(/* @__PURE__ */ new Set([...mem.frontmatter.tags ?? [], "promoted", `promotedFrom:${srcNs}:${memoryId}`, ...note ? [`note:${note}`] : []])),
1900
1932
  entityRef: mem.frontmatter.entityRef,
@@ -1903,6 +1935,11 @@ Best for:
1903
1935
  supersedes: mem.frontmatter.supersedes,
1904
1936
  links: mem.frontmatter.links
1905
1937
  });
1938
+ if (tombstoneBlocked) {
1939
+ return toolResult(
1940
+ `Promotion of ${srcNs}:${memoryId} \u2192 ${dstNs}:${newId} is queued for review (tombstone-blocked): no active promoted copy was created.`
1941
+ );
1942
+ }
1906
1943
  if (orchestrator.config.queryAwareIndexingEnabled && indexesExist(orchestrator.config.memoryDir)) {
1907
1944
  const promoted = await dst.getMemoryById(newId).catch(() => null);
1908
1945
  if (promoted?.path && promoted.frontmatter?.created) {
@@ -3442,7 +3479,7 @@ async function syncDreamSurfaceEntries(params) {
3442
3479
  };
3443
3480
  const existing = findSurfaceMemoryByAttribute(memories, DREAM_ENTRY_ID_KEY, entry.id);
3444
3481
  if (!existing) {
3445
- const memoryId = await storage.writeMemory("moment", content, {
3482
+ const { id: memoryId } = await storage.writeMemory("moment", content, {
3446
3483
  confidence: 0.85,
3447
3484
  tags,
3448
3485
  source: "dreams.md",
@@ -3501,7 +3538,7 @@ async function syncHeartbeatSurfaceEntries(params) {
3501
3538
  };
3502
3539
  const existing = findSurfaceMemoryByAttribute(memories, HEARTBEAT_ENTRY_ID_KEY, entry.id) ?? findUniqueSurfaceMemoryBySlug(memories, HEARTBEAT_SURFACE_TYPE, entry.slug);
3503
3540
  if (!existing) {
3504
- const memoryId = await storage.writeMemory("principle", content, {
3541
+ const { id: memoryId } = await storage.writeMemory("principle", content, {
3505
3542
  confidence: 0.95,
3506
3543
  tags,
3507
3544
  source: "heartbeat.md",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-remnic",
3
3
  "name": "Remnic OpenClaw Plugin",
4
- "version": "9.3.729",
4
+ "version": "9.3.730",
5
5
  "kind": "memory",
6
6
  "description": "Local semantic memory for OpenClaw with bundled Remnic core runtime. Requires plugins.slots.memory set to this plugin id for hooks to fire.",
7
7
  "setup": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/plugin-openclaw",
3
- "version": "9.3.729",
3
+ "version": "9.3.730",
4
4
  "description": "OpenClaw adapter for Remnic memory with bundled @remnic/core runtime",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,7 @@
72
72
  "dependencies": {
73
73
  "@sinclair/typebox": "^0.34.0",
74
74
  "openai": "^6.0.0",
75
- "@remnic/core": "^9.3.729"
75
+ "@remnic/core": "^9.3.730"
76
76
  },
77
77
  "peerDependencies": {
78
78
  "openclaw": ">=2026.4.1 || 2026.4.7-1 || 2026.4.9-beta.1 || 2026.4.11-beta.1 || 2026.4.12-beta.1 || 2026.4.14-beta.1 || 2026.4.15-beta.1 || 2026.4.15-beta.2 || 2026.4.19-beta.1 || 2026.4.19-beta.2 || 2026.4.20-beta.1 || 2026.4.20-beta.2 || 2026.4.22-beta.1 || 2026.4.23-beta.1 || 2026.4.23-beta.2 || 2026.4.23-beta.3 || 2026.4.23-beta.4 || 2026.4.23-beta.5 || 2026.4.23-beta.6 || 2026.4.24-beta.1 || 2026.4.24-beta.2 || 2026.4.24-beta.3 || 2026.4.24-beta.4 || 2026.4.24-beta.5 || 2026.4.24-beta.6 || 2026.4.25-beta.1 || 2026.4.25-beta.2 || 2026.4.25-beta.3 || 2026.4.25-beta.4 || 2026.4.25-beta.5 || 2026.4.25-beta.6 || 2026.4.25-beta.7 || 2026.4.25-beta.8 || 2026.4.25-beta.9 || 2026.4.25-beta.10 || 2026.4.25-beta.11 || 2026.4.26-beta.1 || 2026.4.27-beta.1 || 2026.4.29-beta.1 || 2026.4.29-beta.2 || 2026.4.29-beta.3 || 2026.4.29-beta.4 || 2026.4.30-beta.1 || 2026.5.2-beta.1 || 2026.5.2-beta.2 || 2026.5.2-beta.3 || 2026.5.3-beta.1 || 2026.5.3-beta.2 || 2026.5.3-beta.3 || 2026.5.3-beta.4 || 2026.5.3-1 || 2026.5.4-beta.1 || 2026.5.4-beta.2 || 2026.5.4-beta.3 || 2026.5.5-beta.1 || 2026.5.5-beta.2 || 2026.5.6-beta.1 || 2026.5.7-beta.1 || 2026.5.9-beta.1 || 2026.5.10-beta.1 || 2026.5.10-beta.2 || 2026.5.10-beta.3 || 2026.5.10-beta.4 || 2026.5.10-beta.5 || 2026.5.10-beta.6 || 2026.5.12-beta.1 || 2026.5.12-beta.2 || 2026.5.12-beta.3 || 2026.5.12-beta.4 || 2026.5.12-beta.5 || 2026.5.12-beta.6 || 2026.5.12-beta.7 || 2026.5.12-beta.8 || 2026.5.14-beta.1 || 2026.5.14-beta.2 || 2026.5.16-beta.1 || 2026.5.16-beta.2 || 2026.5.16-beta.3 || 2026.5.16-beta.4 || 2026.5.16-beta.5 || 2026.5.16-beta.6 || 2026.5.16-beta.7 || 2026.5.18-beta.1 || 2026.5.19-alpha.1 || 2026.5.19-beta.1 || 2026.5.19-beta.2 || 2026.5.20-beta.1 || 2026.5.20-beta.2 || 2026.5.21-alpha.1 || 2026.5.21-beta.1 || 2026.5.22-beta.1 || 2026.5.23-alpha.1 || 2026.5.24-alpha.1 || 2026.5.24-beta.1 || 2026.5.24-beta.2 || 2026.5.25-alpha.1 || 2026.5.25-alpha.2 || 2026.5.25-beta.1 || 2026.5.26-beta.1 || 2026.5.26-beta.2 || 2026.5.27-alpha.1 || 2026.5.27-beta.1 || 2026.5.28-alpha.1 || 2026.5.28-beta.1 || 2026.5.28-beta.2 || 2026.5.28-beta.3 || 2026.5.28-beta.4 || 2026.5.29-alpha.1 || 2026.5.30-beta.1 || 2026.5.30-beta.2 || 2026.5.31-alpha.1 || 2026.5.31-beta.1 || 2026.5.31-beta.2 || 2026.5.31-beta.3 || 2026.5.31-beta.4 || 2026.6.1-alpha.1 || 2026.6.1-alpha.2 || 2026.6.1-alpha.3 || 2026.6.1-beta.1 || 2026.6.1-beta.2 || 2026.6.1-beta.3 || 2026.6.2-alpha.1 || 2026.6.2-alpha.2 || 2026.6.2-beta.1 || 2026.6.3-alpha.1 || 2026.6.4-alpha.1 || 2026.6.5-alpha.1 || 2026.6.5-alpha.2 || 2026.6.5-beta.1 || 2026.6.5-beta.2 || 2026.6.5-beta.3 || 2026.6.5-beta.5 || 2026.6.5-beta.6 || 2026.6.6-alpha.1 || 2026.6.6-beta.2 || 2026.6.6 || 2026.6.7-beta.1 || 2026.6.8-beta.1 || 2026.6.8-beta.2 || 2026.6.9-beta.1 || 2026.6.10-beta.1 || 2026.6.10-beta.2 || 2026.6.11-beta.1"
@@ -82,7 +82,7 @@
82
82
  "acorn": "^8.16.0",
83
83
  "tsup": "^8.5.1",
84
84
  "typescript": "^5.9.3",
85
- "@remnic/core": "^9.3.729"
85
+ "@remnic/core": "^9.3.730"
86
86
  },
87
87
  "license": "MIT",
88
88
  "repository": {