Merge nucleic/olive-umber-vole-0xpn into dev

This commit is contained in:
2026-07-18 17:30:38 -07:00
parent 9941d4435e
commit 33518eb800
2 changed files with 19 additions and 3 deletions
@@ -659,7 +659,13 @@ final class HostConnection {
previous = nil
sessions.append(summary)
}
let becameWaiting = summary.status == .awaitingInput && previous?.status != .awaitingInput
// A `.waitingBackground` turn is parked on an armed monitor, not on the user, so it
// must not fire the needs-you notification — each monitor tick's re-invoked turn would
// otherwise re-alert. It settles at `.awaitingInput` like any other turn end, so gate
// on the disposition explicitly.
let becameWaiting = summary.status == .awaitingInput
&& previous?.status != .awaitingInput
&& summary.disposition != .waitingBackground
if becameWaiting, !summary.archived { callbacks.sessionBecameWaiting(summary) }
callbacks.didUpdate()
case .dashboard(let snapshot):
+12 -2
View File
@@ -222,6 +222,9 @@ enum Palette {
/// finished-the-work turn reads as "done" (success) rather than the calm "ready" accent.
static func status(_ status: SessionStatus, disposition: TurnDisposition? = nil) -> Color {
if status == .awaitingInput, disposition == .completed { return success }
// Waiting on an armed background watch — still working in the background, so the calm
// "active" tint rather than the "ready for you" accent that pulls the eye.
if status == .awaitingInput, disposition == .waitingBackground { return active }
switch status {
case .idle, .provisioning: return neutral
case .running: return active
@@ -254,6 +257,7 @@ enum Palette {
enum StatusStyle {
static func symbol(_ status: SessionStatus, disposition: TurnDisposition? = nil) -> String {
if status == .awaitingInput, disposition == .completed { return "checkmark.circle.fill" }
if status == .awaitingInput, disposition == .waitingBackground { return "clock" }
switch status {
case .idle: return "circle"
case .provisioning: return "circle.dotted"
@@ -268,6 +272,7 @@ enum StatusStyle {
static func label(_ status: SessionStatus, disposition: TurnDisposition? = nil) -> String {
if status == .awaitingInput, disposition == .completed { return "Done" }
if status == .awaitingInput, disposition == .waitingBackground { return "Waiting…" }
return status.displayName
}
@@ -275,7 +280,11 @@ enum StatusStyle {
static func sortRank(_ summary: WireSessionSummary) -> Int {
switch summary.status {
case .awaitingApproval: return 0
case .awaitingInput: return summary.disposition == .completed ? 4 : 1
// Both "Done" and "Waiting…" (parked on a background monitor) are calm — they sort below
// running rather than up with the genuinely-needs-you turns.
case .awaitingInput:
return (summary.disposition == .completed || summary.disposition == .waitingBackground)
? 4 : 1
case .running, .provisioning: return 2
case .idle: return 3
case .finished, .interrupted, .error: return 5
@@ -296,7 +305,8 @@ extension SessionStatus {
func needsYou(_ disposition: TurnDisposition?) -> Bool {
switch self {
case .awaitingApproval: return true
case .awaitingInput: return disposition != .completed
// `.waitingBackground` is parked on a monitor, not on you — not a needs-you state.
case .awaitingInput: return disposition != .completed && disposition != .waitingBackground
default: return false
}
}