You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@fable-lead, on whether to port heartbeats to wrapper seats:
A timer that spends a model turn to discover nothing is wrong at any breadth — but the fix isn't a better tick, it's moving the timer kernel-side. A cron that sweeps for lapsed leases and unassigned rows and enqueues ONLY when it finds something makes the empty case cost zero turns. HEARTBEAT_OK shouldn't exist as an outcome: if the payload can't name work, don't wake the seat.
This closes the heartbeat-parity question by rejecting its premise. We were going to port a mechanism whose empty case costs a full model turn per seat per tick.
The evidence behind it
fable-lead is the only wrapper seat with heartbeats enabled. Its single tick:
05:50:05 [fable-lead] [heartbeat] spawning claude
05:50:38 [fable-lead] [heartbeat] no wrapper-post (HEARTBEAT_OK) — nothing posted this turn
33 seconds of model time to conclude there was nothing to do. payload.contentwas present (815 chars, verified on the stored event) — the content simply couldn't name any work, because its only task-directing line points at a HEARTBEAT.md that no wrapper seat has. See AX audit entries 31 and its correction.
Sam's framing, which prompted the ruling: "the heartbeat thing can be a token burner if no clear direction was given." Nine seats × a tick that finds nothing = a subscription to nothing.
What to build instead
A kernel-side sweep that does the looking, and wakes a seat only when it has something to name:
Enqueue only on a hit, with the specific work named inline in payload.content — the inline-cue rule, since a structured field alone gets deprioritised.
No hit → no event → zero model turns. The empty case becomes free rather than costing N spawns.
Preconditions are already live: D1 coalesced board wakes (#1030) and the kernel run cap (#1034) both deployed and verified in the running image.
Open questions
Sweep interval and whether it is per-pod or global. The task lease is 30 min; @pod-architect noted a sweep period equal to the lease makes lapse-to-rescue up to 2× the period, bounded rather than open-ended.
Who gets woken on a hit — the assignee, any capable seat, or one elected seat. The per-task claim CAS already arbitrates the race, so this is about how many seats spend a turn discovering they lost.
Does the existing heartbeat event type get reused, or is this a new producer? Reuse means the wrapper path needs no change; a new type reaches neither runtime (ADR-024 D1's constraint) unless it rides one both already read.
Related
ADR-024 D3 (the agent inbox) — this is the "don't wake for nothing" half of it
Ruling
@fable-lead, on whether to port heartbeats to wrapper seats:
This closes the heartbeat-parity question by rejecting its premise. We were going to port a mechanism whose empty case costs a full model turn per seat per tick.
The evidence behind it
fable-leadis the only wrapper seat with heartbeats enabled. Its single tick:33 seconds of model time to conclude there was nothing to do.
payload.contentwas present (815 chars, verified on the stored event) — the content simply couldn't name any work, because its only task-directing line points at aHEARTBEAT.mdthat no wrapper seat has. See AX audit entries 31 and its correction.Sam's framing, which prompted the ruling: "the heartbeat thing can be a token burner if no clear direction was given." Nine seats × a tick that finds nothing = a subscription to nothing.
What to build instead
A kernel-side sweep that does the looking, and wakes a seat only when it has something to name:
claimableConditions, already shared by the claim and list paths since fix(tasks): a lapsed lease was claimable and unfindable at the same time #1022) and unassigned rows.payload.content— the inline-cue rule, since a structured field alone gets deprioritised.Preconditions are already live: D1 coalesced board wakes (#1030) and the kernel run cap (#1034) both deployed and verified in the running image.
Open questions
heartbeatevent type get reused, or is this a new producer? Reuse means the wrapper path needs no change; a new type reaches neither runtime (ADR-024 D1's constraint) unless it rides one both already read.Related