') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Correct the MTP Dependency and Runner Claims in OPERATIONS.md by ptr727 · Pull Request #97 · ptr727/PhotoCleaner · GitHub
Skip to content

Correct the MTP Dependency and Runner Claims in OPERATIONS.md - #97

Merged
ptr727 merged 2 commits into
developfrom
fix-mtp-review-findings
Aug 30, 2026
Merged

Correct the MTP Dependency and Runner Claims in OPERATIONS.md#97
ptr727 merged 2 commits into
developfrom
fix-mtp-review-findings

Conversation

@ptr727

@ptr727ptr727 commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Answers three findings raised on #96, the develop -> main promotion of #95. A finding against a promotion PR cannot be fixed on that PR directly, since its head is develop, so the fix lands here first.

PhotoCleanerTests.csproj: PrivateAssets, and Deliberately Not IncludeAssets

Copilot observed that Microsoft.Testing.Extensions.CodeCoverage carries no PrivateAssets/IncludeAssets metadata, unlike the coverlet.collector it replaced and the xunit.analyzers reference five lines below.

Half of that is right, and the other half breaks the build. Measured both ways:

  • PrivateAssets plus that IncludeAssets list fails to compile. The list (runtime; build; native; contentfiles; analyzers; buildtransitive) omits compile, and MTP's generated registration then cannot see the type: obj/Debug/net10.0/SelfRegisteredExtensions.cs(17,9): error CS0234: The type or namespace name 'CodeCoverage' does not exist in the namespace 'Microsoft.Testing.Extensions'.
  • PrivateAssets="all" alone is fine. 373 tests, exit 0, line-rate="0.7446903312045151", identical to before.

So this takes PrivateAssets="all" and adds a comment saying why the IncludeAssets half must not be copied, since the next reader has the exact list sitting five lines below to copy from.

In fairness to the finding's own stated rationale, the effect here is consistency rather than a leak that was actually happening: PrivateAssets suppresses asset flow to consuming projects, and this test project is never packed and is ProjectReferenced by nothing.

OPERATIONS.md: Two Wrong Claims, Both Introduced by #95

The Dependabot runbook named three packages as carrying Microsoft.Testing.Platform. Only two declare it. dotnet nuget why PhotoCleanerTests/PhotoCleanerTests.csproj Microsoft.Testing.Platform:

 [net10.0]
├── Microsoft.Testing.Extensions.CodeCoverage (v18.10.0)
│ └── Microsoft.Testing.Platform (v2.3.3)
└── xunit.v3 (v4.0.0)
└── xunit.v3.mtp-v2 (v4.0.0)
└── xunit.v3.core.mtp-v2 (v4.0.0)
...

Microsoft.NET.Test.Sdk 18.9.0 declares Microsoft.TestPlatform.TestHost and Microsoft.CodeCoverage, the VSTest stack, and no MTP dependency at all (confirmed against its nuspec and project.assets.json). The skew hazard is between two packages, not three. The paragraph now says so while keeping the point that nuget-deps bumps all three together.

That paragraph also now prescribes the right command. The review suggested dotnet list package --include-transitive. That cannot detect this skew: NuGet unifies the platform to one version per target framework, so it prints a single healthy 2.3.3 row whichever major each package was actually built against. On the 18.0.x/MTP-1.x case WORKFLOW.md D1.6 describes, it would print that same healthy row while the run throws TypeLoadException and reports full coverage over zero tests, which is a false all-clear on precisely the failure the paragraph exists to guard. dotnet nuget why reads declared dependencies and does answer it.

The global.json entry claimed the .NET 10 SDK "no longer runs" the suite under VSTest. It does not drop VSTest. What needs .NET 10 is the global.jsontest.runner key itself, since that is the SDK which reads it; MTP predates the key and an MTP test project is a self-hosting executable. The entry now says that, and names all three things a return to VSTest would take (the adapter, the IsTestingPlatformApplication opt-out, and dropping the key) rather than only the adapter.

Also Measured, Not Changed Here

Microsoft.NET.Test.Sdk now looks like dead weight, since VSTest cannot discover xUnit v3 tests without the adapter this repo dropped. It is not a free removal: without it the build fails with xUnit.net v3 test projects must be executable (set project property '<OutputType>Exe</OutputType>'), because it is what sets that implicitly today. That is its own change with its own surface, so it is not in this PR.

Verification

Build (0 warnings), dotnet csharpier check ., dotnet format style --verify-no-changes, dotnet husky run, markdownlint, and the hub's prose_lint.py over this diff are all clean. The suite runs 373 tests (368 passed, 5 Docker-gated skips) at an unchanged 74.5% line rate.

Not Answered Here

The fourth finding on #96 is against WORKFLOW.md D1.6's secrets: inherit claim. That is hub canonical text and a known hub defect, already filed as ptr727/ProjectTemplate#1114. It is declined in its own thread rather than fixed downstream.

Summary by CodeRabbit

  • Documentation

    • Clarified troubleshooting guidance for Microsoft.Testing.Platform and VSTest dependency version mismatches.
    • Expanded documentation covering .NET SDK requirements, xUnit integration, and configuration for reverting to VSTest.
  • Build & Configuration

    • Updated code coverage tooling configuration so the package remains an internal build dependency and does not flow to consuming projects.
    • Helps prevent unintended package propagation and testing-platform version conflicts.

Answers three findings raised on #96, the promotion of #95.
`PhotoCleanerTests.csproj` takes `PrivateAssets="all"` on
`Microsoft.Testing.Extensions.CodeCoverage`, and deliberately not the
`IncludeAssets` list its sibling references carry. That list omits the `compile`
assets, and MTP's generated `SelfRegisteredExtensions.cs` then fails to build
with `CS0234: The type or namespace name 'CodeCoverage' does not exist`. A
comment records this, since the next reader has the same list five lines below
to copy from.
`OPERATIONS.md` had two wrong claims, both introduced by #95.
The Dependabot runbook said `Microsoft.Testing.Extensions.CodeCoverage`,
`xunit.v3`, and `Microsoft.NET.Test.Sdk` all resolve Microsoft.Testing.Platform
2.3.3. Only the first two declare it: the coverage extension directly, and
`xunit.v3` through `xunit.v3.mtp-v2`. `Microsoft.NET.Test.Sdk` 18.9.0 declares
`Microsoft.TestPlatform.TestHost` and `Microsoft.CodeCoverage`, the VSTest
stack, and no MTP dependency at all. The skew hazard is therefore between two
packages rather than three, and the paragraph now says so while keeping the
point that `nuget-deps` bumps all three together.
That paragraph also now prescribes `dotnet nuget why` rather than
`dotnet list package --include-transitive`. The flat list cannot detect this
skew: NuGet unifies the platform to one version per target framework, so it
prints a single healthy row whichever major each package was built against,
which is a false all-clear on exactly the failure being guarded.
The `global.json` entry said `dotnet test` reaches the suite "rather than the
VSTest host the .NET 10 SDK no longer runs it under". The SDK did not drop
VSTest. What needs .NET 10 is the `global.json` `test.runner` key itself, since
that is the SDK which reads it, and MTP predates the key. The entry now says
that, and names all three things a return to VSTest would take rather than only
the adapter.
Verified: `dotnet nuget why PhotoCleanerTests/PhotoCleanerTests.csproj
Microsoft.Testing.Platform` prints exactly the two roots the prose describes.
Build (0 warnings), csharpier, `dotnet format style`, `dotnet husky run`,
markdownlint, and the hub's `prose_lint.py` over the diff are clean, and the
suite runs 373 tests at an unchanged 74.5% line rate.
CopilotAI lite review requested due to automatic review settings August 30, 2026 15:36
@coderabbitai

coderabbitaiBot commented Aug 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8bb5ba0d-f7e7-491b-9848-1a50e0fd9786

📥 Commits

Reviewing files that changed from the base of the PR and between bdd38f4 and dd4cd3e.

📒 Files selected for processing (1)
  • OPERATIONS.md

Included review availability: Your plan provides up to 10 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The pull request marks the code coverage package as private and updates operational guidance for Microsoft.Testing.Platform, VSTest, Dependabot troubleshooting, and global.json test-runner configuration.

Changes

Test stack dependency guidance

Layer / File(s)Summary
Private code coverage dependency
PhotoCleanerTests/PhotoCleanerTests.csproj
The Microsoft.Testing.Extensions.CodeCoverage reference now uses PrivateAssets="all".
Test stack troubleshooting documentation
OPERATIONS.md
The documentation identifies Microsoft.Testing.Platform package sources, explains platform-version skew symptoms, adds dotnet nuget why guidance, and documents the requirements to use or revert from xUnit MTP integration.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Merge Risk:⚪ Minimal · up to dd4cd

This PR corrects test-project dependency metadata and operational documentation without introducing an actionable merge-blocking risk; it is merge-ready after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately identifies the primary documentation changes in OPERATIONS.md, including corrected MTP dependency and runner information. It does not mention the related project-file change, but …
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title accurately identifies the primary documentation changes in OPERATIONS.md, including corrected MTP dependency and runner information. It does not mention the related project-file change, but the title remains concise and specific.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-mtp-review-findings

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Correct MTP dependency guidance and isolate coverage assets

🐞 Bug fix📝 Documentation⚙️ Configuration changes🕐 10-20 Minutes

Grey Divider

AI Description

• Correct MTP dependency and .NET 10 runner guidance in operations documentation.
• Recommend dotnet nuget why for detecting package-level MTP version skew.
• Keep coverage tooling private without excluding compile assets required by MTP registration.
Diagram

graph TD
CFG["Global runner config"] --> TP["Test project"] --> MTP["MTP platform"]
GROUP["NuGet dependency group"] --> COV["Coverage extension"] --> MTP
GROUP --> XU["xUnit v3"] --> MTP
GROUP --> SDK["Test SDK"] --> VS["VSTest stack"]
Loading
High-Level Assessment

The chosen approach is appropriate: PrivateAssets=&quot;all&quot; prevents transitive exposure without removing compile assets required by MTP registration, while dotnet nuget why reveals each package's declared MTP path rather than NuGet's unified resolved version. Copying the analyzer IncludeAssets filter or using dotnet list package --include-transitive would produce misleading or broken results.

Files changed (2) +4 / -3

Documentation (1) +2 / -2
OPERATIONS.mdCorrect MTP dependency and runner troubleshooting guidance+2/-2

Correct MTP dependency and runner troubleshooting guidance

• Clarifies that only the coverage extension and xUnit v3 bring in Microsoft.Testing.Platform, while Microsoft.NET.Test.Sdk carries VSTest dependencies. Replaces misleading transitive-package inspection guidance with 'dotnet nuget why' and explains the .NET 10 'global.json' runner key versus MTP's independent lifecycle.

OPERATIONS.md

Other (1) +2 / -1
PhotoCleanerTests.csprojPrevent coverage package assets from flowing transitively+2/-1

Prevent coverage package assets from flowing transitively

• Marks Microsoft.Testing.Extensions.CodeCoverage as private to the test project. Documents why the analyzer-style 'IncludeAssets' filter must not be copied: excluding compile assets breaks generated MTP extension registration with CS0234.

PhotoCleanerTests/PhotoCleanerTests.csproj

CopilotAI 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.

🟢 Approval recommended

The changes are narrowly scoped to documentation corrections and a safe, build-oriented test dependency metadata tweak with no issues found in the reviewed diff.

Pull request overview

This PR corrects operational documentation about the Microsoft.Testing.Platform (MTP) dependency chain and test-runner requirements, and updates the test project’s coverage package reference metadata to prevent a build break from a copied IncludeAssets pattern.

Changes:

  • Set PrivateAssets="all" on Microsoft.Testing.Extensions.CodeCoverage and document why IncludeAssets must not be copied from xunit.analyzers.
  • Fix OPERATIONS.md to correctly identify which packages declare MTP, and prescribe dotnet nuget why (not dotnet list package --include-transitive) for diagnosing platform-major skew.
  • Clarify the global.json guidance: .NET 10+ is required to read the test.runner key, and reverting to VSTest would require multiple coordinated changes.
File summaries
FileDescription
PhotoCleanerTests/PhotoCleanerTests.csprojAdds PrivateAssets="all" to the MTP coverage extension and documents why IncludeAssets is intentionally omitted.
OPERATIONS.mdCorrects MTP dependency claims, updates the Dependabot troubleshooting command, and clarifies the global.json/runner requirements and VSTest rollback steps.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@qodo-code-review

qodo-code-reviewBot commented Aug 30, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Remediation recommended

1. VSTest rollback omits coverage✓ Resolved🐞 Bug≡ Correctness
Description
The new claim that returning to VSTest takes only three changes omits replacing
Microsoft.Testing.Extensions.CodeCoverage with the VSTest coverage collector. Following these
instructions would leave the repository's documented CI coverage setup coupled to MTP, so the
rollback would not preserve its coverage behavior.
Code

OPERATIONS.md[101]

+- [global.json](./global.json) selects Microsoft.Testing.Platform as the test runner for the whole repo. The `test.runner` key itself is what needs the .NET 10 SDK or later, since that is the SDK which reads it. MTP is not new in .NET 10 and an MTP test project is a self-hosting executable, so the platform predates the key. xUnit v3 ships separate VSTest and MTP integrations, and this repo now uses only the second. Going back to VSTest would take three things, not one: the `xunit.runner.visualstudio` adapter, the `IsTestingPlatformApplication` opt-out on the test project, and dropping this key. `global.json` declares no `sdk` key, so it pins no SDK version and affects nothing but test execution.
Evidence
The test project directly references the MTP coverage extension, and the repository's workflow
contract explicitly distinguishes that extension from coverlet.collector, the VSTest collector.
The operations guide also states that the current --coverage invocation is serviced by the MTP
extension, proving that runner rollback involves coverage configuration beyond the three listed
changes.

PhotoCleanerTests/PhotoCleanerTests.csproj[14-16]
WORKFLOW.md[152-152]
OPERATIONS.md[20-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The VSTest rollback instructions list only the runner adapter, project opt-out, and `global.json` change, but omit migrating the MTP-specific coverage package and invocation back to their VSTest equivalents.
## Issue Context
`WORKFLOW.md` explicitly says `Microsoft.Testing.Extensions.CodeCoverage` replaces the VSTest `coverlet.collector`, while `OPERATIONS.md` documents the current MTP extension as the component producing coverage for CI.
## Fix Focus Areas
- OPERATIONS.md[101-101]
- PhotoCleanerTests/PhotoCleanerTests.csproj[14-16]
- OPERATIONS.md[20-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 7 rules
Review mode: ⚖️ Balanced: The PR changes runtime project configuration and operational guidance for the test runner, so it is not skip-eligible; its localized logic is low-risk but warrants a complete single-pass review to verify dependency metadata and claims.

Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadOPERATIONS.md Outdated
Qodo raised, against the previous commit, that the `global.json` entry named
three things as selecting Microsoft.Testing.Platform and omitted the coverage
package. Correct: with `Microsoft.Testing.Extensions.CodeCoverage` in place, a
project carrying only the other three would run under VSTest with no coverage
collector at all, so the list understated what the choice rests on.
The entry now names four rather than three, and no longer frames them as a
rollback recipe, since a recipe stated in a runbook rots into a wrong one. It
describes the current state instead, which carries the same information without
promising a procedure.
It also records that a move back is not this repo's alone to make. The
`dotnet test` invocation that collects coverage lives in the hub-hosted
validator, so the runner choice is only partly local.
Verified: build (0 warnings), 373 tests at an unchanged 74.5% line rate,
markdownlint clean, and the hub's `prose_lint.py` clean over the diff, with the
one remaining `sentence-length` hit on `OPERATIONS.md:47` being the pre-existing
opening sentence this branch does not touch.
CopilotAI review requested due to automatic review settings August 30, 2026 15:41

CopilotAI 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.

🟢 Approval recommended

Changes are narrowly scoped, internally consistent with the referenced workflow contract, and appear unlikely to introduce functional or documentation regressions.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@ptr727
ptr727 merged commit 0113879 into developAug 30, 2026
19 checks passed
@ptr727
ptr727 deleted the fix-mtp-review-findings branch August 30, 2026 15:45
ptr727 added a commit that referenced this pull request Aug 30, 2026
The doc-drift half of the hub resync against ptr727/ProjectTemplate at
2.0.526, separated from the MTP migration (#95, #97) because the two are
different drift classes. Audit run stamp 2026-08-30T20:48:19Z, hub f3b4cc9.
- `GOVERNANCE.md`, two `verbatim` sections re-vendored byte-exact. "Durable
Knowledge and Self-Improvement" had lost the bullet on when a durable rule
earns a mechanical hook, and "Repository Boundaries and Write Safety" trailed
the hub on the worktree-isolation bullet, which now names the `gh-write-guard`
hook backstop and the standalone-clone fallback's grant.
- `WORKFLOW.md`, two dropped hub clauses restored. D8.3 regains the sentence on
a tracker setting `auto-merge: false`, and D1.2 regains the parenthetical
naming both `needs:` edges on the validation job. Every repo-specific
annotation on D1.1, D1.2, D1.4, D1.5, D4.1 and the S1 to S11 rows is kept.
- `AGENTS.md`, the intro said the file holds "two things". It has held three
since the Fleet Bootstrap section was carried, so it now says so.
- `.editorconfig-checker.json`, the hub's `Exclude` block carried. This repo has
no Python tree, but `uv` creates those cache directories when running a Python
script from the hub against this checkout, so the excludes are reachable here.
- `.github/skills/repo-worktree/SKILL.md` and `resync-a-repo/SKILL.md`,
verbatim re-vendors.
Deliberately not changed. `WORKFLOW.md` Section 3 keeps its local "and the
hub's `repo-config/README.md`" pointer, which the hub does host and which
matches how `AUDIT.md` already refers to hub-hosted tooling.
Verified: every repo-specific block in the three mixed-fidelity files survives
the re-vendor, checked by full-file diff against both the hub and the pre-change
copy. All 18 verbatim `GOVERNANCE.md` sections and all 3 `AGENTS.md` sections
now byte-match hub f3b4cc9, and `diff -rq` over `.github/skills/` is empty.
markdownlint and the hub's `prose_lint.py` over the diff are clean.
ptr727 added a commit that referenced this pull request Aug 30, 2026
* Re-Vendor Drifted Governance Sections and Skill Files from the Hub
The doc-drift half of the hub resync against ptr727/ProjectTemplate at
2.0.526, separated from the MTP migration (#95, #97) because the two are
different drift classes. Audit run stamp 2026-08-30T20:48:19Z, hub f3b4cc9.
- `GOVERNANCE.md`, two `verbatim` sections re-vendored byte-exact. "Durable
Knowledge and Self-Improvement" had lost the bullet on when a durable rule
earns a mechanical hook, and "Repository Boundaries and Write Safety" trailed
the hub on the worktree-isolation bullet, which now names the `gh-write-guard`
hook backstop and the standalone-clone fallback's grant.
- `WORKFLOW.md`, two dropped hub clauses restored. D8.3 regains the sentence on
a tracker setting `auto-merge: false`, and D1.2 regains the parenthetical
naming both `needs:` edges on the validation job. Every repo-specific
annotation on D1.1, D1.2, D1.4, D1.5, D4.1 and the S1 to S11 rows is kept.
- `AGENTS.md`, the intro said the file holds "two things". It has held three
since the Fleet Bootstrap section was carried, so it now says so.
- `.editorconfig-checker.json`, the hub's `Exclude` block carried. This repo has
no Python tree, but `uv` creates those cache directories when running a Python
script from the hub against this checkout, so the excludes are reachable here.
- `.github/skills/repo-worktree/SKILL.md` and `resync-a-repo/SKILL.md`,
verbatim re-vendors.
Deliberately not changed. `WORKFLOW.md` Section 3 keeps its local "and the
hub's `repo-config/README.md`" pointer, which the hub does host and which
matches how `AUDIT.md` already refers to hub-hosted tooling.
Verified: every repo-specific block in the three mixed-fidelity files survives
the re-vendor, checked by full-file diff against both the hub and the pre-change
copy. All 18 verbatim `GOVERNANCE.md` sections and all 3 `AGENTS.md` sections
now byte-match hub f3b4cc9, and `diff -rq` over `.github/skills/` is empty.
markdownlint and the hub's `prose_lint.py` over the diff are clean.
* Drop the D1.2 Parenthetical Again, Which Is False for This Repo
Both reviewers independently flagged the D1.2 clause restored in the previous
commit. They are right, and the restore was a mistake.
The hub's parenthetical reads "(both the aggregator and `smoke-build`, which
`needs:` the validation job by name)". In this repo `smoke-build` declares
`needs: [changes]` and nothing else, per
`.github/workflows/test-pull-request.yml`, so the clause asserts an edge that
does not exist here. The bullet's own repo-specific annotation two sentences
later already says as much: the aggregator `needs:` validate directly,
independent of `changes`/`smoke-build`.
So its absence from this copy was a deliberate local adaptation rather than
drift from the hub, and re-vendoring it put a false claim about this repo's own
workflow into this repo's own contract doc. D1.2 goes back to the form it had
on develop.
This does not generalize to the D8.3 clause in the same commit, which stays.
That one describes a tracker this repo does not have, rather than contradicting
a workflow it does have, and `WORKFLOW.md` carries the whole D8 section as
inapplicable-but-present already.
Verified against the workflow rather than the doc: `grep` for the `needs:` lines
in `test-pull-request.yml` gives `smoke-build` -> `[changes]` and
`check-workflow-status` -> `[changes, validate, smoke-build]`. markdownlint and
the hub's `prose_lint.py` over the diff stay clean.
@ptr727ptr727 mentioned this pull request Aug 30, 2026
Sign up for freeto 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

@ptr727