diff --git a/src/ClaudeDo.Localization/locales/de.json b/src/ClaudeDo.Localization/locales/de.json index bd683e49..c2ff182a 100644 --- a/src/ClaudeDo.Localization/locales/de.json +++ b/src/ClaudeDo.Localization/locales/de.json @@ -471,6 +471,9 @@ "folderColorHint": "Färbt den Ordnernamen und seine Führungslinie in der Seitenleiste.", "workingDirectory": "Arbeitsverzeichnis", "workingDirectoryPlaceholder": "(keines)", + "baseBranch": "Basis-Branch", + "baseBranchPlaceholder": "(ausgecheckter Branch)", + "baseBranchHint": "Neue Task-Branches starten hier, und freigegebene Arbeit wird hierhin gemergt, z.B. dev. Leer = der gerade ausgecheckte Branch.", "browse": "Durchsuchen...", "defaultCommitType": "Standard-Commit-Typ", "manualList": "Manuelle Liste (Erinnerungen)", diff --git a/src/ClaudeDo.Localization/locales/en.json b/src/ClaudeDo.Localization/locales/en.json index db1f11e4..5f09e69d 100644 --- a/src/ClaudeDo.Localization/locales/en.json +++ b/src/ClaudeDo.Localization/locales/en.json @@ -471,6 +471,9 @@ "folderColorHint": "Tints the folder name and its guide line in the sidebar.", "workingDirectory": "Working directory", "workingDirectoryPlaceholder": "(none)", + "baseBranch": "Base branch", + "baseBranchPlaceholder": "(checked-out branch)", + "baseBranchHint": "New task branches start here and approved work merges back here, e.g. dev. Leave empty to use whatever branch is checked out.", "browse": "Browse...", "defaultCommitType": "Default commit type", "manualList": "Manual list (reminders)", diff --git a/src/ClaudeDo.Ui/ViewModels/Agent/AgentConfigEditorViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Agent/AgentConfigEditorViewModel.cs index 952ee7c0..208e0ff4 100644 --- a/src/ClaudeDo.Ui/ViewModels/Agent/AgentConfigEditorViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Agent/AgentConfigEditorViewModel.cs @@ -208,13 +208,13 @@ public sealed partial class AgentConfigEditorViewModel : ViewModelBase, IDisposa catch { } } - // verifyCommand, ticketProjectId and powerUseAllowed are List-only fields owned by + // verifyCommand, ticketProjectId, powerUseAllowed and baseBranch are List-only fields owned by // ListSettingsModalViewModel (not this editor, which is also reused for Task scope); the caller // passes them through so the single UpdateListConfig call carries the full desired row instead // of clobbering it. powerUseAllowed stays null-by-default for the same reason ticketProjectId // does: a caller that doesn't own it must not revoke the list's opt-in by omission. public async System.Threading.Tasks.Task SaveAsync( - string? verifyCommand = null, int? ticketProjectId = null, bool? powerUseAllowed = null) + string? verifyCommand = null, int? ticketProjectId = null, bool? powerUseAllowed = null, string? baseBranch = null) { if (TargetId is null) return; var model = string.IsNullOrWhiteSpace(Model) ? null : Model; @@ -227,7 +227,7 @@ public sealed partial class AgentConfigEditorViewModel : ViewModelBase, IDisposa if (_scope == AgentConfigScope.Task) await _worker.UpdateTaskAgentSettingsAsync(new UpdateTaskAgentSettingsDto(TargetId, model, sp, ap, turns, skills, permission)); else - await _worker.UpdateListConfigAsync(new UpdateListConfigDto(TargetId, model, sp, ap, turns, skills, verifyCommand, permission, ticketProjectId, powerUseAllowed)); + await _worker.UpdateListConfigAsync(new UpdateListConfigDto(TargetId, model, sp, ap, turns, skills, verifyCommand, permission, ticketProjectId, powerUseAllowed, baseBranch)); } private List? SelectedSessionSkillNames() diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs index 4e363abc..23154686 100644 --- a/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs @@ -667,7 +667,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable WorktreeBaseCommit = entity.Worktree?.BaseCommit ?? entity.HandlerBaseCommit; WorktreeHeadCommit = entity.Worktree?.HeadCommit ?? entity.HandlerHeadCommit; WorktreeStateLabel = entity.Worktree?.State.ToString(); - BranchLine = entity.Worktree is { } w ? $"{w.BranchName} ← main" : null; + BranchLine = entity.Worktree?.BranchName; var (add, del) = ParseDiffStat(entity.Worktree?.DiffStat); DiffAdditions = add; DiffDeletions = del; @@ -930,7 +930,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable WorktreeBaseCommit = entity.Worktree?.BaseCommit ?? entity.HandlerBaseCommit; WorktreeHeadCommit = entity.Worktree?.HeadCommit ?? entity.HandlerHeadCommit; WorktreeStateLabel = entity.Worktree?.State.ToString(); - BranchLine = entity.Worktree is { } w ? $"{w.BranchName} ← main" : null; + BranchLine = entity.Worktree?.BranchName; if (Task is { } row && entity.Worktree?.DiffStat is { } stat) row.DiffStat = stat; var (add, del) = ParseDiffStat(entity.Worktree?.DiffStat); @@ -1220,7 +1220,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable if (Task == null) return; if (Dialogs == null) return; - var branchName = $"claudedo/{Task.Id.Replace("-", "")}"; + var branchName = BranchLine ?? "the task branch"; var ok = await Dialogs.ConfirmAsync( $"Reset and retry?\nThis discards branch {branchName} (and uncommitted changes), then queues the task to run from the beginning."); if (!ok) return; @@ -1382,7 +1382,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable private async System.Threading.Tasks.Task ResetReviewAsync() { if (Task is null || !_worker.IsConnected || Dialogs is null) return; - var branchName = $"claudedo/{Task.Id.Replace("-", "")}"; + var branchName = BranchLine ?? "the task branch"; var ok = await Dialogs.ConfirmAsync( $"Reset working tree?\nThis discards branch {branchName} (and all changes) and returns the task to Idle."); if (!ok) return; diff --git a/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs index 4db039c6..ce76be52 100644 --- a/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs @@ -59,6 +59,8 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase // harvests new work, longer handoff chain) when this AND the global switch in Settings → // Execution are both on. Off by default — the global switch alone must never change a list's behaviour. [ObservableProperty] private bool _powerUseAllowed; + // Basis neuer Worktrees und Default-Merge-Ziel; leer = ausgecheckter Branch. + [ObservableProperty] private string _baseBranch = ""; // Dropdown hidden entirely when no ticket-system base URL is configured (Settings → Files tab). // Icon key into the UI icon library (IconKeyConverter -> "Icon." StreamGeometry). [ObservableProperty] private string _icon = DefaultIcon; @@ -275,6 +277,7 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase cfg = Agent.LastLoadedListConfig; VerifyCommand = cfg?.VerifyCommand ?? ""; PowerUseAllowed = cfg?.PowerUseAllowed ?? false; + BaseBranch = cfg?.BaseBranch ?? ""; } catch (Exception ex) { @@ -377,7 +380,9 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase await Agent.SaveAsync( string.IsNullOrWhiteSpace(VerifyCommand) ? null : VerifyCommand, ticketProjectId, - PowerUseAllowed); + PowerUseAllowed, + // Always explicit too: "" clears the stored base branch. + BaseBranch.Trim()); Saved = true; CloseAction?.Invoke(); diff --git a/src/ClaudeDo.Ui/Views/Modals/ListSettingsModalView.axaml b/src/ClaudeDo.Ui/Views/Modals/ListSettingsModalView.axaml index 9e5ca8cc..f2959da0 100644 --- a/src/ClaudeDo.Ui/Views/Modals/ListSettingsModalView.axaml +++ b/src/ClaudeDo.Ui/Views/Modals/ListSettingsModalView.axaml @@ -124,6 +124,14 @@ Foreground="{DynamicResource StatusErrorBrush}" FontSize="12" TextWrapping="Wrap"/> + + + + + +