Skip to content

feat(spawn): add worker git worktree isolation#1250

Draft
ymote wants to merge 2 commits into
mainfrom
feat/spawn-worktree-isolation-294
Draft

feat(spawn): add worker git worktree isolation#1250
ymote wants to merge 2 commits into
mainfrom
feat/spawn-worktree-isolation-294

Conversation

@ymote

@ymote ymote commented May 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • refresh feat(spawn): git worktree isolation per sub-agent #294 closure branch onto current origin/main f6936c452389c5172496ee0c3e13393956086d92
  • add isolation: "worktree" to builtin spawn calls, allocating each worker under .octos/work/<agent_id> on a fresh octos/worker/<agent_id> branch
  • rebind child tool registries, task CWD, plugin work dirs, and inherited session scopes to the worker worktree while preserving parent scope policy
  • write worker worktree status tombstones and teach octos clean to remove orphaned .octos/work/* directories
  • keep current-main turn-ledger behavior while applying the spawn worktree isolation changes

Closes #294

Current-main refresh

  • Base: f6936c452389c5172496ee0c3e13393956086d92.
  • Head: 8439df924fd6845f68ff165d5509d26ef38a0c99.
  • Isolated checkout: /Users/yuechen/home/octos/target/octos-1250-fresh.epPHQW/octos.
  • Environment: Darwin arm64; rustc 1.95.0; cargo 1.95.0.
  • Refresh conflict resolved only in crates/octos-agent/src/agent/loop_runner.rs, preserving current-main turn-ledger recording and applying the worktree isolation slice.
  • Final refreshed diff is limited to crates/octos-agent/src/tools/spawn.rs, crates/octos-cli/src/commands/clean.rs, and crates/octos-core/src/session_scope.rs.

Validation

  • git status --short --branch showed a clean isolated checkout at push time.
  • git ls-files --others --exclude-standard was empty at push time.
  • git diff --check origin/main...HEAD passed.
  • cargo fmt --all -- --check passed.
  • typos crates/octos-agent/src/tools/spawn.rs crates/octos-cli/src/commands/clean.rs crates/octos-core/src/session_scope.rs passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo test -p octos-core with_workspace -- --nocapture passed: 2 tests.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo test -p octos-agent worker_worktree_slug_validation -- --nocapture passed: 1 matching test.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-fegal-agent-worktree-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo test -p octos-agent worktree_isolation_runs_concurrent_writers -- --nocapture passed: 1 matching test.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-cli-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo test -p octos-cli clean_collects_orphaned_worker_worktrees_only -- --nocapture passed: 1 matching test.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo check -p octos-agent --all-targets passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo check -p octos-cli --all-targets passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo clippy -p octos-agent --lib --tests --no-deps -- -D warnings passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo clippy -p octos-cli --lib --no-deps -- -D warnings passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-f693-target CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 cargo clippy --workspace --all-targets -- -D warnings passed.

CI / merge status

  • GitHub CI is green on refreshed head 8439df924fd6845f68ff165d5509d26ef38a0c99.
  • Merge is branch-protection blocked by required review: reviewDecision=REVIEW_REQUIRED.

@ymote ymote requested a review from bobdingAI May 28, 2026 11:35
@ymote

ymote commented May 30, 2026

Copy link
Copy Markdown
Contributor Author

Current-main validation refresh for #294 / PR #1250:

  • Base tested: origin/main 4b6d7218b14e91ece68ecde1ca10216975baea58
  • PR head: 4a38893120d1be0a972091bb5b6d439b392aa131
  • Local merge rehearsal: 3383043f80238ba69efb3d8ab5de7c64baf0cd8c
  • Isolated checkout: /private/tmp/octos-1250-refresh-HxWQx9/octos
  • Environment: rustc 1.95.0 (59807616e 2026-04-14), cargo 1.95.0 (f2d3ce0bd 2026-03-21), Darwin 25.5.0 arm64
  • Current-main rehearsal diff is limited to:
    • crates/octos-agent/src/tools/spawn.rs
    • crates/octos-cli/src/commands/clean.rs
    • crates/octos-core/src/session_scope.rs
  • No generated/untracked repo artifacts: git ls-files --others --exclude-standard was empty.

Commands/results:

  • git diff --check origin/main...HEAD passed.
  • rustfmt --edition 2024 --check crates/octos-agent/src/tools/spawn.rs crates/octos-cli/src/commands/clean.rs crates/octos-core/src/session_scope.rs passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-core-target CARGO_INCREMENTAL=0 cargo test -p octos-core with_workspace -- --nocapture passed: 2/2 selected tests.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-agent-slug-target CARGO_INCREMENTAL=0 cargo test -p octos-agent worker_worktree_slug_validation -- --nocapture passed: 1 selected test plus filtered integration targets.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-agent-worktree-target CARGO_INCREMENTAL=0 cargo test -p octos-agent worktree_isolation_runs_concurrent_writers -- --nocapture passed: 1 selected test plus filtered integration targets.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-cli-clean-target CARGO_INCREMENTAL=0 cargo test -p octos-cli clean_collects_orphaned_worker_worktrees_only -- --nocapture passed: 1 selected test plus filtered integration targets.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-agent-check-target CARGO_INCREMENTAL=0 cargo check -p octos-agent --all-targets passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-cli-check-target CARGO_INCREMENTAL=0 cargo check -p octos-cli --all-targets passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-cli-clippy-target CARGO_INCREMENTAL=0 cargo clippy -p octos-cli --lib --no-deps -- -D warnings passed.
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-agent-clippy-target CARGO_INCREMENTAL=0 cargo clippy -p octos-agent --lib --tests --no-deps -- -D warnings failed on unrelated current-main octos-agent lint debt outside this PR diff: crates/octos-agent/src/agent/execution.rs clippy::doc_overindented_list_items and crates/octos-agent/src/agent/streaming.rs clippy::assertions_on_constants.

Acceptance mapping:

  • Slug traversal validation is covered by worker_worktree_slug_validation_rejects_traversal.
  • Concurrent worker isolation is covered by worktree_isolation_runs_concurrent_writers_on_separate_branches.
  • Worker workspace/session-scope policy is covered by the selected octos-core with_workspace tests.
  • octos clean orphan handling is covered by clean_collects_orphaned_worker_worktrees_only.

Result: #294 acceptance still looks satisfied by this PR on a clean current-main merge rehearsal. Remaining gates are branch protection review (mergeable=MERGEABLE, mergeStateStatus=BLOCKED, reviewDecision=REVIEW_REQUIRED) plus the unrelated current-main octos-agent clippy debt if strict agent clippy is rerun before that debt lands.

@ymote ymote force-pushed the feat/spawn-worktree-isolation-294 branch from 4a38893 to 0925e19 Compare May 30, 2026 18:28
@ymote

ymote commented May 30, 2026

Copy link
Copy Markdown
Contributor Author

Current-main validation refresh for #294 / PR #1250:

Commit / PR:

  • PR: feat(spawn): add worker git worktree isolation #1250 (Closes #294)
  • Previous head: 4a38893120d1be0a972091bb5b6d439b392aa131
  • Refreshed head: 0925e19b4c9802a15e98549a3508fe56280bdcdf
  • Base: origin/main 4b6d7218b14e91ece68ecde1ca10216975baea58
  • Branch shape: single linear current-main commit.

Environment:

  • Isolated ignored clone: /Users/yuechen/home/octos/target/octos-1250-refresh-current-8Rt6fn/octos
  • rustc 1.95.0 (59807616e 2026-04-14)
  • cargo 1.95.0 (f2d3ce0bd 2026-03-21)
  • Darwin 25.5.0 arm64

Commands / result:

  • cargo fmt --all -- --check - pass
  • git diff --check origin/main...HEAD - pass
  • git ls-files --others --exclude-standard - empty
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-target CARGO_INCREMENTAL=0 cargo test -p octos-core with_workspace -- --nocapture - pass, 2/2
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-target CARGO_INCREMENTAL=0 cargo test -p octos-agent worker_worktree_slug_validation -- --nocapture - pass, 1/1
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-agent-worktree-target CARGO_INCREMENTAL=0 cargo test -p octos-agent worktree_isolation_runs_concurrent_writers -- --nocapture - pass, 1/1
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-cli-target CARGO_INCREMENTAL=0 cargo test -p octos-cli clean_collects_orphaned_worker_worktrees_only -- --nocapture - pass, 1/1
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-target CARGO_INCREMENTAL=0 cargo check -p octos-agent --all-targets - pass
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-target CARGO_INCREMENTAL=0 cargo check -p octos-cli --all-targets - pass
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-target CARGO_INCREMENTAL=0 cargo clippy -p octos-agent --lib --tests --no-deps -- -D warnings - pass
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-target CARGO_INCREMENTAL=0 cargo clippy -p octos-cli --lib --no-deps -- -D warnings - pass
  • CARGO_TARGET_DIR=/private/tmp/octos-1250-final-target CARGO_INCREMENTAL=0 cargo clippy --workspace --all-targets -- -D warnings - pass

Acceptance coverage:

  • Slug traversal validation: worker_worktree_slug_validation.
  • Concurrent worker worktree isolation: worktree_isolation_runs_concurrent_writers.
  • Workspace/session-scope policy: with_workspace.
  • octos clean orphan handling: clean_collects_orphaned_worker_worktrees_only.

No generated artifacts were present in the isolated checkout. Remaining gap before closure is branch protection review/merge.

@ymote

ymote commented May 30, 2026

Copy link
Copy Markdown
Contributor Author

Final CI refresh for #294 closure PR after the current-main push:

  • Base: 4b6d7218b14e91ece68ecde1ca10216975baea58
  • Head: 0925e19b4c9802a15e98549a3508fe56280bdcdf
  • GitHub CI: all reported required/default lanes are green: check, check-matrix, dashboard, swarm-app, test-octos-agent (lib), test-octos-agent (integration), test-octos-cli, typos, and blocked-author email. Platform/package lanes that are normally conditional were skipped.
  • Local validation from the earlier refresh comment still applies: focused feat(spawn): git worktree isolation per sub-agent #294 tests, cargo check for octos-agent/octos-cli, strict targeted clippy, workspace clippy, rustfmt, diff check, and no generated repo artifacts.

Remaining blocker: normal merge is still blocked only by branch protection requiring review (MERGEABLE / BLOCKED / REVIEW_REQUIRED). No admin bypass used.

@ymote ymote force-pushed the feat/spawn-worktree-isolation-294 branch from 0925e19 to 8439df9 Compare June 2, 2026 16:21
ymote and others added 2 commits June 21, 2026 01:05
Resolves the first two codex-gate P1s on the worktree-isolation path; a third
(validate-worktree-path-before-git-creates-it) remains and needs restructuring,
so this PR is NOT yet mergeable.

- session_scope::with_workspace: reject `..` and require the workspace to be
  under root by CANONICAL form (canonicalize_lossy walks ancestors), closing the
  lexical-only escape + the missing-symlinked-leaf hole.
- spawn: only rebind the session scope for Worktree isolation; shared spawns keep
  the parent scope (default spawns were failing in scoped gateway sessions).

Tests: with_workspace_rejects_{parent_dir,symlinked_workspace}_escape.
@ymote ymote force-pushed the feat/spawn-worktree-isolation-294 branch from 8439df9 to 76d6ff6 Compare June 20, 2026 17:45
@ymote ymote marked this pull request as draft June 20, 2026 17:45
@ymote

ymote commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

Deferred for rework — converted to draft. During the backlog landing sweep, the codex pre-merge gate found this worktree-isolation path to be security-sensitive with layered issues across 3 review rounds. I fixed the first two P1s + one P2 (pushed 76d6ff6f), but a 3rd P1 needs restructuring, so this isn't mergeable yet.

Fixed (in 76d6ff6, tested)

  • [P1] scope escapeSessionScope::with_workspace accepted a workspace that lexically started with root but canonically escaped (symlinked component / ..). Now rejects .. and requires the workspace under root by canonical form via canonicalize_lossy (ancestor-walking, so a missing symlinked leaf is also caught). Tests: with_workspace_rejects_{parent_dir,symlinked_workspace}_escape.
  • [P1] default shared spawns broke — the scope was rebound (with_workspace) for every spawn; in gateway/session-actor wiring the spawn cwd is outside the per-profile scope root, so default (shared) spawns failed. Now only worktree isolation rebinds the scope; shared keeps the parent scope.
  • [P2] missing-leaf symlink hole — folded into the canonical fix above (uses the ancestor-walking canonicalize_lossy).

Remaining before merge

  • [P1] validate-before-createallocate_worker_worktree runs git worktree add (writing the checkout to disk, possibly outside the scope root) before the scope validates the path. Validate the intended worktree path against the session scope before invoking git. This needs allocate_worker_worktree to take the scope (restructuring).
  • [P2] worktree placement for subdir sessionsrev-parse --show-toplevel returns the ancestor repo root, so .octos/work lands outside the scope root when launched from a repo subdir. Base the work root on the scope root.
  • [P2] concurrent slug collision — if another allocator wins the slug after the exists-check, git worktree add fails instead of trying the next suffix; retry on collision.

The first two P1 fixes + the P2 are a sound foundation; the rework should add validate-before-create + scope-rooted placement on top. Build/test/clippy are green on 76d6ff6f (the remaining items are correctness/security gaps, not compile failures).

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.

feat(spawn): git worktree isolation per sub-agent

1 participant