import { type Action, type PlanContext } from "../internals/plan.js"; import type { EccHookEnvPatch } from "./ecc-hook-controls-projection.js"; import type { HookAdoptionOffer } from "./hook-registrar-adoption.js"; import { type ProjectedHookSettings } from "./hook-registrar-native.js"; import { type GuardedRead } from "./hook-registrar-read.js"; import { type HookRegistration } from "./schema.js"; export { adoptedHookRegistrations, type HookAdoptionDeclaration, type HookAdoptionOffer, type HookAdoptionProvenance, } from "./hook-registrar-adoption.js"; export { assertHookRegistrations, destinationHookEntries, MAX_REPORTED_HOOK_ENTRIES, type NativeHookEntry, nativeHookEntryKey, type ProjectedHookCommand, type ProjectedHookGroup, type ProjectedHookSettings, } from "./hook-registrar-native.js"; export { HOOK_REGISTRAR_DESTINATION, HOOK_REGISTRAR_MAX_DESTINATION_BYTES, HOOK_REGISTRAR_MAX_RECEIPT_BYTES, HOOK_REGISTRAR_RECEIPT_FORMAT, HOOK_REGISTRAR_RECEIPT_PATH, } from "./hook-registrar-read.js"; export { type HookReceiptEntry, type HookReceiptPrior, type HookRegistrarReceipt, hookRegistrationOwnerId, readHookRegistrarReceipt, } from "./hook-registrar-receipt.js"; export { type HookRegistration, type HookRegistrationOwner, hookCommandDigest, type ThirdPartyLauncherPin, } from "./schema.js"; /** * The `hook-managed-settings` projector. * * AIH is the sole REGISTRAR of client hook entries; third-party runtimes stay * the EXECUTORS. Those are different ownerships, and the whole module turns on * keeping them apart: * * - Activating a registry — executing a third party's handlers under AIH's * dispatcher identity — is forbidden. Nothing here loads, parses, interprets * or re-emits a third party's command. * - Projecting a registration — writing a third party's own launcher into a * destination AIH owns, with a receipt that can revoke it — is what this * module does. It is the only way an installed third-party hook can ever be * uninstalled. Where a source ships no removal path of its own, the receipt * is the only removal authority there is. The specific third-party * observation behind that lives in the decision log, not here: this file * holds no evidence for it and must not assert it as fact. * * A projected third-party entry is transported, never transformed — its command * and every native field around it alike. The only thing AIH computes about a * launcher is a hash, and the only thing that hash is used for is proving it did * not change. */ /** * Claude is the only supported target. Codex publishes no per-event hook output * contract AIH has evidence for, and inventing one would be a guess — the same * reason the ECC composite dispatcher was deliberately left Codex-unchanged. */ export declare const HOOK_REGISTRAR_TARGETS: readonly ["claude"]; /** * Every selected registration becomes exactly one native entry. Overlapping * entries are BOTH projected: silent merging causes capability loss nothing * downstream can diagnose from the resulting configuration. */ export declare function projectedHookSettings(registrations: readonly HookRegistration[]): ProjectedHookSettings; export interface HookOverlap { event: string; functionTag: string; owners: string[]; registrations: string[]; } /** * Two selected hooks on the same event that declare the same function overlap. * Reported with both owners named, and never auto-resolved: the administrator * decides, which trades convenience for diagnosability on purpose. */ export declare function hookOverlaps(registrations: readonly HookRegistration[]): HookOverlap[]; export interface HookEventSpawnCost { event: string; entries: number; spawns: number; } export interface HookSpawnProjection { events: HookEventSpawnCost[]; totalEntries: number; totalSpawns: number; /** * Processes spent on hooks the source's own controls report as off. This is * not zero and must never be modelled as zero: a source that evaluates its * disable list inside its launcher has already paid for the process. */ sourceDisabledSpawns: number; } /** Per event, entries and expected process spawns — reported before apply. */ export declare function hookSpawnProjection(registrations: readonly HookRegistration[]): HookSpawnProjection; export interface UnownedHookEntry { event: string; /** Attributed only where a declared launcher pin matches; otherwise `unknown`. */ owner: string; command: string; } export interface DriftedHookEntry { id: string; event: string; reason: "missing" | "launcher-pin-mismatch"; } export interface HookDriftReport { destination: string; unowned: UnownedHookEntry[]; drifted: DriftedHookEntry[]; adoption: HookAdoptionOffer[]; /** Entries beyond the reporting bound — counted, never silently dropped. */ omitted: number; } /** * A destination containing entries AIH did not emit is drift. AIH reports them * by owner and event and offers adoption; it never silently absorbs one. */ export declare function hookRegistrarDrift(input: { destination: unknown; registrations: readonly HookRegistration[]; }): HookDriftReport; /** * What `repair` reports about this destination: the ownership verdict plus every * entry AIH did not emit, listed by owner and event. AIH never silently absorbs * one — each is offered for adoption, which is the act that gives AIH the * authority to revoke it later. */ export declare function hookRegistrarReport(root: string): { state: HookRegistrarStateReport["state"]; detail: string; unowned: UnownedHookEntry[]; adoption: HookAdoptionOffer[]; }; export interface HookRegistrarStateReport { /** * `active` is an EXACT match: the `hooks` key holds what the receipt says AIH * wrote and nothing else. `cohabited` is the same ownership proof over a key * that also holds content AIH did not emit — the normal configuration of a * file a repository, a third-party framework and AIH all write, and a state * revocation acts on. Neither one widens the other: a surface that cannot tell * them apart cannot tell an operator what uninstall is about to preserve. */ state: "absent" | "unowned" | "active" | "cohabited" | "drifted" | "invalid"; detail: string; } /** Read-only ownership verdict. It never mutates the destination. */ export declare function hookRegistrarState(root: string): HookRegistrarStateReport; /** * Emit every selected hook entry into the destination AIH owns, and record the * receipt that can revoke them. Entries AIH did not emit are refused rather than * absorbed — adoption is an explicit act, never a side effect of projecting. */ export declare function hookRegistrarProjectionActions(ctx: PlanContext, registrations: readonly HookRegistration[], options?: { policyVersion?: string; envPatch?: EccHookEnvPatch; destinationRead?: GuardedRead; }): Action[]; /** * Remove every projected entry — third-party ones included — and restore the * bytes the destination had before AIH first projected. No hand editing, and no * dependence on the source shipping an uninstall path of its own. */ export declare function hookRegistrarRevocationActions(ctx: PlanContext, options?: { envPatch?: EccHookEnvPatch; destinationRead?: GuardedRead; }): Action[];