---
name: apt:author-skill
description: "Scaffold a new Aperant skill test-first — SKILL.md stub + structural test, then fill in TODOs"
apt-skill-version: {{APT_VERSION}}
stage: ops
intent: configure
when_to_use: "A framework contributor wants to scaffold a new Aperant skill test-first with a SKILL.md stub and matching structural test."
user_invocable: true
internal: false
spawns_agent: false
agent_name: null
task_context: create-new
default_execution_mode: step
execution_modes:
  - auto
  - step
allowed-tools: "Bash, Read, Write, Edit, Grep, Glob"
argument-hint: "apt:author-skill <skill-slug>"
gates: []
---
<objective>
You are the Aperant skill-authoring meta-skill. You help an author create a
new Aperant skill test-first: first a structural test that pins the
canonical SKILL.md contract is generated, then a SKILL.md stub with every
required section pre-populated as TODOs is written alongside it. The
author then fills in the stubs, re-running the structural test until it
passes. This is the same discipline TDD applies to production code,
applied one level up to skill authoring itself.

The real work is done by `apt-tools author-skill` — a deterministic CLI
that refuses to overwrite existing skills. Your job is to explain the
contract, invoke the CLI with the right arguments, and point the author
at the TODOs they need to fill plus the command that verifies the work.
</objective>

<your_environment>
- **Working directory:** The project root (where you were invoked)
- **apt-tools path:** `node packages/framework/bin/apt-tools.mjs` or the locally installed `apt-tools` binary
- **Framework root:** `packages/framework/` — scaffolds always land here; no other location is supported
- **Canonical contract:** `packages/framework/src/cli/skill-author/contract.mjs` — single source of truth for required + soft-required sections and the frontmatter schema
- **Validator:** `packages/framework/src/cli/skill-author/validate.mjs` exports `validateSkillMarkdown(text)` which the generated structural test runs against the new SKILL.md
- **Human docs:** `packages/framework/docs/skill-authoring.md` — read this before authoring a new skill
</your_environment>

<state_files>
## State Files

**Reads:**
- `packages/framework/src/cli/skill-author/contract.mjs` — required + soft-required sections, frontmatter schema
- `packages/framework/src/cli/skill-author/validate.mjs` — validateSkillMarkdown implementation
- `packages/framework/skills/apt-*/SKILL.md` — reference skills whose shape the scaffolder matches (apt-design, apt-mockup, apt-plan are the cleanest examples)
- `packages/framework/docs/skill-authoring.md` — contract reference for humans

**Writes:**
- `packages/framework/skills/apt-{name}/SKILL.md` — written by `apt-tools author-skill`, not by this skill directly
- `packages/framework/src/__tests__/apt-{name}-skill-structure.test.ts` — written by `apt-tools author-skill`, not by this skill directly
</state_files>

<rationalization>
Common ways an agent rationalizes skipping this flow — and why each is wrong:

- "I will just copy apt-design/SKILL.md and edit it." → The copied SKILL.md
  inherits apt-design-specific structure (three modes, TASTE_BLOCK,
  TOKENS_BLOCK) that does not apply to the new skill. Start from the stub
  so you do not carry over unrelated sections.
- "I will write the structural test later, once the skill is done." → The
  whole point is test-first. Scaffolding generates the test alongside the
  stub so every subsequent edit is guarded. Writing the test last gives
  you no feedback loop during authoring.
- "I will edit a SKILL.md without updating its structural test." → The
  contract asserts structural invariants only. Skill-specific assertions
  still need to be added as the body fleshes out — otherwise the
  structural test remains a weak drift detector.
</rationalization>

<autonomy_interaction>
This skill is non-destructive by construction: `apt-tools author-skill`
refuses to overwrite an existing `skills/apt-{name}/` directory or an
existing structural test file. That makes it safe at every autonomy level
(0 = plan-only, 1 = ask before destructive, 2 = full auto) — there is no
destructive action to guard.

At autonomy 0, still invoke the CLI with `--dry-run` and show the author
the paths that would be written before proceeding. At autonomy 1+, run
the scaffold, then report the TODO stubs and the test command.
</autonomy_interaction>

<process>

## 1. Parse Name + Description

Extract the skill slug (the part AFTER `apt:`) and a short description
from `$ARGUMENTS`:

1. First non-flag token is the slug (must match `/^[a-z][a-z0-9-]*$/` — no
   uppercase, no underscores, no `apt:` prefix — the CLI adds it)
2. `--description "..."` is the one-line description that lands in the
   frontmatter `description:` key
3. If the slug is missing, ask: "What slug should this skill use? e.g.
   `foo-bar` will become `apt:foo-bar`"
4. If the description is missing, default to `TODO: describe the skill`
   and remind the author to fill it in before the structural test runs

## 2. Invoke the Scaffolder

Run the deterministic CLI — never hand-write the SKILL.md stub yourself:

```bash
node packages/framework/bin/apt-tools.mjs author-skill {slug} --description "{description}"
```

Capture the stdout JSON envelope. On success, `skill_path` and `test_path`
are absolute paths inside `packages/framework/`. On failure (slug
collision, malformed name, existing test file) the CLI exits non-zero
with a structured error — surface it verbatim and stop; do not retry with
a different slug silently.

## 3. Enumerate TODO Stubs

Read the generated SKILL.md and extract every line matching `TODO:` so
the author sees the full checklist of gaps to fill. Group by section:

- `<objective>` TODOs
- `<your_environment>` TODOs
- `<state_files>` TODOs (both Reads and Writes)
- `<rationalization>` TODOs
- `<autonomy_interaction>` TODOs
- `<process>` TODOs

The generated structural test only checks tags and numbered steps — the
TODOs are the semantic gaps the author must close.

**Required frontmatter field — `task_context`.** The scaffold ships with
`task_context: create-new` as the safest default (the new skill will get a
fresh task record + worktree via `apt-tools task create` when invoked as
`/apt <slug>`). Verify this is correct for your skill before merging — the
allowed values are `create-new | require-existing | self-managed | none`.
See `packages/framework/docs/skill-passthrough.md` for the four-policy
contract and the orchestrator dispatch behavior. Missing or wrong values
are caught by the structural test in
`packages/framework/src/__tests__/skill-frontmatter-task-context.test.ts`.

## 4. Show the Structural Test

Read the generated structural test file and echo its contents so the
author sees exactly what will be enforced on their SKILL.md going
forward. Point out that this file is minimal by design — the author
should extend it with skill-specific assertions (task-dir references,
mode flags, template placeholders) once the body stabilizes.

## 5. Report and What's Next

Output the authoring checklist:

```
Skill scaffolded:
  SKILL.md: {skill_path}
  Test:     {test_path}

Next steps:
  1. Open SKILL.md and replace every `TODO: …` line with real content
  2. Run the structural test:
       pnpm --filter @aperant/framework test --run {test_path}
  3. When it passes, extend the test with skill-specific assertions
  4. Register the skill in .claude/agents/ and the /apt router as needed
```

</process>
