@nrafinia/csmesh 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -14
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -42,6 +42,7 @@ PaymentController.Post {http:POST /charge} Api/PaymentController.cs:14
|
|
|
42
42
|
- [Dual Mode: CLI and MCP Server Support](#-dual-mode-cli-and-mcp-server-support)
|
|
43
43
|
- [Empirical Benchmarks](#-empirical-benchmarks)
|
|
44
44
|
- [Key Features](#-key-features)
|
|
45
|
+
- [Confidence & Provenance](#-confidence--provenance)
|
|
45
46
|
- [Installation](#-installation)
|
|
46
47
|
- [Global .NET Tool](#1-as-a-global-net-tool)
|
|
47
48
|
- [Standalone Native AOT Binary](#2-as-a-standalone-native-aot-binary-zero-runtime-dependency)
|
|
@@ -84,7 +85,7 @@ In layered, enterprise .NET applications, **lexical text search (`grep`, `ripgre
|
|
|
84
85
|
4. **Attribute-based & Blazor Endpoint Routing** (`[HttpGet]`, `[HttpPost]`, `@page "/..."`)
|
|
85
86
|
5. **Razor & Blazor Components** (types, `@code` methods, and parameter bindings compiled via Roslyn source generators)
|
|
86
87
|
|
|
87
|
-
**`csmesh` solves this in a single shell command.** It parses your codebase's AST and semantic model via Roslyn into a pre-compiled, frozen symbol graph
|
|
88
|
+
**`csmesh` solves this in a single shell command.** It parses your codebase's AST and semantic model via Roslyn into a pre-compiled, frozen symbol graph and answers in milliseconds — and every edge it hands back carries how it was derived and how sure it is, so an answer can be checked instead of trusted.
|
|
88
89
|
|
|
89
90
|
---
|
|
90
91
|
|
|
@@ -94,7 +95,7 @@ In layered, enterprise .NET applications, **lexical text search (`grep`, `ripgre
|
|
|
94
95
|
|
|
95
96
|
* **⚡ Fast CLI-First Execution:**
|
|
96
97
|
- **Zero Idle Context Overhead:** Incurs zero token spend until explicitly invoked.
|
|
97
|
-
- **
|
|
98
|
+
- **Bounded Output (`--budget`):** Every answer is capped at an estimated token count (`--budget 300`, `--budget 600`), exiting cleanly with code `2` on overflow instead of polluting conversation history. The estimate is `ceil((chars + 1) / 4)`, not a model tokenizer — close enough to size a reply, not a billing figure.
|
|
98
99
|
- **Command Chaining:** Chain queries in a single turn (`csmesh impl IStore --budget 200 && csmesh blast-radius Order.Submit --budget 400`).
|
|
99
100
|
|
|
100
101
|
* **🤖 Native Model Context Protocol (MCP) Server:**
|
|
@@ -124,7 +125,7 @@ The evaluation measured four critical dimensions:
|
|
|
124
125
|
| **2. Deep Call Chain Trace**<br>`csmesh trace OrderEndpoints.CreateOrderAsync` | **156 ms**<br>*(1 command to specified depth)* | **5 to 7 iterative turns**<br>*(manually hopping across controllers, interfaces & handlers)* | **~30x faster** end-to-end task time | **~85% reduction**<br>*(~450 tokens vs. ~4,000 tokens)* |
|
|
125
126
|
| **3. Change Impact & Blast Radius**<br>`csmesh blast-radius OrderRepository.UpdateAsync` | **161 ms**<br>*(reverse graph separating test vs. prod callers)* | **4 to 6 manual turns**<br>*(grep for method name with dozens of false positives)* | Eliminates error-prone manual caller matching | **~80% reduction**<br>*(filters out comments, docs, & unrelated homonyms)* |
|
|
126
127
|
| **4. Multi-Hop Path Finding**<br>`csmesh path Endpoint -> Repository` | **157 ms**<br>*(deterministic 4-hop path across DI & services)* | **Impossible with grep**<br>*(requires multi-file inference, guessing, and trial-and-error)* | Solves in 1 deterministic step | **~95% reduction**<br>*(no intermediate exploratory reads)* |
|
|
127
|
-
| **5. Endpoint & Worker Discovery**<br>`csmesh entrypoints` | **143 ms**<br>*(both HTTP routes & background HostedServices)* | **Multiple grep commands + manual parsing**<br>*(high risk of missing background workers and consumers)* |
|
|
128
|
+
| **5. Endpoint & Worker Discovery**<br>`csmesh entrypoints` | **143 ms**<br>*(both HTTP routes & background HostedServices)* | **Multiple grep commands + manual parsing**<br>*(high risk of missing background workers and consumers)* | One pass over every routing form it knows: attribute routes, minimal APIs, `@page`, hosted services, consumers | Structured, clean, noise-free output |
|
|
128
129
|
| **6. Type Structure & Signature**<br>`csmesh context OrderRecord` | **166 ms**<br>*(fields, nullability, signatures without reading disk)* | `rg` to locate file path + `view_file` to read entire source | 3x fewer steps | **~70% reduction**<br>*(symbol members only, no boilerplate)* |
|
|
129
130
|
| **7. Full Architecture Mapping**<br>`csmesh map` | **174 ms**<br>*(29 projects, dependency flow & entrypoint clusters)* | Read `.slnx` + inspect 29 `.csproj` project files manually | Hundreds of times faster | **~95% reduction** |
|
|
130
131
|
|
|
@@ -174,9 +175,9 @@ The evaluation measured four critical dimensions:
|
|
|
174
175
|
|
|
175
176
|
## ✨ Key Features
|
|
176
177
|
|
|
177
|
-
- **🚀 Native AOT & .NET 10 Ready:**
|
|
178
|
+
- **🚀 Native AOT & .NET 10 Ready:** No JIT warm-up, no runtime to install, and lookup tables frozen once at load (`System.Collections.Frozen`) so a query walks the graph instead of rebuilding indexes. Median query on a 29-project solution: ~150 ms, dominated by graph load, not by the walk.
|
|
178
179
|
- **🎨 Blazor & Razor Component Intelligence:** Indexes Blazor components, `@code` methods, component parameters, and Razor Pages / MVC views. Automatically discovers `@page "/..."` routes as HTTP entrypoints and accurately maps line numbers back to `.razor` and `.cshtml` source files via Roslyn `#line` directives.
|
|
179
|
-
- **🛡️
|
|
180
|
+
- **🛡️ Output Budget (`--budget N`):** A hard cap on estimated output tokens. Prevents agent context exhaustion by exiting with actionable tips when a query is too broad.
|
|
180
181
|
- **💉 DI & IoC Container Intelligence:** Reads service registrations in every form they take — two-argument, `typeof` pairs, keyed, factory lambdas, and alias registrations such as `sp => sp.GetRequiredService<Concrete>()` — and ranks the class the container actually returns ahead of the ones nobody registered.
|
|
181
182
|
- **📨 MediatR & CQRS Linking:** Resolves `_mediator.Send(...)` and `Publish(...)` calls to their concrete request handlers across decoupled project boundaries.
|
|
182
183
|
- **💥 Blast Radius & Impact Analysis:** Computes the reverse call graph to surface all direct/indirect callers, affected controllers, and background consumers before modifying a symbol.
|
|
@@ -187,6 +188,37 @@ The evaluation measured four critical dimensions:
|
|
|
187
188
|
|
|
188
189
|
---
|
|
189
190
|
|
|
191
|
+
## 🔬 Confidence & Provenance
|
|
192
|
+
|
|
193
|
+
Not every edge deserves the same trust, and a tool that flattens that distinction is one an agent learns to double-check anyway. `AddScoped<IStore, SqlStore>()` is read straight off the compiler's symbol table. A Scrutor assembly scan says a family of types is wired, not which pair. Both belong in the graph; only one is a fact.
|
|
194
|
+
|
|
195
|
+
So every edge carries three fields:
|
|
196
|
+
|
|
197
|
+
| Field | What it holds |
|
|
198
|
+
|:---|:---|
|
|
199
|
+
| `Confidence` | `1.0` when the compiler bound the symbol. `0.75` for a filtered assembly scan, `0.55` for an unfiltered one. `0.8` is the trust threshold — below it, an edge is a lead to verify, not an answer, and it never outranks an explicit registration. |
|
|
200
|
+
| `Source` | What produced it: `roslyn-symbol`, `semantic-registration`, `semantic-request`, `factory-lambda`, `assembly-scan`, `short-name-match`. |
|
|
201
|
+
| `Site` | The `file:line` of the registration or of the `Send()` call. The target's own location is on the node; this is the other half, so "now change the binding" doesn't start with a grep. |
|
|
202
|
+
|
|
203
|
+
Anything below the threshold prints its score and origin inline rather than blending in:
|
|
204
|
+
|
|
205
|
+
```text
|
|
206
|
+
$ csmesh impl IStore --budget 300
|
|
207
|
+
IStore -- 2 implementation(s)
|
|
208
|
+
SqlStore [di:scoped, ?0.75 assembly-scan] src/Data/SqlStore.cs:12 @ src/Api/Startup.cs:41
|
|
209
|
+
InMemoryStore [test] tests/Fakes/InMemoryStore.cs:8
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
And what csmesh could not resolve is an answer too, not a silence:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
csmesh unresolved --kind di # registrations that produced no edge, with the reason each failed
|
|
216
|
+
csmesh silence IStore # why a symbol has no callers: unbound sites, out-of-scope types
|
|
217
|
+
csmesh doctor # index health, reference count, stale generated sources, version drift
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The graph is a semantic reconstruction of what the code most likely does at runtime, built from Roslyn plus project structure plus known framework conventions. On a compilation with unresolved references it still answers — and `doctor` tells you how much of it stands on solid ground.
|
|
221
|
+
|
|
190
222
|
## 📦 Installation
|
|
191
223
|
|
|
192
224
|
### ⚡ Automatic One-Line Install (Recommended)
|
|
@@ -257,11 +289,16 @@ csmesh index
|
|
|
257
289
|
```
|
|
258
290
|
|
|
259
291
|
> [!TIP]
|
|
260
|
-
> **
|
|
292
|
+
> **Using source generators — or starting from a cold checkout?** A fresh clone resolves less
|
|
293
|
+
> completely than a built one: package and framework types come from `bin/`, and generated sources
|
|
294
|
+
> (Blazor/Razor, System.Text.Json, `[GeneratedRegex]`, `[LibraryImport]`, `[LoggerMessage]`, ...)
|
|
295
|
+
> live under `obj/`. A plain build restores the references; the flags additionally write the
|
|
296
|
+
> generated sources to disk where `csmesh` can read them:
|
|
261
297
|
> ```bash
|
|
262
298
|
> dotnet build --no-incremental -p:EmitCompilerGeneratedFiles=true
|
|
263
299
|
> csmesh index
|
|
264
300
|
> ```
|
|
301
|
+
> `csmesh doctor` reports what it found, and marks unresolved calls when it could not see them.
|
|
265
302
|
|
|
266
303
|
### 2. Configure Your AI Coding Assistants
|
|
267
304
|
```bash
|
|
@@ -284,7 +321,7 @@ csmesh where discount
|
|
|
284
321
|
csmesh trace OrderService.SubmitOrder --budget 600
|
|
285
322
|
|
|
286
323
|
# Which concrete implementation runs for this interface in DI?
|
|
287
|
-
csmesh impl IPaymentGateway --budget
|
|
324
|
+
csmesh impl IPaymentGateway --budget 600
|
|
288
325
|
|
|
289
326
|
# What breaks if I change this method or property?
|
|
290
327
|
csmesh blast-radius Order.Status --budget 800
|
|
@@ -336,7 +373,7 @@ csmesh entrypoints orders
|
|
|
336
373
|
| `--no-telemetry` | Skip recording the invocation in local usage metrics |
|
|
337
374
|
| `-h, --help` | Display command help and usage examples |
|
|
338
375
|
|
|
339
|
-
Default budgets: `impl`
|
|
376
|
+
Default budgets: `impl` 600, `path` 500, `where`/`trace` 600, `unresolved` 700, `silence` 300, `entrypoints` 800, `map` 850, `context` 900, everything else 800.
|
|
340
377
|
|
|
341
378
|
---
|
|
342
379
|
|
|
@@ -376,7 +413,7 @@ csmesh trace OrderService.Submit --depth 3
|
|
|
376
413
|
#### `csmesh impl <IInterface>`
|
|
377
414
|
Finds all implementations of an interface, ranking DI-bound registrations first.
|
|
378
415
|
```bash
|
|
379
|
-
csmesh impl IPaymentGateway --budget
|
|
416
|
+
csmesh impl IPaymentGateway --budget 600
|
|
380
417
|
csmesh impl IOrderRepository
|
|
381
418
|
```
|
|
382
419
|
|
|
@@ -398,7 +435,7 @@ csmesh entrypoints "POST /orders"
|
|
|
398
435
|
#### `csmesh context <Type.Member>`
|
|
399
436
|
Everything structural about one symbol in a single call: signature, members, callers, callees, implementations and the entrypoints above it. Replaces a `trace` plus an `impl` plus a `blast-radius`.
|
|
400
437
|
```bash
|
|
401
|
-
csmesh context OrderService --budget
|
|
438
|
+
csmesh context OrderService --budget 900
|
|
402
439
|
csmesh context IPaymentGateway.Authorize --depth 2
|
|
403
440
|
```
|
|
404
441
|
|
|
@@ -406,7 +443,7 @@ csmesh context IPaymentGateway.Authorize --depth 2
|
|
|
406
443
|
The shortest route between two symbols, across DI bindings and MediatR dispatch. Answers "how does this controller ever reach that repository".
|
|
407
444
|
```bash
|
|
408
445
|
csmesh path PaymentController.Post SqlOrderStore.Save
|
|
409
|
-
csmesh why OrderController.Post CreateOrderHandler.Handle --budget
|
|
446
|
+
csmesh why OrderController.Post CreateOrderHandler.Handle --budget 500
|
|
410
447
|
```
|
|
411
448
|
|
|
412
449
|
#### `csmesh cycles`
|
|
@@ -433,7 +470,7 @@ csmesh changes --calls --budget 1200
|
|
|
433
470
|
```
|
|
434
471
|
|
|
435
472
|
#### `csmesh review [base]`
|
|
436
|
-
The same structural comparison as `changes`, but against a named git revision instead of whatever the last index happened to see — the question a pull request or a CI gate actually asks. Defaults to the merge base with the remote's default branch, cached per commit so a second run is fast. `--accept` writes the current findings to `.csmesh/accepted.txt`; accepted findings stop being reported, and dead entries are pruned automatically once the base moves past them. Exits `5` when something unaccepted remains, so a pipeline can gate on it without parsing prose.
|
|
473
|
+
The same structural comparison as `changes`, but against a named git revision instead of whatever the last index happened to see — the question a pull request or a CI gate actually asks. Defaults to the merge base with the remote's default branch, cached per commit so a second run is fast. `--accept` writes the current findings to `.csmesh/accepted.txt`; accepted findings stop being reported, and dead entries are pruned automatically once the base moves past them. Exits `5` when something unaccepted remains, so a pipeline can gate on it without parsing prose. When the index predates `HEAD` the comparison is refused rather than guessed at — exit `4`, or `64` for `--accept`, since findings from the wrong current side must not be written to the baseline.
|
|
437
474
|
```bash
|
|
438
475
|
csmesh review # vs. the merge base with the default branch
|
|
439
476
|
csmesh review origin/main --calls
|
|
@@ -549,10 +586,11 @@ A symbol graph is not a replacement for text search or reading code; it is a rep
|
|
|
549
586
|
| `1` | **Not Found** | Symbol does not exist in repository. | Check spelling or verify namespace. |
|
|
550
587
|
| `2` | **Over Budget** | Answer exists but exceeds `--budget`. | Re-run with narrower `--depth` or query a specific callee. |
|
|
551
588
|
| `3` | **Ambiguous** | Multiple symbols match query. | Re-run with qualified `Type.Member` instead of bare member name. |
|
|
552
|
-
| `4` | **No Index** |
|
|
589
|
+
| `4` | **No Index** | No usable graph: not generated, or (for `review`) the index predates HEAD. | Execute `csmesh index` and retry. |
|
|
553
590
|
| `5` | **Changed** (`review` only) | Unaccepted structural change vs. the base revision. | Review the finding, then `csmesh review --accept` if it's fine to keep. |
|
|
554
|
-
| `64`| **Usage Error** | Invalid flags, syntax, or arguments. | Run `csmesh <cmd> --help`. |
|
|
591
|
+
| `64`| **Usage Error** | Invalid flags, syntax, or arguments, including `review --accept` while the index predates HEAD. | Run `csmesh <cmd> --help`. |
|
|
555
592
|
| `70`| **Internal Error** | Unhandled failure inside csmesh. | Re-run with `--debug` and open an issue. |
|
|
593
|
+
| `75`| **Contended** | The graph file is held by another process; the write did not happen. | Nothing is broken — wait briefly and re-run the command. |
|
|
556
594
|
|
|
557
595
|
---
|
|
558
596
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nrafinia/csmesh",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Structural code intelligence & call-graph engine for C# and .NET — built for AI coding agents under hard token budgets",
|
|
5
5
|
"bin": {
|
|
6
6
|
"csmesh": "./bin/run.js"
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"bin/run.js",
|
|
13
13
|
"scripts/install.js"
|
|
14
14
|
],
|
|
15
|
+
"homepage": "https://csmesh.rafinia.info",
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
17
18
|
"url": "https://github.com/nRafinia/CsMesh.git"
|