# Reported issues for RoselineMCP

Pod holds 23 of 37 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to [RoselineMCP](/mcp/roselinemcp).

## Most discussed

### [Bug]: The failure envelope names no checkout, so an omitted `project` miss stays undiagnosable

> **Scope sharpened 2026-08-20 by a backlog triage pass.** Two thirds of this issue have landed; the
> old title and implementation plan described work that is already merged, so a worker picking it up
> cold would have re-implemented #143. What remains is one specific gap, named below. The original
> report is preserved at the bottom.

## What is left

**The failure path names no checkout.** #143 added `resolvedPath` to every response from a tool with
an optional `project` — but only on the **s

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/139) · 2026-08-19 · closed · 4 comments

### [Bug]: The write confirmation asks a human before establishing there is a non-empty write to approve

> **Rescoped 2026-08-20 by a backlog triage pass.** This issue was filed against one instance
> (`newSource` validated after the prompt). That instance is **fixed** — verified against `dev` @
> `eb19739`, not inferred from a PR title. The *root* it was an instance of is still open, and one
> further instance of it remains. The issue now tracks the root; the original report is preserved
> verbatim at the bottom.

## What happened?

**The root: the write-confirmation gate asks a human before estab

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/162) · 2026-08-20 · closed · 3 comments

### [Bug]: The write confirmation is composed per tool by raw interpolation, so caller input can forge the sentence a human approves

## What happened?

Found by the code-review pass on PR #157 (issue #154). **Pre-existing — not introduced by that PR**,
though #157's longer sentence makes the first half of it easier to exploit.

`ToolExecutionHelper.ResolveWriteModeAsync` (#129) centralised the write-confirmation gate's
**policy** — when to elicit, how to read the answer, what a timeout means — but deliberately left the
**wording** to each tool. Each of the three write tools therefore builds its sentence itself, by
interpolati

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/161) · 2026-08-20 · closed · 2 comments

### [Bug]: resolvedPath can name a .sln that does not contain the project that answered

## What happened?

`resolvedPath` — the field added in #143 so a caller can tell which checkout and which project file
actually answered — can name a `.sln` that **does not contain the project the symbols came from**.

`ProjectLoader.LoadAsync` resolves a `.csproj` target by first looking for the nearest ancestor
`.sln` and opening it, then locating the target inside it:

```csharp
var solutionPath = FindSolutionFile(targetPath);
if (solutionPath != null)
{
    var solution = await workspace.Ope

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/151) · 2026-08-20 · closed · 2 comments

### [Feature]: Extract the duplicated write-confirmation block shared by the three write tools

Continues #125.

## What problem does this solve?

The write-confirmation block is copy-pasted verbatim across all three write tools. `ApplyFixesTool.cs`,
`EditMemberTool.cs` and `RenameSymbolTool.cs` each carry the same ~12 lines:

```csharp
var effectivePreviewOnly = previewOnly;
string? declineNote = null;
// Use the caller's request token (not the wall-clock timeout) for the human confirmation
// round-trip: think-time must not be charged against the analysis budget.
if (!previewOnly && !awa

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/129) · 2026-08-19 · closed · 2 comments

### [Feature]: Surface key examples for diagnostics no code fix provider can repair (suggest_fix_examples)

## What problem does this solve?

`apply_fixes` can only repair a diagnostic for which a Roslyn or Roslynator `CodeFixProvider`
exists. `CodeFixProviderFactory.LoadProviders()` builds an ID → provider-type map by reflecting
over the Roslyn built-ins plus the bundled `AnalyzerCatalog` assemblies;
`DiagnosticFilterService.IsFixableDiagnostic()` reads that map, and it is exactly what populates
`list_diagnostics`' `suggestedFixableIds`. Anything outside that map is **reported and then
abandoned**: t

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/180) · 2026-08-21 · open · 1 comment

### [Bug]: Option-binding tests still fail when a ROSELINE_ variable is exported with different casing

Continues #132.

**Related:** #126, #128, #131, #140

## What happened?

#132 made `RoselineMcpOptionsBindingTests`' two `*_Binds_From_The_Documented_Environment_Variable`
tests independent of an ambient `ROSELINE_` export by wrapping each in a scope that clears the
variable for the duration:

```csharp
const string key = "ROSELINE_RoselineMCP__ConfirmDestructiveWrites";
using var _ = ScopedEnvironmentVariable.Set(key, null);
```

That clears **one exact key spelling**. But the two sides of this

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/141) · 2026-08-20 · closed · 1 comment

### [Feature]: Verify edits against the compiler before writing, and add check_compilation

## What problem does this solve?

RoselineMCP's value proposition today is token efficiency: a measured **89% median** reduction per
tool call, and **~13%** end-to-end in realistic, self-directed agent use
([`docs/AGENT-BENCHMARK.md`](../blob/dev/docs/AGENT-BENCHMARK.md), n=1).

That proposition has a shrinking moat — context windows grow, caching gets cheaper, and a 13%
saving becomes invisible. More tellingly, the end-to-end benchmark records that *"quality was
identical in every cell"*: **Ros

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/133) · 2026-08-19 · closed · 1 comment

## Most recent

### [Bug]: ProjectLoader's explicit-.csproj ambiguity fallback catches ArgumentException too broadly

**Related:** #213, #218

## What happened?

`ProjectLoader.FindSolutionFile`'s ambiguous-solution-walk fallback (added by #213 / PR #218) is
gated with:

```csharp
catch (ArgumentException) when (IsExplicitCsprojPath(project))
{
    // degrade to a standalone load of the named .csproj
}
```

This catches the **exception type**, not a signal specific to "the ancestor walk found more than one
`.sln`". Anything else in `FindSolutionFile`'s call chain that happens to throw `ArgumentException`
(e.g. 

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/226) · 2026-08-26 · closed · 0 comments

### [Bug]: FindSolutionFile's ambiguity refusal (#172) breaks an explicitly-named .csproj in a multi-solution monorepo

## What happened?

`ProjectLoader.FindSolutionFile` (the ancestor `.sln` walk `LoadAsync` uses once a `.csproj` target
is resolved) gained an ambiguity check in #172/PR #192: when an ancestor directory holds more than
one candidate `.sln`, it now throws `ArgumentException` instead of silently taking `slnFiles[0]`.
That's correct for the AppleDouble-shadow scenario #172 fixed, but the check runs unconditionally —
for **every** non-`.sln` target `LoadAsync` resolves, including one the caller named

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/213) · 2026-08-26 · closed · 0 comments

### [Feature]: Pin website/src/data/tools.ts to the reflected [McpServerTool] set — #197's root cause survives

## What problem does this solve?

`Continues #197.`

#206 made the website's tool count **self-consistent**. It did not make it **correct**, and the
distinction is the whole of this issue.

The headings now derive from `website/src/data/tools.ts`, so the page can no longer contradict its own
grid. But `tools.ts` is itself a **hand-maintained** array, and nothing links it to the server's actual
`[McpServerTool]` set. The chain has two links and #206 closed only the second:

```
C# [McpServerTool]

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/208) · 2026-08-25 · closed · 0 comments

### [Feature]: ElicitationTests' prompt-assertion helpers encode stale assumptions about the prompt frame

## What problem does this solve?

Deferred by PR #202 (which closed #173) — two defects in `RoselineMCP.Tests/Protocol/ElicitationTests.cs`
that share one root: the **prompt-assertion helpers reason about the sentence heuristically** — by
counting apostrophes and hunting for quote characters — rather than from the `WriteScope` vocabulary
the sentences are actually rendered from. Because the helpers encode assumptions about the *frame*,
they drift whenever the frame changes, and #173 changed it.

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/204) · 2026-08-25 · closed · 0 comments

### [Bug]: The apply_fixes confirmation for a .csproj target reads like a promise to rewrite that file

## What happened?

Deferred deliberately by PR #202 (which closed #173) — filed so the decision is tracked rather than
left in a source comment.

#173 re-ordered two of the three write-confirmation sentences so the resolved target is the **last**
thing in every prompt. That closed a real hole, but it changed the frame the `apply_fixes` sentence
sits in, and the `.csproj` branch inherited a new ambiguity from the move.

`WritePrompt.RenderPrimaryProjectOf` (`RoselineMCP/Models/WriteScope.cs`) bra

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/203) · 2026-08-25 · closed · 0 comments

### [Bug]: verification/check_compilation error paths still anchor to Solution.FilePath — the fourth site diverging from resolvedPath

## What happened?

`Continues #181.`

#151 changed how `resolvedPath` is computed. #181 then updated the three consumers that had been
re-deriving the same anchor independently (`CodeNavigationService.BaseDirOf`, `CodeFixService`'s
`ApplyFixes`, `CodeEditService.RelativePath`) to read one authoritative value,
`LoadedProject.BaseDirectory`. Its scope named exactly those three.

**A fourth site was left behind, deliberately and with the reason recorded** — but it is still a
live divergence in ship

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/199) · 2026-08-25 · closed · 0 comments

### [Feature]: analyzerLoad — count references without analyzers instead of naming each, and name code fixers that fail to load

Continues #183.

**Related:** #180, #183, #188

## What problem does this solve?

#188 shipped the `analyzerLoad` block on `list_diagnostics`, `analyze_solution` and `apply_fixes`:
every analyzer reference that contributed nothing is named, with Roslyn's reason. Two edges were
left for the owner to decide, both measured while landing it:

**(a) Volume.** On a project that references the Roslynator packages — this repository, and any
target that does — **33 of 44** analyzer references yield no C#

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/191) · 2026-08-24 · open · 0 comments

### [Bug]: An analyzer reference that loads nothing is reported as nothing, and its code fixers are never loaded

## What happened?

Two things, one root shape: **RoselineMCP never tells the caller what it could not load.**

**(1) An analyzer reference that fails to load contributes zero diagnostics, silently.**
`DiagnosticComputationService.CollectAnalyzers()` calls `reference.GetAnalyzers(LanguageNames.CSharp)`
inside a `try/catch`. That catch only fires on an **exception**. Roslyn's `AnalyzerFileReference`
does not throw when it cannot load an analyzer type — it raises the `AnalyzerLoadFailed` event and

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/183) · 2026-08-21 · closed · 0 comments

### [Feature]: Add the two missing MCP tool-description components — Limitations and Examples — compactly

## What problem does this solve?

RoselineMCP's own end-to-end benchmark names the bottleneck: **"The highest-leverage improvement is
adoption."** (`docs/AGENT-BENCHMARK.md`, § Takeaways) In the greenfield and
brownfield cells the server was installed *and* the system prompt nudged the agent toward it, and it
made **zero** RoselineMCP calls — the tools were exercised only after `Read`/`Grep`/`Glob` were
removed. The same document's follow-up shows what moves that needle: server-level `instructio

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/179) · 2026-08-21 · closed · 0 comments

### [Feature]: Make turns and tool calls a first-class metric of the agent benchmark, alongside tokens and cost

## What problem does this solve?

This repo measures agent cost in three places, and **none of them counts turns.**

| Benchmark | Question it answers | Unit |
|---|---|---|
| `RoselineMCP.Benchmarks` (`BENCHMARKS.md`) | how long does a service call take? | milliseconds |
| `RoselineMCP.TokenBenchmark` | how compact is *one* tool response? | tokens per task |
| `docs/AGENT-BENCHMARK.md` | does an agent doing a real task end to end spend fewer tokens? | tokens / dollars per session |

Turns — the

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/178) · 2026-08-21 · open · 0 comments

### [Bug]: ApplyFixes' write loop can rewrite a file whose diff turned out blank

## What happened?

Found during code review of #162 (PR #174, which made `ApplyFixesResponse.ChangedFiles` reliably
diff-filtered — a document is only added once its unified diff turns out non-blank).

`CodeFixService.ApplyFixesAsync`'s "Apply changes if not preview only" block still writes from the
**raw Roslyn `changedDocuments` set**, not from the now-filtered `response.ChangedFiles`:

```csharp
// Apply changes if not preview only
if (!previewOnly && changedDocuments.Any())
{
    foreach (va

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/175) · 2026-08-20 · closed · 0 comments

### [Bug]: A checkout path containing an apostrophe unbalances two of the three write-confirmation prompts

## What happened?

Found by the code-review pass on PR #170 (issue #161). **Pre-existing — not introduced by that PR**,
and deliberately left open by it: #161's own exposure table lists the target as injectable "only via a
checkout path containing `'`", which is the operator's filesystem rather than the caller's input.

#161 closed the caller-controlled half. `symbol` and `newName` now pass a whitelist inside
`WritePrompt.Render`, so a caller cannot open or close a quoted run. The **resolved tar

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/173) · 2026-08-20 · closed · 0 comments

### [Bug]: Shared IncidentalScan exposes macOS AppleDouble ghost files (._App.sln) to auto-discovery

## What happened?

`AttributesToSkip = 0` on the shared `IncidentalScan` options (introduced in #158,
`RoselineMCP/Services/ProjectLoader.cs`) is required so that dot-prefixed **directories** — the
`.claude/worktrees/<name>/` layout Claude Code creates — stay discoverable: the default
(`Hidden | System`) would hide them on Unix, since .NET infers `Hidden` from a leading dot.

The same options object is now used for `DiscoveryLevels`, `FindFilesAcross`, and
`FindSolutionFile` — three call sites t

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/172) · 2026-08-20 · closed · 0 comments

### [Feature]: Report the compile verdict after every file write via a `roseline-mcp guard` hook, not only RoselineMCP's own writes

## What problem does this solve?

The compile gate shipped in #133 is the first thing RoselineMCP does that a bigger context window
cannot make obsolete: it is a *correctness* guarantee, not a cost saving. But it only fires on
writes that go **through RoselineMCP's own write tools** — `edit_member`, `rename_symbol`,
`apply_fixes`. That makes it opt-in twice over: the agent must first choose RoselineMCP at all, and
then choose a RoselineMCP write tool over `Edit`/`Write`.

`docs/AGENT-BENCHMARK.m

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/168) · 2026-08-20 · closed · 0 comments

### [Feature]: Run the pre-registered end-to-end quality A/B for the compile-verified edit loop

Continues #133.

## What problem does this solve?

`docs/AGENT-BENCHMARK.md` currently ships a **pre-registered protocol with a deliberately empty
results table**. Its own header says so:

> **Status: not yet run.** The protocol is pre-registered here; the results table is deliberately
> empty. Do not cite anything from this section as a measurement.

That section exists because of the single most important line in the rest of that document:
**"Quality was identical in every cell."** Every bench

[Read the thread](https://github.com/Atypical-Consulting/RoselineMCP/issues/166) · 2026-08-20 · open · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/Atypical-Consulting/RoselineMCP/issues).
