From c91262ac30737e5daeaf09c5f5a64b0f9b19ad32 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Fri, 27 Feb 2026 13:28:40 -0800 Subject: [PATCH] fix(audit): tolerate missing phase0 artifact dir in prune Treat missing artifacts dir as empty input for prune planning/apply workflows on fresh hosts; keep report output behavior intact. Architecture/protocol diagrams reviewed; no updates needed for this script robustness change. --- docs/plans/state.json | 11 +++++++++++ scripts/prune-phase0-baseline-artifacts.ts | 15 +++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/plans/state.json b/docs/plans/state.json index b3bd7e0..6157d09 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -593,6 +593,17 @@ ], "test_status": "pnpm typecheck + node --import tsx/esm scripts/check-phase0-baseline-backend-drift.ts --artifacts-dir docs/plans/artifacts --backend native,native --format json + synthetic-audit capture smoke check passing" }, + "phase0-live-baseline-prune-missing-dir-resilience": { + "status": "completed", + "date": "2026-02-27", + "updated": "2026-02-27", + "summary": "Hardened prune CLI behavior for fresh hosts by treating a missing artifacts directory as an empty artifact set (instead of failing with ENOENT), while preserving report generation behavior.", + "files_modified": [ + "scripts/prune-phase0-baseline-artifacts.ts", + "docs/plans/state.json" + ], + "test_status": "pnpm typecheck + node --import tsx/esm scripts/prune-phase0-baseline-artifacts.ts --artifacts-dir --format json passing" + }, "phase0-instrumentation-ticket-checklist": { "status": "completed", "date": "2026-02-25", diff --git a/scripts/prune-phase0-baseline-artifacts.ts b/scripts/prune-phase0-baseline-artifacts.ts index fdf17ba..ac77f9c 100644 --- a/scripts/prune-phase0-baseline-artifacts.ts +++ b/scripts/prune-phase0-baseline-artifacts.ts @@ -15,7 +15,7 @@ function usage(): string { '', 'Options:', ' --artifacts-dir Artifacts directory (default: docs/plans/artifacts)', - ' --keep-per-family Keep newest rolling tags per family (default: 8)', + ' --keep-per-family Keep newest rolling tags per family (default: 8)', ' --apply Apply deletions (default: dry-run)', ' --report-tag Report tag suffix (default: current UTC date)', ' --write-default-artifacts Write report files to artifacts dir', @@ -78,6 +78,17 @@ async function writeTextFile(pathValue: string, contents: string): Promise await writeFile(pathValue, `${contents}\n`, 'utf8'); } +async function readArtifactFileNames(artifactsDir: string): Promise { + try { + return await readdir(artifactsDir); + } catch (error) { + if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') { + return []; + } + throw error; + } +} + async function main(): Promise { const { values } = parseArgs({ options: { @@ -123,7 +134,7 @@ async function main(): Promise { ? `${defaultBaseName}.md` : undefined; - const files = await readdir(artifactsDir); + const files = await readArtifactFileNames(artifactsDir); const plan = planRollingPhase0ArtifactRetention(files, keepPerFamily); if (apply) {