import Foundation /// Matches `src/db/models.rs::Task` (camelCase). Trimmed to the fields the /// mobile UI needs; extra fields in the payload are tolerated via /// non-exhaustive decoding. struct MakimaTask: Decodable, Identifiable, Hashable { let id: String let ownerId: String? let contractId: String? let parentTaskId: String? let depth: Int? let name: String let description: String? let status: String // "pending"|"running"|"paused"|"blocked"|"done"|"failed" let priority: Int? let plan: String? let isSupervisor: Bool? let daemonId: String? let progressSummary: String? let lastOutput: String? let errorMessage: String? let createdAt: Date? let updatedAt: Date? var statusColor: StatusKind { switch status.lowercased() { case "done", "completed": return .ok case "running": return .active case "pending", "paused": return .idle case "blocked": return .warn case "failed", "error", "cancelled": return .danger default: return .idle } } enum StatusKind { case ok, active, idle, warn, danger } } /// Response shape for `GET /mesh/tasks/{id}/output`. struct TaskOutputResponse: Decodable { let output: String? let lastOutput: String? let truncated: Bool? /// Coalesces whichever field the server populates. var text: String { output ?? lastOutput ?? "" } }