fix(merge): conventional merge-commit default and live verify progress

The merge commit message was hand-rolled per caller ("Merge task: <title>",
"Merge <branch>", "Merge subtask") and ignored the task's commit type. Every
caller now passes a blank message and TaskMergeService fills in
CommitMessageBuilder.BuildMerge -> {commitType}(list-slug): merge <title> plus the
ClaudeDo-Task trailer; the merge modal prefills it from GetMergeTargets.

A merge whose list has a verify command holds the MergeTask call for minutes (5m46s
on this repo), during which the modal only disabled its button - no spinner, no
message, so a landed merge looked like a dead app. TaskMergeService now broadcasts
MergeProgress(taskId, phase, elapsedSeconds) for the merging and verifying phases
(re-reported every 30s) plus a WorkerLog line when verify starts; the modal shows a
spinner and the localized phase.
This commit is contained in:
mika kuns
2026-08-11 19:14:36 +02:00
parent fc9df7f9ac
commit cad0582b37
22 changed files with 405 additions and 31 deletions
@@ -65,6 +65,39 @@ public class CommitMessageBuilderTests
Assert.Equal("ClaudeDo-Task: id-456", lines[4]);
}
[Fact]
public void BuildMerge_ConventionalHeaderWithMergeVerbAndTrailer()
{
var msg = CommitMessageBuilder.BuildMerge("fix", "Lager App", "stop the crash", "id-789");
var lines = msg.Split('\n');
Assert.Equal("fix(lager-app): merge stop the crash", lines[0]);
Assert.Equal("", lines[1]);
Assert.Equal("ClaudeDo-Task: id-789", lines[2]);
}
[Fact]
public void BuildMerge_BlankCommitType_FallsBackToDefault()
{
var msg = CommitMessageBuilder.BuildMerge(" ", "My List", "do it", "id");
Assert.StartsWith("chore(my-list): merge do it", msg);
}
[Fact]
public void BuildMerge_ListNameWithoutSluggableChars_DropsScope()
{
var msg = CommitMessageBuilder.BuildMerge("feat", "!!!", "do it", "id");
Assert.StartsWith("feat: merge do it", msg);
}
[Fact]
public void BuildMerge_TitleTruncatedTo60()
{
var msg = CommitMessageBuilder.BuildMerge("feat", "My List", new string('x', 80), "id");
var titlePart = msg.Split('\n')[0].Split(": merge ", 2)[1];
Assert.Equal(60, titlePart.Length);
}
[Fact]
public void Description_TruncatedTo400()
{