Skip to content

Byte-match AGENTS.md to the canonical section-fidelity model#889

Merged
ptr727 merged 3 commits into
developfrom
feature/880-agents-section-model
Jul 24, 2026
Merged

Byte-match AGENTS.md to the canonical section-fidelity model#889
ptr727 merged 3 commits into
developfrom
feature/880-agents-section-model

Conversation

@ptr727

@ptr727 ptr727 commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Addresses the phase-2 scope update on #880: the hub's per-section fidelity model (spec/section-model.md, ProjectTemplate#420 on main) makes every universal AGENTS.md section verbatim and byte-checked. This makes develop's AGENTS.md byte-match all 15 applicable verbatim sections from hub main@bd2dcd6.

What the audit now requires, and what this does

audit.py extracts each ## <heading> block and byte-compares it (EOL- and action-pin-normalized only) against the hub canonical. I verified all 15 with the audit's own extraction semantics - every one matches. Devcontainer and Repository Layout are intent (presence only); Operational Repositories is appliesTo: operational, N/A for this release repo.

  • Re-vendored 15 verbatim sections byte-for-byte from hub main.
  • Added Devcontainer (intent). This repo ships no committed devcontainer, so the section documents the native .NET SDK + media-tool toolchain and the Docker image as a ready-made environment.
  • Kept Repository Layout (intent) as this repo's own content.

Removed two sections the model does not permit here - no content lost

The section model allows only Devcontainer and Repository Layout as own content; an undeclared extra section is drift to reconcile. Both of mine were reconciled by relocation, not deletion:

  1. Shared Configuration and Tooling was a near-duplicate. Its bullets were already covered by the canonical Editor and Tasks (VS Code tasks/extensions), Workflow YAML Conventions -> Running the Linters Locally (Docker linter invocations), and Verification Discipline (whole-gate-before-push), plus CODESTYLE's Clean-Compile Verification and Analyzer Diagnostics sections. Carrying it alongside the now-verbatim canonical would have been exactly the same-content-different-name duplication the section model exists to stop. Its one unique bit - the IDE0072/IDE0046 format-gate gotcha - moves to CODESTYLE.md's Analyzer Diagnostics section; the release-notes rule moves to ARCHITECTURE.md's Build and Release section.
  2. Logging Conventions is app behavior, not fleet law - the PlexCleaner Serilog level taxonomy. It moves whole to ARCHITECTURE.md (which already had a one-line logging bullet under Code Conventions).

Dropped the Git and Commit Rules repo-specific subsection. Under phase 1 the hub told me to keep it; the section model supersedes that - a ### subsection lives inside the verbatim ## Git and Commit Rules region and breaks its byte-match. Its rule (never self-merge to main; drive feature->develop end-to-end when authorized) is already carried by the verbatim Merge Gate (PR Review Etiquette) and Branching Model, so nothing is lost.

Route-backs for the hub - byte-matching hub text has consequences I cannot fix locally

Byte-match forbids editing the verbatim text, so these are reported, not patched:

  1. Verbatim sections cross-reference "Operational Repositories" three times (Foundational Principles, Branching Model, Release Model), a section a release repo correctly does not carry. The reference dangles in every release repo by construction. Same class as the pre-Bump JsonSchema.Net.Generation from 4.4.0 to 4.5.0 #416 "Running the Linters Locally" dangle, now structural.
  2. The verbatim text carries 16 relative links to hub-only paths that 404 in a downstream repo: ./registry/repos.json, ./STANDUP.md, ./reports/conformance-matrix.md, ./spec/validate.py, ./repo-config/operational/develop.json, and 11 under ./catalog/snippets/.... This collides with the verbatim Documentation Style Conventions rule in the same file - "Carried files carry no coordination references... any reference to the template repo... it is private, so a link 404s for a downstream repo's users." The canonical currently violates its own carried-files rule, and byte-match propagates every broken link to every downstream repo. This wants genericizing at the source (state the behavior, drop the hub-internal path) before it can vendor cleanly. Not audit- or lint-blocking (markdownlint does not check relative-link targets), but the links are dead for a reader of this repo.
  3. Devcontainer is presence-required (appliesTo: *, intent) but not every repo has one. A repo with no devcontainer still must carry the heading, so the honest content is "there is no devcontainer, here is the native toolchain." If that is the intended shape, fine; if Devcontainer should be appliesTo a subset (repos that ship one), that would fit reality better. Flagging, not blocking.

Verification

All 15 verbatim sections confirmed byte-identical via the audit's extraction + normalization. markdownlint-cli2, editorconfig-checker, cspell (README/HISTORY), and the husky pre-commit gate are clean. AGENTS.md/ARCHITECTURE.md/CODESTYLE.md verified ASCII + CRLF. No C# changed.

The hub landed a per-section fidelity model (spec/section-model.md): every
universal section of AGENTS.md is verbatim and byte-checked against the
canonical, only Devcontainer and Repository Layout are intent (this repo's
own content), and Operational Repositories is operational-only, so N/A here.

Re-vendor all 15 applicable verbatim sections byte-for-byte from hub main,
add a Devcontainer section (this repo ships none, so it documents the native
toolchain), and keep Repository Layout as this repo's own.

Remove two sections the model does not permit here, without losing content:

- Shared Configuration and Tooling was a near-duplicate of the canonical
  Editor and Tasks, Workflow YAML Conventions (Running the Linters Locally),
  and Verification Discipline, plus CODESTYLE's clean-compile and analyzer
  sections. Its one unique C# note (the IDE0072/IDE0046 format-gate gotcha)
  moves to CODESTYLE.md; the release-notes rule moves to ARCHITECTURE.md.
- Logging Conventions is PlexCleaner-specific app behavior, not fleet law,
  so it moves whole to ARCHITECTURE.md.

Drop the Git and Commit Rules repo-specific subsection: it broke the section
byte-match and its rule (never self-merge to main, drive feature->develop
when authorized) is already covered by the canonical Merge Gate and
Branching Model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Aligns this repo’s agent governance documentation with the hub’s per-section fidelity model by re-vendoring canonical AGENTS.md sections verbatim, while relocating repo-specific behavior guidance to the appropriate repo-owned docs.

Changes:

  • Re-vendored the applicable canonical AGENTS.md sections to byte-match the hub model.
  • Added/updated ARCHITECTURE.md guidance for logging conventions and release-note maintenance.
  • Captured the .NET Format analyzer auto-fix gotchas in CODESTYLE.md (General section).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
AGENTS.md Re-vendors canonical governance sections to satisfy per-section byte-match requirements and updates section set accordingly.
ARCHITECTURE.md Adds app-specific logging conventions and release-note documentation guidance that no longer belongs in canonical AGENTS.md.
CODESTYLE.md Adds a note about dotnet format analyzer fixers and how they affect the clean-compile gate.

Comment thread CODESTYLE.md Outdated
Copilot flagged the CODESTYLE analyzer-gate bullet; sweeping the class
found two more in this PR's authored additions.

- CODESTYLE: name the gate as `dotnet format style --verify-no-changes
  --severity=info` to match the rest of the file, and split the
  IDE0072/IDE0046 clauses (they were semicolon-spliced).
- ARCHITECTURE release-notes bullet and the AGENTS Devcontainer section:
  recast each semicolon splice per the Character Set rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 24, 2026 15:02

Copilot AI left a comment

Copy link
Copy Markdown

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 3 out of 3 changed files in this pull request and generated 2 comments.

Comment thread ARCHITECTURE.md Outdated
Comment thread ARCHITECTURE.md Outdated
…rose

- MkvToolNix (the suite) capitalized per the tool-name casing rule; the
  mkvmerge/mkvpropedit binary names stay lowercase.
- The relocated release-notes bullet drops its two inline links (code
  spans instead) so it adds no new inline links to a human-facing doc,
  pending the reference-style convert-or-accept disposition.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 24, 2026 15:10

Copilot AI left a comment

Copy link
Copy Markdown

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 3 out of 3 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (6)

AGENTS.md:50

  • This paragraph links to ./repo-config/operational/develop.json, but repo-config/operational/ does not exist in this repository, so the link is broken. Either add the operational ruleset payloads under repo-config/operational/ (if they are meant to exist here) or remove/adjust the link upstream to avoid pointing release repos at missing paths.
- **Configuring branch protection on a fleet repo: don't hand-build the rules.** Reconstructing the rules by hand is error-prone and has gone wrong on past ports. First delete **all** legacy classic branch-protection rules and any stray rulesets (rulesets are the *only* mechanism used), then create **exactly two rulesets named `develop` and `main`** by importing the committed `repo-config/*.json` ruleset payloads via `gh api -X POST "repos/<owner>/<repo>/rulesets"` (`gh ruleset` is read-only). The names are load-bearing - this file and the workflows reference them. Operational repos import [`operational/develop.json`](./repo-config/operational/develop.json) as their `develop` ruleset (the `main` ruleset is shared); [`configure.sh`](./repo-config/configure.sh) selects the right develop payload from the registry `workflowModel` automatically. **Brownfield repos** (pre-existing history) need an extra step: `Require signed commits` rejects legacy unsigned commits and the admin bypass does not cover `git push --force`, so re-signing requires temporarily disabling the ruleset.

AGENTS.md:55

  • These bullets reference catalog/snippets/workflows/..., but this repository has no catalog/ directory, so the links (and the described mechanism) are not actionable here. If PlexCleaner is not intended to vendor the full fleet catalog, consider changing these references upstream (or adding local stub docs/scripts) so contributors are not sent to non-existent paths.
- **Bots (Dependabot and codegen) target both `main` and `develop` in parallel.** [`.github/dependabot.yml`](./.github/dependabot.yml) duplicates every ecosystem entry (one per branch) and [`catalog/snippets/workflows/run-codegen-pull-request-task.yml`](./catalog/snippets/workflows/run-codegen-pull-request-task.yml) runs as a matrix over both branches with branch names `codegen-main` and `codegen-develop`. Each branch absorbs its own bot PRs independently, so neither falls behind, and the forward-only rule still holds (nothing is back-merged from main to develop - both branches receive their updates directly). The merge-bot ([`.github/workflows/merge-bot-pull-request.yml`](./.github/workflows/merge-bot-pull-request.yml)) dispatches `--squash` or `--merge` from each PR's base ref via a `case` statement so the form matches the ruleset on either base. Dependabot **security** PRs (CVE-driven) always open against the repo default branch (`main`) regardless of `target-branch` - the same `case` statement covers them. The merge-bot auto-merges **every** Dependabot tier including semver-major (no ecosystem or update-type guard): the required CI checks are the gate, not the bump magnitude, so a major that breaks the build fails its checks and never merges.
- **Maintainer-pushed commits on a bot PR auto-disable auto-merge.** The merge-bot's `merge-dependabot` and `merge-codegen` jobs only fire on `opened` / `reopened` events (auto-merge is enabled exactly once per PR). When a maintainer pushes commits to a bot's branch (a `synchronize` event with an actor that isn't the same bot), the merge-bot's `disable-auto-merge-on-maintainer-push` job fires and calls `gh pr merge --disable-auto`. The maintainer's commits stay in the PR but won't auto-merge with the bot's content; re-enable auto-merge manually (`gh pr merge --auto <PR>` or the GitHub UI) when ready.
- **Why parallel dual-target rather than develop-only with eventual flow-through:** push-distribution channels (HACS for Home Assistant integrations, Linux distros that vendor from `main`, etc.) consume `main` directly. A develop-only model would leave `main` running stale code during long-running develop features. Codegen content can also be production-critical (live API-derived data, language lists, build catalogs) rather than just sample/demo content, so both branches need fresh codegen on their own cadence.
- **Codegen regenerates committed files; its output must be deterministic from its inputs, never per-run state.** The codegen workflow is a mechanism to refresh files that are checked into the repo: it runs a matrix over `main` and `develop`, each leg regenerating against its own checkout and opening its own PR (`codegen-main -> main`, `codegen-develop -> develop`). For the two legs not to conflict on `develop -> main`, the generated output must depend only on its inputs - never on per-invocation state (timestamps, GUIDs, build IDs), which would diverge every run and conflict on every release. **What** a repo regenerates (data files, source, or both; code changes or pure data) and **how** (download and process an external source, transform local inputs, whatever) is entirely its own concern - the constraint is only that the output be input-deterministic, not how it is produced.
  - *Reference:* the codegen workflow tasks are kept under [`catalog/snippets/workflows/`](./catalog/snippets/workflows/) (`run-codegen-pull-request-task.yml` and its scheduler). A repo adopting codegen supplies its own input-deterministic generator; this repo ships none.

AGENTS.md:63

  • This bullet links to ./catalog/snippets/workflows/publish-plan-task.yml, but this repository has no catalog/ directory. As written, the link 404s and the guidance is not directly verifiable from this repo. Consider adding the referenced workflow snippet(s) or adjusting the reference upstream to point at files that exist here.
- **A human merge never auto-publishes.** [`publish-release.yml`](./.github/workflows/publish-release.yml) is the sole publisher; each run builds the **single trigger branch** (`main` a release, `develop` a prerelease). A first [`plan`](./catalog/snippets/workflows/publish-plan-task.yml) job decides once whether the run publishes and every other job gates on its output. It publishes on a **`workflow_dispatch`** of `main`/`develop` (the human-initiated release), a **code-affecting bot push to `main`** (the codegen App merges every Dependabot/codegen PR, so `github.actor` is the gate - a human merge/promotion to `main` skips), or a **weekly `schedule`** (Docker only, to refresh the base image). The `push` is main-only and paths-filtered, so a develop bot merge and an Actions-only bump publish nothing. A source-only repo publishes on dispatch only.

AGENTS.md:89

  • This section points to ./STANDUP.md, ./reports/conformance-matrix.md, and ./spec/validate.py, but none of those paths exist in this repository (only spec/secrets.json is present). That makes these onboarding/conformance links dead for readers here. Either add the missing docs/scripts (if this repo is intended to carry them) or adjust the canonical text so repos without those files do not link to them.
- **Definition of done is the audit.** Onboarding or materially changing a repo is complete only when it passes [`AUDIT.md`](./AUDIT.md) for its type, **or** carries a committed `reports/<repo>/audit.md` plus a tracking issue for the residual deltas. Do not leave a repo partially stood up and unrecorded - that is itself a defect. Stand a repo (or a new type) up with [`STANDUP.md`](./STANDUP.md); verify it with [`AUDIT.md`](./AUDIT.md); the two share the same manifests, so a repo stood up correctly passes the audit by construction.
- **The registry is ground truth about reality, not intent.** After any conformance change, reconcile the repo's [`registry/repos.json`](./registry/repos.json) entry - `status`, `types`, `releaseTrigger`, `workflowModel`, `driftNotes` - to what the repo actually is. [`spec/validate.py`](./spec/validate.py) proves the catalog is self-consistent; it does **not** prove the catalog matches the live repo. A `validate.py`-clean entry can still be false, and a stale entry is a finding.
- **Prove the docs suffice.** The onboarding docs are sufficient only when a context-free agent stands each supported repo shape - project type(s) plus workflow model - up from them alone; the cold-start self-test in [`STANDUP.md`](./STANDUP.md) and the [conformance matrix](./reports/conformance-matrix.md) track that. A shape that cannot be stood up cold is a documentation defect, fixed in the hub, not worked around per repo.

AGENTS.md:290

  • These two bullets link to ./catalog/snippets/husky/pre-commit and ./catalog/snippets/configs/vscode-tasks.json, but this repo does not have a catalog/ directory, so the links are broken and the guidance is not actionable from here. Consider pointing to the actual in-repo files (.husky/pre-commit, .vscode/tasks.json) or vendoring the referenced snippet files.
- **The [`.husky/pre-commit`](./catalog/snippets/husky/pre-commit) hook** runs **language formatting only** - CSharpier + `dotnet format` (or ruff) via native tooling, no Docker and no doc linters, so it stays fast.
- **The VS Code [Lint tasks](./catalog/snippets/configs/vscode-tasks.json)** run the full doc-lint set via Docker `:latest` on demand, the local surface for Markdown, spelling, workflow, and EditorConfig checks.

AGENTS.md:337

  • This sentence links to ./catalog/snippets/vscode/, but this repo does not have a catalog/ directory, so the link is broken. If the canonical extension list is meant to be referenced here, consider vendoring the referenced content or adjusting the reference to point at files that exist in this repo.
- The `.code-workspace` file carries the shared editor settings and the recommended-extension set. **All VS Code settings and extension recommendations live only here, never in a standalone `.vscode/settings.json` or `.vscode/extensions.json`** (`.vscode/` holds only `tasks.json` and `launch.json`). A **standard set** of extensions applies to every repo (markdownlint, cspell, editorconfig, markdown-all-in-one, better-todo-tree, github-actions, actionlint, shellcheck, claude-code); **language-specific** extensions are added per project (.NET: csdevkit, csharpier; Python: python, pylance, ruff, mypy; Docker: the Docker extension). The catalog holds the full set and per-language additions: [`catalog/snippets/vscode/`](./catalog/snippets/vscode/).

Comment thread AGENTS.md
@ptr727
ptr727 merged commit 55ff24f into develop Jul 24, 2026
16 checks passed
@ptr727
ptr727 deleted the feature/880-agents-section-model branch July 24, 2026 15:38
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