import type { CompiledRule } from './compiler-schema.js'; import type { Stage4VerificationResult } from './stage4-verifier.js'; import { type VerificationOutcomeEntry } from './verification-outcomes.js'; /** * The first-lint promotion interceptor (mmnto-ai/totem#1684 T5). * * Pack rules installed via `totem install` enter the consumer's manifest with * `status: 'pending-verification'` because the cloud-compile bootstrap path * cannot have run Stage 4 against the consumer's codebase. On the first * `totem lint` run after install, this module sweeps the manifest for those * pending entries, invokes the Stage 4 verifier on each, and replaces the * status with one of the four terminal lifecycle values per Invariant #3: * * - `'no-matches'` → `status: 'untested-against-codebase'` * - `'out-of-scope'` → `status: 'archived'` + `archivedReason` * - `'in-scope-bad-example'` → `status: 'active'` + `confidence: 'high'` * - `'candidate-debt'` → `status: 'active'` + `severity: 'warning'` * * Outcomes are written to `.totem/verification-outcomes.json` so subsequent * runs skip re-verification on rules whose `lessonHash` matches a recorded * outcome (Invariant #4). A pack content update produces a new `lessonHash` * which has no recorded outcome → verifier runs again (Invariant #5). * * Empty-pending fast path: when the manifest has zero `'pending-verification'` * rules, the function returns immediately without reading the outcomes file * (Invariant #9) — the common-case lint pass pays no verification cost. * * Per-rule try/catch isolates verifier-throws (Invariant #7): one rule's * failure does not abort the pass; that rule remains `'pending-verification'` * and the next lint retries. */ export interface PromotePendingRulesDeps { /** * Filesystem path to `.totem/verification-outcomes.json`. The interceptor * reads existing outcomes for memoization and atomically rewrites the * file when new outcomes are recorded. */ readonly outcomesPath: string; /** * Pre-wired Stage 4 verifier — typically a closure that builds the * `Stage4VerifierDeps` once (git ls-files, baseline resolution) and then * invokes `verifyAgainstCodebase` per rule. Throws on transient I/O * errors; the interceptor catches and isolates per-rule failures. */ readonly verifier: (rule: CompiledRule) => Promise; /** * ISO-now provider for `verifiedAt` timestamps. Injected so tests can * produce deterministic outcomes; production code passes `() => new Date()`. */ readonly now?: () => Date; /** * Optional logger for verifier failures and self-healing diagnostics. * Defaults to a no-op when omitted — pass an explicit logger to surface * corrupt-cache and verifier-failure diagnostics. The CLI runner wires * this to `log.warn` after sanitization (see `first-lint-promote-runner.ts`). */ readonly onWarn?: (msg: string) => void; } export interface PromotePendingRulesResult { /** * The mutated rule list. Statuses on `'pending-verification'` rules are * replaced per Invariant #3; rules whose verifier threw are unchanged. * Callers persist this to `.totem/compiled-rules.json`. */ readonly mutatedRules: CompiledRule[]; /** * Count of verifier calls this pass (excludes memoized hits). Includes * calls that threw, since the metric reports work attempted rather than * work succeeded — pair with `verifierFailures` to derive the success count. */ readonly verifierInvocations: number; /** Count of rules whose status was replaced with a terminal lifecycle value. */ readonly promoted: number; /** Count of rules whose verifier threw and stayed `'pending-verification'`. */ readonly verifierFailures: number; /** * Whether any rule status mutation occurred. Callers can skip manifest * writes when this is `false` to avoid touching the file on no-op passes. */ readonly changed: boolean; } export declare function promotePendingRules(rules: readonly CompiledRule[], deps: PromotePendingRulesDeps): Promise; /** * Map a Stage 4 outcome to the rule's terminal lifecycle status per * Invariant #3. Pure function so the four-way mapping can be unit-tested * without staging the full interceptor flow. Returns a new rule object; * never mutates the input. */ export declare function applyOutcomeToRule(rule: CompiledRule, entry: VerificationOutcomeEntry): CompiledRule; //# sourceMappingURL=first-lint-promote.d.ts.map