diff --git a/poc-memory/src/bin/poc-hook.rs b/poc-memory/src/bin/poc-hook.rs index 4160d5a..ded3777 100644 --- a/poc-memory/src/bin/poc-hook.rs +++ b/poc-memory/src/bin/poc-hook.rs @@ -18,6 +18,16 @@ use std::time::{SystemTime, UNIX_EPOCH}; const CONTEXT_THRESHOLD: u64 = 900_000; const RATE_LIMIT_SECS: u64 = 60; const SOCK_PATH: &str = ".claude/hooks/idle-timer.sock"; +/// How many bytes of new transcript before triggering an observation run. +/// Override with POC_OBSERVATION_THRESHOLD env var. +/// Default: 20KB ≈ 5K tokens. The observation agent's chunk_size (in .agent +/// file) controls how much context it actually reads. +fn observation_threshold() -> u64 { + std::env::var("POC_OBSERVATION_THRESHOLD") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(20_000) +} fn now_secs() -> u64 { SystemTime::now() @@ -73,6 +83,34 @@ fn check_notifications() { } } +/// Check if enough new conversation has accumulated to trigger an observation run. +fn maybe_trigger_observation(transcript: &PathBuf) { + let cursor_file = poc_memory::store::memory_dir().join("observation-cursor"); + + let last_pos: u64 = fs::read_to_string(&cursor_file) + .ok() + .and_then(|s| s.trim().parse().ok()) + .unwrap_or(0); + + let current_size = transcript.metadata() + .map(|m| m.len()) + .unwrap_or(0); + + if current_size > last_pos + observation_threshold() { + // Queue observation via daemon RPC + let _ = Command::new("poc-memory") + .args(["agent", "daemon", "run", "observation", "1"]) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .spawn(); + + eprintln!("[poc-hook] observation triggered ({} new bytes)", current_size - last_pos); + + // Update cursor to current position + let _ = fs::write(&cursor_file, current_size.to_string()); + } +} + fn check_context(transcript: &PathBuf, rate_limit: bool) { if rate_limit { let rate_file = PathBuf::from("/tmp/claude-context-check-last"); @@ -175,6 +213,7 @@ fn main() { if let Some(ref t) = transcript { check_context(t, false); + maybe_trigger_observation(t); } } "PostToolUse" => {