/** * Parity-drift sensor for `totem doctor --parity` (mmnto-ai/totem-strategy#448). * * Detection is wired across all three tractability classes (mmnto-ai/totem#2073): * - **version-pinned** (PR-1, mmnto-ai/totem#2069): each deps contract whose id * resolves an `@mmnto/*` package name runs through the core * `detectVersionPinnedContract` engine (pin-currency verdict, local-only floor). * - **mechanical content-equality** (mmnto-ai/totem#2073): three artifact shapes, * all local-read-only against the running `@mmnto/cli`'s OWN in-process template: * · **skills** (`claude-skills`): managed-block equality of * `.claude/skills//SKILL.md` via `detectMechanicalContract`. * · **git-hooks**: per-repo REGENERATED whole-file/region equality of the four * `.git/hooks/*` (package-manager + tier parameterized) via * `detectGeneratedArtifactContract` — catches stale-version drift (#1854). * · **session-start-orientation**: STATIC whole-file equality of the * `.claude/hooks/SessionStart.cjs` + `.gemini/hooks/SessionStart.cjs` templates, * also via `detectGeneratedArtifactContract` (no parameterization). * - **manual-attestation** (mmnto-ai/totem#2080): the no-mechanical-sensor class — * `detectManualAttestationContract` surfaces the doctrine-currency row / vendor-SDK * pin as `info` (or honest-absent `skip`), NEVER pass/warn/fail (the "never fails" * contract; structurally cannot gate under `--strict`). * * The remaining contracts — the file-value-equality bot-configs (`cr-profile` etc.) * and the structural-presence dimensions — keep the `skip` "not yet implemented" stub; * their detection is a follow-on. * * The parity sensor owns its OWN render + result type (`ParityLine`) carrying a * WIDER status vocabulary (pass/warn/fail/info/unknown/skip) than the shared * `CheckStatus`, so the verdict-state split (#2073 req #1) never ripples * `CheckStatus` across the unrelated doctor checks. * * Sensor-not-gate: the detectors return `skip`/`warn`/`pass`/`info`/`unknown` — * never `fail`. The `--strict` exit-code decision lives at the CLI edge: a * `warn` from a `blocking: true` contract is promoted to `fail` (non-zero) ONLY * under `--strict`. `info`/`unknown` are never gated. Honest-absent (Tenet 14): * unconfigured → exactly one `skip` line; configured-but-missing / unparseable / * unsupported-schema → `warn`, never a crash. Dynamic-import `@mmnto/totem` to * keep core off the CLI cold-start graph, matching the other doctor checks. * * The **trust-readout** (mmnto-ai/totem#2327, Prop 303 §5(a)) post-processes * the flat per-line dump into the doctor's aggregate output contract: verdict * rollup (per-seat + global, R1), the run-time coverage denominator (R2), * why-not per non-pass row at the level probed (R3), the `--json` verdict * artifact (R4), and the `--strict` declaredly-toothless honesty line (R5). * Spec: mmnto-ai/totem-strategy:doctrine/parity-manifest.md § "The * trust-readout — the doctor's output contract"; deltas raise there, never * silently diverge. Pure post-processing — zero probes added. */ import type { ParityContract, ParityContractVerdict } from '@mmnto/totem'; /** * A parity output line — the per-contract verdict plus its display name. Carries * the WIDER `ParityContractVerdict` status vocabulary (pass/warn/fail/info/ * unknown/skip) rather than the shared `CheckStatus`, so the sensor honors the * verdict-state split (#2073 req #1) without rippling `CheckStatus` across the * other doctor checks. The parity command owns its own renderer. */ export interface ParityLine extends ParityContractVerdict { name: string; } /** Prop 296 §6(a)2 senses-ladder rung a detector actually probed. */ export type SensesLevel = 'declared' | 'present' | 'loaded' | 'usable'; /** * R2 coverage class for one contract — derived per run from the detector * registry ∩ the manifest (the yaml deliberately carries no per-row sensed * flag; Tenet 20). A contract whose detector exists but was scope-skipped this * run still classifies `mechanical` — the registry implements it; the skip is * a run-time verdict the rollup + why-not carry separately. */ export type ReadoutCoverageClass = 'mechanical' | 'attestation-only' | 'honest-absent'; /** R3 reason class for one verdict line (`pass` lines omit theirs; `attestation` is raised Delta 3). */ export type ReadoutReasonClass = 'drift' | 'scoping-skip' | 'honest-absent' | 'detector-error' | 'attestation'; /** * Per-contract readout metadata, tagged at the routing branch that senses the * contract (single source — never re-derived from a mirrored registry, which * would be the Tenet 20 drift hazard). */ export interface ContractReadoutMeta { coverage: ReadoutCoverageClass; /** Absent when nothing was probed (attestation rows, honest-absent stubs). */ sensesProbed?: SensesLevel; } /** The trust-readout raw materials `checkParity` carries out of the manifest `ok` path. */ export interface ParityReadoutInputs { manifest: { schemaVersion: number; status: string; }; contracts: ParityContract[]; meta: Record; } /** * Result of a parity check: the rendered `ParityLine`s plus the set of contract * ids that produced a drift `warn` AND are `blocking: true`. The command * promotes exactly these to `fail` under `--strict` — carrying the ids here * avoids re-loading the manifest at the CLI edge to recover the `blocking` flag. */ export interface ParityCheckResult { results: ParityLine[]; /** Contract ids whose `warn` is `--strict`-promotable (blocking + drift). */ blockingDriftIds: string[]; /** * Whether a repo-local `orient.parityManifest` field was configured (i.e. * `configValue !== undefined` after the global-leak guard). NOT whether the * manifest file loaded — a configured-but-broken manifest is `configured: true` * so the `--strict` fold surfaces the error instead of silently no-op'ing. * Lets the CLI edge fold parity into `--strict` only for repos that opted in * (mmnto-ai/totem#2085, mmnto-ai/totem-strategy#545 Half 2). */ configured: boolean; /** * Manifest load status — the `--json` artifact's `manifest.status` on the * degenerate paths, where there is no manifest-declared status to carry * (mmnto-ai/totem#2327 R4). */ loadStatus: 'ok' | 'not-configured' | 'not-found' | 'unparseable' | 'unsupported-schema'; /** * Trust-readout raw materials (mmnto-ai/totem#2327) — present only on the * manifest `ok` path. The CLI edge assembles the rollup / denominator / * why-not via `buildParityReadout`; degenerate load states render no rollup * (nothing to roll up) and `--json` carries `loadStatus` instead. */ readout?: ParityReadoutInputs; } /** * Resolve, parse, and report the parity manifest as `ParityLine`s. * * Returns `{ results, blockingDriftIds }`: `results[0]` is always the section * summary line; in the `ok` path it is followed by one line per contract (or * per artifact, for multi-artifact mechanical contracts) — a pin-currency * verdict for the deps version-pinned contracts, a content-equality verdict for * the mechanical skills contracts, and a `skip` stub for everything else. All * non-`ok` paths return a single summary entry and an empty `blockingDriftIds`. * * @param cwd The directory to resolve config + manifest against (config/repo root). */ export declare function checkParity(cwd: string): Promise; /** Counts over rendered verdict lines — the R1 rollup unit (raised Delta 2). */ export type ReadoutCounts = Record; /** One `--json` `rows[]` entry — 1:1 with a rendered verdict line (ids repeat for multi-artifact contracts). */ export interface ReadoutRow { id: string; /** Line verdict AFTER the strict blocking promotion, so the artifact matches the rendered output. */ verdict: ParityLine['status']; sensesProbed?: SensesLevel; reasonClass?: ReadoutReasonClass; message: string; lastAttested?: string; /** Display name of the underlying verdict line (human render only — not a `--json` field; R4 names are fixed). */ lineName: string; /** R5: a `blocking: true` contract's line skipped by scoping — rendered skipped-not-gated, never a silent pass. */ skippedNotGated: boolean; } /** The assembled trust-readout — everything R1–R5 render from. */ export interface ParityReadout { manifest: { schemaVersion: number; status: string; }; rollup: { global: ReadoutCounts; perSeat: Record; }; denominator: { mechanical: number; attestationOnly: number; honestAbsent: number; }; strict: { armed: boolean; blockingIds: string[]; gatesAnything: boolean; }; rows: ReadoutRow[]; } /** * Assemble the trust-readout from `checkParity`'s raw materials — pure * post-processing over the existing detector output (Prop 303 non-goal 2: * zero probes added here). */ export declare function buildParityReadout(inputs: ParityReadoutInputs, results: ParityLine[], blockingDriftIds: string[], strict: boolean): ParityReadout; export interface ParityCliOptions { /** * Strict mode (Proposal 273 / 279 `--strict` semantics): promote drift to a * gate failure (non-zero exit) via a thrown TotemError. * * Sensor-not-gate is the default: a drift `warn` reports and exits 0. Under * `--strict`, a `warn` from a `blocking: true` contract (its id carried in * `checkParity`'s `blockingDriftIds`) is rendered as `FAIL` and promoted to a * non-zero exit. Non-blocking drift stays a `warn` even under `--strict`, and * `info` (attested fork) / `unknown` (unprovable) NEVER promote — the * contract's `blocking` flag on a `warn`, not the flag alone, gates the exit. */ strict?: boolean; /** * Folded-into-`--strict` mode (mmnto-ai/totem#2085, mmnto-ai/totem-strategy#545 * Half 2): when set, the command no-ops (renders nothing, throws nothing, exits 0) * if no repo-local `orient.parityManifest` is configured — so `doctor --strict` * exercises parity for opted-in repos while staying byte-identical for non-adopters * (satur8d's zero-churn condition). Default (omitted) preserves the standalone * `doctor --parity` behavior, which still renders the honest-absent SKIP line. */ onlyWhenConfigured?: boolean; /** * Emit the trust-readout as the schema'd `--json` verdict artifact * (mmnto-ai/totem#2327 R4) on stdout INSTEAD of the human render — the * artifact is diffable, so nothing else may share stdout. The `--strict` * exit-code semantics are unchanged (artifact + non-zero exit both happen). */ json?: boolean; /** Test seam — production callers omit and the command uses `process.cwd()`. */ cwdForTest?: string; } /** * CLI entry — runs `checkParity`, renders each `ParityLine`, and throws a * `TotemError` when a blocking contract drifted under `--strict` so the * top-level `handleError` produces the non-zero exit code (no direct * `process.exit` per AGENTS.md). */ export declare function doctorParityCliCommand(options?: ParityCliOptions): Promise; //# sourceMappingURL=doctor-parity.d.ts.map