import type { PlanContext } from "../../internals/plan.js"; import type { Check } from "../../internals/verify.js"; import type { DoctorCardInput } from "../card.js"; import { type HostTuple } from "../host-tuple.js"; import { type FrameworkId } from "../schema.js"; /** * FAIL when an `ecc@`-prefixed plugin enable AND a manual ECC rules copy are * BOTH present at once — upstream warns that stacking the two produces * duplicates. PASS otherwise, naming whichever of the two (if either) was * found. */ export declare function eccDoubleInstallCheck(ctx: PlanContext): Check; /** * FAIL when the binding lock's declared ECC mode disagrees with what is * actually installed: * - `mode: "lean"` but an `ecc@`-prefixed plugin is enabled (a plugin * installed on top of a Lean bind); * - `mode: "full"` but no `ecc@` plugin is enabled while home-scoped Lean * component ownership (a `home:`-prefixed ownership target) is still * recorded in the lock. * PASS when the lock is absent, the bound framework is not `ecc`, or the mode * and installed state agree — nothing to enforce either way. */ export declare function eccModeExclusivityCheck(ctx: PlanContext): Check; /** * B1 — user-scope contamination. Clean ⇒ pass. Leakage ⇒ posture-graded (O4): a * failing check at enterprise, an advisory skip (label downgrade to * PROJECT_BINDING_CONFLICTED) at vibe. Detail is the countable leakage * summary (`N skills, N agents, …`) — counts only, no surface paths, deterministic. */ export declare function bindingContaminationCheck(ctx: PlanContext): Check; /** * B2 — informational context-cost projection over the project's `.claude` surface * tree (AIH static estimate). Pass with the evidence-source label + counts; skip * (no code) when there is no tree to project from. No token number is fabricated. */ export declare function bindingContextCostCheck(ctx: PlanContext): Check; /** * B3 — the D16 host tuple. `in-tuple` ⇒ pass; `version-drift` (hard facts held, only * the Claude Code version advanced) ⇒ advisory skip (`binding.host-version-drift`); * `off-tuple` ⇒ posture-graded like O4 (`binding.host-off-tuple`): a failing check at * enterprise, an advisory skip (support downgrades to HOST_BINDING_UNVALIDATED) at * vibe. Detail names the pinned facts / mismatched field NAMES only — never a * raw machine value — so it is portable and deterministic. `measured` is injectable * for deterministic tests; production measures the live host. */ export declare function bindingHostTupleCheck(ctx: PlanContext, measured?: HostTuple): Promise; /** * B4 — D8 post-bind one-framework drift. A declared framework with no registered * adapter ⇒ diagnosable advisory skip (`binding.no-adapter`), never a throw. More * than one methodology framework with a LIVE surface (the declared one plus any * competing framework attributed in the user-scope contamination scan) ⇒ fail * (`binding.framework-drift`). Exactly one ⇒ pass. `adapterFrameworks` is injectable * so a test can supply a registry built WITHOUT a given adapter. */ export declare function bindingFrameworkDriftCheck(ctx: PlanContext, opts?: { adapterFrameworks?: Iterable; }): Check; /** * B6 — the per-event hook chain across the home, project, and local settings layers * (`probeMany`). One advisory skip per hook (`binding.hook-chain`), sorted for * determinism; a single pass when there are no hooks. Each detail carries the * event/matcher/scope plus the PATH-FREE command origin (basename) — never the raw * command — so it is portable and deterministic. Self-skips when no binding. */ export declare function bindingHookChainChecks(ctx: PlanContext): Check[]; /** * B7 — read-only D18 settings drift, via the pure {@link readClaudeSettingsDrift} * the removal planner also calls (so they cannot disagree). Drift is REPORTED, never * failed (D18 preserves a user-modified owned value) ⇒ advisory skip * (`binding.settings-drift`); no drift ⇒ pass. Detail lists sorted repo-relative * targets + reasons — no absolute path, deterministic. A corrupt lock is a * non-routable skip (surfaced as a fail by `eccModeExclusivityCheck`). */ export declare function bindingSettingsDriftCheck(ctx: PlanContext): Check; /** * B8 — MCP server inventory across the project settings, project local settings, * project `.mcp.json`, home settings, and home `.mcp.json` (the `mcpServersIn` shape * over project + home). Sorted, deduped server-id list ⇒ advisory skip * (`binding.mcp-inventory`) when non-empty; pass when none. Self-skips when no * binding. Deterministic (sorted); server ids are names, never paths. */ export declare function bindingMcpInventoryCheck(ctx: PlanContext): Check; /** * Derive the card's {@link DoctorCardInput} from a doctor run's `Check[]` — the seam * (design §A.3.3) that lets a doctor-aware caller downgrade a card's support label * from the B1/B3 verdicts WITHOUT the card layer importing the doctor. * * Both signals are read by their STABLE `code` (never by matching `detail`): * - `contaminationClean` is false iff B1 emitted `binding.contaminated` (as a * fail at enterprise or an advisory skip at vibe) — otherwise clean. * - `inTuple` is false iff B3 emitted `binding.host-off-tuple`. A * `binding.host-version-drift` is NOT off-tuple: the hard facts held and only the * Claude Code provenance advanced, so it stays in-tuple for the card (design §B.3). * * Absent codes ⇒ `{ contaminationClean: true, inTuple: true }`. Passing this into * {@link buildFrameworkCard} still only issues STRICT when the target is * strict-capable (H4/O1) — a clean doctor is necessary, not sufficient. */ export declare function cardDoctorInputFromChecks(checks: readonly Check[]): DoctorCardInput;