diff --git a/agent-node/VERSION b/agent-node/VERSION index be1dcc8..ea2f1d3 100644 --- a/agent-node/VERSION +++ b/agent-node/VERSION @@ -1 +1 @@ -1.0.73 +1.0.74 diff --git a/agent-node/src/agent_node/core/watcher.py b/agent-node/src/agent_node/core/watcher.py index 3f50201..56199a2 100644 --- a/agent-node/src/agent_node/core/watcher.py +++ b/agent-node/src/agent_node/core/watcher.py @@ -55,6 +55,16 @@ # Resolve real paths to handle symlinks (e.g. /tmp -> /private/tmp on macOS) real_src = os.path.realpath(event.src_path) rel_path = os.path.normpath(os.path.relpath(real_src, self.root_path)) + + # M6: Extremely Critical macOS FSEvent/inotify fix. + # If a file is "deleted" but actually still exists on disk, it's either an os.replace() + # overwrite firing a deleted event for the unlinked inode, or a highly delayed + # FSEvent where a network-write (chunk) re-created a file that was deleted moments ago. + # We MUST suppress this, or it creates an infinite Delete Echo loop in the mesh! + if os.path.exists(real_src) or os.path.lexists(event.src_path): + print(f" [📁🛑] Watcher Suppressing echo delete because file STILL EXISTS (delayed event / replace): {rel_path}", flush=True) + return + # Critical: Do NOT send DELETE for internal temp/lock files. # When sync does os.replace(tmp -> final), the OS fires a delete for .cortex_tmp. # Without this filter, the watcher would relay a spurious DELETE to the Hub server.