import { pathToFileURL, fileURLToPath } from "node:url";
import { createHash } from "node:crypto";
import {
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
renameSync,
rmSync,
symlinkSync,
unlinkSync,
writeFileSync,
} from "node:fs";
import { dirname, join, resolve } from "node:path";
import { tmpdir } from "node:os";
import { resolvePrimeRoot } from "./prime-root.mjs";
const primeRoot = resolvePrimeRoot();
const { loadExtensions } = await import(pathToFileURL(join(primeRoot, "dist/core/extensions/loader.js")));
const extensionPath = fileURLToPath(new URL("./integration-extension.ts", import.meta.url));
const root = mkdtempSync(join(tmpdir(), "prime-snapcompact-integration-"));
const sessionDir = `${root}/sessions/project`;
mkdirSync(sessionDir, { recursive: true });
let activeSessionId = "11111111-1111-4111-8111-111111111111";
let activeSessionFile = `${sessionDir}/${activeSessionId}.jsonl`;
writeFileSync(activeSessionFile, `${JSON.stringify({
type: "session",
version: 3,
id: activeSessionId,
timestamp: new Date().toISOString(),
cwd: process.cwd(),
})}\n`);
const model = {
id: "gpt-5.2",
name: "test vision model",
api: "openai-responses",
provider: "openai",
baseUrl: "https://example.invalid",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 272000,
maxTokens: 16384,
};
const longText = "日本語の履歴と解析結果です。ファイルを確認しました。\n".repeat(6000);
const usage = { input: 100, output: 100, cacheRead: 0, cacheWrite: 0, totalTokens: 200, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } };
const toolResult = (id, text, isError = false) => ({
role: "toolResult",
toolCallId: id,
toolName: "ipython",
content: [{ type: "text", text }],
isError,
timestamp: 2,
});
const oldestMaskedOutput = `oldest tool output ${"MASKED-SECRET".repeat(10_000)}`;
const recentExactOutput = `recent exact output ${"z".repeat(3000)}`;
const oldMessages = [
{
role: "user",
content: [
{ type: "text", text: "inspect the repository" },
{ type: "image", data: "raw-source-image", mimeType: "image/png" },
],
timestamp: 1,
},
{
role: "assistant",
content: [
{ type: "thinking", thinking: "private stale reasoning" },
{ type: "text", text: longText },
...["t1", "t2", "t3", "t4"].map((id) => ({
type: "toolCall",
id,
name: "ipython",
arguments: { id, payload: id === "t4" ? "q".repeat(1200) : id },
})),
],
api: model.api,
provider: model.provider,
model: model.id,
usage,
stopReason: "toolUse",
timestamp: 2,
},
toolResult("t1", oldestMaskedOutput),
toolResult("t2", "second exact output injected suffix"),
toolResult("t3", "third exact output"),
toolResult("t4", recentExactOutput, true),
toolResult("orphan", "orphan output"),
];
const prep = (messages, previousSummary) => ({
firstKeptEntryId: "kept-entry",
messagesToSummarize: messages,
turnPrefixMessages: [],
isSplitTurn: false,
tokensBefore: 100000,
previousSummary,
fileOps: { read: new Set(["src/file.ts"]), written: new Set(), edited: new Set() },
settings: { enabled: true, reserveTokens: 16384, keepRecentTokens: 20000 },
});
const controller = new AbortController();
let branch = [];
const ctx = {
cwd: process.cwd(),
hasUI: false,
ui: { notify() {} },
model: { ...model },
modelRegistry: { async getApiKeyAndHeaders() { return { ok: true, apiKey: "test-key" }; } },
sessionManager: {
getSessionFile: () => activeSessionFile,
getSessionDir: () => sessionDir,
getSessionId: () => activeSessionId,
getBranch: () => branch,
getEntries: () => branch,
},
getSystemPrompt: () => "test system prompt",
compact: () => { throw new Error("context hook must not compact reentrantly"); },
};
const loaded = await loadExtensions([extensionPath], process.cwd());
if (loaded.errors.length) throw new Error(JSON.stringify(loaded.errors));
loaded.runtime.getThinkingLevel = () => "medium";
const extension = loaded.extensions[0];
const before = extension.handlers.get("session_before_compact")[0];
const context = extension.handlers.get("context")[0];
const sessionStart = extension.handlers.get("session_start")[0];
const sessionCompact = extension.handlers.get("session_compact")[0];
ctx.model = { ...model, input: ["text"] };
const initialText = await before({ type: "session_before_compact", preparation: prep(oldMessages), branchEntries: [], customInstructions: undefined, signal: controller.signal }, ctx);
if (!initialText?.compaction) throw new Error("initial text-only compaction did not use projected native compaction");
ctx.model = {
...model,
id: "claude-sonnet-4-5",
api: "anthropic-messages",
provider: "anthropic",
input: ["text"],
};
const initialClaudeText = await before({ type: "session_before_compact", preparation: prep(oldMessages), branchEntries: [], customInstructions: undefined, signal: controller.signal }, ctx);
if (!initialClaudeText?.compaction) {
throw new Error("Claude text compaction did not use its reasoning-safe projection");
}
ctx.model = { ...ctx.model, input: ["text", "image"] };
const initialClaudeVisual = await before({ type: "session_before_compact", preparation: prep(oldMessages), branchEntries: [], customInstructions: undefined, signal: controller.signal }, ctx);
if (
!initialClaudeVisual?.compaction?.details?.snapcompact?.artifact ||
initialClaudeVisual.compaction.details.snapcompact.thinkingIncluded !== false
) {
throw new Error("Claude visual compaction did not record reasoning exclusion");
}
const initialClaudeRef = initialClaudeVisual.compaction.details.snapcompact.artifact;
const initialClaudeArchive = JSON.parse(
readFileSync(join(root, "sessions", "session-artifacts", activeSessionId, "snapcompact", initialClaudeRef.file), "utf8"),
).preserveData.snapcompact;
const initialClaudeArchiveText = [
initialClaudeArchive.text,
initialClaudeArchive.textHead,
initialClaudeArchive.textTail,
].filter((value) => typeof value === "string").join("");
if (initialClaudeArchiveText.includes("private stale reasoning")) {
throw new Error("Claude visual compaction archived replayed reasoning");
}
ctx.model = { ...model };
const initialCustom = await before({ type: "session_before_compact", preparation: prep(oldMessages), branchEntries: [], customInstructions: "focus on tests", signal: controller.signal }, ctx);
if (!initialCustom?.compaction) throw new Error("initial custom-instruction compaction did not use projected native compaction");
const originalWarn = console.warn;
console.warn = () => {};
process.env.PRIME_SNAPCOMPACT_BUN = "/definitely/missing/bun";
const initialFailure = await before({ type: "session_before_compact", preparation: prep(oldMessages), branchEntries: [], customInstructions: undefined, signal: controller.signal }, ctx);
delete process.env.PRIME_SNAPCOMPACT_BUN;
console.warn = originalWarn;
if (!initialFailure?.compaction) throw new Error("first worker failure did not use projected native compaction");
const abortedController = new AbortController();
abortedController.abort();
const aborted = await before({ type: "session_before_compact", preparation: prep(oldMessages), branchEntries: [], customInstructions: undefined, signal: abortedController.signal }, ctx);
if (aborted?.cancel !== true) throw new Error("aborted visual compaction did not cancel");
const splitPreparation = {
...prep([{ role: "user", content: "split history", timestamp: 1 }]),
turnPrefixMessages: [{ role: "user", content: "split turn prefix", timestamp: 2 }],
isSplitTurn: true,
};
const split = await before({ type: "session_before_compact", preparation: splitPreparation, branchEntries: [], customInstructions: undefined, signal: controller.signal }, ctx);
if (!split?.compaction?.details?.snapcompact?.artifact) throw new Error("split visual compaction failed");
const splitRef = split.compaction.details.snapcompact.artifact;
const splitText = JSON.parse(
readFileSync(join(root, "sessions", "session-artifacts", activeSessionId, "snapcompact", splitRef.file), "utf8"),
).preserveData.snapcompact.text ?? "";
if (!splitText.includes("split history") || !splitText.includes("split turn prefix")) {
throw new Error("split visual compaction lost a message group");
}
const rawProjectionInput = JSON.stringify(oldMessages);
const first = await before({ type: "session_before_compact", preparation: prep(oldMessages), branchEntries: branch, customInstructions: undefined, signal: controller.signal }, ctx);
if (!first?.compaction?.details?.snapcompact?.artifact) throw new Error("first SnapCompact compaction missing artifact reference");
if (JSON.stringify(oldMessages) !== rawProjectionInput) throw new Error("visual projection mutated raw messages");
const detailsJson = JSON.stringify(first.compaction.details);
if (Buffer.byteLength(detailsJson) >= 1024 * 1024) throw new Error("compaction details exceed Prime line safety limit");
if (detailsJson.includes("iVBORw0KGgo")) throw new Error("PNG data leaked into compaction details");
const ref1 = first.compaction.details.snapcompact.artifact;
if (first.compaction.details.snapcompact.projectionVersion !== 3) {
throw new Error("visual compaction did not record its projection version");
}
const firstArtifactPath = join(
root,
"sessions",
"session-artifacts",
activeSessionId,
"snapcompact",
ref1.file,
);
const firstArtifactData = readFileSync(firstArtifactPath);
const firstArtifactDocument = JSON.parse(firstArtifactData.toString("utf8"));
const firstArchive = firstArtifactDocument.preserveData.snapcompact;
const firstArchiveText = firstArchive.text ?? "";
if (!firstArchiveText.includes("private stale reasoning")) {
throw new Error("archive lost compatible reasoning");
}
if (first.compaction.details.snapcompact.thinkingIncluded !== true) {
throw new Error("archive did not record compatible reasoning retention");
}
if (firstArchiveText.includes("raw-source-image") || !firstArchiveText.includes("[image]")) {
throw new Error("archive did not replace source image bytes");
}
if (
firstArchiveText.includes("oldest tool output") ||
firstArchiveText.includes("MASKED-SECRET") ||
!firstArchiveText.includes("[tool result]")
) {
throw new Error("archive did not mask the oldest tool result");
}
for (const exact of ["second exact output", "third exact output", recentExactOutput]) {
if (!firstArchiveText.includes(exact)) throw new Error(`archive lost ${exact.slice(0, 24)}`);
}
if (!firstArchiveText.includes("q".repeat(1200))) throw new Error("archive truncated recent tool arguments");
if (!firstArchiveText.includes("[tool result ipython#t4 error=true]")) {
throw new Error("archive lost tool result identity or error state");
}
if (firstArchiveText.includes("orphan output")) throw new Error("archive retained an orphan result");
const compactionEntry = {
type: "compaction", id: "compaction-1", parentId: null, timestamp: Date.now(),
summary: first.compaction.summary, firstKeptEntryId: first.compaction.firstKeptEntryId,
tokensBefore: first.compaction.tokensBefore, details: first.compaction.details, fromHook: true,
};
branch = [compactionEntry, { type: "message", id: "recent-1", parentId: "compaction-1", timestamp: Date.now(), message: { role: "user", content: "continue", timestamp: Date.now() } }];
const hydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "continue", timestamp: Date.now() },
]}, ctx);
const visual = hydrated.messages[0];
const images = visual.content.filter((block) => block.type === "image");
if (visual.role !== "custom" || images.length < 1 || images.length > first.compaction.details.snapcompact.frameBudget) {
throw new Error("vision context did not rehydrate within frame budget");
}
if (images.some((image) => image.detail !== "original")) {
throw new Error("vision context dropped SnapCompact frame detail");
}
ctx.model = {
...model,
id: "claude-sonnet-4-5",
api: "anthropic-messages",
provider: "anthropic",
contextWindow: 1_000_000,
};
const claudeHydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "continue with Claude", timestamp: Date.now() },
]}, ctx);
const claudeArchiveContent = claudeHydrated.messages[0].content;
if (claudeArchiveContent.some((block) => block.type === "image")) {
throw new Error("Claude received reasoning-bearing archive frames");
}
const claudeArchiveText = claudeArchiveContent
.filter((block) => block.type === "text")
.map((block) => block.text)
.join("");
if (claudeArchiveText.includes("private stale reasoning")) {
throw new Error("Claude received archived reasoning as text");
}
if (!claudeArchiveText.includes("inspect the repository")) {
throw new Error("Claude reasoning sanitization discarded the archive");
}
ctx.model = { ...model };
const cachedContextEvent = {
type: "context",
messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "verify artifact path", timestamp: Date.now() },
],
};
const artifactFileBackup = `${firstArtifactPath}.verified`;
renameSync(firstArtifactPath, artifactFileBackup);
symlinkSync(artifactFileBackup, firstArtifactPath);
console.warn = () => {};
let symlinkedFileContext;
try {
symlinkedFileContext = await context(cachedContextEvent, ctx);
} finally {
console.warn = originalWarn;
unlinkSync(firstArtifactPath);
renameSync(artifactFileBackup, firstArtifactPath);
}
if (
symlinkedFileContext?.messages[0]?.role !== "custom" ||
symlinkedFileContext.messages[0].customType !== "snapcompact-context-error"
) {
throw new Error("cached artifact bypassed a no-follow file check");
}
if (!readFileSync(firstArtifactPath).equals(firstArtifactData)) {
throw new Error("artifact file changed during no-follow verification");
}
const artifactDirectoryPath = dirname(firstArtifactPath);
const artifactDirectoryBackup = `${artifactDirectoryPath}-verified`;
renameSync(artifactDirectoryPath, artifactDirectoryBackup);
symlinkSync(artifactDirectoryBackup, artifactDirectoryPath);
console.warn = () => {};
let symlinkedDirectoryContext;
try {
symlinkedDirectoryContext = await context(cachedContextEvent, ctx);
} finally {
console.warn = originalWarn;
unlinkSync(artifactDirectoryPath);
renameSync(artifactDirectoryBackup, artifactDirectoryPath);
}
if (
symlinkedDirectoryContext?.messages[0]?.role !== "custom" ||
symlinkedDirectoryContext.messages[0].customType !== "snapcompact-context-error"
) {
throw new Error("cached artifact bypassed a canonical directory check");
}
const retainedImageCount = 3;
const withRetainedImages = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{
role: "user",
content: Array.from({ length: retainedImageCount }, (_, index) => ({
type: "image",
data: `retained-${index}`,
mimeType: "image/png",
})),
timestamp: Date.now(),
},
]}, ctx);
const budgetedArchiveImages = withRetainedImages.messages[0].content.filter(
(block) => block.type === "image",
).length;
const frozenArchiveImages = visual.content.filter((block) => block.type === "image").length;
if (budgetedArchiveImages !== frozenArchiveImages) {
throw new Error("retained tail images rewrote the archive prefix and busted prompt caching");
}
const projectedBranch = branch;
const legacyArtifact = structuredClone(firstArtifactDocument);
legacyArtifact.preserveData.snapcompact.text = [
"¶think:legacy private reasoning",
"¶call:one()█\u000elegacy result 1\u000f█",
"¶call:two()█\u000elegacy result 2\u000f█",
"¶call:three()█\u000elegacy result 3\u000f█",
"¶call:four()█\u000elegacy result 4\u000f█",
].join("█");
delete legacyArtifact.preserveData.snapcompact.textHead;
delete legacyArtifact.preserveData.snapcompact.textTail;
legacyArtifact.preserveData.snapcompact.truncatedChars = 0;
const legacyData = JSON.stringify(legacyArtifact);
const legacyFile = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa.json";
writeFileSync(join(firstArtifactPath, "..", legacyFile), legacyData, { mode: 0o600 });
const legacyDetails = structuredClone(first.compaction.details);
delete legacyDetails.snapcompact.projectionVersion;
legacyDetails.snapcompact.artifact = {
file: legacyFile,
bytes: Buffer.byteLength(legacyData),
sha256: createHash("sha256").update(legacyData).digest("hex"),
};
branch = [
{ ...compactionEntry, id: "legacy-compaction", details: legacyDetails },
{ type: "message", id: "legacy-recent", parentId: "legacy-compaction", timestamp: Date.now(), message: { role: "user", content: "continue legacy", timestamp: Date.now() } },
];
const legacyHydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "continue legacy", timestamp: Date.now() },
]}, ctx);
if (legacyHydrated.messages[0].content.some((block) => block.type === "image")) {
throw new Error("legacy unprojected archive replayed image frames");
}
const legacyText = legacyHydrated.messages[0].content
.filter((block) => block.type === "text")
.map((block) => block.text)
.join("");
if (legacyText.includes("legacy private reasoning") || legacyText.includes("legacy result 1")) {
throw new Error("legacy archive text was not destructively sanitized");
}
for (const exact of ["legacy result 2", "legacy result 3", "legacy result 4"]) {
if (!legacyText.includes(exact)) throw new Error(`legacy archive lost ${exact}`);
}
const truncatedLegacyArtifact = structuredClone(firstArtifactDocument);
truncatedLegacyArtifact.preserveData.snapcompact.textHead =
"¶user:verified legacy prefix█¶call:cut()█\u000eTRUNCATED-LEGACY-SECRET";
truncatedLegacyArtifact.preserveData.snapcompact.text =
`${truncatedLegacyArtifact.preserveData.snapcompact.textHead}untrusted omitted middle`;
truncatedLegacyArtifact.preserveData.snapcompact.truncatedChars = 1000;
const truncatedLegacyData = JSON.stringify(truncatedLegacyArtifact);
const truncatedLegacyFile = "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb.json";
writeFileSync(join(firstArtifactPath, "..", truncatedLegacyFile), truncatedLegacyData, { mode: 0o600 });
const truncatedLegacyDetails = structuredClone(legacyDetails);
truncatedLegacyDetails.snapcompact.artifact = {
file: truncatedLegacyFile,
bytes: Buffer.byteLength(truncatedLegacyData),
sha256: createHash("sha256").update(truncatedLegacyData).digest("hex"),
};
branch = [
{ ...compactionEntry, id: "truncated-legacy-compaction", details: truncatedLegacyDetails },
{ type: "message", id: "truncated-legacy-recent", parentId: "truncated-legacy-compaction", timestamp: Date.now(), message: { role: "user", content: "continue safely", timestamp: Date.now() } },
];
const truncatedLegacyHydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "continue safely", timestamp: Date.now() },
]}, ctx);
const truncatedLegacyText = truncatedLegacyHydrated.messages[0].content
.filter((block) => block.type === "text")
.map((block) => block.text)
.join("");
if (
truncatedLegacyHydrated.messages[0].content.some((block) => block.type === "image") ||
truncatedLegacyText.includes("TRUNCATED-LEGACY-SECRET") ||
!truncatedLegacyText.includes("verified legacy prefix") ||
!truncatedLegacyText.includes("[tool result]")
) {
throw new Error("truncated legacy archive did not degrade to its sanitized head");
}
branch = projectedBranch;
ctx.model = { ...model, id: "different-model-same-provider" };
const switched = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "continue after model switch", timestamp: Date.now() },
]}, ctx);
const switchedImages = switched.messages[0].content.filter((block) => block.type === "image").length;
if (switchedImages > 5) throw new Error("same-provider model switch reused an unsafe producer frame budget");
// Frozen epoch layout: block bytes must not depend on the live window or the
// growing tail. Every rehydration of the same archive must be byte-identical,
// otherwise each change busts the prompt cache back to the system prefix.
const blockSignature = (content) => createHash("sha256").update(JSON.stringify(content)).digest("hex");
let frozenSignature = blockSignature(visual.content);
for (let turn = 0; turn < 20; turn++) {
ctx.model = turn % 2 === 0 ? { ...model, contextWindow: 10_000, maxTokens: 8192 } : { ...model };
const turnHydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
...Array.from({ length: turn }, (_, i) => ({
role: "user",
content: [
{ type: "text", text: `tail ${i} ${longText.slice(0, 400)}` },
{ type: "image", data: `tail-image-${i}`, mimeType: "image/png" },
],
timestamp: Date.now() + i,
})),
]}, ctx);
const signature = blockSignature(turnHydrated.messages[0].content);
if (signature !== frozenSignature) {
throw new Error(`vision archive blocks changed at tail step ${turn}; prompt cache would bust`);
}
}
ctx.model = { ...model };
ctx.model = { ...model, input: ["text"], contextWindow: 10_000, maxTokens: 8192 };
const exhaustedText = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "text context is already full", timestamp: Date.now() },
]}, ctx);
if (exhaustedText.messages[0].content.length !== 1) {
throw new Error("exhausted text context forced archive text past zero budget");
}
ctx.model = { ...model };
const previousSessionFile = activeSessionFile;
const mismatchedSessionId = "77777777-7777-4777-8777-777777777777";
activeSessionId = mismatchedSessionId;
activeSessionFile = `${sessionDir}/${activeSessionId}.jsonl`;
writeFileSync(activeSessionFile, `${JSON.stringify({
type: "session",
version: 3,
id: "88888888-8888-4888-8888-888888888888",
timestamp: new Date().toISOString(),
cwd: process.cwd(),
parentSession: previousSessionFile,
})}\n`);
console.warn = () => {};
await sessionStart({ type: "session_start", reason: "startup" }, ctx);
console.warn = originalWarn;
if (existsSync(join(root, "sessions", "session-artifacts", mismatchedSessionId))) {
throw new Error("mismatched current session header copied fork artifacts");
}
const maliciousSessionId = "44444444-4444-4444-8444-444444444444";
activeSessionId = maliciousSessionId;
activeSessionFile = `${sessionDir}/${activeSessionId}.jsonl`;
writeFileSync(activeSessionFile, `${JSON.stringify({
type: "session",
version: 3,
id: maliciousSessionId,
timestamp: new Date().toISOString(),
cwd: process.cwd(),
parentSession: resolve(sessionDir, ".."),
})}\n`);
console.warn = () => {};
await sessionStart({ type: "session_start", reason: "startup" }, ctx);
console.warn = originalWarn;
const maliciousArtifactDirectory = join(
root,
"sessions",
"session-artifacts",
maliciousSessionId,
"snapcompact",
);
if (existsSync(maliciousArtifactDirectory)) {
throw new Error("invalid CLI parent session escaped into an artifact copy");
}
const forkSessionId = "22222222-2222-4222-8222-222222222222";
activeSessionId = forkSessionId;
activeSessionFile = `${sessionDir}/${activeSessionId}.jsonl`;
writeFileSync(activeSessionFile, `${JSON.stringify({
type: "session",
version: 3,
id: forkSessionId,
timestamp: new Date().toISOString(),
cwd: process.cwd(),
parentSession: previousSessionFile,
})}\n`);
await sessionStart({ type: "session_start", reason: "startup" }, ctx);
const forkArtifact = join(
root,
"sessions",
"session-artifacts",
forkSessionId,
"snapcompact",
ref1.file,
);
if (!existsSync(forkArtifact)) throw new Error("CLI startup fork did not copy its inherited SnapCompact artifact");
const forkHydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "continue fork", timestamp: Date.now() },
]}, ctx);
if (!forkHydrated.messages[0].content.some((block) => block.type === "image")) {
throw new Error("forked context did not rehydrate copied archive images");
}
const orphan = join(forkArtifact, "..", "33333333-3333-4333-8333-333333333333.json");
writeFileSync(orphan, "orphan", { mode: 0o600 });
await sessionCompact({ type: "session_compact", compactionEntry, fromExtension: true }, ctx);
if (existsSync(orphan)) throw new Error("artifact cleanup did not remove an unreferenced artifact");
if (!existsSync(forkArtifact)) throw new Error("artifact cleanup removed a referenced fork artifact");
const nextMessages = [
{ role: "user", content: "implement and test the fix", timestamp: 3 },
{
role: "assistant",
content: [
{ type: "text", text: "test passed\n".repeat(3000) },
{ type: "toolCall", id: "current-1", name: "ipython", arguments: {} },
{ type: "toolCall", id: "current-2", name: "ipython", arguments: {} },
{ type: "toolCall", id: "empty", name: "ipython", arguments: {} },
{ type: "toolCall", id: "useless", name: "ipython", arguments: {} },
],
api: model.api,
provider: model.provider,
model: model.id,
usage,
stopReason: "toolUse",
timestamp: 4,
},
toolResult("current-1", "current exact output 1"),
toolResult("current-2", "current exact output 2"),
{ ...toolResult("empty", ""), content: [] },
{ ...toolResult("useless", "no matches"), useless: true },
];
const second = await before({ type: "session_before_compact", preparation: prep(nextMessages, first.compaction.summary), branchEntries: branch, customInstructions: undefined, signal: controller.signal }, ctx);
if (!second?.compaction?.details?.snapcompact?.artifact) throw new Error("repeat compaction missing artifact");
if (second.compaction.details.snapcompact.artifact.sha256 === ref1.sha256) throw new Error("repeat compaction did not create a new archive");
if (JSON.stringify(second.compaction.details).includes("iVBORw0KGgo")) throw new Error("repeat details inlined PNG data");
const secondArtifactPath = join(
root,
"sessions",
"session-artifacts",
activeSessionId,
"snapcompact",
second.compaction.details.snapcompact.artifact.file,
);
const secondArchive = JSON.parse(readFileSync(secondArtifactPath, "utf8")).preserveData.snapcompact;
if (secondArchive.frames.some((frame) => frame.font !== "silver")) {
throw new Error("repeat compaction did not retain the prior non-Latin-safe render shape");
}
const secondArchiveText = secondArchive.text ?? "";
for (const exact of [recentExactOutput, "current exact output 1", "current exact output 2"]) {
if (!secondArchiveText.includes(exact)) {
throw new Error(`empty or useless current result displaced ${exact.slice(0, 24)}`);
}
}
for (const removed of ["second exact output", "third exact output", "injected suffix", "no matches"]) {
if (secondArchiveText.includes(removed)) {
throw new Error(`historical result masking retained ${removed}`);
}
}
ctx.model = { ...model, input: ["text"], contextWindow: 128000 };
const textHydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
{ role: "user", content: "continue in text", timestamp: Date.now() },
]}, ctx);
if (textHydrated.messages[0].content.some((block) => block.type === "image")) throw new Error("text-only context contains images");
const textChars = textHydrated.messages[0].content.reduce((n, block) => n + (block.type === "text" ? block.text.length : 0), 0);
if (textChars > 128000 * 3) throw new Error("text-only context was not bounded");
const frozenTextSignature = blockSignature(textHydrated.messages[0].content);
for (let turn = 0; turn < 20; turn++) {
const turnHydrated = await context({ type: "context", messages: [
{ role: "compactionSummary", summary: first.compaction.summary, tokensBefore: first.compaction.tokensBefore, timestamp: Date.now() },
...Array.from({ length: turn }, (_, i) => ({ role: "user", content: `text tail ${i} ${longText.slice(0, 400)}`, timestamp: Date.now() + i })),
]}, ctx);
if (blockSignature(turnHydrated.messages[0].content) !== frozenTextSignature) {
throw new Error(`text archive blocks changed at tail step ${turn}; prompt cache would bust`);
}
}
ctx.model = { ...model, contextWindow: 20000, maxTokens: 4096 };
console.warn = () => {};
const workerFailureWithArchive = await before({ type: "session_before_compact", preparation: prep(nextMessages, first.compaction.summary), branchEntries: branch, customInstructions: undefined, signal: controller.signal }, ctx);
console.warn = originalWarn;
if (workerFailureWithArchive?.cancel !== true) throw new Error("worker failure with an existing archive did not cancel safely");
ctx.model = { ...model, input: ["text"], contextWindow: 20000, maxTokens: 4096 };
console.warn = () => {};
const manual = await before({ type: "session_before_compact", preparation: prep(nextMessages, first.compaction.summary), branchEntries: branch, customInstructions: "focus on tests", signal: controller.signal }, ctx);
console.warn = originalWarn;
if (manual?.cancel !== true) throw new Error("oversize manual text migration did not cancel safely");
console.log(JSON.stringify({
firstDetailsBytes: Buffer.byteLength(detailsJson),
firstFrames: images.length,
switchedModelFrames: switchedImages,
exhaustedBudgetArchiveBlocks: 0,
forkArtifactCopied: true,
orphanGc: true,
repeatFont: "silver",
firstArtifactBytes: ref1.bytes,
repeatArtifactBytes: second.compaction.details.snapcompact.artifact.bytes,
textContextChars: textChars,
firstFailureNativeFallback: initialFailure?.compaction !== undefined,
existingFailureCancelled: workerFailureWithArchive.cancel,
manualOversizeCancelled: manual.cancel,
}, null, 2));
rmSync(root, { recursive: true, force: true });