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