Skip to content

Commit f12b65f

Browse files
authored
Merge pull request #27 from Litenova-Solutions/release/v4.1
Release v4.1.0
2 parents 95b2983 + a922e53 commit f12b65f

101 files changed

Lines changed: 2976 additions & 740 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Build first, then test with `--no-build`. CI verifies build, test, format, and a
4747
- Upgrades degrade to a clear message or a rebuild, never an opaque failure. This invariant applies from the first public tag (v4.0.0) onward: v4 ships a clean slate with no deprecation shims and no legacy names, because nothing was ever released to break (Decision D14). From v4 forward, renaming or removing an MCP tool must keep the old name registered as a deprecation shim that returns an actionable message naming the replacement, for one major version; a client that cached the old surface across an upgrade must not see a bare `Unknown tool`. A change to the index extraction contract must either bump `WorkspaceIndexSchema.TargetVersion` or ride the Fuse-version stamp (`fuse_version` in `index_meta`, compared by `FuseBuildInfo.IsCompatible`), so a stale on-disk index rebuilds itself rather than serving stale data. The changelog entry names the reload or rebuild.
4848
- Capture bundles are versioned and refused when incompatible (C2). A portable capture bundle (`fuse capture --out`, consumed by `fuse index --from-capture`) carries a `CaptureManifest` stamped with a `BundleFormatVersion` and the producing `fuse_version`. A change to the on-disk bundle layout (the manifest shape, the graph serialization, or the compiler-log contents `fuse index --from-capture` depends on) must bump `CaptureManifest.CurrentFormatVersion`; a change to the extraction contract already rides the `fuse_version` major.minor check (`FuseBuildInfo.IsCompatible`). The consumer refuses a bundle whose format version or producing-version is incompatible via `CaptureManifest.IsCompatibleWithRunningBuild` with the actionable `IncompatibilityReason` (re-capture with the running version), so a bundle is never rehydrated into a wrong-shaped store. The changelog entry names the re-capture.
4949

50+
Decision D14 is a one-time v4 exception, not a permanent no-shim policy. v4.0.0 is the first public tag, so R1 deleted every pre-release shim and legacy name; there was no install base to protect. From that tag onward, the upgrade invariant binds: renaming or removing an MCP tool registers the old name as a deprecation shim (actionable message naming the replacement) for one major version, so clients cached across upgrades never see a bare `Unknown tool`. Changelog entries still name every behavioral change; only the pre-v4 migration machinery was dropped.
51+
5052
## MCP Tools
5153

5254
The eight-tool loop surface (U1), plus `fuse_reduce` as the one out-of-loop utility. Each tool is one mental act, so the loop is teachable in a tool description (after an edit, `fuse_check`; before a signature change, `fuse_impact`; before done, `fuse_review`):
@@ -92,7 +94,7 @@ All numbers come from `tests/benchmarks/results` (the recorded data) and the ben
9294

9395
## Working a plan item
9496

95-
Forward work is organized as a dependency-ordered program in [roadmap/v4-plan.md](roadmap/v4-plan.md) (the live program; the original oracle-wave plan is archived at the end of the same file). That file is the execution law; this section is the pointer plus the guardrails inline so they are read before any edit.
97+
Forward work is organized as a dependency-ordered program in [roadmap/v4-plan.md](roadmap/v4-plan.md) (the live program; the original oracle-wave plan is archived at the end of the same file). Post-4.1 hardening tails from the architecture review live in [roadmap/v4.2-plan.md](roadmap/v4.2-plan.md). That file is the execution law; this section is the pointer plus the guardrails inline so they are read before any edit.
9698

9799
- **Reading order for a fresh session.** The plan's Execution protocol section in full, then its Decision records, its Metrics dictionary, its Master checklist (the single source of item status), then the item you are about to work including its Preconditions and Gate.
98100
- **Item lifecycle.** Status lives only in the Master checklist: `[ ]` todo, `[>]` in progress, `[x]` done (gate recorded green in the progress log), `[!]` blocked (progress log names the blocker), `[-]` descoped (progress log names the written decision). Never record status inside item bodies.

CHANGELOG.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,45 @@
22

33
All notable changes to Fuse are documented here. The format is based on Keep a Changelog. Fuse 4.0.0 is the first public release; it carries the whole product and there is no prior public version to migrate from.
44

5+
## [Unreleased]
6+
7+
Planned for 4.2.0 (see [roadmap/v4.2-plan.md](roadmap/v4.2-plan.md)):
8+
9+
- Split `WorkspaceIndexStore` into narrow stores; profile the index hot path first.
10+
- Semantic-tier provider seam (C# behind an interface; no second language in 4.2).
11+
- Unify Fusion and Retrieval scoping; delete the retired flat FTS generator.
12+
- CI job for `RequiresSdk` tests; finish `briefing.md` drift cleanup.
13+
- Unified MCP/CLI/host RPC contract documentation; host IPC and hook ergonomics.
14+
- Narrow `fuse update` process termination.
15+
16+
## [4.1.0] - 2026-07-14
17+
18+
### Added
19+
20+
- Fuse brand icon (`assets/fuse-icon.png`, `assets/fuse-icon.svg`) on the NuGet package gallery, MCP Registry manifest, WinGet locale, site favicons, and the repository README.
21+
- Host RPC threat-model documentation (`internals/host-rpc`) describes the local-trust IPC model: predictable per-root pipe or socket, handshake session token, and served-root binding on RPC methods that carry a `root` argument. The page documents `fuse/check` and `fuse/checkOverlay`.
22+
- Opt-in MCP metrics via `FUSE_METRICS=1` (`fuse.tool.duration`, `fuse.index.mode`, `fuse.reconcile.stamped`) using `System.Diagnostics.Metrics` (no OpenTelemetry dependency).
23+
- `WorkspacePathResolver` confines MCP file arguments (`fuse_check`, `fuse_test`, `fuse_reduce`, `fuse_context`, and related paths) to the workspace root.
24+
- `fuse.json` / `.fuserc` parse failures write a warning to stderr with the file path instead of failing silently.
25+
- `FUSE_MCP_INSTALL_HOME` redirects user-scope MCP install paths for isolated testing; user-scope install coverage for Cursor and Copilot.
26+
- Integration tests for split-store cache recovery, storm reconcile (>300 dirty files), MCP read-after-edit freshness, resident storm eviction (301-file batch), and workspace path escape refusal.
27+
28+
### Changed
29+
30+
- Derived key-value cache data (reduction cache and per-file analysis index) now lives in `.fuse/fuse-cache.db` instead of sharing `.fuse/fuse.db` with the semantic index. Existing cached entries in `fuse.db` are not migrated; rerun with `--use-cache` or `--use-persistent-index` to rebuild the derived cache. The semantic index in `fuse.db` is unchanged.
31+
- `ExperimentalOptions` now carries only focus/change scoping and emission-shaping knobs the fusion pipeline consumes (`CentralityWeight`, `TieredEmission`, `SketchHugeFiles`, `DowngradeBeforeDrop`, `ProximityEdges`, `ProjectGraph`). Query-path retrieval levers were removed from this type; open-ended localize and related lexical ranking live in `Fuse.Retrieval`.
32+
- Host RPC methods that carry a `root` argument reject calls where the root differs from the daemon's served root (the `--directory` the `fuse host` process started with).
33+
- Syntax indexing routes exclusively through `SemanticIndexer` and language syntax providers; the standalone `SyntaxIndexer` type is removed.
34+
- The retired flat FTS candidate generator is gated behind `FUSE_FLAT_FTS=1` diagnostic mode; shipping default remains `LexicalCandidateGenerator` only.
35+
- Performance documentation and README warm-latency figures align with `tests/benchmarks/results/performance.json` and `resident-latency.json`.
36+
- `briefing.md` opening reflects nine MCP tools, no VS Code extension (D15), and corpus-v2 localize recall (37.7 percent).
37+
- The fuse.codes landing page uses a centered hero with terminal-style install commands, benchmark stats, and a shared site footer; WinGet manifests are included in `set-version.ps1` and `verify-version.ps1`.
38+
39+
### Fixed
40+
41+
- When FTS5 is unavailable at index init, the store persists `fts_available=false` in index meta, names it in `fuse_workspace` status and the availability header, and `fuse_find kind=task` refuses with an actionable message instead of returning empty hits.
42+
- `SqliteKeyValueStore` corruption recovery refuses to delete the semantic index database; only `fuse-cache.db` is recreated on corruption.
43+
544
## [4.0.1] - 2026-07-13
645

746
### Added

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<!-- Single source of truth for the product version, applied to every Fuse assembly so the CLI, the host,
55
and FuseBuildInfo (the index version stamp) all report the same number. The release tag must match this
66
(enforced by build/verify-version.ps1); bump every package in lockstep with build/set-version.ps1. -->
7-
<Version>4.0.1</Version>
7+
<Version>4.1.0</Version>
88
<TargetFramework>net10.0</TargetFramework>
99
<ImplicitUsings>enable</ImplicitUsings>
1010
<Nullable>enable</Nullable>

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
<!-- mcp-name: io.github.Litenova-Solutions/fuse -->
22

3+
<p align="center">
4+
<img src="assets/fuse-icon.svg" alt="Fuse" width="72" height="72">
5+
</p>
6+
37
# Fuse
48

59
Fuse is a local .NET tool with a persistent semantic index and pre-write compiler
@@ -44,7 +48,7 @@ syntax-level indexing for that project and reports the mode.
4448
handlers, and tests with provenance. On 69 recorded pull requests the median response was
4549
1,026 tokens at 93.4 percent precision (`review.json`).
4650
- **Read warm.** On the recorded NodaTime run, exact symbol lookup took 2.2 ms at the
47-
median, task localization 42 ms, and review planning 117 ms (`performance.json`;
51+
median, task localization 23.4 ms, and review planning 97.8 ms (`performance.json`;
4852
timings are environment-dependent).
4953

5054
<p align="center">

SECURITY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
| Version | Supported |
66
|---------|-----------|
7+
| 4.1.x | Yes |
78
| 4.0.x | Yes |
89

9-
Security fixes ship in patch releases on the current minor version. Upgrade to the latest 4.0.x release.
10+
Security fixes ship in patch releases on the current minor version. Upgrade to the latest 4.1.x release.
1011

1112
## Reporting a Vulnerability
1213

assets/fuse-icon-256.png

4.89 KB
Loading

assets/fuse-icon.png

2.1 KB
Loading

assets/fuse-icon.svg

Lines changed: 12 additions & 0 deletions
Loading

briefing.md

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,13 @@ Roslyn-backed index of a workspace and resolves what the code actually runs (whi
5555
implementation is injected for an interface, which handler processes a request, which endpoint
5656
serves a route, what a git diff impacts), then hands the agent the exact context a task needs,
5757
reduced to fit the context window. It ships two ways: a .NET global tool (`fuse`) for the
58-
terminal and CI, and a Model Context Protocol (MCP) server (`fuse mcp serve`) with fourteen
59-
tools an agent calls in a loop. There is also a VS Code extension that talks to a resident
60-
host process over JSON-RPC.
58+
terminal and CI, and a Model Context Protocol (MCP) server (`fuse mcp serve`) with nine tools
59+
an agent calls in a loop. A long-lived `fuse host` process on a named pipe serves the
60+
ambient-verification hooks and can share one resident workspace across MCP sessions (the VS Code
61+
extension was removed in v4, Decision D15). On the buildable corpus-v2 benchmark, open-ended
62+
task localization reaches 37.7 percent changed-file recall (95 percent CI 30 to 46) at 21.1
63+
percent precision; precise wiring lookup and graph-backed review remain the deterministic
64+
strengths.
6165

6266
The problem it exists to solve: an AI agent working on an unfamiliar .NET codebase burns
6367
enormous token budget and many tool round-trips just exploring. It greps, opens files, greps
@@ -452,9 +456,9 @@ host, a cold read serves syntax-first then schedules a background upgrade superv
452456
`SemanticUpgradeSupervisor` (N3 part 1): deduped per root, failures logged to stderr, cancelled
453457
and drained on host shutdown so no task is orphaned. It remains off by default because the CLI
454458
`fuse index` is always a synchronous full pass and short-lived callers must not leave background
455-
work running. Documented cold timings (NodaTime, `performance.json`): syntax tier about 18 s;
456-
full semantic pass about 58 s; syntax-first plus background upgrade to semantic-ready about 83 s
457-
additional. N3 remainder (resident workspace plus dependency-scoped semantic re-index) is not yet
459+
work running. Documented cold timings (NodaTime, `performance.json`): syntax tier about 17.8 s;
460+
full semantic pass about 24.6 s; syntax-first plus background upgrade to semantic-ready about
461+
48 s additional. N3 remainder (resident workspace plus dependency-scoped semantic re-index) is not yet
458462
shipped; incremental reconcile still updates syntax rows only (issue 5).
459463

460464
### 6.2 Tier-1 build capture (oracle-grade, opt-in)
@@ -933,15 +937,21 @@ published.
933937

934938
| Operation | P50 | P95 |
935939
|-----------|----:|----:|
936-
| Warm localize | 41.6 ms | 54.6 ms |
937-
| Warm resolve | 0.0 ms | 0.0 ms |
938-
| Warm review plan | 116.6 ms | 135.6 ms |
939-
| Incremental re-index (one file) | 24.2 ms | 28.2 ms |
940-
941-
Cold: syntax tier served in 18,343 ms; semantic-ready after further 83,279 ms (background
942-
upgrade path); full semantic pass 58,245 ms. Incremental re-index updates syntax rows only, not
940+
| Warm localize | 23.4 ms | 25.2 ms |
941+
| Warm find symbol | 2.2 ms | 3.6 ms |
942+
| Warm resolve | 0.0 ms | 0.1 ms |
943+
| Warm review plan | 97.8 ms | 101.3 ms |
944+
| Incremental re-index (one file) | 20.9 ms | 25.4 ms |
945+
946+
Cold: syntax tier served in 17,840 ms; semantic-ready after further 48,329 ms (background
947+
upgrade path); full semantic pass 24,554 ms. Incremental re-index updates syntax rows only, not
943948
cross-file semantic edges.
944949

950+
**Resident verify path (`resident-latency.json`, NodaTime, opt-in with `FUSE_RESIDENT=1`):**
951+
resident warm (build plus rehydrate) 14,092 ms; RSS 162 MB; overlay check (speculative
952+
typecheck, analyzers off) P50 31.2 ms / P95 42.4 ms (S1 gate PASS); delta mode (whole-state
953+
diff) P50 203.9 ms / P95 699.3 ms (S2 gate PASS).
954+
945955
---
946956

947957
### 9.10 N4 bake-off: build-capture vs MSBuildWorkspace (`n4-bakeoff.json`)

build/set-version.ps1

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Sets the product version across every package in one step: the .NET source of truth (Directory.Build.props),
2-
# the MCP registry manifest (both version fields), and the docs website. Run this, commit, then tag the matching
3-
# version; build/verify-version.ps1 enforces the match in CI.
2+
# the MCP registry manifest (both version fields), the docs website, and the WinGet manifests under packaging/winget.
3+
# Run this, commit, then tag the matching version; build/verify-version.ps1 enforces the match in CI.
44
#
55
# ./build/set-version.ps1 3.1.2
66
param(
@@ -29,4 +29,17 @@ $siteJson = Join-Path $root "site/package.json"
2929
Set-Content $siteJson -NoNewline
3030
Write-Host "site/package.json -> $Version"
3131

32+
# WinGet manifests: PackageVersion in all three files; installer URL tracks the release tag.
33+
$wingetDir = Join-Path $root "packaging/winget"
34+
foreach ($manifest in @("Litenova.Fuse.yaml", "Litenova.Fuse.locale.en-US.yaml", "Litenova.Fuse.installer.yaml")) {
35+
$path = Join-Path $wingetDir $manifest
36+
$content = Get-Content $path -Raw
37+
$content = $content -replace 'PackageVersion:\s*[^\r\n]+', "PackageVersion: $Version"
38+
if ($manifest -eq "Litenova.Fuse.installer.yaml") {
39+
$content = $content -replace 'InstallerUrl:\s*[^\r\n]+', "InstallerUrl: https://github.com/Litenova-Solutions/Fuse/releases/download/v$Version/fuse-$Version-setup.exe"
40+
}
41+
Set-Content $path $content -NoNewline
42+
}
43+
Write-Host "packaging/winget/* -> $Version"
44+
3245
& (Join-Path $PSScriptRoot "verify-version.ps1")

0 commit comments

Comments
 (0)