Skip to content

v6.0.0

Choose a tag to compare

@aovestdipaperino aovestdipaperino released this 25 May 08:48
· 140 commits to master since this release

[6.0.0] - 2026-05-25

Breaking

  • Daemon mode removed. The tokensave daemon subcommand, autostart flags (--enable-autostart / --disable-autostart), foreground mode, and all daemon-kit-backed service registration are gone. ~1,100 lines of platform glue (launchd plists, systemd user units, Windows SCM, PID files, UAC elevation) deleted. File-watching now lives inside the MCP server itself — it spawns a notify-backed watcher that runs sync_if_stale_silent for the duration of the agent session, and exits when the agent disconnects. Multiple MCP peers on the same project converge through the existing per-project sync lock plus sync_if_stale_silent's peer-coordination check; no new primitive was needed. Users with a registered autostart service should unload it manually — see "Migration" in docs/TOKEN-SAVE-WHATSNEW.md §6.0.0.
  • UserConfig::daemon_debounce renamed to watcher_debounce. TOML load is backwards-compatible via #[serde(alias = "daemon_debounce")] and any config-mutating command rewrites the file with the new name; Rust struct literals referencing the old name are a compile-time break.
  • McpServer::new now returns Arc<Self>. The embedded watcher task captures a Weak<Self> so it cannot extend the server's lifetime. Embedders that bound the return value continue to compile; destructuring by value or storing into a non-Arc field needs to adapt.
  • tokensave install --agent claude writes the modern hook shape {type, command, args}. Legacy single-string "command": "<bin> <subcmd>" entries are detected by tokensave doctor and auto-rewritten using current_exe() as the binary path (issue #81). This is a breaking change for any external tooling that introspects ~/.claude/settings.json and assumed the legacy concatenated form.
  • Beta release channel disabled. .github/workflows/release-beta.yml is gated behind BETA_CHANNEL_ENABLED=false and a workflow_dispatch-only trigger. The code is preserved for future revival; no *-beta.* versions will ship from this commit forward.

Added

  • tokensave_redundancy MCP tool (#83). AST-level functional-duplicate detector. Computes four signals per function/method body via tree-sitter — AST shape hash, control-flow-graph hash, ordered call-sequence hash, and a 5-gram token-shingle set — then blends them into a [0, 1] composite similarity score (weights 0.40 / 0.25 / 0.20 / 0.15). Pairs are bucketed definite / likely / naming_only and ranked by score. Language-agnostic by design: kind walks use raw tree-sitter strings, so the same code path works for every supported grammar. Computation is lazy — fingerprints land in a new node_fingerprints table (schema v10) keyed by (node_id, body source hash) and persist across MCP sessions. Pairwise comparison is bucketed by body-token count (±25 % window) so it stays sub-quadratic on large repos.
  • tokensave_runtime MCP tool + tokensave status --runtime flag (#80). Captures a process + database telemetry snapshot: PID, RSS, virtual size, sustained CPU% sampled over 200 ms, uptime, host CPU count, total system memory, DB / WAL / SHM file sizes, journal_mode PRAGMA, total indexed source bytes, node and edge counts, and a derived db / source bloat ratio. Lets users hitting unexpected resource pressure attach a structured snapshot to a bug report. Text report mirrors the tokensave status layout; JSON output via --json for machine consumption.
  • tokensave_health details=true sub-score breakdown (#82). Returns per-dimension { score, interpretation, raw_count, source } objects covering acyclicity (with edges_in_cycles), depth (max_chain / ideal_chain), equality (gini + textual interpretation), redundancy (dead_count / total_fns), modularity (textual label + components-after-hub-removal), and coverage discipline (skip_test_coverage_count). The composite quality_signal (geometric mean × 10 000) is preserved as the headline figure.

Changed

  • File-watcher rewritten around notify-debouncer-full 0.8.0-rc.2. Replaces the DIY tokio debounce timer with the maintained library, which coalesces rename pairs, suppresses redundant modify-after-create, and batches event bursts cross-platform. Drop-in transparent to callers — ProjectWatcher::new(root, debounce) signature unchanged.
  • Watcher no longer recursive-watches the project root. Top-level entries are enumerated at startup; IGNORED_DIRS (target/, node_modules/, .git/, …) and dotdirs (.vscode, .idea, …) are never registered as watches, so the kernel never reports events for them. The root itself is watched non-recursively to surface new top-level directories appearing after startup. This is the primary mitigation for the high CPU/RAM symptoms reported in #80 on Windows, where ReadDirectoryChangesW's per-watch buffer could be overwhelmed by churn inside a large node_modules.
  • Direct notify dependency dropped. Pulled transitively through notify-debouncer-full; project_watcher imports types via notify_debouncer_full::notify to keep a single crate instance in the resolver graph (debouncer 0.8.0-rc.2 depends on notify 9.0.0-rc.4).
  • doctor auto-repair logic for hook entries. Modern-shape hooks with the wrong subcommand are fixed in place (preserving the user's bin path); legacy single-string hooks are rewritten using current_exe() since the embedded path cannot be parsed unambiguously when it contains spaces. Breaks the doctor → install loop that issue #81 reported on Windows path-with-spaces installs.

Fixed

  • Hook install on paths with spaces (#81). Previously, install --agent claude wrote "command": "C:/Path With Spaces/tokensave.exe hook-pre-tool-use" as a single string. Claude Code whitespace-splits the field, so the kernel executed C:/Path with arg With and the hook silently never fired. doctor correctly diagnosed the mismatch but then re-installed the same broken shape, looping forever. Switching to {"command": "...", "args": ["hook-..."]} sidesteps the splitter entirely. Doctor now also recognises the legacy shape as needing repair, not removal.

Schema

  • Migration v10. Adds the node_fingerprints table backing tokensave_redundancy: node_id PRIMARY KEY, ast_hash, cfg_hash, call_seq_hash, shingles (comma-separated lowercase hex), body_tokens, source_hash. Indexed on ast_hash and body_tokens for the redundancy query's bucketed scan. As with prior migrations, opening a v9 database triggers a one-time full re-index on first open.

Internal

  • New src/redundancy.rs module. Tree-sitter walk utilities (kind-only AST hash, control-flow filtered hash, ordered call-sequence hash), token shingle generator, Jaccard similarity over sorted shingle sets, composite similarity blender, and the severity bucketing rules. Eight unit tests cover identical-body / different-structure / call-sequence-order / Jaccard self-similarity behaviour.
  • New src/runtime_telemetry.rs module. RuntimeSnapshot { process, database } collected via sysinfo 0.32 + libsql PRAGMA reads. Process side requires a refresh + 200 ms sleep + refresh sequence because sysinfo reports CPU% as a delta between successive readings.
  • TokenSave::db_path() accessor. Recomputes the on-disk DB path via resolve_db_for_branch for diagnostics. Stable across the lifetime of an open TokenSave.
  • Tool registry grew from 68 → 71 (or 67 → 70 when ast-grep is unavailable). Two new entries: tokensave_redundancy, tokensave_runtime. The previously shipped tokensave_health details=true schema knob is documented here for visibility.