The file /Users/neog/Apps/iOS/PROD-Planner2026/Planner2026-iOS/Models/PlannerTask.swift has been updated. Here's the result of running `cat -n` on a snippet of the edited file: 61→} 62→ 63→// MARK: - PlannerTask 64→ 65→struct PlannerTask: Identifiable, Hashable { 66→ var id: UUID = UUID() 67→ var cloudKitRecordID: CKRecord.ID? 68→ var title: String 69→ var notes: String = "" 70→ var priority: TaskPriority = .medium 71→ var status: TaskStatus = .pending 72→ var dueDate: Date? 73→ var scheduledDate: Date? // AI-scheduled date 74→ var scheduledTime: Date? // AI-scheduled time 75→ var estimatedMinutes: Int? // Estimated duration 76→ var actualMinutes: Int? // Actual time spent 77→ var projectId: UUID? // Parent project 78→ var subtasks: [Subtask] = [] 79→ var tags: [UUID] = [] 80→ 81→ // Location features 82→ var locationId: UUID? // Associated location 83→ var hasGeofenceReminder: Bool = false 84→ var geofenceRadius: Double = 100 // meters 85→ var triggerOnEntry: Bool = true // vs on exit 86→ 87→ // AI metadata 88→ var isAISuggested: Bool = false 89→ var aiConfidenceScore: Double? // 0-1 90→ var patternNotes: String? // AI pattern insights 91→ 92→ // Timestamps 93→ var createdAt: Date = Date() 94→ var completedAt: Date? 95→ var modifiedAt: Date = Date() 96→ 97→ // MARK: - Codable Conformance (Manual for CKRecord.ID) 98→ 99→ enum CodingKeys: String, CodingKey { 100→ case id, cloudKitRecordName, title, notes, priority, status 101→ case dueDate, scheduledDate, scheduledTime 102→ case estimatedMinutes, actualMinutes, projectId 103→ case subtasks, tags, locationId 104→ case hasGeofenceReminder, geofenceRadius, triggerOnEntry 105→ case isAISuggested, aiConfidenceScore, patternNotes 106→ case createdAt, completedAt, modifiedAt 107→ } 108→} 109→ 110→// MARK: - Codable 111→ 112→extension PlannerTask: Codable { 113→ init(from decoder: Decoder) throws { 114→ let container = try decoder.container(keyedBy: CodingKeys.self) 115→ id = try container.decode(UUID.self, forKey: .id) 116→ title = try container.decode(String.self, forKey: .title) 117→ notes = try container.decodeIfPresent(String.self, forKey: .notes) ?? "" 118→ priority = try container.decodeIfPresent(TaskPriority.self, forKey: .priority) ?? .medium 119→ status = try container.decodeIfPresent(TaskStatus.self, forKey: .status) ?? .pending 120→ dueDate = try container.decodeIfPresent(Date.self, forKey: .dueDate) 121→ scheduledDate = try container.decodeIfPresent(Date.self, forKey: .scheduledDate) 122→ scheduledTime = try container.decodeIfPresent(Date.self, forKey: .scheduledTime) 123→ estimatedMinutes = try container.decodeIfPresent(Int.self, forKey: .estimatedMinutes) 124→ actualMinutes = try container.decodeIfPresent(Int.self, forKey: .actualMinutes) 125→ projectId = try container.decodeIfPresent(UUID.self, forKey: .projectId) 126→ subtasks = try container.decodeIfPresent([Subtask].self, forKey: .subtasks) ?? [] 127→ tags = try container.decodeIfPresent([UUID].self, forKey: .tags) ?? [] 128→ locationId = try container.decodeIfPresent(UUID.self, forKey: .locationId) 129→ hasGeofenceReminder = try container.decodeIfPresent(Bool.self, forKey: .hasGeofenceReminder) ?? false 130→ geofenceRadius = try container.decodeIfPresent(Double.self, forKey: .geofenceRadius) ?? 100 131→ triggerOnEntry = try container.decodeIfPresent(Bool.self, forKey: .triggerOnEntry) ?? true 132→ isAISuggested = try container.decodeIfPresent(Bool.self, forKey: .isAISuggested) ?? false 133→ aiConfidenceScore = try container.decodeIfPresent(Double.self, forKey: .aiConfidenceScore) 134→ patternNotes = try container.decodeIfPresent(String.self, forKey: .patternNotes) 135→ createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt) ?? Date() 136→ completedAt = try container.decodeIfPresent(Date.self, forKey: .completedAt) 137→ modifiedAt = try container.decodeIfPresent(Date.self, forKey: .modifiedAt) ?? Date() 138→ 139→ // Decode CloudKit record name if present 140→ if let recordName = try container.decodeIfPresent(String.self, forKey: .cloudKitRecordName) { 141→ cloudKitRecordID = CKRecord.ID(recordName: recordName) 142→ } 143→ } 144→ 145→ func encode(to encoder: Encoder) throws { 146→ var container = encoder.container(keyedBy: CodingKeys.self) 147→ try container.encode(id, forKey: .id) 148→ try container.encode(title, forKey: .title) 149→ try container.encode(notes, forKey: .notes) 150→ try container.encode(priority, forKey: .priority) 151→ try container.encode(status, forKey: .status) 152→ try container.encodeIfPresent(dueDate, forKey: .dueDate) 153→ try container.encodeIfPresent(scheduledDate, forKey: .scheduledDate) 154→ try container.encodeIfPresent(scheduledTime, forKey: .scheduledTime) 155→ try container.encodeIfPresent(estimatedMinutes, forKey: .estimatedMinutes) 156→ try container.encodeIfPresent(actualMinutes, forKey: .actualMinutes) 157→ try container.encodeIfPresent(projectId, forKey: .projectId) 158→ try container.encode(subtasks, forKey: .subtasks) 159→ try container.encode(tags, forKey: .tags) 160→ try container.encodeIfPresent(locationId, forKey: .locationId) 161→ try container.encode(hasGeofenceReminder, forKey: .hasGeofenceReminder) 162→ try container.encode(geofenceRadius, forKey: .geofenceRadius) 163→ try container.encode(triggerOnEntry, forKey: .triggerOnEntry) 164→ try container.encode(isAISuggested, forKey: .isAISuggested) 165→ try container.encodeIfPresent(aiConfidenceScore, forKey: .aiConfidenceScore) 166→ try container.encodeIfPresent(patternNotes, forKey: .patternNotes) 167→ try container.encode(createdAt, forKey: .createdAt) 168→ try container.encodeIfPresent(completedAt, forKey: .completedAt) 169→ try container.encode(modifiedAt, forKey: .modifiedAt) 170→ 171→ // Encode CloudKit record name if present 172→ try container.encodeIfPresent(cloudKitRecordID?.recordName, forKey: .cloudKitRecordName) 173→ } 174→ 175→ // MARK: - Computed Properties 176→ 177→ var progress: Double {