Lift MUL-1949's offline backfill failure_reason taxonomy into a shared
in-flight classifier so the agent_task_queue.failure_reason column is
written with refined values (provider_auth_or_access, context_overflow,
provider_capacity_or_rate_limit, …) at write time rather than waiting on
SQL backfill to re-classify after the fact. PR1 of the Grafana board
plan in MUL-2328 — the upcoming PR2 reuses pkg/taskfailure.AllReasons()
to pre-warm the Prometheus failure_reason label set.
* server/pkg/taskfailure: new package with the canonical 21 Reason
constants (7 platform-side + 14 agent_error.* sub-reasons),
AllReasons() returning a defensive copy, IsAgentError() prefix check,
and Classify(rawError) Reason mirroring the SQL CASE rules from
MUL-1949 (db-boy's analysis). 100% statement coverage.
* server/internal/daemon/daemon.go: route the 'agent_error' coarse
fallback paths (StartTask error, runTask early-return error, CompleteTask
permanent rejection, reportTaskResult default branch) and the
executeAndDrain default error case (chained after classifyPoisonedError)
through taskfailure.Classify so blocked / timeout / unknown-status
results all carry a refined reason on the wire.
* server/internal/service/task.go: FailTask classifies errMsg when the
daemon-supplied failureReason is empty, eliminating the legacy
COALESCE(.., 'agent_error') landing.
* server/internal/daemon/poisoned.go: alias FailureReasonIterationLimit
and FailureReasonAPIInvalidRequest to the canonical taskfailure
constants. agent_fallback_message and codex_semantic_inactivity are
pre-existing operational reasons not in the canonical 21 — kept as
literals for now and revisited in a follow-up PR.
Backfill SQL from MUL-1949 stays as the authoritative offline source of
truth; this PR keeps the in-flight classifier in lock-step with the SQL
CASE expression so historical and future rows share the same taxonomy.
No behavior change for the platform-side reasons (queued_expired,
runtime_offline, runtime_recovery, timeout, etc.) which already align
with the canonical set.
Co-authored-by: Eve <eve@multica-ai.local>
Co-authored-by: multica-agent <github@multica.ai>