Phase 5: add kept-window tests — slice, presence, filter, empty kept.
Covers kept-window dedup helpers per SPEC §6.4 and §12.1. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import type { SessionEntry } from "@earendil-works/pi-coding-agent";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
filterSkillsNeedingReinject,
|
||||
getKeptEntries,
|
||||
skillsPresentInKeptWindow,
|
||||
} from "../src/kept";
|
||||
import type { TrackedSkill } from "../src/state";
|
||||
|
||||
const ts = "2024-12-03T14:00:00.000Z";
|
||||
|
||||
function userMessage(id: string, content: string): SessionEntry {
|
||||
return {
|
||||
type: "message",
|
||||
id,
|
||||
parentId: null,
|
||||
timestamp: ts,
|
||||
message: { role: "user", content },
|
||||
} as SessionEntry;
|
||||
}
|
||||
|
||||
function assistantMessage(id: string, content: string): SessionEntry {
|
||||
return {
|
||||
type: "message",
|
||||
id,
|
||||
parentId: null,
|
||||
timestamp: ts,
|
||||
message: { role: "assistant", content: [{ type: "text", text: content }] },
|
||||
} as SessionEntry;
|
||||
}
|
||||
|
||||
function compactionEntry(id: string, firstKeptEntryId: string): SessionEntry {
|
||||
return {
|
||||
type: "compaction",
|
||||
id,
|
||||
parentId: null,
|
||||
timestamp: ts,
|
||||
summary: "summary",
|
||||
firstKeptEntryId,
|
||||
tokensBefore: 1000,
|
||||
} as SessionEntry;
|
||||
}
|
||||
|
||||
const skillBlock = (name: string) =>
|
||||
`<skill name="${name}" location="/skills/${name}/SKILL.md">\nbody\n</skill>`;
|
||||
|
||||
const trackedSkills: TrackedSkill[] = [
|
||||
{
|
||||
name: "alpha",
|
||||
filePath: "/skills/alpha/SKILL.md",
|
||||
baseDir: "/skills/alpha",
|
||||
firstSeenAt: 1,
|
||||
lastSeenAt: 1,
|
||||
sources: ["slash"],
|
||||
},
|
||||
{
|
||||
name: "beta",
|
||||
filePath: "/skills/beta/SKILL.md",
|
||||
baseDir: "/skills/beta",
|
||||
firstSeenAt: 2,
|
||||
lastSeenAt: 2,
|
||||
sources: ["skill-block"],
|
||||
},
|
||||
];
|
||||
|
||||
describe("getKeptEntries", () => {
|
||||
const branch: SessionEntry[] = [
|
||||
userMessage("e1", "old"),
|
||||
userMessage("e2", "kept start"),
|
||||
assistantMessage("e3", "reply"),
|
||||
compactionEntry("e4", "e2"),
|
||||
userMessage("e5", "after compact"),
|
||||
];
|
||||
|
||||
it("slices from firstKeptEntryId through tail", () => {
|
||||
expect(getKeptEntries(branch, "e2").map((entry) => entry.id)).toEqual(["e2", "e3", "e4", "e5"]);
|
||||
});
|
||||
|
||||
it("returns empty when firstKeptEntryId is missing", () => {
|
||||
expect(getKeptEntries(branch, "missing")).toEqual([]);
|
||||
expect(getKeptEntries([], "e1")).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("skillsPresentInKeptWindow", () => {
|
||||
it("detects skill blocks in kept user messages", () => {
|
||||
const kept = [userMessage("k1", skillBlock("alpha")), assistantMessage("k2", "ignored")];
|
||||
expect(skillsPresentInKeptWindow(kept, ["alpha", "beta"])).toEqual(new Set(["alpha"]));
|
||||
});
|
||||
|
||||
it("returns empty when no tracked skills or no blocks", () => {
|
||||
expect(skillsPresentInKeptWindow([userMessage("k1", "plain")], ["alpha"])).toEqual(new Set());
|
||||
expect(skillsPresentInKeptWindow([userMessage("k1", skillBlock("alpha"))], [])).toEqual(new Set());
|
||||
expect(skillsPresentInKeptWindow([], ["alpha", "beta"])).toEqual(new Set());
|
||||
});
|
||||
});
|
||||
|
||||
describe("filterSkillsNeedingReinject", () => {
|
||||
it("returns registered tracked skills absent from kept window", () => {
|
||||
const keptPresent = new Set(["alpha"]);
|
||||
const registered = new Set(["alpha", "beta"]);
|
||||
expect(filterSkillsNeedingReinject(trackedSkills, keptPresent, registered)).toEqual(["beta"]);
|
||||
});
|
||||
|
||||
it("excludes unregistered skills and preserves tracked order", () => {
|
||||
const keptPresent = new Set<string>();
|
||||
const registered = new Set(["alpha", "beta"]);
|
||||
expect(filterSkillsNeedingReinject(trackedSkills, keptPresent, registered)).toEqual(["alpha", "beta"]);
|
||||
expect(filterSkillsNeedingReinject(trackedSkills, keptPresent, new Set(["beta"]))).toEqual(["beta"]);
|
||||
});
|
||||
|
||||
it("returns empty when all tracked skills are in kept window", () => {
|
||||
const keptPresent = new Set(["alpha", "beta"]);
|
||||
const registered = new Set(["alpha", "beta"]);
|
||||
expect(filterSkillsNeedingReinject(trackedSkills, keptPresent, registered)).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user