Files
memind/experience-reflect.test.mjs
T
john 2ec6fdbe11 Implement Experience V1 reflect, retrieval boost, and product metrics.
Add rule-based reflect() to aggregate task outcomes, environment-aware search scoring, experience_saved/recalled events, and structured injection blocks per the V1 schema.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 14:30:59 +08:00

91 lines
3.6 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
buildExecutionPatternAggregate,
environmentMatchBoost,
groupTaskOutcomesByProblem,
planExperienceReflection,
problemFingerprint,
} from './experience-reflect.mjs';
test('problemFingerprint normalizes punctuation and spacing', () => {
assert.equal(problemFingerprint(' SSE connection!!! '), 'sse connection');
});
test('groupTaskOutcomesByProblem groups active task outcomes by problem', () => {
const groups = groupTaskOutcomesByProblem([
{ id: '1', kind: 'task_outcome', status: 'active', problem: 'SSE 断线', title: 'A' },
{ id: '2', kind: 'task_outcome', status: 'active', problem: 'SSE 断线', title: 'B' },
{ id: '3', kind: 'task_outcome', status: 'active', problem: 'SSE 断线', title: 'C' },
{ id: '4', kind: 'task_outcome', status: 'active', problem: 'Other', title: 'D' },
{ id: '5', kind: 'lesson', status: 'active', problem: 'SSE 断线', title: 'E' },
], 3);
assert.equal(groups.length, 1);
assert.equal(groups[0].length, 3);
});
test('environmentMatchBoost rewards component matches', () => {
const boost = environmentMatchBoost(
{ environment_json: JSON.stringify({ runtime: 'goosed', components: ['docker', 'postgres'] }) },
['goosed', 'docker'],
);
assert.equal(boost, 1);
});
test('buildExecutionPatternAggregate merges structured fields', () => {
const payload = buildExecutionPatternAggregate([
{
id: '1',
title: 'SSE 修复',
body: '改 server.rs',
problem: 'SSE connection instability',
result: 'success',
confidence: 0.8,
updated_at: 100,
environment_json: JSON.stringify({ runtime: 'goosed', components: ['docker'] }),
action_json: JSON.stringify({ executor: 'goose', steps: ['edit server.rs'] }),
evidence_json: JSON.stringify({ sources: [{ source_id: 'run:1' }] }),
},
{
id: '2',
title: 'SSE 再修',
body: '补 replay 映射',
problem: 'SSE connection instability',
result: 'success',
confidence: 0.9,
updated_at: 200,
environment_json: JSON.stringify({ components: ['portal'] }),
action_json: JSON.stringify({ executor: 'goose', steps: ['replay mapping'] }),
evidence_json: JSON.stringify({ sources: [{ source_id: 'run:2' }] }),
},
{
id: '3',
title: 'SSE 第三次',
body: '终态恢复',
problem: 'SSE connection instability',
result: 'partial',
confidence: 0.7,
updated_at: 300,
environment_json: JSON.stringify({ components: ['sse'] }),
action_json: JSON.stringify({ executor: 'goose', steps: ['finish sync'] }),
evidence_json: JSON.stringify({ sources: [{ source_id: 'run:1' }] }),
},
]);
assert.equal(payload.kind, 'execution_pattern');
assert.equal(payload.result, 'success');
assert.equal(payload.confidence, 0.8);
assert.deepEqual(payload.environment.components.sort(), ['docker', 'portal', 'sse']);
assert.equal(payload.evidence.sources.length, 2);
assert.deepEqual(payload.evidence.provenance.aggregated_from, ['3', '2', '1']);
});
test('planExperienceReflection skips groups with existing execution_pattern', () => {
const plans = planExperienceReflection([
{ id: '1', kind: 'task_outcome', status: 'active', problem: 'SSE 断线', title: 'A' },
{ id: '2', kind: 'task_outcome', status: 'active', problem: 'SSE 断线', title: 'B' },
{ id: '3', kind: 'task_outcome', status: 'active', problem: 'SSE 断线', title: 'C' },
{ id: 'p1', kind: 'execution_pattern', status: 'active', problem: 'SSE 断线', title: 'pattern' },
], { minGroupSize: 3 });
assert.equal(plans.length, 0);
});