ADR 0013: SkillTemplate Enrichment — description and allowedTools

Field Value
Status Accepted
Date 2026-05-20
Deciders Project maintainers
Supersedes
Superseded by
Related ADRs ADR-0012 (Spec↔core type reconciliation — defers this), ADR-0006 (Stack-pack contract shape), ADR-0011 (Schema library)

Summary

The v4 kit's SKILL.md files carry a rich description and an allowed-tools frontmatter field; the shipped SkillTemplate type in @aidokit/core has neither. As a result @aidokit/base-skills cannot round-trip the v4 metadata and the adapter's emitSkills synthesises a thinner description — the emitted SKILL.md is not byte-faithful to the v4 kit. This ADR adds optional description and allowedTools fields to SkillTemplate so the metadata survives end to end. It is Accepted and implemented: SkillTemplateSchema carries the two optional fields, @aidokit/base-skills populates them for all 18 skills, and the adapter's emitSkills emits them as description / allowed-tools SKILL.md frontmatter. This satisfies the ADR-0012 validation criterion that a SkillTemplate-enrichment ADR exist before the v4 byte-compare reference snapshot is built.


Context

A v4 SKILL.md (kit Part 3 §51) looks like:

---
name: architecture-summary
description: |
  Architecture conventions for this project: layering … Auto-loads when
  implementing or reviewing backend tasks … Do NOT auto-load for: frontend-only
  tasks, documentation tasks …
allowed-tools: Read, Grep, Glob
---

# Architecture Summary

…

The shipped SkillTemplate (@aidokit/core schema.ts) is:

{ id, name, source, sourcePackId?, content, autoLoadTriggers, preloadedBy, required }

It has no slot for the multi-line description (the agent-facing "when to load / when not" text) nor for allowed-tools. Consequences observed while building @aidokit/base-skills and the adapter's emitSkills:

ADR-0012 recorded this as a deferred follow-up "warranting its own ADR when scheduled". This is that ADR.


Decision

1. Add two optional fields to SkillTemplate

export interface SkillTemplate {
  // … existing fields …
  /** Agent-facing "when to load / when not" text — the SKILL.md description. */
  description?: string;
  /** Tools the skill is permitted to use (Claude Code `allowed-tools`). */
  allowedTools?: string[];
}

Both are OPTIONAL, so existing producers (the stack-pack-node-ts skills, which supply bodies only) keep compiling unchanged. SkillTemplateSchema in @aidokit/core/schema gains the two optional fields.

2. emitSkills uses them when present

When description is set, the adapter emits it verbatim into the SKILL.md frontmatter instead of synthesising one. When allowedTools is set, it emits an allowed-tools frontmatter line. When absent, the current synthesised behaviour is the fallback.

3. @aidokit/base-skills populates them from the v4 frontmatter

Each of the 18 base skills carries its real v4 description and allowed-tools in the metadata table, so the emitted SKILL.md round-trips the v4 content.

4. autoLoadTriggers is unchanged

This ADR does not try to derive structured triggers from the prose description. autoLoadTriggers stays a separate, possibly-empty field; deriving tokens from prose is out of scope.


Consequences

Positive

Negative

Neutral


Alternatives considered

Alternative 1: Leave SkillTemplate as-is

Pros: no schema change.

Cons: emitted skills never match v4; the byte-compare test can never cover skills; the agent gets a thinner description than the kit authored.

Reason rejected: it permanently caps skill fidelity and silently discards authored kit content.

Alternative 2: Make content the full SKILL.md (frontmatter + body); emitSkills passes it through

Pros: perfect fidelity for core skills; no new fields.

Cons: stack-pack skills supply a body, not a full file — emitSkills would have to branch on "is this a full file or a body", which is exactly the ambiguity typed fields remove. Two SkillTemplate shapes in one type.

Reason rejected: it pushes a format ambiguity into every emitSkills consumer; optional typed fields are cleaner.

Alternative 3: Carry the description inside content

Pros: no schema change.

Cons: the description is frontmatter metadata, not body prose; burying it in content means every adapter must parse it back out.

Reason rejected: metadata belongs in typed fields, not in the body.


Validation

This decision is validated when:


References

Internal

External