agentleFS
stjarnstromstjarnstrom/spec-system/skills/spec-adopt/SKILL.md

spec-adopt

Skill0 starsChanged 45 days agoMITView on GitHub

Write the first spec for a capability by describing what the code does today: statements pinned as written, evidence mapped from existing tests, anomalies recorded, nothing fixed. Use when the user wants to adopt a capability, bring existing code under spec, or invokes /spec-adopt on a capability named in specs/registry.yaml.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read reality in full: Every owned path, every test that touches them, and the repo's own record — agent instructions, the glossary, the …

    line 25
  2. Very specific:

    Keep each frontmatter list entry on a single line — the bundled YAML fallback in registry.mjs is line-oriented and rejects wrapped entries.

    line 65
  3. Distinctive:

    Update the adopted-capabilities list in the host repo's agent instruction file (the section spec-init installed).

    line 81

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Adopt a capability: describe reality, change nothing. The pin asserts the code satisfies the spec right now — a pin that is a lie from birth makes every later drift check worthless. Desired behaviour is the next amendment's business, never adoption's.

Procedure

  1. Gate. node specs/registry.mjs check must pass. The capability must already be named in specs/registry.yaml with status unspecified or partial (no registry → spec-init first; not listed → propose the entry and stop for the user — naming boundaries is their call). contested means the boundary itself is not agreed: stop, adoption would pin code to a disputed line.
  2. Read reality in full. Every owned path, every test that touches them, and the repo's own record — agent instructions, the glossary, the ADRs that mention this behaviour. You are about to state truth at implementation detail; skimming produces plausible fiction that check cannot catch.

    Scoping tripwire: if the draft needs a table of contents, it is two capabilities — stop and propose the split instead of adopting a layer.

  3. Settle the boundary before writing statements. The registry's paths are hypotheses; adoption is when they get tested against the code.
    • Claim shared files symbol-by-symbol (path#symbol), never whole.
    • Behaviour found in the owned paths that belongs to another capability → an excludes entry naming the owner; contracts this one consumes → depends-on (upgrade any source: code edge to source: spec).
    • A file every capability crosses is a seam — propose it as one rather than owning it.
    • Edit the registry's paths to match what you learned; check enforces disjointness.
  4. Write the statements in specs/<slug>.md per FORMAT.md, IDs under the registry's prefix:

    • Requirements — one observable behaviour each, present tense, no rationale, no history. State what the code does even when what it does is ugly; the wish goes on the anomaly list.
    • verified-by — map existing tests, many-to-many, #describe name for blocks. Where nothing covers a requirement, write UNVERIFIED and keep it: it is the signal that makes coverage arguable. Never write a test during adoption — a test derived from a spec that was derived from the code verifies nothing.
    • Invariants — only properties of the whole capability. Before keeping one, prove it against today's code: actively search for the counter-example (grep for the escaping token, the crossing import). An invariant that is currently false is not an invariant — it is an anomaly and often an uncertainty. Give each a one-line falsifying checked-by command (exit 0 = holds; confirm it goes red on a planted violation before trusting it) or UNCHECKED.
    • Uncertainties — only questions that reading the code twice cannot answer. An uncertainty is not a to-do.

    Keep each frontmatter list entry on a single line — the bundled YAML fallback in registry.mjs is line-oriented and rejects wrapped entries.

  5. Record anomalies in specs/<slug>.anomalies.md: everything the owned code does that nothing justifies — one line plus path, grouped by kind, fixing nothing. The judgement is host-repo-relative: behaviour an ADR or a repo convention explains is not an anomaly here, however odd it looks. Cite the statement an anomaly contradicts where one exists. A long list is fine — its later conversion into spec changes runs well under 1:1, and a spec that absorbs its anomaly list is doing code review's job.
  6. Pin. In the registry: spec:, prefix:, pinned: none, status adopted — or partial with the uncovered remainder stated in the spec's not-covered. Then node specs/registry.mjs pin <capability> records the spec file's content hash as what the code satisfies — the adoption's last act. Run check, then sync to regenerate the tables. Update the adopted-capabilities list in the host repo's agent instruction file (the section spec-init installed).
  7. Report. The counts (requirements and verified/total, invariants and how many checked, uncertainties, anomalies), any boundary changes made in step 3, and the open uncertainties restated as questions for the user.

Rules

  • Adoption changes no code. Outside specs/ and the instruction-file list, git diff stays empty; anything that itches becomes an anomaly line, not a fix.
  • Statements state what is. If a statement cannot be truthfully pinned, the statement is wrong — not the code.
  • From the moment the spec is committed, IDs are permanent: never renumbered, never reused.
  • One capability per adoption. Discoveries about a neighbour's boundary go to the user in the report, not into this spec.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.