iterion

ADR-059 — Skill library: a first-class, referenceable store of skills

Status: accepted (2026-07-05).

Context

Skills (Claude Code SKILL.md markdown files) exist in iterion today only coupled to a distributing artifact:

Both sources converge on one mount point — <workspace>/.claude/skills/ — read by claude_code (--setting-sources project) and by claw’s skill tool (skillLookupRoots). There is no standalone library: nowhere to author/curate skills independently of a bundle, and no way for a workflow to reference a specific skill by name. The closest primitive, the synthesized skills-only plugin, is an all-or-nothing import a git repo unit with an install/enable lifecycle — the wrong shape for “a library the operator edits skill-by-skill and a workflow cherry-picks from”.

Decision

Introduce a first-class skill library with two coordinated halves:

  1. A dedicated store (pkg/skilllib), modeled on the local sealed-secret store (pkg/secrets/local.go): global ~/.iterion/skills/<name>/SKILL.md with a per-project override <workDir>/.iterion/skills/<name>/SKILL.md (directory form, flat <name>.md fallback). Per-skill CRUD; project shadows global by name. This is the hybride model: the dedicated store holds hand-authored/edited skills, and the existing plugin path (SynthesizeSkillsManifest) is retained as the third-party pack import route, surfaced as iterion skill import <git-url>.

  2. A DSL reference — a skills: [name, ...] field on agent/judge nodes and as a workflow-level default (modeled exactly on capabilities:). At run start the runtime resolves the union of referenced names against the library and mirrors only those into .claude/skills/ (reusing the existing 4-branch reconcileSkillFile collision policy), and injects a ## Skills hint (name + description, referenced-by-the-node only) into that node’s system prompt. The skill body is loaded on demand by the agent from .claude/skills/, not inlined.

Reuse, don’t duplicate: the frontmatter parser (runview.readSkillFile) is extracted into a shared helper; the mirror engine (runtime.reconcileSkillFile) is called as-is.

Resolved sub-decisions

Consequences