feat(data): per-list base branch, preserved by every config writer
This commit is contained in:
@@ -21,5 +21,6 @@ public class ListConfigEntityConfiguration : IEntityTypeConfiguration<ListConfig
|
||||
builder.Property(c => c.PermissionMode).HasColumnName("permission_mode");
|
||||
builder.Property(c => c.TicketProjectId).HasColumnName("ticket_project_id");
|
||||
builder.Property(c => c.PowerUseAllowed).HasColumnName("power_use_allowed");
|
||||
builder.Property(c => c.BaseBranch).HasColumnName("base_branch");
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ClaudeDo.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddListBaseBranch : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "base_branch",
|
||||
table: "list_config",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "base_branch",
|
||||
table: "list_config");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,6 +268,10 @@ namespace ClaudeDo.Data.Migrations
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("agent_path");
|
||||
|
||||
b.Property<string>("BaseBranch")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("base_branch");
|
||||
|
||||
b.Property<int?>("MaxTurns")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("max_turns");
|
||||
|
||||
@@ -23,6 +23,12 @@ public sealed class ListConfigEntity
|
||||
// false, also opt-in. ⚠️ Gleiche Falle wie TicketProjectId: SetConfigAsync kopiert verbatim.
|
||||
public bool PowerUseAllowed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Basis neuer Worktrees und Default-Merge-/PR-Ziel (z.B. <c>dev</c>). Null = ausgecheckter Branch
|
||||
/// (privat) bzw. Default-Branch des Remotes (Firma). ⚠️ SetConfigAsync kopiert verbatim.
|
||||
/// </summary>
|
||||
public string? BaseBranch { get; set; }
|
||||
|
||||
// Navigation property
|
||||
public ListEntity List { get; set; } = null!;
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ public sealed class ListRepository
|
||||
existing.PermissionMode = config.PermissionMode;
|
||||
existing.TicketProjectId = config.TicketProjectId;
|
||||
existing.PowerUseAllowed = config.PowerUseAllowed;
|
||||
existing.BaseBranch = config.BaseBranch;
|
||||
}
|
||||
await _context.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
@@ -108,11 +108,12 @@ public record UpdateListDto(string Id, string Name, string? WorkingDir, string D
|
||||
// verbatim. Its scale: null = keep stored, <= 0 = clear the link, > 0 = set it.
|
||||
// PowerUseAllowed is nullable for the same reason: null = keep stored, false = revoke the opt-in.
|
||||
// A non-nullable bool here would let any caller that omits it silently revoke PowerUse for the list.
|
||||
public record UpdateListConfigDto(string ListId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null, string? VerifyCommand = null, string? PermissionMode = null, int? TicketProjectId = null, bool? PowerUseAllowed = null);
|
||||
// BaseBranch: null = keep stored, "" = clear, value = set.
|
||||
public record UpdateListConfigDto(string ListId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null, string? VerifyCommand = null, string? PermissionMode = null, int? TicketProjectId = null, bool? PowerUseAllowed = null, string? BaseBranch = null);
|
||||
|
||||
public record UpdateTaskAgentSettingsDto(string TaskId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null, string? PermissionMode = null);
|
||||
|
||||
public record ListConfigDto(string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null, string? VerifyCommand = null, string? PermissionMode = null, int? TicketProjectId = null, bool PowerUseAllowed = false);
|
||||
public record ListConfigDto(string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null, string? VerifyCommand = null, string? PermissionMode = null, int? TicketProjectId = null, bool PowerUseAllowed = false, string? BaseBranch = null);
|
||||
|
||||
public record SeedResultDto(int Copied, int Skipped);
|
||||
|
||||
|
||||
+8
-5
@@ -10,7 +10,7 @@ using ModelContextProtocol.Server;
|
||||
namespace ClaudeDo.Worker.External;
|
||||
|
||||
public sealed record TaskConfigDto(string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns);
|
||||
public sealed record ListConfigDto(string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns, string? VerifyCommand);
|
||||
public sealed record ListConfigDto(string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns, string? VerifyCommand, string? BaseBranch = null);
|
||||
public sealed record TaskConfigResult(bool Found, TaskConfigDto? Config);
|
||||
public sealed record ListConfigResult(bool Found, ListConfigDto? Config);
|
||||
public sealed record SetListConfigResult(bool Ok, string ListId, ListConfigDto? Config);
|
||||
@@ -55,7 +55,7 @@ public sealed class ConfigMcpTools
|
||||
var cfg = await _lists.GetConfigAsync(listId, cancellationToken);
|
||||
return cfg is null
|
||||
? new ListConfigResult(false, null)
|
||||
: new ListConfigResult(true, new ListConfigDto(cfg.Model, cfg.SystemPrompt, cfg.AgentPath, cfg.MaxTurns, cfg.VerifyCommand));
|
||||
: new ListConfigResult(true, new ListConfigDto(cfg.Model, cfg.SystemPrompt, cfg.AgentPath, cfg.MaxTurns, cfg.VerifyCommand, cfg.BaseBranch));
|
||||
}
|
||||
|
||||
// clearFields (not a per-field sentinel like UpdateList's "" for workingDir) because maxTurns is an
|
||||
@@ -81,7 +81,7 @@ public sealed class ConfigMcpTools
|
||||
"in this list that don't override them (verify command is list-only; tasks cannot override it). Only " +
|
||||
"the fields you pass are changed; omitted fields keep their current value. To clear a field instead, " +
|
||||
"name it in clearFields; clearing all five deletes the list's config unless it also carries settings " +
|
||||
"this tool doesn't expose (session skills, file-scope serialization, permission mode), which are " +
|
||||
"this tool doesn't expose (session skills, permission mode, ticket link, base branch, PowerUse opt-in), which are " +
|
||||
"always preserved.")]
|
||||
public async Task<SetListConfigResult> SetListConfig(
|
||||
string listId, string? model = null, string? systemPrompt = null, string? agentPath = null,
|
||||
@@ -110,7 +110,8 @@ public sealed class ConfigMcpTools
|
||||
// UI-only).
|
||||
var hasUnrelatedSettings = existing is not null
|
||||
&& (existing.SessionSkills is not null
|
||||
|| existing.PermissionMode is not null || existing.TicketProjectId is not null);
|
||||
|| existing.PermissionMode is not null || existing.TicketProjectId is not null
|
||||
|| existing.BaseBranch is not null || existing.PowerUseAllowed);
|
||||
|
||||
ListConfigDto? config;
|
||||
var allCleared = m is null && sp is null && ap is null && mt is null && vc is null;
|
||||
@@ -131,8 +132,10 @@ public sealed class ConfigMcpTools
|
||||
VerifyCommand = vc, SessionSkills = existing?.SessionSkills,
|
||||
PermissionMode = existing?.PermissionMode,
|
||||
TicketProjectId = existing?.TicketProjectId,
|
||||
BaseBranch = existing?.BaseBranch,
|
||||
PowerUseAllowed = existing?.PowerUseAllowed ?? false,
|
||||
}, cancellationToken);
|
||||
config = allCleared ? null : new ListConfigDto(m, sp, ap, mt, vc);
|
||||
config = allCleared ? null : new ListConfigDto(m, sp, ap, mt, vc, existing?.BaseBranch);
|
||||
}
|
||||
|
||||
await _broadcaster.ListUpdated(listId);
|
||||
|
||||
@@ -600,9 +600,12 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
||||
// Gleiches Tri-State-Muster: null = gespeicherten Wert behalten, false = Opt-in widerrufen.
|
||||
var powerUseAllowed = dto.PowerUseAllowed ?? existing?.PowerUseAllowed ?? false;
|
||||
|
||||
// Tri-State wie oben: null = behalten, "" = löschen.
|
||||
var baseBranch = dto.BaseBranch is null ? existing?.BaseBranch : dto.BaseBranch.NullIfBlank();
|
||||
|
||||
// powerUseAllowed muss mit in die Leer-Prüfung: sonst löscht ein Save, bei dem PowerUse das
|
||||
// EINZIGE gesetzte Feld ist, die Config-Zeile und damit das Opt-in gleich wieder mit.
|
||||
if (model is null && systemPrompt is null && agentPath is null && dto.MaxTurns is null && sessionSkills is null && verifyCommand is null && permissionMode is null && ticketProjectId is null && !powerUseAllowed)
|
||||
if (model is null && systemPrompt is null && agentPath is null && dto.MaxTurns is null && sessionSkills is null && verifyCommand is null && permissionMode is null && ticketProjectId is null && !powerUseAllowed && baseBranch is null)
|
||||
{
|
||||
await repo.DeleteConfigAsync(dto.ListId);
|
||||
}
|
||||
@@ -620,6 +623,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
||||
PermissionMode = permissionMode,
|
||||
TicketProjectId = ticketProjectId,
|
||||
PowerUseAllowed = powerUseAllowed,
|
||||
BaseBranch = baseBranch,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -643,7 +647,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
||||
var repo = new ListRepository(ctx);
|
||||
var config = await repo.GetConfigAsync(listId);
|
||||
if (config is null) return null;
|
||||
return new ListConfigDto(config.Model, config.SystemPrompt, config.AgentPath, config.MaxTurns, SkillsFromJson(config.SessionSkills), config.VerifyCommand, config.PermissionMode, config.TicketProjectId, config.PowerUseAllowed);
|
||||
return new ListConfigDto(config.Model, config.SystemPrompt, config.AgentPath, config.MaxTurns, SkillsFromJson(config.SessionSkills), config.VerifyCommand, config.PermissionMode, config.TicketProjectId, config.PowerUseAllowed, config.BaseBranch);
|
||||
}
|
||||
|
||||
public async Task<SetTaskStatusResultDto> SetTaskStatus(string taskId, string status)
|
||||
|
||||
Reference in New Issue
Block a user