hippo-memory 1.13.5 → 1.14.0
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/api.d.ts +20 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +43 -4
- package/dist/api.js.map +1 -1
- package/dist/audit.d.ts +1 -1
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/availability.d.ts +65 -0
- package/dist/availability.d.ts.map +1 -0
- package/dist/availability.js +94 -0
- package/dist/availability.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +523 -484
- package/dist/cli.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +41 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/src/api.js +43 -4
- package/dist/src/api.js.map +1 -1
- package/dist/src/audit.js +1 -1
- package/dist/src/audit.js.map +1 -1
- package/dist/src/availability.js +94 -0
- package/dist/src/availability.js.map +1 -0
- package/dist/src/cli.js +523 -484
- package/dist/src/cli.js.map +1 -1
- package/dist/src/mcp/server.js +41 -0
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/server.js +1 -0
- package/dist/src/server.js.map +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +5 -3
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// J2 — Availability-bias detector (Track J: biases-over-memory-state)
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// Flags when a recall's returned top-K is dominated by recent entries while
|
|
6
|
+
// substantially older relevant candidates in the same MATCHED pool were passed
|
|
7
|
+
// over. This is the availability / recency heuristic (Tversky-Kahneman): what
|
|
8
|
+
// is most mentally available (recent) gets over-weighted relative to what is
|
|
9
|
+
// most relevant. Hippo's substrate makes this measurable: every entry carries a
|
|
10
|
+
// creation timestamp, so we can compare the age distribution of what was
|
|
11
|
+
// RETURNED against the age distribution of the pool it was drawn from.
|
|
12
|
+
//
|
|
13
|
+
// Soft warning ONLY (ROADMAP-RESEARCH.md Track J discipline note): this never
|
|
14
|
+
// filters, reorders, or suppresses a result. It surfaces a hint the calling
|
|
15
|
+
// agent may choose to act on, exactly like J1 anchoringHint / J3
|
|
16
|
+
// planningFallacyHint / C5 suppressionSummary.
|
|
17
|
+
//
|
|
18
|
+
// PURE: no I/O, no env reads. The env gate (HIPPO_AVAILABILITY=off) and the
|
|
19
|
+
// audit emission live in the callers (api.recall, cmdRecall, MCP), mirroring
|
|
20
|
+
// detectAnchoring in recall-history.ts.
|
|
21
|
+
export const DEFAULT_RECENCY_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
22
|
+
export const DEFAULT_RECENT_FRACTION_THRESHOLD = 0.7;
|
|
23
|
+
export const DEFAULT_MIN_RETURNED = 3;
|
|
24
|
+
export const DEFAULT_MIN_POOL = 10;
|
|
25
|
+
export const DEFAULT_MIN_OLDER_PASSED_OVER = 3;
|
|
26
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
27
|
+
const MS_PER_HOUR = 60 * 60 * 1000;
|
|
28
|
+
function median(nums) {
|
|
29
|
+
if (nums.length === 0)
|
|
30
|
+
return 0;
|
|
31
|
+
const sorted = [...nums].sort((a, b) => a - b);
|
|
32
|
+
const mid = Math.floor(sorted.length / 2);
|
|
33
|
+
return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Detect availability/recency bias in a recall result.
|
|
37
|
+
*
|
|
38
|
+
* Returns an AvailabilityHint when ALL of the following hold:
|
|
39
|
+
* 1. topK.length >= minReturned AND pool.length >= minPool (enough signal);
|
|
40
|
+
* 2. recentFraction > recentFractionThreshold (returned slice is recency-dominated);
|
|
41
|
+
* 3. poolMedianAgeDays > topKMedianAgeDays (the pool genuinely skews older,
|
|
42
|
+
* so recency is not just the corpus being young);
|
|
43
|
+
* 4. olderCandidatesPassedOver >= minOlderPassedOver (older matched memories
|
|
44
|
+
* actually existed and were not returned).
|
|
45
|
+
* Otherwise returns null.
|
|
46
|
+
*
|
|
47
|
+
* Entries with an unparseable `created` are dropped defensively so a malformed
|
|
48
|
+
* row cannot poison the medians with NaN.
|
|
49
|
+
*/
|
|
50
|
+
export function detectAvailabilityBias(opts) {
|
|
51
|
+
const now = opts.now ?? Date.now();
|
|
52
|
+
const recencyWindowMs = opts.recencyWindowMs ?? DEFAULT_RECENCY_WINDOW_MS;
|
|
53
|
+
const recentFractionThreshold = opts.recentFractionThreshold ?? DEFAULT_RECENT_FRACTION_THRESHOLD;
|
|
54
|
+
const minReturned = opts.minReturned ?? DEFAULT_MIN_RETURNED;
|
|
55
|
+
const minPool = opts.minPool ?? DEFAULT_MIN_POOL;
|
|
56
|
+
const minOlderPassedOver = opts.minOlderPassedOver ?? DEFAULT_MIN_OLDER_PASSED_OVER;
|
|
57
|
+
const topK = opts.topK
|
|
58
|
+
.map((e) => ({ id: e.id, ts: Date.parse(e.created) }))
|
|
59
|
+
.filter((e) => Number.isFinite(e.ts));
|
|
60
|
+
const pool = opts.pool
|
|
61
|
+
.map((e) => ({ id: e.id, ts: Date.parse(e.created) }))
|
|
62
|
+
.filter((e) => Number.isFinite(e.ts));
|
|
63
|
+
if (topK.length < minReturned || pool.length < minPool)
|
|
64
|
+
return null;
|
|
65
|
+
const recentCount = topK.filter((e) => now - e.ts <= recencyWindowMs).length;
|
|
66
|
+
const recentFraction = recentCount / topK.length;
|
|
67
|
+
if (recentFraction <= recentFractionThreshold)
|
|
68
|
+
return null;
|
|
69
|
+
const topKMedianAgeDays = median(topK.map((e) => (now - e.ts) / MS_PER_DAY));
|
|
70
|
+
const poolMedianAgeDays = median(pool.map((e) => (now - e.ts) / MS_PER_DAY));
|
|
71
|
+
if (poolMedianAgeDays <= topKMedianAgeDays)
|
|
72
|
+
return null;
|
|
73
|
+
const topKIds = new Set(topK.map((e) => e.id));
|
|
74
|
+
const olderCandidatesPassedOver = pool.filter((e) => !topKIds.has(e.id) && (now - e.ts) / MS_PER_DAY > topKMedianAgeDays).length;
|
|
75
|
+
if (olderCandidatesPassedOver < minOlderPassedOver)
|
|
76
|
+
return null;
|
|
77
|
+
const pct = Math.round(recentFraction * 100);
|
|
78
|
+
const windowHours = Math.round(recencyWindowMs / MS_PER_HOUR);
|
|
79
|
+
const summary = `Availability bias risk: ${recentCount} of ${topK.length} returned results are from the ` +
|
|
80
|
+
`last ${windowHours}h (${pct}%), but ${olderCandidatesPassedOver} older matched memories ` +
|
|
81
|
+
`were passed over. Returned median age ${topKMedianAgeDays.toFixed(1)}d vs pool median ` +
|
|
82
|
+
`${poolMedianAgeDays.toFixed(1)}d. The most relevant answer may not be the most recent.`;
|
|
83
|
+
return {
|
|
84
|
+
recentCount,
|
|
85
|
+
returnedCount: topK.length,
|
|
86
|
+
recentFraction,
|
|
87
|
+
topKMedianAgeDays,
|
|
88
|
+
poolMedianAgeDays,
|
|
89
|
+
olderCandidatesPassedOver,
|
|
90
|
+
summary,
|
|
91
|
+
source: 'j2-recency',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=availability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.js","sourceRoot":"","sources":["../src/availability.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAwBH,OAAO,EASL,WAAW,EAGZ,MAAM,aAAa,CAAC;AAiGrB,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAwBH,OAAO,EASL,WAAW,EAGZ,MAAM,aAAa,CAAC;AAiGrB,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAmChC,kFAAkF;AAClF,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AA+rED;;;GAGG;AACH,oHAAoH;AACpH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CA2C/D;AAy6CD,oHAAoH;AACpH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,EACtF,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,MAAkB,GAC1B,IAAI,CA6BN"}
|