# FPF-Aligned Agent Skills Spec (repo-local)
This spec defines how to slice an on-disk “skill” into 4 modules so the runtime can load safely and testably.
## Terms
- Kernel: the instruction body (Markdown) that *does work*.
- Boundary: the YAML frontmatter that *declares the public contract* (identity + compatibility).
- Governance: the subset of Boundary that *constrains* execution (tools, budgets, guards).
- Lifecycle: the runtime that discovers, parses, validates, activates, and records outcomes.
## On-disk contract
A skill is a directory containing `SKILL.md`.
`SKILL.md` MUST start with a YAML frontmatter block delimited by `---` lines, followed by a Markdown body.
Example:
```md
---
name: fpf-skill:hello-world
description: Greets with a short JSON response.
allowed_tools: []
---
# Instructions
...
```
## Separation rule (the knife)
Given the raw bytes of `SKILL.md`:
1. Boundary = YAML between the first `---` and the next `---` (exclusive).
2. Kernel = everything after the closing `---` (verbatim, including leading newlines).
### Boundary fields
Required:
- `name` (string): stable identifier; MUST match directory intent.
- `description` (string): human-readable summary.
Optional (common):
- `version` (string)
- `license` (string)
- `compatibility` (object or string map)
- `metadata` (string map)
Governance fields (optional, but if present they MUST be enforced):
- `allowed_tools` (string array): tool names the skill may call; default = empty array.
- `budgets` (object): e.g., `{ tokens: 1000, time_ms: 5000 }`
- `guards` (object): tri-state guard declarations (allow/deny/unknown).
## Runtime requirements (Lifecycle)
A conforming runtime MUST:
1. Discover skills in a registry root (default: `skills/`).
2. Load `SKILL.md` by `name` → directory mapping.
3. Parse Boundary+Kernel exactly per the knife rule.
4. Expose `allowed_tools` as an array (empty if absent).
5. Fail closed on malformed frontmatter (treat as invalid skill).
6. Provide test hooks for BDD scenarios (black-box acceptable).
## Validation rules (minimum)
- `name` exists and is non-empty.
- If `allowed_tools` exists, it is an array of non-empty strings.
- Kernel is non-empty for “active” skills (policy choice; tests can assert expectations).
## BDD acceptance focus
The first acceptance scenario is: load the reference skill and assert:
- Boundary.name
- Kernel contains a sentinel phrase
- allowed_tools is empty