feat(memory-v2): close Phase A with auto-review, product events, and H5 recall UI.
Add candidate auto-review pipeline, shadow audit tooling, admin metrics page, and user-visible memory recall hints in chat with phase-a readiness checks. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
auditMemoryV2Shadow,
|
||||
detectFalseStoreCandidate,
|
||||
formatMemoryV2ShadowAuditReport,
|
||||
parseSinceArg,
|
||||
} from './memory-v2-shadow-audit.mjs';
|
||||
|
||||
test('parseSinceArg supports hour/day/week windows', () => {
|
||||
const now = Date.parse('2026-07-31T12:00:00.000Z');
|
||||
assert.equal(parseSinceArg('24h', now).sinceMs, now - 86400000);
|
||||
assert.equal(parseSinceArg('7d', now).sinceMs, now - 7 * 86400000);
|
||||
assert.equal(parseSinceArg('2w', now).sinceMs, now - 14 * 86400000);
|
||||
});
|
||||
|
||||
test('detectFalseStoreCandidate flags questions and routing leaks', () => {
|
||||
assert.equal(detectFalseStoreCandidate('SSE 是什么?').suspicious, true);
|
||||
assert.equal(detectFalseStoreCandidate('请记住我每周三做代码评审').suspicious, false);
|
||||
assert.equal(
|
||||
detectFalseStoreCandidate('[Memory Context] 旧记忆').code,
|
||||
'routing_leak',
|
||||
);
|
||||
});
|
||||
|
||||
test('auditMemoryV2Shadow summarizes candidates and pgvector lag', () => {
|
||||
const nowMs = Date.parse('2026-07-31T12:00:00.000Z');
|
||||
const sinceMs = nowMs - 7 * 86400000;
|
||||
const report = auditMemoryV2Shadow({
|
||||
sinceMs,
|
||||
nowMs,
|
||||
candidates: [
|
||||
{
|
||||
id: 'c1',
|
||||
user_id: 'u1',
|
||||
memory_type: 'episodic',
|
||||
content: '请记住我每周三下午做代码评审',
|
||||
status: 'accepted',
|
||||
policy_reason: 'explicit_memory_request',
|
||||
confidence: 0.98,
|
||||
importance: 0.95,
|
||||
created_at: sinceMs + 1000,
|
||||
updated_at: sinceMs + 1000,
|
||||
},
|
||||
{
|
||||
id: 'c2',
|
||||
user_id: 'u1',
|
||||
memory_type: 'semantic',
|
||||
content: 'SSE 是什么?',
|
||||
status: 'candidate',
|
||||
policy_reason: 'stable_fact_signal',
|
||||
confidence: 0.82,
|
||||
importance: 0.75,
|
||||
created_at: sinceMs + 2000,
|
||||
updated_at: sinceMs + 2000,
|
||||
},
|
||||
],
|
||||
memoryItems: [
|
||||
{
|
||||
id: 'm1',
|
||||
user_id: 'u1',
|
||||
label: 'fact',
|
||||
memory_text: '每周三下午做代码评审',
|
||||
status: 'active',
|
||||
created_at: sinceMs + 3000,
|
||||
updated_at: sinceMs + 3000,
|
||||
},
|
||||
{
|
||||
id: 'm2',
|
||||
user_id: 'u2',
|
||||
label: 'fact',
|
||||
memory_text: '使用 pgvector 做语义检索',
|
||||
status: 'active',
|
||||
created_at: sinceMs + 4000,
|
||||
updated_at: sinceMs + 4000,
|
||||
},
|
||||
],
|
||||
pgvectorMemoryIds: new Set(['m1']),
|
||||
pgvectorConfigured: true,
|
||||
agentMemoryEvents: [
|
||||
{
|
||||
event_type: 'agent_memory_resolved',
|
||||
created_at: sinceMs + 5000,
|
||||
data_json: { count: 2 },
|
||||
},
|
||||
{
|
||||
event_type: 'agent_memory_resolved',
|
||||
created_at: sinceMs + 6000,
|
||||
data_json: { count: 0 },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
assert.equal(report.window.candidateCount, 2);
|
||||
assert.equal(report.summary.suspiciousCandidateCount, 1);
|
||||
assert.equal(report.pgvectorLagUsers.length, 1);
|
||||
assert.equal(report.pgvectorLagUsers[0].userId, 'u2');
|
||||
assert.equal(report.summary.resolveHitRate, 0.5);
|
||||
assert.equal(report.ok, false);
|
||||
assert.match(formatMemoryV2ShadowAuditReport(report), /pgvector lag users/);
|
||||
});
|
||||
Reference in New Issue
Block a user