idle: EWMA activity tracking
Track activity level as an EWMA (exponentially weighted moving average) driven by turn duration. Long turns (engaged work) produce large boosts; short turns (bored responses) barely register. Asymmetric time constants: 60s boost half-life for fast wake-up, 5-minute decay half-life for gradual wind-down. Self-limiting boost formula converges toward 0.75 target — can't overshoot. - Add activity_ewma, turn_start, last_nudge to persisted state - Boost on handle_response proportional to turn duration - Decay on every tick and state transition - Fix kent_present: self-nudge responses (fired=true) don't update last_user_msg, so kent_present stays false during autonomous mode - Nudge only when Kent is away, minimum 15s between nudges - CLI: `poc-daemon ewma [VALUE]` to query or set - Status output shows activity percentage
This commit is contained in:
parent
7ea7c78a35
commit
22a9fdabdb
4 changed files with 157 additions and 24 deletions
|
|
@ -104,6 +104,11 @@ enum Command {
|
|||
DreamEnd,
|
||||
/// Force state persistence to disk
|
||||
Save,
|
||||
/// Get or set the activity EWMA (0.0-1.0). No value = query.
|
||||
Ewma {
|
||||
/// Value to set (omit to query)
|
||||
value: Option<f64>,
|
||||
},
|
||||
/// Dump full internal state as JSON
|
||||
Debug,
|
||||
/// Shut down daemon
|
||||
|
|
@ -202,9 +207,10 @@ async fn client_main(cmd: Command) -> Result<(), Box<dyn std::error::Error>> {
|
|||
fmt_secs(s.get_since_activity()),
|
||||
fmt_secs(s.get_notify_timeout()),
|
||||
);
|
||||
println!("kent: {} (last {})",
|
||||
println!("kent: {} (last {}) activity: {:.1}%",
|
||||
if s.get_kent_present() { "present" } else { "away" },
|
||||
fmt_secs(s.get_since_user()),
|
||||
s.get_activity_ewma() * 100.0,
|
||||
);
|
||||
|
||||
let sleep = s.get_sleep_until();
|
||||
|
|
@ -271,6 +277,13 @@ async fn client_main(cmd: Command) -> Result<(), Box<dyn std::error::Error>> {
|
|||
daemon.save_request().send().promise.await?;
|
||||
println!("state saved");
|
||||
}
|
||||
Command::Ewma { value } => {
|
||||
let mut req = daemon.ewma_request();
|
||||
req.get().set_value(value.unwrap_or(-1.0));
|
||||
let reply = req.send().promise.await?;
|
||||
let current = reply.get()?.get_current();
|
||||
println!("{:.1}%", current * 100.0);
|
||||
}
|
||||
Command::Debug => {
|
||||
let reply = daemon.debug_request().send().promise.await?;
|
||||
let json = reply.get()?.get_json()?.to_str()?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue