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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ priority: medium
<!-- SECTION:DESCRIPTION:BEGIN -->
Create GitHub PR and issue templates to guide contributors:

- .github/pull_request_template.md checklist covering tests, build, conventional commit format, and docs
- .github/ISSUE_TEMPLATE/1-bug-report.yml structured bug report form (GitHub issue form, not markdown)
- .github/ISSUE_TEMPLATE/2-feature-request.yml structured feature request form (GitHub issue form, not markdown)
- .github/ISSUE_TEMPLATE/config.yml disables blank issues (`blank_issues_enabled: false`)
- .github/pull_request_template.md - checklist covering tests, build, conventional commit format, and docs
- .github/ISSUE_TEMPLATE/1-bug-report.yml - structured bug report form (GitHub issue form, not markdown)
- .github/ISSUE_TEMPLATE/2-feature-request.yml - structured feature request form (GitHub issue form, not markdown)
- .github/ISSUE_TEMPLATE/config.yml - disables blank issues (`blank_issues_enabled: false`)
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
Expand All @@ -38,8 +38,8 @@ Create GitHub PR and issue templates to guide contributors:
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Created all four GitHub community health files under `.github/`:

- `pull_request_template.md` contributor checklist covering tests, build, conventional commit format, and docs
- `ISSUE_TEMPLATE/1-bug-report.yml` structured GitHub issue form for bug reports
- `ISSUE_TEMPLATE/2-feature-request.yml` structured GitHub issue form for feature requests
- `ISSUE_TEMPLATE/config.yml` disables blank issues (`blank_issues_enabled: false`)
- `pull_request_template.md` - contributor checklist covering tests, build, conventional commit format, and docs
- `ISSUE_TEMPLATE/1-bug-report.yml` - structured GitHub issue form for bug reports
- `ISSUE_TEMPLATE/2-feature-request.yml` - structured GitHub issue form for feature requests
- `ISSUE_TEMPLATE/config.yml` - disables blank issues (`blank_issues_enabled: false`)
<!-- SECTION:FINAL_SUMMARY:END -->
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Root cause: `directories: ["**/*"]` creates one PR per matched directory per ung
| coverlet.msbuild | 4 | 4 separate PRs |
| Microsoft.SourceLink.GitHub | 4 | 4 separate PRs |

With Dependabot's default open-pull-requests-limit of 5, only some directories would receive a PR for a given package before the limit was reached explaining why only AutoFakeItEasy.Tests was updated for Microsoft.NET.Test.Sdk 18.4.0.
With Dependabot's default open-pull-requests-limit of 5, only some directories would receive a PR for a given package before the limit was reached - explaining why only AutoFakeItEasy.Tests was updated for Microsoft.NET.Test.Sdk 18.4.0.

Evidence from git log and closed PR history:

Expand All @@ -42,7 +42,7 @@ Fix: Keep `directories: ["**/*"]` (discovery is working correctly) and add three

- Testing: Microsoft.NET.Test.Sdk, coverlet.msbuild
- Common: Castle.Core, JetBrains.Annotations, Microsoft.SourceLink.GitHub, Microsoft.NETFramework.ReferenceAssemblies
- Other: `*` catch-all consolidates any package not matched by a named group into a single PR, guarding against future ungrouped shared packages
- Other: `*` catch-all - consolidates any package not matched by a named group into a single PR, guarding against future ungrouped shared packages
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
Expand All @@ -55,7 +55,7 @@ Fix: Keep `directories: ["**/*"]` (discovery is working correctly) and add three
## Implementation Plan

<!-- SECTION:PLAN:BEGIN -->
In .github/dependabot.yml, add three groups under the nuget ecosystem entry (order matters Other must be last so named groups take priority):
In .github/dependabot.yml, add three groups under the nuget ecosystem entry (order matters - Other must be last so named groups take priority):

Testing:
patterns:
Expand All @@ -79,7 +79,7 @@ Applied to `.github/dependabot.yml`. The `directories: ["**/*"]` setting was alr

Added three new groups to the nuget ecosystem entry:

- **Testing** `Microsoft.NET.Test.Sdk`, `coverlet.msbuild`
- **Common** `Castle.Core`, `JetBrains.Annotations`, `Microsoft.SourceLink.GitHub`, `Microsoft.NETFramework.ReferenceAssemblies`
- **Other** `*` catch-all placed last so named groups take priority; consolidates any future ungrouped shared package into a single PR automatically
- **Testing** - `Microsoft.NET.Test.Sdk`, `coverlet.msbuild`
- **Common** - `Castle.Core`, `JetBrains.Annotations`, `Microsoft.SourceLink.GitHub`, `Microsoft.NETFramework.ReferenceAssemblies`
- **Other** - `*` catch-all placed last so named groups take priority; consolidates any future ungrouped shared package into a single PR automatically
<!-- SECTION:FINAL_SUMMARY:END -->
6 changes: 3 additions & 3 deletions .backlog/completed/task-11 - Fix-snyk-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ priority: medium
<!-- SECTION:DESCRIPTION:BEGIN -->
Two issues need fixing in `.github/workflows/snyk.yml`:

### Issue 1 Deprecated action
### Issue 1 - Deprecated action

All three scan/monitor steps use `snyk/actions/dotnet@master`, which is officially
deprecated and no longer supported by Snyk (no .NET-specific replacement exists).
Expand All @@ -26,7 +26,7 @@ The recommended migration is `snyk/actions/setup@master` (installs the Snyk CLI
combined with explicit `run: snyk ...` commands. Since the workflow already runs on
`ubuntu-latest`, the Docker-based `setup` action works without any runner change.

### Issue 2 Multiple SARIF runs under the same category
### Issue 2 - Multiple SARIF runs under the same category

The single `upload-sarif` step points to the `snyk/` directory, which contains two
SARIF files (`opensource.sarif` and `code.sarif`). GitHub Code Scanning no longer
Expand All @@ -38,7 +38,7 @@ causing the workflow to fail with:

**Fix:** replace the single directory upload with two steps, each pointing to a
specific file with a distinct `category`. The `category` parameter creates an
independent slot in the GitHub Advanced Security dashboard uploads coexist and
independent slot in the GitHub Advanced Security dashboard - uploads coexist and
neither overwrites the other.
<!-- SECTION:DESCRIPTION:END -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ priority: low
## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Replace `net8.0` with `net10.0` in all four test projects. .NET 10 is LTS (supported until November 2028), making it the right long-term target. .NET 9 STS reaches end of support in May 2026 and is not worth targeting. .NET 8 LTS ends November 2026. Library projects already target `netstandard2.0`/`netstandard2.1` which covers all modern .NET versions no change is needed there.
Replace `net8.0` with `net10.0` in all four test projects. .NET 10 is LTS (supported until November 2028), making it the right long-term target. .NET 9 STS reaches end of support in May 2026 and is not worth targeting. .NET 8 LTS ends November 2026. Library projects already target `netstandard2.0`/`netstandard2.1` which covers all modern .NET versions - no change is needed there.

**Current state:**

Expand Down
10 changes: 5 additions & 5 deletions .backlog/completed/task-3 - Enforce-Conventional-Commits.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Add tooling to enforce the Conventional Commits specification at commit time. Th
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 A git commit-msg hook is in place that validates the message against Conventional Commits format
- [x] #2 The commit is prevented when the message is non-conforming not just warned
- [x] #2 The commit is prevented when the message is non-conforming - not just warned
- [x] #3 Setup instructions are added to CONTRIBUTING.md so contributors activate the hooks after cloning
<!-- AC:END -->

Expand Down Expand Up @@ -53,8 +53,8 @@ Validated behavior locally: valid messages pass and invalid messages fail with n
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Enforced Conventional Commits using Husky.NET + CommitLint.Net via the repository-local .NET tool manifest (`dotnet-tools.json`). Key deliverables:

- `commit-message-config.json` Conventional Commits rules with allowed types
- `.husky/commit-msg` + `.husky/task-runner.json` local git hook that blocks non-conforming messages at commit time
- `.github/workflows/commit-message.yml` CI mirror that validates the latest commit message using the same config, catching any hook bypasses
- `CONTRIBUTING.md` updated single bootstrap (`dotnet tool restore` + `dotnet husky install`) activates all local tools and hooks after cloning
- `commit-message-config.json` - Conventional Commits rules with allowed types
- `.husky/commit-msg` + `.husky/task-runner.json` - local git hook that blocks non-conforming messages at commit time
- `.github/workflows/commit-message.yml` - CI mirror that validates the latest commit message using the same config, catching any hook bypasses
- `CONTRIBUTING.md` updated - single bootstrap (`dotnet tool restore` + `dotnet husky install`) activates all local tools and hooks after cloning
<!-- SECTION:FINAL_SUMMARY:END -->
10 changes: 5 additions & 5 deletions .backlog/completed/task-4 - Add-AI-powered-PR-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ Integrate an AI-powered PR review tool (e.g. CodeRabbit, Reviewpad, or similar)
## Final Summary

<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Selected and configured **CodeRabbit** free for public OSS repos, no infrastructure to maintain.
Selected and configured **CodeRabbit** - free for public OSS repos, no infrastructure to maintain.

Delivered `.coderabbit.yaml` at the repo root with:

- `auto_review.enabled: true` + `high_level_summary: true` automatic PR summary comment on every PR (AC #1)
- `profile: "chill"` non-blocking review style that complements rather than replaces human review
- `auto_apply_labels: true` automatic PR labelling
- `auto_review.enabled: true` + `high_level_summary: true` - automatic PR summary comment on every PR (AC #1)
- `profile: "chill"` - non-blocking review style that complements rather than replaces human review
- `auto_apply_labels: true` - automatic PR labelling

AC #3 (OSS licensing) is satisfied CodeRabbit is free for public repos.
AC #3 (OSS licensing) is satisfied - CodeRabbit is free for public repos.
AC #2 (project conventions awareness) was intentionally skipped by the team; the tool autodiscovers `AGENTS.md` but no explicit `reviews.instructions` were added.
<!-- SECTION:FINAL_SUMMARY:END -->
2 changes: 1 addition & 1 deletion .backlog/completed/task-5 - Add-SECURITY.md.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ priority: low
## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Create a SECURITY.md file at the repository root that documents the vulnerability disclosure process how to report a security issue privately, expected response time, and which versions receive security fixes. GitHub surfaces this file prominently and uses it to populate the 'Report a vulnerability' link.
Create a SECURITY.md file at the repository root that documents the vulnerability disclosure process - how to report a security issue privately, expected response time, and which versions receive security fixes. GitHub surfaces this file prominently and uses it to populate the 'Report a vulnerability' link.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
Expand Down
2 changes: 1 addition & 1 deletion .backlog/completed/task-6 - Add-CODE_OF_CONDUCT.md.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ Add a CODE_OF_CONDUCT.md to the repository root. The [Contributor Covenant](http
<!-- AC:BEGIN -->
- [x] #1 CODE_OF_CONDUCT.md exists at the repository root
- [x] #2 Based on a recognised standard (Contributor Covenant v2.1)
- [x] #3 Enforcement contact set to maintainer GitHub profile (@piotrzajac) no email per project policy
- [x] #3 Enforcement contact set to maintainer GitHub profile (@piotrzajac) - no email per project policy
<!-- AC:END -->
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ Added `commit-message` configuration to both entries in `.github/dependabot.yml`
- NuGet entry: `prefix: "chore(nuget)"`
- GitHub Actions entry: `prefix: "chore(github-actions)"`

`include: "scope"` was intentionally omitted that option produces `deps`/`deps-dev` as the scope (dependency-type based), not the ecosystem name. Embedding the scope directly in `prefix` is the only way to produce ecosystem-specific scopes.
`include: "scope"` was intentionally omitted - that option produces `deps`/`deps-dev` as the scope (dependency-type based), not the ecosystem name. Embedding the scope directly in `prefix` is the only way to produce ecosystem-specific scopes.
<!-- SECTION:PLAN:END -->

## Implementation Notes

<!-- SECTION:NOTES:BEGIN -->
`commit-message.include: "scope"` in Dependabot produces `chore(deps):` or `chore(deps-dev):` based on the dependency type it does NOT use the ecosystem name as the scope. To get `chore(nuget):` and `chore(github-actions):`, the scope must be baked directly into the `prefix` value and `include: "scope"` must be omitted.
`commit-message.include: "scope"` in Dependabot produces `chore(deps):` or `chore(deps-dev):` based on the dependency type - it does NOT use the ecosystem name as the scope. To get `chore(nuget):` and `chore(github-actions):`, the scope must be baked directly into the `prefix` value and `include: "scope"` must be omitted.
<!-- SECTION:NOTES:END -->

## Final Summary
Expand All @@ -52,5 +52,5 @@ Updated `.github/dependabot.yml` to add `commit-message` configuration to both e
- NuGet entry: `prefix: "chore(nuget)"` → produces `chore(nuget): bump <package> from X to Y`
- GitHub Actions entry: `prefix: "chore(github-actions)"` → produces `chore(github-actions): bump <action> from X to Y`

`include: "scope"` was intentionally omitted that option produces `deps`/`deps-dev` as scope (dependency-type based), not the ecosystem name. Embedding the scope in `prefix` is the only way to get ecosystem-specific scopes that satisfy the commit-message CI workflow introduced in TASK-3.
`include: "scope"` was intentionally omitted - that option produces `deps`/`deps-dev` as scope (dependency-type based), not the ecosystem name. Embedding the scope in `prefix` is the only way to get ecosystem-specific scopes that satisfy the commit-message CI workflow introduced in TASK-3.
<!-- SECTION:FINAL_SUMMARY:END -->
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ priority: medium
<!-- SECTION:DESCRIPTION:BEGIN -->
TASK-3 added `dotnet-stryker` to the repository-level tool manifest (`dotnet-tools.json` at repo root) alongside Husky and CommitLint.Net. The `.github/workflows/test-mutations.yml` workflow was not updated accordingly and still contains a dedicated "install stryker.net" step that:

1. Runs `dotnet new tool-manifest` creating a brand-new `.config/dotnet-tools.json` in the working directory, which conflicts with the repo-level manifest.
2. Runs `dotnet tool install --local dotnet-stryker` redundantly re-installing a tool that is already declared in the repo manifest.
1. Runs `dotnet new tool-manifest` - creating a brand-new `.config/dotnet-tools.json` in the working directory, which conflicts with the repo-level manifest.
2. Runs `dotnet tool install --local dotnet-stryker` - redundantly re-installing a tool that is already declared in the repo manifest.

This step must be replaced with `dotnet tool restore`, which restores all tools (husky, commitlint.net, dotnet-stryker) from the existing manifest in a single, consistent step.
<!-- SECTION:DESCRIPTION:END -->
Expand All @@ -45,7 +45,7 @@ In `.github/workflows/test-mutations.yml`, replace the multi-line PowerShell "
<!-- SECTION:NOTES:BEGIN -->
`dotnet tool restore` resolves the manifest by walking up the directory tree from the working directory, finding `dotnet-tools.json` at the repo root. No path argument is needed.

The old step used `dotnet new tool-manifest` which would create `.config/dotnet-tools.json` in the runner's working directory a different path from the repo-root `dotnet-tools.json` causing a manifest collision.
The old step used `dotnet new tool-manifest` which would create `.config/dotnet-tools.json` in the runner's working directory - a different path from the repo-root `dotnet-tools.json` - causing a manifest collision.
<!-- SECTION:NOTES:END -->

## Final Summary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ status: accepted

## Decision

Default `MemberAutoDataBaseAttribute.ShareFixture = true`. The same `IFixture` instance with all its customizations and registered mock objects is reused across every data row produced by the member. Users can opt out with `ShareFixture = false` when independent fixtures per row are required.
Default `MemberAutoDataBaseAttribute.ShareFixture = true`. The same `IFixture` instance - with all its customizations and registered mock objects - is reused across every data row produced by the member. Users can opt out with `ShareFixture = false` when independent fixtures per row are required.

## Consequences

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Moq introduced SponsorLink in a controversial update that embedded telemetry and

## Decision

Explicitly exclude `Moq` from Dependabot NuGet updates it requires manual review and a deliberate upgrade decision.
Explicitly exclude `Moq` from Dependabot NuGet updates - it requires manual review and a deliberate upgrade decision.
Group all other NuGet updates into logical Dependabot groups: `xUnit`, `AutoFixture`, `Analyzers`, `Testing`, `Common`, and `Other`.
GitHub Actions dependencies are also grouped and updated weekly with a `chore(github-actions):` prefix.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ AutoFixture generates arbitrary values for parameters. Tests for boundary condit

Add four parameter-level attributes to Core, all implemented via `IParameterCustomizationSource`:

- `[Except(v1, v2)]` generate values excluding the specified set
- `[PickFromValues(v1, v2)]` pick randomly from a fixed set
- `[PickFromRange(min, max)]` generate within a numeric range
- `[PickNegative]` generate only negative numeric values
- `[Except(v1, v2)]` - generate values excluding the specified set
- `[PickFromValues(v1, v2)]` - pick randomly from a fixed set
- `[PickFromRange(min, max)]` - generate within a numeric range
- `[PickNegative]` - generate only negative numeric values

All four are backed by new specimen builders (`RandomExceptValuesGenerator`, `RandomFixedValuesGenerator`) and request types (`ExceptValuesRequest`, `FixedValuesRequest`).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ Add Semgrep as a parallel SAST scanning step in CI alongside CodeQL. Use the def
## Consequences

- Broader SAST coverage through two independent tools with different rule philosophies.
- Some overlap with CodeQL is intentional independent tools reaching the same conclusion increases confidence.
- Some overlap with CodeQL is intentional - independent tools reaching the same conclusion increases confidence.
- Semgrep findings are reviewed in CI alongside CodeQL results; both must pass before merge.
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ Stop inheriting from AutoFixture attributes. Derive from xUnit's `DataAttribute`

- Clear boundary between the xUnit layer and AutoFixture: each can evolve independently.
- The provider pattern enables per-parameter customization via `IParameterCustomizationSource` attributes applied later in the pipeline.
- All three mock modules (AutoMoq, AutoFakeItEasy, AutoNSubstitute) override only `Customize(IFixture)` the rest of the pipeline is inherited from Core.
- All three mock modules (AutoMoq, AutoFakeItEasy, AutoNSubstitute) override only `Customize(IFixture)` - the rest of the pipeline is inherited from Core.
Loading
Loading