Skip to content

Commit c2ce145

Browse files
ptr727claude
andauthored
Encode the README Structure, Links, and Tools as Auditable Rules (#632)
The README spec was advisory: `readme.sections` sat at verdict `intent`, so nothing mechanically checked section presence, order, shields, or link naming. It is now five `letter` checks driven by declared data. Two wanted changes land with it. The License section closes the file and carries the license shield, which 15 of the 16 repos with a License section already did. The first line under the H1 is the tagline, and it alone carries the 100-character link-free rule and the mirrors, so a README may say more about itself above the fold. Settled alongside them from a survey of all 22 non-archived non-fork repos: a Table of Contents in every README, `Use Cases` renamed to `Overview` with no aliases, `3rd Party Tools` required, and `Questions or Issues` required in a public repo. Reference links gain a closed five-group set, a suffix per kind, and canonical names for the destinations every repo has. `spec/third-party-tools.json` declares 40 shared tools so a tool two repos use is linked and described identically in both. Every rule was measured against the fleet before it shipped, and the corpus run corrected the model three times before the pull request opened: shields keyed on alt text flagged three repos for caption wording, a coverage class would have told 7 repos to add a badge nobody chose, and requiring both Docker version shields is wrong for NxWitness, which carries 40 across six images and four channels that are not `develop`. This repo's own README reports zero findings. The fleet backlog the checks report is 214 findings across 22 repos, recorded in `TODO.md`, and no downstream repo is edited here. The Copilot loop ran 14 rounds for 21 findings, all accepted, of which 18 were in suppressed blocks and 6 were defects introduced by earlier fixes on this branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 9b73d1a commit c2ce145

13 files changed

Lines changed: 1179 additions & 61 deletions

‎AUDIT.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ A check with `intentRef`/`workflowRef` points at the prose section that owns the
5858
-**repo-setup** - every required secret for the repo's publish mechanisms is configured, and no forbidden secret is present (per [`spec/secrets.json`][secrets]).
5959
-**linter-parity** - one config per linter (`.markdownlint-cli2.jsonc`, `cspell.json`, ruff/pyright, editorconfig/csharpier, actionlint) drives the editor extension, the CLI, and CI, and CI runs each.
6060
-**recurring-violations** - comments concise and non-narrative, ASCII only (no em-dash, no smart quotes), US spelling, line endings per `.editorconfig`. These are frequent regressions, so this dimension is high priority and always runs, and each check is grep-able (see below).
61-
-**readme-structure** - the README follows [`spec/readme-structure.md`][readme-structure] (applicable sections, in order).
61+
-**readme-structure** - the README follows [`spec/readme-structure.md`][readme-structure] (applicable sections, in order). Mechanically checked against the declared model in [`spec/readme-sections.json`][readme-sections]: required sections present, declared sections in their relative order, `License` last, the shields each deliverable implies, the license shield in the closing License section, and the tagline and its mirrors. A heading the model does not name is dropped before the order comparison, so a repo-specific section is never a finding.
6262

6363
## 5. Assert the Actions Implement WORKFLOW.md
6464

@@ -161,6 +161,7 @@ The convergence model: the hub audits and the agent **applies** the fixes via ta
161161
[governance-branching-model]: ./GOVERNANCE.md#branching-model
162162
[governance-pr-review-etiquette]: ./GOVERNANCE.md#pr-review-etiquette
163163
[project-types]: ./spec/project-types.json
164+
[readme-sections]: ./spec/readme-sections.json
164165
[readme-structure]: ./spec/readme-structure.md
165166
[repo-config]: ./repo-config/
166167
[repo-config-settings]: ./repo-config/settings.json

‎CODESTYLE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ These apply repo-wide, in every directory:
3636
1.**Markdown linting**: All `.md` files must be lint-clean (error and warning free) via the VS Code `markdownlint` extension. [`.markdownlint-cli2.jsonc`][markdownlint-cli2] at the repo root is the single source of truth, and the davidanson `markdownlint` extension and a command-line `markdownlint-cli2` run both read it, so the IDE and CLI stay in lock-step. Rules it deliberately disables (e.g. `MD013` line-length) are **intentional**, so do not "fix" them. `MD033` inline HTML stays **enabled**: HTML comments are permitted (markdownlint does not flag them), `details` and `summary` are allowed because a GitHub collapsible has no Markdown equivalent, every other element is flagged, and anything with a native Markdown equivalent uses the Markdown. Fix violations at the source rather than disabling rules.
3737
2.**Spelling**: All spelling must be clean via the CSpell VS Code integration, and words must be correctly spelled in **US English** (the repo-wide convention, per [GOVERNANCE.md][governance]). The shared `cspell.json` sets `"language": "en-US"` so British spellings are flagged, where a bare `"en"` accepts both US and British and silently passes the wrong spelling. Project-specific terms go in the shared `cspell.json``words` list, the single source of truth the extension, CLI, and CI all read. The `.code-workspace` must **not** carry its own `cspell.words`/`cSpell.words` block, and when externalizing words into `cspell.json`, delete any word list left in the workspace (a leftover one duplicates the list and silently drifts).
3838
3. **Spelling CI scope**: The enforced CI spell-check gate covers **`README.md` and `HISTORY.md` only**, because these are the files every repo visitor sees, so they must be clean. It is deliberately **not** all `**/*.md`: repos carry many Markdown files full of technical terms, and gating every one of them would mean endlessly padding `cspell.json` just to keep CI green. Broad, live spell-checking across any file (source, Markdown, text) is the **cspell editor extension's** job, so typos still surface to whoever is editing. A repo owner **may** widen their own CI file list, but README + HISTORY are the default. Keep the CI workflow, the `Lint: Spelling` VS Code task, and the GOVERNANCE.md cspell one-liner on the same file list. The list is explicit (not a glob), so a repo that ships no `HISTORY.md` (e.g. one with no changelog) must drop it from all three surfaces and gate on `README.md` alone, since cspell errors on a listed file that does not exist. Markdown *linting* (item 1) stays repo-wide `**/*.md`, which does not choke on technical terms.
39-
4.**`HISTORY.md` mirrors the README opening**: `HISTORY.md` is the maintainer-curated changelog and opens as the README's twin, carrying the same `# <Title>` (without the README's ToC-omit comment) and the same intro paragraph copied verbatim, then a `## Release History` section. The mirrored opening keeps the project identity consistent for a reader who lands on the changelog directly. The audit checks that the title and intro match the README, with HTML comments stripped.
39+
4.**`HISTORY.md` mirrors the README opening**: `HISTORY.md` is the maintainer-curated changelog and opens as the README's twin, carrying the same `# <Title>` (without the README's ToC-omit comment) and the same **tagline**copied verbatim, then a `## Release History` section. The tagline is the first line after the README's H1, and it is the whole of the mirror: a README may carry further paragraphs below it, explaining the project to a reader before the fold, and the changelog does not repeat them, because it opens on the identity and then goes straight to the releases. The mirrored opening keeps the project identity consistent for a reader who lands on the changelog directly. The audit checks that the title and the tagline match the README, with HTML comments stripped.
4040
5.**"Markdown" is the format's name**: The format is a proper noun, so prose capitalizes it, meaning a Markdown file, a Markdown link, and the Markdown a surface renders. Lowercase is for the strings a machine reads and for nothing else: a tool or package name (`markdownlint`, `markdownlint-cli2`, `yzhang.markdown-all-in-one`), a settings key (`markdown.extension.toc.levels`), a heading anchor (`#markdown-and-spelling`), an identifier in code, and a file extension. A hyphenated compound in prose is prose, so it capitalizes too (Markdown-only), which is the boundary a mechanical sweep gets wrong, since it reads the hyphen as the mark of an identifier. What this settles is the mix rather than either spelling, because a file carrying both gives the next author no default to follow and a reviewer a finding to raise on whichever one it wrote last. The rule lives here because every repo carries this file, so the convention arrives with it rather than being re-decided per repo.
4141

4242
## .NET

‎GOVERNANCE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ Contributors commit to this repo with signed commits. The SSH-signing setup live
424424

425425
Every repo's GitHub repository details (the About panel) follow a fixed convention so the fleet stays consistent and self-describing.
426426

427-
-**Description** matches the README's first non-empty line after the `#` H1 heading, as plain text, stripping Markdown links (`[text](url)` and `[text][ref]` become `text`) since a description is not rendered. The README is the source of truth: set the description from it (`gh api -X PATCH repos/<owner>/<repo> -f description=...`), never the reverse. When the current description is *more specific* than the README (a chip revision or variant the README omits), surface the drift to the maintainer rather than silently discarding the detail, and the fix is to sharpen the README so the description follows it. Keep the line at most **100 characters**, Docker Hub's short-description cap and the tightest surface it feeds. For a repo that publishes a Docker image, the **Docker Hub short description** mirrors the same README intro line, so one canonical sentence carries to the README, the About panel, and Docker Hub alike.
427+
- **Description** matches the README's **tagline**, its first non-empty line after the `#` H1 heading, as plain text, stripping Markdown links (`[text](url)` and `[text][ref]` become `text`) since a description is not rendered. It is that one line and not the paragraph it opens: a README may carry further paragraphs below the tagline, and no mirror reads them. The README is the source of truth: set the description from it (`gh api -X PATCH repos/<owner>/<repo> -f description=...`), never the reverse. When the current description is *more specific* than the README (a chip revision or variant the README omits), surface the drift to the maintainer rather than silently discarding the detail, and the fix is to sharpen the README so the description follows it. Keep the line at most **100 characters**, Docker Hub's short-description cap and the tightest surface it feeds. For a repo that publishes a Docker image, the **Docker Hub short description** mirrors the same tagline, so one canonical sentence carries to the README, the About panel, and Docker Hub alike. Docker Hub receives it from the About panel, which the docker-readme task reads at publish time, so an About panel left diverged from the README is carried onward rather than corrected there.
428428
-**Topics** are optional, and any that are present match the repo's actual content. Do not invent topics to fill the field.
429429
-**Include in the home page**: Releases on, Deployments off, Packages off. These toggles are UI-only, since the REST and GraphQL APIs neither read nor write them, so they are set by hand and cannot be audited through `gh`.
430430

‎README.md‎

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Agent enablement for a fleet of repositories: autonomy and repeatable quality in
44

55
## Build and Distribution <!-- omit from toc -->
66

7-
-**Source Code**: [GitHub][projecttemplate-link] for source, issues, discussions, and CI/CD pipelines.
7+
-**Source Code**: [GitHub][github-link] for source, issues, discussions, and CI/CD pipelines.
88
-**Versioned Releases**: [GitHub Releases][releases-link] for version-tagged source archives.
99

1010
### Build Status <!-- omit from toc -->
@@ -66,6 +66,7 @@ Nothing here is installed as a dependency. The rules are read, the baseline is c
6666
-[For Workflows](#for-workflows)
6767
-[Questions or Issues](#questions-or-issues)
6868
-[Development Environment Setup](#development-environment-setup)
69+
-[3rd Party Tools](#3rd-party-tools)
6970
-[License](#license)
7071

7172
## What This Repo Is
@@ -253,6 +254,20 @@ Contributors sign every commit. See [docs/ssh-signing.md][ssh-signing] for SSH c
253254

254255
Changes land the same way every fleet change does: a feature branch, a squash merge into `develop`, a Copilot review loop driven to green, and a merge only with the maintainer's explicit approval. The backlog is [`TODO.md`][todo], which holds the work that is ready to pick up along with the reasoning behind each item, so read it before proposing something it already covers.
255256

257+
## 3rd Party Tools
258+
259+
The third-party tools, libraries, and actions this project depends on.
260+
261+
| Tool | Role |
262+
| --- | --- |
263+
|[cspell][cspell-link]| Spell checker. |
264+
|[editorconfig-checker][editorconfig-checker-link]| Line-ending and whitespace linter. |
265+
|[GitHub Actions][github-actions-link]| CI and automation runner. |
266+
|[GitHub Dependabot][dependabot-link]| Dependency update bot. |
267+
|[Markdown All in One][markdown-all-in-one-link]| Markdown editing extension. |
268+
|[markdownlint-cli2][markdownlint-link]| Markdown linter. |
269+
|[Nerdbank.GitVersioning][nbgv-link]| Version computation from git height. |
270+
256271
## License
257272

258273
Licensed under the [MIT License][license]\
@@ -273,6 +288,15 @@ Licensed under the [MIT License][license]\
273288
[license-shield]: https://img.shields.io/github/license/ptr727/ProjectTemplate?label=License
274289
[releases-build-shield]: https://img.shields.io/github/actions/workflow/status/ptr727/ProjectTemplate/publish-release.yml?event=schedule&logo=github&label=Releases%20Build
275290

291+
<!-- Distribution -->
292+
293+
[actions-link]: https://github.com/ptr727/ProjectTemplate/actions
294+
[commits-link]: https://github.com/ptr727/ProjectTemplate/commits
295+
[discussions-link]: https://github.com/ptr727/ProjectTemplate/discussions
296+
[github-link]: https://github.com/ptr727/ProjectTemplate
297+
[issues-link]: https://github.com/ptr727/ProjectTemplate/issues
298+
[releases-link]: https://github.com/ptr727/ProjectTemplate/releases
299+
276300
<!-- Repo -->
277301

278302
[agent-safety]: ./host-setup/agent-safety/README.md
@@ -316,9 +340,10 @@ Licensed under the [MIT License][license]\
316340

317341
<!-- External -->
318342

319-
[actions-link]: https://github.com/ptr727/ProjectTemplate/actions
320-
[commits-link]: https://github.com/ptr727/ProjectTemplate/commits
321-
[discussions-link]: https://github.com/ptr727/ProjectTemplate/discussions
322-
[issues-link]: https://github.com/ptr727/ProjectTemplate/issues
323-
[projecttemplate-link]: https://github.com/ptr727/ProjectTemplate
324-
[releases-link]: https://github.com/ptr727/ProjectTemplate/releases
343+
[cspell-link]: https://cspell.org
344+
[dependabot-link]: https://github.com/dependabot
345+
[editorconfig-checker-link]: https://github.com/editorconfig-checker/editorconfig-checker
346+
[github-actions-link]: https://github.com/actions
347+
[markdown-all-in-one-link]: https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one
348+
[markdownlint-link]: https://github.com/DavidAnson/markdownlint-cli2
349+
[nbgv-link]: https://github.com/dotnet/Nerdbank.GitVersioning

0 commit comments

Comments
 (0)