Parent epic: #1000
Depends on: #1004, #1006, #1007, and #1008.
Work type
Shippable macOS GUI lifecycle and controls slice.
Problem
The existing tasks foundation can display coarse cron active/paused rows and pending callbacks, but it does not present the full execution lifecycle or consistently expose actions. TaskInfo.actions is decoded without a complete end-to-end control path, and refresh behavior is not enough to prove that a scheduled continuation advanced the chat.
Protected user path
A user schedules “every five minutes check whether the website is deployed” or “in two minutes say hello,” sees when it will run, watches it start and finish, sees the new chat messages, and can pause/resume/delete the cron or cancel the callback.
How to fix
- Extend the additive /v1/tasks representation with next_run_at/fires_at, last_run_at, execution status, linked run ID, attempts, last safe error, updated_at, and server-authoritative allowed actions.
- Add or finish scoped endpoints for cron pause/resume/delete and callback cancel. Validate action availability server-side, not only in Swift.
- Model task kind/state/actions as typed Swift values with forward-compatible unknown handling.
- Add row/detail controls with confirmation for destructive delete, disabled/loading/error states, keyboard access, VoiceOver labels, and visible next/last execution status.
- Refresh task state from lifecycle events where available, with bounded polling fallback.
- Add transcript system entries or equivalent UI treatment for scheduled, started, retrying/skipped, succeeded, failed, canceled, and deleted transitions. Do not fabricate an assistant message; actual assistant output must come from the run stream.
- Link a task's active/last run into the existing conversation and run controls.
Acceptance criteria
- Cron rows show enabled/paused, next run, last result, and linked run.
- Callback rows show due time, attempts/state, last error when failed, and linked run.
- Pause/resume/delete/cancel work from the GUI and immediately reconcile to server state.
- A cron/callback-triggered run visibly advances the open chat.
- Failed/retrying/skipped states are distinguishable and accessible.
- Unauthorized or stale actions fail safely and refresh allowed actions.
- State remains correct after app restart and SSE reconnect.
- Existing task display behavior remains compatible with older additive payloads.
Test-first plan
Backend tests:
- task serialization for every lifecycle state;
- scope/auth and action availability;
- pause/resume/delete/cancel endpoint success, conflict, not found, and stale action.
Swift tests:
- decoder forward compatibility;
- row/detail rendering and accessible labels;
- each action's request and reconciliation;
- lifecycle event refresh and polling fallback;
- transcript entries versus actual assistant output;
- error/retry/skipped states.
Run:
- go test ./internal/server -run 'Test.*Tasks|Test.*Cron.*Action|Test.*Callback.*Cancel' -count=1
- go test ./internal/server -race -count=1
- swift test --package-path macapp --filter Task
- swift test --package-path macapp
Scope boundaries
In scope: additive task API/action endpoints, Mac models/views/actions, transcript lifecycle UX, tests, accessibility, docs.
Out of scope: scheduler/retry implementation itself, a generalized notification center, and iOS/web clients.
Rollout / rollback
Add fields and endpoints compatibly. Hide controls when the server omits an allowed action. Rollback the new controls while retaining read-only task display and additive server fields.
Definition of done
One PR closes this issue, includes backend and Swift regression coverage, demonstrates the real path in the installed Mac app, updates UX/API/engineering docs and indexes, and passes required verification.
Parent epic: #1000
Depends on: #1004, #1006, #1007, and #1008.
Work type
Shippable macOS GUI lifecycle and controls slice.
Problem
The existing tasks foundation can display coarse cron active/paused rows and pending callbacks, but it does not present the full execution lifecycle or consistently expose actions. TaskInfo.actions is decoded without a complete end-to-end control path, and refresh behavior is not enough to prove that a scheduled continuation advanced the chat.
Protected user path
A user schedules “every five minutes check whether the website is deployed” or “in two minutes say hello,” sees when it will run, watches it start and finish, sees the new chat messages, and can pause/resume/delete the cron or cancel the callback.
How to fix
Acceptance criteria
Test-first plan
Backend tests:
Swift tests:
Run:
Scope boundaries
In scope: additive task API/action endpoints, Mac models/views/actions, transcript lifecycle UX, tests, accessibility, docs.
Out of scope: scheduler/retry implementation itself, a generalized notification center, and iOS/web clients.
Rollout / rollback
Add fields and endpoints compatibly. Hide controls when the server omits an allowed action. Rollback the new controls while retaining read-only task display and additive server fields.
Definition of done
One PR closes this issue, includes backend and Swift regression coverage, demonstrates the real path in the installed Mac app, updates UX/API/engineering docs and indexes, and passes required verification.