Files
skills/feature-spec/SKILL.md
Mathias d6a71e370e
Some checks failed
release / tag (push) Has been cancelled
chore: bootstrap skills library — 19 skills + installer + CI auto-tag
Phase 1 of mathias/skills extraction (infra#62 Track D — homelab
next-step plan addendum). Imports ~/dev/.skills/ verbatim (19 skill
dirs + SKILLS_INDEX.md) and adds the installation surface:

- Taskfile.yml — install / update / list / release / check targets
- install.sh — bootstrap installer for hosts without Task. Idempotent
  symlink wirer; default checkout at ~/.local/share/skills/ on every
  host; SKILLS_REF env var pins a tag (default: main).
- .gitea/workflows/release.yml — auto-tag every push to main by
  Bump-Type footer (major/minor/patch, default patch). Skipped when
  commit contains [skip-release].
- README — usage, versioning, contribution flow, secret-hygiene rule.

Phase 1 wires Claude Code only (~/.claude/skills/<name> global +
<repo>/.claude/skills/<name> per-repo). Phase 2 adds Crush, opencode,
antigravity, and gitea-resident agents (cobalt-dingo, agentsquad)
once their skill conventions are researched.

Public repo, markdown-only — no secrets, no client names. Verified
via pre-push grep before initial push.

[skip-release]
2026-05-24 14:59:54 +02:00

8.0 KiB

name, description
name description
feature-spec Write a tight implementation-level spec for a single feature or component before coding it. Use after a project-level spec exists (see spec-driven-dev) and you need to nail down one feature inside it.

Feature Spec

Overview

A feature spec is the implementation-level contract for one feature or component, written by an engineer before code. It is shorter and more focused than a project-level spec (spec-driven-dev) — it assumes the project context, the stack, and the user are already known. Its job is to force one decision: what does done look like, and what is explicitly not in this feature.

Core principle: If you cannot write three measurable success criteria, you do not understand the feature well enough to build it.

When to Use

  • About to start implementing a feature inside an existing, already-specced project
  • A change that touches more than one file or one package
  • A change that introduces a new public API, schema, or external contract
  • Any time the requirements feel "obvious" — that feeling usually means assumptions are stacking silently

When NOT to use:

  • Project kickoff or first-time architecture decisions — use spec-driven-dev instead, which covers the broader lifecycle (Objective, Tech Stack, Project Structure, Boundaries, etc.)
  • Single-line fixes, typos, dependency bumps
  • Spike or throwaway prototypes (note them as such; no spec needed)

Iron Laws

  1. Success criteria must be measurable. "The system is fast" is banned. "p99 < 200ms under 100 RPS" is valid. If you cannot state a measurement, the criterion is not a criterion.
  2. An "Out of scope" section is mandatory. If you do not draw the boundary, the implementer (you, future-you, or another agent) will guess wrong.
  3. Every technical decision in "Technical approach" must have a rationale. A decision is any choice where a reasonable alternative existed and was not taken. "Use Postgres" is not a decision; "use Postgres because the rest of the stack uses it and we need transactions across user + invoice" is.

Spec Template

# Spec: [Feature Name]

## Problem Statement

What problem does this feature solve? For whom? Why now?
(2-4 sentences. If you cannot answer "why now," ask before writing the rest.)

## Success Criteria

- [ ] Criterion 1 — measurable and verifiable
- [ ] Criterion 2 — measurable and verifiable
- [ ] Criterion 3 — measurable and verifiable

## Constraints

Non-negotiable requirements the solution must satisfy.
Examples: "must not change the public API", "must complete in < 500ms",
"must not require a database migration", "must work offline".

## Out of Scope

What this feature explicitly does NOT do, even if related.
Anything plausibly in scope that you decided to defer goes here.

## Technical Approach

The architecture or design decisions, with rationale for each.
Each bullet should answer "why this choice over the obvious alternative."

## Risks

What could go wrong, and how it would be mitigated or detected.
At least one risk must be listed; "no risks" usually means insufficient analysis.

Worked Example

# Spec: IBAN extraction from Swedish PDF invoices

## Problem Statement

Invoice processors at small accounting firms manually copy IBANs from PDF
invoices into the banking system. The current parser handles ~60% of formats;
40% require manual fallback, defeating the automation premise.

Why now: the pilot customer is onboarding three new firms next month, all of
which use formats currently in the 40%.

## Success Criteria

- [ ] IBAN extracted correctly from ≥ 95% of a 200-invoice test corpus
- [ ] Zero false positives (extracting a non-IBAN string as an IBAN) on the corpus
- [ ] p99 extraction time < 500ms per invoice
- [ ] Returns a structured error (not a panic) for unrecognized formats

## Constraints

- Must not require a new dependency (PDF library is already chosen)
- Must work without network access (no external IBAN validation API)
- Must be callable from the existing `Parser.Extract(ctx, r)` signature

## Out of Scope

- Non-Swedish IBAN formats (separate spec when needed)
- BIC/SWIFT extraction (handled by a separate parser)
- OCR — input is assumed to be text-extractable PDF, not scanned image
- Validating that the IBAN refers to a real account

## Technical Approach

- Layered regex-then-checksum approach: regex narrows candidates, MOD-97
  checksum validates. Rationale: pure regex is too permissive; pure
  checksum requires too many candidates to test.
- Use the existing `pdfplumber` text layer rather than re-extracting.
  Rationale: extraction is already the slow path; reusing the layer
  avoids doubling extraction time.
- Return `(iban string, ok bool, err error)` not `(*IBAN, error)`.
  Rationale: the caller almost always wants to know "did we find one"
  separately from "did extraction itself fail," and a pointer return
  invites nil-deref bugs.

## Risks

- Regex tuned to current corpus may overfit; mitigation: corpus is held out
  per-firm, so we will see degradation at the next firm onboarding before
  it reaches production.
- MOD-97 implementation bugs are subtle; mitigation: cross-check against
  the Wikipedia reference implementation in tests.

Common Rationalizations

Rationalization Reality
"It's a small feature, I don't need a spec" Small features still need a measurable definition of done. The spec stays small too.
"I'll write the spec after, when I know more" Then it is documentation, not a spec. The point is forcing clarity before the code locks in your assumptions.
"The success criteria are obvious" If they are obvious, they are easy to write down. If they are hard to write down, they are not obvious.
"I don't have time to enumerate out-of-scope items" You will spend more time arguing over scope creep at review than writing this section now.

Brain MCP Integration

The brain holds prior feature specs across the project. Use it to keep constraints and out-of-scope decisions coherent across related features.

At spec start:

  • Run brain_query for prior specs in the same area or for the same problem domain. Reusing the same constraints and out-of-scope decisions across related features keeps the system coherent.

After spec is approved:

  • Run brain_write with the spec's success criteria and out-of-scope list. Future related specs can cross-reference rather than re-derive.

Logging

Call session_log once at the end of every phase to record the outcome. Pass-rate is computed downstream by the /pass-rate HTTP endpoint, which treats pass as success, fail as failure, skip as neither.

At end of each phase:

  • session_log with {skill: "feature-spec", phase: "<phase-name>", final_status: "pass" | "fail" | "skip", message: "<one-line summary>", duration_ms: <wall-clock>, project_root: "<absolute path>"}

Phases for this skill: draft

Status semantics:

  • pass — the phase's intended outcome was reached (spec drafted and approved).
  • fail — the phase's intended outcome was NOT reached (spec rejected, blocked on unresolved questions).
  • skip — phase was skipped intentionally.

Why this matters: the routing pod (Plan 6) reads pass-rate to decide whether to route a future call to a local model. If your skill never logs, the routing pod sees no data.

Mode 2 Routing Note

Spec writing requires interpretation of intent and tradeoff reasoning — work where Claude generally outperforms a 9-13B local model. This skill is intentionally not a Mode 2 routing candidate. In Mode 2, the routing layer should leave feature-spec calls on Claude.

Cross-References

  • Load spec-driven-dev instead if this is the first spec for a project (broader template, includes tech stack, project structure, boundaries).
  • Load problem-analysis skill before this if the problem statement itself feels fuzzy.
  • Load tdd skill once the spec is approved — each success criterion becomes a test.
  • Load planning skill if the spec implies more than ~5 implementation tasks.