/** * Deterministic guards on every skills write/enable (design v3 §API) — v1 has NO semantic analyzer; * these are the checks a file manager can decide from the manifest and the bytes alone, answered * identically on every daemon: * * - name charset + prefix; name UNIQUE across the FULL catalog, disabled skills included * (a manifest is keyed by name — a duplicate is a blocking collision, annotated with whether * the skill it collides with is core-by-reference, so the UI can say why it matters); * - the SKILL.md frontmatter parses and its `name` equals the path-derived name (a rename in * place would desynchronize the manifest key, the invocation identity, and the directory); * - disabling or renaming a core-by-reference skill is blocking — a governed run would dispatch * a phase whose skill is gone from the snapshot; * - a `SKILL.md` anywhere but a skill's root is blocking: it would create an unregistered nested * skill through the parent's endpoint (nested ownership, v3 §6) — `POST /skills` adds skills; * - an edit under `scripts/` or `schemas/` (a skill's own, or the root support tree) is allowed * but a WARNING: those files back behavior, not prose, and every invocation shares them; * - content that makes a skill non-portable (`${CLAUDE_PLUGIN_ROOT}`, `${CLAUDE_SKILL_DIR}`, * cwd-relative scripts, `../` links, paths into another skill, a declared * `requires-harness: claude`) is a warning PER REASON with `file:line` (F-079): the skill * becomes Claude-only and leaves every non-Claude delivery view (`views/copilot/`, the * per-launch `--skill` lists core builds). * * `{verdict, findings[]}` is the ONE result shape; a mutation with a `blocked` verdict writes nothing. * Publish-time validation (unresolved refs, core closure, drift) lives in the store — it needs the * whole tree. */ import type { SkillConflictFinding, SkillFindingKind, SkillFindingSeverity, SkillPortabilityReason, SkillVerdict } from '../core/types.js'; import { type PortabilityContext, type PortabilityIssue } from './refs.js'; /** The name charset — a manifest key, a directory segment, and a URL path segment at once. */ export declare const SKILL_NAME_RE: RegExp; /** The catalog facts the guards consult — structural, so the store hands its manifest in directly. */ export interface CatalogEntryView { core: boolean; enabled: boolean; dir: string; } export type CatalogView = Readonly>; export interface FindingAnchor { skill?: string | null; file?: string | null; line?: number | null; against?: { name: string; core: boolean; }; /** `non-portable` only: the reason this finding reports (api-types 0.34.0). */ portabilityReason?: SkillPortabilityReason; } export declare function finding(kind: SkillFindingKind, severity: SkillFindingSeverity, explanation: string, evidence: string, anchor?: FindingAnchor): SkillConflictFinding; /** `blocked` when any finding blocks, `warnings` when any warns, `clear` otherwise. */ export declare function verdictOf(findings: ReadonlyArray): SkillVerdict; /** Charset + the `wicked-garden-` prefix with a non-empty remainder. */ export declare function nameGuard(name: string): SkillConflictFinding | null; /** Unique across the FULL catalog, disabled skills included. */ export declare function collisionGuard(catalog: CatalogView, name: string): SkillConflictFinding | null; /** * The SKILL.md body must carry parseable frontmatter whose `name` is exactly `expectedName`. * A mismatch on a core skill additionally reports `core-rename` — the workflow that names it * would dispatch into a void. `severity` lets publish-time validation downgrade a DISABLED * skill's defects to warnings (it is not in the snapshot). */ export declare function frontmatterGuard(skillMd: string | undefined, expectedName: string, opts: { isCore: boolean; file: string; severity?: SkillFindingSeverity; }): SkillConflictFinding[]; /** A path under `scripts/` or `schemas/` → warning. `rel` is relative to the tree being edited. */ export declare function supportFileGuard(rel: string, skill: string | null): SkillConflictFinding | null; /** A `SKILL.md` anywhere but the skill root would create an unregistered nested skill → blocking. */ export declare function nestedSkillCreateGuard(rel: string, skill: string): SkillConflictFinding | null; /** One sentence per reason token (design W4 §5.1) — the "why" the finding and the studio drawer show. */ export declare const PORTABILITY_EXPLANATION: Record; /** * Content that makes a skill non-portable → ONE warning per reason per file, anchored at the first * line the reason occurs on (further hits are counted in the evidence). `ctxFor` answers the * validator's context for a skill-relative path (where the file sits, what exists in the bundle). */ export declare function nonPortableGuard(files: Readonly>, skill: string, ctxFor: (rel: string) => PortabilityContext): SkillConflictFinding[]; /** Disabling a core-by-reference skill is blocking. */ export declare function coreDisableGuard(name: string, entry: CatalogEntryView): SkillConflictFinding | null; /** Reset needs a baseline; a user-added skill has none. */ export declare function noBaselineGuard(name: string, userAdded: boolean): SkillConflictFinding | null; //# sourceMappingURL=guards.d.ts.map