/** * 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