Files
ST-Bionic-Memory-Ecology/tests/story-timeline.mjs
2026-04-08 22:41:49 +08:00

120 lines
3.4 KiB
JavaScript

import assert from "node:assert/strict";
import { createEmptyGraph, createNode } from "../graph/graph.js";
import {
applyBatchStoryTime,
classifyStoryTemporalBucket,
clearManualActiveStorySegment,
deriveStoryTimeSpanFromNodes,
resolveActiveStoryContext,
setManualActiveStorySegment,
upsertTimelineSegment,
} from "../graph/story-timeline.js";
const graph = createEmptyGraph();
const night = upsertTimelineSegment(
graph,
{ label: "昨夜冲突", relation: "same", confidence: "high" },
{ source: "extract" },
);
assert.equal(night.created, true);
assert.equal(graph.timelineState.segments.length, 1);
const morningBatch = applyBatchStoryTime(
graph,
{
label: "第二天清晨",
relation: "after",
confidence: "high",
tense: "ongoing",
advancesActiveTimeline: true,
},
"extract",
);
assert.equal(morningBatch.ok, true);
assert.equal(morningBatch.timelineAdvanceApplied, true);
assert.equal(graph.historyState.activeStoryTimeLabel, "第二天清晨");
assert.equal(graph.historyState.lastExtractedStorySegmentId, morningBatch.extractedSegmentId);
const future = upsertTimelineSegment(
graph,
{
label: "明天夜里",
relation: "after",
confidence: "medium",
tense: "future",
},
{ referenceSegmentId: morningBatch.extractedSegmentId, source: "extract" },
);
assert.equal(graph.timelineState.segments.length, 3);
const currentNode = createNode({
type: "event",
fields: { title: "当前事件" },
seq: 10,
});
currentNode.storyTime = {
segmentId: morningBatch.extractedSegmentId,
label: "第二天清晨",
tense: "ongoing",
relation: "same",
anchorLabel: "",
confidence: "high",
source: "extract",
};
const flashbackNode = createNode({
type: "event",
fields: { title: "旧回忆" },
seq: 8,
});
flashbackNode.storyTime = {
segmentId: night.storyTime.segmentId,
label: "昨夜冲突",
tense: "flashback",
relation: "before",
anchorLabel: "",
confidence: "high",
source: "extract",
};
const futureNode = createNode({
type: "event",
fields: { title: "未来计划" },
seq: 12,
});
futureNode.storyTime = future.storyTime;
const currentBucket = classifyStoryTemporalBucket(graph, currentNode, {
activeSegmentId: morningBatch.extractedSegmentId,
});
assert.equal(currentBucket.bucket, "current");
assert.equal(currentBucket.suppressed, false);
const flashbackBucket = classifyStoryTemporalBucket(graph, flashbackNode, {
activeSegmentId: morningBatch.extractedSegmentId,
cueMode: "flashback",
});
assert.equal(flashbackBucket.bucket, "flashback");
assert.equal(flashbackBucket.rescued, true);
const futureBucket = classifyStoryTemporalBucket(graph, futureNode, {
activeSegmentId: morningBatch.extractedSegmentId,
});
assert.equal(futureBucket.bucket, "future");
assert.equal(futureBucket.suppressed, true);
const span = deriveStoryTimeSpanFromNodes(graph, [flashbackNode, currentNode], "derived");
assert.equal(span.startLabel, "昨夜冲突");
assert.equal(span.endLabel, "第二天清晨");
assert.equal(span.mixed, true);
const manualResult = setManualActiveStorySegment(graph, { label: "昨夜冲突" });
assert.equal(manualResult.ok, true);
assert.equal(resolveActiveStoryContext(graph).activeStoryTimeLabel, "昨夜冲突");
const cleared = clearManualActiveStorySegment(graph);
assert.equal(cleared.ok, true);
assert.equal(resolveActiveStoryContext(graph).activeStoryTimeLabel, "第二天清晨");
console.log("story-timeline tests passed");