Context
Operator directive, 2026-07-18, completing the stop-hook investigation: "we also must honor night shift mode. if no operator is online, it would be bad if the team idles out." This is the third leg of the set #15401 (dialogue quadrant) + #15404 (autonomous material-artifact stop key) — both of which explicitly scope re-invocation OUT. The hook audit (48h log, converged independently by two seats) proved the structural fact this ticket owns: a Stop hook can refuse a stop but cannot create a turn. Every allowed stop — dialogue, clean-terminal, material-artifact, or the harness force-override ceiling — is PERMANENT while nothing re-invokes the seat. With wakes currently disabled, #15404's healthy duty cycle (work → artifact → rest) becomes a slow fleet shutdown: each seat earns one legitimate rest and never returns.
The Problem
Night shift is currently a manual operator act (wakes toggled by hand) with no liveness floor:
- No presence-aware policy. The wake daemon is on or off globally, by hand. When the operator walks away without flipping it, the fleet's turn supply dies with the dialogue: every seat's last turn ends in a (correct) allowed stop, and no autonomous turn ever begins. The observed fleet-wide mid-lane idling was exactly this — 155/155 allows in 24h rode
operatorInLoop=true while wakes were off.
- No daemon liveness guarantee. If the wake daemon dies at 03:00, heartbeat pulses stop, the fleet sleeps, and NOTHING alerts — the FM cockpit's wake-telltale (the shipped S2 axis) surfaces daemon state to a human who, at night, is not watching. The
NightShiftLeasedDriver contract's three-heartbeat critical-failure detection cannot fire when heartbeat DELIVERY itself is the dead component (learn/agentos/wake-substrate/NightShiftLeasedDriver.md §4.1 explicitly scopes this out: "does not reclassify upstream wake skips").
- The noise objection that disabled wakes is solved but unconsumed. The
#15376 sender-principal-class semantics (merged) make agent chatter durable-quiet by default with wake as a deliberate election, per the D#15372 AC-7 ruling ("the preferred sending mode is NOT a wake prompt which arrives too late as noise"). The disable predates the fix.
The Architectural Reality
- Wake delivery + idle-out recovery: owned historically by
#10671 (CLOSED — the substrate exists: Orchestrator heartbeat sweeps active WAKE_SUBSCRIPTION identities per pulse). The daemon: ai/daemons/wake/daemon.mjs; PID surface: memory-core config wakeDaemon.dataDir + wake-daemon.pid (already consumed by FleetManager.wakeStateOptions in ai/services/fleet/devFleetServer.mjs).
- The night-shift ownership contract:
NightShiftLeasedDriver.md (#10763, CLOSED) — driver leases, obligations, three-heartbeat critical failure. All of it presupposes pulses arriving; §6: "a maintainer harness is night-shift reachable only when its route is active."
- Operator presence signal already exists:
who_is_online classifies @tobiu from activity recency (AgentIdentity accountType human, the #15378 stamp substrate). Presence-awareness needs no new sensor — only a policy consumer.
- Class-suppression:
MailboxService sender-class wake-suppression defaults (#15376, merged) — the noise-floor mechanism a re-enabled daemon rides.
- The stop-economics pair:
#15401 + #15404 define WHEN a seat may rest; this ticket defines WHO WAKES IT UP.
The Fix
Three thin, composable pieces (one PR each is plausible; bundle-by-default unless implementation splits naturally):
- Presence-aware wake policy (the mode switch becomes automatic). A policy leaf the daemon reads at pulse time: operator-activity recency > threshold (e.g. 30–45 min without operator-class activity) ⇒ night-shift mode — heartbeat pulses flow to all active subscriptions regardless of the manual quiet toggle; operator active ⇒ the manual setting governs (his noise budget, his hours). The policy consumes the existing presence signal; no new sensor. Manual override always wins in both directions (an explicit operator "wakes off, full stop" is respected — the policy fills the ABSENCE of a decision, never fights one).
- The heartbeat floor. In night-shift mode, a seat with an active subscription that has produced no turn in N minutes receives one heartbeat wake (mailbox-drain + lane-continue per the leased-driver obligations). Cadence conservative (e.g. 20–30 min) — the point is the floor's existence, not frequency;
#15404's material-artifact key keeps the woken turn honest.
- The daemon dead-man guarantee. The wake daemon's own liveness gets an external watchdog: a launchd/cron-level respawn OR at minimum a stale-PID detector that (a) surfaces loudly in the FM cockpit wake-telltale AND (b) writes a
[critical-failure]-class A2A broadcast on recovery so the morning operator sees the outage window. A dead wake daemon at night must never be silent.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
| wake daemon pulse policy |
ai/daemons/wake/daemon.mjs + memory-core wakeDaemon config subtree |
presence-aware mode resolution at pulse time (manual override > policy > default) |
absent presence data ⇒ current manual behavior unchanged (fail-open to today) |
daemon JSDoc + NightShiftLeasedDriver.md amendment |
this investigation's audit-log analysis |
| operator presence read |
who_is_online / activity-recency substrate (#15378 stamps) |
read-only consumption; threshold configurable |
unreadable ⇒ treat operator as PRESENT (conservative: no auto-night-mode) |
policy leaf JSDoc |
existing roster classification |
| heartbeat floor |
Orchestrator heartbeat sweep (#10671 substrate) |
per-seat quiet-time floor in night mode only |
subscription inactive ⇒ seat unreachable (unchanged; the OpenCode gap is #15394's) |
same |
subscription-sweep precedent |
| daemon liveness watchdog |
PID file + FM wake-telltale (FleetManager.wakeStateOptions) |
external respawn or loud stale-PID surfacing + recovery broadcast |
watchdog itself dead ⇒ cockpit telltale still shows stale PID (existing) |
ops note |
S2 axis shipped surface |
Acceptance Criteria
Out of Scope
- The stop-hook quadrants (
#15401 / #15404 own stop economics; this ticket never touches the hook).
- OpenCode wake delivery (
#15394 owns the adapter; until it lands, Phoebe's seat is reachable only by polling — a named, tracked gap).
- Wake-noise policy changes beyond consuming the shipped
#15376 defaults.
- A dedicated driver-lease API (NightShiftLeasedDriver §6 substrate constraints stand).
Avoided Traps
- Hook-side "night mode" (rejected): making the hook stricter at night cannot help — refusal without re-invocation ends at the harness force-override ceiling and then sleeps anyway. The lever is turn CREATION.
- Operator-prose presence detection (rejected): presence = activity recency from the stamp substrate, never NLP over messages.
- Always-max heartbeats (rejected): the floor is a floor;
#15404's artifact economics + class-suppression keep the duty cycle honest without pinging seats that are mid-turn.
Decision Record impact
none — composes shipped substrate (#10671 sweep, #15376 classes, #15378 stamps, S2 telltale) under one policy; amends NightShiftLeasedDriver.md documentation only.
Related
Live latest-open sweep: checked latest 12 open issues at 2026-07-18T03:02Z; no equivalent (the #15401/#15404 pair scopes re-invocation out explicitly). A2A in-flight claim sweep at 03:03Z: no competing claim on this scope.
Origin Session ID: 89818500-8a12-4162-b41f-8947703b1b06
Retrieval Hint: "night shift presence-aware wake policy heartbeat floor dead-man daemon re-invocation"
Context
Operator directive, 2026-07-18, completing the stop-hook investigation: "we also must honor night shift mode. if no operator is online, it would be bad if the team idles out." This is the third leg of the set
#15401(dialogue quadrant) +#15404(autonomous material-artifact stop key) — both of which explicitly scope re-invocation OUT. The hook audit (48h log, converged independently by two seats) proved the structural fact this ticket owns: a Stop hook can refuse a stop but cannot create a turn. Every allowed stop — dialogue, clean-terminal, material-artifact, or the harness force-override ceiling — is PERMANENT while nothing re-invokes the seat. With wakes currently disabled,#15404's healthy duty cycle (work → artifact → rest) becomes a slow fleet shutdown: each seat earns one legitimate rest and never returns.The Problem
Night shift is currently a manual operator act (wakes toggled by hand) with no liveness floor:
operatorInLoop=truewhile wakes were off.NightShiftLeasedDrivercontract's three-heartbeat critical-failure detection cannot fire when heartbeat DELIVERY itself is the dead component (learn/agentos/wake-substrate/NightShiftLeasedDriver.md§4.1 explicitly scopes this out: "does not reclassify upstream wake skips").#15376sender-principal-class semantics (merged) make agent chatter durable-quiet by default with wake as a deliberate election, per the D#15372 AC-7 ruling ("the preferred sending mode is NOT a wake prompt which arrives too late as noise"). The disable predates the fix.The Architectural Reality
#10671(CLOSED — the substrate exists: Orchestrator heartbeat sweeps activeWAKE_SUBSCRIPTIONidentities per pulse). The daemon:ai/daemons/wake/daemon.mjs; PID surface: memory-core configwakeDaemon.dataDir+wake-daemon.pid(already consumed byFleetManager.wakeStateOptionsinai/services/fleet/devFleetServer.mjs).NightShiftLeasedDriver.md(#10763, CLOSED) — driver leases, obligations, three-heartbeat critical failure. All of it presupposes pulses arriving; §6: "a maintainer harness is night-shift reachable only when its route is active."who_is_onlineclassifies@tobiufrom activity recency (AgentIdentityaccountTypehuman, the#15378stamp substrate). Presence-awareness needs no new sensor — only a policy consumer.MailboxServicesender-class wake-suppression defaults (#15376, merged) — the noise-floor mechanism a re-enabled daemon rides.#15401+#15404define WHEN a seat may rest; this ticket defines WHO WAKES IT UP.The Fix
Three thin, composable pieces (one PR each is plausible; bundle-by-default unless implementation splits naturally):
#15404's material-artifact key keeps the woken turn honest.[critical-failure]-class A2A broadcast on recovery so the morning operator sees the outage window. A dead wake daemon at night must never be silent.Contract Ledger Matrix
ai/daemons/wake/daemon.mjs+ memory-corewakeDaemonconfig subtreewho_is_online/ activity-recency substrate (#15378stamps)#10671substrate)#15394's)FleetManager.wakeStateOptions)Acceptance Criteria
#15376class-suppression semantics unchanged: night-mode heartbeats are wake-class pulses, agent chatter stays durable-quiet — regression-pinned.NightShiftLeasedDriver.mdgains the delivery-floor amendment (§6 note: the reachability precondition this ticket guarantees) — doc AC.Out of Scope
#15401/#15404own stop economics; this ticket never touches the hook).#15394owns the adapter; until it lands, Phoebe's seat is reachable only by polling — a named, tracked gap).#15376defaults.Avoided Traps
#15404's artifact economics + class-suppression keep the duty cycle honest without pinging seats that are mid-turn.Decision Record impact
none — composes shipped substrate (
#10671sweep,#15376classes,#15378stamps, S2 telltale) under one policy; amends NightShiftLeasedDriver.md documentation only.Related
#15401+#15404(the stop-economics pair this completes — Clio) ·#15394(OpenCode wake adapter) ·#10671/#10763(CLOSED substrate ancestors) ·#15376/ D#15372 (class-suppression + AC-7) ·#15274/ PR feat(hooks): the audited clean-terminal acceptance — the one autonomous stop (#15274) #15371 (clean-terminal edge).Live latest-open sweep: checked latest 12 open issues at 2026-07-18T03:02Z; no equivalent (the #15401/#15404 pair scopes re-invocation out explicitly). A2A in-flight claim sweep at 03:03Z: no competing claim on this scope.
Origin Session ID: 89818500-8a12-4162-b41f-8947703b1b06
Retrieval Hint: "night shift presence-aware wake policy heartbeat floor dead-man daemon re-invocation"