spec-eval 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ben Jones
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,293 @@
1
+ Metadata-Version: 2.4
2
+ Name: spec-eval
3
+ Version: 0.2.0
4
+ Summary: A trust-eval for your specs: coverage, drift, and sufficiency of markdown specs against code.
5
+ Author: Ben Jones
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/benjaminjones/spec-eval
8
+ Project-URL: Repository, https://github.com/benjaminjones/spec-eval
9
+ Project-URL: Issues, https://github.com/benjaminjones/spec-eval/issues
10
+ Keywords: spec-driven-development,documentation-drift,docs-as-code,living-documentation,llm-as-judge,code-documentation,backfill-documentation
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Software Development :: Documentation
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: anthropic>=0.40
21
+ Requires-Dist: openai>=1.50
22
+ Requires-Dist: google-genai>=1.0
23
+ Requires-Dist: PyYAML>=6.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=7; extra == "dev"
26
+ Requires-Dist: hypothesis>=6; extra == "dev"
27
+ Requires-Dist: ruff>=0.4; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # spec-eval — Build fast with AI. Validate with specs.
31
+
32
+ **Your code changes fast. Your docs fall behind. spec-eval keeps them honest.**
33
+
34
+ *The trust layer for [spec-driven development](https://en.wikipedia.org/wiki/Spec-driven_development) — iterate fast, keep the spec and code in agreement.*
35
+
36
+ *A trust-eval for your specs — coverage, drift, and sufficiency, measured against the code.*
37
+
38
+ [Get started](#try-it) · [Tutorial](GETTING-STARTED.md) · [No API key?](#run-via-prompt-chat-no-setup) · [Second opinion](#higher-stakes-get-a-second-opinion) · [FAQ](FAQ.md)
39
+
40
+ A **spec** is short for **specification** — a plain-English description of what your code should do. **spec-eval**
41
+ keeps one beside your code — per file, or per folder — and checks the two still agree, so the spec stays worth
42
+ trusting. How far you lean on it is up to you. **No specs yet? spec-eval writes them for you.**
43
+
44
+ ## Table of contents
45
+
46
+ - [The problem](#the-problem)
47
+ - [What it checks](#what-it-checks)
48
+ - [What it creates](#what-it-creates)
49
+ - [Try it](#try-it)
50
+ - [Run via prompt chat (no setup)](#run-via-prompt-chat-no-setup)
51
+ - [Run in the terminal, no key (Claude subscription)](#run-in-the-terminal-no-key-claude-subscription)
52
+ - [Run in the terminal with an API key (for CI)](#run-in-the-terminal-with-an-api-key-for-ci)
53
+ - [How the scores are made](#how-the-scores-are-made)
54
+ - [Reading the scores](#reading-the-scores)
55
+ - [Higher stakes? Get a second opinion](#higher-stakes-get-a-second-opinion)
56
+ - [Proof it works](#proof-it-works)
57
+ - [More](#more)
58
+ - [FAQ](#faq)
59
+ - [Feedback](#feedback)
60
+ - [Acknowledgements](#acknowledgements)
61
+
62
+ ## The problem
63
+
64
+ Specs go stale the moment code moves on — and one stale spec is enough to stop a reader trusting all of them.
65
+ AI coding agents make code move faster than any hand-maintained doc can follow.
66
+
67
+ **spec-eval** treats specs like code: **run a check — via a chat prompt, an ordinary command, or a CI step — and
68
+ the spec is measured against the source.** A spec you can check is a spec you can trust.
69
+
70
+ ## What it checks
71
+
72
+ Three simple questions:
73
+
74
+ | Check | The question it answers | How |
75
+ |---|---|---|
76
+ | **coverage** | Does this code have a spec at all? | Just counts files. Free — no AI, no key. |
77
+ | **drift** | Does the spec say something the code doesn't do? | An AI reads each spec and its code and lists the clashes. |
78
+ | **sufficiency** | How completely does the spec capture the code's behavior? | An AI lists what the spec misses and scores it 0–1 — an indicator, not a guarantee. |
79
+
80
+ Your **code is the source of truth** — the spec is what gets graded against it.
81
+
82
+ ## What it creates
83
+
84
+ Everything it writes is plain markdown, right next to your code:
85
+
86
+ ```text
87
+ your code specs beside it spec-reports/
88
+ ┌────────────┐ ┌────────────┐ ┌────────────────┐
89
+ │ parser.py │ generate │ parser.md │ coverage │ coverage.md │
90
+ │ api.py │ ──────────► │ api.md │ audit │ report.md │
91
+ │ … │ │ … │ ──────────► │ sufficiency.md │
92
+ └────────────┘ └────────────┘ sufficiency └───────┬────────┘
93
+
94
+
95
+ SPEC-HEALTH.md
96
+ (one-page scorecard)
97
+ ```
98
+
99
+ ## Try it
100
+
101
+ Prefer a guided walkthrough? **[Getting-started tutorial →](GETTING-STARTED.md)**
102
+
103
+ **The commands** — in the order you'll typically use them:
104
+
105
+ - **coverage** — which files have no spec yet? *(free — no AI)*
106
+ - **generate** — writes a plain-English spec beside each file that has none *(uses AI)*
107
+ - **sufficiency** — how completely does each spec capture the code? Scored 0–1 *(uses AI)*
108
+ - **audit** — the drift check: does any spec clash with the code? Run it at every milestone *(uses AI)*
109
+
110
+ None of them change your files — reports go to `spec-reports/`. The exception is `generate`, which writes new
111
+ specs beside your code: review them and commit the keepers like code.
112
+
113
+ The `(uses AI)` commands (`generate`, `sufficiency`, `audit`) need an AI behind them — `coverage` never does.
114
+ Three ways to run them, least setup first:
115
+
116
+ ### Run via prompt chat (no setup)
117
+
118
+ Ask the coding agent you already have (Claude Code, Copilot, Cursor, …) — nothing to install, no key, answers
119
+ land in the chat:
120
+ ```text
121
+ Read path/to/spec-eval/skills/spec-check/SKILL.md and follow it —
122
+ first check coverage, then check my specs against my code.
123
+ ```
124
+ The path is wherever you cloned this repo — no clone? Give your agent [the file's link](skills/spec-check/SKILL.md).
125
+
126
+ Optionally save reports — add:
127
+ ```text
128
+ and save the results to spec-reports/
129
+ ```
130
+ The agent writes them itself (its own scores; the terminal adds the exact coverage % and a run history).
131
+
132
+ **Make it a standing command** *(optional, one-time)* — copy the [`skills/`](skills/) into your agent's skills
133
+ folder (Claude Code: `.claude/skills/`). Then the prompt is the command:
134
+ ```bash
135
+ mkdir -p .claude/skills && cp -r path/to/spec-eval/skills/* .claude/skills/
136
+ ```
137
+ ```text
138
+ Which files have no spec yet? # coverage
139
+ Write a spec for src/parser.py # generate
140
+ Check my specs against my code # sufficiency + audit
141
+ ```
142
+
143
+ ### Run in the terminal, no key (Claude subscription)
144
+
145
+ Install once, then add `--model claude-code` to any `(uses AI)` command — **spec-eval** routes through the
146
+ `claude` CLI you're already logged into (no key; your `ANTHROPIC_API_KEY` is hidden from the call, so it can't
147
+ accidentally bill the paid API). The same four commands, in the same order as the list above:
148
+ ```bash
149
+ pip install spec-eval # or, from a clone: pip install -e .
150
+ spec-eval coverage ./your-project # free — no AI, no key
151
+ spec-eval generate ./your-project --model claude-code
152
+ spec-eval sufficiency ./your-project --model claude-code
153
+ spec-eval audit ./your-project --model claude-code
154
+ ```
155
+ Every terminal run writes its reports to `spec-reports/` (plus a `runs.jsonl` history line).
156
+
157
+ ### Run in the terminal with an API key (for CI)
158
+
159
+ Export a key and run any command above **without** `--model claude-code` — an API key is the default. This is
160
+ the option for CI, the checks that run automatically on every push (store the key as a repo secret):
161
+ ```bash
162
+ export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY / GOOGLE_API_KEY
163
+ ```
164
+
165
+ > [!NOTE]
166
+ > A typical first run is `coverage → generate → sufficiency`, then at every milestone after: `audit` — plus
167
+ > `sufficiency` when you've added behavior. The [tutorial](GETTING-STARTED.md) has step-by-step guides for
168
+ > starting with no specs and for existing docs.
169
+
170
+ > [!TIP]
171
+ > **Version control is also your preview.** The three checks never modify your project; `generate` adds
172
+ > ordinary new files — review them with `git diff`, edit what's off, and drop any you don't want with
173
+ > `git checkout -- <file>`. (A full `generate --overwrite` rewrites everything, so save it for first setup.)
174
+
175
+ A few things worth knowing:
176
+
177
+ - **No config needed** — by default each spec pairs with the code file of the same name beside it (`parser.md` ↔ `parser.py`).
178
+ Prefer one spec per folder? `--layout per-dir` ([FAQ](FAQ.md#can-i-use-one-spec-per-folder-instead-of-one-per-file)).
179
+ - **Any language, three providers** — swap the model with `--model openai:…`, `google:…`, or `claude-code`
180
+ (Anthropic is the default); code is read as plain text. Want another provider? [Open an issue](#feedback).
181
+ - **Your other docs are safe** — by default only a `.md` next to code with the same name counts as a spec, so your
182
+ READMEs are left alone. (Folder specs and overview indexes only appear if you opt in with `--layout` / `--overview`.)
183
+ - **What's shared** — to grade a spec, its code and text go to your AI provider. That's it. (`coverage` sends nothing — it runs fully on your machine.)
184
+
185
+ **Keep it honest on every commit** — add one line to a git hook (a script git runs before each commit) so new
186
+ code always needs a spec; copy-paste setup in [the tutorial](GETTING-STARTED.md#make-it-routine):
187
+ ```bash
188
+ spec-eval coverage . --min 90 # fails the commit if coverage drops below 90% (free — no AI)
189
+ ```
190
+
191
+ ## How the scores are made
192
+
193
+ Three scores, three simple ideas:
194
+
195
+ - **coverage** = spec files you *have* ÷ spec files you *need* → a percent. Just counting, **no AI**.
196
+ *(9 of 10 code files have a spec → 90%.)*
197
+ - **drift** = the number of spots where the spec and the code flat-out disagree. **`0` = they match.**
198
+ - **sufficiency** = how much of what the code does is actually written in the spec, from **`0` to `1`**.
199
+ *(`1.0` = it's all there; `0.1` = almost none of it is.)*
200
+
201
+ Those three are **per spec**. The repo's one **sufficiency** score is just their **average** — each spec's
202
+ `0`–`1`, added up and divided by how many specs were scored. *(coverage is already one repo-wide `%`; drift is
203
+ the total count across specs.)*
204
+
205
+ `coverage` is pure counting. The other two need an **AI reader**: it reads each spec next to its code and grades
206
+ the pair against a fixed rubric — one model call per pair. Two things follow from that:
207
+
208
+ > [!NOTE]
209
+ > AI scores **wobble**: the same spec might get 0.78 one run and 0.72 the next, like two teachers grading the same
210
+ > essay. Watch the **trend**, not the decimal — a jump like 0.72 → 0.85 is a real improvement.
211
+
212
+ > [!IMPORTANT]
213
+ > AI calls **spend tokens** — through your API key, your Claude subscription with `--model claude-code`, or
214
+ > your coding agent's own usage if you asked in chat. Every CLI run prints its exact call and token counts.
215
+
216
+ **Want the exact rules behind each score?** spec-eval specs its own scoring — read
217
+ [`spec_eval/coverage.md`](spec_eval/coverage.md) (how coverage counts),
218
+ [`spec_eval/rubric.md`](spec_eval/rubric.md) (the drift rules), and
219
+ [`spec_eval/sufficiency.md`](spec_eval/sufficiency.md) (how the 0–1 score is decided).
220
+
221
+ ## Reading the scores
222
+
223
+ Each run writes a short report to `spec-reports/` (a `.md` you read, a `.json` for tools):
224
+
225
+ - **coverage** — the % of your code that has a spec, and which files don't. *(live example: [coverage.md](spec-reports/coverage.md))*
226
+ - **drift** — each place a spec and the code disagree, with a suggested fix. `0` is clean. *(live example: [report.md](spec-reports/report.md))*
227
+ - **sufficiency** — a `0`–`1` score per spec (worst first), listing what's missing with a searchable code pointer
228
+ (`file.py (function)`). `1.0` = the grader found nothing missing — guidance, not a guarantee. *(live example: [sufficiency.md](spec-reports/sufficiency.md))*
229
+
230
+ The three examples are **spec-eval grading itself**, rolled up in [SPEC-HEALTH.md](SPEC-HEALTH.md).
231
+
232
+ Every command also appends a line to `runs.jsonl` — timestamp, git commit, scores — so you can track change over
233
+ time.
234
+
235
+ ## Higher stakes? Get a second opinion
236
+
237
+ `drift` and `sufficiency` are **AI judgments** — one model can miss something or be too generous. For a spec that needs extra attention — a critical path, complex design, or compliance code — run the
238
+ **same check with two different AI vendors** and compare. Give each run its own
239
+ `--out` folder (otherwise the second run overwrites the first report):
240
+
241
+ ```bash
242
+ spec-eval audit ./your-project --model anthropic:claude-opus-4-8 --out spec-reports/claude
243
+ spec-eval audit ./your-project --model google:gemini-3.5-flash --out spec-reports/gemini
244
+
245
+ diff spec-reports/claude/report.md spec-reports/gemini/report.md # or read them side by side
246
+ ```
247
+
248
+ How to read two reports:
249
+
250
+ - **Both flag it** → almost certainly real. Fix these first.
251
+ - **Only one flags it** → a judgment call. Read the quoted evidence and decide.
252
+ - **Sufficiency scores differ a little** → normal wobble. Compare the **gaps lists**, not the decimals — the same
253
+ missing behavior named by both graders is the signal.
254
+
255
+ Each vendor reads its own key from the environment — `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY` —
256
+ so put both keys in one `.env` and each run picks up the one it needs. (Want one fewer key? Swap either side for
257
+ `--model claude-code`, which uses your Claude Code login instead.)
258
+
259
+ ## Proof it works
260
+
261
+ - **spec-eval specs itself** — every module in [`spec_eval/`](spec_eval/) has its own spec:
262
+ **coverage 100% · drift 0 · sufficiency ≈0.86** ([receipt](SPEC-HEALTH.md) — the exact, dated score).
263
+
264
+ ## More
265
+
266
+ - **Works with [spec-driven development](https://en.wikipedia.org/wiki/Spec-driven_development).** SDD's goal is a spec you can *trust*, and **spec-eval** is that trust layer.
267
+ Use it three ways: **grade the specs you already have**, **generate specs** for code that has none, or **check as
268
+ you write** (with the skills). Spec-first, code-first, or in between — it meets you where you are.
269
+ - **Grow the spec and the code together.** The best version of "in between": draft a little spec, write a little
270
+ code, check they still agree — repeat. The two can even move in parallel (you shape the spec while your coding
271
+ agent writes the code; the check is where they meet), so the spec is *born accurate* instead of written up
272
+ afterward.
273
+ - **Just want to vibe code?** Fine — build first, check later, automatically: a pre-commit gate and a GitHub
274
+ Action can run the checks for you — see [Make it routine](GETTING-STARTED.md#make-it-routine).
275
+ - **Higher-stakes spec?** Run it past two vendors and compare — see [Higher stakes? Get a second opinion](#higher-stakes-get-a-second-opinion) above.
276
+
277
+ ## FAQ
278
+
279
+ Common questions — from *"which command do I run first?"* through costs, layouts, and score accuracy — live in
280
+ **[FAQ.md](FAQ.md)**.
281
+
282
+ ## Feedback
283
+
284
+ Found a bug, a bad score, or a spec that misses the point? [Open an issue](https://github.com/benjaminjones/spec-eval/issues) — a report snippet and the command you ran is plenty.
285
+
286
+ ## Acknowledgements
287
+
288
+ Built on the Anthropic, OpenAI, and Google SDKs (MIT / Apache-2.0) + PyYAML.
289
+
290
+ ---
291
+ *Terms you may be searching for: software specification · documentation drift · living documentation · docs as code · backfill
292
+ documentation · spec-driven development (SDD) · agentic development · AI-assisted coding · vibe coding · vibe engineering ·
293
+ AI code documentation · LLM-as-judge / trust eval. MIT licensed.*
@@ -0,0 +1,264 @@
1
+ # spec-eval — Build fast with AI. Validate with specs.
2
+
3
+ **Your code changes fast. Your docs fall behind. spec-eval keeps them honest.**
4
+
5
+ *The trust layer for [spec-driven development](https://en.wikipedia.org/wiki/Spec-driven_development) — iterate fast, keep the spec and code in agreement.*
6
+
7
+ *A trust-eval for your specs — coverage, drift, and sufficiency, measured against the code.*
8
+
9
+ [Get started](#try-it) · [Tutorial](GETTING-STARTED.md) · [No API key?](#run-via-prompt-chat-no-setup) · [Second opinion](#higher-stakes-get-a-second-opinion) · [FAQ](FAQ.md)
10
+
11
+ A **spec** is short for **specification** — a plain-English description of what your code should do. **spec-eval**
12
+ keeps one beside your code — per file, or per folder — and checks the two still agree, so the spec stays worth
13
+ trusting. How far you lean on it is up to you. **No specs yet? spec-eval writes them for you.**
14
+
15
+ ## Table of contents
16
+
17
+ - [The problem](#the-problem)
18
+ - [What it checks](#what-it-checks)
19
+ - [What it creates](#what-it-creates)
20
+ - [Try it](#try-it)
21
+ - [Run via prompt chat (no setup)](#run-via-prompt-chat-no-setup)
22
+ - [Run in the terminal, no key (Claude subscription)](#run-in-the-terminal-no-key-claude-subscription)
23
+ - [Run in the terminal with an API key (for CI)](#run-in-the-terminal-with-an-api-key-for-ci)
24
+ - [How the scores are made](#how-the-scores-are-made)
25
+ - [Reading the scores](#reading-the-scores)
26
+ - [Higher stakes? Get a second opinion](#higher-stakes-get-a-second-opinion)
27
+ - [Proof it works](#proof-it-works)
28
+ - [More](#more)
29
+ - [FAQ](#faq)
30
+ - [Feedback](#feedback)
31
+ - [Acknowledgements](#acknowledgements)
32
+
33
+ ## The problem
34
+
35
+ Specs go stale the moment code moves on — and one stale spec is enough to stop a reader trusting all of them.
36
+ AI coding agents make code move faster than any hand-maintained doc can follow.
37
+
38
+ **spec-eval** treats specs like code: **run a check — via a chat prompt, an ordinary command, or a CI step — and
39
+ the spec is measured against the source.** A spec you can check is a spec you can trust.
40
+
41
+ ## What it checks
42
+
43
+ Three simple questions:
44
+
45
+ | Check | The question it answers | How |
46
+ |---|---|---|
47
+ | **coverage** | Does this code have a spec at all? | Just counts files. Free — no AI, no key. |
48
+ | **drift** | Does the spec say something the code doesn't do? | An AI reads each spec and its code and lists the clashes. |
49
+ | **sufficiency** | How completely does the spec capture the code's behavior? | An AI lists what the spec misses and scores it 0–1 — an indicator, not a guarantee. |
50
+
51
+ Your **code is the source of truth** — the spec is what gets graded against it.
52
+
53
+ ## What it creates
54
+
55
+ Everything it writes is plain markdown, right next to your code:
56
+
57
+ ```text
58
+ your code specs beside it spec-reports/
59
+ ┌────────────┐ ┌────────────┐ ┌────────────────┐
60
+ │ parser.py │ generate │ parser.md │ coverage │ coverage.md │
61
+ │ api.py │ ──────────► │ api.md │ audit │ report.md │
62
+ │ … │ │ … │ ──────────► │ sufficiency.md │
63
+ └────────────┘ └────────────┘ sufficiency └───────┬────────┘
64
+
65
+
66
+ SPEC-HEALTH.md
67
+ (one-page scorecard)
68
+ ```
69
+
70
+ ## Try it
71
+
72
+ Prefer a guided walkthrough? **[Getting-started tutorial →](GETTING-STARTED.md)**
73
+
74
+ **The commands** — in the order you'll typically use them:
75
+
76
+ - **coverage** — which files have no spec yet? *(free — no AI)*
77
+ - **generate** — writes a plain-English spec beside each file that has none *(uses AI)*
78
+ - **sufficiency** — how completely does each spec capture the code? Scored 0–1 *(uses AI)*
79
+ - **audit** — the drift check: does any spec clash with the code? Run it at every milestone *(uses AI)*
80
+
81
+ None of them change your files — reports go to `spec-reports/`. The exception is `generate`, which writes new
82
+ specs beside your code: review them and commit the keepers like code.
83
+
84
+ The `(uses AI)` commands (`generate`, `sufficiency`, `audit`) need an AI behind them — `coverage` never does.
85
+ Three ways to run them, least setup first:
86
+
87
+ ### Run via prompt chat (no setup)
88
+
89
+ Ask the coding agent you already have (Claude Code, Copilot, Cursor, …) — nothing to install, no key, answers
90
+ land in the chat:
91
+ ```text
92
+ Read path/to/spec-eval/skills/spec-check/SKILL.md and follow it —
93
+ first check coverage, then check my specs against my code.
94
+ ```
95
+ The path is wherever you cloned this repo — no clone? Give your agent [the file's link](skills/spec-check/SKILL.md).
96
+
97
+ Optionally save reports — add:
98
+ ```text
99
+ and save the results to spec-reports/
100
+ ```
101
+ The agent writes them itself (its own scores; the terminal adds the exact coverage % and a run history).
102
+
103
+ **Make it a standing command** *(optional, one-time)* — copy the [`skills/`](skills/) into your agent's skills
104
+ folder (Claude Code: `.claude/skills/`). Then the prompt is the command:
105
+ ```bash
106
+ mkdir -p .claude/skills && cp -r path/to/spec-eval/skills/* .claude/skills/
107
+ ```
108
+ ```text
109
+ Which files have no spec yet? # coverage
110
+ Write a spec for src/parser.py # generate
111
+ Check my specs against my code # sufficiency + audit
112
+ ```
113
+
114
+ ### Run in the terminal, no key (Claude subscription)
115
+
116
+ Install once, then add `--model claude-code` to any `(uses AI)` command — **spec-eval** routes through the
117
+ `claude` CLI you're already logged into (no key; your `ANTHROPIC_API_KEY` is hidden from the call, so it can't
118
+ accidentally bill the paid API). The same four commands, in the same order as the list above:
119
+ ```bash
120
+ pip install spec-eval # or, from a clone: pip install -e .
121
+ spec-eval coverage ./your-project # free — no AI, no key
122
+ spec-eval generate ./your-project --model claude-code
123
+ spec-eval sufficiency ./your-project --model claude-code
124
+ spec-eval audit ./your-project --model claude-code
125
+ ```
126
+ Every terminal run writes its reports to `spec-reports/` (plus a `runs.jsonl` history line).
127
+
128
+ ### Run in the terminal with an API key (for CI)
129
+
130
+ Export a key and run any command above **without** `--model claude-code` — an API key is the default. This is
131
+ the option for CI, the checks that run automatically on every push (store the key as a repo secret):
132
+ ```bash
133
+ export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY / GOOGLE_API_KEY
134
+ ```
135
+
136
+ > [!NOTE]
137
+ > A typical first run is `coverage → generate → sufficiency`, then at every milestone after: `audit` — plus
138
+ > `sufficiency` when you've added behavior. The [tutorial](GETTING-STARTED.md) has step-by-step guides for
139
+ > starting with no specs and for existing docs.
140
+
141
+ > [!TIP]
142
+ > **Version control is also your preview.** The three checks never modify your project; `generate` adds
143
+ > ordinary new files — review them with `git diff`, edit what's off, and drop any you don't want with
144
+ > `git checkout -- <file>`. (A full `generate --overwrite` rewrites everything, so save it for first setup.)
145
+
146
+ A few things worth knowing:
147
+
148
+ - **No config needed** — by default each spec pairs with the code file of the same name beside it (`parser.md` ↔ `parser.py`).
149
+ Prefer one spec per folder? `--layout per-dir` ([FAQ](FAQ.md#can-i-use-one-spec-per-folder-instead-of-one-per-file)).
150
+ - **Any language, three providers** — swap the model with `--model openai:…`, `google:…`, or `claude-code`
151
+ (Anthropic is the default); code is read as plain text. Want another provider? [Open an issue](#feedback).
152
+ - **Your other docs are safe** — by default only a `.md` next to code with the same name counts as a spec, so your
153
+ READMEs are left alone. (Folder specs and overview indexes only appear if you opt in with `--layout` / `--overview`.)
154
+ - **What's shared** — to grade a spec, its code and text go to your AI provider. That's it. (`coverage` sends nothing — it runs fully on your machine.)
155
+
156
+ **Keep it honest on every commit** — add one line to a git hook (a script git runs before each commit) so new
157
+ code always needs a spec; copy-paste setup in [the tutorial](GETTING-STARTED.md#make-it-routine):
158
+ ```bash
159
+ spec-eval coverage . --min 90 # fails the commit if coverage drops below 90% (free — no AI)
160
+ ```
161
+
162
+ ## How the scores are made
163
+
164
+ Three scores, three simple ideas:
165
+
166
+ - **coverage** = spec files you *have* ÷ spec files you *need* → a percent. Just counting, **no AI**.
167
+ *(9 of 10 code files have a spec → 90%.)*
168
+ - **drift** = the number of spots where the spec and the code flat-out disagree. **`0` = they match.**
169
+ - **sufficiency** = how much of what the code does is actually written in the spec, from **`0` to `1`**.
170
+ *(`1.0` = it's all there; `0.1` = almost none of it is.)*
171
+
172
+ Those three are **per spec**. The repo's one **sufficiency** score is just their **average** — each spec's
173
+ `0`–`1`, added up and divided by how many specs were scored. *(coverage is already one repo-wide `%`; drift is
174
+ the total count across specs.)*
175
+
176
+ `coverage` is pure counting. The other two need an **AI reader**: it reads each spec next to its code and grades
177
+ the pair against a fixed rubric — one model call per pair. Two things follow from that:
178
+
179
+ > [!NOTE]
180
+ > AI scores **wobble**: the same spec might get 0.78 one run and 0.72 the next, like two teachers grading the same
181
+ > essay. Watch the **trend**, not the decimal — a jump like 0.72 → 0.85 is a real improvement.
182
+
183
+ > [!IMPORTANT]
184
+ > AI calls **spend tokens** — through your API key, your Claude subscription with `--model claude-code`, or
185
+ > your coding agent's own usage if you asked in chat. Every CLI run prints its exact call and token counts.
186
+
187
+ **Want the exact rules behind each score?** spec-eval specs its own scoring — read
188
+ [`spec_eval/coverage.md`](spec_eval/coverage.md) (how coverage counts),
189
+ [`spec_eval/rubric.md`](spec_eval/rubric.md) (the drift rules), and
190
+ [`spec_eval/sufficiency.md`](spec_eval/sufficiency.md) (how the 0–1 score is decided).
191
+
192
+ ## Reading the scores
193
+
194
+ Each run writes a short report to `spec-reports/` (a `.md` you read, a `.json` for tools):
195
+
196
+ - **coverage** — the % of your code that has a spec, and which files don't. *(live example: [coverage.md](spec-reports/coverage.md))*
197
+ - **drift** — each place a spec and the code disagree, with a suggested fix. `0` is clean. *(live example: [report.md](spec-reports/report.md))*
198
+ - **sufficiency** — a `0`–`1` score per spec (worst first), listing what's missing with a searchable code pointer
199
+ (`file.py (function)`). `1.0` = the grader found nothing missing — guidance, not a guarantee. *(live example: [sufficiency.md](spec-reports/sufficiency.md))*
200
+
201
+ The three examples are **spec-eval grading itself**, rolled up in [SPEC-HEALTH.md](SPEC-HEALTH.md).
202
+
203
+ Every command also appends a line to `runs.jsonl` — timestamp, git commit, scores — so you can track change over
204
+ time.
205
+
206
+ ## Higher stakes? Get a second opinion
207
+
208
+ `drift` and `sufficiency` are **AI judgments** — one model can miss something or be too generous. For a spec that needs extra attention — a critical path, complex design, or compliance code — run the
209
+ **same check with two different AI vendors** and compare. Give each run its own
210
+ `--out` folder (otherwise the second run overwrites the first report):
211
+
212
+ ```bash
213
+ spec-eval audit ./your-project --model anthropic:claude-opus-4-8 --out spec-reports/claude
214
+ spec-eval audit ./your-project --model google:gemini-3.5-flash --out spec-reports/gemini
215
+
216
+ diff spec-reports/claude/report.md spec-reports/gemini/report.md # or read them side by side
217
+ ```
218
+
219
+ How to read two reports:
220
+
221
+ - **Both flag it** → almost certainly real. Fix these first.
222
+ - **Only one flags it** → a judgment call. Read the quoted evidence and decide.
223
+ - **Sufficiency scores differ a little** → normal wobble. Compare the **gaps lists**, not the decimals — the same
224
+ missing behavior named by both graders is the signal.
225
+
226
+ Each vendor reads its own key from the environment — `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY` —
227
+ so put both keys in one `.env` and each run picks up the one it needs. (Want one fewer key? Swap either side for
228
+ `--model claude-code`, which uses your Claude Code login instead.)
229
+
230
+ ## Proof it works
231
+
232
+ - **spec-eval specs itself** — every module in [`spec_eval/`](spec_eval/) has its own spec:
233
+ **coverage 100% · drift 0 · sufficiency ≈0.86** ([receipt](SPEC-HEALTH.md) — the exact, dated score).
234
+
235
+ ## More
236
+
237
+ - **Works with [spec-driven development](https://en.wikipedia.org/wiki/Spec-driven_development).** SDD's goal is a spec you can *trust*, and **spec-eval** is that trust layer.
238
+ Use it three ways: **grade the specs you already have**, **generate specs** for code that has none, or **check as
239
+ you write** (with the skills). Spec-first, code-first, or in between — it meets you where you are.
240
+ - **Grow the spec and the code together.** The best version of "in between": draft a little spec, write a little
241
+ code, check they still agree — repeat. The two can even move in parallel (you shape the spec while your coding
242
+ agent writes the code; the check is where they meet), so the spec is *born accurate* instead of written up
243
+ afterward.
244
+ - **Just want to vibe code?** Fine — build first, check later, automatically: a pre-commit gate and a GitHub
245
+ Action can run the checks for you — see [Make it routine](GETTING-STARTED.md#make-it-routine).
246
+ - **Higher-stakes spec?** Run it past two vendors and compare — see [Higher stakes? Get a second opinion](#higher-stakes-get-a-second-opinion) above.
247
+
248
+ ## FAQ
249
+
250
+ Common questions — from *"which command do I run first?"* through costs, layouts, and score accuracy — live in
251
+ **[FAQ.md](FAQ.md)**.
252
+
253
+ ## Feedback
254
+
255
+ Found a bug, a bad score, or a spec that misses the point? [Open an issue](https://github.com/benjaminjones/spec-eval/issues) — a report snippet and the command you ran is plenty.
256
+
257
+ ## Acknowledgements
258
+
259
+ Built on the Anthropic, OpenAI, and Google SDKs (MIT / Apache-2.0) + PyYAML.
260
+
261
+ ---
262
+ *Terms you may be searching for: software specification · documentation drift · living documentation · docs as code · backfill
263
+ documentation · spec-driven development (SDD) · agentic development · AI-assisted coding · vibe coding · vibe engineering ·
264
+ AI code documentation · LLM-as-judge / trust eval. MIT licensed.*
@@ -0,0 +1,52 @@
1
+ [project]
2
+ name = "spec-eval"
3
+ dynamic = ["version"] # single source of truth: spec_eval/__init__.py (__version__)
4
+ description = "A trust-eval for your specs: coverage, drift, and sufficiency of markdown specs against code."
5
+ readme = "README.md"
6
+ requires-python = ">=3.9"
7
+ license = { text = "MIT" }
8
+ authors = [{ name = "Ben Jones" }]
9
+ keywords = ["spec-driven-development", "documentation-drift", "docs-as-code", "living-documentation",
10
+ "llm-as-judge", "code-documentation", "backfill-documentation"]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Intended Audience :: Developers",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Programming Language :: Python :: 3",
16
+ "Topic :: Software Development :: Documentation",
17
+ "Topic :: Software Development :: Quality Assurance",
18
+ ]
19
+ dependencies = [
20
+ "anthropic>=0.40",
21
+ "openai>=1.50",
22
+ "google-genai>=1.0",
23
+ "PyYAML>=6.0",
24
+ ]
25
+
26
+ [project.optional-dependencies]
27
+ dev = ["pytest>=7", "hypothesis>=6", "ruff>=0.4"]
28
+
29
+ [project.scripts]
30
+ spec-eval = "spec_eval.cli:main"
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/benjaminjones/spec-eval"
34
+ Repository = "https://github.com/benjaminjones/spec-eval"
35
+ Issues = "https://github.com/benjaminjones/spec-eval/issues"
36
+
37
+ [build-system]
38
+ requires = ["setuptools>=61"]
39
+ build-backend = "setuptools.build_meta"
40
+
41
+ [tool.setuptools]
42
+ packages = ["spec_eval"]
43
+
44
+ [tool.setuptools.dynamic]
45
+ version = { attr = "spec_eval.__version__" }
46
+
47
+ [tool.pytest.ini_options]
48
+ testpaths = ["tests"]
49
+ python_files = ["test_*.py"]
50
+
51
+ [tool.ruff] # Layer 0 — static analysis
52
+ line-length = 120
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ """spec-eval — portable code↔doc drift audit + fingerprint."""
2
+ __version__ = "0.2.0" # THE single source of version truth; pyproject.toml reads this via dynamic version
@@ -0,0 +1,4 @@
1
+ from .cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()