@joshuaswarren/openclaw-engram 8.3.68 → 8.3.69

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
@@ -10587,9 +10587,16 @@ function recencyWeight(frontmatter, nowMs) {
10587
10587
  return clamp01(1 - ageDays / 90);
10588
10588
  }
10589
10589
  function feedbackWeight(signals) {
10590
- const raw = signals?.feedbackScore ?? 0;
10590
+ const raw = (signals?.feedbackScore ?? 0) + (signals?.actionPriorScore ?? 0);
10591
10591
  return clamp01((raw + 1) / 2);
10592
10592
  }
10593
+ function boundedFeedbackScore(signals) {
10594
+ const raw = (signals?.feedbackScore ?? 0) + (signals?.actionPriorScore ?? 0);
10595
+ if (!Number.isFinite(raw)) return 0;
10596
+ if (raw < -1) return -1;
10597
+ if (raw > 1) return 1;
10598
+ return raw;
10599
+ }
10593
10600
  function isProtectedMemory(frontmatter, policy) {
10594
10601
  return frontmatter.policyClass === "protected" || policy.protectedCategories.includes(frontmatter.category);
10595
10602
  }
@@ -10619,7 +10626,7 @@ function computeDecay(memory, now, signals) {
10619
10626
  const ageRisk = clamp01(ageDays / 180);
10620
10627
  const staleAccessRisk = clamp01(staleAccessDays / 120);
10621
10628
  const confidenceRisk = 1 - confidenceTierWeight(frontmatter);
10622
- const feedbackRisk = clamp01(((signals?.feedbackScore ?? 0) * -1 + 1) / 2);
10629
+ const feedbackRisk = clamp01((boundedFeedbackScore(signals) * -1 + 1) / 2);
10623
10630
  const heat = computeHeat(memory, now, signals);
10624
10631
  const score = ageRisk * 0.3 + staleAccessRisk * 0.25 + confidenceRisk * 0.2 + feedbackRisk * 0.1 + (1 - heat) * 0.15;
10625
10632
  return clamp01(score);
@@ -11981,6 +11988,7 @@ var CompoundingEngine = class {
11981
11988
  this.identityAuditWeeklyDir = path23.join(config.memoryDir, "identity", "audits", "weekly");
11982
11989
  this.identityAuditMonthlyDir = path23.join(config.memoryDir, "identity", "audits", "monthly");
11983
11990
  this.identityImprovementLoopsPath = path23.join(config.memoryDir, "identity", "improvement-loops.md");
11991
+ this.memoryActionEventsPath = path23.join(config.memoryDir, "state", "memory-actions.jsonl");
11984
11992
  }
11985
11993
  weeklyDir;
11986
11994
  mistakesPath;
@@ -11990,6 +11998,7 @@ var CompoundingEngine = class {
11990
11998
  identityAuditWeeklyDir;
11991
11999
  identityAuditMonthlyDir;
11992
12000
  identityImprovementLoopsPath;
12001
+ memoryActionEventsPath;
11993
12002
  async ensureDirs() {
11994
12003
  await mkdir16(this.weeklyDir, { recursive: true });
11995
12004
  await mkdir16(path23.dirname(this.mistakesPath), { recursive: true });
@@ -11998,7 +12007,8 @@ var CompoundingEngine = class {
11998
12007
  await this.ensureDirs();
11999
12008
  const weekId = opts?.weekId ?? isoWeekId(/* @__PURE__ */ new Date());
12000
12009
  const entries = await this.readFeedbackEntriesForWeek(weekId);
12001
- const mistakes = this.buildMistakes(entries);
12010
+ const actionPatterns = await this.readActionFailurePatternsForWeek(weekId);
12011
+ const mistakes = this.buildMistakes(entries, actionPatterns);
12002
12012
  const continuity = this.config.continuityAuditEnabled ? await this.readContinuityAuditReferences(weekId) : { monthId: monthIdFromIsoWeek(weekId), weeklyPath: null, monthlyPath: null };
12003
12013
  const reportPath = path23.join(this.weeklyDir, `${weekId}.md`);
12004
12014
  const md = this.formatWeeklyReport(weekId, entries, mistakes.patterns, continuity);
@@ -12114,7 +12124,34 @@ var CompoundingEngine = class {
12114
12124
  }
12115
12125
  return out;
12116
12126
  }
12117
- buildMistakes(entries) {
12127
+ async readActionFailurePatternsForWeek(weekId) {
12128
+ const out = [];
12129
+ try {
12130
+ const raw = await readFile16(this.memoryActionEventsPath, "utf-8");
12131
+ const lines = raw.split("\n");
12132
+ for (const line of lines) {
12133
+ if (!line.trim()) continue;
12134
+ try {
12135
+ const parsed = JSON.parse(line);
12136
+ if (typeof parsed.timestamp !== "string" || typeof parsed.action !== "string") continue;
12137
+ const ts = new Date(parsed.timestamp);
12138
+ if (!Number.isFinite(ts.getTime()) || isoWeekId(ts) !== weekId) continue;
12139
+ const policy = parsed.policyDecision === "deny" || parsed.policyDecision === "defer" ? parsed.policyDecision : null;
12140
+ const failed = parsed.outcome === "failed" || parsed.outcome === "skipped";
12141
+ if (!failed && policy === null) continue;
12142
+ const ns = typeof parsed.namespace === "string" && parsed.namespace.length > 0 ? parsed.namespace : "default";
12143
+ const suffix = typeof parsed.reason === "string" && parsed.reason.trim().length > 0 ? ` - ${parsed.reason.trim().slice(0, 140)}` : "";
12144
+ out.push(
12145
+ `memory-action/${ns}: ${parsed.action} ${parsed.outcome ?? "unknown"}${policy ? `/${policy}` : ""}${suffix}`
12146
+ );
12147
+ } catch {
12148
+ }
12149
+ }
12150
+ } catch {
12151
+ }
12152
+ return out;
12153
+ }
12154
+ buildMistakes(entries, actionPatterns = []) {
12118
12155
  const patterns = [];
12119
12156
  for (const e of entries) {
12120
12157
  if (e.learning && e.learning.trim().length > 0) {
@@ -12125,6 +12162,7 @@ var CompoundingEngine = class {
12125
12162
  patterns.push(`${e.agent}: ${e.reason.trim()}`.slice(0, 240));
12126
12163
  }
12127
12164
  }
12165
+ patterns.push(...actionPatterns);
12128
12166
  const uniq = Array.from(new Set(patterns)).slice(0, 500);
12129
12167
  return { updatedAt: (/* @__PURE__ */ new Date()).toISOString(), patterns: uniq };
12130
12168
  }
@@ -15591,6 +15629,58 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
15591
15629
  return null;
15592
15630
  }
15593
15631
  }
15632
+ actionOutcomePriorDelta(event) {
15633
+ if (event.outcome === "failed") return -0.3;
15634
+ if (event.policyDecision === "deny") return -0.22;
15635
+ if (event.policyDecision === "defer") return -0.14;
15636
+ if (event.outcome === "skipped") return -0.1;
15637
+ if (event.outcome !== "applied") return 0;
15638
+ switch (event.action) {
15639
+ case "store_episode":
15640
+ case "store_note":
15641
+ case "update_note":
15642
+ return 0.08;
15643
+ case "create_artifact":
15644
+ case "summarize_node":
15645
+ case "link_graph":
15646
+ return 0.04;
15647
+ case "discard":
15648
+ return -0.03;
15649
+ default:
15650
+ return 0;
15651
+ }
15652
+ }
15653
+ async buildLifecycleActionPriors() {
15654
+ const events = await this.storage.readMemoryActionEvents(1200);
15655
+ if (events.length === 0) return /* @__PURE__ */ new Map();
15656
+ const nowMs = Date.now();
15657
+ const windowMs = 14 * 24 * 60 * 60 * 1e3;
15658
+ const byMemory = /* @__PURE__ */ new Map();
15659
+ for (const event of events) {
15660
+ if (typeof event.memoryId !== "string" || event.memoryId.trim().length === 0) continue;
15661
+ const ts = Date.parse(event.timestamp);
15662
+ if (!Number.isFinite(ts)) continue;
15663
+ const ageMs = nowMs - ts;
15664
+ if (ageMs < 0 || ageMs > windowMs) continue;
15665
+ const delta = this.actionOutcomePriorDelta(event);
15666
+ if (delta === 0) continue;
15667
+ const recencyWeight2 = Math.max(0.2, 1 - ageMs / windowMs);
15668
+ const list = byMemory.get(event.memoryId) ?? [];
15669
+ if (list.length >= 8) list.shift();
15670
+ list.push({ weightedDelta: delta * recencyWeight2, weight: recencyWeight2 });
15671
+ byMemory.set(event.memoryId, list);
15672
+ }
15673
+ const out = /* @__PURE__ */ new Map();
15674
+ for (const [memoryId, deltas] of byMemory.entries()) {
15675
+ if (deltas.length === 0) continue;
15676
+ const weightedSum = deltas.reduce((sum, item) => sum + item.weightedDelta, 0);
15677
+ const weightTotal = deltas.reduce((sum, item) => sum + item.weight, 0);
15678
+ if (weightTotal <= 0) continue;
15679
+ const score = weightedSum / weightTotal;
15680
+ out.set(memoryId, Math.max(-0.25, Math.min(0.15, score)));
15681
+ }
15682
+ return out;
15683
+ }
15594
15684
  async runLifecyclePolicyPass(allMemories) {
15595
15685
  const now = /* @__PURE__ */ new Date();
15596
15686
  const nowIso = now.toISOString();
@@ -15611,13 +15701,16 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
15611
15701
  archiveDecayThreshold: this.config.lifecycleArchiveDecayThreshold,
15612
15702
  protectedCategories: this.config.lifecycleProtectedCategories
15613
15703
  };
15704
+ const actionPriors = await this.buildLifecycleActionPriors();
15614
15705
  for (const memory of allMemories) {
15615
15706
  if (memory.frontmatter.status === "superseded") {
15616
15707
  continue;
15617
15708
  }
15618
15709
  evaluatedCount += 1;
15619
15710
  const currentState = resolveLifecycleState(memory.frontmatter);
15620
- const decision = decideLifecycleTransition(memory, policy, now);
15711
+ const actionPriorScore = actionPriors.get(memory.frontmatter.id);
15712
+ const signals = typeof actionPriorScore === "number" && Number.isFinite(actionPriorScore) ? { actionPriorScore } : void 0;
15713
+ const decision = decideLifecycleTransition(memory, policy, now, signals);
15621
15714
  const nextState = memory.frontmatter.status === "archived" ? "archived" : decision.nextState;
15622
15715
  countsByState[nextState] += 1;
15623
15716
  if (memory.frontmatter.verificationState === "disputed") {