What happened
scripts/prose_lint.py --check dead-path reports a Markdown mention of a path git once tracked and the tree no longer holds. In a downstream repository that has retired repo-config/configure.sh per the retire disposition in spec/divergences.json, that path is exactly this shape: git once tracked it, the tree no longer holds it, and the carried docs still name it, correctly, as the hub's copy that a repository reaches rather than carries.
Observed on ptr727/PhotoCleaner#51 (the develop -> main promotion after the resync in ptr727/PhotoCleaner#50). The prose-gate action diffs the promotion against origin/main, so the mentions that landed on develop in ptr727/PhotoCleaner#49 (which retired the file) come into scope and fail the required Validate job / Lint job:
AUDIT.md:71: dead-path: path 'repo-config/configure.sh' is deleted from this tree -> re-point, rewrite, or remove the stale mention
GOVERNANCE.md:29: dead-path: path 'repo-config/configure.sh' is deleted from this tree -> re-point, rewrite, or remove the stale mention
repo-config/README.md:5: dead-path: path 'repo-config/configure.sh' is deleted from this tree -> re-point, rewrite, or remove the stale mention
Two of the three hits are hub-owned text the repository cannot reword:
GOVERNANCE.md "Repository Boundaries and Write Safety" (verbatim section) says "the hub's own repo-config/configure.sh does exactly this, and a repository reaches it there rather than carrying a copy".
repo-config/README.md (verbatim whole file) names repo-config/configure.sh as the hub's script on line 5, and again on lines 7 and 26.
The third, AUDIT.md, is an intent carry a repo could reword, but the sentence is the same claim: run the hub's repo-config/configure.sh.
The rule's own exemption, carried_paths(), reads the scanning tree's spec/files.json, which no downstream repository carries, so downstream the exemption set is empty and the hub-hosted class has no way to be recognized. In the hub itself the file exists, so the rule is silent there and the gap only shows once a repository has done what RESYNC.md section 4 tells it to do.
Why it matters
Every repository that retires repo-config/configure.sh and then promotes develop -> main will hit this at the promotion gate, where the diff base is main. A feature PR into develop may not see it (the mentions are already on develop), so it surfaces at the step with the least room to fix it. The only local escape is a ruleset bypass by the maintainer, which is the wrong remedy for a linter false positive.
Options
- Recognize the hub-hosted class in the rule. The prose-gate action bundles
prose_lint.py from the hub, so it can bundle the hub's hub-hosted path set alongside it (the retire dispositions in spec/divergences.json, or the derived hub-tracked-minus-files.json set the audit's carried-scope dimension already computes) and treat a mention of one of those paths as a pointer to the hub rather than a dead path.
- Reword the two verbatim units to name the script without a path (for example "the hub's configure script"), so the mention is not path-shaped. This trades a precise reference for lint silence and reintroduces the "layout section that names no path" blind spot
RESYNC.md section 4 warns about, so it is the weaker option.
- Both, if the rule change is wanted anyway and the wording is judged clearer without the path.
Reported from a hub checkout at 0e84805, run stamp audit run 2026-08-15T14:40:08Z | hub 0e84805.
What happened
scripts/prose_lint.py --check dead-pathreports a Markdown mention of a path git once tracked and the tree no longer holds. In a downstream repository that has retiredrepo-config/configure.shper theretiredisposition inspec/divergences.json, that path is exactly this shape: git once tracked it, the tree no longer holds it, and the carried docs still name it, correctly, as the hub's copy that a repository reaches rather than carries.Observed on ptr727/PhotoCleaner#51 (the
develop -> mainpromotion after the resync in ptr727/PhotoCleaner#50). The prose-gate action diffs the promotion againstorigin/main, so the mentions that landed ondevelopin ptr727/PhotoCleaner#49 (which retired the file) come into scope and fail the requiredValidate job / Lint job:Two of the three hits are hub-owned text the repository cannot reword:
GOVERNANCE.md"Repository Boundaries and Write Safety" (verbatim section) says "the hub's ownrepo-config/configure.shdoes exactly this, and a repository reaches it there rather than carrying a copy".repo-config/README.md(verbatim whole file) namesrepo-config/configure.shas the hub's script on line 5, and again on lines 7 and 26.The third,
AUDIT.md, is an intent carry a repo could reword, but the sentence is the same claim: run the hub'srepo-config/configure.sh.The rule's own exemption,
carried_paths(), reads the scanning tree'sspec/files.json, which no downstream repository carries, so downstream the exemption set is empty and the hub-hosted class has no way to be recognized. In the hub itself the file exists, so the rule is silent there and the gap only shows once a repository has done whatRESYNC.mdsection 4 tells it to do.Why it matters
Every repository that retires
repo-config/configure.shand then promotesdevelop -> mainwill hit this at the promotion gate, where the diff base ismain. A feature PR intodevelopmay not see it (the mentions are already ondevelop), so it surfaces at the step with the least room to fix it. The only local escape is a ruleset bypass by the maintainer, which is the wrong remedy for a linter false positive.Options
prose_lint.pyfrom the hub, so it can bundle the hub's hub-hosted path set alongside it (theretiredispositions inspec/divergences.json, or the derived hub-tracked-minus-files.jsonset the audit'scarried-scopedimension already computes) and treat a mention of one of those paths as a pointer to the hub rather than a dead path.RESYNC.mdsection 4 warns about, so it is the weaker option.Reported from a hub checkout at
0e84805, run stampaudit run 2026-08-15T14:40:08Z | hub 0e84805.