// // PendingAction.swift // Poche // // Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // import Foundation /// A side-effect proposed by the model, waiting for the user's explicit /// confirmation. The model never writes; it proposes, the app decides /// (CLAUDE.md §3 — the non-negotiable principle). struct PendingAction: Identifiable, Sendable { enum Status: Sendable, Equatable { case waiting case executing case failed(String) } enum Payload: Sendable { case reminder(ReminderDraft) case event(EventDraft) case note(NoteDraft) case newTask(TaskDraft) case taskUpdate(TaskUpdateDraft) } let id = UUID() let payload: Payload var status: Status = .waiting /// Card headline — always future tense: nothing has happened yet. var title: String { switch payload { case .reminder: "Créer un rappel" case .event: "Créer un événement" case .note: "Enregistrer une note" case .newTask: "Créer une tâche" case .taskUpdate: "Modifier une tâche" } } /// Resolved values shown in clear text (dates already validated). var fields: [(label: String, value: String)] { switch payload { case .reminder(let draft): [("Titre", draft.title), ("Échéance", DateResolver.display(draft.due))] + (draft.list.map { [("Liste", $0)] } ?? []) case .event(let draft): [("Titre", draft.title), ("Début", DateResolver.display(draft.start)), ("Fin", DateResolver.display(draft.end))] + (draft.location.map { [("Lieu", $0)] } ?? []) case .note(let draft): [("Titre", draft.title), ("Contenu", String(draft.content.prefix(140)))] case .newTask(let draft): [("Titre", draft.title)] + (draft.details.map { [("Détails", String($0.prefix(140)))] } ?? []) + (draft.due.map { [("Échéance", DateResolver.display($0))] } ?? []) case .taskUpdate(let draft): [("Tâche", draft.currentTitle)] + (draft.newTitle.map { [("Nouveau titre", $0)] } ?? []) + (draft.newDue.map { [("Nouvelle échéance", DateResolver.display($0))] } ?? []) + (draft.markDone == true ? [("État", "Marquer comme faite")] : []) } } /// One-line summary used for system notices and agent notes. var summary: String { switch payload { case .reminder(let draft): "Rappel « \(draft.title) » pour \(DateResolver.display(draft.due))" case .event(let draft): "Événement « \(draft.title) » le \(DateResolver.display(draft.start))" case .note(let draft): "Note « \(draft.title) »" case .newTask(let draft): "Tâche « \(draft.title) »" case .taskUpdate(let draft): "Modification de la tâche « \(draft.currentTitle) »" } } } struct ReminderDraft: Sendable { let title: String let due: Date let list: String? } struct EventDraft: Sendable { let title: String let start: Date let end: Date let location: String? } struct NoteDraft: Sendable { let title: String let content: String } struct TaskDraft: Sendable { let title: String let details: String? let due: Date? } struct TaskUpdateDraft: Sendable { let taskID: UUID let currentTitle: String let newTitle: String? let newDue: Date? let markDone: Bool? }