/**
 * Stale `installed-packs.json` detector for the rule-engine UX nudge
 * fast-path (mmnto-ai/totem#1811, ADR-101).
 *
 * When `applyAstRulesToAdditions` hits a Tree-sitter language miss
 * (file extension mapped by no registered language), it normally
 * throws `TotemParseError` with an "install the pack" hint. After
 * `mmnto-ai/totem#1811` the rule-engine first asks this module
 * whether the user is one `totem sync --packs-only` away from a
 * working state — pre-1.27.0 manifest, missing manifest, malformed
 * cohort, or a cohort whose major.minor differs from the running
 * engine. Patch-level cohort drift passes (caret-range pack semver
 * tolerance — OQ2 disposition).
 */
import { TotemError } from './errors.js';
export type StaleManifestReason = 'no-manifest' | 'no-cohort' | 'cohort-mismatch';
export interface StaleManifestDetection {
    readonly reason: StaleManifestReason;
    /** Manifest's recorded cohort, if present and parseable. */
    readonly manifestCohort?: string;
    /** Running `@mmnto/totem` engine version. */
    readonly engineVersion: string;
}
export interface DetectStaleManifestOptions {
    /** Project root (where `.totem/` lives). */
    readonly workingDirectory: string;
    /** Totem directory name, defaults to `.totem`. */
    readonly totemDir?: string;
    /** Test seam: stub the engine-version resolver. */
    readonly resolveVersion?: () => string;
    /** Test seam: stub the file reader (returns null for ENOENT). */
    readonly readManifest?: (manifestPath: string) => string | null;
}
/**
 * Decide whether the running engine is ahead of (or out of sync with)
 * the manifest's recorded cohort. Returns `null` when no nudge is
 * warranted (manifest reads cleanly and major.minor matches the
 * engine), otherwise returns a structured detection that the caller
 * surfaces as a `STALE_MANIFEST` `TotemError`.
 *
 * Failure-mode discipline (Tenet 4):
 * - Manifest missing (ENOENT): `{ reason: 'no-manifest' }`.
 * - Manifest unreadable / non-JSON / fails schema: treated as missing
 *   (`'no-manifest'`). The lint-time path is a UX nudge, not a
 *   correctness gate; surfacing schema noise here would mask the
 *   underlying "user just needs to re-sync" signal.
 * - Cohort field absent (pre-1.27.0 manifest): `'no-cohort'`.
 * - Cohort field present but not semver-valid: `'no-cohort'`
 *   (defensive fallback — design doc spec line for malformed cohort).
 * - Cohort major.minor differs from engine: `'cohort-mismatch'`.
 * - `engineVersion` itself not semver-valid (defensive — should not
 *   happen given `resolveEngineVersion`'s '0.0.0' sentinel fallback,
 *   but a malformed `@mmnto/totem` package.json could surface one):
 *   return `null` so the caller falls through to the original
 *   `TotemParseError` unmasked. Source-level validation of engine
 *   version is tracked separately as mmnto-ai/totem#1829.
 */
export declare function detectStaleManifest(opts: DetectStaleManifestOptions): StaleManifestDetection | null;
/**
 * Build the `TotemError('STALE_MANIFEST', ...)` surfaced when a
 * Tree-sitter language miss collides with an out-of-sync manifest.
 * The diagnostic always points at the same recovery: `totem sync
 * --packs-only`. The message reflects which class of staleness
 * fired so users can correlate with their environment (CI vs local,
 * pre-1.27.0 manifest vs minor bump).
 */
export declare function staleManifestError(detection: StaleManifestDetection, context: {
    readonly file: string;
    readonly extension: string;
    readonly ruleHash: string;
}): TotemError;
//# sourceMappingURL=stale-manifest.d.ts.map