import { z } from "zod"; /** * Committed skill approval lockfile at the repo ROOT (`aih-skills.lock.json`) — * the team-shared record of WHICH external skills are approved, at WHAT commit, * against WHICH evidence. Root-level and committed like `aih-org-policy.json` * (NOT the gitignored `.aih/`, which holds local evidence), so a fresh clone * reads the same approvals the reviewer made. */ export declare const AIH_SKILLS_LOCK_FILE = "aih-skills.lock.json"; /** * Skill names come from COMMITTED, hand-editable files (the lockfile, pack * manifests) and later feed PATH construction (`skillCardRelPath`, promoted-dir * resolution). A crafted name like `../../package-lock` would traverse out of the * card directory and let a destructive command archive an arbitrary in-repo file — * so names are validated at every parse boundary: forward-slash-separated segments * only, no empty/`.`/`..` segments, no absolute/drive/UNC forms, no backslashes or * control characters. */ export declare const skillNameSchema: z.ZodString; export declare const sourceScopePathSchema: z.ZodString; export declare const SkillLockEntrySchema: z.ZodObject<{ name: z.ZodString; source: z.ZodString; commit: z.ZodString; verdict: z.ZodEnum<{ GREEN: "GREEN"; YELLOW: "YELLOW"; }>; pack: z.ZodOptional; firstParty: z.ZodOptional; scope: z.ZodString; card: z.ZodString; evidenceSha256: z.ZodString; sourceScope: z.ZodOptional; includedPaths: z.ZodArray; excludedSkillPaths: z.ZodArray; }, z.core.$strip>>; approvedBy: z.ZodOptional; approvedAt: z.ZodString; }, z.core.$strip>; export type SkillLockEntry = z.infer; export interface SkillsLock { schemaVersion: 1; skills: SkillLockEntry[]; } export declare const MAX_SKILLS_LOCK_BYTES: number; export type ExactSkillsLockRead = { state: "absent"; } | { state: "malformed"; } | { state: "valid"; lock: SkillsLock; sourceBytes: Buffer; sourceSha256: string; mode: number; }; export interface ExactSkillsLockReadDeps { afterInspect?: () => void; afterOpen?: () => void; } export declare function readSkillsLockExact(root: string, deps?: ExactSkillsLockReadDeps): ExactSkillsLockRead; /** * Read the committed skills lockfile. Fail-SOFT per entry (mirrors * `readTrustLock`): a malformed file yields an empty lock and a malformed ENTRY * is dropped while valid siblings survive — so an upsert + rewrite never * crashes on hand-edited state, and never amplifies it either. Duplicate NAMES * are dropped the same way (first entry wins): every aih writer dedupes by name, * so a duplicate can only come from a hand-edited file — and letting it through * would make every by-name join downstream (inventory, packs, marketplace) * silently last-write-wins on which source/commit/pack a skill "has". */ export declare function readSkillsLock(root: string): SkillsLock; export declare function readSkillsLockStrictForWrite(root: string): SkillsLock; /** Replace-or-append `entry` by skill name — immutable, name-sorted for stable committed diffs. */ export declare function upsertSkillLockEntry(lock: SkillsLock, entry: SkillLockEntry): SkillsLock; /** Drop the entry for `name` — immutable, sibling order preserved (the mirror of {@link upsertSkillLockEntry}). */ export declare function removeSkillLockEntry(lock: SkillsLock, name: string): SkillsLock;