Skip to content

docs: design for isolated worktrees on write-capable tasks (#4, proposal 1) - #22

Open
hessabi wants to merge 1 commit into
TheOnlyFusionCube:mainfrom
hessabi:docs/worktree-writes-design
Open

hessabi wants to merge 1 commit into
TheOnlyFusionCube:mainfrom
hessabi:docs/worktree-writes-design

Conversation

@hessabi

@hessabi hessabi commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

This is the short design PR for proposal 1 (isolated worktrees) requested in #4. It adds one file, design/worktree-writes.md, and makes no code changes. It lives under design/ rather than docs/, because docs/ is the Pages site.

What it decides, against the contract in your follow-up

  • Starting tree: snapshot-carry. The worktree starts from a snapshot commit of the caller's working tree, built with a throwaway index, so the caller's checkout, index, refs and stash are never modified. No commits, submodules, sparse checkout and a size cap each fail with guidance.
  • Location, naming and state.
    • Worktrees live outside the repo and outside the tmp fallback, with branches named devin/<suffix>.
    • Job ids are validated, and they are the only input to paths and refs.
    • A per-worktree metadata file survives the 50-job prune.
    • Existing job statuses are unchanged, including cancel_pending.
  • Resume. Devin runs with the worktree as its cwd. There is a new --resume-job, and --resume and --resume-id resolve through worktree metadata.
  • Apply.
    • It previews by default and mutates only with --confirm <deltaId>.
    • Each touched path is classified ok, needs-3way or blocked.
    • It uses binary-safe, all-or-nothing git apply, and never overwrites uncommitted caller edits.
    • The worktree is kept on any failure.
  • Cancel and cleanup. Nothing is deleted automatically. Cleanup is a dry run by default, and discarding unapplied work is explicit and per job.
  • Other paths.
    • Non-git directories refuse with guidance; --in-place still works there.
    • The portable contract for Codex and other agents is flags plus --json with stable error codes.
    • The security notes say plainly that this is not a sandbox, and that no permission or sandbox flag changes.
  • Rollout. Phase 1 is an opt-in --worktree foundation PR; Phase 2 switches the default. Each has a test list.

What it asks you to decide (section 14)

  1. Is snapshot-carry acceptable, or do you prefer fail-on-dirty as the first policy?
  2. Is writing worktrees to a user-level data directory acceptable?
  3. Should there be any persistent, human-only way to flip the default back to in-place? The design says no.
  4. How should gitignored files (node_modules, .env) be handled?
  5. Should apply reuse the portable confirmation contract chosen for proposal 6?

The doc also lists Devin CLI behaviors I couldn't verify from the bundled docs: resume from a worktree cwd, project-root detection with a linked worktree, workspace trust, and sandbox writes under .git/worktrees. They're marked as things to test in Phase 1.

…sionCube#4)

Design only, no code changes. Covers the Proposal 1 contract from the maintainer on TheOnlyFusionCube#4: starting-tree policy, worktree location and naming, job state, resume, /devin:apply, cancel and cleanup, non-git directories, portable CLI behavior, security notes, and phased rollout.

@TheOnlyFusionCube TheOnlyFusionCube left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design review — comments only; not policy sign-off or approval to implement. The phased worktree-first direction, preserving the caller's checkout, no silent non-Git fallback, durable review-before-apply intent, and explicit "not a sandbox" warning fit #4.

Shared blocking decision with #21: apply --confirm establishes patch identity/freshness, not human authorization. An agent with unrestricted shell can preview, obtain the 12-hex ID, and apply by itself. Reuse #21's approval semantics, not its bare hash-token mechanism: a canonical operation digest plus an independent trusted host-mediated human decision, with preview-only fail-closed behavior for noninteractive clients lacking that boundary. Consent must bind job, source/final delta, destination repository/branch, touched paths and current destination HEAD/index/working-tree state. Revalidate immediately before mutation; refuse on drift. TTY and disable-model-invocation are useful UX defenses, not proof of user presence. Treat --confirm as integrity only. Destructive cleanup --discard-unapplied and the lower-isolation --in-place path also need an explicit policy; an agent-supplied flag is not inherently human-only.

Concrete design revisions before implementation:

  1. Dirty-tree privacy (§4). Snapshot-carry automatically adds staged/unstaged and untracked non-ignored content to commits, branches, pinned refs and the shared Git object database; secrets may persist or be accidentally pushed. The unchanged caller checkout does not eliminate that exposure. For Phase 1 I lean toward fail-on-dirty, or opt-in explicitly reviewed snapshot-carry listing what will be persisted and excluding sensitive/untracked content by default. Please make this a maintainer choice. Never silently copy/symlink ignored .env files.
  2. Apply atomicity (§8). git apply --3way can alter the index and leave conflicts/markers, contradicting "never stage" / "all-or-nothing" / "nothing changed on failure." Either defer --3way in Phase 1 with manual recovery guidance, or design/test a transaction and rollback strategy with separate consent for possible conflicts/index changes. Preserve the worktree on failure. Also specify how concurrent checkout edits between --check and apply invalidate authorization.
  3. Durable state (§§5–6/9). Worktree paths are durable, but authoritative /worktrees/*.json can still use os.tmpdir() for non-Claude clients; loss undermines recovery. Put authoritative metadata in durable user-level data or prove complete reconstruction from refs/branches without temporary state. Include permissions and ownership checks.
  4. Promises/tests (§§3/13). The clean-tree test says all refs remain identical, yet devin/* and refs/devin-companion/* are deliberately created. Assert existing refs plus checkout/index/stash are unchanged instead. Preview does not change caller files/index, but it does write patch/metadata and can create Git objects/refs. Test symlink/path races, collisions, binaries, resume invalidating previous approval, staged files and agent self-approval under auto-exec.
  5. Phase gates. Keep Phase 1 opt-in and Phase 2 separately reviewed after verifying linked-worktree root detection, Devin resume, trust and sandbox writes under shared .git/worktrees. Do not weaken permissions or silently fall back to --in-place. Keep portable CLI/JSON contracts for Codex and other clients.

Maintainer decisions requested: (a) reuse #21's genuinely trusted host-mediated approval contract with no-host preview-only fallback; (b) fail-on-dirty vs snapshot-carry in Phase 1; (c) durable user-level worktree and metadata location; (d) no persistent in-place override (my preference); (e) ignored-file handling later and never automatic secret carry; (f) defer --3way until transactional behavior is established. These are recommendations, not final authorization. Please cross-link the agreed contract to #21 and keep implementation separate until settled.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants