- backup.mjs restore(relPaths): SCOPED per-fil-rollback erstatter hel-tre rmSync(srcDir)+cpSync. Ruller kun tilbake kjøringens egne skriv; parallelle økters skriv til søsken-filer overlever; intet destruktivt rm→cp-vindu. Nyskapte filer slettes; prior bytes gjenopprettes atomisk. - migrate-corpus.mjs: returnert restore() er nå en null-arg closure bundet til kjøringens skrive- liste (public API uendret) → scoped. detectStaleRollback aborterer ved forrige krasj-sentinel; cleanupOldBackups pruner backups forbi retention etter vellykket batch. - 5 drivere (backfill-status/-category, dedup-plain-header, relabel-dato/-dialect): writeFileSync → atomicWriteSync (crash-safe tmp+rename) + recovery-kontrakt i header. - backfill-category.mjs: refaktorert importerbar (isMain-guard + run()/planCategoryBackfill/ categoryForFile/FOLDER_CATEGORY-eksporter, parameterisert root) → testbar uten scan-side-effekt. - Tester (+16): 6 scoped-restore (parallel-preservering, ny-fil-sletting, throws-guard) erstatter 2 hel-tre; test-backfill-category (frosset taxonomi + hermetisk plan); test-driver-atomic-writes (5 drivere); migrate stale-abort + cleanup-wiring. Suite 859→875 exit 0. validate-plugin 250/0.
29 lines
1.2 KiB
JavaScript
29 lines
1.2 KiB
JavaScript
// tests/kb-update/test-driver-atomic-writes.test.mjs
|
|
// RX-OPS2 acceptance: every corpus-writing driver routes its writes through the
|
|
// crash-safe atomicWriteSync (tmp+rename), never a bare writeFileSync that can leave a
|
|
// half-written reference file. Mirrors the existing migrate-corpus source guard
|
|
// (test-migrate-apply.test.mjs) for the five standalone drivers.
|
|
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { join, dirname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const KB = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'scripts', 'kb-update');
|
|
|
|
const DRIVERS = [
|
|
'backfill-status.mjs',
|
|
'backfill-category.mjs',
|
|
'dedup-plain-header.mjs',
|
|
'relabel-dato.mjs',
|
|
'relabel-dialect.mjs',
|
|
];
|
|
|
|
for (const driver of DRIVERS) {
|
|
test(`${driver} — writes corpus files via atomicWriteSync, never bare writeFileSync`, () => {
|
|
const src = readFileSync(join(KB, driver), 'utf8');
|
|
assert.match(src, /atomicWriteSync/, `${driver} must import/use the atomic writer`);
|
|
assert.doesNotMatch(src, /\bwriteFileSync\b/, `${driver} must not call writeFileSync directly`);
|
|
});
|
|
}
|