feature-spec
Skill1 starsChanged 5 days agoMITView on GitHub
Create, audit, and keep-in-sync multi-doc feature specs from a single source of truth (a facts registry), so no two docs ever contradict. Use when the user wants to write a feature spec / design doc set, audit spec docs for consistency, or validate that every shared datum matches across documents.
20 other projects use a version of this.
Adopted by
Most recently taken up by
- insight68/Skillstheir own version, first seen Nov 8, 2026
- PiloTracer/pilo.ai.logicbisontheir own version, first seen Oct 11, 2026
- akachandan1/proofstacktheir own version, first seen Oct 11, 2026
- edu6565/claude-skillstheir own version, first seen Oct 11, 2026
- Simone-Tarantino/godot-superpowerstheir own version, first seen Oct 11, 2026
- WikiEducationFoundation/WikiEduDashboardtheir own version, first seen Oct 9, 2026
Used with
Projects with it also use changelog.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
HashiCorpSkillchangelog
Add a `.changelog/<PR_NUMBER>.txt` entry for a GitHub Pull Request, commit, and push.
Also in 4 projects that use this
Other versions20 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 20
- WikiEducationFoundation/WikiEduDashboard★ 431same name
- PackmindHub/packmind★ 321same name
- https-deeplearning-ai/sc-spec-driven-development-files★ 310same name
- natnew/awesome-ai-scientists★ 20same name
- yasunori0418/skills★ 9same name
- insight68/Skills★ 5same name
- carreiras/claude-skills★ 4same name
- devexpert-io/harness-starter★ 4same name
- gonimar/claude-web-studio★ 4same name
- Simone-Tarantino/godot-superpowers★ 2same name
10 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
We split this skill into the rules it gives an agent
2 rules. 0 are common, 1 is distinctive, and 1 is very specific to this project.
0
Common
Most of the 18 edited versions we read keep these.
1
Distinctive
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
- Very specific: line 10
Core idea: one source of truth: Every shared datum lives once in _facts.yml.
- Distinctive: line 63
The log outranks the context window: Read it first, re-read at the versions it names, open your entry before editing.
“Common” is measured: kept by at least 6 in 10 of the 18 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Feature Spec — spec doc sets that never contradict
A feature spec is not one file — it's a set (master plan + implementation + tests/E2E + stakeholder requirements) that shares many of the same facts (dates, timeouts, contracts, endpoints, bot lists, backoff numbers…). Contradictions creep in because each fact is copied into 3 places and drifts.
Core idea: one source of truth. Every shared datum lives once in _facts.yml. Docs reference it. Auditing stops being "read 3 docs and compare prose" and becomes "check no doc contradicts _facts.yml" — mechanical and near-deterministic.
Where this skill's files are: ${CLAUDE_SKILL_DIR}. Every scripts/…, references/…, templates/…, profiles/… and agents/… path in this skill and in its references is relative to that directory, not to the repo you work in: run python3 ${CLAUDE_SKILL_DIR}/scripts/audit.py docs/features/<slug>/ from the root of the repo whose spec you are working on, and read ${CLAUDE_SKILL_DIR}/references/mode-audit.md.
Directory layout for a feature named <slug>:
docs/features/<slug>/
_facts.yml # single source of truth — the ONLY place shared data is authored
_log.md # append-only handoff log — who edited what, against which version
01-master-plan.md # stage 1 — `new`. the decision: is this worth building?
02-implementation.md # stage 2 — `implement`. the build, once the answer is yes
02e-tests-and-e2e.md # stage 2 — `implement`. how each phase is known to work, and the Definition of Done
03-stakeholder-requirements.md # stage 2 — `implement`.Docs 02, 02e and 03 are not written by new. They are ~75% of the set's prose and the
only part that must be rewritten whole every time the plan moves — and a plan gets
bounced two, three, four times before anyone commits to it. new writes the registry
and doc 01, which is everything you need to decide; implement writes the rest once
the decision is made. Which doc belongs to which stage is docs[].stage in the
registry, and audit reads it before running a single check.
(If the project keeps specs flat like docs/features/<slug>-01-...md, honor that — put _facts.yml as docs/features/<slug>/_facts.yml or <slug>-_facts.yml. Match the repo's existing convention; do not impose a new one.)
Modes
new → (bounce the plan with the user) → review → user confirms (status: reviewed)
→ implement → verify → ship. audit and sync run at any point; handoff
runs whenever the set changes hands.
Every mode starts by reading _log.md from disk (references/handoff.md) — audit.py --open first, for what is still open; the log itself where a finding points into it. It records which agent last touched the set, which file versions they read, and what they decided about the previous round's findings. It outranks your context window — if the two disagree, your context is stale and the files must be re-read at the versions the log names. Every mode that edits opens its entry BEFORE editing and completes it after — a stub naming the agent, the versions read, and what it is about to do; the findings, edits and dispositions filled in when the round ends. Not the other way round: a round that dies halfway then leaves a trace instead of silence. Real case: a delegated subagent wrote all four documents and hit a session limit before writing its entry — from outside it looked like it had produced nothing, and the next round spent its time reconstructing work that was already on disk. A round that finishes completes its own entry; a round that does not is exactly the one that needed the stub. Then read the stub back (tail -n 8 _log.md) before the first edit: a stub whose command failed in silence leaves exactly the silence it exists to prevent. Real case: a stub command died on unmatched ", its author read the next line of output instead, and a whole round ran with nothing on disk.
Each mode is one file, read before running it. The table says what the mode does and what it refuses; the file says how. Nothing in this table is enough to run a mode.
| mode | does | refuses / never | file |
new <slug> | python3 scripts/new.py docs/features/<slug> --title TEXT --agent NAME [--dry] first: resolves the profile (walk up, nearest wins), lists siblings, writes the minimal registry, _log.md with the R1 stub and doc 01's headings, runs audit; then you decide the siblings, fills _facts.yml with every claim carrying a basis:, runs the gap sweep, writes doc 01 only, scaffolds _log.md at step 2, runs audit. --with-build chains implement for a decision already made | never writes docs 02/02e/03; never invents a command, an owner or a value — asks in one batch (references/intake.md) | references/mode-new.md |
review <slug> | gap sweep: base + one layer per _profile.yml gap_sweep_layers:. Findings FUNCTIONAL / SECURITY, each with a failure scenario. Asks whether it is worth building at this scale, with the number | no scenario, no finding; a stack with no layer is a stated blind spot, not a pass | references/mode-review.md, references/parallel.md |
implement <slug> | writes 02-implementation.md, 02e-tests-and-e2e.md, 03-stakeholder-requirements.md; stub with audit.py --entry --read-line, close with --edits-line; covers every pending downstream coverage item; stamps regenerated_on:; runs audit | refuses unless review ran with every finding dispositioned, the user flipped status: reviewed, and every changes[] entry has a kind: | references/mode-implement.md |
audit <slug> | --open for items demanding action, each entry with an in: line naming the doc spans that cite it (--compact: one line per item), --index for registry line spans, --get KEY [KEY ...] for the exact text of single entries (defects.D2, acceptance.AC1) instead of reading by offset, --doc-index for each doc's sections with their line spans and the registry entries each cites (--cites KEY for the sections citing one entry), so a round reads sections and not whole docs, python3 scripts/audit.py docs/features/<slug>/, then the judgment pass over REQUIRES A HUMAN PASS and the candidates. Emits the matrix rows it changed + findings CONTRADICTION / DRIFT / POLISH. Repeated findings of one check and message print once with every member listed (--full prints each; counts, exit code and --json unchanged). --deep adds a cold reviewer. A set carrying old DRIFT: --write-baseline FILE once, then --baseline FILE lists only new findings and fails only on a new CONTRADICTION/DRIFT | never edits unless told "fix"; the script never executes evidence.cmd | references/mode-audit.md |
verify <slug> | reconciles the registry against a device run: confirmed → measured with n:/spread:/conditions:, refuted → dead; walks depends_on both ways; re-runs review if changes[] changed shape; a criterion that could not run records acceptance[].attempts[] on itself (facts.py add-attempt), and closes: ties it to the accepted risk it settles; stub with audit.py --entry --read-line, close with --edits-line | aborts before the run if a precondition is missing (aborted_no_conditions); G1 blocks shipped on an asserted root cause | references/mode-verify.md |
ship <slug> --tag <tag> | python3 scripts/ship.py docs/features/<slug>/ --tag <tag> [--on DATE] [--url URL]: runs G1 / check 14 / check 26 as if already shipped, then flips status:, writes tracking.shipped_in / shipped_on / release_url, appends the dates.revisions[] entry, prepends doc 01's changelog entry, and prints the **Stage:** and **Edits:** lines for the open log entry | refuses while any gate would fire, naming the entry; never touches defects[] / acceptance[] / changes[] / docs[].stage; never writes the log | references/mode-ship.md |
sync <slug> | python3 scripts/sync.py docs/features/<slug>/ [--apply]: diffs the old registry — --from-file PATH, --from REF, the _facts.synced.yml snapshot, or git HEAD, first that exists — against disk and replaces each changed value in the docs in scope — dry run by default, --apply writes; you resolve only what it reports (ambiguous values, decisions, legacy/derived docs); a registry kept out of git starts with --init-base once, when the docs match it; --decision <key> lists cited_in: sections; stub with audit.py --entry --read-line, close with --edits-line | moves data, never shape — a cancelled decision or a moved changes[] entry is implement's | references/mode-sync.md |
handoff <slug> [round] | appends the round entry: agent, Read: / Edits: with line count + blob per file (audit.py --read-line / --edits-line), Log read through:, one disposition per prior finding; when check 16 says rotate, open the rotation stub and run python3 scripts/rotate.py docs/features/<slug>/ [--dry] (moves the rounds, checks the bytes reassemble, prints the Archived: / Edits: / Stage: lines; --rotate-plan only shows the plan); --session prints session brief from --open + git status | a rejection without evidence; a reviewed flip inferred from conversation | references/mode-handoff.md |
view <slug> | python3 scripts/render.py docs/features/<slug>/ → one self-contained view.html | never edited, never a source | references/mode-view.md |
Rules that keep it honest
The full list is references/rules.md — every mode that writes is held to it, and it moved out of this file verbatim, not summarized. The ones that decide most rounds:
- Verbatim copy guarantees consistency with the registry, including any error IN it. Harden the input: every claim declares
basis:, measured data is run not copied,changesvsrelated_docsare disjoint, contracts live incontracts.*not prose. - Ask, never invent. Unknowns travel as
null,[MANUAL]orbasis: asserted+falsified_by:. An unmarked unknown is the defect. - The log outranks the context window. Read it first, re-read at the versions it names, open your entry before editing.
_facts.ymlis edited as text, never round-tripped through a YAML dumper. Exact string replacement through theEdittool, old text copied from aReadof those lines, never retyped;safe_loadto read. A vault-ingested registry may be a two-document stream:safe_load_all(), last document.- Registry is authoritative; the profile says how this repo finds out. A command belongs to the profile, its output to the registry.
- A clean audit does not mean the registry is true.
verifyis the gate; shipping with a cause still asserted is allowed once, in writing, with an expiry (defects[].accepted), and the criterion that would settle it says so (acceptance[].closes).audit.py --openlists what is still open before any mode starts. - Wrong entries are retracted or corrected, never deleted; an id is never recycled.
- Prose is written once, against a plan that stopped moving. Docs 02/02e/03 exist only after
reviewand the user's confirmation.
References
references/parallel.md— splitting a mode across subagents by tier (strong/mid/cheap), the runners (claude,agy,orca,inline), the_inbox/disk coordination, and the rules that keep one writer per file.agents/spec-*.md— the three read-only tier definitions to copy into.claude/agents/.references/mode-<name>.md— one per mode, the full procedure;references/rules.md— the rules every writing mode is held to.references/doc-pattern.md— the 4-doc pattern, section skeletons, naming, cross-ref rules.references/audit-protocol.md— the checks that need a human pass, the index of the ones the script settles, severity taxonomy, matrix format.references/audit-checks-script.md— the full text of every[script]check, read only when one of its findings needs explaining.references/gap-sweep.md— thereviewmode checklist: does this spec add functional/security gaps? Stack layers alongside it:gap-sweep-web-baas.md,gap-sweep-android-native.md,gap-sweep-mobile-tv.md,gap-sweep-payments-onprem.md,gap-sweep-web-3d-client.md.references/intake.md— the questions to ask before writing anything, batched, with what may never be guessed.references/handoff.md— the append-only_log.md, for sets passed between agents: entry format, dispositions, and why the log beats the context window.references/evidence.md— thebasis:/evidence:contract, theverifymode, and the gates that keep an asserted root cause from shipping.references/implementable.md— how to write doc 02 so a context-free executor can build it.references/render.md— theviewmode: what the HTML render reads, the invariants it holds, and the gates it surfaces.scripts/render.py— the renderer itself. Deterministic and standalone: no model writes the HTML, so the view cannot drift from the files it renders.scripts/audit.py— the mechanized half of the audit protocol. Shares its registry walk and basis gates withrender.pyby importing them, so the two cannot drift: a check implemented twice is the defect this skill exists to prevent.scripts/ship.py— the flip toshipped(references/mode-ship.md). Importsaudit.py's gates so the refusal and the audit's--as-status shippedpreview cannot disagree; edits the registry and doc 01 as text so comments survive; prints the log lines and never writes the log.scripts/facts.py— appends attempts to acceptance criteria (references/mode-verify.md,references/evidence.md). Importsaudit.pygates andship.pytext helpers; edits_facts.ymlas text so comments survive; validates against the schema, enforces append-only order, round-trip equality, and idempotency; prints the Edits line and never writes the log.scripts/sync.py— the data half ofsync(references/mode-sync.md). Imports the datum walk and word boundaries fromrender.pyand the stage gating fromaudit.py, so it replaces exactly what the provenance view and the audit call a datum; never guesses (ambiguous values are reported, not applied), never writes_log.mdorlegacy/deriveddocs, skips a doc that changed since the plan, writes atomically; prints the Edits line and never writes the log.scripts/new.py— the deterministic half ofnew(references/mode-new.md): profile walk, sibling list, minimal registry with only template keys,_log.mdR1 stub, doc 01 headings in the profile's language; runsauditon the result; never decides siblings or asks intake questions.scripts/rotate.py— executes the_log.mdrotation planned byaudit.py'srotate_plan_data(references/handoff.md): refuses without an open rotation stub, on an existing archive or a log changed since the plan; atomic writes; restores the log if the archive and the kept part do not reassemble the original byte for byte.scripts/triage.py— optional ranking over the candidates from checks 3, 4, 8 and 13, sorted intokeep/uncertain/suppressed. Importsaudit.pyfor the candidates themselves, so it can only reorder what the offline run already found; with no SDK or key it prints the same list, unranked.tests/— one fixture per mechanized check, each reproducing the real failure that motivated it, plus the false positives that must stay unreported.python3 tests/test_audit.py.python3 tests/test_ship.pycoversship.py: the gates refuse before any write and name the entry, the edits land where checks 28 and 40 read them with comments intact,--drywrites nothing.python3 tests/test_facts.pycoversfacts.py: flow and block append, comment preservation, idempotency,--dry,--status, and gate refusals.python3 tests/test_render.pycoversrender.py's own security boundary: a URL scheme allowlist on rendered links/images, and confinement on every registry path it reads content from.python3 tests/test_triage.pycoverstriage.py's offline half — the one that has to hold when nothing is installed: thatcollect()reproducesaudit.py's candidate list exactly, in both directions, so it can only reorder what the offline run found; that the fallback prints every candidate rather than filtering one; and that 0, 1 and 2 stay distinguishable for a caller. Ranking itself is not exercised — a test that needs a key is a test that does not run.python3 tests/test_sync.pycoverssync.pyon a temporary git repo: replacement, dry run writes nothing, legacy untouched, ambiguous values reported and not applied, a doc changed since the plan is not written,HEADequal to disk warns, an untracked registry exits 2.python3 tests/test_new.pycoversnew.pyon a temporary git repo;python3 tests/test_rotate.pycoversrotate.py: reassembly byte for byte, dry run, refusals, paths with spaces and$(…).templates/—_facts.yml.tpl,_log.md.tpl, and one.tplper doc.profiles/—_profile.yml.tpl(the contract) plus starter profiles per stack. Copy one into the repo as its_profile.yml; never fill one in place — a realapp_idor agent name written into a starter leaks into every other project using this skill.- The starters and the
gap-sweep-<layer>.mdfiles are independent and disposable. A repo needs only the ones matching its stacks; delete the rest, nothing else references them. Adding one for a new stack is ~20 lines (profile) and ~40 (layer), and is the normal way this skill grows.
- The starters and the
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.

