From 064ebe81cd603a17c7afb248d86d37bae259b646 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 05:47:15 +0000 Subject: [PATCH 1/5] Bump astral-sh/setup-uv from 9.0.0 to 10.0.1 in the actions-deps group (#927) Bumps the actions-deps group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv). Updates `astral-sh/setup-uv` from 9.0.0 to 10.0.1 - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/c771a70e6277c0a99b617c7a806ffedaca235ff9...20cfd1bf945f4377ade1205e4dbc17946fc9a30d) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions-deps ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/validate-task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-task.yml b/.github/workflows/validate-task.yml index bd5a7274..400be2fd 100644 --- a/.github/workflows/validate-task.yml +++ b/.github/workflows/validate-task.yml @@ -89,7 +89,7 @@ jobs: # the VSCode tasks run the latest tools, so local may differ slightly by design. Config lives # in RegressionTests/pyproject.toml, so run from that directory (mypy resolves config from CWD). - name: Setup uv step - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 - name: Lint Python step working-directory: RegressionTests From 86ed9a56c3c347f18cfe84b5a0f387dad8717e2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:48:06 +0000 Subject: [PATCH 2/5] Bump streetsidesoftware/cspell-action in the actions-deps group (#931) Bumps the actions-deps group with 1 update: [streetsidesoftware/cspell-action](https://github.com/streetsidesoftware/cspell-action). Updates `streetsidesoftware/cspell-action` from 8.4.0 to 9.0.1 - [Release notes](https://github.com/streetsidesoftware/cspell-action/releases) - [Changelog](https://github.com/streetsidesoftware/cspell-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/streetsidesoftware/cspell-action/compare/de2a73e963e7443969755b648a1008f77033c5b2...e0668cf020899e887ee8ad4d173c31738a79eae8) --- updated-dependencies: - dependency-name: streetsidesoftware/cspell-action dependency-version: 9.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions-deps ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/validate-task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-task.yml b/.github/workflows/validate-task.yml index 400be2fd..b90d6cb9 100644 --- a/.github/workflows/validate-task.yml +++ b/.github/workflows/validate-task.yml @@ -77,7 +77,7 @@ jobs: # Spell-check the user-facing docs; word list + exclusions live in cspell.json (shared with the editor). - name: Spell check step - uses: streetsidesoftware/cspell-action@de2a73e963e7443969755b648a1008f77033c5b2 # v8.4.0 + uses: streetsidesoftware/cspell-action@e0668cf020899e887ee8ad4d173c31738a79eae8 # v9.0.1 with: files: | README.md From d03675124e7f51cc113d59a316fcb9c59e828d74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Aug 2026 05:46:56 +0000 Subject: [PATCH 3/5] Bump docker/setup-buildx-action in the actions-deps group (#933) Bumps the actions-deps group with 1 update: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action). Updates `docker/setup-buildx-action` from 4.2.0 to 4.3.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/bb05f3f5519dd87d3ba754cc423b652a5edd6d2c...37fe631027851001ddb9b187196cc803df7f5f0e) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-deps ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docker-task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-docker-task.yml b/.github/workflows/build-docker-task.yml index 0c89fa5f..81d6ead1 100644 --- a/.github/workflows/build-docker-task.yml +++ b/.github/workflows/build-docker-task.yml @@ -65,7 +65,7 @@ jobs: platforms: arm64 - name: Setup Buildx step - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 with: platforms: ${{ env.PLATFORMS }} From 0e9b0b9870a95a0f8bdc8135ae812e634d45ed8a Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Sun, 30 Aug 2026 08:09:37 -0700 Subject: [PATCH 4/5] Resync With the Hub, Migrate to MTP, and Adopt the Reusable Workflow Chain (#940) * Adopt the fleet LF line-ending default and renormalize the tree The hub moved the fleet default from CRLF-with-LF-exceptions to LF-with-a-CRLF-exception-for-bat-and-cmd. `.editorconfig` now declares `[*] end_of_line = lf` and `.gitattributes` declares `* text=auto eol=lf`, so git enforces the ending on checkout and renormalize rather than leaving it to the editor. The per-type LF pins those two files carried (`*.sh`, the husky hook, `uv.lock`, Dockerfiles, workflow YAML) are redundant under the new default and are dropped. `git add --renormalize .` converts the 160 tracked CRLF files to LF. Only `.editorconfig`, `.editorconfig-checker.json` and `.gitattributes` carry content changes; every other file in this commit is line-endings only, as `git diff --ignore-cr-at-eol` shows. The six binary files are untouched. * Re-vendor the carried instruction set from the hub Carries `CLAUDE.md`, the file that imports `AGENTS.md` into a Claude Code session, which this repo never had. Re-vendors the verbatim sections the audit reported stale: `AGENTS.md` "Context and Delegation Discipline" and "Where the Rules Live", and `GOVERNANCE.md` "Durable Knowledge and Self-Improvement", "Repository Boundaries and Write Safety", "Operational Repositories", "Hub-Hosted Tooling", "Verification Discipline", "PR Review Etiquette", "Workflow YAML Conventions" and "Repository Details". The repo-specific intro paragraphs, "Devcontainer" and "Repository Layout" are intent-fidelity and stay this repo's own. "Running the Linters Locally" is promoted from `###` to `##`, matching the hub's own heading level so the `AGENTS.md` rules table resolves, and takes the hub's current content: the per-tool Docker one-liners are superseded by the hub-hosted `scripts/docker_lint.py` wrapper. The PowerShell block goes with them, since this repo tracks no `.ps1` file and the wrapper discovers its own targets. `CODESTYLE.md` takes the hub's current local-gate and Shell wording, and `AGENTS.md` now names the `shell-codestyle` Skill alongside the other two. The PlexCleaner .NET and Python subsections are unchanged. `AUDIT.md` is rewritten against hub-hosted configuration: `repo-config/` and `spec/secrets.json` are no longer carried, so the self-audit reaches `repo-config/configure.sh check` and `spec/audit.py` from a hub checkout rather than diffing local payloads that are about to be deleted. `.github/copilot-instructions.md` takes the hub's current runbook, which routes to `scripts/pr_review.py` in place of the hand-rolled GraphQL. The "Disproved Claims" section keeps its shape and rules and carries no entry: this repo had none of its own, and the hub's are proofs about the hub's tree. * Delete the retired repo-config and spec carries `spec/divergences.json` gives both trees a `retire` disposition: the branch rulesets, the repository settings and the secrets declaration are hub-hosted ground truth reached from a hub checkout, not payloads a repo carries. A carried copy can only restate the hub's computation or drift from it between resyncs. The inbound sweep re-points the two "Repository Layout"/"Configuration Layout" bullets that described the directories, and drops the `host-tools.json` note's aside citing the carried `spec/secrets.json` as precedent for omitting a `$schema` pointer. `AUDIT.md` was already rewritten against the hub-hosted payloads in the previous commit. The `HISTORY.md` mention stays: it records what a past release shipped and was true then. * Carry the .github/skills tree from the hub `spec/files.json` declares `.github/skills` a `verbatim-tree` with `prune`, applying to every fleet repo, so the 37 files are carried whole rather than adapted. `scripts/carry.py apply` wrote them and reports the source and target digests equal. `.github/copilot-instructions.md` already points a review at `.github/skills/code-review/SKILL.md`; until now that path resolved to nothing here. * Migrate the test project to Microsoft.Testing.Platform The .NET 10 SDK refuses to run a VSTest target for a project that pulls in `Microsoft.Testing.Platform.MSBuild`, which xunit.v3 4.0.0 does. That is what has been failing the `Run unit tests` and `Build Docker image` jobs on Dependabot's nuget-deps bumps (#937 to `develop`, #938 to `main`), each re-rolled once with the same result, so the group has not landed since xunit.v3 went to 4.0.0. ptr727/ProjectTemplate#1088 catalogs the same break across the fleet and recommends the coverlet.MTP route, already round-tripped in ptr727/LanguageTags#325, and this is that migration. - `global.json` opts `dotnet test` into Microsoft.Testing.Platform. The hub cannot supply this file, since it lives in each consumer's own root. - `xunit.runner.visualstudio` is dropped, being the VSTest adapter. - `coverlet.collector` becomes `coverlet.MTP`, whose self-registration codegen needs the package on the test project's compile-time closure, so the `PrivateAssets`/`IncludeAssets` restriction the VSTest data collector carried is not re-applied. - The CI unit-test step becomes `dotnet test --coverlet --coverlet-output-format cobertura --results-directory ./coverage`, which still lands Cobertura XML where the existing Codecov step reads it. - `Docker/Dockerfile` copies `global.json` into the builder, without which `Docker/Build.sh`'s own `dotnet test` falls back to VSTest and fails the image build the same way. The rest of the group's bumps ride along, and `ptr727.LanguageTags` and `ptr727.Utilities` go to their current versions rather than the ones the stale Dependabot PR names. `dotnet outdated` reports nothing outdated, and `.config/dotnet-tools.json` is already at the current csharpier 1.3.0, husky 0.9.1 and dotnet-outdated-tool 4.8.1. Verified locally on the .NET 10.0.400 SDK: 239 of 239 tests pass under MTP, Cobertura XML is produced, and `csharpier check` and `dotnet format style --verify-no-changes` are clean. * Adopt the hub-hosted reusable workflow chain `spec/divergences.json` gives `build-release-task.yml`, `build-docker-task.yml` and `get-version-task.yml` a `retire` disposition, and the audit reported `publish-release.yml` missing its `plan` and `validate` jobs and `merge-bot-pull-request.yml` missing `merge-bot`. Both findings are the same migration, which the hub's `docs/reusable-workflows.md` tracks with PlexCleaner as an open checkbox on stages 1, 3 and 4. - `merge-bot-pull-request.yml` becomes the caller stub. The hub task is a superset of the two jobs carried here, and this repo passes no `rules` or `delete-branch` input: it has no tracker branch outside the built-in pairs, and `delete_branch_on_merge` is off fleet-wide. - `publish-release.yml` gains `plan` (the hub's `publish-plan-task`), which replaces the `ref_name in (main, develop)` job guard and now fails a dispatch from any other branch rather than skipping silently, and `validate`, which is the gate the retired local `build-release-task` used to run inside itself. `publish` calls the hub's `build-release-task`, and `publish-docker-readme` calls the hub's task for the Docker Hub overview, which the retired local Docker task used to push as a step. - `test-pull-request.yml` keeps its `push`-on-every-branch trigger and its aggregator, and its `smoke-build` now calls the hub release task. Both callers move to `permissions: {}` with a per-job `contents: read` grant, in place of the repository default of `write`. - `build-executable-task.yml` is deleted with them. It is not a hub-hosted file, but the hub's `dotnet-publish` default builds the same seven runtimes with the same MSBuild properties and archives the same `PlexCleaner.7z`, so no hook is needed. The `docker-prepare` default likewise emits this repo's exact tags, `./Docker/Dockerfile` context and cache repository. `validate-task.yml` stays carried: the hub's own unit-test step is the VSTest invocation Microsoft.Testing.Platform rejects (ptr727/ProjectTemplate#1088). `WORKFLOW.md` is reconciled against the new job graph, including all three flow diagrams, D0.4 for the pin contract, the D4.1 dispatch-guard change, D4.6 moving the validate gate to the caller, D9.5 naming a carried copy of a hub task a defect, and a new S15 trace for a hub-pin bump. `ARCHITECTURE.md`, `GOVERNANCE.md` "Repository Layout", `OPERATIONS.md` and `PlexCleaner.slnx` follow the same sweep. Verified locally: `actionlint` clean over the four workflows, markdownlint, cspell, ruff, ruff format, mypy and editorconfig-checker clean. * Exclude build output from the EditorConfig check The hub's `.editorconfig-checker.json` excludes the Python cache directories and nothing else, because editorconfig-checker normally scopes itself with `git ls-files` and never sees ignored build output. That fails in a git worktree, which is the layout `repo-worktree` mandates for every task: `.git` is a pointer file there, so `git` is unusable inside the linter's container and it falls back to walking the filesystem. It then reports 25 end-of-line errors against `.artifacts/**` `.pdb`, `.cache`, and the MTP-generated `SelfRegisteredExtensions.cs` after any local build. `.editorconfig-checker.json` is `intent` fidelity in `spec/files.json`, so this repo adds the three patterns its own `.gitignore` already lists. Reproduced before the change and clean after, in this worktree. * Select the test project with --project in the Docker build The Docker image build failed on this branch with "Specifying a project for 'dotnet test' should be via '--project'". Under Microsoft.Testing.Platform, which `global.json` now opts into, no 10.x SDK honors a positional project path, and the two SDKs this repo meets differ only in how loudly they say so. The 10.0.400 SDK the host pins ignores the path and resolves from the current directory, which is why this passed locally. The newer `dotnet-sdk-10.0` apt package the builder stage installs from `ubuntu:rolling` fails outright. The quiet arm is the worse one in the builder, since `/Builder` carries neither `PlexCleaner.slnx` nor a root project for that fallback to find, so `--project` is required there rather than merely tidier. Verified by rebuilding the builder stage with `--no-cache-filter builder`: 239 of 239 tests pass inside the container. * Answer the first review round Three findings from the review, each verified before acting on it. `createschema` now writes `PlexCleaner.schema.json` with LF and a trailing newline, so a regeneration is byte-identical to the tracked file instead of a whole-file working-tree diff against the repo's new LF default. The line ending is set on that one write rather than on `ConfigFileJsonContext`, which was the first attempt. That context also writes the user's own `PlexCleaner.json`, through `WriteDefaultsToFile`, `OpenAndUpgrade`'s schema upgrade, and the `RegisterInvalidFiles` ignore-list update, so flipping it there would silently rewrite a Windows user's settings file to LF on the next run that upgrades it. `PlexCleaner.defaults.json` is not a beneficiary either way: its comments are hand-restored and its `UseSystem`/`AutoUpdate` values are platform-dependent, so it cannot be regenerated in place at all. The sidecar, tool-info and process-result contexts keep CRLF, unchanged. Verified: `createschema` leaves the tree clean, and `defaultsettings` against a scratch path still writes CRLF. `publish-release.yml`'s comment above the `plan` job said a feature-branch dispatch resolves `publish == false`. The hub task exits with an `::error::` instead, which this branch's own D4.1 already states. `RegressionTests/README.md` said Python source is CRLF, which this branch made untrue. * Deserialize idet theory data to the type xUnit asked for `FfMpegIdetInfoSerializer.Deserialize` called `JsonSerializer.Deserialize`, deserializing into the serializer class rather than into `FfMpegIdetInfo`, and fell back to a bare `new object()` on null. Both arms return something the `Parse_Idet_Parse_Test` theory's `FfMpegIdetInfo` parameter cannot accept, so any execution path that round-trips theory data through the registered serializer fails at the parameter bind rather than in the serializer. Proved by reflection against the built test assembly: with the old code `Deserialize(typeof(FfMpegIdetInfo), json)` returns `PlexCleanerTests.FfMpegIdetInfoSerializer`, and with the new code it returns `PlexCleaner.FfMpegIdetInfo`. The whole suite is unaffected either way, 239 of 239 before and after, because the in-process run hands theory data to the test directly rather than through the serializer, which is why this has sat latent. Pre-existing rather than introduced here, but the file is in the test project this branch migrates to Microsoft.Testing.Platform, the execution host that decides whether the round-trip happens at all, and the fix is one line. Raised by Copilot as a body-only finding on all three review rounds. --- .config/dotnet-tools.json | 54 +- .dockerignore | 74 +- .editorconfig | 489 +- .editorconfig-checker.json | 30 +- .gitattributes | 36 +- .github/ISSUE_TEMPLATE/bug_report.yml | 172 +- .github/ISSUE_TEMPLATE/config.yml | 10 +- .github/copilot-instructions.md | 400 +- .github/dependabot.yml | 86 +- .github/skills/add-host-tool/SKILL.md | 46 + .github/skills/agent-conduct/SKILL.md | 47 + .github/skills/audit-a-repo/SKILL.md | 37 + .../carried-instruction-file-guard/SKILL.md | 31 + .github/skills/code-review/SKILL.md | 71 + .github/skills/comment-and-doc-style/SKILL.md | 251 + .../references/carried-doc-references.md | 61 + .../references/line-endings.md | 117 + .../references/markdown-links.md | 64 + .../copilot-instructions-keeper/SKILL.md | 95 + .github/skills/dotnet-codestyle/SKILL.md | 211 + .../references/conventions.md | 136 + .../references/project-config.md | 21 + .../dotnet-codestyle/references/testing.md | 25 + .github/skills/drive-pr/SKILL.md | 131 + .../skills/fleet-conformance-check/SKILL.md | 74 + .../skills/git-commit-conventions/SKILL.md | 167 + .../references/history-rewrite.md | 24 + .github/skills/local-strict-review/SKILL.md | 71 + .github/skills/merge-and-release/SKILL.md | 225 + .../operational-vs-release-workflow/SKILL.md | 156 + .../branch-protection-and-promotion.md | 110 + .../references/release-publish-mechanics.md | 135 + .github/skills/pr-review-conduct/SKILL.md | 178 + .github/skills/python-codestyle/SKILL.md | 185 + .../python-codestyle/references/code-style.md | 93 + .../python-codestyle/references/profiles.md | 74 + .../python-codestyle/references/testing.md | 17 + .github/skills/repo-worktree/SKILL.md | 229 + .github/skills/resync-a-repo/SKILL.md | 85 + .github/skills/shell-codestyle/SKILL.md | 62 + .github/skills/skill-lifecycle/SKILL.md | 49 + .github/skills/standup-a-repo/SKILL.md | 105 + .../upstream-contribution-workflow/SKILL.md | 84 + .github/skills/workflow-ci-contract/SKILL.md | 47 + .../references/d-guarantees.md | 70 + .../references/test-methodology.md | 27 + .github/workflows/build-docker-task.yml | 113 - .github/workflows/build-executable-task.yml | 107 - .github/workflows/build-release-task.yml | 225 - .github/workflows/get-version-task.yml | 56 - .github/workflows/merge-bot-pull-request.yml | 90 +- .github/workflows/publish-release.yml | 78 +- .github/workflows/test-pull-request.yml | 27 +- .github/workflows/validate-task.yml | 6 +- .gitignore | 40 +- .husky/task-runner.json | 64 +- .markdownlint-cli2.jsonc | 36 +- .vscode/launch.json | 912 +-- .vscode/tasks.json | 802 +-- AGENTS.md | 215 +- ARCHITECTURE.md | 963 +-- AUDIT.md | 105 +- CLAUDE.md | 5 + CODESTYLE.md | 156 +- Directory.Build.props | 28 +- Directory.Packages.props | 47 +- Docker/Build.sh | 8 +- Docker/Dockerfile | 2 + Docker/README.md | 70 +- Docs/ClosedCaptions.md | 372 +- Docs/CustomOptions.md | 212 +- Docs/LanguageMatching.md | 54 +- GOVERNANCE.md | 627 +- HISTORY.md | 916 +-- LICENSE | 42 +- OPERATIONS.md | 119 +- PlexCleaner.code-workspace | 100 +- PlexCleaner.defaults.json | 364 +- PlexCleaner.schema.json | 692 +- PlexCleaner.slnx | 164 +- PlexCleaner/AssemblyVersion.cs | 96 +- PlexCleaner/AudioProps.cs | 38 +- PlexCleaner/Bitrate.cs | 224 +- PlexCleaner/BitrateInfo.cs | 244 +- PlexCleaner/CommandLineOptions.cs | 984 +-- PlexCleaner/ConfigFileJsonSchema.cs | 720 ++- PlexCleaner/Convert.cs | 370 +- PlexCleaner/ConvertOptions.cs | 326 +- PlexCleaner/DtsInfo.cs | 106 +- PlexCleaner/Extensions.cs | 58 +- PlexCleaner/FfMpegBuilder.cs | 556 +- PlexCleaner/FfMpegIdetInfo.cs | 528 +- PlexCleaner/FfMpegTool.cs | 1084 ++-- PlexCleaner/FfMpegToolJsonSchema.cs | 398 +- PlexCleaner/FfProbeBuilder.cs | 320 +- PlexCleaner/FfProbeTool.cs | 1004 +-- PlexCleaner/GitHubRelease.cs | 88 +- PlexCleaner/GlobalUsings.cs | 6 +- PlexCleaner/HandBrakeBuilder.cs | 346 +- PlexCleaner/HandBrakeTool.cs | 320 +- PlexCleaner/IProcessPlugin.cs | 82 +- PlexCleaner/JsonSerialization.cs | 134 +- PlexCleaner/KeepAwake.cs | 84 +- PlexCleaner/Language.cs | 62 +- PlexCleaner/LoggerFactory.cs | 220 +- PlexCleaner/MatroskaStructure.cs | 360 +- PlexCleaner/MediaInfoBuilder.cs | 184 +- PlexCleaner/MediaInfoTool.cs | 496 +- PlexCleaner/MediaInfoToolJsonSchema.cs | 212 +- PlexCleaner/MediaInfoToolXmlSchema.cs | 188 +- PlexCleaner/MediaInfoXmlParser.cs | 870 +-- PlexCleaner/MediaProps.cs | 478 +- PlexCleaner/MediaTool.cs | 1030 +-- PlexCleaner/MediaToolInfo.cs | 148 +- PlexCleaner/Metrics.cs | 466 +- PlexCleaner/MkvMergeBuilder.cs | 394 +- PlexCleaner/MkvMergeTool.cs | 674 +- PlexCleaner/MkvProcess.cs | 122 +- PlexCleaner/MkvPropEditBuilder.cs | 304 +- PlexCleaner/MkvPropEditTool.cs | 410 +- PlexCleaner/MkvToolJsonSchema.cs | 374 +- PlexCleaner/Monitor.cs | 638 +- PlexCleaner/PerFileLogLevel.cs | 166 +- PlexCleaner/PlexCleaner.csproj | 132 +- PlexCleaner/PluginLoader.cs | 238 +- PlexCleaner/Process.cs | 1292 ++-- PlexCleaner/ProcessDriver.cs | 1090 ++-- PlexCleaner/ProcessFile.cs | 5712 ++++++++--------- PlexCleaner/ProcessOptions.cs | 954 +-- PlexCleaner/ProcessResultJsonSchema.cs | 210 +- PlexCleaner/Program.cs | 1174 ++-- PlexCleaner/Properties/launchSettings.json | 238 +- PlexCleaner/SelectMediaProps.cs | 290 +- PlexCleaner/SevenZipBuilder.cs | 220 +- PlexCleaner/SevenZipTool.cs | 418 +- PlexCleaner/SidecarFile.cs | 1468 ++--- PlexCleaner/SidecarFileJsonSchema.cs | 654 +- PlexCleaner/SubtitleProps.cs | 326 +- PlexCleaner/TagMap.cs | 24 +- PlexCleaner/TagMapSet.cs | 278 +- PlexCleaner/ToolInfoJsonSchema.cs | 134 +- PlexCleaner/Tools.cs | 712 +- PlexCleaner/ToolsOptions.cs | 88 +- PlexCleaner/TrackProps.cs | 1610 ++--- PlexCleaner/VerifyClassifier.cs | 174 +- PlexCleaner/VerifyOptions.cs | 144 +- PlexCleaner/VerifyResult.cs | 26 +- PlexCleaner/VideoProps.cs | 488 +- PlexCleanerTests/.editorconfig | 20 +- PlexCleanerTests/ClosedCaptionsProbeTests.cs | 98 +- PlexCleanerTests/CommandLineTests.cs | 1118 ++-- PlexCleanerTests/ConfigFileTests.cs | 166 +- PlexCleanerTests/DefaultTrackFlagsTests.cs | 230 +- PlexCleanerTests/DtsInfoTests.cs | 232 +- PlexCleanerTests/FfMpegIdetDecisionTests.cs | 224 +- PlexCleanerTests/FfMpegIdetInfoSerializer.cs | 86 +- PlexCleanerTests/FfMpegIdetParsingTests.cs | 280 +- PlexCleanerTests/FfMpegNalUnitTests.cs | 50 +- PlexCleanerTests/FfProbeLogTests.cs | 118 +- PlexCleanerTests/MetricsTests.cs | 384 +- PlexCleanerTests/PerFileLogLevelTests.cs | 498 +- PlexCleanerTests/PlexCleanerFixture.cs | 354 +- PlexCleanerTests/PlexCleanerTests.csproj | 53 +- PlexCleanerTests/PluginLoaderTests.cs | 94 +- PlexCleanerTests/ProcessDriverTests.cs | 70 +- PlexCleanerTests/SidecarFileTests.cs | 168 +- PlexCleanerTests/StreamTimingsProbeTests.cs | 82 +- PlexCleanerTests/ToolFailureLogFormatTests.cs | 270 +- PlexCleanerTests/ToolProgressParsingTests.cs | 92 +- PlexCleanerTests/VerifyClassifierTests.cs | 176 +- PlexCleanerTests/VersionParsingTests.cs | 188 +- PlexCleanerTests/WildcardTests.cs | 36 +- .../DtsTimestampRepair.csproj | 20 +- .../DtsTimestampRepairPlugin.cs | 178 +- .../MatroskaCleanupPlugin.cs | 172 +- .../MatroskaHeaderCleanup.csproj | 20 +- README.md | 2216 +++---- RegressionTests/README.md | 370 +- RegressionTests/audit_physical.py | 226 +- RegressionTests/catalog_corpus.py | 196 +- RegressionTests/corpus_common.py | 744 +-- RegressionTests/locate_issue.py | 442 +- RegressionTests/pyproject.toml | 50 +- RegressionTests/reduce_corpus.py | 1044 +-- RegressionTests/reduction-rules.example.json | 54 +- RegressionTests/synthetic/hevc_nal.py | 176 +- RegressionTests/synthetic/inject_cc_sei.py | 110 +- .../synthetic/inject_hdr10plus_sei.py | 128 +- RegressionTests/synthetic/synthesize.py | 346 +- Samples/PlexCleaner/PlexCleaner.v1.json | 114 +- Samples/PlexCleaner/PlexCleaner.v2.json | 264 +- Samples/PlexCleaner/PlexCleaner.v3.json | 280 +- Samples/PlexCleaner/PlexCleaner.v4.json | 288 +- Samples/PlexCleaner/Sidecar.State.PlexCleaner | 26 +- Samples/PlexCleaner/Sidecar.v1.PlexCleaner | 22 +- Samples/PlexCleaner/Sidecar.v2.PlexCleaner | 22 +- Samples/PlexCleaner/Sidecar.v3.PlexCleaner | 22 +- Samples/PlexCleaner/Sidecar.v4.PlexCleaner | 24 +- Samples/PlexCleaner/Sidecar.v5.PlexCleaner | 26 +- Sandbox/Program.cs | 282 +- Sandbox/Sandbox.csproj | 24 +- Sandbox/TestSomething.cs | 16 +- WORKFLOW.md | 1194 ++-- codecov.yml | 32 +- cspell.json | 711 +- global.json | 5 + host-tools.json | 36 +- repo-config/README.md | 39 - repo-config/develop.json | 61 - repo-config/main.json | 58 - repo-config/settings.json | 10 - spec/secrets.json | 34 - version.json | 20 +- 213 files changed, 32332 insertions(+), 29642 deletions(-) create mode 100644 .github/skills/add-host-tool/SKILL.md create mode 100644 .github/skills/agent-conduct/SKILL.md create mode 100644 .github/skills/audit-a-repo/SKILL.md create mode 100644 .github/skills/carried-instruction-file-guard/SKILL.md create mode 100644 .github/skills/code-review/SKILL.md create mode 100644 .github/skills/comment-and-doc-style/SKILL.md create mode 100644 .github/skills/comment-and-doc-style/references/carried-doc-references.md create mode 100644 .github/skills/comment-and-doc-style/references/line-endings.md create mode 100644 .github/skills/comment-and-doc-style/references/markdown-links.md create mode 100644 .github/skills/copilot-instructions-keeper/SKILL.md create mode 100644 .github/skills/dotnet-codestyle/SKILL.md create mode 100644 .github/skills/dotnet-codestyle/references/conventions.md create mode 100644 .github/skills/dotnet-codestyle/references/project-config.md create mode 100644 .github/skills/dotnet-codestyle/references/testing.md create mode 100644 .github/skills/drive-pr/SKILL.md create mode 100644 .github/skills/fleet-conformance-check/SKILL.md create mode 100644 .github/skills/git-commit-conventions/SKILL.md create mode 100644 .github/skills/git-commit-conventions/references/history-rewrite.md create mode 100644 .github/skills/local-strict-review/SKILL.md create mode 100644 .github/skills/merge-and-release/SKILL.md create mode 100644 .github/skills/operational-vs-release-workflow/SKILL.md create mode 100644 .github/skills/operational-vs-release-workflow/references/branch-protection-and-promotion.md create mode 100644 .github/skills/operational-vs-release-workflow/references/release-publish-mechanics.md create mode 100644 .github/skills/pr-review-conduct/SKILL.md create mode 100644 .github/skills/python-codestyle/SKILL.md create mode 100644 .github/skills/python-codestyle/references/code-style.md create mode 100644 .github/skills/python-codestyle/references/profiles.md create mode 100644 .github/skills/python-codestyle/references/testing.md create mode 100644 .github/skills/repo-worktree/SKILL.md create mode 100644 .github/skills/resync-a-repo/SKILL.md create mode 100644 .github/skills/shell-codestyle/SKILL.md create mode 100644 .github/skills/skill-lifecycle/SKILL.md create mode 100644 .github/skills/standup-a-repo/SKILL.md create mode 100644 .github/skills/upstream-contribution-workflow/SKILL.md create mode 100644 .github/skills/workflow-ci-contract/SKILL.md create mode 100644 .github/skills/workflow-ci-contract/references/d-guarantees.md create mode 100644 .github/skills/workflow-ci-contract/references/test-methodology.md delete mode 100644 .github/workflows/build-docker-task.yml delete mode 100644 .github/workflows/build-executable-task.yml delete mode 100644 .github/workflows/build-release-task.yml delete mode 100644 .github/workflows/get-version-task.yml create mode 100644 CLAUDE.md create mode 100644 global.json delete mode 100644 repo-config/README.md delete mode 100644 repo-config/develop.json delete mode 100644 repo-config/main.json delete mode 100644 repo-config/settings.json delete mode 100644 spec/secrets.json diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 957373e9..3975ed52 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -1,27 +1,27 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "csharpier": { - "version": "1.3.0", - "commands": [ - "csharpier" - ], - "rollForward": false - }, - "husky": { - "version": "0.9.1", - "commands": [ - "husky" - ], - "rollForward": false - }, - "dotnet-outdated-tool": { - "version": "4.8.1", - "commands": [ - "dotnet-outdated" - ], - "rollForward": false - } - } -} +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "1.3.0", + "commands": [ + "csharpier" + ], + "rollForward": false + }, + "husky": { + "version": "0.9.1", + "commands": [ + "husky" + ], + "rollForward": false + }, + "dotnet-outdated-tool": { + "version": "4.8.1", + "commands": [ + "dotnet-outdated" + ], + "rollForward": false + } + } +} diff --git a/.dockerignore b/.dockerignore index 45141c8f..44ceb9da 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,37 +1,37 @@ -# .NET build artifacts -**/bin/ -**/obj/ -**/out/ -.artifacts/ -**/.artifacts/ - -# Visual Studio / VS Code -.vs/ -.vscode/ -*.user -*.suo -*.userosscache -*.sln.docstates - -# Test results -TestResults/ -**/TestResults/ - -# NuGet packages -*.nupkg -*.snupkg -packages/ - -# Git -.git/ -.gitignore -.gitattributes - -# CI/CD -.github/ -.codex - -# Other -*.log -*.tmp -*.cache +# .NET build artifacts +**/bin/ +**/obj/ +**/out/ +.artifacts/ +**/.artifacts/ + +# Visual Studio / VS Code +.vs/ +.vscode/ +*.user +*.suo +*.userosscache +*.sln.docstates + +# Test results +TestResults/ +**/TestResults/ + +# NuGet packages +*.nupkg +*.snupkg +packages/ + +# Git +.git/ +.gitignore +.gitattributes + +# CI/CD +.github/ +.codex + +# Other +*.log +*.tmp +*.cache diff --git a/.editorconfig b/.editorconfig index 2bea93b3..3e63e3a6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,257 +1,232 @@ -# https://editorconfig.org - -# https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names -# https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions -# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview - -# https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/coding-style.md -# https://github.com/dotnet/runtime/blob/main/.editorconfig - -# https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format -# Verify with: dotnet format style --verify-no-changes --severity=info --verbosity=detailed - -# Root config -root = true - -# Defaults: CRLF is the default, and only the LF exceptions below are declared. -# Most LF pins are shared with `.gitattributes`, which git enforces: `*.sh`, the husky pre-commit shebang, `uv.lock`, and Dockerfiles. -# The workflow-YAML pin (`.github/workflows/*`) is `.editorconfig`-only. -# For those, git stays passive (`* -text`) and CI (editorconfig-checker) enforces LF. -# Keep the `[*]` `end_of_line = crlf` default, which the Windows-GUI and WSL-engine workflow requires because Windows tooling misbehaves on LF. -# Every uncovered file type relies on that default too. -[*] -charset = utf-8 -end_of_line = crlf -indent_size = 4 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true - -# Markdown files -[*.md] -trim_trailing_whitespace = false - -# Xml files -[*.{xml,csproj,props,targets}] -indent_size = 2 - -# Yaml files -[*.{yml,yaml}] -indent_size = 2 - -# Workflow YAML is LF, because Dependabot and Actions rewrite it with LF, so declaring LF keeps it consistent instead of mixed. -# Endings are still left alone by git (`* -text`), and this file plus CI (editorconfig-checker) enforce it. -# Other YAML stays CRLF. -[.github/workflows/*.{yml,yaml}] -end_of_line = lf - -# This repository's own hook, paired with the `.gitattributes` pin. -# The git pin alone leaves the editor free to write a CRLF shebang, which would break it. -[.husky/pre-commit] -end_of_line = lf - -# Linux scripts -[*.sh] -end_of_line = lf - -# The uv tool regenerates uv.lock with LF on every platform, so pin it here. -# Without the pin an EOL check (editorconfig-checker or CI) fails on every `uv lock` or `uv sync` until the file is manually reconverted. -# The rationale matches the shebang and Dockerfile pins, where a tool owns the ending. -# A Python repo on the CRLF default carries this, and a repo with no lockfile is unaffected. -[uv.lock] -end_of_line = lf - -# Dockerfiles are LF, because CRLF breaks RUN heredocs and line continuations. -[{Dockerfile,*.Dockerfile}] -end_of_line = lf - -# .NET-only below, covering C# and ReSharper style. -# Everything above is the line-ending governance every derived repo carries. - -# C# files -[*.cs] -# Suppressions follow CODESTYLE.md "Analyzer Diagnostics and Suppressions". -# Prefer a [SuppressMessage] attribute, or the owning project's .editorconfig. -# Relax a rule repo-wide here only when it applies to every project, never for a brownfield batch. -dotnet_diagnostic.IDE0055.severity = none -dotnet_analyzer_diagnostic.severity = suggestion - -# Repo-wide CA relaxations that apply to every project here, since PlexCleaner is a console app rather than a reusable library. -# Public API surface rules do not apply to a console app. -dotnet_diagnostic.CA1002.severity = none # Do not expose List -dotnet_diagnostic.CA1024.severity = none # Use properties where appropriate -dotnet_diagnostic.CA1034.severity = none # Nested types should not be visible -dotnet_diagnostic.CA1052.severity = none # Static holder types (builder pattern uses partial classes) -dotnet_diagnostic.CA1055.severity = none # URI return values should not be strings -dotnet_diagnostic.CA1056.severity = none # URI properties should not be strings -dotnet_diagnostic.CA1062.severity = none # Validate parameters of public methods -dotnet_diagnostic.CA1515.severity = none # Consider making public types internal -dotnet_diagnostic.CA1724.severity = none # Type names should not match namespaces -dotnet_diagnostic.CA2227.severity = none # Collection properties should be read only - -# Console app context: no localization, no SynchronizationContext, intentional case usage -dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters -dotnet_diagnostic.CA1307.severity = none # Specify StringComparison for clarity -dotnet_diagnostic.CA1308.severity = none # Normalize strings to uppercase (code intentionally lowercases) -dotnet_diagnostic.CA2007.severity = none # ConfigureAwait (console app has no SynchronizationContext) -dotnet_diagnostic.CA2234.severity = none # Pass System.Uri instead of string - -# False positives or inapplicable in this codebase -dotnet_diagnostic.CA1508.severity = none # Dead code (false positive with ??= pattern) -dotnet_diagnostic.CA5392.severity = none # DefaultDllImportSearchPaths (limited intentional P/Invoke, risk accepted) -csharp_indent_block_contents = true -csharp_indent_braces = false -csharp_indent_case_contents = true -csharp_indent_case_contents_when_block = false -csharp_indent_labels = one_less_than_current -csharp_indent_switch_labels = true -csharp_new_line_before_catch = true -csharp_new_line_before_else = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_open_brace = all -csharp_new_line_between_query_expression_clauses = true -csharp_prefer_braces = true -csharp_prefer_simple_default_expression = true -csharp_prefer_simple_using_statement = true -csharp_prefer_static_anonymous_function = true -csharp_prefer_static_local_function = true -csharp_prefer_system_threading_lock = true -csharp_preferred_modifier_order = public,private,protected,internal,file,static,abstract,sealed,virtual,override,readonly,unsafe,volatile,async,extern,new,partial:warning -csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = false -csharp_space_after_cast = false -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_after_comma = true -csharp_space_after_dot = false -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_after_semicolon_in_for_statement = true -csharp_space_around_binary_operators = before_and_after -csharp_space_around_declaration_statements = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_before_comma = false -csharp_space_before_dot = false -csharp_space_before_open_square_brackets = false -csharp_space_before_semicolon_in_for_statement = false -csharp_space_between_empty_square_brackets = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_declaration_name_and_open_parenthesis = false -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_between_square_brackets = false -csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true -csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true -csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true -csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true -csharp_style_allow_embedded_statements_on_same_line_experimental = true -csharp_style_conditional_delegate_call = true -csharp_style_deconstructed_variable_declaration = true -csharp_style_expression_bodied_accessors = true -csharp_style_expression_bodied_constructors = true -csharp_style_expression_bodied_indexers = true -csharp_style_expression_bodied_lambdas = true -csharp_style_expression_bodied_local_functions = true -csharp_style_expression_bodied_methods = true -csharp_style_expression_bodied_operators = true -csharp_style_expression_bodied_properties = true -csharp_style_implicit_object_creation_when_type_is_apparent = true -csharp_style_inlined_variable_declaration = true -csharp_style_namespace_declarations = file_scoped -csharp_style_pattern_matching_over_as_with_null_check = true -csharp_style_pattern_matching_over_is_with_cast_check = true -csharp_style_prefer_extended_property_pattern = true -csharp_style_prefer_implicitly_typed_lambda_expression = true -csharp_style_prefer_index_operator = true -csharp_style_prefer_local_over_anonymous_function = true -csharp_style_prefer_method_group_conversion = true -csharp_style_prefer_not_pattern = true -csharp_style_prefer_null_check_over_type_check = true -csharp_style_prefer_pattern_matching = true -csharp_style_prefer_primary_constructors = true -csharp_style_prefer_range_operator = true -csharp_style_prefer_readonly_struct = true -csharp_style_prefer_readonly_struct_member = true -csharp_style_prefer_switch_expression = true -csharp_style_prefer_top_level_statements = true -csharp_style_prefer_tuple_swap = true -csharp_style_prefer_unbound_generic_type_in_nameof = true -csharp_style_prefer_utf8_string_literals = true -csharp_style_throw_expression = true -csharp_style_unused_value_assignment_preference = discard_variable -csharp_style_unused_value_expression_statement_preference = discard_variable -csharp_style_var_elsewhere = false -csharp_style_var_for_built_in_types = false -csharp_style_var_when_type_is_apparent = false -csharp_using_directive_placement = outside_namespace -dotnet_code_quality_unused_parameters = all -dotnet_hide_advanced_members = false -dotnet_member_insertion_location = with_other_members_of_the_same_kind -dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion -dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style -dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion -dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style -dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields -dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case -dotnet_naming_style.camel_case_underscore_style.required_prefix = _ -dotnet_naming_style.pascal_case_style.capitalization = pascal_case -dotnet_naming_style.static_prefix_style.capitalization = camel_case -dotnet_naming_style.static_prefix_style.required_prefix = s_ -dotnet_naming_symbols.constant_fields.applicable_kinds = field -dotnet_naming_symbols.constant_fields.required_modifiers = const -dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal -dotnet_naming_symbols.private_internal_fields.applicable_kinds = field -dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected -dotnet_naming_symbols.static_fields.applicable_kinds = field -dotnet_naming_symbols.static_fields.required_modifiers = static -dotnet_prefer_system_hash_code = true -dotnet_property_generation_behavior = prefer_throwing_properties -dotnet_remove_unnecessary_suppression_exclusions = none -dotnet_search_reference_assemblies = true -dotnet_separate_import_directive_groups = false -dotnet_sort_system_directives_first = true -dotnet_style_allow_multiple_blank_lines_experimental = true -dotnet_style_allow_statement_immediately_after_block_experimental = true -dotnet_style_coalesce_expression = true -dotnet_style_collection_initializer = true -dotnet_style_explicit_tuple_names = true -dotnet_style_namespace_match_folder = true -dotnet_style_null_propagation = true -dotnet_style_object_initializer = true -dotnet_style_operator_placement_when_wrapping = beginning_of_line -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity -dotnet_style_parentheses_in_other_operators = never_if_unnecessary -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity -dotnet_style_predefined_type_for_locals_parameters_members = true -dotnet_style_predefined_type_for_member_access = true -dotnet_style_prefer_auto_properties = true -dotnet_style_prefer_collection_expression = when_types_loosely_match -dotnet_style_prefer_compound_assignment = true -dotnet_style_prefer_conditional_expression_over_assignment = true -dotnet_style_prefer_conditional_expression_over_return = true -dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed -dotnet_style_prefer_inferred_anonymous_type_member_names = true -dotnet_style_prefer_inferred_tuple_names = true -dotnet_style_prefer_is_null_check_over_reference_equality_method = true -dotnet_style_prefer_simplified_boolean_expressions = true -dotnet_style_prefer_simplified_interpolation = true -dotnet_style_qualification_for_event = false -dotnet_style_qualification_for_field = false -dotnet_style_qualification_for_method = false -dotnet_style_qualification_for_property = false -dotnet_style_readonly_field = true -dotnet_style_require_accessibility_modifiers = for_non_interface_members - -# ReSharper settings -resharper_csharp_trailing_comma_in_multiline_lists = true -resharper_csharp_var_for_built_in_types = false -resharper_csharp_var_when_type_is_apparent = false -resharper_csharp_var_when_type_is_not_apparent = false +# https://editorconfig.org + +# https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names +# https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview + +# https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/coding-style.md +# https://github.com/dotnet/runtime/blob/main/.editorconfig + +# https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format +# Verify with: dotnet format style --verify-no-changes --severity=info --verbosity=detailed + +# Root config +root = true + +# Defaults: LF is the default, and only the CRLF exception below is declared. +# `.gitattributes` mirrors these two defaults as Git's normalization fallback. +# CI verifies the committed bytes against this file. +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +# Markdown files +[*.md] +trim_trailing_whitespace = false + +# Xml files +[*.{xml,csproj,props,targets}] +indent_size = 2 + +# Yaml files +[*.{yml,yaml}] +indent_size = 2 + +# Windows batch and command scripts: the one CRLF exception to the `[*]` LF default above. +[*.{bat,cmd}] +end_of_line = crlf + +# .NET-only below, covering C# and ReSharper style. +# Everything above is the line-ending governance every derived repo carries, and a non-.NET repo carries this section unused, per CODESTYLE.md's whole-file model. + +# C# files +[*.cs] +# Suppressions follow CODESTYLE.md "Analyzer Diagnostics and Suppressions". +# Prefer a [SuppressMessage] attribute, or the owning project's .editorconfig. +# Relax a rule repo-wide here only when it applies to every project, never for a brownfield batch. +dotnet_diagnostic.IDE0055.severity = none +dotnet_analyzer_diagnostic.severity = suggestion + +# Repo-wide CA relaxations that apply to every project here, since PlexCleaner is a console app rather than a reusable library. +# Public API surface rules do not apply to a console app. +dotnet_diagnostic.CA1002.severity = none # Do not expose List +dotnet_diagnostic.CA1024.severity = none # Use properties where appropriate +dotnet_diagnostic.CA1034.severity = none # Nested types should not be visible +dotnet_diagnostic.CA1052.severity = none # Static holder types (builder pattern uses partial classes) +dotnet_diagnostic.CA1055.severity = none # URI return values should not be strings +dotnet_diagnostic.CA1056.severity = none # URI properties should not be strings +dotnet_diagnostic.CA1062.severity = none # Validate parameters of public methods +dotnet_diagnostic.CA1515.severity = none # Consider making public types internal +dotnet_diagnostic.CA1724.severity = none # Type names should not match namespaces +dotnet_diagnostic.CA2227.severity = none # Collection properties should be read only + +# Console app context: no localization, no SynchronizationContext, intentional case usage +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters +dotnet_diagnostic.CA1307.severity = none # Specify StringComparison for clarity +dotnet_diagnostic.CA1308.severity = none # Normalize strings to uppercase (code intentionally lowercases) +dotnet_diagnostic.CA2007.severity = none # ConfigureAwait (console app has no SynchronizationContext) +dotnet_diagnostic.CA2234.severity = none # Pass System.Uri instead of string + +# False positives or inapplicable in this codebase +dotnet_diagnostic.CA1508.severity = none # Dead code (false positive with ??= pattern) +dotnet_diagnostic.CA5392.severity = none # DefaultDllImportSearchPaths (limited intentional P/Invoke, risk accepted) +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = false +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true +csharp_prefer_braces = true +csharp_prefer_simple_default_expression = true +csharp_prefer_simple_using_statement = true +csharp_prefer_static_anonymous_function = true +csharp_prefer_static_local_function = true +csharp_prefer_system_threading_lock = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,abstract,sealed,virtual,override,readonly,unsafe,volatile,async,extern,new,partial:warning +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true +csharp_style_conditional_delegate_call = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = true +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = true +csharp_style_expression_bodied_methods = true +csharp_style_expression_bodied_operators = true +csharp_style_expression_bodied_properties = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_namespace_declarations = file_scoped +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_implicitly_typed_lambda_expression = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true +csharp_style_prefer_switch_expression = true +csharp_style_prefer_top_level_statements = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_unbound_generic_type_in_nameof = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false +csharp_using_directive_placement = outside_namespace +dotnet_code_quality_unused_parameters = all +dotnet_hide_advanced_members = false +dotnet_member_insertion_location = with_other_members_of_the_same_kind +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +dotnet_naming_style.static_prefix_style.capitalization = camel_case +dotnet_naming_style.static_prefix_style.required_prefix = s_ +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static +dotnet_prefer_system_hash_code = true +dotnet_property_generation_behavior = prefer_throwing_properties +dotnet_remove_unnecessary_suppression_exclusions = none +dotnet_search_reference_assemblies = true +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_collection_expression = when_types_loosely_match +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false +dotnet_style_readonly_field = true +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# ReSharper settings +resharper_csharp_trailing_comma_in_multiline_lists = true +resharper_csharp_var_for_built_in_types = false +resharper_csharp_var_when_type_is_apparent = false +resharper_csharp_var_when_type_is_not_apparent = false diff --git a/.editorconfig-checker.json b/.editorconfig-checker.json index e019960b..940ba637 100644 --- a/.editorconfig-checker.json +++ b/.editorconfig-checker.json @@ -1,10 +1,20 @@ -{ - "Disable": { - "Charset": true, - "Indentation": true, - "IndentSize": true, - "TrimTrailingWhitespace": true, - "InsertFinalNewline": true, - "MaxLineLength": true - } -} +{ + "Exclude": [ + "(^|/)\\.artifacts/", + "(^|/)\\.mypy_cache/", + "(^|/)\\.pytest_cache/", + "(^|/)\\.ruff_cache/", + "(^|/)\\.venv/", + "(^|/)__pycache__/", + "(^|/)bin/", + "(^|/)obj/" + ], + "Disable": { + "Charset": true, + "Indentation": true, + "IndentSize": true, + "TrimTrailingWhitespace": true, + "InsertFinalNewline": true, + "MaxLineLength": true + } +} diff --git a/.gitattributes b/.gitattributes index a4cb45ca..efb6dddb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,29 +1,7 @@ -# Default: git does not normalize line endings (`* -text`), and .editorconfig end_of_line rules guide what the editor writes. -# The exception pins below are git's own enforcement, forcing LF for execution-sensitive classes regardless of editor. -# Configure with: git config --global core.autocrlf false -# Renormalize with: git add --renormalize . -# Inspect with: git ls-files --eol -* -text - -# Exception: scripts must stay LF regardless of the `* -text` default, because a CRLF shebang breaks execution. -# `.editorconfig` covers `*.sh`, but an extensionless executable matches no extension rule. -# Pin those here, so git enforces LF on checkout and on `--renormalize`. -# Any repo whose tooling ships extensionless scripts adds the matching path pin. -# The s6-overlay init is `Docker/s6-overlay/** text eol=lf`, and a husky or git hook is `.husky/pre-commit text eol=lf`. -*.sh text eol=lf -# This repository's own hook, which is the extensionless case the comment above names. -.husky/pre-commit text eol=lf - -# Vanilla `.py` follows the CRLF default, since Python's universal newlines accept CRLF and it is commonly edited on Windows. -# Pin LF only for a `.py` executed directly via its shebang, by path. -# This repo has none, since the RegressionTests tooling is run as `python3