6f3e53a56a
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>
102 lines
3.0 KiB
JavaScript
102 lines
3.0 KiB
JavaScript
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/);
|
|
});
|