import { z } from "zod"; import { AihError } from "../errors.js"; import { type HostTuple } from "./host-tuple.js"; import type { ContextCostReport } from "./hosts/claude/context-cost.js"; import { type BindingLock } from "./lock.js"; import type { FrameworkCardDisclosure, RawSourceOutcome, SelectedProfileGate } from "./scan-gate.js"; import { type BindingSource } from "./schema.js"; /** * The typed, versioned Framework Card (W7 design §A) — a single derived, * rebuildable evidence record that REPLACES the three ad-hoc `lines` formatters * the adapters shipped. Each `report()` builds a card; {@link renderFrameworkCard} * emits the human view from it. The committed DECLARATION stays the only * authority (D7); the card is regenerated on a `cardVersion` bump (O2 — no * migration machinery). * * H3/O3: the COMMITTED card carries NO machine-local path. * {@link assertNoMachineLocalPath} fails closed on any absolute path, drive * letter, `~/`, `$HOME`, or `%USERPROFILE%` in any string field, reusing the * lock's `home:`/repo-relative label convention (a `home:`-prefixed label is a * portable machine-scope MARKER, not a machine path, and is accepted). * * H4/O1: the support label is NOT self-asserted. A card build takes an optional * {@link DoctorCardInput}; STRICT is issued ONLY when the framework's * (aspirational) `targetLabel` is strict-capable AND the doctor reports * contamination-clean AND in-tuple. Absent input ⇒ never STRICT (falls to * `PROJECT_BINDING_CONFLICTED` / `HOST_BINDING_UNVALIDATED`). */ export declare const CARD_SCHEMA_VERSION: 1; /** The D13 support-label taxonomy (design §A.2). */ export declare const SUPPORT_LABELS: readonly ["STRICT_PROJECT_BINDING_VERIFIED", "PROJECT_BINDING_CONFLICTED", "PROJECT_SELECTED_SHARED_RUNTIME", "REFERENCE_ONLY", "DEFERRED", "PACKAGE_CI_VALIDATED", "HOST_BINDING_UNVALIDATED"]; export type SupportLabel = (typeof SUPPORT_LABELS)[number]; /** Per-event hook chain entry (design §A.2 / §B.6). Populated by the Phase 1b hook probe. */ export declare const HookEntrySchema: z.ZodObject<{ event: z.ZodString; matcher: z.ZodOptional; commandOrigin: z.ZodString; scope: z.ZodEnum<{ home: "home"; local: "local"; project: "project"; }>; }, z.core.$strict>; export type HookEntry = z.infer; /** A shared-state / config / binary / backup surface the binding touches (design §A.2). */ export declare const SharedStateEntrySchema: z.ZodObject<{ label: z.ZodString; kind: z.ZodEnum<{ backup: "backup"; binary: "binary"; config: "config"; "state-dir": "state-dir"; }>; note: z.ZodOptional; }, z.core.$strict>; export type SharedStateEntry = z.infer; /** Context-cost projection (design §A.2, wrapping `ContextCostReport`). */ export declare const ContextCostCardSchema: z.ZodObject<{ available: z.ZodBoolean; evidenceSource: z.ZodEnum<{ "aih-estimate": "aih-estimate"; "host-reported": "host-reported"; }>; evidence: z.ZodString; projectedTokens: z.ZodOptional; estimate: z.ZodBoolean; }, z.core.$strict>; export type ContextCostCard = z.infer; /** * The W8 Framework Value Gate disclosure (design §"New card fragment") — the * CREDIT side shown SIDE BY SIDE with the cost debit and scan/support risk, never * a composite. Surface deltas use `z.number().int()` (NOT NonNeg): a contaminated * baseline can drive a negative delta, and the honest measurement must survive * to drive INSUFFICIENT rather than be clamped to look clean (Q8). */ export declare const FrameworkValueCardSchema: z.ZodObject<{ verdict: z.ZodEnum<{ DELIVERS_VALUE: "DELIVERS_VALUE"; INCOMPLETE_MEASUREMENT: "INCOMPLETE_MEASUREMENT"; INSUFFICIENT_VALUE: "INSUFFICIENT_VALUE"; }>; invocableSurfaceDelta: z.ZodNumber; governanceSurfaceDelta: z.ZodNumber; contextCostTokens: z.ZodOptional; characteristicWorkflow: z.ZodObject<{ name: z.ZodString; succeeded: z.ZodBoolean; baselineAbsent: z.ZodBoolean; }, z.core.$strict>; dimensionsDelivered: z.ZodArray; minSurfaceDelta: z.ZodNumber; baselineRef: z.ZodString; }, z.core.$strict>; export type FrameworkValueCard = z.infer; /** * The rule-9 five-way scan disclosure (design §A.2 — mirrors * `FrameworkCardDisclosure` at `scan-gate.ts:1009`, the never-surfaced type W7 * surfaces). Kept structurally in sync via {@link scanCardIdentity}, whose typed * `disclosure` parameter is the real scan-gate type. */ export declare const FrameworkCardDisclosureSchema: z.ZodObject<{ rawFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; bySeverity: z.ZodObject<{ info: z.ZodNumber; low: z.ZodNumber; medium: z.ZodNumber; high: z.ZodNumber; critical: z.ZodNumber; }, z.core.$strict>; }, z.core.$strict>; closureFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; unknownReachability: z.ZodNumber; }, z.core.$strict>; inertFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; }, z.core.$strict>; acceptedRuntimeFindings: z.ZodObject<{ total: z.ZodNumber; }, z.core.$strict>; visibleTypographyAdvisories: z.ZodObject<{ total: z.ZodNumber; files: z.ZodNumber; }, z.core.$strict>; residualRisk: z.ZodObject<{ blockingUnaccepted: z.ZodNumber; unknownReachability: z.ZodNumber; inertReported: z.ZodNumber; }, z.core.$strict>; }, z.core.$strict>; /** The scan-identity fragment (design §A.2). `deepScanKey`/`runtimeQualKey` are Phase-2. */ export declare const ScanCardIdentitySchema: z.ZodObject<{ rawSourceScan: z.ZodEnum<{ CLEAN: "CLEAN"; FINDINGS_PRESENT: "FINDINGS_PRESENT"; }>; selectedProfileGate: z.ZodEnum<{ ALLOW: "ALLOW"; ALLOW_WITH_CONDITIONS: "ALLOW_WITH_CONDITIONS"; BLOCK: "BLOCK"; }>; disclosure: z.ZodObject<{ rawFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; bySeverity: z.ZodObject<{ info: z.ZodNumber; low: z.ZodNumber; medium: z.ZodNumber; high: z.ZodNumber; critical: z.ZodNumber; }, z.core.$strict>; }, z.core.$strict>; closureFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; unknownReachability: z.ZodNumber; }, z.core.$strict>; inertFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; }, z.core.$strict>; acceptedRuntimeFindings: z.ZodObject<{ total: z.ZodNumber; }, z.core.$strict>; visibleTypographyAdvisories: z.ZodObject<{ total: z.ZodNumber; files: z.ZodNumber; }, z.core.$strict>; residualRisk: z.ZodObject<{ blockingUnaccepted: z.ZodNumber; unknownReachability: z.ZodNumber; inertReported: z.ZodNumber; }, z.core.$strict>; }, z.core.$strict>; deepScanKey: z.ZodOptional; runtimeQualKey: z.ZodOptional; coverage: z.ZodArray; reason: z.ZodOptional; }, z.core.$strict>>; }, z.core.$strict>; export type ScanCardIdentity = z.infer; declare const CountsSchema: z.ZodObject<{ skills: z.ZodNumber; agents: z.ZodNumber; commands: z.ZodNumber; rules: z.ZodNumber; hooks: z.ZodNumber; mcpServers: z.ZodNumber; }, z.core.$strict>; export type FrameworkCardCounts = z.infer; /** * The typed Framework Card (design §A.2). Strict + versioned. The D7 identity * (`scannedDigest`/`loadedDigest`/`match`) is optional as a group — a * not-yet-provisioned preview card carries none of the three; a provisioned card * carries all three with `match === (scannedDigest === loadedDigest)`, mirroring * the lock's own invariant. `contextCost`/`scanCache` are optional: the scan * disclosure is a provision-time artifact (supplied by Phase 1b/provision), and a * preview has no cost projection. */ export declare const FrameworkCardSchema: z.ZodObject<{ cardVersion: z.ZodLiteral<1>; framework: z.ZodEnum<{ ecc: "ecc"; superpowers: "superpowers"; }>; mode: z.ZodOptional>; host: z.ZodLiteral<"claude">; scope: z.ZodLiteral<"project">; supportLabel: z.ZodEnum<{ DEFERRED: "DEFERRED"; HOST_BINDING_UNVALIDATED: "HOST_BINDING_UNVALIDATED"; PACKAGE_CI_VALIDATED: "PACKAGE_CI_VALIDATED"; PROJECT_BINDING_CONFLICTED: "PROJECT_BINDING_CONFLICTED"; PROJECT_SELECTED_SHARED_RUNTIME: "PROJECT_SELECTED_SHARED_RUNTIME"; REFERENCE_ONLY: "REFERENCE_ONLY"; STRICT_PROJECT_BINDING_VERIFIED: "STRICT_PROJECT_BINDING_VERIFIED"; }>; targetLabel: z.ZodEnum<{ DEFERRED: "DEFERRED"; HOST_BINDING_UNVALIDATED: "HOST_BINDING_UNVALIDATED"; PACKAGE_CI_VALIDATED: "PACKAGE_CI_VALIDATED"; PROJECT_BINDING_CONFLICTED: "PROJECT_BINDING_CONFLICTED"; PROJECT_SELECTED_SHARED_RUNTIME: "PROJECT_SELECTED_SHARED_RUNTIME"; REFERENCE_ONLY: "REFERENCE_ONLY"; STRICT_PROJECT_BINDING_VERIFIED: "STRICT_PROJECT_BINDING_VERIFIED"; }>; source: z.ZodDiscriminatedUnion<[z.ZodObject<{ kind: z.ZodLiteral<"git">; repository: z.ZodString; commitSha: z.ZodString; treeDigest: z.ZodString; }, z.core.$strict>, z.ZodObject<{ kind: z.ZodLiteral<"npm">; package: z.ZodString; exactVersion: z.ZodString; integrity: z.ZodString; }, z.core.$strict>], "kind">; scannedDigest: z.ZodOptional; loadedDigest: z.ZodOptional; match: z.ZodOptional; installMechanism: z.ZodString; verifiedHostTuple: z.ZodObject<{ claudeCode: z.ZodObject<{ measuredOn: z.ZodString; }, z.core.$strict>; windowsBuild: z.ZodString; windowsUbr: z.ZodOptional; arch: z.ZodString; node: z.ZodString; bun: z.ZodString; ramClassGb: z.ZodNumber; vcpuClass: z.ZodNumber; }, z.core.$strict>; counts: z.ZodObject<{ skills: z.ZodNumber; agents: z.ZodNumber; commands: z.ZodNumber; rules: z.ZodNumber; hooks: z.ZodNumber; mcpServers: z.ZodNumber; }, z.core.$strict>; hooks: z.ZodArray; commandOrigin: z.ZodString; scope: z.ZodEnum<{ home: "home"; local: "local"; project: "project"; }>; }, z.core.$strict>>; mcpServers: z.ZodArray; scriptsBinariesDeps: z.ZodArray; network: z.ZodString; update: z.ZodString; telemetry: z.ZodString; lockdown: z.ZodArray>; sharedState: z.ZodArray; note: z.ZodOptional; }, z.core.$strict>>; contextCost: z.ZodOptional; evidence: z.ZodString; projectedTokens: z.ZodOptional; estimate: z.ZodBoolean; }, z.core.$strict>>; scanCache: z.ZodOptional; selectedProfileGate: z.ZodEnum<{ ALLOW: "ALLOW"; ALLOW_WITH_CONDITIONS: "ALLOW_WITH_CONDITIONS"; BLOCK: "BLOCK"; }>; disclosure: z.ZodObject<{ rawFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; bySeverity: z.ZodObject<{ info: z.ZodNumber; low: z.ZodNumber; medium: z.ZodNumber; high: z.ZodNumber; critical: z.ZodNumber; }, z.core.$strict>; }, z.core.$strict>; closureFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; unknownReachability: z.ZodNumber; }, z.core.$strict>; inertFindings: z.ZodObject<{ total: z.ZodNumber; high: z.ZodNumber; }, z.core.$strict>; acceptedRuntimeFindings: z.ZodObject<{ total: z.ZodNumber; }, z.core.$strict>; visibleTypographyAdvisories: z.ZodObject<{ total: z.ZodNumber; files: z.ZodNumber; }, z.core.$strict>; residualRisk: z.ZodObject<{ blockingUnaccepted: z.ZodNumber; unknownReachability: z.ZodNumber; inertReported: z.ZodNumber; }, z.core.$strict>; }, z.core.$strict>; deepScanKey: z.ZodOptional; runtimeQualKey: z.ZodOptional; coverage: z.ZodArray; reason: z.ZodOptional; }, z.core.$strict>>; }, z.core.$strict>>; valueGate: z.ZodOptional; invocableSurfaceDelta: z.ZodNumber; governanceSurfaceDelta: z.ZodNumber; contextCostTokens: z.ZodOptional; characteristicWorkflow: z.ZodObject<{ name: z.ZodString; succeeded: z.ZodBoolean; baselineAbsent: z.ZodBoolean; }, z.core.$strict>; dimensionsDelivered: z.ZodArray; minSurfaceDelta: z.ZodNumber; baselineRef: z.ZodString; }, z.core.$strict>>; residualRisks: z.ZodArray; enterpriseDisposition: z.ZodString; }, z.core.$strict>; export type FrameworkCard = z.infer; /** Corrupt / schema-invalid / machine-path-carrying card — fail closed, never guess. */ export declare class FrameworkCardError extends AihError { constructor(message: string); } export declare function parseFrameworkCard(value: unknown): FrameworkCard; /** * Fail closed unless EVERY string field of the card is free of a machine-local * path (H3). Enforced at card build (not just at serialize) so a leaked path is * refused before it can reach the committed file. */ export declare function assertNoMachineLocalPath(card: FrameworkCard): void; /** The doctor's two D13 inputs — contamination-clean AND in-tuple gate STRICT (H4). */ export interface DoctorCardInput { contaminationClean: boolean; inTuple: boolean; } /** * Downgrade the framework's aspirational `targetLabel` to the actual support * label (O1). STRICT is issued ONLY when the target is strict-capable AND the * doctor reports both contamination-clean and in-tuple. Contamination downgrades * to `PROJECT_BINDING_CONFLICTED` (O4); off-tuple to `HOST_BINDING_UNVALIDATED` * (O5, §B.3) — for a non-strict target too. Absent input never issues STRICT. */ export declare function deriveSupportLabel(targetLabel: SupportLabel, doctor: DoctorCardInput | undefined): SupportLabel; /** The D7 identity fragment (source + scanned/loaded/match) recovered from a lock. */ export declare function sourceIdentityFromLock(lock: BindingLock): { source: BindingSource; identity: { scannedDigest: string; loadedDigest: string; match: boolean; }; }; /** * The D18 ownership-target split every adapter report already computed * (`isHomeScopedTarget`): repo-relative targets vs `home:`-prefixed machine-scope * targets. Both sorted for determinism; both are portable labels (no abs path). */ export declare function d18SurfaceLabels(lock: BindingLock): { repoRelative: string[]; homeScope: string[]; }; /** Wrap a produced `ContextCostReport` into the card's cost + counts fragment. */ export declare function contextCostCard(report: ContextCostReport): { contextCost: ContextCostCard; counts: FrameworkCardCounts; }; /** * A cost fragment for the case the evidence source could not project (install * root absent, resolved checkout path not recorded, …). The `reason` MUST be a * clean, path-free label — a raw estimator error message may embed an absolute * path and must NOT be threaded through here. */ export declare function contextCostUnavailable(reason: string): ContextCostCard; /** * The scan-identity fragment (design §A.2), the seam Phase 1b/provision fills * from a live `ScanDisposition`. The `disclosure` parameter is the real * `FrameworkCardDisclosure` (scan-gate.ts:1009) so the card schema and the * disposition stay structurally in sync. */ export declare function scanCardIdentity(input: { rawSourceScan: RawSourceOutcome; selectedProfileGate: SelectedProfileGate; disclosure: FrameworkCardDisclosure; coverage?: { dimension: string; status: "produced" | "missing"; reason?: string; }[]; deepScanKey?: string; runtimeQualKey?: string; }): ScanCardIdentity; /** Build input — the typed facts an adapter `report()`/`provision()` supplies. */ export interface FrameworkCardBuildInput { framework: FrameworkCard["framework"]; mode?: "lean" | "full"; scope: "project"; /** The framework's aspirational label; downgraded to the support label via `doctor`. */ targetLabel: SupportLabel; source: BindingSource; /** The D7 identity, when provisioned (all three or none). */ identity?: { scannedDigest: string; loadedDigest: string; match: boolean; }; installMechanism: string; /** Defaults to `SUPPORTED_HOST_TUPLE` (the pinned tuple the binding targets). */ verifiedHostTuple?: HostTuple; counts?: Partial; hooks?: HookEntry[]; mcpServers?: string[]; scriptsBinariesDeps?: string[]; network?: string; update?: string; telemetry?: string; lockdown?: { key: string; value: string; }[]; sharedState?: SharedStateEntry[]; contextCost?: ContextCostCard; scanCache?: ScanCardIdentity; valueGate?: FrameworkValueCard; residualRisks?: string[]; enterpriseDisposition?: string; /** Absent ⇒ support label is NEVER STRICT (O1). Supplied by the Phase 1b doctor. */ doctor?: DoctorCardInput; } /** * Assemble a validated, canonical, machine-path-free {@link FrameworkCard}. * Arrays are canonicalized (sorted, deduped) at build so the card itself is * deterministic, and the zod schema + {@link assertNoMachineLocalPath} both run * before it is returned — an invalid or path-leaking card can never escape. */ export declare function buildFrameworkCard(input: FrameworkCardBuildInput): FrameworkCard; /** * The single deterministic renderer that REPLACES the three ad-hoc `lines` * builders. A pure function of the card (arrays already canonical), so two * renders of the same card are byte-identical. */ export declare function renderFrameworkCard(card: FrameworkCard): string[]; /** `/.aih/binding/framework-card.json` — beside the lock (O8). */ export declare function frameworkCardPath(root: string): string; /** * Atomically write the committed card (validate + no-machine-path -> temp file * with owner-only mode -> rename), mirroring `writeBindingLockAtomic` * (`lock.ts:180`). The card is O8's provision output; the provision-side CALL * SITE is Phase 1b — this is the function it wires to. */ export declare function writeFrameworkCardAtomic(root: string, card: FrameworkCard): void; /** * Read the committed card. Absent => `undefined`. A present-but-unparseable / * schema-invalid / machine-path-carrying card FAILS CLOSED with * {@link FrameworkCardError} — a damaged derived record is never silently * treated as empty (mirrors `readBindingLock`). */ export declare function readFrameworkCard(root: string): FrameworkCard | undefined; export {};