Reconcile the PlexCleaner Registry Entry and Report After the 2026-08-15 Resync - #732
Conversation
…-15 resync Closes the hub-side half of RESYNC.md for the PlexCleaner pass promoted this morning (ptr727/PlexCleaner#922, #923, #924, main at 16f196e). Report: the committed one was dated 2026-07-04 and predated the AGENTS.md and GOVERNANCE.md split, the retirement of repo-config/configure.sh, and the README structure sweep. Re-measured at 16f196e rather than carried forward. Two of the workflow divergences it recorded are closed (the validate-release entry gate now runs in both directions, and the release task deletes its transfer artifacts at consumption), two still stand as letter misses, and two new drift items surfaced: no prose gate runs in that repo's CI, and a .gitattributes LF pin matches no tracked file. Registry: the branch-hygiene driftNote described a state this pass did not re-verify and that no longer holds (the Dependabot branches are gone and the live list is longer), so it is deleted per AUDIT.md section 8 rather than re-snapshotted. The other two notes were re-checked and stand. Ledger: the publish-release.yml and validate-task.yml gap dispositions move from investigate to accepted, settled by reading every cataloged repo's copy on its ground-truth branch. Neither can be declared, since the job lists are per-repo and no appliesTo selector separates the carriers from the repos that carry none. What each must honor is already declared through test-pull-request.yml and build-release-task.yml. reports/divergences.md regenerated from the ledger.
There was a problem hiding this comment.
Pull request overview
Updates the hub-side RESYNC artifacts for the PlexCleaner promotion on 2026-08-15 by refreshing the PlexCleaner audit snapshot, reconciling the registry entry, and settling previously “investigate” ledger items so the generated fleet divergence report reflects current dispositions.
Changes:
- Mark
.github/workflows/publish-release.ymland.github/workflows/validate-task.ymlgap dispositions asacceptedinspec/divergences.json. - Replace the stale PlexCleaner audit report with a re-measured 2026-08-15 snapshot and updated ledger settlement narrative.
- Regenerate/refresh derived reporting (
reports/divergences.md,reports/conformance-matrix.md) and remove an obsolete PlexCleaner registry drift note.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/divergences.json | Settles two workflow gap dispositions from investigate to accepted with updated rationale. |
| reports/plexcleaner/audit.md | Replaces the old audit snapshot with a fresh 2026-08-15 report and updated drift/ledger notes. |
| reports/divergences.md | Regenerated divergence report reflecting the updated dispositions and current fleet state. |
| reports/conformance-matrix.md | Records the first audit date for the csharp + python (PlexCleaner) shape. |
| registry/repos.json | Removes a stale PlexCleaner branch-hygiene drift note from the registry entry. |
Suppressed comments (1)
reports/plexcleaner/audit.md:70
- This escalation bullet also claims #721 was "fixed in this change", but there’s no corresponding fix in this PR. Consider removing the "fixed" claim or citing the PR/commit where it was actually fixed.
- **#721, fixed in this change.** `prose_lint.py --check dead-path` cannot recognize a hub-hosted path in a repository that retired the file, so `GOVERNANCE.md:29` here reports as a dead path. This repository is a second carrier of the finding PhotoCleaner hit at its promotion gate.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The report was rewritten whole, which flattened it to LF and failed editorconfig-checker. Normalized back to CRLF, the endings the tree pins. Content: the #721 fix is credited to #731 rather than to this change, the carrier counts say they include the hub's own copy so they read one above the downstream carrier lists in reports/divergences.md, and the workflow model moves off the Types line onto its own.
|
Answering the suppressed finding from round 1, which opens no thread (
Accepted, and it was right on both occurrences. Fixed in 72a3fa1: the escalation bullet now reads "fixed in #731 rather than here", and the Drift Finding that made the same claim cites #731 as well. The rule change lives in #731, which this PR only depends on for the |
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.
Suppressed comments (2)
reports/divergences.md:17
- This generated bullet enumerates the carrier repos in the heading (“carried by …”), but the reason text still says “The carriers are not enumerated here…”, which contradicts what the reader sees and is confusing. Suggest rewording the underlying ledger reason (in spec/divergences.json) so it stays true both in the ledger (no per-repo list) and in the generated report (list is derived from live state).
- **repo-config/configure.sh** (manifest gap, carried by ESPHome-NonRoot, Financial-Modeling, HomeAssistant-Config, LanguageTags, NxWitness, PhotoCleaner, Utilities, VSCode-Server-DotNetCore, Vantage-Config, aiopurpleair, homeassistant-purpleair) - The script is hub-hosted rather than carried, per GOVERNANCE.md "Hub-Hosted Tooling", so it is no longer a manifest entry and a downstream copy is retired rather than re-vendored. Every copy the fleet holds is the hub's content with nothing per-repo in it, and the copies predate the payload-driven check mode, which is the drift this removes rather than converges. Delete the copy as each repo is next visited and run the hub's script against the repo instead. The carriers are not enumerated here, because the fleet-wide gap pass names them from live state and a hand-kept list understated them: it read six while fifteen repos carry one. The ruleset payloads and settings.json stay carried, since those are what the repo is audited against and what its own AUDIT.md diffs the live configuration against.
spec/divergences.json:16
- These ledger reasons refer to “the carrier list above”, but spec/divergences.json itself doesn’t include a carrier list for these gaps, so “above” is ambiguous in the ledger context. Consider referencing the generated report explicitly (or noting it’s the downstream carrier list) to keep the ledger self-explanatory.
{ "path": ".github/workflows/publish-release.yml", "disposition": "accepted", "reason": "A path collision rather than a carry, settled 2026-08-15 by reading every cataloged repo's copy on its ground-truth branch (18 copies read, the hub's own included, and 4 repos carry none, so the carrier list above names 17). Each repo's publisher is its own. The job keys are per-repo (publish in 15 of the 18, against create-release on homeassistant-purpleair, publish-pypi on aiopurpleair, and an eight-job orchestration on NxWitness), and the triggers run from dispatch-only through dispatch plus schedule plus a paths-filtered push. No interface contract the schema can express fits that spread, and no appliesTo selector separates the carriers from the four that carry none, since both source-only and csharp+console repos sit on either side. What the file must honor is declared elsewhere and needs no second entry: build-release-task.yml carries the interface contract for the release path, and WORKFLOW.md's D2.3, D4.1, and D7.1 are read by hand per AUDIT.md section 5.", "tracking": null },
{ "path": ".github/workflows/validate-task.yml", "disposition": "accepted", "reason": "As publish-release.yml, and settled in the same 2026-08-15 read (14 copies read, the hub's own included, and 8 repos carry none, so the carrier list above names 13). Every carrier is on: workflow_call over a per-repo job list, in six distinct shapes across the 14 (lint alone on 3, unit-test plus lint on 5, validate alone on 2, lint plus test plus docs on 2, compile-test plus lint on 1, and unit-test plus lint plus codegen-drift on 1), so the only thing every copy shares is the trigger, which no contract field states. The 8 that carry none inline their validation instead, and no selector separates them, since source-only repos again sit on either side. The fixed part is the required check the aggregator reports, which test-pull-request.yml declares at interface fidelity and the ruleset binds by name.", "tracking": null }
Two suppressed review findings, both about a reference that only resolves in the rendered report. The new reasons said "the carrier list above", which names nothing in the ledger itself, and the configure.sh reason said the carriers are not enumerated here while the generated bullet enumerates them in its heading. Each now names where the list lives.
|
Answering the two suppressed findings from round 2, which open no threads. Both accepted, fixed in 49789c5.
Correct, and it was my wording. Both reasons now say "the carrier list in the generated reports/divergences.md names 17" (and 13), so the reference resolves from inside the ledger rather than only from the rendered page.
Also correct, and pre-existing rather than from this change, but it is one clause and the fix is the same shape as the one above, so it is done here rather than deferred. The |
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.
Suppressed comments (2)
spec/divergences.json:16
- Same self-referential phrasing issue as the publish-release entry: this reason mentions “the generated reports/divergences.md”, but the same string is emitted into that generated report. Rewording to “the downstream carrier list” keeps the meaning without pointing at the report itself.
{ "path": ".github/workflows/validate-task.yml", "disposition": "accepted", "reason": "As publish-release.yml, and settled in the same 2026-08-15 read (14 copies read, the hub's own included, and 8 repos carry none, so the carrier list in the generated reports/divergences.md names 13). Every carrier is on: workflow_call over a per-repo job list, in six distinct shapes across the 14 (lint alone on 3, unit-test plus lint on 5, validate alone on 2, lint plus test plus docs on 2, compile-test plus lint on 1, and unit-test plus lint plus codegen-drift on 1), so the only thing every copy shares is the trigger, which no contract field states. The 8 that carry none inline their validation instead, and no selector separates them, since source-only repos again sit on either side. The fixed part is the required check the aggregator reports, which test-pull-request.yml declares at interface fidelity and the ruleset binds by name.", "tracking": null }
spec/divergences.json:15
- The reason text references
reports/divergences.mdas “the generated reports/divergences.md”, but this string is also embedded verbatim intoreports/divergences.mdduring generation. That makes the report self-referential and less clear. Consider wording that works in both contexts (e.g., “the downstream carrier list”).
This issue also appears on line 16 of the same file.
{ "path": ".github/workflows/publish-release.yml", "disposition": "accepted", "reason": "A path collision rather than a carry, settled 2026-08-15 by reading every cataloged repo's copy on its ground-truth branch (18 copies read, the hub's own included, and 4 repos carry none, so the carrier list in the generated reports/divergences.md names 17). Each repo's publisher is its own. The job keys are per-repo (publish in 15 of the 18, against create-release on homeassistant-purpleair, publish-pypi on aiopurpleair, and an eight-job orchestration on NxWitness), and the triggers run from dispatch-only through dispatch plus schedule plus a paths-filtered push. No interface contract the schema can express fits that spread, and no appliesTo selector separates the carriers from the four that carry none, since both source-only and csharp+console repos sit on either side. What the file must honor is declared elsewhere and needs no second entry: build-release-task.yml carries the interface contract for the release path, and WORKFLOW.md's D2.3, D4.1, and D7.1 are read by hand per AUDIT.md section 5.", "tracking": null },
The reason text is embedded into the generated report, so a phrase naming that report reads as self-referential once rendered. Both reasons now give the downstream count outright, which is true in either context.
|
Answering the round-3 suppressed findings (both the same point, on
Right, and it is the second time this clause has been reworded, so it is now written to need no referent at all: "18 copies read, the hub's own included, so 17 downstream repos carry one and 4 carry none" (and 14/13/8 for the validator). That states the downstream count outright, which is true in the ledger and in the generated report alike, and it also removes the ambiguity the round-2 finding raised. The audit report's matching sentence is reworded the same way. |
… the Upstream Repo-Layout Segment (#734) Closes #719 Closes #720 Closes #721 Closes #722 Promotes six merged `develop` PRs to `main`: - #732 -- Reconcile the PlexCleaner registry entry and audit report after the 2026-08-15 resync (closes #719). - #731 -- Exempt hub-hosted paths from the prose gate's `dead-path` rule (closes #721). - #730 -- Fix the hub slug and the dead anchor in the canonical `copilot-instructions.md` (closes #720, #722). - #723 -- Refresh the PhotoCleaner audit report after the 0e84805 resync. - #733 -- Add an `upstream/` segment to the repo layout convention (addresses #725, not closed -- the fork-naming variant differs from the issue's proposal). - #724 -- Add the HomeAutomation-Config audit report and reconcile its registry entry. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Follow-up to #732, which settled `.github/workflows/publish-release.yml` and `.github/workflows/validate-task.yml` as `accepted` gaps. That call was wrong and this reverses it. ## What was wrong `accepted` means "a path collision, the repo's own file", and its effect is to silence the finding and stop the audit measuring either file ever again. The fleet's intent for these two is the opposite: carry the hub's copy as closely as each repository's targets allow, so a diff against the canonical stays small and readable. The reasoning behind #732 tested both files against `interface` fidelity, found correctly that no named contract fits (job keys and triggers are genuinely per-repo), and then concluded that nothing could be declared. That skipped `intent`, which is exactly the tier for this: presence asserted, equivalence judged by hand against the `intentRef`, content never hashed, and a staleness advisory raised when the hub's canonical moves past a carrier's copy. The `appliesTo` claim was also wrong for the publisher. Re-measured: every repository lacking one carries `releaseTrigger: none` (AudioCleaner, HolidayLights, EspDinIoT, DevKitCIoT), and all 18 carriers carry a publishing trigger. That is an exact selector, and it states something true, namely that a repository which publishes a release has a publisher. ## What this does ```json { "path": ".github/workflows/validate-task.yml", "fidelity": "intent", "intentRef": "WORKFLOW.md#d1---pr-fast-feedback-smoke", "appliesTo": "*" }, { "path": ".github/workflows/publish-release.yml", "fidelity": "intent", "intentRef": "WORKFLOW.md#d4---release--publish", "appliesTo": ["two-phase", "dispatch-only", "publish-on-merge"] } ``` Both ledger rows are deleted, since a declared file is no longer a gap and `fidelity_honesty.py` drops such a row from the generated report by construction. The validator is declared fleet-wide **by decision rather than by measurement**: no selector separates its carriers from the repositories that inline validation into `test-pull-request.yml`, and the maintainer's call is that the reusable task is the fleet standard. The skill text already reads that way, naming `publish-release.yml` in the orchestration layer that is "the standardization baseline". ## Measured impact, whole fleet One full audit run at `audit run 2026-08-15T17:35:45Z | hub 0713008`: | | absent (letter) | staleness advisory (drift) | | --- | --- | --- | | `publish-release.yml` | 0 | 17 | | `validate-task.yml` | 8 | 13 | - The publisher's 0 absences confirm the selector is exact. - The validator's 8 absences are the convergence this asks for: homeassistant-purpleair, KiCadLibrary, EspDinIoT, ESPHome-Config, HomeAssistant-Config, DevKitCIoT, Vantage-Config, HolidayLights. - **17 of the 30 advisories are a false class**, and they are not this change's fault so much as this change's discovery: the intent advisory compares dates with no action-pin normalization, and the hub's publisher last changed in a Dependabot pin bump (`1892d6f`), so every carrier trips at once on drift the fidelity model already calls governed and per-repo. Filed as #735 with three options. - The other 13 are against `0d18078`, which added `ruff format --check`. Real content, though a repository that adopted the same step independently still reports as trailing, which is why the tier is an advisory and not a verdict. ## PlexCleaner report `reports/plexcleaner/audit.md` is updated in place, since it is the report this settlement was written into. Its two new advisories are read and retired in Drift Finding 6: the validator copy already runs `ruff format --check` at a pinned version, and the publisher advisory is the pin-bump class above. Verdict is unchanged at operational. Verified: `spec/validate.py`, `spec/audit.py --selftest` (which asserts no declared path leaks into the hub-only set), `scripts/repo_gate.py`, the whole-tree prose gate, markdownlint, and editorconfig-checker all pass.
…xes (#741) Promotes `develop` to `main`. Two commits since #734, both governance rather than tooling, and the trial merge is conflict-free. Closes #737 Closes #738 ## #736, the publisher and validator declared at intent fidelity `spec/files.json` gains `.github/workflows/publish-release.yml` and `.github/workflows/validate-task.yml`, and the two matching `investigate` rows leave `spec/divergences.json`, a declared file being no longer a gap. This reverses the call #732 shipped. That change settled both as `accepted`, which silences the finding and stops the audit measuring either file again, and the maintainer caught that as the opposite of what the fleet wants for them. `interface` genuinely does not fit, since job keys and triggers are per-repo across every carrier, but `intent` does: presence asserted, equivalence judged by hand, and a staleness advisory when the hub's copy moves past a carrier's. Scope is measured rather than assumed. The publisher applies to the three publishing `releaseTrigger` values, which selects exactly the 18 carriers, since every repository lacking one carries `releaseTrigger: none`. The validator applies to `*` by decision, making the reusable validation task the fleet standard. What promoting this turns on, fleet-wide, measured in one run at `audit run 2026-08-15T17:35:45Z | hub 0713008`: 0 absences for the publisher, 8 for the validator (homeassistant-purpleair, KiCadLibrary, EspDinIoT, ESPHome-Config, HomeAssistant-Config, DevKitCIoT, Vantage-Config, HolidayLights), and 30 staleness advisories. 17 of those 30 are a known false class, since the advisory has no action-pin normalization and the hub's publisher last changed in a Dependabot bump, filed as #735. `reports/plexcleaner/audit.md` is updated in the same commit, since it is the report the earlier settlement was written into. ## #740, two carried-wording fixes Both raised by Copilot against a carried copy on ptr727/ESPHome-Config#94, and both are the same failure: a faithful copy makes every carrier re-litigate one finding. - **#737**: the `GOVENANCE.md` quotation now reads as quoted ("the reviewer's own spelling and a path no diff carries") in the three Markdown occurrences. The misspelling stays literal, because it is the evidence for the sentence it sits in. - **#738**: the `AGENTS.md` sentence named no sections and read as "none of this file is editable". It now names the three byte-locked sections and states that the preamble above them is the repository's own. ## Verification Run against `develop` at `7c67328`: whole-tree prose gate, `repo_gate.py` (eol, eol-coverage, sha-pin), `spec/validate.py`, `spec/audit.py --selftest`, `build_dist.py --check`, markdownlint, and editorconfig-checker all pass. `git merge-tree` of `main` and `develop` is conflict-free, so there is no EOL-only conflict to resolve on this promotion.
Closes #719
The hub-side half of
RESYNC.mdfor the PlexCleaner pass promoted this morning (ptr727/PlexCleaner#922, #923, #924,mainat16f196e). All three checkboxes on the issue.Report (
reports/plexcleaner/audit.md). The committed one was dated 2026-07-04 and described drift that no longer exists. Re-measured at16f196erather than carried forward, so every workflow divergence the old snapshot recorded was re-read:validate-releaseis now a dedicated entry job checking both directions, and the release task deletes itsrelease-asset-*transfer artifacts at the point of consumption.changespaths-filter (it over-builds and cannot under-build), and a dispatch guard that skips silently rather than failing fast..gitattributes:29pins*.Dockerfileto LF with no tracked file matching, which failsrepo_gate.py --check eol-coverage.developis 0 ahead and 89 behindmainwith identical trees, so the count is the promotion-merge artifact rather than the divergence the 2026-07 snapshot reported.Verdict: operational.
spec/audit.py PlexCleanerreports clean after the ledger settlement below.Registry. The branch-hygiene
driftNoteis deleted. The three Dependabot branches it names are gone and the live list holds seven branches beyondmainanddeveloprather than four, so it describes neither state, and branch hygiene is not a baseline deviation any check scores. Re-snapshotting it would only rot again. TheARCHITECTURE.md/codecov.ymlnote and the csharp+python shape note were both re-verified and stand, down to theRegressionTests/pyproject.tomlholding only ruff and mypy config.status,types,publish,requiredSecrets,consumerModel,releaseTrigger, andconfigLayoutare unchanged.Ledger.
.github/workflows/publish-release.ymland.github/workflows/validate-task.ymlmove frominvestigatetoaccepted, settled by reading every cataloged repo's copy on its ground-truth branch rather than by judgment:publishin 15 of 18, againstcreate-release,publish-pypi, and an eight-job orchestration), and triggers run from dispatch-only through dispatch plus schedule plus a paths-filtered push.workflow_calltrigger.interfacecontract the schema can express fits either, and noappliesToselector separates the carriers from the non-carriers, sincesource-onlyrepos sit on both sides of each. What each file must honor is already declared throughtest-pull-request.ymlandbuild-release-task.yml, plus WORKFLOW.md's D-guarantees read by hand.This clears the last standing finding in every repo that carries these two files, so it is worth a second look at review.
reports/divergences.mdis regenerated from the ledger and picks up live fleet state since its last run.Also.
reports/conformance-matrix.mdgets thecsharp+pythonrow's first audit date, this being the first run to judge thepythonchecks.Verified:
spec/validate.py,spec/audit.py --selftest,scripts/repo_gate.py, the whole-tree and diff-scoped prose gates, and markdownlint all pass.