Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .claude/rules/docs-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ When creating or editing any markdown file, follow the discipline below. These a
- Document a tunable value by the **name a consumer changes it by** (env var, config key, CLI flag, or a named member of a centralized constants/config module that other code reads), judging by role, not location. Don't document an ephemeral local variable as the config surface.
- **Acronyms** in prose you write or edit use capitals (ID, URL) and are expanded on first use per doc ("Deoxyribonucleic acid (DNA)"). Keep exact casing for brand/tool/package names (npm, iOS), domain terms (snRNA), and direct code references (an `id` field).
- No placeholders, TODOs, or empty "add details here" sections.
- **Two readers, one document.** Every page is read by a newcomer meeting the system for the first time and by someone who already works in it, and serving only the second is the ordinary failure. Serve both by order rather than by splitting the page: what the subject is and why a reader would reach for it, what that reader must already have or have read, then the depth in full. A page only its author can follow is not finished, and neither is one whose reader could have got it faster from the source.
- **Introduce every term of art where the document first uses it**, in a short parenthesis or by a link to the document that defines it, then use it unchanged. Expanding an acronym is not introducing it, since the expansion is often as opaque as the abbreviation. Spell a concept one way across [`docs/`](../../docs/index.md): a concept spelled three ways is three concepts to anyone meeting it, and it defeats their search.
- A document opens with a single H1 named for its file, then a one to three sentence introduction for a reader who does not yet know the subject, then H2s. Headings are unique and fully descriptive ("Retry backoff limits", not "Limits"), because anchors are generated from them, and use sentence case.
- **Tables only for uniform data scanned quickly.** If columns repeat across rows, cells sit empty, or a cell holds a sentence of prose, use a list instead.
- Prefer Markdown to raw HTML for layout or styling.
Expand Down
57 changes: 32 additions & 25 deletions .claude/skills/audit-docs/SKILL.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions .claude/skills/audit-docs/agents/claim-verifier.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ Where the proving string holds a credential value, such as a token, a password,
- **not reached**: the file is absent, the symbol is not in it, the body sits behind a boundary you cannot open (generated, compiled, vendored, remote), or you did not open it.
- **not established**: you read the whole body and no string either proves or contradicts the claim, the outcome is fixed by a value supplied elsewhere, or the claim as worded cannot be falsified.

**A claim naming more than one file is verified against each of them, not returned unproven for spanning them.** An orientation sentence rests on several files, so read the symbol in every file the caller named and settle each part separately: CONFIRMED where every part carries its own quote, REFUTED where any part is contradicted, UNPROVEN naming the part left uncovered. Being unfalsifiable against one symbol is not the disqualifier here; an uncovered part is.

Uncertainty resolves to UNPROVEN, never to CONFIRMED. UNPROVEN costs the caller one claim; a CONFIRMED without proof puts an unchecked statement into published documentation.

**Refuting a claim about something absent.** A claim that the code does something its body never does has no contradicting string to quote. Quote the code occupying the position where the claimed behaviour would have to sit: the catch block whose only statement is a return, the branch that falls through, the handler that returns before the claimed call. That quote carries REFUTED. When nothing occupies that position at all, the verdict is UNPROVEN (not established).
Expand Down
33 changes: 23 additions & 10 deletions .claude/skills/audit-docs/agents/coverage-mapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ The agent does not receive the purpose of the audit, the report being drafted, o

## Walk each document once

For every document in scope, open it and record four things.
For every document in scope, open it and record five things.

1. **Path**, exactly as it sits on disk.
2. **Subject claimed**, taken from the H1 and the opening paragraph, in one clause, as the document states it rather than as the agent would restate it.
3. **Code the subject maps to**: the file, module, or symbol the subject names, located in the code area and opened far enough to confirm the subject exists there. A search hit is not a mapping.
4. **Status**, exactly one, from the closed list below.
4. **Type**, exactly one of tutorial, how-to guide, reference, or explanation, decided by what the document's reader needs rather than by its subject: content informing action serves the acquisition of skill as a tutorial and its application as a how-to guide, and content informing cognition serves acquisition as an explanation and application as a reference. A document that is plainly navigation and nothing else is recorded as `navigation`.
5. **Status**, exactly one, from the closed list below.

A document the walk did not open is never given a status. It goes in the count of documents in scope not opened, listed by path, so that a short map cannot be read as a clean one.

Expand Down Expand Up @@ -63,21 +64,29 @@ Compiled during the walk and returned alongside the per-document map.

## Worked map

| Document | Subject claimed | Code | Status |
| -------------------------------- | ---------------------------------- | -------------------- | -------------------------------------------------------------------------- |
| `docs/guide/queue-consumers.md` | how a worker drains the job queue | `worker/consumer.go` | covered |
| `docs/reference/cache-warmer.md` | a background cache warmer | none | orphaned |
| `docs/guide/installation.md` | installing and running the service | `scripts/install.sh` | duplicated (`README.md`, the same eight steps) |
| `docs/reference/http-errors.md` | the error codes the API returns | `lib/http/errors.rb` | contradicted (`docs/guide/clients.md` gives 404 where the code raises 410) |
| Document | Subject claimed | Code | Type | Status |
| -------------------------------- | ---------------------------------- | -------------------- | ------------ | -------------------------------------------------------------------------- |
| `docs/guide/queue-consumers.md` | how a worker drains the job queue | `worker/consumer.go` | how-to guide | covered |
| `docs/reference/cache-warmer.md` | a background cache warmer | none | reference | orphaned |
| `docs/guide/installation.md` | installing and running the service | `scripts/install.sh` | how-to guide | duplicated (`README.md`, the same eight steps) |
| `docs/reference/http-errors.md` | the error codes the API returns | `lib/http/errors.rb` | reference | contradicted (`docs/guide/clients.md` gives 404 where the code raises 410) |

No row carries `tutorial`, and that is the finding the type column exists to surface: this set documents every subject it has and still gives a first-time reader nowhere to start.

## The entry path

A set can be complete, accurate, and have no way in. Report the entry path as `present`, naming the document, only where one document takes a first-time reader through one task end to end and says what a finished run looks like. A link hub listing the other documents is `absent`, and so is an installation checklist that stops at the last command without saying what the reader should then see.

This is a report and never a licence to write the missing document. The caller decides that, under a rule this agent does not carry.

## Output format returned

```text
SCOPE: <the scope as received>

DOCUMENTS
| path | subject claimed | code | status | detail |
| ---- | --------------- | ---- | ------ | ------ |
| path | subject claimed | code | type | status | detail |
| ---- | --------------- | ---- | ---- | ------ | ------ |
| <one row per document opened; detail names the other document, the point of disagreement, or the unmapped label> |

UNDOCUMENTED
Expand All @@ -89,9 +98,13 @@ UNRESOLVED REFERENCES
HISTORICAL NARRATION
- <document> :: <line quoted verbatim, with any credential value replaced by [REDACTED]> :: <the phrase that flagged it>

ENTRY PATH
<present, naming the document, or absent> :: <one clause on what a first-time reader would have to read instead>

COUNTS
documents opened: <n>
documents in scope not opened: <n>, listed by path
types: <n> tutorial, <n> how-to guide, <n> reference, <n> explanation, <n> navigation
```

## Closing rule
Expand Down
12 changes: 6 additions & 6 deletions .claude/skills/audit-docs/agents/curation-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ One document, and the code that document describes. Nothing else. The agent does

## The two readers, and how each one fails

`SKILL.md` requires every document to serve internal developers maintaining the architecture and external developers consuming the interface. Those two readers do not fail in the same way, so one read tests for both.
`SKILL.md` requires every document to serve two readers: a newcomer meeting the system for the first time, and an experienced reader who already works in it. They do not fail in the same way, so one read tests for both.

### The deep technical reader
### The experienced reader

This reader fails when the document restates what the code already says and adds nothing that cannot be read faster from the source: no constraint, no invariant, no reason, no boundary.

Expand Down Expand Up @@ -45,7 +45,7 @@ Four terms carry the meaning of the first version and none of them is introduced

## The test applied to each reader

**Deep technical reader**: could this reader get this faster from the source? Where the answer is yes, the paragraph is not earning its place, and the finding names what it would have to add to earn it.
**Experienced reader**: could this reader get this faster from the source? Where the answer is yes, the paragraph is not earning its place, and the finding names what it would have to add to earn it.

Answer it with the cited symbol open. Calling a paragraph a restatement without reading what it restates is an inference from a name, which is the move the grounding rule exists to stop, and where the source could not be opened the paragraph goes on the borderline list rather than among the findings.

Expand All @@ -63,7 +63,7 @@ A paragraph is not earning its place when it is one of these five. Nothing outsi
- An enumeration padded to look complete, where an entry was added for symmetry rather than because the code carries it.
- Historical narration, which the current-state rule already governs and which a reader cannot check against something that is gone.

The first entry and the deep technical reader's test are one defect seen from two angles, so a restating paragraph is named once, on the list, and the maintainer verdict states the pattern rather than repeating the paragraph. The two questions come apart on the other reader: a newcomer blocker is context the document never supplies, so that verdict can read FAILED while every paragraph present is earning its place.
The first entry and the experienced reader's test are one defect seen from two angles, so a restating paragraph is named once, on the list, and that reader's verdict states the pattern rather than repeating the paragraph. The two questions come apart on the other reader: a newcomer blocker is context the document never supplies, so that verdict can read FAILED while every paragraph present is earning its place.

**The counterweight, and it is half of this question.** Connective prose that carries the logic is not bloat. Cutting it produces a choppy document that costs the reader more than the words saved, because the reasoning it held moves back into the reader's head. The target is concise, not terse, and a paragraph carrying a why or a how stays even where it runs longer than the paragraphs around it.

Expand All @@ -75,8 +75,8 @@ A decision record exists to preserve past intent, so a superseded option, an aba

```text
DOCUMENT: <path>
MAINTAINER (deep technical): SERVED | FAILED - <the specific blocker>
CONSUMER (newcomer): SERVED | FAILED - <the specific blocker>
EXPERIENCED READER: SERVED | FAILED - <the specific blocker>
NEWCOMER: SERVED | FAILED - <the specific blocker>
NOT EARNING ITS PLACE:
- <heading, then the paragraph's opening words> - <which of the five> - <what it would have to add>
BORDERLINE, LEFT ALONE:
Expand Down
13 changes: 11 additions & 2 deletions .claude/skills/audit-docs/assets/audit-report.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,17 @@ Sources that could not be resolved this run: [name each one and what you used in
- Corrected `[document]`: [the statement that contradicted the code] replaced with [the statement the code supports], from `[symbol]` in `[file]`.
- Deleted [section] from `[document]`: [describes a removed feature / duplicated in `[document]` / cannot be corrected].
- Created `[new document]`: [why no existing document was a home for it], filed as [tutorial / how-to guide / reference / explanation].
- Oriented `[document]`: [the acronym, term of art, prerequisite, or missing statement of subject that stopped a first-time reader] introduced at [where].

(Deletion needs one of the three listed reasons. Anything else is a correction. A created file needs the structure check stated first: which existing homes were considered and why each did not fit.)
**Both readers, one line per document opened:**

| Document | Newcomer | Experienced reader |
| -------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `[path]` | [served, or the first place a reader who has not seen this codebase stops] | [served, or the paragraph they could get faster from the source, and what it would have to add] |

**Entry path:** [present, naming the document that takes a first-time reader through one task end to end / absent, and what a first-time reader has to read instead].

(Deletion needs one of the three listed reasons. Anything else is a correction. A created file needs the structure check stated first: which existing homes were considered and why each did not fit. The entry path is reported whether or not it was written, and it is written only where the invoking task asked for it.)

## Phase 3 result: in-code documentation audit

Expand All @@ -67,7 +76,7 @@ Public symbols left as they stand because their implementation was not read: [`C
| `[path]` | [documented [count] previously undocumented public symbols] |
| `[path]` | [created, [tutorial / how-to guide / reference / explanation]] |

Kinds to choose from: corrected a factual statement, documented a public symbol, corrected an existing documentation tag, removed an outdated or restating comment, removed a comment repeated above a usage site, removed a duplicated section, created, deleted.
Kinds to choose from: corrected a factual statement, documented a public symbol, corrected an existing documentation tag, removed an outdated or restating comment, removed a comment repeated above a usage site, removed a duplicated section, introduced a term on first use, added orientation for a first-time reader, created, deleted.

(One row per file, not one per edit. If no file changed, replace the table with "No files changed.")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Keep the quote to one line or the fragment carrying the operative token. A ten-l

## Why the quote stays out of the published sentence

The quote is a private verification token, not published text. The page cites the file and symbol through a single markdown link and states the behaviour in your own words: no pasted source, no line range, no commit hash, no "as of" qualifier. A reader follows the link to the file as it stands today, whereas pasted source and line ranges go stale on the next edit, silently and without a signal to anyone.
The quote is a private verification token, not published text. The page cites the file and symbol through a single markdown link and states the behaviour in your own words: no pasted source, no line range, no commit hash, no "as of" qualifier. **This governs source pasted as evidence for a claim, and reaches nothing else.** A short usage example written for a reader to copy and adapt is a different artifact serving a different purpose, and the snippet allowance governs it. A reader follows the link to the file as it stands today, whereas pasted source and line ranges go stale on the next edit, silently and without a signal to anyone.

One value is withheld even from the note. Where the proving string holds a credential value, such as a token, a password, an API key, a private key, or a session identifier, record the string with that value replaced by `[REDACTED]`, leaving the surrounding assignment or call intact. The recheck at output time then runs on the text around the placeholder, which is what the note exists to make possible. Never reconstruct the value a placeholder stands for. A credential value belongs in neither the note nor the page.

Expand Down
Loading