Files
pi-auto-reinject/test/settings.test.ts
T
grayhook 8f48040eac Phase 14: add debug reinject diag logging — B-002 filter visibility
Expose settings.debug snapshots on session_compact and before_agent_start
so Phase 14 can see which filter stage drops --skill paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 14:29:56 +07:00

166 lines
4.8 KiB
TypeScript

import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
import { tmpdir } from "os";
import { join } from "path";
import { afterEach, describe, expect, it } from "vitest";
import {
DEFAULT_SKILL_REINJECT_SETTINGS,
SKILL_REINJECT_SETTINGS_KEY,
createDefaultSettings,
effectiveEnabled,
effectiveIntegration,
mergeSkillReinjectIntoSettingsFile,
mergeSkillReinjectSettings,
parseSkillReinjectPartial,
} from "../src/settings";
const tempDirs: string[] = [];
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
rmSync(dir, { recursive: true, force: true });
}
});
function tempSettingsPath(): string {
const dir = mkdtempSync(join(tmpdir(), "pi-skill-reinject-settings-"));
tempDirs.push(dir);
return join(dir, "settings.json");
}
describe("createDefaultSettings", () => {
it("matches SPEC §7.3 defaults", () => {
expect(createDefaultSettings()).toEqual(DEFAULT_SKILL_REINJECT_SETTINGS);
});
});
describe("parseSkillReinjectPartial", () => {
it("ignores invalid shapes and fields", () => {
expect(parseSkillReinjectPartial(null)).toEqual({});
expect(parseSkillReinjectPartial([])).toEqual({});
expect(
parseSkillReinjectPartial({
enabled: "yes",
autoCompactIntegration: "bogus",
extra: true,
}),
).toEqual({});
});
it("keeps valid fields only", () => {
expect(
parseSkillReinjectPartial({
enabled: true,
suffix: "custom",
}),
).toEqual({ enabled: true, suffix: "custom" });
});
it("parses debug flag", () => {
expect(parseSkillReinjectPartial({ debug: true })).toEqual({ debug: true });
});
});
describe("mergeSkillReinjectSettings", () => {
it("applies global then project overrides on defaults", () => {
expect(
mergeSkillReinjectSettings({ enabled: true }, { trackReadPaths: false }),
).toEqual({
...DEFAULT_SKILL_REINJECT_SETTINGS,
enabled: true,
trackReadPaths: false,
});
});
it("lets project win over global for the same field", () => {
expect(
mergeSkillReinjectSettings({ enabled: true }, { enabled: false }),
).toEqual({
...DEFAULT_SKILL_REINJECT_SETTINGS,
enabled: false,
});
});
});
describe("mergeSkillReinjectIntoSettingsFile", () => {
it("merges skillReinject fields across successive writes", () => {
const path = tempSettingsPath();
mergeSkillReinjectIntoSettingsFile(path, { enabled: true });
mergeSkillReinjectIntoSettingsFile(path, { triggerTurn: true });
const saved = JSON.parse(readFileSync(path, "utf8")) as Record<string, unknown>;
expect(saved[SKILL_REINJECT_SETTINGS_KEY]).toEqual({
enabled: true,
triggerTurn: true,
});
});
it("preserves existing top-level keys", () => {
const path = tempSettingsPath();
writeFileSync(
path,
`${JSON.stringify({ theme: "light", compaction: { enabled: false } }, null, 2)}\n`,
"utf8",
);
mergeSkillReinjectIntoSettingsFile(path, { enabled: true, suffix: "x" });
const saved = JSON.parse(readFileSync(path, "utf8")) as Record<string, unknown>;
expect(saved.theme).toBe("light");
expect(saved.compaction).toEqual({ enabled: false });
expect(saved[SKILL_REINJECT_SETTINGS_KEY]).toEqual({
enabled: true,
suffix: "x",
});
});
});
describe("effectiveEnabled", () => {
const settings = createDefaultSettings();
it("uses session override when set", () => {
expect(effectiveEnabled(true, settings)).toBe(true);
expect(effectiveEnabled(false, { ...settings, enabled: true })).toBe(false);
});
it("falls back to global enabled when override is null", () => {
expect(effectiveEnabled(null, settings)).toBe(false);
expect(effectiveEnabled(null, { ...settings, enabled: true })).toBe(true);
});
});
describe("effectiveIntegration", () => {
const base = createDefaultSettings();
it("honors explicit defer and immediate", () => {
expect(
effectiveIntegration({ ...base, autoCompactIntegration: "defer" }, false),
).toBe("defer");
expect(
effectiveIntegration({ ...base, autoCompactIntegration: "immediate" }, true),
).toBe("immediate");
});
it("uses triggerTurn when integration is off", () => {
expect(
effectiveIntegration({ ...base, autoCompactIntegration: "off", triggerTurn: false }, true),
).toBe("defer");
expect(
effectiveIntegration({ ...base, autoCompactIntegration: "off", triggerTurn: true }, true),
).toBe("immediate");
});
it("defers when auto mode detects pi-auto-compact", () => {
expect(effectiveIntegration(base, true)).toBe("defer");
});
it("uses triggerTurn in auto mode without pi-auto-compact", () => {
expect(effectiveIntegration({ ...base, triggerTurn: false }, false)).toBe("defer");
expect(effectiveIntegration({ ...base, triggerTurn: true }, false)).toBe("immediate");
});
it("prefers session integration override", () => {
expect(
effectiveIntegration({ ...base, autoCompactIntegration: "immediate" }, false, "defer"),
).toBe("defer");
});
});