Say That a Path Grep Misses a Description of the File - #660
Conversation
The sweep told a reader to grep the path and read every hit, which finds uses of the file and cannot find a description of it. A layout bullet calling a deleted script "the apply script" names no path, so it survives every search for one. Measured rather than predicted. Blog's resync deleted its carried configure.sh, swept the path across the tree, read every hit, and merged, and GOVERNANCE.md "Repository Layout" still described repo-config/ as holding the apply script. The sweep was run correctly and the rule was what fell short. Both statements of the remedy gain the same sentence, since one rule stated two ways across these two files is the defect #656 already had to fix once. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR tightens the documented deletion-sweep procedure so it no longer relies solely on path-based greps (which catch usages but can miss prose descriptions of a file/directory), by adding an explicit step to reread the repository-description docs after the grep.
Changes:
- Update
RESYNC.mddeletion workflow to add a post-grep step: read the files that describe what the repo holds, to catch stale descriptions that don`t name the deleted path. - Update
AUDIT.mdconvergence guidance to include the same post-grep step for any deletion. - Add a short, measured example motivating why a path grep can miss stale layout prose.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| RESYNC.md | Extends the deletion sweep guidance to include checking repo-description docs after grepping for the deleted path. |
| AUDIT.md | Mirrors the deletion sweep guidance update in the audit convergence procedure. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The pull request body claimed both files carry an identical sentence. They did not: one read "since a grep for the path finds uses" and the other "because the grep finds uses", and only the second was bold. What was actually verified was that a substring appeared in both, which is a narrower fact than the claim made of it. The connective now matches, so the rule sentence is the same in both modulo the sentence-initial capital and the emphasis RESYNC.md gives it as a step in a procedure. The evidence sentence after it still differs, deliberately: the step-by-step file carries the measured case and the reference file does not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The previous commit rewrote the file through Python's read_text and write_text, which silently converted every line ending to LF while this repo's editorconfig sets CRLF. The content was unaffected: git diff --ignore-cr-at-eol is empty against the previous commit, so only the endings moved. editorconfig-checker is the only gate that catches this. prose_lint, markdownlint-cli2 and the eol check all passed on the converted file, and the push went out before its exit code was read. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
AUDIT.md:169
- The PR description says both files carry an identical sentence for this new instruction, but here the wording is embedded mid-sentence (lowercase "then" after a comma) and the follow-up "layout section" example doesn't name where to look. Splitting this into a separate sentence starting with "Then" (matching RESYNC.md) and naming the concrete location (e.g.
GOVERNANCE.md"Repository Layout") makes the procedure unambiguous and keeps the two documents in sync.
- **Any deletion sweeps the inbound references to the path, and the sweep is part of the deletion rather than follow-up.** This governs every removal and not only a `hub-only:` one, because nothing about it depends on who owned the file: the removal is one edit and finishing the job usually takes several more, so grep the path tree-wide first and read every hit, then read the files whose job is to say what the repo holds, since a grep for the path finds uses of the file and misses descriptions of it. A layout section calling a deleted script "the apply script" names no path and survives every search for one. A link whose target has an equivalent elsewhere is re-pointed at it, the hub's copy being that equivalent for a hub-hosted file, a **runnable command** citing the path is rewritten to the invocation that still works, and a mention with no equivalent anywhere is removed along with its reference definition, which [GOVERNANCE.md "Documentation Style Conventions"][governance-documentation-style] requires because an orphaned definition fails the no-unused-defs rule. Measured rather than hypothetical, in both directions: retiring `configure.sh` makes five lines of one repo's carried `repo-config/README.md` wrong, two of them commands a reader would run, and deleting a repo-owned nested `AGENTS.md` took three edits across two files, where removing the inline link alone tripped `MD053` on the definition it orphaned and would have failed CI rather than merely breaking prose.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
RESYNC.md:76
- The PR description says both files carry the identical sentence; in RESYNC.md that sentence is bolded, so it isn't literally identical to the AUDIT.md wording. If exact matching is intentional (e.g., to simplify future audits/grep), make the sentence formatting consistent by removing the bold markers here (or applying the same formatting in both files).
- **Sweep every inbound reference to the path, and count that as part of the deletion.** This governs any deletion rather than only a `hub-only:` finding. The three bullets above turn on a disposition and so belong to this detector, where the sweep turns on nothing: it applies the same way to a file the repository owns and removes for reasons of its own, which is where the fleet first hit it. Deleting the file is one edit and finishing the job usually takes several more, so grep the path tree-wide before deleting and read every hit. **Then read the files whose job is to say what the repo holds, since a grep for the path finds uses of the file and misses descriptions of it.** A layout section calling a deleted script "the apply script" names no path, so it survives every search for one and goes stale silently. This is measured rather than predicted: a resync deleted a carried script, swept its path across the tree, merged, and left `GOVERNANCE.md` "Repository Layout" still describing the directory as holding it. Three shapes appear among the hits and they are fixed differently. A link whose target has an equivalent elsewhere is **re-pointed** at it, the hub's copy being that equivalent for a hub-hosted file, since a pointer that resolves nowhere teaches a reader that a pointer in carried text is decorative. A **runnable command** citing the deleted path is rewritten to the invocation that still works, and this is the one that costs a reader real time, because a documented command fails where a dead link merely disappoints. A mention with no equivalent anywhere is **removed** rather than re-pointed, and removing a reference-style link removes its definition with it, per [GOVERNANCE.md "Documentation Style Conventions"][governance-documentation-style], since an orphaned definition fails the no-unused-defs rule and is a gate failure rather than untidiness.
Two improvements the reviewer identified, and the claim that caused the churn. The instruction was embedded mid-sentence in AUDIT.md, opening on a lowercase "then" after a comma, where RESYNC.md gave it its own sentence. In a procedure a step that hides inside another clause is a step a reader skips, so it is a sentence now. It also said only that a layout section can go stale without naming one. It names GOVERNANCE.md "Repository Layout", which is the section that actually went stale, so a reader knows where to look rather than what to look for. The two files still differ, deliberately, and the pull request description is what was wrong rather than the text. They state the same rule in the same words and carry their own emphasis and their own evidence, which is the difference between a reference document and a procedure someone follows step by step. Claiming an identical sentence was a claim wider than the substring match that was actually run, and chasing it produced two rounds of edits to content that was already correct. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ptr727
commented
Aug 10, 2026
Both suppressed findings answered together, since they and the two threads all trace to one cause: the description claimed an identical sentence and that claim was false. What was actually verified was that the substring The two concrete suggestions inside those findings were both right and are taken in ed00ea7:
The bold in RESYNC.md stays. Exact matching was never the intent, so the formatting difference is not a defect to normalize away: that file is a procedure and the sentence is a step in it, where Since this PR is about a rule that missed something, worth recording that the rule it fixes has now been confirmed twice from outside: the ESPHome-Config agent reports the identical "and the apply script" wording sitting unswept in its own |
Uh oh!
There was an error while loading. Please reload this page.
Two squashes. **Merge with a merge commit, never a squash, and never with `--delete-branch`** — this PR's head *is* `develop`. | PR | What | |---|---| | [#659](#659) | A backlog entry recording that a disproof about carried text has nowhere fleet-wide to live, after the same false claim was disproved twice about one canonical | | [#660](#660) | The deletion sweep now says a path grep finds *uses* of a file and misses *descriptions* of it | ## Why [#660](#660) wants promoting rather than waiting It corrects a rule that is actively being followed. Blog's resync ran the sweep correctly, merged, and still left `GOVERNANCE.md` "Repository Layout" describing `repo-config/` as holding *"the apply script"* — a file it had just deleted. The ESPHome-Config agent has since confirmed the identical wording sits unswept in its own `Repository Layout`, **ahead of its own `configure.sh` retirement**. Its eleven grep hits across five files are a floor rather than a count. Promoting this puts the corrected rule in front of that work rather than behind it. ## Verification on the merged head `spec/validate.py` OK, `spec/audit.py --selftest` PASS, 557 script tests OK, `editorconfig-checker` clean, `repo_gate --check eol` clean, working tree clean. One defect of my own was found and fixed inside [#660](#660): a Python `read_text`/`write_text` rewrite silently converted `RESYNC.md` to LF against this repo's CRLF. Restored in `a12cd33` and verified content-identical with `git diff --ignore-cr-at-eol`. `editorconfig-checker` is the only gate that sees that class. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
A pre-release check that found something, rather than a change anyone asked for. ## Problem `HISTORY.md`'s Version 2.0 entry enumerates what this repository became: *"the shared fleet rules, a machine-readable `spec/`, the fleet `registry/`, per-repo audit `reports/`, branch rulesets, and the `AUDIT.md` convergence procedure."* Three things shipped since are **peers of the items in that list** and appear nowhere in it: - **`RESYNC.md`**, now the third procedure an agent routes between, not a detail of the second - **The host tool contract** and its version floors, `spec/host-tools.json` plus a carried `host-tools.json` per repository - **The derived detector** for files the hub hosts rather than carries, so a retired file is found rather than remembered ## Why it was worth catching first A patch release cut against this entry would have published a changelog whose summary omits the session's main deliverable. A reader asking how a repository resyncs would find an enumeration naming only the procedure that *measures*. `HISTORY.md` is per minor version rather than per patch, so nothing is owed for a routine `2.0.x`. What is owed is that the 2.0 summary stay true about what 2.0 contains, and it had stopped being true. ## The pattern, third time today This is the same shape as the `spec/` enumerations corrected in [#653](#653) and the `Repository Layout` bullet corrected downstream in Blog: **a list that was accurate when written, going stale under a change that never mentioned it, with no gate that reads it.** The recurrence is worth noting on its own. Three instances in one session suggests enumerations are a standing hazard rather than three accidents, and the deletion sweep's new "read the files whose job is to say what the repo holds" ([#660](#660)) covers deletions only. Additions have no equivalent instruction. Not fixing that here. ## Verification The `README.md` and `HISTORY.md` openings must mirror per `spec/readme-structure.md`, so that was checked rather than assumed: titles match, taglines match, using the audit's own extraction. `cspell` on both gated files clean, `prose_lint --diff HEAD` clean, `markdownlint-cli2` clean, `editorconfig-checker` clean, CRLF preserved byte-wise. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
A gap in the deletion sweep, found by running the sweep correctly and still leaving a stale claim behind.
Problem
AUDIT.mdsection 10 andRESYNC.mdsection 4 tell a reader to "grep the path tree-wide first and read every hit." That finds uses of a file and cannot find a description of it.A layout bullet calling a deleted script "the apply script" names no path, so it survives every search for one and goes stale silently.
Measured, not predicted
Blog's resync deleted its carried
repo-config/configure.sh, swept the path across the tree, read every hit, and merged.GOVERNANCE.md"Repository Layout" still describedrepo-config/as holding "branch rulesets and the apply script".The sweep was run correctly. The rule was what fell short. It was caught one PR later, by eye, while adding an unrelated bullet to the same section.
Since then the ESPHome-Config agent has confirmed the same shape sitting in its own tree, unswept, ahead of its own
configure.shretirement: itsRepository Layoutbullet carries the identical wording. Its eleven grep hits across five files are a floor rather than a count.Change
Both files gain the same instruction, in the same words: after the path grep, read the files whose job is to say what the repo holds.
They are not byte-identical, and that is intended. An earlier version of this description claimed an identical sentence, which was wrong twice over: the wording differed, and what had actually been verified was that a substring appeared in both. That overclaim generated four review findings and two rounds of edits to content that was already correct. What is true is narrower and is the thing that matters: the same rule, stated in the same words, with each file carrying its own emphasis and its own evidence.
RESYNC.mdbolds it as a procedure step and carries the measured case;AUDIT.mdstates it as a reference and names the stale section inline.Two further improvements from review, both real:
AUDIT.mdinstruction was embedded mid-sentence on a lowercase "then". In a procedure, a step hidden inside another clause is a step a reader skips. It is its own sentence now.GOVERNANCE.md"Repository Layout", the section that actually went stale, so a reader knows where to look rather than only what to look for.What this does not claim
No mechanical check, because a description names nothing a grep can anchor to. It tells the reader where to look, which is narrower and more honest than "read everything."
Verification
prose_lint --diff HEAD,repo_gate --check eol,markdownlint-cli2on both files,editorconfig-checker: clean.One defect of my own in this branch, fixed in
a12cd33: a Pythonread_text/write_textrewrite silently convertedRESYNC.mdto LF against this repo's CRLF, and the push went out beforeeditorconfig-checker's exit was read. Restored and verified content-identical withgit diff --ignore-cr-at-eol. Every later edit here usesread_bytes/write_bytesand gates before committing.🤖 Generated with Claude Code