MCPcopy Create free account
hub / github.com/compozy/agh / RecoverTask

Method RecoverTask

internal/task/block_service.go:316–368  ·  view source on GitHub ↗

RecoverTask clears task-level needs_attention escalation through the service-owned transition.

(ctx context.Context, id string, note string, actor ActorContext)

Source from the content-addressed store, hash-verified

314
315// RecoverTask clears task-level needs_attention escalation through the service-owned transition.
316func (m *Service) RecoverTask(ctx context.Context, id string, note string, actor ActorContext) (*Task, error) {
317 if err := requireWriteAuthority(actor); err != nil {
318 return nil, err
319 }
320 trimmedID := strings.TrimSpace(id)
321 if trimmedID == "" {
322 return nil, fmt.Errorf("%w: task.id is required", ErrValidation)
323 }
324 if actor.Actor.Kind.Normalize() == ActorKindAgentSession {
325 return nil, autonomyError(
326 AutonomyForeignRun,
327 ErrPermissionDenied,
328 "agent session %q cannot recover task %q without operator scope",
329 strings.TrimSpace(actor.Actor.Ref),
330 trimmedID,
331 )
332 }
333 normalizedNote := strings.TrimSpace(note)
334 if err := rejectTaskSecretText("task.recover_note", normalizedNote); err != nil {
335 return nil, err
336 }
337 recoveredAt := m.now().UTC()
338 cleared, err := m.store.ClearTaskNeedsAttention(ctx, NeedsAttentionClearMutation{
339 TaskID: trimmedID,
340 ClearedBy: actor.Actor,
341 ClearedAt: recoveredAt,
342 })
343 if err != nil {
344 return nil, err
345 }
346 reconciled, err := m.reconcileTaskCascade(ctx, cleared.ID)
347 if err != nil {
348 return nil, err
349 }
350 if eventErr := m.recordTaskEvent(ctx, reconciled.ID, "", taskEventRecovered, actor, recoveredTaskPayload{
351 Status: reconciled.Status,
352 Note: redactTaskSecretText(normalizedNote),
353 At: recoveredAt,
354 }); eventErr != nil {
355 slog.Error(
356 "task: recovered event failed after committed recover",
357 "error", eventErr,
358 "event_type", taskEventRecovered,
359 "task_id", reconciled.ID,
360 )
361 }
362 m.dispatchTaskRecovered(ctx, reconciled, actor, normalizedNote, recoveredAt)
363 m.autoEnqueueReadyTaskDetached(ctx, reconciled.ID, autoEnqueueTrigger{
364 Kind: autoEnqueueTriggerRecover,
365 Ref: reconciled.ID,
366 }, actor)
367 return &reconciled, nil
368}
369
370// ExpireTaskBlocks finalizes expired transient blocks through service-owned transitions.
371func (m *Service) ExpireTaskBlocks(

Callers

nothing calls this directly

Calls 12

reconcileTaskCascadeMethod · 0.95
recordTaskEventMethod · 0.95
dispatchTaskRecoveredMethod · 0.95
requireWriteAuthorityFunction · 0.85
autonomyErrorFunction · 0.85
rejectTaskSecretTextFunction · 0.85
redactTaskSecretTextFunction · 0.85
NormalizeMethod · 0.45
nowMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected