From expansion
Use when a codebase property needs a formal guarantee — mathematical invariants, security boundaries, data privacy, normalization correctness. Creates ASSERTION proof files citing specific code lines, and re-verifies them when code changes.
How this skill is triggered — by the user, by Claude, or both
Slash command
/expansion:doc-proverThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Creates and maintains formal ASSERTION → PROOF documents. Each proof has two layers: a **human narrative** that builds understanding through explanation, and a **machine manifest** that enables automated re-verification when code changes.
Creates and maintains formal ASSERTION → PROOF documents. Each proof has two layers: a human narrative that builds understanding through explanation, and a machine manifest that enables automated re-verification when code changes.
A proof is a legal brief, not a comment. It builds a chain of evidence from specific code lines to a conclusion. A reader can verify the assertion by reading ONLY the proof file, without reading the entire codebase.
Two audiences, one file: The human reads the narrative top-down to understand why the property holds. The agent reads the manifest bottom-up to check whether the cited code has changed.
Announce at start: "Using doc-prover to create/verify assertion: ."
doc-audit flagged an invalidated proof (PROOF!)Not for: General module docs (use doc-writer), drift detection (use doc-audit), visual architecture (use canvas-diagrams).
| Category | Example | What to prove |
|---|---|---|
| Mathematical | "Betweenness centrality is normalized to [0,1]" | Show the normalization code, prove bounds |
| Security | "OPENROUTER_API_KEY is only sent to openrouter.ai" | Trace every use of the key, show no other destination |
| Privacy | "Uploaded Twitter archive data never leaves the local machine" | Show all network calls, prove none include archive data |
| Data invariant | "Curation splits are deterministic — same tweet always gets same split" | Show the hash function, prove it's pure |
| Consistency | "API response format always includes status field" | Show all route return statements |
| Correctness | "Brier score calculation matches the standard formula" | Show the formula, map to code |
Location: docs/proofs/<assertion-name>.md
Naming: kebab-case, descriptive. E.g., split-determinism.md, api-key-locality.md, betweenness-normalization.md.
Every proof file has two parts: the Human Proof (top) and the Machine Manifest (bottom). The human proof is what you read. The machine manifest is what the agent checks.
# ASSERTION: <Claim in plain English>
<!--
Status: valid | invalidated | under-review
Created: YYYY-MM-DD
Last verified: YYYY-MM-DD
Code hash: <git short sha at verification time>
Verified by: <human|agent>
-->
---
## Part I: Human Proof
---
### Claim
<Precise statement of what is being asserted. Unambiguous.
Mathematical notation if applicable.>
### Why This Matters
<What breaks or becomes untrustworthy if this assertion is false.
Why someone would want this guarantee. Written for a person who
has never seen this codebase.>
### The Argument
<A narrative explanation — like a textbook proof or a well-written
blog post — that walks the reader through WHY this property holds.
Use natural language, build intuition, explain the design.>
<Embed code snippets inline where they help understanding, but
don't just dump code. Explain what each piece does and how it
connects to the next.>
<Structure as a story with a beginning (setup), middle (the key
mechanism), and end (why this guarantees the property).>
**Example narrative style:**
> The system assigns every tweet to exactly one of three splits
> (train/dev/test) using a deterministic hash. The key insight is
> that the split depends ONLY on the tweet ID — no randomness, no
> database state, no ordering. Here's how:
>
> The function `split_for_tweet()` in `schema.py` takes a tweet ID,
> computes its SHA256 hash, extracts the first 8 hex digits as an
> integer, and takes modulo 100. This gives a bucket 0-99:
>
> ```python
> bucket = int(hashlib.sha256(tweet_id.encode("utf-8")).hexdigest()[:8], 16) % 100
> ```
>
> Buckets 0-69 → train (70%), 70-84 → dev (15%), 85-99 → test (15%).
>
> Because SHA256 is a pure function with no external state, the same
> tweet ID always produces the same bucket, and therefore the same
> split. This holds across runs, across machines, across time.
### Boundary Conditions
<Edge cases, assumptions, and conditions under which
the assertion might NOT hold. Written conversationally:>
- **Assumption:** <what must be true for this proof to hold>
- **Exception:** <known case where the assertion is weaker>
- **Threat:** <what code change would invalidate this proof>
- **What would break this:** <specific scenario>
### Verification (for the skeptical reader)
<How a human can verify this themselves. Could be:>
- A command to run
- A manual test to perform
- A specific file to read
- A query to execute
```bash
# Example: verify two runs produce identical splits
python -c "from src.data.golden.schema import split_for_tweet; print(split_for_tweet('12345'))"
# Run again — same result every time
```
### Related
- Module doc: [`docs/modules/<name>.md`](../modules/<name>.md)
- ADR: `docs/adr/NNN-<name>.md` (if applicable)
- Other proofs that depend on this one: [list]
---
## Part II: Machine Manifest
---
<This section is for automated re-verification by the agent.
Humans can skip this. The agent uses it to check whether cited
code has changed since the proof was written.>
### Citations
| # | File | Symbol | Lines | Code hash | Status |
|---|------|--------|-------|-----------|--------|
| 1 | `<relative/path/to/file.py>` | `<function_or_class>` | `<start>-<end>` | `<sha>` | valid |
| 2 | `<relative/path/to/another.py>` | `<function_or_class>` | `<start>-<end>` | `<sha>` | valid |
**Symbol anchoring:** Line numbers are recorded at proof-creation time but may shift. During re-verification, if `git diff` shows changes, locate the symbol by name first, then compare the code snapshot. If the symbol contains identical code at different line numbers, the citation is still valid — update the line numbers in the table.
### Cited Code Snapshots
#### Citation 1: `<file.py>:<start>-<end>`
```python
<exact code at those lines at verification time>
```
**Establishes:** <one-sentence fact>
#### Citation 2: `<another.py>:<start>-<end>`
```python
<exact code>
```
**Establishes:** <one-sentence fact>
### Logical Chain (formal)
1. Citation 1 establishes that <X>.
2. Citation 2 establishes that <Y>.
3. From X and Y, it follows that <Z>.
4. Therefore, <the assertion holds>.
### Re-verification Commands
```bash
# Quick check: have any cited files changed?
git diff <proof_code_hash>..HEAD -- <file1> <file2> ...
# If diff is empty → all citations still valid
# If diff is non-empty → re-examine affected citations
```
digraph prover {
"Receive assertion" [shape=box];
"Identify relevant code" [shape=box];
"Trace all paths" [shape=box];
"Build evidence chain" [shape=box];
"Identify boundaries" [shape=box];
"Write proof file" [shape=box];
"Add to INDEX.md" [shape=box];
"Add ASSERTION tag to module doc" [shape=box];
"Present to human" [shape=doublecircle];
"Receive assertion" -> "Identify relevant code";
"Identify relevant code" -> "Trace all paths";
"Trace all paths" -> "Build evidence chain";
"Build evidence chain" -> "Identify boundaries";
"Identify boundaries" -> "Write proof file";
"Write proof file" -> "Add to INDEX.md";
"Add to INDEX.md" -> "Add ASSERTION tag to module doc";
"Add ASSERTION tag to module doc" -> "Present to human";
}
doc-audit finding, or agent observationfile:line with exact code snippets. Each step should establish one fact.docs/modules/<name>.md:
- **ASSERTION: <claim>** → [`docs/proofs/<name>.md`](../proofs/<name>.md)
When doc-audit flags a PROOF! finding, or on periodic review:
git diff <proof_code_hash>..HEAD -- <cited_file>validvalid → invalidated)valid → invalidated or under-review)"Proof
split-determinismcitation 3 invalidated:schema.py:110-116changed. The hash function was modified from SHA256 to SHA512. The assertion still holds (determinism is preserved) but the proof needs updating."
| Layer | Who reads it | What it answers | Where in file |
|---|---|---|---|
| Human Proof (Part I) | Humans, new contributors | "WHY does this property hold?" | Top of file |
| Machine Manifest (Part II) | Agent, doc-audit | "HAS the cited code changed?" | Bottom of file |
Agent re-verification workflow (fast path):
# Check all cited files at once using the manifest table
git diff <proof_code_hash>..HEAD -- <file1> <file2> <file3>
# Empty output → proof still valid, no further reading needed
Human verification workflow (understanding path):
server.py:360-362schema.py:split_for_tweet:110-116). During re-verification, if lines shifted but the symbol still contains the same code, the citation is still valid — find the symbol by name, not by line number.OPENROUTER_API_KEY finds 3 occurrences, all in this file"| Level | Standard | When to use |
|---|---|---|
| Sketch | High-level argument, key citations | Low-stakes, stable code |
| Standard | Full evidence chain, all paths cited | Default for most assertions |
| Rigorous | Exhaustive search, negative evidence, boundary analysis | Security, privacy, financial correctness |
The user should specify which level they want. Default to Standard.
Part I — Human Proof:
Part II — Machine Manifest:
file:line, code hash, and code snapshotgit diff command providedIntegration:
docs/proofs/<name>.mdGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub anantham/expansion --plugin expansion