Skip to content

Make carried template docs repo-agnostic; codify the no-cross-reference rule - #344

Merged
ptr727 merged 2 commits into
developfrom
carried-docs-repo-agnostic-339
Jul 18, 2026
Merged

Make carried template docs repo-agnostic; codify the no-cross-reference rule#344
ptr727 merged 2 commits into
developfrom
carried-docs-repo-agnostic-339

Conversation

@ptr727

@ptr727 ptr727 commented Jul 18, 2026

Copy link
Copy Markdown
Owner

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 carried AUDIT.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-only reports/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

File Change
repo-config/README.md Remove the [vantage-config] link + External group; the self-audit-carry bullet describes the adapted AUDIT.md shape self-containedly, pointing to the issue for a current example
AGENTS.md New rule under Documentation Style Conventions; the mixed-consumer-config example keeps its Windows-editor/CRLF context but drops the repo names
CODESTYLE.md Logging-seam and Python "Two profiles" examples describe the pattern, no repo names
spec/project-types.json python profileNote genericized; new recurring.norepoxref audit check
spec/secrets.json 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.

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.
  • Grep confirms no residual illustrative cross-repo reference in any carried file, and the Vantage URL is gone from all carried paths.

🤖 Generated with Claude Code

…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>
Copilot AI review requested due to automatic review settings July 18, 2026 00:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.md and rewrites examples to be self-contained.
  • Adds a new carried-doc rule in AGENTS.md and adds a new recurring audit check (recurring.norepoxref) in spec/project-types.json.
  • Generalizes remaining repo-specific examples/notes in carried docs/spec (e.g., CODESTYLE.md and spec/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.

Comment thread AGENTS.md Outdated
Comment thread spec/project-types.json Outdated
…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>
Copilot AI review requested due to automatic review settings July 18, 2026 00:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
ptr727 merged commit 3f16b43 into develop Jul 18, 2026
7 checks passed
@ptr727
ptr727 deleted the carried-docs-repo-agnostic-339 branch July 18, 2026 00:22
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>
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants