InboxWakePolicy class final
The idle inbox-wake lane policy (gh-1180).
The hosts' idle inbox watchers (CLI, app) start a turn when mail arrives while idle. Two protections share that gate:
- the agent-chatter anti-storm cap: at most maxStreak consecutive wakes without user input, so two chatty instances cannot ping-pong forever;
- the user-input guarantee: mail of kind AgentMessageKind.user IS the user talking and must always wake — its delivery resets the streak, so gating it on the counter would deadlock (no run → no reset → no run).
gh-1180 adds the missing third lane: a delivered schedule_message
self-reminder ([scheduled] prefix, from == to == the recipient's
own mailbox) is a DELIBERATE, agent-chosen cadence — a night watch,
a periodic sweep, a delayed follow-up — not chatter. It is EXEMPT
from the cap so a self-chain wakes forever, with one guard: wakes
arriving faster than scheduledSelfCadenceFloor are a busy-spin
disguised as self-scheduling (a zero-delay re-schedule loop) and
count against the ordinary cap, bounding the storm exactly like
foreign chatter.
Constructors
- InboxWakePolicy({int maxStreak = defaultMaxInboxWakeStreak, Duration scheduledSelfCadenceFloor = defaultScheduledSelfCadenceFloor, DateTime clock()?})
Properties
- clock → DateTime Function()?
-
Injectable clock (tests); null uses DateTime.now.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- maxStreak → int
-
Consecutive chatter wakes allowed without user input.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- scheduledSelfCadenceFloor ↔ Duration
-
Minimum spacing between two EXEMPT scheduled-self wakes; anything
faster counts against the cap. Mutable so a host test can collapse
it (zero: every self wake exempt) or exercise the spin guard.
getter/setter pair
- streak ↔ int
-
Consecutive inbox-triggered wakes without user input.
getter/setter pair
Methods
-
announceRefusal(
) → bool - Whether THIS call may announce the current refusal: true exactly once per refusal episode. An episode opens on the first refusal and closes when the gate reopens — a user-input reset (resetStreak) or any allowed cap-consuming (non-exempt) wake. Hosts gate their visible refusal line AND their refusal receipts on this: the gate holds until user input arrives, so per-tick announcements would append ~43k duplicate lines/day to the receipt trail (review: the wake_attempted spam) and spam the terminal.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
resetStreak(
) → void - A delivered user-kind message (or a typed line) IS the user talking. Ends the refusal episode too (see announceRefusal): the two pieces of episode state live side by side so they cannot drift apart.
-
toString(
) → String -
A string representation of this object.
inherited
-
wakeDecisionFor(
List< AgentMessage> pending, {bool pluginPending = false}) → InboxWakeDecision - Decides — and books — the wake for one pending batch. Call only when mail is pending and the host is idle; a refused decision leaves the counters untouched, so the next tick retries under the same rules.
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Methods
-
isScheduledSelfMail(
AgentMessage message) → bool -
Whether
messageis the delivery of a scheduled self-reminder: the scheduler's[scheduled]prefix addressed from the recipient's own mailbox (from == to). Foreign chatter cannot produce the shape by accident — itsfromIdis the sender's mailbox, never mine.
Constants
- defaultMaxInboxWakeStreak → const int
-
The anti-storm cap for foreign agent-to-agent chatter (unchanged
behavior — the old
_maxInboxWakeStreak). - defaultScheduledSelfCadenceFloor → const Duration
- Wakes closer together than this are a spin, not a cadence (gh-1180 E5): the exemption must not open a busy-spin.