Code analysis only: confirmed by reading the code, not reproduced live. Filed for completeness after the v0.9.1 sync work.
Problem
Registry writes are neither atomic nor serialized, so a concurrent registration can be lost permanently.
upsert_workspace (src-tauri/core/src/workspace/registry.rs:56-61) is an unlocked read-modify-write:
let mut workspaces = load_registry(file)?;
workspaces.retain(|w| w.path != entry.path);
workspaces.push(entry);
save_registry(file, &workspaces)
save_registry then writes with a plain std::fs::write (registry.rs:51), truncating in place rather than writing a temp file and renaming.
Two consequences:
- Lost workspace (permanent). Multiple MCP sidecars run concurrently, one per agent session. If two call
init_workspace at the same time, both read the same registry, and the second write clobbers the first entry. That workspace never appears in the GUI, and nothing retries, because as far as the agent is concerned the registration succeeded.
- Torn read (transient). A reader can observe a partially written file. The GUI's reconcile logs the parse error and returns, so the workspace stays unlisted until the next focus reconcile. Self-correcting, but it means a legitimate write can be invisible for a while.
The same non-atomic std::fs::write pattern is used for doc, task, and memory writes; those are self-correcting on the next scan, so this issue is scoped to the registry, where the loss is permanent.
Proposed fix
Write via temp file plus std::fs::rename in save_registry (rename is atomic on the same filesystem, which fixes the torn read), and guard the read-modify-write in upsert_workspace with an advisory file lock so concurrent sidecars serialize instead of clobbering.
Problem
Registry writes are neither atomic nor serialized, so a concurrent registration can be lost permanently.
upsert_workspace(src-tauri/core/src/workspace/registry.rs:56-61) is an unlocked read-modify-write:save_registrythen writes with a plainstd::fs::write(registry.rs:51), truncating in place rather than writing a temp file and renaming.Two consequences:
init_workspaceat the same time, both read the same registry, and the second write clobbers the first entry. That workspace never appears in the GUI, and nothing retries, because as far as the agent is concerned the registration succeeded.The same non-atomic
std::fs::writepattern is used for doc, task, and memory writes; those are self-correcting on the next scan, so this issue is scoped to the registry, where the loss is permanent.Proposed fix
Write via temp file plus
std::fs::renameinsave_registry(rename is atomic on the same filesystem, which fixes the torn read), and guard the read-modify-write inupsert_workspacewith an advisory file lock so concurrent sidecars serialize instead of clobbering.