diff --git a/src/core/remediation/context.ts b/src/core/remediation/context.ts index 8599df699..e34bddcfe 100644 --- a/src/core/remediation/context.ts +++ b/src/core/remediation/context.ts @@ -8,6 +8,7 @@ import type { BrainEngine } from '../engine.ts'; import type { RecommendationContext } from '../brain-score-recommendations.ts'; +import { LINK_EXTRACTOR_VERSION_TS } from '../link-extraction.ts'; // Re-export so consumers can `import { RecommendationContext } from '../remediation'` // — the canonical RecommendationContext type still lives in @@ -74,9 +75,13 @@ export async function loadRecommendationContext( /** * Real extraction-lag count — the SAME staleness `gbrain extract --stale` - * processes (engine.countStalePagesForExtraction). Drives the sync→extract - * recommendation pipeline; replaces the legacy `health.stale_pages` proxy - * that no longer reflected real extraction work after the v10 trigger drop. + * processes (engine.countStalePagesForExtraction with + * versionTs=LINK_EXTRACTOR_VERSION_TS, matching doctor's links_extraction_lag + * check — without versionTs, pages stamped before an extractor version bump + * would lag for doctor/extract but never trip this gate). Drives the + * sync→extract recommendation pipeline; replaces the legacy + * `health.stale_pages` proxy that no longer reflected real extraction work + * after the v10 trigger drop. * * Shared by loadRecommendationContext AND the D7 per-step recheck in * runRemediation — the recheck MUST refresh this gate alongside getHealth, @@ -84,7 +89,7 @@ export async function loadRecommendationContext( */ export async function countExtractionLag(engine: BrainEngine): Promise { try { - return await engine.countStalePagesForExtraction(); + return await engine.countStalePagesForExtraction({ versionTs: LINK_EXTRACTOR_VERSION_TS }); } catch { /* counter unavailable (very old brain / mid-migration) — treat as 0 */ return 0; diff --git a/test/remediation-context-extraction-lag.test.ts b/test/remediation-context-extraction-lag.test.ts index 94a0ad362..7ac7ab1af 100644 --- a/test/remediation-context-extraction-lag.test.ts +++ b/test/remediation-context-extraction-lag.test.ts @@ -44,4 +44,19 @@ describe('loadRecommendationContext — extractionLagPages wiring', () => { const ctx = await loadRecommendationContext(engine); expect(ctx.extractionLagPages).toBeGreaterThan(0); }); + + it('counts pages stamped before LINK_EXTRACTOR_VERSION_TS (version-bump arm)', async () => { + // Backdate p0 so BOTH the NULL arm and the updated_at arm are quiet: + // updated_at < links_extracted_at, but links_extracted_at predates the + // extractor version stamp. doctor's links_extraction_lag and + // `extract --stale` both count this page; the remediation gate must too. + await engine.executeRaw( + `UPDATE pages SET updated_at = '2020-01-01T00:00:00Z'::timestamptz, + links_extracted_at = '2020-01-02T00:00:00Z'::timestamptz + WHERE slug = 'p0'`, + [], + ); + const ctx = await loadRecommendationContext(engine); + expect(ctx.extractionLagPages).toBeGreaterThan(0); + }); });