feat(audit): retain rolling phase0 prune reports

This commit is contained in:
William Valentin
2026-02-27 10:57:00 -08:00
parent 6e7a0aa37f
commit 7988d662e8
10 changed files with 83 additions and 8 deletions
@@ -12,20 +12,23 @@ describe('phase0BaselineArtifactRetention', () => {
'phase0_baseline_live_backend_pi_embedded_2026-02-27-010203.jsonl',
'phase0_baseline_live_backend_native_2026-02-27-010203.json',
'phase0_baseline_live_backend_drift_2026-02-27-010203.md',
'phase0_baseline_live_prune_2026-02-27-010203.json',
'phase0_baseline_live_2026-02-27.json',
'phase0_baseline_live_gateway_2026-02-27.jsonl',
'phase0_baseline_2026-02-25.md',
'phase0_baseline_live_backend_pi_embedded_2026-02-27.md',
'phase0_baseline_live_prune_2026-02-27.md',
'not_a_phase0_file.txt',
]);
expect(rows).toHaveLength(5);
expect(rows).toHaveLength(6);
expect(rows.map((row) => row.family).sort()).toEqual([
'backend_drift',
'backend_native',
'backend_pi_embedded',
'channel',
'gateway',
'prune',
]);
});
@@ -43,7 +46,10 @@ describe('phase0BaselineArtifactRetention', () => {
'phase0_baseline_live_backend_native_2026-02-27-020304.json',
'phase0_baseline_live_backend_drift_2026-02-27-010203.json',
'phase0_baseline_live_backend_drift_2026-02-27-020304.json',
'phase0_baseline_live_prune_2026-02-27-010203.json',
'phase0_baseline_live_prune_2026-02-27-020304.json',
'phase0_baseline_live_2026-02-27.json',
'phase0_baseline_live_prune_2026-02-27.json',
];
const plan = planRollingPhase0ArtifactRetention(files, 1);
@@ -53,6 +59,7 @@ describe('phase0BaselineArtifactRetention', () => {
{ family: 'backend_pi_embedded', total_tags: 2, keep_tags: 1, remove_tags: 1 },
{ family: 'backend_native', total_tags: 2, keep_tags: 1, remove_tags: 1 },
{ family: 'backend_drift', total_tags: 2, keep_tags: 1, remove_tags: 1 },
{ family: 'prune', total_tags: 2, keep_tags: 1, remove_tags: 1 },
]);
const removeSet = new Set(plan.remove.map((row) => row.file_name));
@@ -62,23 +69,28 @@ describe('phase0BaselineArtifactRetention', () => {
expect(removeSet.has('phase0_baseline_live_backend_pi_embedded_2026-02-27-010203.json')).toBe(true);
expect(removeSet.has('phase0_baseline_live_backend_native_2026-02-27-010203.json')).toBe(true);
expect(removeSet.has('phase0_baseline_live_backend_drift_2026-02-27-010203.json')).toBe(true);
expect(removeSet.has('phase0_baseline_live_prune_2026-02-27-010203.json')).toBe(true);
const keepSet = new Set(plan.keep.map((row) => row.file_name));
expect(keepSet.has('phase0_baseline_live_2026-02-27.json')).toBe(false);
expect(keepSet.has('phase0_baseline_live_prune_2026-02-27.json')).toBe(false);
expect(keepSet.has('phase0_baseline_live_2026-02-27-020304.json')).toBe(true);
expect(keepSet.has('phase0_baseline_live_2026-02-27-020304.md')).toBe(true);
expect(keepSet.has('phase0_baseline_live_prune_2026-02-27-020304.json')).toBe(true);
});
it('supports zero keep limit', () => {
const plan = planRollingPhase0ArtifactRetention([
'phase0_baseline_live_2026-02-27-010203.json',
'phase0_baseline_live_gateway_2026-02-27-010203.json',
'phase0_baseline_live_prune_2026-02-27-010203.md',
], 0);
expect(plan.keep).toHaveLength(0);
expect(plan.remove.map((row) => row.file_name).sort()).toEqual([
'phase0_baseline_live_2026-02-27-010203.json',
'phase0_baseline_live_gateway_2026-02-27-010203.json',
'phase0_baseline_live_prune_2026-02-27-010203.md',
]);
});
+6 -1
View File
@@ -3,7 +3,8 @@ export type Phase0RollingArtifactFamily =
| 'gateway'
| 'backend_pi_embedded'
| 'backend_native'
| 'backend_drift';
| 'backend_drift'
| 'prune';
export interface Phase0RollingArtifactFile {
file_name: string;
@@ -46,6 +47,10 @@ const FAMILY_PATTERNS: Array<{ family: Phase0RollingArtifactFamily; pattern: Reg
family: 'backend_drift',
pattern: /^phase0_baseline_live_backend_drift_(\d{4}-\d{2}-\d{2}-\d{6})\.(json|md)$/,
},
{
family: 'prune',
pattern: /^phase0_baseline_live_prune_(\d{4}-\d{2}-\d{2}-\d{6})\.(json|md)$/,
},
];
function parseRollingTagTimestampMs(tag: string): number | undefined {