feat(dotnet): add core reporter (listener, collector, writer, SPI hook) - #194
Merged
Conversation
Adds the .NET reporter core: an MTP V2 (Microsoft Testing Platform) in-process extension that captures test results and writes .claude/tdd-guard/data/test.json. Framework-agnostic - any MTP V2- hosted framework works without reporter changes. Following the guidance on issue nizos#84 ("keeping the PR focused and the initial implementation simple will make it much easier for me to review") and the shape accepted for the JUnit5 reporter (nizos#160 - listener, collector, JSON writer, SPI/hook registration, build wrapper, unit tests only), this PR is scoped identically: - TddGuard.Dotnet.Core/ - pure domain types and functions, no MTP dependency - TddGuard.Dotnet/ - the MTP V2 extension (listener + builder hook) - TddGuard.Dotnet.Tests/ - unit and property-based tests only No src/ changes. No CI changes (separate PR). No integration test factory or framework compatibility smoke tests (separate PRs, same as JUnit5's follow-up sequence). Design: - Domain logic (Core) has zero MTP dependency - testable without a test host - Errors are values: ProjectRootResolver.Resolve() returns OneOf<ProjectRoot, ResolveError>, no exceptions for flow control - Per ADR-010: when neither TDD_GUARD_PROJECT_ROOT nor CLAUDE_PROJECT_DIR is set, the extension disables itself and logs to stderr - it does not silently fall back to cwd - Cross-platform path handling: Path.GetFullPath() + normalized comparison for the ancestor-of-cwd check (handles Windows separators, case-insensitivity, trailing separators, macOS /var -> /private/var symlinks) Testing: 70 unit tests, including property-based roundtrip serialization (FsCheck). All pass on .NET 10. Distribution: Planned for NuGet.org, published by the maintainer - following up separately on issue nizos#84.
This was referenced Jul 23, 2026
Owner
|
Hi @edblackburn, Thanks for the PR! I'm back from vacation and should be able to look at it this weekend. Talk to you soon! :) |
Owner
|
Hi @edblackburn, Thanks for the PR and great work! I closed and re-opened the PR just to get the npm audit check to pick up a dependency fix that landed on main earlier today. I will merge this and follow up with dotnet support in the devcontainer. A few things that I would like your read on before we publish:
Thanks again, this is outstanding work. I have now been looking forward to it and I'm glad to have you as a contributor. Excited for the rest of the stack so we can get it published. :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the .NET reporter core: an MTP V2 (Microsoft Testing Platform) in-process extension that captures test results and writes
.claude/tdd-guard/data/test.json. Framework-agnostic — any MTP V2-hosted framework works without reporter changes.Scope
Following your guidance on issue #84 ("keeping the PR focused and the initial implementation simple will make it much easier for me to review") and the shape you accepted for the JUnit5 reporter (#160 — listener, collector, JSON writer, SPI/hook registration, build wrapper, unit tests only), this PR is scoped identically:
TddGuard.Dotnet.Core/— pure domain types and functions, no MTP dependencyTddGuard.Dotnet/— the MTP V2 extension (listener + builder hook)TddGuard.Dotnet.Tests/— unit and property-based tests onlyNo
src/changes. No CI changes (separate PR, stacked on this one). No integration test factory or framework compatibility smoke tests (separate PRs, same as JUnit5's follow-up sequence).Design
ProjectRootResolver.Resolve()returnsOneOf<ProjectRoot, ResolveError>, no exceptions for flow controlTDD_GUARD_PROJECT_ROOTnorCLAUDE_PROJECT_DIRis set, the extension disables itself and logs to stderr — it does not silently fall back to cwdPath.GetFullPath()+ normalized comparison for the ancestor-of-cwd check (handles Windows separators, case-insensitivity, trailing separators, macOS/var→/private/varsymlinks)Testing
70 unit tests, including property-based roundtrip serialization (FsCheck). All pass on .NET 10.
Distribution
Planned for NuGet.org, published by you — following up separately on issue #84.
Stacked PRs
This is the first of a stack of 4 PRs decomposing the reporter the way JUnit5 landed:
feat/dotnet-ci→ CI build stepfeat/dotnet-integration-tests→ Node integration test factory + minimal fixturesfeat/dotnet-framework-compat→ framework compatibility smoke testsEach is based on the previous, so they'll show as small incremental diffs once opened.