← Back to dashboard

Run Detail

alaro-refactor

nightshift/refactor-2026-03-17
Completed

28/28 done

28 tasks
Created 6d 18h ago Completed 6d 8h ago Repo /home/dev/projects/alaro Worktree /home/dev/projects/alaro

Tasks

Ordered by sort order and updated live.

  1. Description

    AlarmEditView.swift is ~1200 lines with 25+ @State properties and deeply nested sub-views. It needs to be broken into smaller, focused files. Goal: Extract logical sections (schedule picker, snooze config, reminder config, chip components, etc.) into their own SwiftUI view files. Keep AlarmEditView as the orchestrator that owns state and passes bindings. Target: AlarmEditView under ~300 lines after extraction. Use your judgment on exactly how to slice it — the key constraint is that each extracted view should be a self-contained, reusable section. Pure extraction refactor — no behavior changes. Main file: Alaro/Views/Alarms/AlarmEditView.swift

    Latest Worker Note
    Task reset
  2. Description

    After sub-view extraction (task 1), AlarmEditView still has 25+ @State properties. Consolidate them into a single form state object. Goal: Create an @Observable AlarmFormState class that owns all the form fields. Add init(from:) for populating from an existing alarm and applyTo(_:) for writing back. Replace the scattered @State properties with a single @State form object. Decide how to expose state to sub-views (bindings, @Bindable, or passing the whole object). Pick whatever feels cleanest. Pure refactor — no behavior changes. Main file: Alaro/Views/Alarms/AlarmEditView.swift

    Latest Worker Note
    Task reset
  3. Description

    Alarm.swift is ~940 lines mixing the @Model class, schedule enums, date calculation logic, and remote serialization structs. Goal: Split into focused files. Suggested splits (adapt as needed): - Schedule date calculation helpers (nextFireDate, monthly/yearly fire date logic) into their own file - Remote serialization structs (RemoteAlarm, RemoteAlarmSchedule, etc.) into their own file - Keep the @Model class, enums, and basic computed properties in Alarm.swift Target: Alarm.swift under ~400 lines. Use your judgment on exact boundaries. Pure refactor — no behavior changes. Main file: Alaro/Models/Alarm.swift

    Latest Worker Note
    Task reset
  4. Description

    EscalationHandler.swift is ~630 lines handling both notification scheduling AND user response processing. Goal: Split into focused files — one for creating/cancelling UNNotificationRequests, one for handling user actions (acknowledge, snooze, dismiss). Keep a thin coordinator that exposes the public API other services call. Use your judgment on exact file boundaries and naming. Update all callers. Pure refactor — no behavior changes. Main file: Alaro/Services/EscalationHandler.swift — check callers in SyncEngine.swift, PushHandler.swift, AlaroApp.swift

    Latest Worker Note
    Task reset
  5. Description

    APIClient.swift is ~870 lines with all API endpoints in one file. Goal: Split into domain-specific extensions (device, alarm, reminder, sync). Keep the base client (URL config, auth headers, shared helpers, error types) in the main file. Move endpoint methods into extensions and request/response model structs into a models file. Use your judgment on exact grouping. Swift extensions across files work naturally. Pure refactor — no behavior changes. Main file: Alaro/Services/APIClient.swift

    Latest Worker Note
    Task reset
  6. Description

    PushHandler.swift is ~600 lines mixing push payload parsing with business logic. Goal: Separate payload decoding from application logic. Extract decoders and appliers into their own files, keeping PushHandler as a thin coordinator. Use your judgment on naming and boundaries. Update callers. Pure refactor — no behavior changes. Main file: Alaro/Services/PushHandler.swift

    Latest Worker Note
    Task reset
  7. Description

    AlaroApp.swift is ~340 lines with manual service creation and wiring. Goal: Extract service initialization into a ServiceContainer (or similar) that owns all service instances and handles dependency wiring. AlaroApp should just create the container and inject services into the SwiftUI environment. Target: AlaroApp.swift under ~100 lines. Pure refactor — no behavior changes. Main file: Alaro/AlaroApp.swift

    Latest Worker Note
    Task reset
  8. Description

    store.go is 3377 lines with all CRUD for every entity in one file. Goal: Split Store methods into domain-specific files (device, alarm, reminder, tombstone, demo, push log, etc.). Keep the Store struct, constructor, DB init, and transaction helpers in the base file. Go allows methods on the same type across files in the same package — use this. Use your judgment on exact file boundaries. Run `go test ./cmd/alaro-server/...` after to verify. Pure refactor — no behavior changes. Main file: cmd/alaro-server/store.go

    Latest Worker Note
    Task reset
  9. Description

    server.go is 1162 lines with all HTTP handlers, middleware, and error helpers. Goal: Split into focused files — handlers by domain (device, alarm, reminder, sync/health), middleware, and shared error/response helpers. Keep the Server struct, constructor, and route registration in the base file. Go allows methods on the same type across files — use this. Use your judgment on grouping. Run `go test ./cmd/alaro-server/...` after to verify. Pure refactor — no behavior changes. Main file: cmd/alaro-server/server.go

    Latest Worker Note
    Task reset
  10. Description

    apns.go is 740 lines mixing JWT token management, payload building, coalescing, and HTTP sending. Goal: Extract distinct concerns into their own files — JWT lifecycle, payload coalescing, and keep the APNs client/sender in the main file. Use your judgment on exact boundaries. Run `go test ./cmd/alaro-server/...` after to verify. Pure refactor — no behavior changes. Main file: cmd/alaro-server/apns.go

    Latest Worker Note
    Task reset
  11. Description

    The server uses basic log.Logger for all output. Switch to Go's built-in log/slog for structured JSON logging. Goal: Replace all log.Printf/Println calls with slog.Info/Error/Debug/Warn. Set up a JSON handler in main.go. Add structured fields to request logging (method, path, status, duration, device_id) and APNs logging. Add a LOG_LEVEL config option (default: info). Non-functional change — behavior stays the same, output format changes. Files: all Go files in cmd/alaro-server/

    Latest Worker Note
    Task reset
  12. Description

    Schema evolution currently uses ad-hoc ensureColumnExists() calls during startup. Replace with a proper numbered migration system. Goal: Create a migrations table + ordered migration runner. Convert the current schema into migration 1 (baseline). Remove all ensureColumnExists calls. Future changes become new numbered migrations. Make it idempotent for existing databases. Keep it simple — no external dependencies. Run `go test ./cmd/alaro-server/...` after to verify. Main file: cmd/alaro-server/store.go (read to find current schema and ensureColumn calls)

    Latest Worker Note
    Task reset
  13. Description

    Background tasks (tombstone pruning, alarm escalation retries, demo cleanup) use raw time.AfterFunc with no centralized shutdown coordination. Goal: Create a background task manager that tracks goroutines and supports graceful shutdown via context cancellation. Migrate existing background tasks to use it. Wire shutdown into main.go's signal handling. Run `go test ./cmd/alaro-server/...` after to verify. Files: cmd/alaro-server/main.go, cmd/alaro-server/store.go, cmd/alaro-server/alarm_escalation.go, cmd/alaro-server/demo_alarm_cleanup.go

    Latest Worker Note
    Task reset
  14. Description

    The previous overnight run merged reminders into alarms and was supposed to delete ReminderEditView.swift and ReminderListView.swift. Verify cleanup is complete. Goal: Check if deleted files still exist, search for any remaining references to ReminderEditView, ReminderListView, ReminderRowView, or standalone reminder creation flows. Remove any dead references. Keep the Reminder model (needed for sync compatibility). Files: search the whole Alaro/ directory

    Latest Worker Note
    Task reset
  15. Description

    Error handling is inconsistent — scattered error vars, mixed checking styles, no structured error types. Goal: Create centralized error types for both iOS (AlaroError enum conforming to LocalizedError) and Server (Go structured error types with proper Is/As support). Update API client and handlers to use them. Ensure consistent JSON error response format on the server. Use your judgment on which errors to centralize vs leave as-is. Focus on the most impactful ones (API errors, validation, quota limits). Files: iOS — Alaro/Services/APIClient.swift. Server — cmd/alaro-server/server.go, cmd/alaro-server/store.go

    Latest Worker Note
    Task reset
  16. Description

    This is a meta-task. Do NOT write code. 1. Analyse the entire Alaro repository (iOS app + Go server) for refactoring opportunities. Look for: - Large files that should be split - Duplicated logic that should be consolidated - Inconsistent patterns that should be unified - Dead code or unused imports - Missing abstractions or overly complex functions - Naming inconsistencies - Any other code smells 2. For each opportunity, estimate effort. Only include tasks that can be completed in ≤60 minutes each. 3. Return a structured list of refactoring tasks, each with: - A clear title - A description explaining what to change and why (leave freedom for the worker to decide how) - The main files involved - A phase label (ios-refactor, server-refactor, or cleanup) 4. Then add each task to this nightshift run via the dashboard API: POST http://127.0.0.1:9100/api/runs/a0733734-a875-4856-a168-c5939ce2f7f7/tasks Content-Type: application/json Body: {"title": "...", "phase": "...", "description": "..."} 5. Do NOT duplicate tasks that already exist in this run. Check existing tasks first: GET http://127.0.0.1:9100/api/runs/a0733734-a875-4856-a168-c5939ce2f7f7/tasks Skip anything already covered by the existing 15 tasks. Focus on fresh opportunities the initial planning missed.

    Latest Worker Note
    Completed analysis and task creation directly as supervisor. Three parallel exploration agents analysed iOS files, Go server files, and cross-cutting patterns. Identified 11 fresh refactoring opportunities not covered by existing 15 tasks: SyncEngine split (17), AlarmScheduler split (18), makeRemoteAlarm dedup (19), AlarmListView coordinator (20), handler boilerplate DRY (21), payment.go JWS split (22), shared APNS package (23), normalize validation consolidation (24), AlarmStore pattern consolidation (25), EscalationNotificationScheduler dedup (26), token hex utility (27).
  17. Description

    SyncEngine.swift is ~789 lines mixing merge logic, confirmation, connectivity monitoring, and error mapping. Goal: Extract the large merge() method (~131 lines) into domain-specific helpers (mergeAlarms, mergeReminders, mergeTombstones). Extract hardDeleteAlarmLocally/hardDeleteReminderLocally into a shared deletion helper since they follow nearly identical patterns. Extract the error-code-to-string mapping (~35 lines) into a dedicated helper or lookup table. Target: SyncEngine.swift under ~400 lines with clearer separation of concerns. Keep the sync coordination (reconnect, processBackgroundQueue) in the main file. Pure refactor — no behavior changes. Main file: Alaro/Services/SyncEngine.swift

    Latest Worker Note
    Codex completed the split successfully. Verified line counts, file structure, and method references. No build tools available but project.yml auto-includes all files in Alaro/ directory.
  18. Description

    AlarmScheduler.swift is ~798 lines mixing notification scheduling, repair logic, and date/calendar calculations. Goal: Extract the schedule building logic (buildSchedule, buildFixedSchedule, buildWeeklySchedule, monthly/yearly schedule functions) and date calculation helpers (scheduledDate, ordinalWeekdayDay, monthDate, resolvedDate) into a separate AlarmScheduleBuilder or similar. These are pure functions that transform alarm configuration into UNNotificationRequests — easy to extract and test independently. Target: AlarmScheduler.swift under ~400 lines, focused on coordination. Schedule building in its own file. Pure refactor — no behavior changes. Main file: Alaro/Services/AlarmScheduler.swift

    Latest Worker Note
    Extraction complete. All specified functions moved. AlarmScheduler at 470 lines (above ~400 target but all extractable pure functions have been moved; remaining code is coordination). Original formatting preserved for minimal diff noise.
  19. Description

    The makeRemoteAlarm() function (~12 lines converting an Alarm model to a RemoteAlarm DTO) is duplicated in 4 files: AlarmScheduler.swift, AlarmListView.swift, EscalationNotificationScheduler.swift, and RemoteStateApplicator.swift. Goal: Extract makeRemoteAlarm() into a single shared location (e.g., an extension on Alarm, or a method on RemoteAlarm like init(from:)). Update all 4 call sites to use the shared version. Remove all duplicates. Pure refactor — no behavior changes. Files: Alaro/Services/AlarmScheduler.swift, Alaro/Views/Alarms/AlarmListView.swift, Alaro/Services/EscalationNotificationScheduler.swift, Alaro/Services/RemoteStateApplicator.swift

    Latest Worker Note
    accept_codex_result
  20. Description

    AlarmListView.swift is ~515 lines mixing SwiftUI view code with alarm toggle/delete business logic including snapshot-and-rollback error recovery. Goal: Extract the alarm action logic (toggleAlarm ~44 lines, deleteAlarm ~59 lines, their shared snapshot/rollback patterns, and sync engine configuration) into a separate coordinator or view model. The view should only handle display and delegate actions. Also extract the filtering/sorting computed properties (visibleAlarms, activeAlarms, pastAlarms) which could live on the coordinator. Target: AlarmListView.swift focused on layout/display, action logic in a separate file. Pure refactor — no behavior changes. Main file: Alaro/Views/Alarms/AlarmListView.swift

    Latest Worker Note
    Reviewed Codex output: coordinator correctly extracts all business logic, view delegates properly, AlarmSnapshot already existed for rollback pattern. No compilation available but diff review confirms behavior parity.
  21. Description

    The HTTP handler files (server_handler_device.go, server_handler_alarm.go, server_handler_reminder.go) repeat the same boilerplate patterns: - Device context extraction (deviceFromContext + error response) repeated 15+ times - Path value extraction (strings.TrimSpace(r.PathValue("id"))) repeated 5+ times - Store error handling (check error, log, write error response) repeated 10+ times Goal: Extract shared helpers to reduce repetition: - requireDevice(r, w) helper that extracts device from context or writes error and returns nil - pathParam(r, name) helper for trimmed path values - handleStoreError(w, r, err, logger) for the common error-check-log-respond pattern Update all handler files to use the new helpers. Run go test after. Pure refactor — no behavior changes. Files: cmd/alaro-server/server_handler_device.go, server_handler_alarm.go, server_handler_reminder.go, server_helpers.go

    Latest Worker Note
    mark_done
  22. Description

    payment.go is 443 lines mixing App Store Server Notification handling with low-level JWS/ECDSA cryptographic verification. Goal: Extract the cryptographic verification logic into a separate file (e.g., payment_jws.go). This includes verifyCompactJWS(), verifyCertificateChain(), and related helpers. Keep the business logic (notification handling, subscription resolution) in payment.go. Also consider splitting verifyCompactJWS() (~42 lines) into smaller functions: parseCompactJWS, parseCertificateChain, verifySignature. Run go test after. Pure refactor — no behavior changes. Main file: cmd/alaro-server/payment.go

    Latest Worker Note
    Codex completed the refactoring in one turn. Verified tests pass and go vet is clean.
  23. Description

    Both alaro-server and alaro-push duplicate APNS JWT signing and P8 key parsing: - parseP8Key() is nearly identical in both packages - JWT signing (signAPNsJWT vs signAPNSJWT) is duplicated with identical logic - Token caching with 50-minute TTL and mutex patterns duplicated - APNS URL constants duplicated Goal: Create a shared internal package (e.g., internal/apnsjwt/) containing the P8 key parser, JWT signer, token cache, and APNS URL constants. Update both alaro-server and alaro-push to import from the shared package. Run go test for both packages after. Pure refactor — no behavior changes. Files: cmd/alaro-server/apns_jwt.go, cmd/alaro-server/apns.go, cmd/alaro-push/apns.go

    Latest Worker Note
    Task complete - all verification passed.
  24. Description

    store_normalize.go (356 lines) has duplicated validation patterns in normalizeSchedule(): - HH:MM time string parsing and hour/minute bounds checking repeated 3 times (for fixed, weekly, and monthly schedule types) - Ordinal week/weekday validation duplicated between monthly and yearly schedules - Pointer dereferencing boilerplate repeated throughout normalizeAlarmRequest() Goal: Extract shared helpers: - parseAndValidateLocalTime(time string) (hour, minute int, err error) — replaces 3 copies - validateOrdinalSchedule(week, weekday) error — replaces 2 copies - Consider splitting normalizeAlarmRequest() into validateAlarmRequest() + applyAlarmDefaults() Run go test after. Pure refactor — no behavior changes. Main file: cmd/alaro-server/store_normalize.go

    Latest Worker Note
    done
  25. Description

    AlarmStore.swift (475 lines) has significant duplication between alarm and reminder operations: - Fetch-by-predicate pattern repeated for both Alarm and Reminder (identical except for type) - Keyed fetch methods duplicated for both types - Dirty flag fetching duplicated with identical FetchDescriptor setup - Soft/hard delete pattern duplicated with identical conditional logic - createAlarm() has 15+ parameters — consider using a builder struct Goal: Extract generic fetch helpers (e.g., a generic fetch<T: PersistentModel>(predicate:) method) to reduce alarm/reminder code duplication. Consolidate the soft/hard delete pattern. Consider a parameter struct for createAlarm() to reduce its argument count. Pure refactor — no behavior changes. Main file: Alaro/Services/AlarmStore.swift

    Latest Worker Note
    Codex completed all requested changes in a single session. Reviewed output — changes are correct and preserve all existing public API.
  26. Description

    EscalationNotificationScheduler.swift (347 lines) has duplicated patterns: - pendingNotificationIdentifiers() and deliveredNotificationIdentifiers() are nearly identical methods differing only in which UNUserNotificationCenter method they call. Extract to a parameterized helper. - Three uses of withCheckedThrowingContinuation wrapping similar callback-based async patterns. Extract a reusable async wrapper. - refreshReminderState() (49 lines) mixes state calculation with state mutation — extract the calculation into a pure function. Pure refactor — no behavior changes. Main file: Alaro/Services/EscalationNotificationScheduler.swift

    Latest Worker Note
    All three deduplication targets addressed by Codex in a single pass. Verified final file structure.
  27. Description

    DeviceRegistrationService.swift repeats the pattern tokenData.map { String(format: "%02x", $0) }.joined() three times for converting APNs token Data to hex string. Goal: Extract a Data extension (e.g., Data.hexString or Data.apnsTokenString) and replace all 3 occurrences. Check if this pattern appears elsewhere in the codebase too (AlarmSnoozeHandler was flagged). Small cleanup — 15 minutes max. Main file: Alaro/Services/DeviceRegistrationService.swift

    Latest Worker Note
    worker launch failed
  28. Description

    All refactoring work is done on the nightshift branch. Now clean it up and merge. 1. Review all uncommitted changes with `git diff` and `git status`. 2. Group related changes into small, focused commits. Each commit should cover one logical unit (e.g., one file split, one extraction). Write clear commit messages. 3. Push the branch to the remote. 4. Merge the branch into main. Do not squash everything into one big commit — keep the history granular and readable.

    Latest Worker Note
    Grouped all uncommitted changes into 8 focused commits, pushed to remote, and fast-forward merged into main.