Skip to content

fix(bridge): same-size same-mtime file rewrites bypass ensure_open resync #162

Description

@bug-ops

Description

SyncSignature uses (mtime, size) to detect external file changes. A file rewrite that produces the same size within the filesystem's mtime tick granularity (1 second on ext4/HFS+) generates an identical signature. The stat→read→re-stat pattern introduced in #103 does not close this window: if the write completed before the first stat, both stats return the same mtime and size.

Common triggers:

  • A formatter that reorders imports or comments without changing file size
  • A macro-expansion tool that produces same-length output
  • Any atomic rename(2) replacement within the same mtime tick

Reproduction Steps

  1. Open a Rust file via an MCP tool call (triggers ensure_open)
  2. Replace the file with same-byte-count content within the same second
  3. Call get_hover or another tool on the modified file
  4. Observe: mcpls sends the old content to the LSP server (stale textDocument/didOpen)

Expected Behavior

mcpls should detect the content change and resync the document.

Actual Behavior

SyncSignature comparison returns equal; resync is skipped.

Affected Code

  • crates/mcpls-core/src/bridge/state.rsSyncSignature and ensure_open

Fix Direction

Include a content hash (e.g. xxhash or blake3 of first N bytes) in SyncSignature as a tie-breaker when (mtime, size) is identical to the cached value.

Environment

  • Filesystem: ext4 (1 s mtime resolution), HFS+ (1 s), APFS (1 ns — significantly less likely)
  • Severity: low in practice, but silent data corruption for affected cases

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium: suboptimal behavior, minor inconsistencybugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions