diff --git a/src/commands/doctor.ts b/src/commands/doctor.ts index b918ed8ef..e7c446579 100644 --- a/src/commands/doctor.ts +++ b/src/commands/doctor.ts @@ -3742,7 +3742,9 @@ function collectMarkdownSlugs(root: string): Set { continue; } for (const e of entries) { - if (e.name.startsWith('.') || e.name === 'node_modules') continue; + // Hidden directories can contain canonical, tracked knowledge (for + // example `.archive/`). Only implementation metadata is never a page. + if (e.name === '.git' || e.name === 'node_modules') continue; const childRel = rel ? `${rel}/${e.name}` : e.name; if (e.isDirectory()) stack.push(childRel); else if (/\.mdx?$/i.test(e.name)) out.add(slugifyPath(childRel).toLowerCase()); diff --git a/src/core/config.ts b/src/core/config.ts index 4ab5a212e..6ac3daa25 100644 --- a/src/core/config.ts +++ b/src/core/config.ts @@ -1087,6 +1087,10 @@ export const KNOWN_CONFIG_KEYS: readonly string[] = [ // consent reads this key, and enabling it is the documented path to // `gbrain takes extract --from-pages` — same unregistered-key class. 'takes.bootstrap_enabled', + // Orphan reporting scope. These are consumed by core/orphan-policy.ts and + // documented there as the per-brain override path. + 'orphans.exclude_prefixes', + 'orphans.exclude_slugs', 'sync.cost_gate_min_usd', 'sync.federated_v2', 'embed.backfill_cooldown_min', diff --git a/test/config-set.test.ts b/test/config-set.test.ts index 05526b858..076d98af8 100644 --- a/test/config-set.test.ts +++ b/test/config-set.test.ts @@ -71,6 +71,11 @@ describe('KNOWN_CONFIG_KEYS', () => { expect(KNOWN_CONFIG_KEYS).not.toContain('conversation_parser.llm_polish_enabled'); }); + test('contains orphan-reporting override keys', () => { + expect(KNOWN_CONFIG_KEYS).toContain('orphans.exclude_prefixes'); + expect(KNOWN_CONFIG_KEYS).toContain('orphans.exclude_slugs'); + }); + test('no duplicate entries', () => { const set = new Set(KNOWN_CONFIG_KEYS); expect(set.size).toBe(KNOWN_CONFIG_KEYS.length); diff --git a/test/doctor-silent-death-checks.test.ts b/test/doctor-silent-death-checks.test.ts index d26e5b140..4269db426 100644 --- a/test/doctor-silent-death-checks.test.ts +++ b/test/doctor-silent-death-checks.test.ts @@ -150,6 +150,16 @@ describe('undeclared_db_only_pages (#2784)', () => { expect(c.status).toBe('ok'); }); + test('file-backed page under a canonical hidden directory → ok', async () => { + const repo = makeRepo(); + mkdirSync(join(repo, '.archive', 'people'), { recursive: true }); + writeFileSync(join(repo, '.archive', 'people', 'alice-example.md'), '# Alice'); + await addSource('src-a', repo); + await addPage('.archive/people/alice-example', { sourceId: 'src-a' }); + const c = await checkUndeclaredDbOnlyPages(engine); + expect(c.status).toBe('ok'); + }); + test('derive-phase default prefixes are implicitly declared', async () => { const repo = makeRepo(); await addSource('src-a', repo);