/**
 * WikiLintService — deterministic validation pass over a vault.
 *
 * Per v2.1 spec §3, the third Phase 1 skill (alongside `wiki-ingest` and
 * `wiki-query`). Unlike `wiki-bookkeep` (vault HEALTH metrics — counts,
 * recent activity, duplicate clusters), lint focuses on CORRECTNESS:
 *
 *   - **frozenPathRespected** — no markdown content in folders flagged
 *     `frozen: true` in SCHEMA.md (other than the SCHEMA.md itself /
 *     legitimate frozen content). Lint refuses to alter frozen paths.
 *   - **missingEntities** — `[[wikilinks]]` that don't resolve to any
 *     page in the vault. Either the target was renamed, deleted, or the
 *     wikilink was made up. The lint flags them; the agent decides.
 *   - **orphanPages** — pages with zero incoming wikilinks, excluding
 *     seed pages (log.md, index.md, README*). These are candidates for
 *     either deletion or new linking.
 *   - **staleClaims** — files un-touched for `staleDays` (default 90).
 *   - **restructureProposals** — heuristics for llm-curated/ only: large
 *     un-indexed folders, near-duplicate filenames.
 *
 * The service never writes. The agent's LLM reads the report and decides
 * whether to ingest a consolidation, archive stale pages, etc.
 *
 * @module services/wiki/wiki-lint.service
 */
/** Default age threshold (days) for marking a page stale. */
export declare const WIKI_LINT_DEFAULT_STALE_DAYS = 90;
/** Folder size threshold above which lint proposes an `index.md` rollup. */
export declare const WIKI_LINT_ROLLUP_THRESHOLD = 20;
/** Max number of pages walked per lint pass. */
export declare const WIKI_LINT_MAX_PAGES = 1000;
/** Cap per category to keep the payload bounded. */
export declare const WIKI_LINT_MAX_ROWS_PER_SECTION = 50;
/** Pages with these basenames never count as "orphans". */
export declare const WIKI_LINT_SEED_BASENAMES: Set<string>;
/**
 * A `[[wikilink]]` target is "concept-shaped" (vs a dangling typo) when
 * it appears at least this many times across the vault. Below this, the
 * unresolved target is just noise; at or above this, the concept is
 * load-bearing and deserves its own page.
 */
export declare const WIKI_LINT_MISSING_CONCEPT_THRESHOLD = 3;
export interface WikiLintInput {
    vaultPath: string;
    staleDays?: number;
}
export interface WikiLintFrozenViolation {
    /** Relative path of the offending file. */
    path: string;
    /** The frozen folder it lives in. */
    frozenFolder: string;
}
export interface WikiLintMissingEntity {
    /** Page that contains the dangling wikilink. */
    sourcePath: string;
    /** The unresolved wikilink target. */
    target: string;
    /** Line number in the source page (1-based). */
    lineNumber: number;
}
export interface WikiLintRestructureProposal {
    /** Plain-English description of the proposal, e.g. "folder X has 31 pages without an index.md — propose llm-curated/X/index.md". */
    description: string;
    /** Optional related path (folder or page). */
    path?: string;
}
/**
 * A wikilink target that appears repeatedly across the vault but has no
 * dedicated page. Karpathy's lint contract names this explicitly:
 * *"important concepts mentioned but lacking their own page."* Different
 * from `missingEntities` (which is one-off dangling refs / typos):
 * `missingConcepts` is **frequency-weighted** signal that the team keeps
 * mentioning a thing → write a page for it.
 */
export interface WikiLintMissingConcept {
    /** The wikilink target referenced (e.g. `verify-output`). */
    target: string;
    /** How many distinct wikilink occurrences resolved to nothing. */
    referenceCount: number;
    /** Sample sources (capped) that reference this concept. */
    sources: string[];
}
export interface WikiLintReport {
    vault: {
        scope: string;
        id: string;
        path: string;
    };
    generatedAt: string;
    staleDays: number;
    frozenPathRespected: boolean;
    frozenViolations: WikiLintFrozenViolation[];
    missingEntities: WikiLintMissingEntity[];
    /** New 2026-05-26: frequency-weighted "missing concept" signals. */
    missingConcepts: WikiLintMissingConcept[];
    orphanPages: string[];
    staleClaims: string[];
    restructureProposals: WikiLintRestructureProposal[];
    truncated: boolean;
}
export type WikiLintOutcome = {
    ok: true;
    report: WikiLintReport;
} | {
    ok: false;
    reason: 'vault_missing' | 'schema_missing' | 'invalid_input';
    message: string;
};
/**
 * Singleton lint service. Stateless — pattern mirrors the other wiki
 * services so the controller wiring is uniform.
 */
export declare class WikiLintService {
    private static instance;
    private readonly logger;
    private readonly schemaLoader;
    private constructor();
    static getInstance(): WikiLintService;
    static resetInstance(): void;
    /**
     * Generate a lint report for the given vault.
     */
    generate(input: WikiLintInput): Promise<WikiLintOutcome>;
    /**
     * Recursive walk collecting `.md` files. Honors `WIKI_LINT_MAX_PAGES`.
     */
    private collectFiles;
    /**
     * Find `.md` files that live inside any frozen folder. SCHEMA.md and
     * legitimate sibling files inside frozen dirs (e.g. `sop/<role>.md`)
     * are excluded — frozen folders ARE allowed to contain content; what's
     * NOT allowed is `wiki-ingest` writing INTO them. That's a runtime
     * check elsewhere. Lint surfaces files only when they look like they
     * were created by ingest patterns (timestamp-prefixed slugs).
     */
    private detectFrozenViolations;
    /**
     * One read pass per file: pulls `[[wikilink]]` references, builds the
     * inverse "incoming" map for orphan detection, and emits missing-entity
     * rows for any link that resolves to nothing.
     */
    private scanWikilinks;
    /**
     * A page is an orphan when no other page wikilinks to it AND it is
     * not a seed page (log.md / index.md / README.md / SCHEMA.md).
     */
    private detectOrphans;
    /**
     * Find load-bearing concepts referenced repeatedly across the vault
     * but lacking a dedicated page. Karpathy's lint contract names this:
     * *"important concepts mentioned but lacking their own page."*
     *
     * Frequency-filtered (`WIKI_LINT_MISSING_CONCEPT_THRESHOLD`, default 3)
     * so we ignore typos and inline-code-style `[[X]]` brackets that aren't
     * meant as wikilinks. Distinct from `missingEntities`, which flags every
     * dangling ref individually.
     *
     * Results sort by referenceCount desc — highest-leverage concepts first.
     */
    private detectMissingConcepts;
    /**
     * Files whose content is older than `staleDays`.
     *
     * Migrated pages may have an `original_date` frontmatter field
     * (e.g. the legacy decision was made 2026-02-01 but we wrote the
     * markdown TODAY). Stale detection should respect the original date
     * when present — otherwise every freshly-migrated old page would look
     * "new" by mtime alone. Falls back to mtime when frontmatter is absent.
     */
    private detectStale;
    /**
     * Heuristic restructure proposals — only for `llm-curated/` since
     * frozen folders cannot be restructured.
     *
     * (1) A subfolder with > WIKI_LINT_ROLLUP_THRESHOLD pages and NO `index.md`
     *     gets an "add an index.md rollup" proposal.
     * (2) Near-duplicate filename prefixes (e.g. `pricing-v1.md`, `pricing-v2.md`)
     *     get a "consider merging" proposal.
     */
    private proposeRestructures;
}
//# sourceMappingURL=wiki-lint.service.d.ts.map