Add configurable repo/worktree storage root with re-clone flow#280
Conversation
Root cause of wrong-remote pushes: - Workers used 'git fetch origin pull/<N>/head:pr-<N>' which creates a branch with NO tracking info. Subsequent 'git push' defaulted to origin, silently pushing to PureWeen/PolyPilot even for fork PRs. - Workers also used 'git rebase + --force-with-lease' which is unnecessary when using merge. Fix: - .squad/routing.md: updated Fix Process to use 'gh pr checkout <N>' (sets correct tracking) and 'git merge origin/main' (no force push needed) - .squad/decisions.md: explicit rules against force push and manual fetch - push-to-pr.sh: script that derives correct remote from gh pr view metadata and pushes without --force, with pre-push safety checks Verified: 'gh pr checkout' correctly sets tracking to fork remote for PR #280 (vitek-karas) and to origin for same-repo PRs like #247 (PureWeen). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t + VsCodeVariant Editor - Keep both ConnectionSettings.RepositoryStorageRoot (PR #280) and Editor (main) - Keep both NormalizeRepositoryStorageRoot (PR #280) and NormalizeEnumFields (main) - Merge RepoManager: instance-based ReposDir/WorktreesDir (reads from settings) with SetBaseDirForTesting static method (for test isolation from main) - Keep Load() BackfillWorktreeClonePaths AND _loadedSuccessfully = true - Fix duplicate else-if and repo variable scope issue in RemoveWorktreeAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
f94d528 to
79a2981
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
79a2981 to
5c35b15
Compare
Consolidate infrastructure/tooling settings under the Developer group: - Move CLI Source from its own 'Copilot CLI' group into Developer - Move Repository Storage from Connection group into Developer - Remove the now-empty Copilot CLI group - Developer group is now always visible (not gated on GitAutoUpdate) - Update search keywords for the reorganized groups Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…polypilot-clone-root-7299
## Problem PR review workers were pushing to the wrong remote (e.g., pushing to `origin/PureWeen` when the PR comes from a fork like `vitek-karas`), and using `--force-with-lease` after rebasing unnecessarily. ### Root Cause (verified by testing) Workers were using manual checkout: ```bash git fetch origin pull/<N>/head:pr-<N> git checkout pr-<N> ``` This creates a branch with **no tracking info** (`Remote: NONE`, `Merge: NONE`). When the worker then runs `git push` or `git push origin`, git defaults to `origin` (PureWeen/PolyPilot) — even if the PR came from a fork. In contrast, `gh pr checkout <N>` correctly sets up tracking: - Same-repo PR #247: `Remote: origin`, `Merge: refs/heads/copilot/build-notification-and-timers` ✅ - Fork PR #280: `Remote: vitek-karas`, `Merge: refs/heads/Add-a-way-to-specify-polypilot-clone-root-7299` ✅ The second problem was `git rebase origin/main` + `--force-with-lease`, which requires force pushing. Using `git merge origin/main` adds a merge commit instead — no force push needed. ## Changes ### `push-to-pr.sh` A shell script that: 1. Reads PR metadata via `gh pr view` to find the correct owner and branch 2. Maps the owner to the correct git remote 3. Pushes to that remote **without** `--force` 4. Verifies the push landed by comparing local and remote HEADs 5. Refuses to push if current branch doesn't match the PR branch (guards against wrong-branch pushes) ### `.squad/routing.md` Updated Fix Process replacing rebase+force-push with merge+safe-push, with clear explanation of why `gh pr checkout` is required. ### `.squad/decisions.md` Explicit shared rules: - Never force push - Always use `gh pr checkout` (not manual fetch) - Always merge (not rebase) - Always verify push target before pushing - Use `push-to-pr.sh` for all PR pushes ### `.squad/team.md` Team definition file (required for squad directory to be recognized by PolyPilot's squad discovery). --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…erPicker guard - Developer nav button now shows when GitAutoUpdate.IsAvailable OR PlatformHelper.IsDesktop - BrowseRepositoryStorageRoot() wrapped in #if MACCATALYST || WINDOWS for GTK compat Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…polypilot-clone-root-7299
efba135 to
10d7af4
Compare
…polypilot-clone-root-7299
- Add spacing between input and action buttons (margin-top on actions) - Fix Use Default button to reliably clear input (use empty string) - Add GetDefaultStorageRoot() to show true default path in placeholder - Style placeholder text as italic with reduced opacity for clarity - Add margin-top to settings-field for consistent section spacing - Change Use Default button from red (stop-btn) to green (start-btn) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
I fixed some UI bugs - and manually tested it - it works well for me. |
…polypilot-clone-root-7299
…lot-clone-root-7299' into Add-a-way-to-specify-polypilot-clone-root-7299
PR #280 Re-Review — "Add configurable repo/worktree storage root with re-clone flow"CI Status: 5-Model Consensus Review (claude-opus-4.6 ×2, claude-sonnet-4.6, gemini-3-pro-preview, gpt-5.3-codex)
🔴 CRITICAL —
|
…polypilot-clone-root-7299
- Cache GetStorageRootDir() result to avoid ConnectionSettings.Load() disk I/O on every ReposDir/WorktreesDir access (was ~10 calls per operation) - Add InvalidateStorageRoot() for settings changes in Settings.razor - Add _stateLock protection around BareClonePath mutations and Save() in EnsureRepoCloneInCurrentRootAsync - Wrap BackfillWorktreeClonePaths iteration with _stateLock - Clear _storageRoot in SetBaseDirForTesting for test isolation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🔍 PR #280 Re-Review — Post-Fix Assessment"Add configurable repo/worktree storage root with re-clone flow"Fix commit: Previous Findings Status
New Findings EvaluationThe re-review raised 4 new concerns. All were investigated and resolved:
Test Coverage
CI StatusRecommendation: ✅ ApproveBoth critical findings from the initial review are resolved:
Remaining items (2, 4, 5) are deliberate design tradeoffs with acceptable risk profiles. No new blocking issues found. |
## Problem PR review workers were pushing to the wrong remote (e.g., pushing to `origin/PureWeen` when the PR comes from a fork like `vitek-karas`), and using `--force-with-lease` after rebasing unnecessarily. ### Root Cause (verified by testing) Workers were using manual checkout: ```bash git fetch origin pull/<N>/head:pr-<N> git checkout pr-<N> ``` This creates a branch with **no tracking info** (`Remote: NONE`, `Merge: NONE`). When the worker then runs `git push` or `git push origin`, git defaults to `origin` (PureWeen/PolyPilot) — even if the PR came from a fork. In contrast, `gh pr checkout <N>` correctly sets up tracking: - Same-repo PR PureWeen#247: `Remote: origin`, `Merge: refs/heads/copilot/build-notification-and-timers` ✅ - Fork PR PureWeen#280: `Remote: vitek-karas`, `Merge: refs/heads/Add-a-way-to-specify-polypilot-clone-root-7299` ✅ The second problem was `git rebase origin/main` + `--force-with-lease`, which requires force pushing. Using `git merge origin/main` adds a merge commit instead — no force push needed. ## Changes ### `push-to-pr.sh` A shell script that: 1. Reads PR metadata via `gh pr view` to find the correct owner and branch 2. Maps the owner to the correct git remote 3. Pushes to that remote **without** `--force` 4. Verifies the push landed by comparing local and remote HEADs 5. Refuses to push if current branch doesn't match the PR branch (guards against wrong-branch pushes) ### `.squad/routing.md` Updated Fix Process replacing rebase+force-push with merge+safe-push, with clear explanation of why `gh pr checkout` is required. ### `.squad/decisions.md` Explicit shared rules: - Never force push - Always use `gh pr checkout` (not manual fetch) - Always merge (not rebase) - Always verify push target before pushing - Use `push-to-pr.sh` for all PR pushes ### `.squad/team.md` Team definition file (required for squad directory to be recognized by PolyPilot's squad discovery). --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…een#280) ## Summary - add `ConnectionSettings.RepositoryStorageRoot` and normalize/validate it - update `RepoManager` to resolve clone/worktree roots from the setting while keeping `repos.json` under `~/.polypilot` - preserve existing worktree cleanup behavior by persisting `WorktreeInfo.BareClonePath` - add bulk `RecloneAllRepositoriesToCurrentRootAsync` and lazy migration for existing repos on new worktree/fetch/branch operations - add Settings UI to pick/reset storage root and trigger "Re-clone all registered repos in new root" - add unit tests for settings + repo storage behavior ## Validation - `dotnet build -f net10.0-maccatalyst /p:CopilotSkipCliDownload=true` - `dotnet test /p:CopilotSkipCliDownload=true --filter "FullyQualifiedName~ConnectionSettingsTests"` - `dotnet test /p:CopilotSkipCliDownload=true --filter "FullyQualifiedName~RepoManagerStorageTests"` - `dotnet test /p:CopilotSkipCliDownload=true --filter "FullyQualifiedName!~CliPathResolutionTests"` --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Shane Neuville (HE/HIM) <shneuvil@microsoft.com>
Summary
ConnectionSettings.RepositoryStorageRootand normalize/validate itRepoManagerto resolve clone/worktree roots from the setting while keepingrepos.jsonunder~/.polypilotWorktreeInfo.BareClonePathRecloneAllRepositoriesToCurrentRootAsyncand lazy migration for existing repos on new worktree/fetch/branch operationsValidation
dotnet build -f net10.0-maccatalyst /p:CopilotSkipCliDownload=truedotnet test /p:CopilotSkipCliDownload=true --filter "FullyQualifiedName~ConnectionSettingsTests"dotnet test /p:CopilotSkipCliDownload=true --filter "FullyQualifiedName~RepoManagerStorageTests"dotnet test /p:CopilotSkipCliDownload=true --filter "FullyQualifiedName!~CliPathResolutionTests"