Make carried template docs repo-agnostic; codify the no-cross-reference rule - #344
Merged
Conversation
…ce rule A file the fleet carries verbatim must name no sibling fleet repo and link none: any fleet repo may be private, so a cross-repo link 404s in a public carrier (the blessed-reference link to the private Vantage-Config already 404s in the public PlexCleaner/LanguageTags/ Utilities carries), and a cross-repo reference couples the repos and rots as they diverge. A repo name belongs only where that repo is the file's subject; a current good example is named in the onboarding/ conformance issue or the hub-only conformance-matrix, not a carried doc. - repo-config/README.md: drop the [vantage-config] link and its External group; the "Adapted self-audit carry" bullet now describes the adapted AUDIT.md shape self-containedly and points to the issue for a current example. Generalize the "Downstream Carry" intent. - AGENTS.md: add the rule under Documentation Style Conventions (repo-agnostic carried files; pairs with the present-tense rule); the mixed-consumer-config example keeps its Windows-editor/CRLF context but drops the repo names. - CODESTYLE.md: the logging-seam and Python "Two profiles" examples describe the pattern without naming a repo. - spec/project-types.json: python profileNote genericized; new recurring.norepoxref audit check enforces the rule. - spec/secrets.json: the coverage-threshold note no longer names repos. Hub-only files (registry/repos.json, reports/conformance-matrix.md) keep repo names - naming repos is their subject, and they are not carried. Downstream copies of the carried files correct on each repo's next conformance touch. Validated: spec/validate.py OK; markdownlint + editorconfig-checker clean; no residual illustrative cross-repo reference in any carried file. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the template's carried documentation/spec content to be repo-agnostic by removing illustrative cross-repo references (and cross-repo links), and codifies that constraint as a recurring audit expectation for the fleet.
Changes:
- Removes a cross-repo external link from
repo-config/README.mdand rewrites examples to be self-contained. - Adds a new carried-doc rule in
AGENTS.mdand adds a new recurring audit check (recurring.norepoxref) inspec/project-types.json. - Generalizes remaining repo-specific examples/notes in carried docs/spec (e.g.,
CODESTYLE.mdandspec/secrets.json) to avoid naming specific sibling repos.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| AGENTS.md | Adds the new “no sibling repo references/links in carried docs” rule under Documentation Style Conventions. |
| CODESTYLE.md | Rewrites example references to describe patterns generically rather than naming specific repos. |
| repo-config/README.md | Removes the external sibling-repo link and rewrites the self-audit carry guidance to be self-contained. |
| spec/project-types.json | Generalizes the Python profile note and adds a new recurring audit check for the no-cross-reference rule. |
| spec/secrets.json | Generalizes the Codecov note to remove repo-specific examples. |
…s (Copilot #344) 'and link none' read as banning all links - reworded to make clear only cross-repo references (a sibling fleet repo's name or link) are barred; same-repo file/anchor links and external links are unaffected. The recurring.norepoxref check now lists the carried files by real path instead of shorthand. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
spec/project-types.json:145
- The recurring.norepoxref assertion's parenthetical file list is incomplete (it omits other carried paths like repo-config/settings.json, repo-config/operational/develop.json, and most of spec/). Since this text is used as an auditable rule description, hard-coding a partial list can go stale and be misread as the full carried set. Consider describing the carried scope generically (repo-config/, spec/) or explicitly marking the list as non-exhaustive.
{ "id": "recurring.norepoxref", "verdict": "intent", "assert": "A carried file (AGENTS.md, CODESTYLE.md, WORKFLOW.md, README.md, .github/copilot-instructions.md, repo-config/README.md, repo-config/develop.json, repo-config/main.json, spec/secrets.json, the carried AUDIT.md) names no sibling fleet repo as an illustrative example and adds no link (inline URL or reference definition) to another fleet repo; only cross-repo references are banned - same-repo file/anchor links and external links are fine. A repo name appears only where that repo is the file's subject. Rationale: a cross-repo link 404s in a public carrier when the target is private, and couples the repos. A current example is named in the onboarding/conformance issue or the hub-only reports/conformance-matrix.md, never a carried doc.", "intentRef": "AGENTS.md#documentation-style-conventions" }
ptr727
added a commit
that referenced
this pull request
Jul 18, 2026
…only doc (#345) (#349) Fixes #345 (both findings). Surfaced when ESPHome-Config became the first **public** repo to carry `repo-config/README.md`. ## Finding 1: carry-process narration shipped downstream `repo-config/README.md` is carried verbatim by every fleet repo, but it shipped carry-**process** guidance - `## Downstream Carry`, the ruleset import/regen procedure, and the maintainer `## Brownfield Migration`. That is meta-guidance for whoever performs the carry, not a current fact about the repo the file lands in (it's also what hosted the private-repo link #344 removed). **Split** (the settled approach): - **New hub-only `docs/repo-config-carry.md`** holds the process: Downstream Carry, Applying the Config, Regenerating the Payloads, Brownfield Migration. It's not in `spec/files.json` baseline, so it's never carried; being hub-only it may name repos and link the hub freely. - **`repo-config/README.md` trims to current facts** about a repo's own config: file descriptions, what the rulesets enforce, the secrets each mechanism needs, the general settings. - **Cross-refs fixed** (carried docs can't link a hub-only doc): `AGENTS.md` plain-text-mentions the hub doc for the full procedure/brownfield and drops two stale anchors (`Rules / Rulesets`, `Template - GitHub Setup`); `STANDUP.md` and `spec/files.json` (both hub-only) link the new doc directly. ## Finding 2: repo-scoped secrets schema clarity The rule for the adapted `spec/secrets.json` now lives in the hub doc: a **source-only** repo whose publish targets all map to a null mechanism carries just `baseline` (+ `note`) - it omits `targetMechanisms`, since a lone routing map with no `mechanisms` reads as "the audit ignores the mechanism list" (Copilot tripped on it 3x across the standup PRs). A repo with a real mechanism carries `mechanisms` **and** its `targetMechanisms` routing, which the audit picks up. ## Rollout Hub only. Downstream repos' carried `repo-config/README.md` (and any source-only `spec/secrets.json` still carrying an all-null `targetMechanisms`) correct on each repo's next conformance touch - consistent with the prior sweeps. ESPHome-Config already stripped both in its standup. ## Validation `spec/validate.py` OK; markdownlint + editorconfig-checker clean on all changed files; CI-scoped cspell (README+HISTORY) clean; grep confirms no dangling references to the moved sections. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 18, 2026
Closed
ptr727
added a commit
that referenced
this pull request
Jul 18, 2026
…ck (#359) The template is private, so any reference to it from a carried file 404s for that repo's readers and exposes template machinery a consumer should never have to see. Raised from downstream work where the references were being stripped by hand, repo by repo. ## Scope of the leak Swept every cataloged repo. **13 of 20 reference the template; 8 are public:** | repo | public | files | |---|---|---| | Utilities | yes | copilot-instructions, HISTORY | | LanguageTags | yes | copilot-instructions | | aiopurpleair | yes | copilot-instructions | | homeassistant-purpleair | yes | AGENTS, copilot-instructions | | PlexCleaner | yes | copilot-instructions | | VSCode-Server-DotNetCore | yes | copilot-instructions | | NxWitness | yes | AGENTS, copilot-instructions | | ESPHome-Config | yes | AGENTS | | Financial-Modeling / HomeAutomation-Config / KiCadLibrary / HomeAssistant-Config / MediaTools | no | assorted | The dominant instance is a stale `copilot-instructions.md` paragraph telling agents to report drift upstream, which **hard-links the private template twice** - and one link targets an `AGENTS.md#staying-in-sync-and-reporting-drift-upstream` section **the hub no longer has**, so it 404s even for someone with access. The hub itself carries neither the paragraph nor that section: this is stale carried content that outlived its source (#305 territory, and exactly the "prose asserting the old behavior" rule from #356). ## The rule #344 barred *sibling*-repo references but arguably let the template through as "the subject". `AGENTS.md` now says explicitly: > **This includes the template repo itself.** A carried file names it in neither prose nor a link ... Where a carried file needs to express a template-level behavior - "report a rule discrepancy upstream" - state the behavior, not the destination; the maintainer supplies the destination out of band. That preserves the agent-to-agent reporting flow (which is real and valuable) while keeping it out of a public file. ## Mechanized, not left to review This spread silently across 13 repos, so `spec/audit.py` now checks the two agent-instruction files for the template name and raises a drift finding. The template name is derived from **the git remote**, not the checkout directory name - a clone into a differently-named folder would otherwise stop detecting with no signal, which is the fail-open case the check exists to prevent (AGENTS.md "Verification Discipline": gates fail loud, never narrow quietly). ```text PlexCleaner -> DRIFT carried: .github/copilot-instructions.md references the template repo ... ESPHome-Config -> DRIFT carried: AGENTS.md references the template repo ... Vantage-Config -> clean ``` ## Downstream Not fixed here - the 13 carried copies need the reference removed in their own repos. Raising the delivery shape (per-repo issues vs. folding into each repo's existing conformance issue) rather than filing 13 issues unilaterally. `spec/validate.py`, markdownlint, editorconfig-checker: clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ptr727
added a commit
that referenced
this pull request
Jul 19, 2026
Reported from a downstream session: Copilot insisted on removing a `README.md` link pointing to a related device-builder repo, citing the no-cross-repo-link rule. That link was legitimate content. The rule I wrote in #344/#359 made that misreading reasonable, so this fixes the rule rather than the reviewer. ## Two defects in the rule as written **1. It led with the mechanism and buried the carve-out.** The sentence opened with "adds no link (inline URL or reference definition) to another fleet repo" and only qualified it fifteen lines later with "unless that repo is the subject". Read top-down, the ban looks absolute. **2. It claimed `README.md` is carried verbatim. It is not.** `spec/files.json` gives `README.md` neither `whole: true` nor `sections`, so it is a per-repo file governed only by `readme-structure.md`. A repo's own README is its own content. The rule never should have reached it, which is exactly where the over-application landed. ## Restated by intent Two things banned in carried files: - **Any reference to the template repo**, prose or link. Private, so it 404s, and the coordination flow is machinery a consumer should not see. - **A sibling fleet repo named as an illustrative example** ("repo X does it this way", "see repo Y's adoption"). That couples repos and rots as they diverge. And explicitly permitted: > **A contextually relevant link to a related project is not a coordination reference, and is expected.** Where another repo is part of this repo's subject matter - the image that consumes this config, the builder that generates this hardware, a library this depends on - link it normally. The test is whether the link serves a reader of *this* repo's content, not whether the target happens to be in the fleet. Plus the scope correction: the rule governs carried template content, and a repo's own `README.md` and topical docs are outside it. `spec/project-types.json`'s `recurring.norepoxref` is reworded to match. ## The mechanical check needed no change `spec/audit.py` greps only for the **template name** in the two agent-instruction files. It never looked for sibling links, so it was not the source of the over-application and its behavior is unchanged - re-verified against PlexCleaner (flags) and Vantage-Config (clean). `spec/validate.py`, markdownlint, editorconfig-checker: clean. *Downstream note: ESPHome-NonRoot is amending its local AGENTS.md for the same reason. Once this lands, its next carry converges on this wording.* 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A file the fleet carries verbatim must name no sibling fleet repo and link none. Raised by the ESPHome-Config adoption: the
repo-config/README.md"blessed reference" pointed a[vantage-config]link at the private Vantage-Config, which 404s in every public carrier (PlexCleaner, LanguageTags, Utilities already carry it). Two reasons, both general: any fleet repo may be private -> a cross-repo link 404s in a public carrier; and a cross-repo reference couples the repos and rots as they diverge.The rule (now codified in AGENTS.md)
A carried file (
AGENTS.md,CODESTYLE.md,WORKFLOW.md,README.md,.github/copilot-instructions.md,repo-config/*,spec/*, the carriedAUDIT.md) is repo-agnostic: it describes the shape/pattern self-containedly and names a sibling repo only where that repo is the subject. A current good example is named in the onboarding/conformance issue (one-off, not carried) or the hub-onlyreports/conformance-matrix.md(a fleet tracking table) - never a carried doc. This pairs with the present-tense rule: state the current shape, not its provenance.Changes
repo-config/README.md[vantage-config]link + External group; the self-audit-carry bullet describes the adaptedAUDIT.mdshape self-containedly, pointing to the issue for a current exampleAGENTS.mdCODESTYLE.mdspec/project-types.jsonpythonprofileNote genericized; newrecurring.norepoxrefaudit checkspec/secrets.jsonHub-only files (
registry/repos.json,reports/conformance-matrix.md) keep repo names - naming repos is their subject and they are not carried.Rollout
Hub only. The 6 repos that already carry the bad link (public: PlexCleaner, LanguageTags, Utilities - live 404; private: Vantage-Config, HomeAutomation-Config, MediaTools) correct on each repo's next conformance touch. ESPHome-Config's in-flight adoption carries the fixed hub
repo-config/README.md, so it never inherits the link.Validation
python3 spec/validate.py-> OK; markdownlint + editorconfig-checker clean.🤖 Generated with Claude Code