Skip to content

Give Roslyn the runtime its build asks for - #171

Merged
DavidBakerEffendi merged 2 commits into
mainfrom
dave/roslyn-requires-net10
Aug 26, 2026
Merged

Give Roslyn the runtime its build asks for#171
DavidBakerEffendi merged 2 commits into
mainfrom
dave/roslyn-requires-net10

Conversation

@DavidBakerEffendi

Copy link
Copy Markdown
Collaborator

The roslyn shard failed the v0.3.1 freeze
(32933786955)
with ten errored C# cases — every initialize failing in milliseconds. The
server's stderr, which the workflow log does not carry, says:

You must install or update .NET to run this application.
Framework: 'Microsoft.NETCore.App', version '10.0.0' (arm64)
.NET location: /opt/homebrew/Cellar/dotnet@8/8.0.130/libexec
The following frameworks were found:  8.0.30

vscode-csharp 2.140.9 targets net10.0. Its runtimeconfig:

{ "tfm": "net10.0",
  "framework": { "name": "Microsoft.NETCore.App", "version": "10.0.0" },
  "rollForward": "Major" }

rollForward: Major only rolls upward, so 8.x can never satisfy 10.0.0. This
step asserted net8.0 and pinned the .NET 8 keg to guarantee it — provisioning
the one runtime the server cannot use.

How this survived two prior changes

The net8.0 premise lived in a comment, not in the server, and both earlier
changes inherited it:

The fix

Read the requirement rather than restate it: stage the VSIX first, take the
framework version from the server's own runtimeconfig.json, select the
matching Homebrew formula (dotnet for 10, dotnet@N otherwise), and assert
that major is present. A future VSIX bump now moves the runtime with it.

The muxer-by-absolute-path check, the runtime-not-SDK check, and the PATH
resolution check are all kept — they were right, just aimed at the wrong major.

Verification

On macOS arm64 against the pinned VSIX:

runtime csharp-baseline.yaml
.NET 8.0.30 6 errors, stderr above
.NET 10.0.11 6 passed, 0 errors

Full ten-case C# legacy slice against the freeze gate:

ran 10 planned: 7 passed, 3 failed, 0 errors
GATE: completed=true authored=10/10 errors=0 files=3 => PASS

The three failures are reference-server disagreement and do not gate.

Also exercised the new selection logic directly against the extracted VSIX:
required_framework=10.0.0required_major=10 → formula dotnet → runtime
assertion passes.

Closes the last blocker on #155.

🤖 Generated with Claude Code

DavidBakerEffendi and others added 2 commits August 26, 2026 11:04
The roslyn shard failed the v0.3.1 freeze with ten errored C# cases. The
language server started and every initialize request failed in milliseconds.
Its stderr, which the workflow log does not carry, says:

  You must install or update .NET to run this application.
  Framework: 'Microsoft.NETCore.App', version '10.0.0'
  The following frameworks were found: 8.0.30

vscode-csharp 2.140.9 targets net10.0. This step asserted net8.0 and pinned the
Homebrew .NET 8 keg to guarantee it, so it provisioned the one runtime the
server cannot use. Its runtimeconfig sets rollForward: Major, which only rolls
upward, so 8.x can never satisfy a 10.0.0 request.

That premise came from a comment rather than from the server, and the previous
two changes here inherited it: the original gate rejected the runner for
offering .NET 10 -- exactly what Roslyn needs -- and the follow-up made the
provisioning succeed, which moved the failure from the gate to the launch and
made it look like a runtime that was merely absent.

Read the requirement instead of restating it. Stage the VSIX first, take the
framework version from the server's own runtimeconfig, select the matching
Homebrew formula, and assert that major is present. A future VSIX bump now
moves the runtime with it rather than failing at launch against a version
pinned in a comment.

Verified against the pinned VSIX and both runtimes on macOS arm64. Under .NET
8.0.30 the C# baseline errors on all six cases with the stderr above; under
.NET 10.0.11 it is six passed, zero errors. The full ten-case C# legacy slice
satisfies the freeze gate: authoredCases 10, errors 0, three case files, seven
passed and three reference disagreements that do not gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The freeze-shard test asserted the exact dotnet@8 provisioning lines, and the
toolchain probe rehearsed the same sequence to catch regressions cheaply. Both
encoded net8.0 as a fact rather than reading it from the server, so neither
could have caught the premise being wrong -- the test pinned it in place and
the probe would have reported a green contract the freeze no longer depends on.

Assert the derivation instead of the value. The test now requires that the
framework is read from the runtimeconfig and that the runtime gate is written
against that major, and forbids a restated dotnet@8 prefix or a literal
NETCore.App 8 grep surviving anywhere in the workflow.

The probe resolves the framework the same way the freeze does: download the
pinned VSIX, read its runtimeconfig, choose the Homebrew formula, and pass both
values to the later steps as step outputs. A future VSIX bump moves the probe
with the freeze rather than leaving it rehearsing an old contract.

Testing: unittest discover runs 39 tests green, and both workflows' shell
blocks pass bash -n.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@DavidBakerEffendi
DavidBakerEffendi merged commit 32661f7 into main Aug 26, 2026
5 checks passed
@DavidBakerEffendi
DavidBakerEffendi deleted the dave/roslyn-requires-net10 branch August 26, 2026 09:46
DavidBakerEffendi added a commit that referenced this pull request Aug 26, 2026
The v0.3.1 legacy freeze

([32954887242](https://github.com/BrokkAi/usagebench/actions/runs/32954887242))
ran **all eleven candidate shards green** — roslyn included, so #171
worked —
and then failed in aggregation:

```
Error: canonicalize promotion artifact docs/legacy-promotion-selection-policy.md
Caused by: No such file or directory (os error 2)
```

`freeze-manifest` resolves a promotion manifest's bound artifacts
relative to
the staged corpus. The legacy manifest binds its eligibility policy
under
`docs/`, and `stage-release-bundle.sh` copies `benchmarks fixtures
adapters
schema src containers scripts` plus a few root files — never `docs/`. So
the
bundle could not canonicalize an artifact its own manifest hash-binds,
which is
exactly the self-verifying property the tier exists to provide.

It is the only such artifact: sweeping every `file` reference in
`benchmarks/promotion/**` yields one path outside the staged prefixes,
bound by
both `manifest.json` and `cohort.json`.

## The fix

Copy exactly the bound files, **derived by reading the promotion
manifests**
rather than naming `docs/` here, so a newly bound artifact is staged
without
editing this script. Not all of `docs/` — that carries `node_modules`
and build
output, which would bloat the bundle and hand the analyzer a large
unrelated
tree to index.

## Verification, against the failed run's own evidence

- Staging emits the policy at the manifest's expected path, sha256
`1ac2968892c97af5…` — **matching the binding** — and `docs/` contributes
that
  one file and nothing else.
- Downloaded all eleven shard reports from that run and re-ran the exact
  aggregation: **succeeds**, satisfies the workflow's
`snapshotKind == "legacy_promoted" and balancedCoreCaseCount == 110 and
(.corpus | length == 30)` gate, and `generate-results` produces both
pages.

That run's Bifrost report also confirms the expected set from #160
exactly:

```
110 cases: 106 passed, 1 improved, 3 failed, 0 errors   (bifrost 6624e883)
  improved  cpp-parity-function-like-macro-expanded-call
  failed    rust-struct-construction                                  (#170)
  failed    rust-parity-module-declaration-definition                 (#170)
  failed    scala-parity-case-class-generated-construction-and-copy
```

## Regression cover

Adds a test asserting the derivation is present and that every artifact
bound
outside the staged prefixes actually exists. `unittest discover` runs 40
tests
green; reproduction contract exits 0.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant