@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.
Files changed (2) hide show
  1. package/README.md +52 -14
  2. 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 that returns exact answers in milliseconds.
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
- - **Hard Token Caps (`--budget`):** Guarantees answers fit within strict limits (e.g. `--budget 300` or `--budget 600`), exiting cleanly with code `2` on overflow instead of polluting conversation history.
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)* | 100% automated structural coverage | Structured, clean, noise-free output |
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:** Instantaneous sub-millisecond execution, zero JIT warm-up, and zero-allocation queries via `System.Collections.Frozen`.
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
- - **🛡️ Token-Budget Enforcement (`--budget N`):** Hard limits on output tokens. Prevents agent context exhaustion by exiting with actionable tips when a query is too broad.
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
- > **For Blazor & Razor projects:** Run your build with compiler-generated files enabled once, so Roslyn outputs component sources for `csmesh` to discover:
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 300
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` 300, `path`/`where` 400, `trace`/`unresolved` 600, `map`/`silence` 700, everything else 800.
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 300
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 800
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 400
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** | Symbol graph has not been generated. | Execute `csmesh index` and retry. |
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.4.1",
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"