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
4 changes: 2 additions & 2 deletions .claude/rules/docs-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ When creating or editing any markdown file, follow the discipline below. These a
- **Zero hallucination.** Document only what the code provably does. Read the implementation; don't infer behaviour from a name, type, comment, file location, or familiar pattern.
- **Prove it.** Before writing any technical claim, know the exact file (and ideally lines) that prove it. If you can't, don't write it. Silence beats speculation: no "appears to", "should", "will", or planned/intended behaviour.
- Fix existing statements that contradict the code.
- **Cut a comment by whole sentences.** Delete each sentence that restates the declaration or the code beneath it, re-describes members carrying their own comments, or narrates alternatives or reasoning where the code needs only the conclusion, and keep every other sentence word for word: the one sentence saying what a public symbol does and a sentence explaining a non-obvious internal always stay, and being accurate is not, on its own, a reason a sentence stays. A package or file comment says what the unit is for and never tours its members.
- **Current state only.** Describe the code as it is now, in prose and in comments alike. Never narrate the past ("replaces", "used to", "formerly", "for the first time", "unlike the old") and never name a file, flag, or tool that no longer exists: git carries that history, and a reader cannot check a claim against something that is gone. Future intent lives in a `TODO` in the code, never in the documentation. **Name the line a comment describes**, and delete the comment where no line corresponds: that is the test the phrase list misses, and a comment explaining why something was removed is what it catches, since its subject is a decision and its reader is looking at the pull request. Rationale worth keeping goes in a decision record of its own under [`docs/`](../../docs/index.md), created when the first one is needed, rather than scattered through the files it explains.
- **Cut a comment by whole sentences, above the public floor.** Never delete or cut below one sentence the documentation comment on a public or exported symbol, a public structure member, or a package or module. Keep the sentence saying what it does, even where it restates the name, code, or syntax; where unclear, keep the first sentence. Correct a wrong or absent-content claim from the body. If the body was not read, keep the comment and report it. Cut other sentences that restate code, re-describe documented members, or narrate alternatives or reasoning where the code needs only the conclusion, keeping every other sentence word for word. A package or file comment says what the unit is for and never tours its members.
- **Current state only.** Describe the code as it is now, in prose and in comments alike. Never narrate the past ("replaces", "used to", "formerly", "for the first time", "unlike the old") and never name a file, flag, or tool that no longer exists. Future intent lives in a `TODO` in the code, never in the documentation. **Name the line a comment describes.** Where no line corresponds, correct a public or exported symbol's comment from its body; delete an internal comment on that ground. A note about a deliberate omission the code depends on and a file header pass this test. Rationale worth keeping goes in a decision record of its own under [`docs/`](../../docs/index.md).

## Style

Expand Down
15 changes: 8 additions & 7 deletions .claude/skills/audit-docs/SKILL.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions .claude/skills/audit-docs/agents/surface-auditor.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ A comment can be accurate and still be in the wrong place. Report every comment

Both halves of the test are mechanical, and both are required. The comment names a symbol, and the line beneath it uses that same symbol. A comment above a line that does not reference the symbol it discusses is a different comment and is never reported.

**The declaration bounds the entry, and this list is the one most likely to reach past the scope.** A symbol is used far from where it is declared, so following a usage site to its declaration is exactly how a pass drifts into code nobody asked it to touch. Report a copy under `REPEATED` only where the declaration sits inside the paths handed in **and** its body was opened this run. Where the declaration lies outside those paths, or inside them but unopened, the copy is not an entry: the comparison that would justify removing it was never made. It goes under `UNRESOLVED` with the declaration's path named, which lets the caller widen the scope deliberately rather than inherit a deletion nobody could check.
**A declaration, including an export or re-export statement, is not a use.** Report a copy under `REPEATED` only where the declaration sits inside the paths handed in **and** its body was opened this run. Where the declaration lies outside those paths, or inside them but unopened, report the copy as `UNRESOLVED` with the declaration's path.

```javascript
// isBetaEnabled mirrors the beta-features flag.
Expand All @@ -90,13 +90,13 @@ SYMBOL: `isBetaEnabled`. COMMENT: `isBetaEnabled mirrors the beta-features flag.

## List four: sentences a comment does not need

A comment can be true, non-repeated, and still carry sentences its reader does not need. This list covers **every** comment in the paths handed in: inline comments, documentation comments on declarations, and file, module, or package comments. Report a comment here when it holds at least one sentence of these three kinds:
A comment can be true, non-repeated, and still carry sentences its reader does not need. This list covers **every** comment in the paths handed in: inline comments, documentation comments on declarations, and file, module, or package comments. A public or exported symbol, a public structure member, or a package or module always keeps at least one sentence: keep the sentence saying what it does, or the first sentence when unclear. Correct a wrong or absent-content claim from the body, never delete that comment; if the body was not read, keep and report it. Report a comment here when it holds at least one sentence of these three kinds:

- a sentence restating the declaration or the code beneath it, such as a signature retold in prose or a straightforward conditional, loop, or assignment walked through step by step, other than the one sentence a public symbol's documentation comment gives to what the symbol does, which is required even where it restates the name or body;
- a sentence restating the declaration or the code beneath it, such as a signature retold in prose or a straightforward conditional, loop, or assignment walked through step by step, except for the public floor sentence, which is always kept even where it restates the name, code, or syntax;
- a sentence listing or re-describing members that carry their own comments, which is how a package or type comment turns into a tour of the interface: each member's own comment, and the reference the language generates from them, already carry it;
- a sentence narrating alternatives considered or reasoning walked through, where the code needs only the conclusion.

Report the comment's own sentences in two verbatim sets: `KEEP`, the sentences carrying something the code does not show, and `CUT`, each sentence of the three kinds above beside the code string or member comment it restates. The one sentence a public symbol's documentation comment gives to what the symbol does, and a sentence explaining a non-obvious internal, are always `KEEP`. Never write replacement text: a reworded or merged sentence is a new claim, and the caller writes any new wording from code it opens itself. A comment that is also wrong goes under `CONTRADICTED` as well, and the caller corrects it before cutting.
Report the comment's own sentences in two verbatim sets: `KEEP`, the sentences carrying something the code does not show, and `CUT`, each sentence of the three kinds above beside the code string or member comment it restates. For a public or exported symbol, public structure member, or package or module, `KEEP` is never empty: keep its summary sentence, or the first sentence if unclear. A wrong comment in this group is corrected from the body, never deleted; an unread body means keep and report it. A sentence explaining non-obvious internal logic is also always `KEEP`. Never write replacement text: the caller writes any new wording from code it opens itself. A wrong comment also goes under `CONTRADICTED`, and the caller corrects it before cutting.

```python
# We need to check if the user is eligible for the discount.
Expand Down Expand Up @@ -144,7 +144,7 @@ Each of these produces noise rather than a finding, so leave each one out of the
- a comment that is merely terse, or plain, or worded differently from how a convention would word it: every list;
- an internal helper whose name and signature already carry what it does: `UNDOCUMENTED`;
- a missing comment on a binding inside a function body: `UNDOCUMENTED`;
- a comment sitting on a declaration: `REPEATED`, since a declaration is never a use, each member of a public structure carries its own comment, and a file-level header says what the file or package is for. The same comment is still read for `CONTRADICTED` and `VERBOSE`;
- a comment sitting on a declaration: `REPEATED`, since a declaration, including an export or re-export statement, is not a use. A member's comment and a file-level header are still read for `CONTRADICTED` and `VERBOSE`;
- a type annotation restated in prose: `CONTRADICTED`, since it is a style question and not a contradiction, though under `VERBOSE` it is a restating sentence;
- anything the agent could not open: every list, since it is reported as unread in the counts and never as a finding.

Expand Down Expand Up @@ -189,7 +189,7 @@ BLOCKED BY: <outside the paths handed in / inside them and not opened>

VERBOSE
<file path> :: <symbol, or the line the comment sits above>
KEEP: <each sentence carrying what the code does not show, verbatim, with any credential value replaced by [REDACTED]>
KEEP: <each sentence carrying what the code does not show, verbatim, with any credential value replaced by [REDACTED]; never empty for a public symbol, public structure member, package, or module, where its summary sentence or, if unclear, first sentence goes here>
CUT: <each sentence to delete, verbatim> :: <the code string or member comment it restates, verbatim, or the reasoning it narrates>

COUNTS
Expand Down
3 changes: 2 additions & 1 deletion .claude/skills/audit-docs/assets/audit-report.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Undocumented public symbols outside the change, listed rather than documented: [
| `[path]` | [documented [count] previously undocumented public symbols] |
| `[path]` | [created, [tutorial / how-to guide / reference / explanation]] |

Kinds to choose from: made the change the request asked for, 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, cut sentences from a comment, removed a duplicated section, introduced a term on first use, added orientation for a first-time reader, created, and, only where the request asked or the user approved it, renamed, moved, split, merged, or deleted.
Kinds to choose from: made the change the request asked for, corrected a factual statement, documented a public symbol, retained a public documentation comment at its one-sentence floor, corrected an existing documentation tag, removed an outdated or restating internal comment, removed a comment repeated above a usage site, cut sentences from a comment, removed a duplicated section, introduced a term on first use, added orientation for a first-time reader, created, and, only where the request asked or the user approved it, renamed, moved, split, merged, or deleted.

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

Expand Down Expand Up @@ -122,6 +122,7 @@ This run edits documentation, so a code defect is reported here and left alone.

- Every phase carries a status line, including a phase whose answer is that the documentation was already accurate.
- Every symbol reported in Phase 3 as left as it stands because its implementation was not read also appears under Unverified.
- No documentation comment on a public or exported symbol, public structure member, package, or module was deleted or cut below one sentence.
- Every file changed is inside the scope, and none was renamed, moved, split, or deleted unless the request asked for it or the user approved it.
- Every file named in a phase result appears in the files changed table, and every row of that table is a file that was edited.
- The file count in the summary matches the number of rows in the table.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Delegation needs care. When the symbol forwards to another, the proof lives in t

An absence claim ("does not validate the payload", "no retry on a 4xx") cannot be proved by copying one string, because the evidence is a branch that is not there. Ground it by enumerating the full set of branches and quoting the boundary that closes the set: the final `else`, the `default` case, the end of the match, or the last statement of the body. Then search for anything else that writes the same path (a subclass, an override, middleware, a decorator, a registered hook, generated code) and confirm none of them supplies the behaviour you are calling absent. Record the search you ran next to the quote. If the set cannot be closed, because dispatch is dynamic or the handler list is assembled at run time, the claim goes under "Unverified" instead of on the page.

A comment with no corresponding line also makes an absence claim. Prove the absence across its full scope before treating the comment as false; on a public or exported symbol, correct it from the body rather than deleting it.

## Provable is not the same as worth writing

Grounding decides whether a statement **may** be written. It never decides that it **should** be, and it never decides how many times. Holding proof for one fact is proof about one fact, not a licence to state it at every site where it happens to be true.
Expand Down
10 changes: 5 additions & 5 deletions .claude/skills/audit-docs/references/voice-and-ai-tells.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ Treat a hedge as an accuracy failure first and a voice failure second. `appears

## Prose that restates the code instead of adding to it

Cut any sentence a reader could reconstruct from the declaration. Prose earns its place by carrying what a signature cannot: why the thing exists, what the caller owes it, what happens at the boundary, and what a value means at its limits. The exception is consumer-facing reference material, whose readers cannot open the source, so stating what the function does is the entire job, and a public symbol's documentation comment, whose one sentence saying what the symbol does stays even where it restates the name: the pairs below show how to write that sentence, not a reason to cut it.
Cut any sentence a reader could reconstruct from the declaration, except the one-sentence floor on a public symbol's documentation comment. That sentence stays as written even when it restates the name, code, or syntax. The pairs below distinguish that existing floor from additional documentation to write only when the body proves it.

```python
# Restates the signature:
# The floor, kept as written:
def set_timeout(seconds: int) -> None:
"""Sets the timeout to the given number of seconds."""

Expand All @@ -106,9 +106,9 @@ def set_timeout(seconds: int) -> None:
```

```go
// Restates: Close closes the writer.
// Adds: Close flushes buffered rows before releasing the file handle, and
// a write after Close returns ErrClosed rather than panicking.
// Floor, kept as written: Close closes the writer.
// Written new: Close flushes buffered rows before releasing the file handle,
// and a write after Close returns ErrClosed rather than panicking.
func (w *Writer) Close() error {
flushErr := w.flush()
w.closed = true
Expand Down
Loading