Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ Clarify devcontainer setup steps in README

## Documentation Style Conventions

- **Carried files carry no coordination references.** In the files the fleet carries (`AGENTS.md`, `GOVERNANCE.md`, `CODESTYLE.md`, `WORKFLOW.md`, `.github/copilot-instructions.md`, the `repo-config/` and `spec/` files, the carried `AUDIT.md`), two things are banned. **Any reference to the template repo**, in prose or in a link: the coordination flow is machinery a consumer of that repo should never have to see, and naming where a file came from is the derived-from framing the present-tense rule below independently forbids. Where a carried file must express a template-level behavior ("report a rule discrepancy upstream"), state the behavior rather than the destination. The maintainer supplies the destination out of band. And **a sibling fleet repo named as an illustrative example** ("repo X does it this way", "see repo Y's adoption"), which couples the repos and rots as they diverge. To point at a current good example, name it in the onboarding or conformance issue, never in a carried doc. **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. This rule governs carried template content. A repo's own `README.md` and topical docs are its own content, not carried verbatim, and it does not reach them. This pairs with the present-tense rule below: state the current shape, not a history of which repo it came from.
- **Carried files carry no coordination references.** In the files the fleet carries (`AGENTS.md`, `GOVERNANCE.md`, `CODESTYLE.md`, `WORKFLOW.md`, `.github/copilot-instructions.md`, the `repo-config/` and `spec/` files, the carried `AUDIT.md`), two things are banned. **Any reference to the template repo**, in prose or in a link: the coordination flow is machinery a consumer of that repo should never have to see, and naming where a file came from is the derived-from framing the present-tense rule below independently forbids. Where a carried file must express a template-level behavior ("report a rule discrepancy upstream"), state the behavior rather than the destination. **The one exception is a verbatim section, and `AGENTS.md` "Fleet Bootstrap" is why it exists.** That section's whole function is to name where the canonical rules live, for an agent in a repository whose carried copies are stale, partial, or absent, which is exactly when no other file present can say it. Its bytes are fixed fleet-wide, so a repository cannot edit the reference out without failing the verbatim check instead, and a rule banning it would be unsatisfiable rather than merely strict. The exception is scoped to the verbatim region and never leaks past it: the same document's own prose is governed normally, so a repository that names the destination in a paragraph it owns is still in breach. A reference that reaches a verbatim section is a defect in the canonical, fixed once at the source rather than reported against every repository carrying it. The maintainer supplies the destination out of band. And **a sibling fleet repo named as an illustrative example** ("repo X does it this way", "see repo Y's adoption"), which couples the repos and rots as they diverge. To point at a current good example, name it in the onboarding or conformance issue, never in a carried doc. **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. This rule governs carried template content. A repo's own `README.md` and topical docs are its own content, not carried verbatim, and it does not reach them. This pairs with the present-tense rule below: state the current shape, not a history of which repo it came from.

### Markdown

Expand Down
2 changes: 1 addition & 1 deletion reports/conformance-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The primary shapes are stood up as whole repos. The **composable targets** (`nug
| Shape | Reference repo | Cold-standup | Last audited | First gap / notes |
|---|---|---|---|---|
| `python` + `source-only` | Financial-Modeling | not-tested | - | Reference for the source-release (dispatch-only) profile. The downstream standup issue is open. |
| `hugo` + `source-only` + `release` | Blog | not-tested | 2026-08-05 | Hugo static site (#456, #558), stood up 2026-08-01 and cataloged 2026-08-03. Release and deploy are independent surfaces: a dispatch-only publisher cuts the tag, and a separate dispatch deploys to a `self-hosted` filesystem per environment. Reclassified off the interim `source-only`-alone declaration when the type landed. **The 2026-08-05 run is the first to judge the `hugo` checks**, since the 2026-08-03 one predated the type and graded the repo as `source-only` alone. All nine pass, the repo is operational, and the three deviations the first run recorded are closed (ptr727/Blog#27, ptr727/Blog#28, ptr727/Blog#29). Two drift classes stay open, both of them the hub having advanced: seven stale verbatim carries and 17 prose findings. This is the shape `hugo.deploy.retention` was written against: its deploy credential is confined write-only, so the deploy can neither prune nor read the destination back, and the prune is a host-side timer its runbook records as host-owned. The first draft of that check demanded an in-pipeline assertion and would have pushed a correct design to widen a deliberately narrow credential. The run also surfaced a hub defect rather than a repo one, carried as escalation 1 of the report: `spec/audit.py`'s template-reference check has no exemption for the byte-locked `Fleet Bootstrap` section, whose first sentence must name the hub, so it fires unclearably on every repo that has carried the current canonical. |
| `hugo` + `source-only` + `release` | Blog | not-tested | 2026-08-05 | Hugo static site (#456, #558), stood up 2026-08-01 and cataloged 2026-08-03. Release and deploy are independent surfaces: a dispatch-only publisher cuts the tag, and a separate dispatch deploys to a `self-hosted` filesystem per environment. Reclassified off the interim `source-only`-alone declaration when the type landed. **The 2026-08-05 run is the first to judge the `hugo` checks**, since the 2026-08-03 one predated the type and graded the repo as `source-only` alone. All nine pass, the repo is operational, and the three deviations the first run recorded are closed (ptr727/Blog#27, ptr727/Blog#28, ptr727/Blog#29). Two drift classes stay open, both of them the hub having advanced: seven stale verbatim carries and 17 prose findings. This is the shape `hugo.deploy.retention` was written against: its deploy credential is confined write-only, so the deploy can neither prune nor read the destination back, and the prune is a host-side timer its runbook records as host-owned. The first draft of that check demanded an in-pipeline assertion and would have pushed a correct design to widen a deliberately narrow credential. The run also surfaced a hub defect rather than a repo one, carried as escalation 1 of the report: the template-reference check had no exemption for the byte-locked `Fleet Bootstrap` section, whose first sentence must name the hub, so it fired unclearably on every repo that had carried the current canonical. Fixed since, across all three surfaces that stated the rule: the scan in `spec/audit.py` excises a file's verbatim sections before looking for the name, and `GOVERNANCE.md` "Documentation Style Conventions" and `recurring.norepoxref` both carry the exception and its boundary. It cleared exactly two findings fleet-wide and kept the other eleven. |
| `csharp` + `console` | - | not-tested | - | |
| `csharp` + `docker` | - | not-tested | - | |
| `csharp` + `python` | PlexCleaner | not-tested | - | First mixed-language shape (#339). Python is a stdlib-only `uvx` **scripts** profile subtree (`RegressionTests/`): no `uv.lock`, `pyproject.toml` lint/type config only, mypy checker, `python.uvlock.pinned` + `python.coverage.codecov` N/A, and `codecov.yml` stays required for the C# side. Both language rule-sets apply (CODESTYLE.md "Two profiles"). |
Expand Down
94 changes: 83 additions & 11 deletions spec/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,46 @@ def extract_section(text, heading):
return "\n".join(out) if capturing else None


# Carried files scanned for a coordination reference (GOVERNANCE.md "Documentation Style Conventions").
TEMPLATE_REF_SCANNED = ("AGENTS.md", "GOVERNANCE.md", ".github/copilot-instructions.md")


def strip_sections(text, names):
"""`text` with each named `## <heading>` region removed, located by position rather than by content.

Region rules match extract_section (a fenced `## ` is not a boundary, a sibling H2 ends the region), so
the two agree on where a section starts and stops.
Positional removal is the point: deleting the extracted text instead would also delete an identical
passage anywhere else in the document, including one quoted inside the prose the caller means to read.
That failure is silent and it fails open, since the removed duplicate takes its content out of the scan.
"""
want = {n.strip().lower() for n in names}
out, dropping, fenced = [], False, False
for ln in normalize(text).split("\n"):
stripped = ln.strip()
if stripped.startswith("```") or stripped.startswith("~~~"):
fenced = not fenced
elif not fenced and stripped.startswith("## "):
dropping = stripped[2:].strip().lower() in want # a sibling H2 always ends the previous region
if not dropping:
out.append(ln)
return "\n".join(out)


def template_ref_outside_verbatim(text, verbatim_names, hub_name):
"""True when `hub_name` appears in `text` outside every one of its verbatim sections.

A verbatim section's bytes are the hub's canonical and are checked byte-for-byte elsewhere, so a hub
reference inside one cannot be removed downstream: the repo would have to fail the verbatim check to
clear this one. `AGENTS.md > Fleet Bootstrap` is the standing case, since naming the hub is that
section's entire function - it is the byte-locked entry point stating where the canonical rules live,
and a repo holding no current copy of anything else is exactly who reads it. Excising the verbatim
regions before scanning keeps the check pointed at the prose a repo actually owns. A hub reference that
reaches a verbatim section is the hub's defect to fix once in the canonical, never each repo's to clear.
"""
return hub_name.lower() in strip_sections(text, verbatim_names).lower()


def heading_texts(markdown):
"""Lowercased heading texts in a Markdown document, for case-insensitive section-presence matching."""
return {m.group(1).strip().lower() for line in markdown.splitlines() for m in (_HEADING.match(line),) if m}
Expand Down Expand Up @@ -683,17 +723,6 @@ def audit_repo(entry, spec, branch=None):
for name in sorted(present - claimed_names):
findings.append(("DRIFT", f"secrets: {name} in the {store} store is claimed by no applicable mechanism (stale?)"))

# --- Carried files must not reference the template repo ---
# The coordination flow is machinery a consumer should not see, so a carried file states the behavior rather than the destination.
# This reads AGENTS.md, GOVERNANCE.md and .github/copilot-instructions.md, where a stale "report drift upstream" paragraph once spread.
# Skip the hub itself, whose own carried files are the source, where naming the repo they live in is correct.
# A downstream repo naming it is still flagged, which is the point.
if entry.get("name") != HUB_NAME:
for path in ("AGENTS.md", "GOVERNANCE.md", ".github/copilot-instructions.md"):
doc = gh(f"repos/{slug}/contents/{path}?ref={ground}", ok404=True)
if doc and doc.get("content") and HUB_NAME.lower() in base64.b64decode(doc["content"]).decode("utf-8", "replace").lower():
findings.append(("DRIFT", f"carried: {path} references the template repo by name or link (the coordination flow is machinery this repo's readers should not see; state the behavior, not the destination)"))

# --- Dependabot ecosystem coverage ---
# A repo's tree implies Dependabot ecosystems it must track: github-actions when it ships workflows
# (the action versions they reference otherwise go stale, and a merge-bot then has no PRs to auto-merge),
Expand Down Expand Up @@ -811,6 +840,19 @@ def audit_repo(entry, spec, branch=None):
for h in sorted(h2s - declared):
findings.append(("DRIFT", f"section: '{h}' in {path} is not a declared section - reconcile it (a duplicate of a verbatim section, or repo-specific content that moves to a topical doc), or confirm it is intentional (spec/section-model.md)"))

# --- Carried files must not reference the template repo ---
# The coordination flow is machinery a consumer should not see, so a carried file states the behavior rather than the destination.
# A stale "report drift upstream" paragraph once spread this way.
# Skip the hub itself, whose own carried files are the source, where naming the repo they live in is correct.
# A downstream repo naming it in prose it owns is still flagged, which is the point.
# Verbatim sections are excised first, and template_ref_outside_verbatim carries why that is not a loophole.
# Sited here, in the file loop, so the scan reuses the content already fetched for the section checks and reads the same selector-resolved verbatim list they were judged against.
if path in TEMPLATE_REF_SCANNED and entry.get("name") != HUB_NAME:
if text is None:
findings.append(("DRIFT", f"carried: could not read {path} content on {ground} to scan for a coordination reference (no inline content returned); verify by hand"))
elif template_ref_outside_verbatim(text, verbatim_secs[path], HUB_NAME):
findings.append(("DRIFT", f"carried: {path} references the template repo by name or link outside its verbatim sections (the coordination flow is machinery this repo's readers should not see; state the behavior, not the destination)"))

# --- HISTORY.md mirrors the README opening ---
# spec/readme-structure.md "HISTORY.md": the changelog opens as the README's twin - same H1 title and the
# same intro paragraph. Checked only when both files were readable (absence is already a file LETTER above).
Expand Down Expand Up @@ -1015,6 +1057,36 @@ def _selftest():
else:
print(" ok section: heading in region, fenced ## kept, sibling H2 ends, None if absent, whitespace-tolerant locate, re-cased heading rehashes")

# Coordination-reference scan: the hub name inside a verbatim section is exempt, outside one is not.
# The first case is the real AGENTS.md shape, where the byte-locked Fleet Bootstrap block must name the hub and a repo therefore cannot clear a finding against it.
# The CRLF case matters because extract_section normalizes EOLs while carried files are CRLF on this fleet, so excision must survive that.
boot = "## Fleet Bootstrap\n\nThe canonical rules live in `github.com/acme/Hub`.\n"
owned = "## Where the Rules Live\n\nReport a rule discrepancy to acme/Hub.\n"
clean_doc = "# AGENTS\n\n" + boot + "\n## Where the Rules Live\n\nState the behavior, not the destination.\n"
dirty_doc = "# AGENTS\n\n" + boot + "\n" + owned
tref = [
("hub name only inside the verbatim section", clean_doc, {"Fleet Bootstrap"}, False),
("hub name in prose the repo owns", dirty_doc, {"Fleet Bootstrap"}, True),
("same document with nothing declared verbatim still flags", clean_doc, set(), True),
("CRLF document excises the same way", clean_doc.replace("\n", "\r\n"), {"Fleet Bootstrap"}, False),
("a re-cased verbatim heading still excises", clean_doc.replace("## Fleet Bootstrap", "## fleet bootstrap"), {"Fleet Bootstrap"}, False),
("no hub reference at all", "# AGENTS\n\n## Where the Rules Live\n\nNothing to see.\n", {"Fleet Bootstrap"}, False),
# A second region under the same heading is excised by name, which is right: both are that section.
("the heading appearing twice excises both", "# AGENTS\n\n" + boot + "\n## Notes\n\n" + boot, {"Fleet Bootstrap"}, False),
# A fenced copy is not a heading, so it is prose the repo owns and the reference in it must flag.
# This is the case that made positional excision necessary, because removing the extracted text instead would delete the fenced copy along with the real region and the scan would fail open.
# That is the one arrangement a repo could otherwise use to carry the reference in a document it owns.
("a fenced copy of the section is prose, not the section", "# AGENTS\n\n## Notes\n\n```\n" + boot + "```\n\n" + boot, {"Fleet Bootstrap"}, True),
]
tref_ok = True
for label, doc, verb, want in tref:
got = template_ref_outside_verbatim(doc, verb, "acme/Hub")
if got != want:
ok = tref_ok = False
print(f" FAIL template-ref: {label} (expected {want}, got {got})")
if tref_ok:
print(f" ok template-ref: {len(tref)} cases, verbatim regions excised before the hub-name scan")

# Issue generator: findings land in the right buckets and the title carries the count.
fe = {"name": "Widget", "types": ["python"]}
it, ib = render_issue(fe, [("LETTER", "file: X absent"), ("DRIFT", "verbatim: Y differs"), ("ERROR", "gh failed")],
Expand Down
Loading
Loading