* docs(cli): clarify `issue rerun` semantics
The CLI table described `multica issue rerun <id>` as "Rerun the most
recent agent task", which led users to expect it would re-run whichever
agent ran last. The actual behavior is to enqueue a fresh task for the
issue's **current** agent assignee, regardless of who ran most
recently — see `TaskService.RerunIssue` in
`server/internal/service/task.go`.
Also fix a stale claim in `tasks.mdx`: the "Manual rerun" section
described session inheritance as "Yes", but commit b1345685 made manual
rerun pass `force_fresh_session=true` precisely to avoid replaying a
poisoned session. Only **automatic retry** still inherits the session.
Updates EN + ZH mirrors of `cli.mdx` and `tasks.mdx`.
Co-authored-by: multica-agent <github@multica.ai>
* docs(tasks): tighten rerun trigger surface; clean stale Go comments
Apply review feedback on PR #2304:
- `tasks.mdx` / `tasks.zh.mdx`: rerun is triggered via CLI or the
`/api/issues/{id}/rerun` endpoint, not "UI or CLI" — there's no rerun
affordance in web/desktop today.
- `tasks.mdx` / `tasks.zh.mdx`: comparison table — manual rerun applies
to "Issues with an agent assignee", not "All sources". The handler
rejects with `issue is not assigned to an agent` for anything else,
and there's no rerun path for chat or autopilot tasks.
- `task_lifecycle.go`: `RerunIssue` doc comment claimed the new task
"carries the most recent session_id/work_dir so the agent can resume".
That has been false since b1345685 — rewrite to reflect the actual
`force_fresh_session=true` contract.
- `agent.sql` (regenerated `agent.sql.go`): `GetLastTaskSession` doc
said it serves "auto-retry / manual rerun"; manual rerun is now
routed around it via `force_fresh_session=true`. Note both the
auto-retry path it does serve and the rerun escape hatch.
No logic change.
Co-authored-by: multica-agent <github@multica.ai>
---------
Co-authored-by: multica-agent <github@multica.ai>
* feat(server): orphan-task recovery + auto-retry + manual rerun (MUL-1128)
When the daemon process crashed mid-task the issue was stuck at
in_progress for up to 2.5h: the in-flight task timeout was the only
mechanism that ever moved the row, and the runtime heartbeat sweeper
only fires after the runtime stays offline for 45s — a quick restart
beats both windows.
This change implements the A+B plan from the issue thread:
A. lifecycle hygiene
- migration 055 adds attempt / max_attempts / parent_task_id /
failure_reason / last_heartbeat_at to agent_task_queue
- new daemon-auth endpoint POST /runtimes/{id}/recover-orphans:
daemon calls it on every register so the server fails any
dispatched/running tasks the previous process left behind
- new daemon-auth endpoint POST /tasks/{id}/session: persists the
agent's session_id + work_dir mid-flight so a crash doesn't
lose the resume pointer (claude+codex emit MessageStatus with
SessionID; daemon forwards on the first one it sees)
- FailAgentTask / FailStaleTasks / FailTasksForOfflineRuntimes
now set failure_reason ('agent_error' / 'timeout' /
'runtime_offline')
B. auto-retry with resume context
- TaskService.MaybeRetryFailedTask spawns a fresh queued attempt
carrying parent's session_id/work_dir when the failure reason
is infrastructure-shaped (timeout, runtime_offline,
runtime_recovery) and attempt < max_attempts; skips autopilot
- wired into the runtime sweeper paths and TaskService.FailTask
so the user transparently sees a new in_progress run instead of
a stuck row
- new user-auth POST /api/issues/{id}/rerun + multica issue rerun
CLI for the manual escape hatch
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(server): address PR review for orphan-task recovery (MUL-1128)
Three review-must-fix items on top of the A+B implementation:
1. recover-orphans now funnels through TaskService.HandleFailedTasks,
the same shared post-failure pipeline used by the runtime sweeper.
This guarantees task:failed events are emitted, agent status is
reconciled, and issues stuck in_progress with no remaining active
task are reset to todo even when no auto-retry is created
(max_attempts exhausted, autopilot, non-retryable reason).
2. RerunIssue now uses CancelAgentTasksByIssueAndAgent, scoped to the
issue's current assignee. The previous implementation called
CancelAgentTasksByIssue, which would collateral-cancel parallel
@-mention agents on the same issue.
3. GetLastTaskSession now considers both completed and failed tasks
(mirroring GetLastChatTaskSession), ordering by the most recent
timestamp. With UpdateAgentTaskSession pinning session_id/work_dir
mid-flight, an auto-retry or manual rerun of a daemon-crash failure
now actually resumes the prior conversation context instead of
starting fresh — matching the stated B-branch behaviour.
go build / go vet pass; the existing service and agent test suites pass.
runtime_sweeper / handler integration tests require a local DB with the
055 migration (and the pre-existing 050 first_executed_at column).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>