feat(worker): session skills SignalR surface + per-level persistence

This commit is contained in:
Mika Kuns
2026-07-23 16:47:14 +02:00
committed by mika kuns
parent 4626481359
commit b4c58087d2
18 changed files with 397 additions and 19 deletions
@@ -72,6 +72,43 @@ public class AppSettingsRepositoryTests : IDisposable
Assert.Null(row.CentralWorktreeRoot);
}
[Fact]
public async Task UpdateAsync_Persists_SessionSkills_Json()
{
using (var ctx = _db.CreateContext())
{
var repo = new AppSettingsRepository(ctx);
await repo.UpdateAsync(new AppSettingsEntity
{
SessionSkills = "[\"ponytail\",\"ponytail-help\"]",
});
}
using var readCtx = _db.CreateContext();
var row = await new AppSettingsRepository(readCtx).GetAsync();
Assert.Equal("[\"ponytail\",\"ponytail-help\"]", row.SessionSkills);
}
[Fact]
public async Task UpdateAsync_Blank_SessionSkills_Stored_As_Null()
{
using (var ctx = _db.CreateContext())
{
var repo = new AppSettingsRepository(ctx);
await repo.UpdateAsync(new AppSettingsEntity { SessionSkills = "[\"a\"]" });
}
using (var ctx = _db.CreateContext())
{
var repo = new AppSettingsRepository(ctx);
await repo.UpdateAsync(new AppSettingsEntity { SessionSkills = null });
}
using var readCtx = _db.CreateContext();
var row = await new AppSettingsRepository(readCtx).GetAsync();
Assert.Null(row.SessionSkills);
}
[Fact]
public async Task DailyPrepMaxTasks_defaults_to_5_and_persists()
{
@@ -60,6 +60,42 @@ public sealed class ListRepositoryConfigTests : IDisposable
Assert.Equal("haiku-4-5", fetched.Model);
}
[Fact]
public async Task SetConfig_Persists_SessionSkills_On_Insert()
{
await _repo.SetConfigAsync(new ListConfigEntity
{
ListId = _listId,
SessionSkills = "[\"ponytail\"]",
});
var fetched = await _repo.GetConfigAsync(_listId);
Assert.NotNull(fetched);
Assert.Equal("[\"ponytail\"]", fetched.SessionSkills);
}
[Fact]
public async Task SetConfig_Persists_SessionSkills_On_Update()
{
await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = "[\"a\"]" });
await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = "[\"b\",\"c\"]" });
var fetched = await _repo.GetConfigAsync(_listId);
Assert.NotNull(fetched);
Assert.Equal("[\"b\",\"c\"]", fetched.SessionSkills);
}
[Fact]
public async Task SetConfig_Null_SessionSkills_Clears_On_Update()
{
await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = "[\"a\"]" });
await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = null });
var fetched = await _repo.GetConfigAsync(_listId);
Assert.NotNull(fetched);
Assert.Null(fetched.SessionSkills);
}
public void Dispose()
{
_ctx.Dispose();
@@ -72,4 +72,33 @@ public sealed class TaskRepositoryAgentSettingsTests : IDisposable
Assert.Null(entity.SystemPrompt);
Assert.Null(entity.AgentPath);
}
[Fact]
public async Task UpdateAgentSettingsAsync_Persists_SessionSkills()
{
var taskId = await SeedTaskAsync();
await _repo.UpdateAgentSettingsAsync(taskId, null, null, null, sessionSkills: "[\"ponytail\",\"ponytail-help\"]");
var entity = await _repo.GetByIdAsync(taskId);
Assert.NotNull(entity);
Assert.Equal("[\"ponytail\",\"ponytail-help\"]", entity!.SessionSkills);
}
[Fact]
public async Task UpdateAgentSettingsAsync_Null_SessionSkills_ClearsColumn()
{
var taskId = await SeedTaskAsync();
using (var ctx = _db.CreateContext())
{
await new TaskRepository(ctx).UpdateAgentSettingsAsync(taskId, null, null, null, sessionSkills: "[\"a\"]");
}
await _repo.UpdateAgentSettingsAsync(taskId, null, null, null, sessionSkills: null);
var entity = await _repo.GetByIdAsync(taskId);
Assert.NotNull(entity);
Assert.Null(entity!.SessionSkills);
}
}