diff --git a/MISSION.md b/MISSION.md index fc3a28a2..4b4e5345 100644 --- a/MISSION.md +++ b/MISSION.md @@ -56,11 +56,12 @@ You are working on GitHub issue `{{ issue.identifier }}`: {{ issue.title }} You are working in a git worktree on branch `mission/{{ issue.identifier | downcase }}`. 1. **Read project guidelines** — check for AGENTS.md, CLAUDE.md, or similar files first. -2. **Post your workpad** — use your mission tools to post a plan on the issue before writing code. -3. **Understand the codebase** — explore the relevant code before making changes. -4. **Implement** — make focused, minimal changes. Run tests and linters. -5. **Commit** — keep commits clean and atomic. Update your workpad as you go. -6. **Create a PR** targeting `main` when complete. Attach it to the issue. +2. **Sync with latest `main`** — before writing code, fetch the latest changes and rebase your worktree branch onto `origin/main` (or the configured base branch). Prefer `git pull --rebase` / `git fetch` + `git rebase`. Do not create merge commits. +3. **Post your workpad** — use your mission tools to post a plan on the issue before writing code. +4. **Understand the codebase** — explore the relevant code before making changes. +5. **Implement** — make focused, minimal changes. Run tests and linters. +6. **Commit** — keep commits clean and atomic. Update your workpad as you go. +7. **Create a PR** targeting `main` when complete. Attach it to the issue. ## Rules @@ -69,4 +70,6 @@ You are working in a git worktree on branch `mission/{{ issue.identifier | downc - Do not expand scope. File follow-up issues for anything tangential. - Keep the workpad updated — it is the primary way humans track your progress. - Use gitmoji in commit messages and PR titles (e.g. ✨, 🐛, ♻️, 🔧). +- Prefer rebases over merges when syncing with the base branch. +- **NEVER create merge commits.** Keep mission branches linear. - **NEVER merge PRs.** Create the PR, verify CI passes, and address any review feedback — but leave merging to a human. \ No newline at end of file diff --git a/orbitdock-server/crates/connector-claude/src/lib.rs b/orbitdock-server/crates/connector-claude/src/lib.rs index 03ba6ed4..70c82e82 100644 --- a/orbitdock-server/crates/connector-claude/src/lib.rs +++ b/orbitdock-server/crates/connector-claude/src/lib.rs @@ -589,9 +589,25 @@ impl ClaudeConnector { if allow_bypass_permissions { args.push("--allow-dangerously-skip-permissions"); } - let allowed_joined = allowed_tools.join(","); + + // When permission_mode is "acceptEdits", ensure edit tools are explicitly + // in the allowedTools list. The --permission-prompt-tool stdio flag routes + // ALL permission decisions through the control protocol, so the CLI's + // internal --permission-mode auto-accept logic may not fire. Passing them + // as --allowedTools guarantees the CLI pre-approves them. + let mut effective_allowed: Vec = allowed_tools.to_vec(); + if permission_mode == Some("acceptEdits") { + for tool in ["Edit", "Write", "NotebookEdit"] { + let tool_str = tool.to_string(); + if !effective_allowed.contains(&tool_str) { + effective_allowed.push(tool_str); + } + } + } + + let allowed_joined = effective_allowed.join(","); let disallowed_joined = disallowed_tools.join(","); - if !allowed_tools.is_empty() { + if !effective_allowed.is_empty() { args.extend(["--allowedTools", &allowed_joined]); } if !disallowed_tools.is_empty() { diff --git a/orbitdock-server/crates/server/src/domain/git/repo.rs b/orbitdock-server/crates/server/src/domain/git/repo.rs index 09c88d90..5197b388 100644 --- a/orbitdock-server/crates/server/src/domain/git/repo.rs +++ b/orbitdock-server/crates/server/src/domain/git/repo.rs @@ -257,6 +257,11 @@ pub async fn delete_remote_branch(repo_path: &str, branch: &str) -> Result<(), S run_git_checked(&["push", "origin", "--delete", branch], repo_path).await } +/// Fetch the latest refs from `origin`. +pub async fn fetch_origin(repo_path: &str) -> Result<(), String> { + run_git_checked(&["fetch", "origin"], repo_path).await +} + /// Initialize a new git repository at the given path. pub async fn git_init(path: &str) -> Result<(), String> { run_git_checked(&["init"], path).await diff --git a/orbitdock-server/crates/server/src/domain/instructions.rs b/orbitdock-server/crates/server/src/domain/instructions.rs index 603275bf..3f504d70 100644 --- a/orbitdock-server/crates/server/src/domain/instructions.rs +++ b/orbitdock-server/crates/server/src/domain/instructions.rs @@ -123,6 +123,17 @@ multiple comments. One living document. - Use `mission_report_blocked` only for true blockers (missing auth, secrets, permissions) - Create a PR when complete, then use `mission_link_pr` to attach it to the issue - **NEVER merge PRs.** After opening the PR, check CI status and address review feedback — but leave merging to a human. -- If you discover out-of-scope work, use `mission_create_followup` instead of expanding scope"# +- If you discover out-of-scope work, use `mission_create_followup` instead of expanding scope + +## Git Workflow + +Your worktree is automatically based on the latest remote base branch at dispatch time. +Keep your branch linear — **never create merge commits**. + +- Sync with base branch: `git fetch origin && git rebase origin/main` (or the configured base branch) +- Prefer `git pull --rebase` over `git pull` +- If you need to stay current mid-work: `git fetch origin && git rebase origin/main` +- **NEVER** run `git merge` — always rebase +- Keep commits clean and atomic"# .to_string() } diff --git a/orbitdock-server/crates/server/src/domain/mission_control/template.rs b/orbitdock-server/crates/server/src/domain/mission_control/template.rs index a91962b4..c9ed0852 100644 --- a/orbitdock-server/crates/server/src/domain/mission_control/template.rs +++ b/orbitdock-server/crates/server/src/domain/mission_control/template.rs @@ -82,11 +82,12 @@ You are working on {issue_label} `{{{{ issue.identifier }}}}`: {{{{ issue.title You are working in a git worktree on branch `mission/{{{{ issue.identifier | downcase }}}}`. 1. **Read project guidelines** — check for AGENTS.md, CLAUDE.md, or similar files first. -2. **Post your workpad** — use your mission tools to post a plan on the issue before writing code. -3. **Understand the codebase** — explore the relevant code before making changes. -4. **Implement** — make focused, minimal changes. Run tests and linters. -5. **Commit** — keep commits clean and atomic. Update your workpad as you go. -6. **Create a PR** targeting `main` when complete. Attach it to the issue. +2. **Sync with latest `main`** — before writing code, fetch the latest changes and rebase your worktree branch onto `origin/main` (or the configured base branch). Prefer `git pull --rebase` / `git fetch` + `git rebase`. Do not create merge commits. +3. **Post your workpad** — use your mission tools to post a plan on the issue before writing code. +4. **Understand the codebase** — explore the relevant code before making changes. +5. **Implement** — make focused, minimal changes. Run tests and linters. +6. **Commit** — keep commits clean and atomic. Update your workpad as you go. +7. **Create a PR** targeting `main` when complete. Attach it to the issue. ## Rules @@ -94,6 +95,9 @@ You are working in a git worktree on branch `mission/{{{{ issue.identifier | dow - Stop early only for true blockers (missing auth, permissions, secrets). - Do not expand scope. File follow-up issues for anything tangential. - Keep the workpad updated — it is the primary way humans track your progress. +- Prefer rebases over merges when syncing with the base branch. +- **NEVER create merge commits.** Keep mission branches linear. +- **NEVER merge PRs.** Create the PR, verify CI passes, and address any review feedback — but leave merging to a human. "# ) } diff --git a/orbitdock-server/crates/server/src/runtime/mission_dispatch.rs b/orbitdock-server/crates/server/src/runtime/mission_dispatch.rs index 798bdb3c..3e7989a2 100644 --- a/orbitdock-server/crates/server/src/runtime/mission_dispatch.rs +++ b/orbitdock-server/crates/server/src/runtime/mission_dispatch.rs @@ -89,12 +89,27 @@ pub async fn dispatch_issue( ); } + // Fetch latest refs so the worktree starts from the current remote HEAD + if let Err(err) = crate::domain::git::repo::fetch_origin(&ctx.repo_root).await { + warn!( + component = "mission_control", + event = "dispatch.fetch_failed", + mission_id = %mission_id, + issue_id = %issue.id, + error = %err, + "git fetch origin failed — worktree will use local state" + ); + } + + // Use origin/ so the worktree is based on the freshly-fetched remote ref + let remote_base = format!("origin/{}", ctx.base_branch); + // Create worktree via the runtime helper (also persists the record) let worktree_path = match crate::runtime::worktree_creation::create_tracked_worktree( registry, &ctx.repo_root, &branch_name, - Some(&ctx.base_branch), + Some(&remote_base), orbitdock_protocol::WorktreeOrigin::Agent, ctx.worktree_root_dir.as_deref(), true, // always clean up stale worktrees — if we're dispatching, no active session owns them