Extract a spec from what was actually agreed
SkillFiles & storageTurn an unwritten agreement into a checkable spec — pull the requirements out of this conversation, a ticket, a pasted thread, or a design discussion, and write them to the project's spec file as numbered, falsifiable claims. Use before starting a feature, when the user says "write this up", "turn this into a spec", "make a design doc", "what did we agree", "capture the requirements", or "create design.md"; when a review skill halts because no spec exists; and at the point a conversation has produced enough decisions that the next session would lose them. This produces the contract that `design-check` and `verify-feature` measure against — it does not verify anything itself.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Extract a spec from what was actually agreed skill
What this skill tells your AI
The instructions your AI receives, as published by arcasilesgroup/ai-engineering in skills/ai-verify/tiers/1-standalone/spec-extract/SKILL.md and read by ahel’s review.
design-check halts without a spec. verify-feature falls back to reconstructing one
from conversation memory, which is the weakest contract it supports. Both problems are the
same problem: the agreement exists, but only in a chat log that nobody will re-read and
that the next session cannot see.
Your job is to move it out of the conversation and into a file, without inventing anything. The single failure mode of this skill is a confident spec containing requirements nobody ever asked for — that is worse than no spec, because every downstream verification then measures against fiction and reports it as fact.
1. Do not read the implementation first
If code already exists for this work, do not read it before you have drafted the
requirement list. You will reconstruct requirements that the code happens to satisfy,
and produce a spec that is guaranteed to pass its own check. This is the same ordering
rule as verify-feature §1 and it matters more here, because the artifact persists.
There is one legitimate exception, and it must be labeled. When the goal is explicitly to document something already built — a legacy subsystem, an inherited codebase — you are writing a descriptive spec, not a prescriptive one. Say so in the header, because a descriptive spec cannot detect drift that already happened; it canonizes it.
2. Gather sources in order of authority
- The user's own messages in this session — the most common source, and the one that disappears when the session ends. Read the whole session, not the opening ask.
- A ticket or issue —
gh issue view,glab issue view, a linked doc, a pasted thread. Quote it rather than paraphrase where the wording is load-bearing. - Existing partial docs — a half-written
design.md, an ADR, a README section, a TODO list. These are prior agreements; do not silently overwrite them. - Project invariants that constrain this work —
CLAUDE.md,AGENTS.md,CONTRIBUTING.md, the schema, the auth convention. These are requirements even though nobody restated them for this feature.
Requirements do not arrive as requirements. Scan specifically for the three shapes people never label:
- Corrections — "no, moderators too". A correction supersedes the original. Record the latest version and note that it changed, so the earlier form does not resurface in someone's memory as an unmet requirement.
- Constraints — "don't touch the webhook", "has to work on the free tier". These become non-goals or explicit boundaries, and they are the requirements most often violated by accident.
- Offhand asides — a number mentioned once, an edge case named in passing, a name for something. If it was said once and never contradicted, it is in.
3. Write each requirement as a falsifiable claim with a stable ID
The output has to be checkable by an agent that will never see this conversation, so every requirement is a statement that can be shown true or false by pointing at code.
- Not "admins can manage products" → "an
owneroradmincan create, edit, publish and delete a product from/admin/store, and each write re-checks role server-side." - Not "it should be fast" → get the number, or record it under Open questions with the reason it is unspecified. Never let a vague requirement into the numbered list; it will be scored as met by whatever exists.
Give every requirement a stable ID (R1, R2, …). This is not cosmetic.
design-check produces a requirement-by-requirement traceability table, and stable IDs are
what let two reviews weeks apart be compared, and what lets a fix reference the thing it
closes. IDs are append-only: when a requirement is dropped, mark it WITHDRAWN in place
rather than renumbering the ones after it.
Cover the categories the work touches — the ones people forget are where drift hides:
- Behavior, including empty, loading, error, offline, unauthenticated, permission-denied and partial-failure states
- Data model and migrations — new fields, backfills, compatibility with what is currently deployed
- Access control — who can reach it, and where it is enforced server-side
- Side effects — payments, emails, webhooks, jobs, cache invalidation, analytics
- Interface conformance — which design surface or style guide governs the UI
- Non-goals — what this deliberately does not do
4. Mark provenance on every line, and never launder an assumption
Each requirement carries one of three provenance tags. This is the core of the skill.
| Tag | Meaning |
|---|---|
stated | The user or the ticket said this, more or less in these words |
implied | Follows necessarily from something stated — the empty state of a list they asked for, the migration a new column needs |
assumed | You supplied it. Nobody said it. It is probably right and it is still yours |
implied is a real category and worth keeping — a spec that omits the error state because
nobody spoke it aloud is a spec that will pass while the feature breaks. But the tag makes
the reach visible.
assumed items get surfaced explicitly: list them back to the user before you write the
file and ask them to confirm, correct or delete each one. This is the round trip that
makes the whole artifact trustworthy. An assumption that survives review becomes stated;
one the user rejects is deleted, not softened.
If you find yourself unable to tag something, that is the tell that you are writing a requirement out of your own sense of how the feature should work. Move it to Open questions.
5. Write it where the project already keeps specs
Find the convention before inventing one: a spec directory (docs/features/,
docs/specs/, docs/rfcs/, adr/), an existing design.md or DESIGN.md, or a location
named in README.md, CONTRIBUTING.md, CLAUDE.md or AGENTS.md. Match the existing
format and naming — a document that looks like its neighbours gets read.
If the project has no convention at all, default to design.md at the repo root, because
that is the first path design-check and full-review look for, and say that you chose
it. If the project keeps no docs and the user does not want one, output the spec into the
conversation instead and stop — do not add an orphan file to a repo with nowhere for it to
live. A stale contract is worse than none: it makes the next verification confidently
wrong.
Never overwrite an existing spec. Read it, merge, and mark what changed.
6. Output shape
# <Feature> — design
**Status:** draft | agreed | shipped
**Type:** prescriptive (written before the build) | descriptive (documents existing behavior)
**Sources:** <session <date> · issue #NN · docs/rfcs/0004.md>
**Last updated:** <date>
## Goal
<two or three sentences: the user-visible outcome and who it is for>
## Requirements
| ID | Requirement | Provenance | Notes |
|---|---|---|---|
| R1 | An `owner`/`admin` can delete a product from `/admin/store`; role re-checked server-side | stated | |
| R2 | Deleting a product invalidates the storefront listing cache | implied | R1 has no effect for readers otherwise |
| R3 | Deletion is soft — row retained with `deleted_at` | assumed | **confirm:** hard delete may be intended |
| R4 | ~~Bulk delete~~ | stated | WITHDRAWN 2026-07-14 — descoped mid-session |
## Non-goals
- No cart. Explicitly out of scope for this feature.
- Physical products are not supported.
## Constraints
- Do not modify the Stripe webhook handler.
## Open questions
- What is the acceptable latency for the listing page? "Fast" was the only bar given.
Requirements go in one flat numbered table, not nested by theme. Nesting reads better and verifies worse — a traceability table needs one row per checkable claim.
7. Hand off
When the file is written, say what it unlocks, in one line each:
design-checknow has something to check against, andfull-reviewwill stop skipping that lane.verify-featurewill prefer this file over conversation memory — including over your memory, which is the point.
Then offer, once, to run one of them. Do not run a review automatically: the spec is a proposal until the user has read it, and verifying against an unreviewed spec produces confident results about the wrong contract.
Keeping it alive
A spec is living until the feature ships. Afterwards, the durable facts — the permission model, the schema, the invariant everyone needs to know — are worth graduating to the places people actually read: the agent-rules file, a gotchas doc, the schema reference. Follow the project's own lifecycle for that if it has one. Do not leave the only copy of a load-bearing invariant in a spec nobody opens again.
Signals
- GitHub stars
- 55
- Forks
- 3
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
spec-extract- Source
- github.com/arcasilesgroup/ai-engineering