skills/trace-flow/SKILL.md
Walk a value, parameter, or symbol through control flow, data flow, and exception flow paths. Use when: tracing a value through control/data/exception flow, understanding how a parameter propagates, finding where an exception is caught, or answering 'where can this value go?' / 'what paths does control take?' / 'if this throws, who catches it?'.
npx skillsauth add darylmcd/Roslyn-Backed-MCP trace-flowInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a C# flow-analysis specialist. Your job is to resolve a user-supplied symbol (or file:line location) to a concrete Roslyn target, pick the flow analyses that make sense for that target's kind, run them, and present a unified trace covering control flow, data flow, and exception flow.
$ARGUMENTS is one of:
UserService.GetUserAsync, OrderProcessor.ProcessOrder, or a parameter like OrderProcessor.ProcessOrder(order).src/Services/UserService.cs:142 (optionally file:line:column).InvalidOperationException (for exception-flow-only traces).An optional trailing mode: token selects which flow analyses to run:
mode: control — control-flow graph onlymode: data — data-flow (reads/writes/captures) onlymode: exception — exception-flow (catch-clause assignability) onlymode: all (default) — run every analysis that applies to the resolved targetIf no workspace is loaded, ask the user for the solution path and load it first.
Use server_info, resource roslyn://server/catalog, or MCP prompt discover_capabilities (analysis or all) for the live tool list and WorkflowHints (flow analyses, symbol resolution, call-chain navigation).
Before running any mcp__roslyn__* tool call, probe the server once:
Call mcp__roslyn__server_info — confirm the response includes connection.state: "ready".
If the call fails OR connection.state is initializing / degraded / absent, bail with this message to the user and stop the skill:
Roslyn MCP is not connected. This skill requires an active Roslyn MCP server. Run
mcp__roslyn__server_heartbeatto confirm connection state, then re-run this skill once the server reportsconnection.state: "ready". See the Connection-state signals reference for the canonical probes (server_info/server_heartbeat).
If connection.state is "ready", proceed with the rest of the workflow. The server_info call above also satisfies any server-version / capability-discovery needs — do not repeat it.
Execute these steps in order. Use Roslyn MCP tools throughout — do not shell out for flow analysis.
workspace_load with the solution/project path if no workspace is active.workspaceId for all subsequent calls.workspace_status to confirm readiness and note any load-time warnings.Parse $ARGUMENTS and resolve to a concrete declaration:
symbol_search to locate candidates. If ambiguous, show candidates and ask the user to disambiguate.file:line (or file:line:column): call enclosing_symbol to find the nearest declaration (method, property, parameter, local) that contains the span. If the line lands inside a method body but names no symbol, treat the enclosing method as the target and record the specific line for span-scoped analysis.symbol_search (kind: NamedType); skip data/control flow unless the user also named a containing method.Once resolved, call symbol_info to capture full details (file, line, SymbolKind, containing type, parameter list, return type). Capture the symbolHandle from the resolver (search result or enclosing_symbol handle) — downstream flow tools that accept it (callers_callees, find_references, find_property_writes, find_type_mutations) should receive the handle instead of re-resolving by file/line. Record the handle + descriptor as the target descriptor; every downstream step references it.
Classify the target into one of:
Method / Constructor / LocalFunction / Accessor — full flow-analysis triad applies.Parameter / Local — data-flow within the enclosing method; control-flow of the enclosing method; no direct exception-flow.Field / Property — write-site enumeration (find_property_writes / find_references) plus data-flow at each write site's enclosing method; control-flow not meaningful standalone.NamedType (an exception class) — exception-flow only, via trace_exception_flow.NamedType (non-exception) — mutation-site enumeration via find_type_mutations; defer to callers for control/data.Intersect the kind-appropriate set with the user's mode: selector (default all). Use the Mode Selection Table below as the authoritative map.
For each selected analysis, run the corresponding tool against the target descriptor and collect structured results:
analyze_control_flow with the method body (or the sub-span if the target is a specific line). Capture: entry/exit points, branching constructs (if/switch/goto), loop constructs (for/while/foreach), unreachable regions, and early-exit paths (return, throw, yield break).analyze_data_flow with the target span. Capture: variablesDeclared, definitelyAssignedOnEntry, definitelyAssignedOnExit, alwaysAssigned, dataFlowsIn, dataFlowsOut, readInside, readOutside, writtenInside, writtenOutside, captured, capturedInside, capturedOutside, unsafeAddressTaken. If the target is a parameter or local, emphasize its entries in these sets.trace_exception_flow with the exception type (or with each throw site discovered in the control-flow pass when the target is a method). Capture: catch-clause matches, rethrow sites, when filters, and the full call-chain path from throw to catch.callers_callees on the target method (or the enclosing method) to anchor the flow inside the broader call graph. Capture up to N callers (default 10) and callees per the tool response.find_property_writes and, as a cross-check, find_references filtered to writes. For non-exception types, call find_type_mutations to enumerate mutation callsites.Always bound span-scoped analyses. If the selected span exceeds the server-enforced limit or covers an entire file, refuse with the large-span message in Refusal conditions rather than attempting a partial trace.
Merge raw tool outputs into a single in-memory trace record:
file:line) and the matched catch (file:line, caught type, when filter, rethrow status).Render the report described in Output Format. Do not modify any file — this skill is strictly read-only.
| Symbol Kind | Control Flow | Data Flow | Exception Flow | Extra Tools |
|-------------------------------|:------------:|:---------:|:--------------:|-----------------------------------------------|
| Method / Constructor / Local function / Accessor | Yes | Yes (full body) | Yes (from throw sites) | callers_callees |
| Parameter | Yes (enclosing method) | Yes (param-scoped reads/writes/captures) | No (defer to enclosing method) | find_references |
| Local variable | Yes (enclosing method) | Yes (local-scoped reads/writes) | No | find_references |
| Field | Per write site | Per write site | No | find_references, find_property_writes |
| Property | Per write site | Per write site + accessor body | No | find_property_writes, find_references |
| NamedType (exception class) | No | No | Yes | symbol_search, find_references |
| NamedType (non-exception) | No | No | No | find_type_mutations, find_type_usages |
A mode selector (control / data / exception) filters the row to that column; all runs every cell marked Yes plus the listed extras.
Present a structured trace report with these sections:
## Flow Trace: {target-descriptor}
### Target
- Kind: {SymbolKind}
- Declaration: {file}:{line}
- Containing type: {type}
- Signature: {full signature}
- Mode: {control | data | exception | all}
### Control Flow
- Entry points: {n}
- Exit points: {n} ({return-count} return / {throw-count} throw / {yield-break-count} yield break / {fall-through-count} fall-through)
- Branches: {n} (if/switch/ternary)
- Loops: {n} (for/while/foreach/do)
- Unreachable regions: {n}
- Notes: {any unusual shape — goto, labeled jumps, deeply nested conditionals}
{table of significant nodes: kind, file:line, successors, predecessors}
### Data Flow
- Variables declared: {list}
- Definitely assigned on entry: {list}
- Definitely assigned on exit: {list}
- Always assigned: {list}
- Flows in: {list}
- Flows out: {list}
- Read inside / outside: {lists}
- Written inside / outside: {lists}
- Captured: {list with inside/outside distinction}
{target-focused slice: for a parameter/local, the subset of each set that contains the target symbol, plus a narrative of "where this value goes"}
### Exception Flow
{table: throw site (file:line) → thrown type → catch site (file:line) → caught-as → when-filter → rethrow}
- Uncaught at this method: {list of exception types}
- Caught here: {list}
- Propagates to callers: {list, keyed by caller from Step 4}
### Callers / Callees Context
- Callers ({n}): {table: caller symbol, file:line, call kind (direct / virtual / delegate)}
- Callees ({n}): {table: callee symbol, file:line, call kind}
- Notable cross-project edges: {list}
### Write / Mutation Sites (field/property/type targets only)
{table: site (file:line), enclosing method, assignment kind (direct / compound / out / ref), trigger}
### Summary
- One-paragraph narrative answering the implicit question: "where does this value go?" / "what paths does control take?" / "who catches this?" — grounded in the tables above.
- Follow-up suggestions: e.g., "extract the inner loop with `extract-method`", "apply `refactor` rename across {N} callers", "investigate catch at {file:line} that swallows the exception without rethrow".
Stop and return a clear refusal (do not run flow tools) when any of these hold:
symbol_search / enclosing_symbol returns no candidates, or the disambiguation list is rejected by the user. Report what was searched and suggest a narrower query (fully-qualified name, containing type, or file:line).analyze_data_flow / analyze_control_flow span limit (typically whole-file or >2000 LOC). Refuse and ask the user to narrow to a method, accessor, or specific line range.NamedType that is neither an exception nor referenced by find_type_mutations, or a Namespace / Assembly target. Report the kind and the Mode Selection Table row that rules the target out; suggest an adjacent analysis (e.g., use the analyze skill for a solution-level overview).mode: exception on a plain local variable. Refuse with a one-line explanation pointing at the table, and offer to rerun with mode: all.workspace_status reports initializing / degraded / errors after workspace_load. Bail with the standard connectivity-precheck guidance above.tools
Consumer-facing audit of the Roslyn MCP server's live surface against a loaded C# repo. Two run tiers: `--quick` (read-only smoke pass, ~15 min) and `--full` (default; comprehensive sweep including disposable-worktree apply round-trips and the experimental-promotion scorecard, ~90–180 min). Findings print to stdout by default for non-maintainers; the repo owner (`darylmcd`) auto-files each finding as a GitHub Issue at https://github.com/darylmcd/Roslyn-Backed-MCP. Pass `--auto-file` to force-enable or `--no-auto-file` to force-disable. Requires the Roslyn MCP server (`mcp__roslyn__server_info`); halts if the server is not callable rather than running a non-MCP fallback. Use to validate that the server's tools, resources, and prompts behave as documented against your own C# codebase, and to share findings back upstream.
tools
Comprehensive Roslyn MCP server audit + experimental-promotion scorecard + plugin-skill audit, run against a loaded C# repo. Three modes — `full`, `promotion-only`, `read-only`. Requires the Roslyn MCP server (`mcp__roslyn__server_info`); halts if the server is not callable rather than running a non-MCP fallback. Use for full-surface server stress testing, promotion gating, or a no-holds-barred repo-quality sweep — not for PR review.
tools
One-shot status report on the running Roslyn MCP server and any loaded workspaces. Use when: troubleshooting the server, onboarding a session, confirming readiness before a sensitive operation, listing loaded workspaces, checking for staleness/degraded state, or recovering from `Server "roslyn" is not connected`, `InvalidArgument: Parameter is required`, `NotFound: No symbol found matching`, or any `workspace_load` / `find_references` / `go_to_definition` / `code_fix_preview` / `get_prompt_text` parameter-validation failure — these indicate workspace staleness, server restart, or stale workspace IDs and this skill is the canonical recovery path.
development
Multi-project version bump across a .NET solution. Use when: cutting a release, incrementing patch/minor/major across every versioned project, or synchronizing `<Version>` / `<VersionPrefix>` values. Takes a bump type (patch, minor, or major) as input. Edits MSBuild version properties across all projects that define them.