v0.1.9
[0.1.9] — 2026-05-22
Post-0.1.8 follow-through: a deep audit pass over the previously
untouched modules (walker, lockfile, json, rewrite, script, parallel),
the recast-mcp server crate for MCP-aware AI agents, a nightly
fuzz workflow, a criterion regression gate on PRs, and the symlink +
concurrent-apply regression tests that pin down behavior the audit
exposed.
Added
recast-mcpcrate. Model Context Protocol server that exposes
the recast engine to MCP-aware AI agents (Claude Desktop, Cursor,
Continue, Cline, custom MCP clients). Library-linked against
recast-core— no subprocess, no CLI string assembly, no JSON
parse round-trip. Speaks JSON-RPC over stdio per MCP convention.
Four tools, 1:1 with the planner API:recast_preview,
recast_apply,recast_structural,recast_recover. Typed
argument schemas (viarmcp1.7 +schemars1.x) so agents can't
malform calls; engine errors propagate asMcpErrorwith the
typedkinddiscriminator preserved in the payload.- Walker symlink regression tests. Cover cycle detection,
dangling links, escape-root behavior with/without
follow_symlinks, and the gitignore interaction when following
links. Symlink semantics now documented inwalker.rsmodule
doc-comment. - Concurrent-apply integration tests in
crates/recast/tests/concurrency.rs. External fs2 lock on
.recast.lockforcesrecast --applyto exit non-zero with the
Lockederror;--forcebypasses the guard. - Nightly fuzz workflow (
.github/workflows/fuzz.yml) runs three
cargo-fuzz targets (compile_friendly_query,
structural_rewrite_friendly, pattern_compile_convergence) for 60
minutes each per day. Corpus cached across runs so coverage
compounds. - Criterion regression gate (
.github/workflows/bench.yml) runs
benches on every PR, diffs against themainbaseline stored on
gh-pages, comments + fails the check at >50% regression.
Changed
- Walker uses
WalkParallelinstead of the single-threaded
iterator. Honors the surrounding rayon pool's thread count so
--threads Nis now respected for the walk phase as well. label_for_pathfast path for absolute / plain-relative paths
— skips the PathBuf rebuild when no leading./needs stripping.
Saves one allocation per labeled file in the planner's hot loop.from_applyroutes throughheader(plan)to dedupe the
JsonHeader construction; the two header builders no longer drift.
Fixed
- Lockfile error misclassification.
acquire_workspace_lock
used to fold everyio::Errorfromtry_lock_exclusiveinto
Error::Locked, hiding permission-denied / ENOSPC / EIO behind
"another recast is already applying". Now matches on
ErrorKind::WouldBlockand only that variant maps toLocked;
every other variant propagates asError::Iowith the underlying
source preserved. - Workspace lock derivation canonicalizes input paths and locks
at the deepest common ancestor. Two--applyinvocations against
the same tree from different CWDs (or one againstsrc/, one
againstsrc/sub/) now share one.recast.lockinstead of
proceeding in parallel. - EXDEV fallback in
commit_one,rollback_committed, and
recover_sweep. A newrename_with_exdev_fallbackhelper catches
ErrorKind::CrossesDevicesfromfs::renameand degrades to
copy + sync_all + remove_file. Same-directory renames inside a
normal filesystem never hit this path; overlayfs, unionfs, FUSE
backends, and certain container layouts can return EXDEV even for
lexically-sibling renames, so the apply now degrades cleanly
rather than aborting.