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.
In this repository14 other files it gives its agents.
- architectureSkill
- debugSkill
- fan-outSkill
- finishSkill
- merge-conflictsSkill
- reviewSkill
- spec-amendSkill
- spec-boundariesSkill
- spec-implementSkill
- spec-initSkill
- spec-reviewSkill
- spec-runSkill
- spec-shapeSkill
- tddSkill
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
- Distinctive: line 25
Read reality in full: Every owned path, every test that touches them, and the repo's own record — agent instructions, the glossary, the …
- Very specific: line 65
Keep each frontmatter list entry on a single line — the bundled YAML fallback in registry.mjs is line-oriented and rejects wrapped entries.
- Distinctive: line 81
Update the adopted-capabilities list in the host repo's agent instruction file (the section spec-init installed).
≈ “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.
Files
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
- Gate.
node specs/registry.mjs checkmust pass. The capability must already be named inspecs/registry.yamlwith statusunspecifiedorpartial(no registry → spec-init first; not listed → propose the entry and stop for the user — naming boundaries is their call).contestedmeans the boundary itself is not agreed: stop, adoption would pin code to a disputed line. 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
checkcannot 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.
- 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
excludesentry naming the owner; contracts this one consumes →depends-on(upgrade anysource: codeedge tosource: 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;
checkenforces disjointness.
- Claim shared files symbol-by-symbol (
Write the statements in
specs/<slug>.mdper 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 namefor blocks. Where nothing covers a requirement, writeUNVERIFIEDand 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-bycommand (exit 0 = holds; confirm it goes red on a planted violation before trusting it) orUNCHECKED. - 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.
- 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. - Pin. In the registry:
spec:,prefix:,pinned: none, statusadopted— orpartialwith the uncovered remainder stated in the spec'snot-covered. Thennode specs/registry.mjs pin <capability>records the spec file's content hash as what the code satisfies — the adoption's last act. Runcheck, thensyncto regenerate the tables. Update the adopted-capabilities list in the host repo's agent instruction file (the section spec-init installed). - 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 diffstays 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.
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
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.

