fix(mcp): report a Failed task's failureReason instead of a bare status

get_task/batch_get_tasks now return failureReason (max_turns|timeout|error|
cancelled|unknown) plus failureTurnsUsed/failureMaxTurns on a Failed task, so
max_turns (worktree usually fine, continue_task) is distinguishable from a
real error (reset_failed_task) without pulling get_task_log's raw NDJSON.
Classified and stamped onto TaskEntity by TaskRunner.MarkFailed via
TaskStateService.FailAsync; TaskRunEntity also keeps the CLI's raw
terminal_reason/result_subtype/errors for deeper diagnosis. reset_failed_task's
description now warns explicitly that it discards the worktree and points at
continue_task for max_turns. Surfaced on the task card's status-chip tooltip.
This commit is contained in:
mika kuns
2026-08-10 14:20:00 +02:00
parent 6a2a19cc9e
commit a067a7bfff
19 changed files with 1295 additions and 24 deletions
@@ -226,7 +226,9 @@ public sealed class TaskStateService : ITaskStateService
: new TransitionResult(true, null);
}
public async Task<TransitionResult> FailAsync(string taskId, DateTime finishedAt, string? error, CancellationToken ct)
public async Task<TransitionResult> FailAsync(
string taskId, DateTime finishedAt, string? error, CancellationToken ct,
string failureReason = "error", int? turnsUsed = null, int? maxTurns = null)
{
await using (var ctx = await _dbFactory.CreateDbContextAsync(ct))
{
@@ -239,7 +241,10 @@ public sealed class TaskStateService : ITaskStateService
.ExecuteUpdateAsync(s => s
.SetProperty(t => t.Status, TaskStatus.Failed)
.SetProperty(t => t.FinishedAt, finishedAt)
.SetProperty(t => t.Result, error), ct);
.SetProperty(t => t.Result, error)
.SetProperty(t => t.FailureReason, failureReason)
.SetProperty(t => t.FailureTurnsUsed, turnsUsed)
.SetProperty(t => t.FailureMaxTurns, maxTurns), ct);
if (affected == 0)
return new TransitionResult(false, "Task not in a failable state (must be Running or Queued).");