/** * PURE deterministic lesson hygiene: decay-based pruning + conflict quarantine. * * PURE — the clock is never read here; `now` is injected by the CLI handler * (mirrors reconcileFact's { now } pattern at reconcile.ts:54). Operates * ONLY on the fields each record carries; the CLI assembles recency input (createdAt) * by reading per-lesson files and passing it in via PrunableLesson.createdAt. * * Conflict detection: DETERMINISTIC — two lessons sharing the same contradiction key * (category root + discriminator tag) with opposing polarity markers are BOTH moved * to quarantine. No LLM. * * Decay: lessons below `minOccurrences` that are also older than `maxAgeMs` are * quarantined. Missing createdAt is treated as "maximally stale" (decays immediately * when occurrences are below threshold), which is conservative and documented here * as a deliberate choice — prefer to quarantine an unknown-age low-occurrence lesson * rather than silently keep it forever. */ import type { LessonIndexRecord } from "../../state/memory.js"; /** Default age threshold for decay: 30 days in milliseconds. */ export declare const THIRTY_DAYS_MS: number; /** A LessonIndexRecord enriched with CLI-derived recency proxy (ISO createdAt). */ export interface PrunableLesson extends LessonIndexRecord { /** ISO 8601 createdAt, assembled by the CLI from the per-lesson .md file. May be absent. */ createdAt?: string; } export interface PruneOptions { /** Injected ISO wall-clock — NEVER read inside this module. */ now: string; /** * Lessons with occurrences strictly below this value AND older than maxAgeMs * are quarantined as decayed. Default: 2. */ minOccurrences?: number; /** * Age threshold in milliseconds. A lesson is considered stale when * (now - createdAt) > maxAgeMs. Default: 30 days. */ maxAgeMs?: number; } export interface PruneResult { /** Lessons retained in INDEX.md. Sorted by lessonId ASC for byte-stability. */ kept: PrunableLesson[]; /** Lessons to be moved to QUARANTINE.md. Sorted by lessonId ASC for byte-stability. */ quarantined: PrunableLesson[]; } /** * Partition lessons into kept vs. quarantined. * * Phase 1 (conflict detection): identifies deterministically contradictory pairs. * A pair is contradictory when both records share the same contradiction key * (category root + discriminator tag) AND carry opposing polarity markers * (one "keep"-marked, one "avoid"-marked). BOTH are quarantined. * * Phase 2 (decay): for remaining records, quarantines those below `minOccurrences` * that are also stale (createdAt older than maxAgeMs, or createdAt absent). * * Both output arrays are sorted by lessonId ASC for byte-identical repeated runs. * * @param records - Enriched lesson records (with optional createdAt from CLI) * @param opts.now - ISO 8601 wall-clock, injected — never read inside * @param opts.minOccurrences - Below-threshold occurrence count (default 2) * @param opts.maxAgeMs - Staleness threshold in ms (default 30 days) */ export declare function pruneLessons(records: PrunableLesson[], { now, minOccurrences, maxAgeMs }: PruneOptions): PruneResult; //# sourceMappingURL=hygiene.d.ts.map