Build EventContext with runtime state and client-exposed capabilities. Session stats are always populated from AHP's observed runtime state so harnesses can make advisory decisions without a separate in-core advisor. Memory summary and current task are populated if set via setter methods.
(&self)
| 758 | /// harnesses can make advisory decisions without a separate in-core advisor. |
| 759 | /// Memory summary and current task are populated if set via setter methods. |
| 760 | fn build_context(&self) -> Option<a3s_ahp::EventContext> { |
| 761 | let snapshot = self.runtime_snapshot(); |
| 762 | |
| 763 | // Build session stats from tracked data |
| 764 | let session_stats = SessionStats { |
| 765 | total_actions: snapshot.total_events_processed as usize, |
| 766 | total_tokens: snapshot.tokens_used, |
| 767 | duration_ms: snapshot.uptime_ms, |
| 768 | error_count: snapshot.error_count, |
| 769 | }; |
| 770 | |
| 771 | // Get optional memory summary |
| 772 | let memory_summary = read_or_recover(&self.memory_summary).clone(); |
| 773 | |
| 774 | // Get optional current task |
| 775 | let current_task = read_or_recover(&self.current_task).clone(); |
| 776 | |
| 777 | // Get recent facts |
| 778 | let recent_facts = read_or_recover(&self.recent_facts).clone(); |
| 779 | |
| 780 | let capabilities = if self.capabilities.is_empty() { |
| 781 | None |
| 782 | } else { |
| 783 | Some(self.capabilities.clone()) |
| 784 | }; |
| 785 | |
| 786 | Some(a3s_ahp::EventContext { |
| 787 | recent_facts: (!recent_facts.is_empty()).then_some(recent_facts), |
| 788 | memory_summary, |
| 789 | session_stats: Some(session_stats), |
| 790 | current_task, |
| 791 | capabilities, |
| 792 | }) |
| 793 | } |
| 794 | |
| 795 | /// Map AHP decision to hook result based on event type. |
| 796 | fn map_decision( |
no test coverage detected