Phase 15: add B-003 regression script with unit gate and artifact audit
Run compaction fallback, kept inject, and mid-turn steer tests; document lost-reinject.jsonl auto→null source signature from the original bug. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Executable
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Phase 15 regression gate for B-003 (mid-turn / missed reinject).
|
||||
*
|
||||
* 1. Runs focused unit tests for source fallback, kept inject entries, mid-turn steer.
|
||||
* 2. Audits lost-reinject.jsonl (if present) for the pre-fix failure signature.
|
||||
*
|
||||
* Full two-compact RPC E2E needs a long session; use manual checklist in TODO.md §15.
|
||||
*/
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { resolve, dirname } from "node:path";
|
||||
|
||||
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const artifactPath = resolve(repoRoot, "lost-reinject.jsonl");
|
||||
|
||||
const unitPatterns = [
|
||||
"test/compaction-source-fallback.test.ts",
|
||||
"test/kept-window.test.ts",
|
||||
"test/reinject-mid-turn.test.ts",
|
||||
"test/reinject-double-compact.test.ts",
|
||||
];
|
||||
|
||||
function runUnitGate() {
|
||||
const result = spawnSync("npm", ["test", "--", ...unitPatterns], {
|
||||
cwd: repoRoot,
|
||||
stdio: "inherit",
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
process.exit(result.status ?? 1);
|
||||
}
|
||||
}
|
||||
|
||||
function auditLostReinjectArtifact() {
|
||||
if (!existsSync(artifactPath)) {
|
||||
console.log("b003-repro: lost-reinject.jsonl not found — skip artifact audit");
|
||||
return;
|
||||
}
|
||||
const lines = readFileSync(artifactPath, "utf8").split("\n").filter(Boolean);
|
||||
const stateEntries = [];
|
||||
const injectEntries = [];
|
||||
for (const line of lines) {
|
||||
try {
|
||||
const entry = JSON.parse(line);
|
||||
if (entry.customType === "skill-reinject:state" && entry.data) {
|
||||
stateEntries.push({
|
||||
id: entry.id,
|
||||
ts: entry.timestamp,
|
||||
lastCompactionSource: entry.data.lastCompactionSource,
|
||||
pendingReinject: entry.data.pendingReinject ?? [],
|
||||
});
|
||||
}
|
||||
if (entry.type === "custom_message" && entry.customType === "skill-reinject:inject") {
|
||||
injectEntries.push({ id: entry.id, ts: entry.timestamp });
|
||||
}
|
||||
} catch {
|
||||
// skip malformed lines
|
||||
}
|
||||
}
|
||||
const nullSourceAfterAuto = stateEntries.filter(
|
||||
(entry, index) =>
|
||||
index > 0 &&
|
||||
entry.lastCompactionSource === null &&
|
||||
stateEntries[index - 1]?.lastCompactionSource === "auto",
|
||||
);
|
||||
console.log("b003-repro artifact audit:");
|
||||
console.log(` state snapshots: ${stateEntries.length}`);
|
||||
console.log(` skill-reinject:inject messages: ${injectEntries.length}`);
|
||||
console.log(` auto→null source transitions (pre-fix bug): ${nullSourceAfterAuto.length}`);
|
||||
if (nullSourceAfterAuto.length > 0) {
|
||||
console.log(" sample null-source entry:", JSON.stringify(nullSourceAfterAuto[0]));
|
||||
console.log(
|
||||
" post-fix expectation: ensureCompactionSourceMarked on session_compact → lastCompactionSource: auto",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("b003-repro: running unit regression gate…");
|
||||
runUnitGate();
|
||||
auditLostReinjectArtifact();
|
||||
console.log("b003-repro: PASS (unit gate)");
|
||||
Reference in New Issue
Block a user