# `error-codes` ## Purpose Defines the canonical error-code registry for `@suaveplan/install-agent-skills`. Every plugin-side failure path (invalid bundled manifest, unknown skill id under `--only`/`--exclude`, empty/invalid target directory) surfaces as an `InstallSkillsError` carrying a literal-typed `code` from this registry. The host's plan-stage catch (`runPlan`) re-throws any `SuaveplanError` unchanged, so these codes reach the caller without being wrapped in `INSTALLER.PLAN_FAILED`. ## Features - Frozen registry built via `defineCodes("INSTALL_SKILLS", [...])`. - `InstallSkillsError` extends `SuaveplanError` with a public widened constructor. - Three codes in the minimum surface: `MANIFEST_INVALID`, `UNKNOWN_SKILL`, `TARGET_DIR_INVALID`. - Stable `error.name === "InstallSkillsError"` so serialised payloads carry a recognisable name across bundlers. ## Basic Example ```ts import { INSTALL_SKILLS_CODES, InstallSkillsError, } from "@suaveplan/install-agent-skills"; throw new InstallSkillsError( INSTALL_SKILLS_CODES.UNKNOWN_SKILL, "install_skills.unknown_skill", { context: { id: "nonexistent" } } ); ``` ## Advanced Example ```ts import { InstallSkillsError } from "@suaveplan/install-agent-skills"; function classify(err: unknown): string { if (!(err instanceof InstallSkillsError)) return "other"; switch (err.code) { case "INSTALL_SKILLS.MANIFEST_INVALID": return "rebuild bundle"; case "INSTALL_SKILLS.UNKNOWN_SKILL": return "fix --only/--exclude"; case "INSTALL_SKILLS.TARGET_DIR_INVALID": return "supply targetDir"; default: return "unhandled"; } } ``` ## API Reference - `INSTALL_SKILLS_CODES` — frozen `{ [K]: "INSTALL_SKILLS.K" }` map. - `type InstallSkillsErrorCode` — union of every literal in the registry. - `class InstallSkillsError extends SuaveplanError`. ## Implementation Notes The host's plan stage uses `instanceof SuaveplanError` (the shared base class) to decide whether to re-throw or wrap, so codes from this registry flow through the host's plan-stage catch unchanged and reach the caller with their original `INSTALL_SKILLS.*` code intact. `MANIFEST_INVALID` covers parse, read, and schema errors — callers don't have to handle three variants and the underlying cause is always available via `err.cause` for log-and-continue paths. `UNKNOWN_SKILL` is emitted by the plan stage when an `--only` or `--exclude` entry doesn't match any id in the bundled manifest, with the offending id captured in `err.context.id` so error reporters can show useful suggestions. `TARGET_DIR_INVALID` guards against empty or non-string answers; under normal use the prompt schema's default value (`.suaveplan/skills`) prevents this path entirely, but defensive validation ensures programmatic callers can't slip past it.