fix(copaw, filesync): delete API, .agentteamsignore + mc mirror --remove (close #896) - #1105
Open
RerankerGuo wants to merge 2 commits into
Open
Conversation
agentscope-ai#896 Close agentscope-ai#896. Three interlocked fixes for the shared-file deletion + ignore gap reported in that issue: 1. filesync(action='delete') — new shared-path delete action - sync.py: add FileSync.delete_shared_path() which issues mc rm --recursive --force against the MinIO shared/ key and then unlinks the local counterpart (file or directory). - filesync.py: allow action='delete' in the validation set and route it through delete_shared_path; global-shared remains read-only. Handles absent-remote gracefully so 'delete after teammate already removed' is idempotent. 2. .agentteamsignore (legacy .hiclawignore) support in push_local - sync.py _parse_ignore_file() / _matches_ignore_pattern() implement a gitignore subset: blanks + # comments, trailing / for dir-only, basename globs (*.tmp) match at any depth, and anchored path globs (config/local.json) match from the sync root. .agentteamsignore wins when both it and .hiclawignore exist. push_local() consults the patterns just after the built-in exclusion lists. 3. mc mirror --remove for directory shared pull/push (ghost-file loop) - pull_shared_path directory mirrors, push_shared_path directory mirrors, both gain --remove so a delete that has been pushed does not get re-imported on the next pull. Startup mirror_all's primary worker-prefix mirror keeps credentials excluded and does NOT yet add --remove because that scope can legitimately contain on-disk-only runtime artifacts; the targeted shared/ mirrors are the correct place for the flag. Changelog entry added per copaw/AGENTS.md change policy. Co-authored-by: RerankerGuo <[email protected]>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
RerankerGuo
force-pushed
the
fix/issue-896-file-sync-ignore-and-delete
branch
from
July 30, 2026 00:53
96ccb54 to
3b5f09c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three interlocked fixes for the shared-file deletion + ignore gap reported in #896:
.agentteamsignore(legacy:.hiclawignore) support in the periodicpush_localuploader — a gitignore-style pattern file at the worker sync root (basename globs, anchored paths, directory-only with trailing/, # comments + blanks). Patterns there add on top of the existing built-in Manager-owned / auto-mirrored exclusion lists, so transient tool outputs, caches, per-project.envfiles and the like are never uploaded to MinIO. Legacy.hiclawignoreis honored as a fallback so pre-rename projects continue to work.mc mirror --removefor shared directory pull + push closes the prior "ghost file" loop: a file deleted locally and then pushed to MinIO (via --remove on push) no longer gets re-imported on the next shared directory pull (--remove on the pull side). Startup worker-prefix mirror intentionally keeps the flag off so local-only runtime artifacts and session files are not wiped; the flag is only added on the targeted shared/ directory mirrors where deletions are user-visible and intentional.Design Decisions
mirror_allprimary worker prefix mirror? That scope mixes Controller-written (MinIO is source of truth) and Worker-written (local only, e.g. session snapshots) files. Adding --remove there would legitimately delete Worker state with no recovery path. The shared/ directories are the correct scope for the flag because both sides treat them as shared mutable state.fnmatch-level basename globs + anchored path globs + trailing/directory markers. No!negations, no**/multi-level — those can be added later if real-world user demand surfaces..agentteamsignorewins when both it and.hiclawignoreexist. Explicitly forward-looking; existing installations get a clear migration path when they rename the file.Change List
copaw/src/copaw_worker/sync.py_parse_ignore_file()+_matches_ignore_pattern()ignore helpers (gitignore-style subset).FileSync.delete_shared_path()—mc rm --recursive --force+ local cleanup (shutil.rmtree / unlink), graceful handling of already-removed remote objects, global-shared/ read-only gate.push_local()now parses user ignore rules from the sync root and filters candidates after built-in exclusions.pull_shared_path()directory mirrors gain--remove; same for the mirror-fallback path on cp failure.push_shared_path()directory mirrors gain--remove.copaw/src/copaw_worker/hooks/tools/filesync.py"delete"; routing invokessync.delete_shared_path()and returns{ok:true, deleted:true}. global-shared/ is blocked at the sync layer.changelog/current.md— entry added percopaw/AGENTS.mdchangelog policy.Risk Assessment
--removeon shared dir mirrors. If a user has local-only content sitting undershared/with no MinIO counterpart, that content is removed the next time filesync pulls that directory. This is the correct mirror semantics given the shared/ namespace's contract ("MinIO is the source of truth for shared data"), and matches OpenClaw's mc mirror usage for shared/ — but any legacy workflow that stashed local-only files under shared/ will see those files disappear. Mitigation: documented behavior change +.agentteamsignoregives such workflows an immediate opt-out to place ignored files elsewhere..hiclawignore, basename globs, directory-only patterns, anchored paths, and integration with push_local-style filters; noagentscope/nio/richdependencies so the test runs independently in the CI Python interpreter of the maintainer's choice.mc rm --recursive --forcewith a "does not exist" result is converted to an INFO log plus normal exit — teammates can remove the same shared file concurrently without error, which is the correct idempotent behavior for a user-facing delete.Test Plan
python3 -m py_compile copaw/src/copaw_worker/sync.py— Syntax OK.python3 -m py_compile copaw/src/copaw_worker/hooks/tools/filesync.py— Syntax OK..hiclawignorefallback,.agentteamsignorewins over.hiclawignore, basename*.tmpmatch at any depth, directory-onlysecrets/match at any depth, anchoredconfig/local.jsononly matches from root, push_local-style glob on tmp files) → all PASS.copaw/tests/— blocked on local environment lackingagentscope / nio / richdependencies; same failures exist on unmodifiedmainso no regression is introduced.shared/projects/pr-896/with a.env+output.tmpplus aREADME.md, configure.agentteamsignorewith*.tmp\n.env\n, run CoPaw Worker startup, invokefilesync(action="push") shared/projects/pr-896/→ verify onlyREADME.mdlands in MinIO.--remove, then pull back into a fresh local dir → verify deleted file does not reappear.filesync(action="delete")twice on a just-removed shared directory → second call returns{ok:true, deleted:true}with no error.