microsoft / microsoft/microsoft-ui-reactor
[Bug] SourceSnippetSanityTests anchors repo-root on CWD, not AppContext.BaseDirectory — can validate a sibling worktree
- Dominant language
- C#
- Stars
- 646
- Forks
- 54
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 84
Description
### What happened?
`tests/Reactor.DocPipeline.Tests/SourceSnippetSanityTests.cs:27` anchors its repo-root walk on the **process current directory**:
```csharp
private static string FindRepoRoot()
{
var dir = Directory.GetCurrentDirectory(); // <-- process CWD
while (dir is not null)
{
if (File.Exists(Path.Combine(dir, "Reactor.slnx")) || Directory.Exists(Path.Combine(dir, ".git")))
return dir;
dir = Path.GetDirectoryName(dir);
}
throw new InvalidOperationException("Reactor repo root not found from test cwd.");
}
```
Every other copy in the repo anchors on `AppContext.BaseDirectory` — the test assembly's own location, which is necessarily inside the tree that built it:
| file | anchor |
|---|---|
| `tests/Reactor.AppTests/Tests/Spec051DevtoolsPackageE2ETests.cs:131` | `AppContext.BaseDirectory` |
| `tests/Reactor.IntegrationTests/Packaging/CreateTemplateTests.cs:367` | `AppContext.BaseDirectory` |
| `tests/Reactor.DocPipeline.Tests/VersionSubstitutionTests.cs:213` | `AppContext.BaseDirectory` |
| `tests/Reactor.Tests/TemplateMetadataTests.cs:194` | `AppContext.BaseDirectory` |
| `tests/Reactor.Tests/VersionSingleSourceTests.cs:210` | `AppContext.BaseDirectory` |
| `src/Reactor.Cli/Pack/RepoRootFinder.cs:13` (the shared one) | `AppContext.BaseDirectory` |
| **`tests/Reactor.DocPipeline.Tests/SourceSnippetSanityTests.cs:27`** | **`Directory.GetCurrentDirectory()`** |
**Why it matters here specifically.** `AGENTS.md` tells contributors *"Work in a clean worktree, not `main`: `git worktree add …`"*, so a developer machine is expected to have **several valid checkouts of this repo at once**. A CWD-anchored walk finds whichever tree the process happens to be standing in. If that is a *sibling worktree*, `src/Reactor/Hooks/UseMemoCells.cs` exists there too, `ExtractFromSource` succeeds, and the test **passes green having validated a different tree than the one it was built from**. The repo's own recommended workflow is the precondition for the failure.
**Severity: low / latent**, and I'd rather state the mitigations than overclaim:
- The test runner normally sets CWD to the assembly output directory, so today this usually coincides with `AppContext.BaseDirectory`. I have not observed it fire.
- It `throw`s when no root is found, so the "wrong machine entirely" case fails **loudly** rather than silently.
- The silent-wrong-answer case needs CWD to sit inside *another checkout of this same repo* — real on a worktree-using dev box or a mutation/merge harness that drives a scratch worktree, but not on a clean CI runner.
The general hazard is worth recording regardless: `Set-Location`/`cd` in a driver script does **not** update the .NET process working directory, so managed relative-path resolution and shell relative-path resolution can silently disagree. Verified on this machine:
```
after Set-Location to :
Get-Location : C:\...\Temp\pA-4cefdf
[Environment]::CurrentDirectory : C:\...\
Set-Location updated CurrentDirectory? -> False
[IO.Path]::GetFullPath('probe.txt') : C:\...\\probe.txt <- not pA
```
Note the failure is silent **only when the same relative path is valid under both roots** — otherwise it throws. Parallel worktrees of one repo guarantee that condition, which is what makes this shape worth avoiding rather than merely noting.
### Steps to reproduce
1. `git worktree add ../wt-b origin/main` so two valid checkouts exist.
2. Build `Reactor.DocPipeline.Tests` in worktree A.
3. Run the test host with the process working directory set inside worktree B.
4. `Extracts_demo_region_from_UseMemoCells` passes — against **B's** `src/Reactor/Hooks/UseMemoCells.cs`, not A's.
### Suggested fix
One line — switch the anchor, matching the five siblings:
```csharp
var dir = AppContext.BaseDirectory;
```
Better, since a shared implementation already exists: have these tests call `RepoRootFinder.FindRepoRoot()` (`src/Reactor.Cli/Pack/RepoRootFinder.cs`) instead of each re-deriving it. Six near-identical private copies is how one of them drifted. That consolidation is the actual fix; the anchor change is the stopgap.
### Reactor version / commit
`8d3db0a271b0e5bc8043782e63c3cd8d6e6b5e89` — but the affected file is unmodified by that branch and is present on `main`.
### Platform
x64
### .NET SDK version
10.0.302
### Windows version
Windows 11 Enterprise Insider Preview (build 26310)
### Windows App SDK version
N/A — `Reactor.DocPipeline.Tests` is a headless test project with no Windows App SDK dependency.
### Logs / stack trace
N/A — no failure observed; this is a latent anchoring inconsistency found by inspection after verifying the underlying path-resolution divergence, not a reproduced red test.
### Confirmation
- [x] I have searched existing issues and this isn't a duplicate.
- [x] This bug reproduces against the current `main` branch (the file is untouched by my branch).
Contributor guide
Research direction
Start at tests/Reactor.DocPipeline.Tests/SourceSnippetSanityTests.cs:27 and compare its FindRepoRoot anchor with AppContext.BaseDirectory and src/Reactor.Cli/Pack/RepoRootFinder.cs. Run the affected SourceSnippetSanityTests, including Extracts_demo_region_from_UseMemoCells, with separate worktrees; done means the test resolves files from the assembly's own checkout rather than the process CWD.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100