feat(cli): add vfs seed for portable dirty-base capture - #6
Merged
Conversation
Capture dirty worktree and local commit state before mounting so pinned sessions retain the sender's merged view across machines. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This was referenced Jul 27, 2026
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.
Description
What
Adds
vfs seed <session-id> --pin <commit>: captures a run session's live git state (dirty and untracked files, deletions, local commits, index) into its portable delta without mounting.vfs run --session <id> --seed-pin <commit>is the atomic startup form.Why
A session created on a dirty checkout only sees that dirty state through overlay base read-through, which does not travel. Without seed, a receiver materializing the packed delta over a pristine checkout at the pin would silently lose the sender's uncommitted work. Capture-by-construction from birth is the design; seed extends it to bases that were already dirty at session start.
How
Seed diffs the base checkout against
--pinand imports through the core bulk-import API (no FUSE/NFS mount):git status --untracked-files=all).HEADand the current branch ref under delta.git/paths; the sender's index bytes come along, preserving staged-vs-unstaged state.session already seeded; a live session fails with the same exit-3 gate as pack.Stack (merged bottom-up 2026-07-28, vfs main @
3b2af42):Related Issue
Part of AC-768
Reviewer Guide
Diff shape: ~80%
cmd/seed.rs, ~10%run/integration (--seed-pinlock choreography), ~10% core overlay/session support.Review depth: Deep on the git-state capture matrix; the correctness question is "which sender states round-trip".
Read order:
crates/vfs-cli/src/cmd/seed.rs— status enumeration, bulk import, whiteout recording, git pack + index capture, staging publishcrates/vfs-cli/src/cmd/run/linux.rs+darwin.rs— exclusive-create-then-downgrade-to-shared lock ordering for--seed-pincrates/vfs-core/src/fs/overlay/mod.rs— whiteout API surface seed relies ondocs/MANUAL.md— the portable-state contract (ignored files excluded, index revalidation semantics)Open for pushback: copying raw index bytes rather than regenerating the index on the receiver. Git revalidates cached stat fields against the pristine checkout at the pin, so stale stats self-heal, but it is the least obvious part of the contract.
Risk & Impact
Seed writes into the session delta, so a capture bug corrupts portable state at birth; the staging-then-publish structure bounds that to "seed failed, retry" rather than a half-seeded live delta. The exclusion of ignored files is deliberate scope (build outputs and caches stay base-local) and is documented as the portable-state boundary.
Verification
Behavior verified. Dirty file, untracked file, deleted-since-pin, staged-vs-unstaged, and local-commit states round-trip to a receiver materialization over a pristine pin checkout; second seed and live-session seed fail with the documented errors (verified @
10507f1).Regression coverage. CLI suite exercises the seed state matrix and the exit-code gates; core tests pin whiteout semantics.
Not tested. Submodule-containing worktrees; out of scope for the MVP contract and rejected by the state enumeration rather than mishandled.
Standard validators. cargo build/test and CLI shell suites clean.