Summary
Add a first-class way for a user/entity to temporarily tune heartbeat interruption behavior — both less proactive ("I'm busy, don't bother me until tomorrow morning") and more proactive ("keep suggesting things, I'm open to ideas right now").
The current engine has strong heartbeat decision logic (urgency tiers, cooldowns, nudge backoff, time-period suppression, quiet hours), but there is no explicit per-entity override for short-lived interruption preference.
Problem
Right now heartbeat behavior is shaped by:
- watcher scheduling / adaptive intervals
- urgency tiers and cooldowns
- time-period suppression (
working, evening, late_night, quiet)
- nudge silence thresholds / backoff
- quiet hours and deadline/scheduled bypass rules
That gives good default behavior, but it does not let the user say things like:
- "I'm busy now, don't bother me until tomorrow morning"
- "Pause suggestions for 4 hours"
- "Be more proactive today"
- "Keep suggesting stuff, I want more ideas right now"
These are not exactly the same as quiet hours, and they are not well-modeled as only changing the watcher tick interval. The real product need is a temporary per-entity interruption policy override that influences heartbeat decisions.
Proposed scope
Introduce a persisted per-entity cadence override with expiry.
Override modes
-
Suppress / snooze mode
- reduce or suppress low/normal interruption behavior until a specified time
- examples:
busy
pause_suggestions
snooze_until
-
Proactive mode
- temporarily increase willingness to suggest / nudge / act on non-urgent signals
- examples:
proactive
high_touch
more_ideas
Key design requirements
- override is scoped per entity (not global)
- override is temporary and has an expiry timestamp
- override is evaluated in the heartbeat decision layer, not only in watcher scheduling
- urgent/immediate signals still have a defined breakout path
- behavior is explainable in decision/debug output
- override expiration is automatic
Recommended design direction
Primary control should live in heartbeat decision logic, with watcher cadence changes as an optional secondary optimization.
Why:
- changing only the watcher interval is too coarse
- decision logic already owns interruption semantics (cooldowns, nudge gating, urgency, suppression reasons)
- a per-entity override belongs closer to
evaluateShouldAct / nudge suppression than to process-level scheduling alone
A good first implementation would:
- persist a
cadence override record per entity
- load it during heartbeat evaluation
- modify cooldown / nudge / suggestion behavior based on mode
- preserve urgent break-through behavior for scheduled/deadline/critical cases
- expose the active override in debug/developer-trace surfaces
Suggested behavior
Suppress / snooze
When active:
- suppress low / normal suggestion paths
- likely suppress nudge flow entirely
- optionally suppress elevated signals depending on configuration
- do not suppress immediate/critical signals by default
Examples:
busy until tomorrow 9am
do not bother me for 3 hours
pause suggestions today
Proactive
When active:
- shorten cooldown multipliers
- lower the bar for surfacing suggestions
- make nudge logic more willing during valid time periods
- still respect hard safety/quiet-hour boundaries unless explicitly designed otherwise
Examples:
be more proactive today
keep surfacing ideas this afternoon
I want more nudges right now
Non-goals
- full natural-language parsing in this issue
- replacing quiet hours
- suppressing critical deadline/scheduled signals with no escape hatch
- a permanent learned personality/preference system
- watcher-only interval tuning without decision-layer integration
Likely implementation areas
heartbeat_decide.go
- apply override in
evaluateShouldAct
- integrate with cooldown / suppression / nudge decisions
heartbeat_options.go
- add option plumbing as needed for tests / API path
watcher.go
- optional secondary optimization if per-entity cadence should influence scheduling
storage/*
- persist active cadence override with expiry
cmd/keyoku-server/handlers*.go
- API surface for set/get/clear override
- debug / trace response types
- expose active override in developer-facing diagnostics
Open design questions
- Should
busy/snooze suppress only low/normal, or also elevated?
- Should proactive mode adjust only cooldowns, or also time-period suppression / nudge thresholds?
- Should the initial API be explicit/structured (recommended), with natural-language mapping handled elsewhere?
- Should watcher scheduling eventually become entity-aware, or is decision-layer control sufficient for v1?
Acceptance criteria
- Can set a per-entity cadence override with an expiry
- Can clear / inspect the current override
- Heartbeat decision logic changes behavior while override is active
- Immediate/critical signals still break through according to documented rules
- Override expires automatically and behavior returns to normal
- Debug/developer-trace output makes the active override visible
- Tests cover:
- suppressive mode reducing interruptions
- proactive mode increasing willingness to surface suggestions
- expiry behavior
- urgent breakout behavior
Notes
This feels adjacent to heartbeat reflection / personalization work, but it is narrower and operationally useful on its own: it gives users a direct, temporary control over how interruptive Keyoku should be without forcing them to reconfigure global watcher defaults.
Summary
Add a first-class way for a user/entity to temporarily tune heartbeat interruption behavior — both less proactive ("I'm busy, don't bother me until tomorrow morning") and more proactive ("keep suggesting things, I'm open to ideas right now").
The current engine has strong heartbeat decision logic (urgency tiers, cooldowns, nudge backoff, time-period suppression, quiet hours), but there is no explicit per-entity override for short-lived interruption preference.
Problem
Right now heartbeat behavior is shaped by:
working,evening,late_night,quiet)That gives good default behavior, but it does not let the user say things like:
These are not exactly the same as quiet hours, and they are not well-modeled as only changing the watcher tick interval. The real product need is a temporary per-entity interruption policy override that influences heartbeat decisions.
Proposed scope
Introduce a persisted per-entity cadence override with expiry.
Override modes
Suppress / snooze mode
busypause_suggestionssnooze_untilProactive mode
proactivehigh_touchmore_ideasKey design requirements
Recommended design direction
Primary control should live in heartbeat decision logic, with watcher cadence changes as an optional secondary optimization.
Why:
evaluateShouldAct/ nudge suppression than to process-level scheduling aloneA good first implementation would:
cadence overriderecord per entitySuggested behavior
Suppress / snooze
When active:
Examples:
busy until tomorrow 9amdo not bother me for 3 hourspause suggestions todayProactive
When active:
Examples:
be more proactive todaykeep surfacing ideas this afternoonI want more nudges right nowNon-goals
Likely implementation areas
heartbeat_decide.goevaluateShouldActheartbeat_options.gowatcher.gostorage/*cmd/keyoku-server/handlers*.goOpen design questions
busy/snoozesuppress onlylow/normal, or alsoelevated?Acceptance criteria
Notes
This feels adjacent to heartbeat reflection / personalization work, but it is narrower and operationally useful on its own: it gives users a direct, temporary control over how interruptive Keyoku should be without forcing them to reconfigure global watcher defaults.