diff --git a/agent-node/agent_node/core/sync.py b/agent-node/agent_node/core/sync.py index af8c8c0..f130762 100644 --- a/agent-node/agent_node/core/sync.py +++ b/agent-node/agent_node/core/sync.py @@ -44,6 +44,33 @@ session_dir = self.get_session_dir(session_id, create=True) print(f"[📁] Reconciling Sync Directory: {session_dir}") + from shared_core.ignore import CortexIgnore + ignore_filter = CortexIgnore(session_dir) + expected_paths = {f.path for f in manifest.files} + + # 1. Purge extraneous local files and directories (handles Deletions) + for root, dirs, files in os.walk(session_dir, topdown=False): + for name in files: + abs_path = os.path.join(root, name) + rel_path = os.path.relpath(abs_path, session_dir) + if rel_path in [".cortexignore", ".gitignore"]: continue + if rel_path not in expected_paths and not ignore_filter.is_ignored(rel_path): + try: + os.remove(abs_path) + print(f" [📁🗑️] Deleted extraneous local file: {rel_path}") + except Exception as e: + print(f" [⚠️] Failed to delete file {rel_path}: {e}") + + for name in dirs: + abs_path = os.path.join(root, name) + rel_path = os.path.relpath(abs_path, session_dir) + if rel_path not in expected_paths and not ignore_filter.is_ignored(rel_path): + try: + if not os.listdir(abs_path): + os.rmdir(abs_path) + except Exception: + pass + needs_update = [] for file_info in manifest.files: target_path = os.path.join(session_dir, file_info.path) diff --git a/ai-hub/app/core/grpc/core/mirror.py b/ai-hub/app/core/grpc/core/mirror.py index 3f7403e..08faf9d 100644 --- a/ai-hub/app/core/grpc/core/mirror.py +++ b/ai-hub/app/core/grpc/core/mirror.py @@ -90,6 +90,31 @@ def reconcile(self, session_id: str, remote_manifest: agent_pb2.DirectoryManifest) -> List[str]: """Compares remote manifest with local mirror and returns list of paths missing/changed.""" workspace = self.get_workspace_path(session_id) + ignore_filter = self.get_ignore_filter(session_id) + + expected_paths = {f.path for f in remote_manifest.files} + + # 1. Purge extraneous local files and directories (handles Deletions) + for root, dirs, files in os.walk(workspace, topdown=False): + for name in files: + abs_path = os.path.join(root, name) + rel_path = os.path.relpath(abs_path, workspace) + if rel_path in [".cortexignore", ".gitignore"]: continue + if rel_path not in expected_paths and not ignore_filter.is_ignored(rel_path): + try: + os.remove(abs_path) + print(f" [📁🗑️] Ghost Mirror deleted extraneous file: {rel_path}") + except Exception: pass + + for name in dirs: + abs_path = os.path.join(root, name) + rel_path = os.path.relpath(abs_path, workspace) + if rel_path not in expected_paths and not ignore_filter.is_ignored(rel_path): + try: + if not os.listdir(abs_path): + os.rmdir(abs_path) + except Exception: pass + needs_update = [] for remote_file in remote_manifest.files: if remote_file.is_dir: continue