import { describe, expect, test } from "bun:test";
import { buildPkbReminder } from "./pkb-reminder-builder.js";
// Byte-for-byte fixture of the PKB reminder. Asserted verbatim so that any
// future edit to the BODY text is caught by tests.
const BASE_REMINDER =
"" +
"\nStay present in this conversation. Use `remember` when something feels worth pausing to mark — corrections (highest priority), plans, decisions, felt moments. You don't have to capture everything in the moment — a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
"\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing." +
"\n";
describe("buildPkbReminder", () => {
test("empty hints returns exact base reminder byte-for-byte", () => {
expect(buildPkbReminder([])).toBe(BASE_REMINDER);
});
test("single hint renders one bullet with no duplicates or trailing blank line", () => {
const out = buildPkbReminder(["projects/alpha.md"]);
const expected =
"" +
"\nStay present in this conversation. Use `remember` when something feels worth pausing to mark — corrections (highest priority), plans, decisions, felt moments. You don't have to capture everything in the moment — a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
"\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing." +
"\nBased on the current context, these files look especially relevant:" +
"\n- projects/alpha.md" +
"\n";
expect(out).toBe(expected);
// Exactly one bullet.
const bulletCount = (out.match(/^- /gm) ?? []).length;
expect(bulletCount).toBe(1);
// No blank line before closing tag.
expect(out.includes("\n\n")).toBe(false);
});
test("three hints render all three in order", () => {
const hints = ["a.md", "sub/b.md", "c/d/e.md"];
const out = buildPkbReminder(hints);
const expected =
"" +
"\nStay present in this conversation. Use `remember` when something feels worth pausing to mark — corrections (highest priority), plans, decisions, felt moments. You don't have to capture everything in the moment — a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
"\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing." +
"\nBased on the current context, these files look especially relevant:" +
"\n- a.md" +
"\n- sub/b.md" +
"\n- c/d/e.md" +
"\n";
expect(out).toBe(expected);
// Order check — each should appear after the previous.
const idxA = out.indexOf("- a.md");
const idxB = out.indexOf("- sub/b.md");
const idxC = out.indexOf("- c/d/e.md");
expect(idxA).toBeGreaterThan(-1);
expect(idxB).toBeGreaterThan(idxA);
expect(idxC).toBeGreaterThan(idxB);
});
test("hints with special chars (< and &) are emitted verbatim (no escaping)", () => {
const hints = ["weird.md", "foo&bar.md"];
const out = buildPkbReminder(hints);
expect(out).toContain("- weird.md");
expect(out).toContain("- foo&bar.md");
// Ensure no HTML-style escaping happened.
expect(out).not.toContain("<");
expect(out).not.toContain("&");
});
});