fix(api): resolve zip-namespace collisions when merging drive mounts - #5524
Conversation
The drive folds the artifact's agent mount into the session drive under an `agent-files/` symlink the runner creates in the cwd. geesefs degrades that symlink to a 0-byte OBJECT named `agent-files` in the cwd store (runner comment: "geesefs silently degrades symlinks to empty files across remounts"). "Download all" archives the cwd mount and the folded agent mount as separate sources. The cwd `agent-files` object was archived as a FILE, colliding with the `agent-files/` DIRECTORY the agent-mount source contributes. On extraction the file blocks the directory, so the agent's files were dropped from the zip. `build_archive_work_list` now skips the bare `agent-files` fold marker, the same entry the frontend display already filters (`isAgentFilesFold`). The real content ships from the agent-mount source under `agent-files/`. Added a unit test. Fixes #5482
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughArchive generation now filters the degraded session ChangesArchive namespace handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 2ffc47d5-da40-47d3-8b1c-0b958a0b9a5a
📒 Files selected for processing (2)
api/oss/src/core/mounts/service.pyapi/oss/tests/pytest/unit/test_mounts_file_ops.py
Railway Preview Environment
|
"Download all" merges several mounts into ONE zip (cwd at the root, the agent mount under `agent-files/`). A zip carries no directory entries — `a/b` implies the directory `a` — so a FILE member named `a` blocks it and everything under `a/` is lost on extraction. An object store holds `a` and `a/b` side by side happily, so the merged namespace can contain a pair a zip cannot represent. That is the shape of #5482: geesefs degrades the runner's `agent-files` symlink into a plain object in the cwd store, which archived as a file shadowed the `agent-files/` directory the folded agent mount contributes. `build_archive_work_list` now runs the merged list through `_resolve_zip_namespace`: a member shadowed by a directory is dropped, and a duplicate path keeps the first source. This fixes the reported bug by the invariant rather than by name, whatever the degraded object's size, and guards the whole collision class. The degraded link is also skipped up front, scoped to the cwd mount root — the one path the runner reserves (it unlinks whatever else sits there on attach), so a real `agent-files` file anywhere else, including at the agent mount's own root, still ships. Without that, an empty agent mount would leave the marker in the zip as a phantom file the drive itself hides. Fixes #5482
Context
"Download all" in the Files drawer produced a zip missing the
agent-filescontent (#5482).The archive merges several mounts into ONE zip: the session cwd at the root, and the artifact's agent mount folded in under
agent-files/. A zip carries no directory entries — a membera/bimplies the directorya— so a member that is a FILE namedablocks that directory and everything undera/is lost on extraction. An object store holdsaanda/bside by side happily, so the merged namespace can contain a pair a zip cannot represent.That is the shape of this bug. The runner symlinks the agent mount into the cwd as
agent-files/; geesefs degrades that symlink to a plain object namedagent-filesin the cwd store ("geesefs silently degrades symlinks to empty files across remounts"). Archived as a file, it shadowed theagent-files/directory the agent-mount source contributes, and the agent's files never landed.Changes
build_archive_work_listruns the merged work list through a new_resolve_zip_namespace: a member shadowed by a directory is dropped, and a duplicate path keeps the first source. This fixes the bug by the invariant rather than by name — whatever the degraded object is called and whatever its size — and closes the whole collision class, which is reachable across sources for any pair of mounts.agent-filesfile anywhere else, including at the agent mount's own root (presented asagent-files/agent-files), still ships. Without this, an empty agent mount would leave the marker in the zip as a phantom file the drive itself hides.Before (zip entries):
agent-files(degraded object),agent-files/plan.md, … → a file-vs-directory collision.After:
agent-files/plan.md, … — the shadowing member is dropped.Tests
TestArchiveZipNamespace, against the in-memory fake store, models the real two-source shape (cwd mount + folded agent mount) rather than one synthetic mount:agent-filesis not a reserved name outside the cwd root (docs/agent-filesand the agent mount's ownagent-filesboth ship);reportvsreport/q1.csv);Each rule is independently covered: disabling either one fails only its own tests. Full
apiunit suite green (1475 passed).ruff format+ruff checkclean.What to QA
agent-files/folder and its files are present.agent-filesentry.Fixes #5482