fix(doctor): exclude soft-deleted pages from raw_provenance check

Sibling frontmatter checks (quarantined_pages, flagged_pages) filter
deleted_at IS NULL; without it a deleted synthesized page keeps warning
(and its slug keeps being named) through the 72h recovery window with
no way to clear the warn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-07-23 15:38:32 -07:00
co-authored by Claude Fable 5
parent bf56e8cb8e
commit 566d3e2f75
2 changed files with 14 additions and 1 deletions
+2 -1
View File
@@ -549,7 +549,8 @@ export async function childTableOrphansCheck(engine: BrainEngine): Promise<Check
*/
export async function rawProvenanceCheck(engine: BrainEngine): Promise<Check> {
const where = `
(COALESCE(p.frontmatter->>'dream_generated', '') = 'true' OR p.type = 'synthesis')
p.deleted_at IS NULL
AND (COALESCE(p.frontmatter->>'dream_generated', '') = 'true' OR p.type = 'synthesis')
AND NOT (COALESCE(p.frontmatter, '{}'::jsonb) ?| ARRAY['raw_trace', 'raw_source', 'source_uri', 'raw_trace_exempt'])
AND NOT EXISTS (SELECT 1 FROM raw_data rd WHERE rd.page_id = p.id)
AND NOT EXISTS (SELECT 1 FROM synthesis_evidence se WHERE se.synthesis_page_id = p.id)`;
+12
View File
@@ -85,6 +85,18 @@ describe('rawProvenanceCheck (#1978, warn-only v1)', () => {
expect(result.status).toBe('ok');
});
test('soft-deleted violators are not flagged', async () => {
await engine.putPage('wiki/derived/deleted-no-trace', {
type: 'note', title: 'Deleted violator', compiled_truth: 'body', timeline: '',
frontmatter: { dream_generated: true },
});
expect((await rawProvenanceCheck(engine as unknown as BrainEngine)).status).toBe('warn');
await engine.executeRaw(
`UPDATE pages SET deleted_at = now() WHERE slug = 'wiki/derived/deleted-no-trace'`,
);
expect((await rawProvenanceCheck(engine as unknown as BrainEngine)).status).toBe('ok');
});
test('query failure degrades to warn, never throws', async () => {
const broken = { executeRaw: async () => { throw new Error('boom'); } } as unknown as BrainEngine;
const result = await rawProvenanceCheck(broken);