WIP: Unified Housekeeping rebuild / Gecombineerde Housekeeping-herbouw #53

Closed
Simo wants to merge 68 commits from codex/housekeeping-rebuild-stepwise into main
pull from: codex/housekeeping-rebuild-stepwise
2 changed files with 43 additions and 5 deletions
Showing only changes of commit f2e67ebace - Show all commits

No files matched your search

@@ -0,0 +1,34 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
describe("StudioClient batch completion contract", () => {
it("marks React state without recursively invoking its completion callback", () => {
const source = readFileSync(
new URL("./studio-client.tsx", import.meta.url),
"utf8",
);
const callbackBody = source.match(
/const markBatchDone = useCallback\(\(\) => \{([\s\S]*?)\n\t\}, \[\]\);/,
)?.[1];
expect(callbackBody).toBeDefined();
expect(callbackBody).toContain("setBatchDone(true);");
expect(callbackBody).not.toContain("markBatchDone();");
});
it("resets the completion ref and React state before every batch", () => {
const source = readFileSync(
new URL("./studio-client.tsx", import.meta.url),
"utf8",
);
const callbackBody = source.match(
/const resetBatchDone = useCallback\(\(\) => \{([\s\S]*?)\n\t\}, \[\]\);/,
)?.[1];
expect(callbackBody).toBeDefined();
expect(callbackBody).toContain("batchDoneRef.current = false;");
expect(callbackBody).toContain("setBatchDone(false);");
expect(source.match(/resetBatchDone\(\);/g)).toHaveLength(4);
expect(source.match(/setBatchDone\(false\);/g)).toHaveLength(1);
});
});
@@ -154,7 +154,11 @@ export function StudioClient({
const batchDoneRef = useRef(false);
const markBatchDone = useCallback(() => {
batchDoneRef.current = true;
markBatchDone();
setBatchDone(true);
}, []);
const resetBatchDone = useCallback(() => {
batchDoneRef.current = false;
setBatchDone(false);
}, []);
const [batchSucceeded, setBatchSucceeded] = useState(0);
const [batchFailed, setBatchFailed] = useState(0);
@@ -430,7 +434,7 @@ export function StudioClient({
initial.set(cn, { classname: cn, status: "pending" });
}
setBatchProgress(initial);
setBatchDone(false);
resetBatchDone();
setBatchSucceeded(0);
setBatchFailed(0);
setFailedClassnames([]);
@@ -693,7 +697,7 @@ export function StudioClient({
return;
}
setBatchDone(false);
resetBatchDone();
setBatchSucceeded(0);
setBatchFailed(0);
setBatchCancelling(false);
@@ -831,7 +835,7 @@ export function StudioClient({
async function retryFailed(failed: string[]) {
if (!activeSource || failed.length === 0) return;
// For clone sources, re-run cloneAllMissing with only the failed classnames
setBatchDone(false);
resetBatchDone();
setBatchSucceeded(0);
setBatchFailed(0);
setFailedClassnames([]);
@@ -1957,7 +1961,7 @@ export function StudioClient({
onCancel={cloneAllAbortRef.current ? cancelCloneAll : cancelBatch}
onDismiss={() => {
setBatchProgress(null);
setBatchDone(false);
resetBatchDone();
setVerification(null);
setFailedClassnames([]);
}}