import { type CodexAdmissionReceipt, type CodexCorpusWriteOptions } from "./codex-corpus-write.js"; import { connectCodexHookRpc } from "./codex-hook-rpc.js"; import { type ReviewedCodexSkillDenial, type CodexPluginSkillControl } from "./codex-plugin-skill-controls.js"; import { type CodexNativeHookEnvelope, type ProcessInspector, type NativePolicyHelperRunner } from "./codex-native-skill-policy.js"; import { type CodexNativeSkillCatalog } from "./codex-native-skill-catalog.js"; import type { NativeDiscoveryWitnessKind } from "./native-discovery-witness-change.js"; import { type BigIntStats } from "node:fs"; import { type DiscoveryExecutable, type AgentDiscoveryBinding, type ReviewedDiscoveryInputs } from "./agent-discovery.js"; import { type IntegrationAgent } from "./agent-adapters.js"; import type { CodexHookDiscoveryRecovery } from "./codex-hook-discovery-recovery.js"; import { type ClaudeCoordinatedHookEvent } from "./claude-settings-witness.js"; import { type ReviewArtifactChange } from "./retained-review-artifacts.js"; import { type NativeSkillAllowance } from "./native-skill-allowance.js"; export type { IntegrationAgent } from "./agent-adapters.js"; export type { NativeSkillAllowance } from "./native-skill-allowance.js"; export type ContextHookEvent = "UserPromptSubmit" | "SessionStart" | "SubagentStart"; export interface AgentRootAlias { agent: IntegrationAgent; home: string; alias: string; target: string; link: string; aliasIdentity: string; targetIdentity: string; } export interface NativeSkillEntry { agent: string; path: string; hash: string; managed: boolean; vendor: boolean; system?: boolean; bridge?: boolean; bridgeHome?: string; rootAlias?: AgentRootAlias; codexHome?: string; allowed?: { id: string; treeSha256: string; }; allowanceUnknown?: true; } export interface NativeMigrationTarget { agent: string; projectRoot: string; path: string; treeSha256: string; vendor?: true; } export interface NativeMigrationTargetManifest { schema: "hasna.skills-native-migration-targets.v1"; targets: NativeMigrationTarget[]; digest: string; } export interface AgentConfigChange { path: string; before: string | null; after: string; } export interface AgentIntegrationPlan { codexReconcile?: CodexPluginReconcilePlanState; cacheWitnessUpgrade?: CodexSemanticCacheUpgrade; reviewArtifactSources?: Array<{ path: string; sha256: string; }>; retainedReviewArtifacts?: ReviewArtifactChange[]; reviewArtifactMigration?: ReviewArtifactMigration; observedNativeSources?: Array<{ path: string; sha256: string | null; }>; codexPluginSkillReview?: { version: string; cwd: string; catalogSha256: string; configSha256: string | null; }; observedSettings?: { path: string; before: string; }; settingsWitnessUpgrade?: { agent: "claude" | "codex" | "sumi"; path: string; fromHashMode: string; fromSha256: string; toHashMode: string; toSha256: string; reviewedPreimage: string; currentSettingsSha256: string; replacedWitnesses: Array<{ hashMode: string; sha256: string; }>; }; dataDir: string; profileId: string; changes: AgentConfigChange[]; nativeSkills: NativeSkillEntry[]; observedPolicy?: { path: string; before: string | null; }; discoveryBefore?: AgentDiscoveryBinding[]; discoveryAfter?: AgentDiscoveryBinding[]; discoveryExecutables?: Record; rootAliases?: AgentRootAlias[]; managedAgentChecks?: { home: string; projectDir?: string; agents: IntegrationAgent[]; }; retainedReviewChecks?: { home: string; projectDir: string; agents: IntegrationAgent[]; }; nativeSkillAllowances?: NativeSkillAllowance[]; } /** Normalize only the verified OS prefix, never hide user-controlled links. */ export declare function canonicalSystemPath(path: string): string; export declare function canonicalAgentPath(path: string, aliases: AgentRootAlias[]): string; export declare function recheckRootAliases(aliases: AgentRootAlias[]): void; /** Parse the reviewed exact-target binding used by native migration. Paths are * deliberately project-relative so a manifest cannot silently select another * checkout when a project root changes. */ export declare function parseNativeMigrationTargetManifest(input: string | Buffer): NativeMigrationTargetManifest; /** Read a manifest without following links or opening special files, with a * finite bound so a CLI cannot block on an untrusted path. */ export declare function readNativeMigrationTargetManifest(path: string): NativeMigrationTargetManifest; /** Validate every reviewed target before any archive directory or journal is created. */ export declare function selectNativeMigrationTargets(inventory: NativeSkillEntry[], manifest: NativeMigrationTargetManifest): NativeSkillEntry[]; export declare function inventoryNativeSkills(home?: string, options?: { includeVendor?: boolean; guardHermes?: boolean; projectDir?: string; projectDirs?: string[]; agents?: readonly IntegrationAgent[]; agentRoots?: Array<{ agent: string; path: string; }>; configured?: boolean; discoveryInputs?: ReviewedDiscoveryInputs; allowRootAliases?: boolean; reviewedCacheAlias?: string; nativeSkillAllowances?: readonly unknown[]; nativeSkillAllowancePolicyUnproven?: boolean; disabledVendorPaths?: readonly string[]; disabledVendorSkill?: (entry: NativeSkillEntry) => boolean; codexInstallationInputRoots?: readonly string[]; }): NativeSkillEntry[]; /** Planning is read-only; credentials and unrelated settings never appear in CLI output. */ export declare function planAgentIntegration(options: { home?: string; dataDir?: string; agents: IntegrationAgent[]; command?: string; profileId?: string; includeVendor?: boolean; projectDir?: string; discoveryInputs?: ReviewedDiscoveryInputs; allowRootAliases?: boolean; reviewedCacheAlias?: string; reviewCuaDriverSkill?: boolean; codexNativeCatalog?: CodexNativeSkillCatalog; codexSkillDenials?: ReviewedCodexSkillDenial[]; codexReconcile?: CodexPluginReconcileInput; }): AgentIntegrationPlan; export interface ClaudeManagedHookProjection { schema: "hasna.claude-managed-hook-projection.v1"; targetSha256: string; sourceSha256: string; replacements: Array<{ event: string; groupIndex: number; hookIndex: number; beforeSha256: string; command: string; }>; } export interface ClaudeManagedHookProjectionOptions { home?: string; dataDir?: string; projectDir?: string; /** Exact caller-owned bytes, never a new native home or a path to be written. */ targetSettings: string; expectedTargetSha256: string; /** Supply the preceding plan's source witness when checking it before use. */ expectedSourceSha256?: string; } export declare function assertNativePathAcl(path: string, observed: BigIntStats, options?: { allowDenyOnly?: boolean; descriptor?: number; creationParent?: boolean; }): void; /** Read-only projection for a copied Claude configuration. This does not install * hooks, adopt target discovery, change policy, or confer write/admission authority. * The caller must preserve the full target, hold its owning writer lease, replan * against both witnesses, CAS the full bytes and revalidate after application. */ export declare function planClaudeManagedHookProjection(options: ClaudeManagedHookProjectionOptions): ClaudeManagedHookProjection; /** Plan an explicitly authorized Stop hook replacement without adopting drift. * The caller owns authorization of its exact Stop hook delta; Skills refuses * every other settings change and owns discovery witnesses and guarded writes. * No policy means this installer has no Skills integration to update. */ export interface ClaudeHookUpdateOptions { home?: string; dataDir?: string; expectedSettingsSha256: string; replacement: string; } export declare function planClaudeStopHookUpdate(options: ClaudeHookUpdateOptions): AgentIntegrationPlan | null; /** Cooperating safety installers may replace only PreToolUse. The caller owns * its exact hook authorization; Skills retains discovery and native guards. */ export declare function planClaudePreToolUseHookUpdate(options: ClaudeHookUpdateOptions): AgentIntegrationPlan | null; export declare function planClaudeHookEventsUpdate(options: ClaudeHookUpdateOptions & { events: readonly ClaudeCoordinatedHookEvent[]; }): AgentIntegrationPlan | null; /** Explicitly rebind one legacy review after exact preimage and semantic comparison. * Runtime readers never relax the old witness. All other discovery sources, * unknown settings, native controls and policy bytes remain guarded. */ export declare function planAgentSettingsWitnessUpgrade(options: { agent: "claude" | "codex" | "sumi"; targetCodexVersion?: 2 | 3 | 4 | 5 | 7 | 8; targetClaudeVersion?: 3 | 4 | 5; reviewedPreimage: string; home?: string; dataDir?: string; projectDir?: string; expectedPolicySha256: string; expectedSettingsSha256: string; }): AgentIntegrationPlan; export interface CodexSemanticCacheUpgrade { agent: "codex"; appOnlyParents: string[]; /** Explicit cache parents whose complete native mcp_tool hook contract was already enrolled. */ reviewedHookParents?: string[]; expectedPolicySha256: string; expectedSettingsSha256: string; expectedCacheWitnessSha256?: string; home?: string; dataDir?: string; } /** Explicit current capability review. Old aggregate directory digests remain * evidence, not a reconstructed historical tree or a new byte baseline. */ export declare function planCodexSemanticCacheWitnessUpgrade(options: CodexSemanticCacheUpgrade): AgentIntegrationPlan; export interface ReviewArtifactMigration { kind: "codex-native-catalog"; sourcePath: string; expectedPolicySha256: string; expectedSourceSha256: string; home?: string; dataDir?: string; projectDir?: string; } /** Explicit exact-proof migration. Never captures a new catalog or refreshes live inputs. */ export declare function planReviewedArtifactMigration(options: ReviewArtifactMigration): AgentIntegrationPlan; /** Exact copies, names and deny rows one Codex name reconcile plans. */ export interface CodexPluginReconcileInput { copies: Array<{ path: string; hash: string; }>; /** New qualified names added to the reviewed controls. */ names: string[]; /** Plugin parents whose documents the reconcile reviews: enrolled and newly enrolled. */ parents: string[]; /** Caller-verified native install receipts: of newly enrolled remote parents, * and of enrolled remote parents whose stored controls lack one (healed). */ remoteIdentities: Record; /** Catalog-only skills outside the plugin cache: deny-only rows, no control. */ nameDenies: string[]; pathDenies: string[]; /** The saved review with stale enrolled-plugin cache witnesses re-captured. */ discovery?: AgentDiscoveryBinding; } export interface CodexPluginReconcileRequest { home: string; dataDir: string; projectDir: string; catalog: CodexNativeSkillCatalog; } export interface CodexPluginReconcilePlanState extends CodexPluginReconcileInput { request: CodexPluginReconcileRequest; } export interface CodexPluginReconcileReport { codexVersion: string; /** Qualified names this reconcile adds to the reviewed controls and denies by name. */ enrolled: string[]; /** Qualified names already enrolled before this reconcile. */ alreadyEnrolled: number; /** Catalog skills outside the plugin cache (Codex runtime plugins) denied by their stable qualified name. */ denied: string[]; /** Skills denied by exact path because no stable qualified name covers them, with the reason. */ pathDenied: Array<{ name: string; path: string; reason: "plugin-disabled" | "no-qualified-name"; }>; /** Plugins explicitly disabled in [plugins]: no enrollment and no refusal. */ inactive: string[]; /** Every plugin this run classified as skills-only, citing the manifests read. */ classified: Array<{ pluginId: string; capabilities: string[]; manifests: string[]; }>; /** Reviewed cache witnesses re-captured after a skills-only version change. */ rebasedWitnesses: number; /** Enrolled remote plugins whose controls stored without the install receipt gain the verified one. */ bound: string[]; /** Plugin-cache skill names left as they are: an existing path rule or an inactive plugin already makes them inert. */ skipped: number; /** Native skills Codex loads after the reconcile; always exactly the bridge. */ allowed: string[]; } /** A refusal: nothing was written and the guard keeps blocking with `code`. */ export declare class CodexPluginReconcileRefusal extends Error { readonly code: string; readonly refusals: Array<{ pluginId: string; reasons: string[]; manifests?: string[]; }>; constructor(code: string, detail: string, refusals?: Array<{ pluginId: string; reasons: string[]; manifests?: string[]; }>); } /** The reconcile writes only appended disable rows and the bounded policy fields * that record them; anything else is a different review and refuses. */ export declare function assertCodexReconcileScope(plan: AgentIntegrationPlan, scope: { configPath: string; policyPath: string; prior: CodexPluginSkillControl[]; names: string[]; remoteIdentities?: Record; discovery: AgentDiscoveryBinding; }): void; /** Read-only plan for `skills hook codex-reconcile`. Enumerates the plugin-cache * skills the strict guard refuses and the catalog skills Codex would load from * its runtime cache; enrolls plugin-cache names whose capability tuple is * unchanged (or a not yet enrolled skills-only plugin), denies runtime skills by * qualified name (by exact path, reported, when Codex gives none), and refreshes * the reviewed binding through planAgentIntegration. A null plan means nothing * needs writing. Every refusal writes nothing. */ export declare function planCodexPluginNameReconcile(request: CodexPluginReconcileRequest): { plan: AgentIntegrationPlan | null; report: CodexPluginReconcileReport; }; export declare function applyAgentIntegration(plan: AgentIntegrationPlan, options?: CodexCorpusWriteOptions): { changed: string[]; backups: string[]; rootAliases?: AgentRootAlias[]; } & CodexAdmissionReceipt; export interface CodexReconcileApplyOptions extends CodexCorpusWriteOptions { /** The Codex home the owned app-server uses; omit for the default ~/.codex. */ codexHome?: string; /** Test seam for the owned Codex app-server; production starts `codex app-server`. */ connect?: typeof connectCodexHookRpc; } export interface CodexReconcileApplyResult extends CodexAdmissionReceipt { changed: string[]; backups: string[]; receipt?: string; nativeConfigVersion?: string; rootAliases?: AgentRootAlias[]; } /** Apply a Codex name reconcile. The deny rows go through Codex's own writer * (`config/batchWrite` with the user layer's `expectedVersion` and * `reloadUserConfig`), so a concurrent Codex writer such as the desktop app * makes the write refuse instead of being overwritten. The policy is written in * the Skills transaction only after the config readback matches the plan. * Either failure is compensated; the config is restored only through Codex's * writer and only when nobody changed it since this run's write. */ export declare function applyCodexPluginReconcile(plan: AgentIntegrationPlan, options?: CodexReconcileApplyOptions): Promise; export declare function archiveNativeSkills(inventory: NativeSkillEntry[], options: CodexCorpusWriteOptions & { dataDir?: string; includeUnmanaged?: boolean; includeVendor?: boolean; allowRootAliases?: boolean; targetManifest?: NativeMigrationTargetManifest; }): { entries: Array<{ source: string; archive: string; hash: string; discoveryOnly?: boolean; }>; receiptPath?: string; rootAliases?: AgentRootAlias[]; targetManifest?: { schema: string; digest: string; targetCount: number; }; } & CodexAdmissionReceipt; /** Native hook input for the Codex policy adapter. Only the Codex hook paths that * receive native SessionStart/UserPromptSubmit input supply it; install-time and * other guard calls never do. `inspector` is a test seam for process lineage. */ export interface CodexNativePolicyGuardInput extends CodexNativeHookEnvelope { inspector?: ProcessInspector; helperRunner?: NativePolicyHelperRunner; /** Absolute epoch ms by which the hook must answer; bounds the hash and helper. */ deadlineMs?: number; } interface ManagedBridgeOptions { home?: string; dataDir?: string; projectDir?: string; projectDirs?: string[]; profileId?: string; codexDiscoveryRecovery?: CodexHookDiscoveryRecovery; codexNativePolicy?: CodexNativePolicyGuardInput; /** Live Codex prompt hook only. Exempt vendor Codex plugin-cache copies that * Codex configuration provably disables, and tolerate, with a warning, the * discovery-witness changes a vendor plugin refresh provably makes. Enabled * vendor copies and every other change still refuse. Install, trust, migrate * and sync never pass it. */ codexPromptHook?: boolean; /** Live lifecycle hooks only (prompt, session, subagent and tool events). * - A legacy full-file settings witness that no longer matches stays current * when the narrowed digest recorded for its review is unchanged, and a * matching one is recorded (narrowed-witness-ledger.ts). * - Anything that stops the skills-cli bridge from being verified is a * NativeBridgeIntegrityRefusal, and any other failure to verify native * discovery (a changed root alias, an unreadable settings file, an * inventory error) is reported as NATIVE_SKILL_DRIFT, so the hook can fail * open instead of blocking the prompt. * Install, trust, migrate, sync and upgrades never pass it. */ liveHook?: boolean; /** Live tool events that would load the skills-cli bridge (Claude * Skill(skills-cli), Gemini activate_skill(skills-cli), Hermes * skill_view(skills-cli)); requires liveHook. Before such a call proceeds, * no native copy may be able to resolve under the bridge's own name, in any * tier the agent searches, including after an earlier drift skipped the * inventory. A found copy, or a check that cannot complete, is a * NativeBridgeIntegrityRefusal. */ bridgeToolCall?: boolean; /** Install planning only: the reviewed Cua driver allowance this plan will * record. Guards called after the write read it back from the policy, so a * failed policy write cannot be hidden by reusing the plan's copy. */ nativeSkillAllowances?: readonly NativeSkillAllowance[]; } /** Result of a guard call; both lists are empty unless the caller opted in. * `codexInertVendorCopies` holds the canonical skill directories exempted as * disabled vendor copies; `codexDiscoveryChanges` the witnesses tolerated as a * vendor plugin refresh. */ export interface ManagedBridgeReport { codexInertVendorCopies: string[]; codexDiscoveryChanges: Array<{ kind: NativeDiscoveryWitnessKind; path: string | null; }>; } /** Package-classified installed-plugin content below the Codex plugin cache that * a verified restricted policy cannot load. Classification is the existing plugin * manifest identity and real-path binding, never a path prefix; user, repo and * project copies, unclassified cache files and any allowed host path refuse. */ export declare function isInertCodexPluginCacheCopy(entry: NativeSkillEntry, cache: string, allowedHostPaths: readonly string[], read: (path: string) => string): boolean; /** A vendor plugin-cache copy that Codex configuration provably disables, so its * payload never loads natively. Vendor means: classified installed-plugin content * in an allowlisted OpenAI marketplace (exact names), with the native remote * install receipt for remote marketplaces, no Skills-managed or Hasna marker, * and a plugin whose every cached version passes the fail-closed refresh check * (codexVendorPluginRefreshSafe: one Codex manifest with only known keys, no * hooks, MCP, command, agent or extension declaration, no other manifest * location, no link and no skill hidden from the inventory or nested in * another). Classification reads only the Codex manifest, so without that check * a version could load payloads no rule here covers. Disabled means: a `[[skills.config]]` * rule names its exact SKILL.md path or its plugin-qualified name with * `enabled = false` (the native ordered evaluation agrees), and no matching rule * enables it. A whole-plugin `[plugins.""] enabled = false` table is never * enough: remote state can enable a locally disabled remote plugin, and a * cache copy carries no proof that its source is configuration-controlled. */ export declare function isInertCodexVendorPluginCopy(entry: NativeSkillEntry, cache: string, rules: unknown, read: (path: string) => string): boolean; /** Visible, non-blocking warning for the discovery-witness changes the live Codex * prompt hook tolerated as a vendor plugin refresh, or undefined when there were * none. One bounded line; paths only, never payloads or file contents. */ export declare function codexPromptDriftWarning(report: ManagedBridgeReport): string | undefined; /** Run before any prompt context load. Missing ownership or reappearing native * discovery files require repair; verified cache availability is not an override. */ export declare function assertManagedAgentBridge(agent: IntegrationAgent, options?: ManagedBridgeOptions): ManagedBridgeReport; /** Consumption-edge check: native registry content and path must name the * exact owned bridge, and live on-disk custody must still verify now. */ export declare function assertOpenCodeNativeBridge(skill: unknown, options?: ManagedBridgeOptions): void; export declare function normalizeAgentHookPrompt(agent: IntegrationAgent, event: string, prompt: string): string; export declare function isAgentSubmittedPrompt(prompt: unknown): boolean; export declare function hookContextOutput(event: string, result: { context: string; receipt?: unknown; omitted?: Array<{ slug: string; version: string; loadCommand: string; }>; }): Record; export declare function assertNativeExportAllowed(dataDir?: string): void;