agentleFS
grimoire-rsgrimoire-rs/grimoire/.claude/skills/code-docs-cleanup/SKILL.md

code-docs-cleanup

Skill15 starsChanged 17 days agoApache-2.0View on GitHub

Clause-by-clause procedure for shortening and cleaning up source-code comments without losing a guard, the comment that says why a non-obvious line must stay as it is and what breaks if it changes. Use when someone asks to shorten, trim or clean up comments, says a file has too many or overly verbose comments or is over-commented, cut comment density or comment bloat, split an essay comment or an over-long doc comment or docstring, move design rationale out of code into a decision record, remove plan, work-package, review-round or decision IDs from comments, delete comments that restate the code, bring a file under the code-docs length caps, or prepare a file or package for the code-docs comment ratchet. Not for writing the comment standards, which the code-docs rule carries, not for --help, JSON Schema, MCP tool descriptions or other text that renders to users, and not for user-facing documentation pages, which the docs-quality rules cover.

  • Installs packages

The file

Show its rules and text

We split this skill into the rules it gives an agent

21 rules. About 0 are common, 15 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈15

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not run it when:

    line 47
  2. Distinctive:

    Touched files: only the files the change already edits (CLN-08).

    line 107
  3. Distinctive:

    Write a worklist in a scratch directory outside the repo.

    line 161
  4. Distinctive:

    Delete a clause outright only when the list positively identifies it as narration, tautology, a banner, a bare ID or unquantified pure …

    line 176
  5. Distinctive:

    Keep the constraint and the concrete consequence of breaking it.

    line 188
  6. Distinctive:

    Keep nothing else in the guard: no history, no weighed alternatives, no bare ID.

    line 191
  7. Very specific:

    Put a caller-visible precondition in the doc comment and an implementation hazard in a plain comment at its line (GRD-04).

    line 201
  8. Distinctive:

    When the guard clauses alone exceed the cap, keep them all and tighten the wording.

    line 204
  9. Distinctive:

    Never invent a consequence the original does not state and the code does not show.

    line 209
  10. Very specific:

    Keep that one local line naming the owner, even when the owning construct states itself, such as assert_never(x) or a scoped #[deny(...)].

    line 253
  11. Distinctive:

    Never point at a commit, a branch, a backup ref or a gitignored path (RTE-02).

    line 276
  12. Distinctive:

    Leave these where they are and list them in the report.

    line 286
  13. Distinctive:

    Delete a bare process ID and keep the constraint it labelled, in words (LNK-01).

    line 290
  14. Very specific:

    Add a record pointer in its place only when the same block already names that file, or when you have read the record and it holds the …

    line 293
  15. Distinctive:

    Keep every file-qualified pointer (GRD-11):

    line 298
  16. Distinctive:

    Commit the cleanup on its own, with only prose in it.

    line 362
  17. Very specific:

    If the repo keeps the rule's baselines, record the drop in the same commit, never with --allow-regression, and let --check confirm it …

    line 366
  18. Distinctive:

    MUST = Block. SHOULD = Warn: fix, or state why not in the commit body.

    line 402
  19. Very specific:

    every CLN-02 review item, and how you resolved it.

    line 422
  20. Very specific:

    every --cites record, for a human to confirm it holds the removed argument.

    line 423
  21. Distinctive:

    Reporting success from its own reading: instead of the check and the re-check.

    line 465

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

code-docs-cleanup

Shorten the comments in a source file without losing a guard. A guard is any clause that names a constraint a plausible edit would break, with or without the consequence. It is how the next agent learns why a non-obvious line looks the way it does and whether it may change it.

The comment standards live in the installed code-docs rule, cited here by ID: GRD (guards), RTE (routing), LNK (pointers and IDs), SRF (rendered surfaces) and LEN (length and ratchet). The cleanup-safety rules, CLN, are this skill's own: Cleanup rules. Three facts shape every step (as of 2026-09):

  • In agent-written code most comment lines are guards and contracts, not essays. Deleting by category or by length deletes guards.
  • The shipped guard recogniser finds fewer than half of real guards (recall about 0.43). A block it does not flag is unclassified, never safe to cut.
  • The editing agent's belief that the meaning survived is not evidence. The structural check and a cold re-check are.

Contents: When to run · Setup · Scope · Procedure · Never touch · Cleanup rules · Report · MUST rows · What agents get wrong · References

When to run

Run it when:

  • A change already edits a file whose comments are over the length caps (LEN-01, LEN-02), carry bare process IDs (LNK-01), or hold an essay.
  • The owner names files for a sweep, or asks to bring a package down before its ratchet baseline is recorded (LEN-03).
  • A review flags an over-cap block, or a pointer left beside the essay it was meant to replace (RTE-09).

Do not run it when:

  • The text renders to users: --help, JSON Schema, MCP tool descriptions, argparse or commander help, or a published package's API docs. That is an interface change (SRF-01, SRF-02). It moves rationale into plain comments and may regenerate goldens, which this skill never does.
  • The file is a test, generated, vendored, a lock or manifest file, or a golden. Bare IDs in test files and test regions (LNK-01's bare-id-test key) go in a separate test-only change: list them in the report.
  • Another branch has the file in flight (see Scope).
  • The fix is code: a type that owns a guard (GRD-12), a lint to enable (GRD-09, GRD-10), a test to rename. Each is its own reviewable diff.
  • The repo's own rules protect the comment kind, for example a local rule that keeps section dividers or phase markers. The local rule wins until it is amended. Leave those comments and report the conflict.

Setup

  1. Find the rule's checks, in the project first, then in the global client directories: find . "$HOME/.claude" "$HOME/.config" -path '*/code-docs/checks/cleanup_check.py' -not -path '*/node_modules/*' 2>/dev/null | head -n 1. CHECKS below is the directory of that hit; any installed copy works. Read the code-docs.md index installed beside the code-docs/ folder. No hit means the rule is installed neither in the project nor globally: install it with grim add ghcr.io/ocx-sh/lore/code-docs. Where the client tool cannot install it, copy code-docs.md and the code-docs/ folder from the rule's source into the client's rules directory (such as .claude/rules/) with rsync -a --exclude __pycache__ or git archive, so no stale .pyc file rides along, commit that on its own before the cleanup, and run the find again.
  2. python3 "$CHECKS/cleanup_check.py" --self-test and python3 "$CHECKS/guard_recogniser.py" --self-test both exit 0.
  3. git status --porcelain lists nothing untracked that the cleanup did not create. cleanup_check.py reads every untracked file as an added path and fails it (CLN-05). An untracked file you did not create is the owner's: never delete or revert it. Run the cleanup from a clean worktree, or ask the owner to move the file.
  4. Pick the mode and set BASE=HEAD. The check fails any non-prose line that differs from the base, so the working tree holds only uncommitted cleanup: the touched files', or in a sweep one file's.
ModeWhenBefore each file
Touched files (default)Cleaning files the current change already editsCommit the change's code first
SweepThe owner named files, or asked for a package sweepCommit the previous file's cleanup, on a branch made for the sweep from the default branch
  1. Declare every library-kind package in .code-docs.json before ranking or cleaning anything: python3 "$CHECKS/comment_census.py" --root . --report lists undeclared packages that look published. The caps, and so the scope of the sweep, depend on the declaration.

Caps are the rule's defaults: plain blocks 5 lines, doc blocks 10, or 15 for a public item in a library-kind package. The census reads them, and the list of library packages, from .code-docs.json at the repo root. An adopter may override both there, and list under interface_files the sources a generator the checks do not know renders, such as a TS-to-JSON-Schema script. Their doc comments are then frozen like clap's.

Scope

  • Touched files: only the files the change already edits (CLN-08). Never widen to a neighbour because it looks worse.
  • Sweep: one file per commit (CLN-08). Rank packages with python3 "$CHECKS/comment_census.py" --root . --report and files with --over-cap. Before starting a file, and again before merge, skip it if either command prints anything:
FILE=src/example.rs; MAIN=origin/main; SELF=$(git branch --show-current)
git worktree list --porcelain | grep -e '^branch' | cut -d/ -f3- | grep -v -x -F -e "$SELF" | xargs -r -I{} git log -1 --format='{} %h %cs' "$MAIN..{}" -- "$FILE" || echo "in-flight check unavailable"
FILE=src/example.rs gh pr list --state open --limit 100 --json headRefName,files --jq '.[] | select(any(.files[]; .path == env.FILE)) | .headRefName' || echo "in-flight check unavailable"

The first names a worktree branch with commits on the file, the second an open pull request that edits it. Commit age settles nothing: a branch idle for a week still merges. in-flight check unavailable means unknown, never clear: list the file as unchecked in the report and have the owner confirm it before merge.

Procedure

Work one file at a time, one block at a time, top to bottom. Steps 1 to 3 read and classify every block. Steps 3 to 7 edit prose only, and only in over-cap blocks, blocks with a bare ID, and guards that fail GRD-01 or GRD-05. Every other block stays byte-identical. Steps 8 to 10 prove the edit.

1. List the blocks

FILE=src/example.rs
python3 "$CHECKS/comment_census.py" --root . --over-cap | grep -F -e "$FILE:"
python3 "$CHECKS/guard_recogniser.py" --root . | grep -F -e "$FILE:"
python3 "$CHECKS/linkage_check.py" ids --root . | grep -F -e "$FILE:"
python3 "$CHECKS/linkage_check.py" pointers --root . | grep -F -e "$FILE:"
git grep -n -F -e "${FILE##*/}" -- . ":(exclude)$FILE" ':(exclude)*.md'
MODULE=example; DOTTED=package.example   # the module without its extension, and its Python dotted path
git grep -n -F -e "$MODULE.js" -e "$MODULE'" -e "$DOTTED" -- . ":(exclude)$FILE" ':(exclude)*.md'
git grep -n -F -e "::: $DOTTED" -e "automodule:: $DOTTED" -- .

The first four rank the work. They do not bound it: every comment block in the file goes through step 3, flagged or not. The rest find every reader, under every name it can use: the path (a script, task file, CI config or test), the module name without its extension (a TS/JS import ending in .js), the Python dotted module path, and a doc-generator directive (mkdocstrings ::: pkg.module, Sphinx automodule::). Never exclude *.md from the directive search: a hit there means the module's docstrings render into published docs, so treat them as interface text (CLN-03). Read every hit; a name can match an unrelated file (_rest.py also matches 01_shellcheck_rest.py). One that reads the file owns its comment text: text a check asserts stays verbatim. Record each in the worklist.

2. Record every guard before you edit

Write a worklist in a scratch directory outside the repo. One row per guard clause: the line it guards, the constraint, the breaking edit, the consequence, and any owner the text claims (a test, a lint, a type). When unsure whether a clause is a guard, it is one.

The worklist feeds steps 5, 8 and 9. It is never an input to the check, which derives everything from the diff so that the editing agent never writes its own grading input (CLN-04).

3. Classify clause by clause, guard first

Split every block into clauses and tag each with references/decision-list.md (RTE-01). Check for a guard before anything else.

  • Delete a clause outright only when the list positively identifies it as narration, tautology, a banner, a bare ID or unquantified pure provenance (CLN-01). Argument and record paraphrase leave only through step 6.
  • Length, a history phrase or a Step N: opener identifies nothing.
  • A block the recogniser flags, a SAFETY: label, the repo's deferred-shortcut marker (for example ponytail:) and a comment another rule mandates (a discard rationale, a lint-suppression reason) are never deleted whole (GRD-06).
  • Text a repo check asserts (step 1) stays verbatim.
  • A clause that fits no row stays.

4. Rewrite each guard as fact plus consequence, at its line

  • Keep the constraint and the concrete consequence of breaking it. No edit goes below that floor (GRD-01). "Important", "careful" or "load-bearing" alone is not a consequence.
  • Keep nothing else in the guard: no history, no weighed alternatives, no bare ID. Name the tempting edit only when the constraint does not imply it, and name the sibling the code must not be unified with when that is the risk (GRD-02).
  • Split a guard block over 5 lines clause by clause. Every breaking edit the original forbade keeps its own sentence, at the line it guards. Never paraphrase several guards into one line (CLN-02, LEN-05). State each guard once (GRD-03).
  • Phrase it as a present-tense fact, never a command to the reader (GRD-05). History that still constrains an edit becomes a present-tense guard (RTE-11).
  • Put a caller-visible precondition in the doc comment and an implementation hazard in a plain comment at its line (GRD-04). Add no marker prefix. SAFETY: stays where the language uses it.
  • When the guard clauses alone exceed the cap, keep them all and tighten the wording. The cap never drops a guard.
  • Rewrite a clause as you move it. The check fails prose the recogniser does not flag that reappears, 80% or more intact, elsewhere in the same file (CLN-04).
  • Never invent a consequence the original does not state and the code does not show. Keep the original wording and list the block in the report.

5. Shrink a guard to its owner only after a planted edit fails it

A guard shrinks to a one-line pointer only when every breaking edit it names has a proven owner (CLN-07, GRD-07, RTE-03). An owner is an enabled lint, a scoped deny, a type check, or any test, named in the block or not. It is proven only when it passes on the unmodified scratch copy and fails on that exact edit applied to the same copy: a test already red before the edit proves nothing. Run the suite on the planted edit to find the candidates, then each red test alone:

SCRATCH=$(mktemp -d)/proof
git worktree add --detach "$SCRATCH" HEAD
export CARGO_TARGET_DIR="$PWD/target"   # reuse the warm build
# TS, no workspace packages: ln -s "$PWD/node_modules" "$SCRATCH/node_modules"
# TS, in a workspace: (cd "$SCRATCH" && npm ci --offline) or (cd "$SCRATCH" && pnpm install --offline --frozen-lockfile)
# apply ONE breaking edit from the worklist by hand inside $SCRATCH, then:
(cd "$SCRATCH" && timeout 1800 cargo test -p example_crate)
(cd "$SCRATCH" && timeout 1800 cargo test -p example_crate a_file_ttl_cannot_outlive_the_ceiling)
git worktree remove --force "$SCRATCH"

Swap the commands for the repo's runner, with a name filter for the second, such as uv run pytest -k NAME, npx vitest run FILE -t NAME or go test -run NAME ./pkg/, or the lint or type check itself (cargo clippy, tsc --noEmit, npx pyright). A shared environment that resolves the package back to the main tree, such as an editable install or a symlinked node_modules in a workspace, never sees the edit; install offline from the lockfile there instead.

OutcomeCounts as
The test prints a failure, or the lint or type check errors on the edited lineOwner proven for this edit
A build error from a leftover the edit orphaned, such as an unused import or binding under deny-warningsNo result. Remove the leftover and run again
Exit 124 with no test result lineProven only when the guard's stated consequence is the hang itself
The candidate already fails on the unmodified scratch copyNot an owner. It proves nothing about this edit
The owner stays greenNot an owner. The prose stays
Two tests, one failsOnly the failing test is an owner
The owner is compiled out on this host, such as a platform-gated assertUnproven here. Run it on its target platform, or the prose stays
  • The pointer names every test that failed on the edit and none that stayed green. Name the symbol, never a plan ID or a file:line (RTE-05).
  • Keep that one local line naming the owner, even when the owning construct states itself, such as assert_never(x) or a scoped #[deny(...)]. This skill never cuts a guard to nothing (RTE-03).
  • Any breaking edit without a proven owner keeps its mechanism, the edit and the consequence.
  • A mutation tool is optional support, never the proof. Budget one warm build per repo, then seconds per test.

6. Split an essay

  • Guard, contract and why clauses stay, rewritten per step 4.
  • An argument clause (alternatives weighed, the design story) goes one of three ways:
    • A tracked record already holds it in its own words: delete it, keep one pointer to that record, and pass the record to the check with --cites (RTE-09). The check lists --cites records for a human to confirm.
    • It argues a decision someone could reopen, and it is not limited in scope, time, risk and cost: append it to a decision record, and the code keeps one pointer (RTE-10).
    • Otherwise the choice is small: keep its conclusion as one why sentence when the code does not show it, and delete the rest.
  • A pointer is path/to/record.md#section. The file is tracked (LNK-02). The anchor is the shortest unique heading prefix, never a line number (LNK-03). Never point at a commit, a branch, a backup ref or a gitignored path (RTE-02).
  • A record is new, or receives additions only. Declare each one to the check with --relocation (CLN-05). The moved text must land there, and the paraphrase never stays beside the pointer (CLN-04).
  • An added record pointer is legal only when the block named that file before the edit, or the file is a --relocation or --cites record. The check fails any other (CLN-04, LNK-05).
  • Some clauses belong somewhere this diff may not touch. A universal negative belongs on the doc comment of the test that asserts it (RTE-04). An invariant true at every file a path-scoped rule matches belongs in that rule (RTE-07). Leave these where they are and list them in the report.

7. Remove bare IDs, carry every pointer

  • Delete a bare process ID and keep the constraint it labelled, in words (LNK-01). This covers the rule's families, the repo's own families (LNK-14), and a short label cited outside the block that defines it (LNK-13).
  • Add a record pointer in its place only when the same block already names that file, or when you have read the record and it holds the removed argument in its own words, passed to the check with --cites (LNK-05). Never guess which document a colliding ID meant. A pointer that replaces prose the ID labelled follows step 6.
  • Keep every file-qualified pointer (GRD-11):
    • A pointer to a record that moved: find the move and repoint it (LNK-10).
    • A dead pointer you cannot trace: leave it and report it.
    • A pointer to a commit, a branch or an untracked path is no pointer (RTE-02). Replace it with the constraint it stood for, stated in words.

8. Run the structural gate

python3 "$CHECKS/cleanup_check.py" --base "$BASE" --relocation docs/adr/0042-example-record.md --cites docs/design/decisions.md

Pass --relocation once per record that received text, and --cites once per record a new pointer names because it already held the removed argument (step 6). Drop a flag that has no record. Exit 1 lists blocking findings, including any added pointer step 6 does not allow: fix each one and run it again. Exit 0 may still print CLN-02 review items and the --cites records. Read each review item against the worklist: every breaking edit still has its own sentence.

Then check that no pointer was dropped (GRD-11). This prints the pointers the diff removed and did not add back:

MB=$(git merge-base "$BASE" HEAD)
comm -23 <(git diff -U0 "$MB" -- . ':(exclude)*.md' | grep -e '^-' | grep -v -e '^---' | grep -oE -e '[A-Za-z0-9_./-]+\.md' | sort -u) <(git diff -U0 "$MB" -- . ':(exclude)*.md' | grep -e '^+' | grep -v -e '^+++' | grep -oE -e '[A-Za-z0-9_./-]+\.md' | sort -u)

Then run the repo's full local check chain: every CI job for these files and every task-runner target (task check, make check, npm run scripts), not only what CI runs. Run it at BASE first, in a scratch worktree or before the first edit. Only a failure new since BASE counts; report the pre-existing reds. The chain must include:

  • the doctests: Rust cargo test --doc on each crate with a lib target, and Python pytest --doctest-modules where the repo uses doctests;
  • the doc build with warnings denied, which catches a broken intra-doc link: RUSTDOCFLAGS='-D warnings' cargo doc --no-deps;
  • the type checker, where a deleted @ts-expect-error or # type: ignore surfaces;
  • the linter.

9. Re-check the reason for every shortened guard

For each guard you shortened, run a fresh read-only session against an exported copy of the edited tree with no git history, so the probe can read neither the commit message that carries the guard's reason (step 10) nor the old comment through git. Ask the unled question first ("Why is it written this way? Could it be written differently without changing anything that matters?"), score it, and only then ask the led question naming the recorded breaking edit (CLN-06). Prompts, command and scoring are in references/reason-recheck.md.

  • It is SHOULD for touched files and required for every shortened guard in a sweep file.
  • Touched files run it before the commit. A sweep commits one file at a time and runs it once, over every guard the sweep shortened, before the final report.
  • A guard passes at mechanism plus consequence with a keep verdict. Anything lower goes back to step 4, rewritten or restored from the base. In a sweep, that fix is a new commit that passes step 8 again.

10. Commit

  • Commit the cleanup on its own, with only prose in it. Never fold it into a code commit, and never squash it into one later.
  • In a sweep, one file per commit, together with any record that file's prose moved to.
  • If the repo keeps the rule's baselines, record the drop in the same commit, never with --allow-regression, and let --check confirm it (LEN-03, LNK-01). Do it after step 8: cleanup_check.py fails any changed non-source path, baselines included.
python3 "$CHECKS/comment_census.py" --root . --update .code-docs-length.json
python3 "$CHECKS/linkage_check.py" ids --root . --update .code-docs-linkage.json
python3 "$CHECKS/linkage_check.py" pointers --root . --update .code-docs-linkage.json
python3 "$CHECKS/comment_census.py" --root . --check .code-docs-length.json
  • In the body, list each shortened guard with its proof: the owner that failed, or the re-check level (in a sweep, the final report carries the levels). Also list the records that received text and what was left for another change.

Never touch

cleanup_check.py fails the diff on each of these. Knowing them up front saves the rerun.

Line or pathWhat goes wrongRule
Code, including a comment that shares its line with codeA "comment-only" diff changes behaviourCLN-03
Doc text that renders to users (clap, schemars, click, typer, pydantic, MCP tools, files under interface_files)The user contract changes, and goldens driftCLN-03
Tool directives: @ts-expect-error, # noqa, # type: ignore, eslint-disable, nolint, //go:buildThe build or the lint result changesCLN-03
Licence headersLegal text changesCLN-03
Fenced code, a Python Example:/Examples: section, a reST :: literal block, and a >>> doctest line, inside doc commentsA test is deletedCLN-03
A Python docstring that is the function's only statementThe body empties and the file stops parsingCLN-03
Adding or deleting a source fileCode moves under cover of proseCLN-03
Test files and in-file test regions such as #[cfg(test)]A test is "tidied"CLN-05
Lock, manifest, generated, golden or snapshot filesDependencies or recorded output changeCLN-05
Any other non-source path, except a declared record that only growsUnreviewed edits ride alongCLN-05

Cleanup rules

MUST = Block. SHOULD = Warn: fix, or state why not in the commit body.

IDRuleVerificationSeverity
CLN-01Classify every block clause by clause, guard first. Delete only a clause positively identified as narration, tautology, a banner, a bare ID or unquantified pure provenance. A block that matches nothing, or that the recogniser flags, stays.Each deletion passes its decision-list test read against the code. cleanup_check.py fails a flagged or labelled block removed whole with no replacementMUST
CLN-02Before shortening a guard block over 5 lines, split it into clauses. Every clause naming a breaking edit and its consequence keeps its own sentence at the line it guards. Never paraphrase several guards into one line.List every edit the block forbade and find each surviving sentence. cleanup_check.py prints CLN-02 review items and never fails on themMUST
CLN-03Leave every non-prose line byte-identical: code, interface doc text, tool directives, licence headers, fenced code and doctests. A Python Example:/Examples: section and a reST :: literal block are frozen the same way as fenced code. A Python file that parsed at the base still parses.cleanup_check.py, then the repo's own build, doc, doctest and lint gateMUST
CLN-04Removed prose is gone: it never reappears at 80% token overlap or more in the file's other comments, a declared relocation lands in its record, and a pointer never sits beside the paraphrase it replaced. An added record pointer names a file the block named before the edit, a --relocation record, or a --cites record that already holds the removed argument. Every input comes from the diff, never from a list the editing agent wrote.cleanup_check.py, with --relocation and --cites once per record; a human confirms each --cites recordMUST
CLN-05Touch no test file or in-file test region, lock or manifest, generated or golden file, or non-source path other than a declared record that is new or only grows.cleanup_check.py. RECORD=docs/adr/0042-example-record.md; git diff --numstat "$BASE" -- "$RECORD" shows 0 deleted linesMUST
CLN-06Re-check every shortened guard in a fresh read-only session: the unled question first, scored for mechanism plus consequence, then the led question naming the recorded breaking edit. A may-change after a strong unled answer fails.Step 9, with references/reason-recheck.mdSHOULD; required for every shortened guard in a sweep
CLN-07Shrink a guard to a one-line pointer only when every breaking edit it names has an owner that failed on that edit in a scratch copy: an enabled lint, a scoped deny, a type check or any test, named in the block or not. The pointer names every test that failed and none that stayed green. An edit with no proven owner keeps its mechanism, edit and consequence.Step 5's planted-edit run, once per owner and editMUST
CLN-08Clean only the files the change already touches. A sweep runs one file per commit and skips any file another branch or an open pull request has in flight, checked before starting it and again before merge.The two commands under Scope print nothingSHOULD

Report

Return, per file:

  • over-cap lines before and after, from --over-cap;
  • blocks deleted, guards shortened (each with its owner proof or re-check level), and records that received text;
  • every CLN-02 review item, and how you resolved it;
  • every --cites record, for a human to confirm it holds the removed argument;
  • gate failures already red at BASE, and files whose in-flight check was unavailable;
  • what you left for another change: interface leaks, test-doc and rule candidates, dead pointers, local-rule conflicts, commented-out code, a clause the code contradicts, bare IDs in tests with the file's bare-id-test count, and any guard whose consequence you could not state.

MUST rows this procedure surfaces

Restated so a cleanup run without the rule loaded still reports them with the right ID. Cleanup rules and the installed rule hold the text and full verification.

#FindingRule
1A block deleted without being positively identified as narration, tautology, a banner, a bare ID or unquantified pure provenanceCLN-01
2A recogniser-flagged block, a SAFETY: label, a deferred-shortcut marker, or a comment another rule mandates, removed whole with no replacementCLN-01, GRD-06
3A block over 3 lines routed whole instead of clause by clauseRTE-01
4A guard block over 5 lines shortened without a clause split, or several guards paraphrased into one lineCLN-02
5A guard cut below constraint plus consequenceGRD-01
6A non-prose line changed: code, interface text, a directive, a licence header, fenced code or a doctestCLN-03
7Removed prose survives elsewhere in the file, a declared relocation did not land, or a pointer sits beside the paraphrase it replacedCLN-04
8The diff touches a test or test region, a lock or manifest, a generated or golden file, or a non-source path other than a declared record that only growsCLN-05
9A guard shrunk to a pointer without a failing planted-edit run for every breaking edit, or a pointer naming a test that stayed greenCLN-07, GRD-07, RTE-03
10A file-qualified pointer dropped without the same target reappearingGRD-11
11A record pointer added to a file the block did not name before the edit, that is neither a --relocation nor a --cites recordCLN-04, LNK-05
12A pointer to a commit, a branch, a backup ref or a gitignored pathRTE-02
13A record pointer that does not resolve to a tracked fileLNK-02

What agents get wrong

Ranked, most frequent first. Each mode, its tell and its catch are in references/failure-modes.md.

  1. Collapsing a guard bundle into one paraphrase, dropping the consequence clause first.
  2. Deleting by category or length: "long means essay", "past tense means history", "Step N: means narration".
  3. Crediting an owner by its name. A test named after the constraint often stays green on the breaking edit.
  4. Adding the pointer and keeping the essay beside it.
  5. Reporting success from its own reading instead of the check and the re-check.
  6. Incidental edits outside prose: a help string, a directive, a doctest.

References

ReadWhen
references/decision-list.mdStep 3 and 4: tagging a clause, writing a guard, choosing the register, meeting a cap
references/reason-recheck.mdStep 9: the unled and led prompts, the session command, the scoring levels
references/failure-modes.mdBefore a sweep, or when a check fails and the cause is unclear

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.