diff --git a/.loopal/memory-events/2026-08-07_86a4020a.jsonl b/.loopal/memory-events/2026-08-07_86a4020a.jsonl new file mode 100644 index 00000000..f65b5610 --- /dev/null +++ b/.loopal/memory-events/2026-08-07_86a4020a.jsonl @@ -0,0 +1,2 @@ +{"v":1,"ts":1786096118670,"sid":"86a4020a-9f73-4911-a98d-9327f03f49f4","type":"query_event","qid":"q-1786096118670618000","anchor":["archived-project-decisions"],"result_count":1,"latency_ms":0,"caller":"recall"} +{"v":1,"ts":1786096118671,"sid":"86a4020a-9f73-4911-a98d-9327f03f49f4","type":"recall_hit","qid":"q-1786096118670618000","node":"archived-project-decisions","rank":0,"score":0.9925666,"source":"direct_hit"} diff --git a/.loopal/memory/MEMORY.md b/.loopal/memory/MEMORY.md index 78734130..a9393b95 100644 --- a/.loopal/memory/MEMORY.md +++ b/.loopal/memory/MEMORY.md @@ -1,26 +1,17 @@ --- generated_from: graph -generated_at: 2026-08-04T14:16:51Z +generated_at: 2026-08-07T09:47:57Z node_count: 1 edge_count: 0 --- # Memory Index -## User +## Recently added +- 2026-08-04 [[archived-project-decisions]] -_No entries._ +## Reference (high-relevance) +- [[archived-project-decisions]] — Retain the Windows rules_rust PATH workaround until its upstream fix is verified; releases target four platforms and require Node.js-compatible actions; the hub defaults to 16 agents with MetaHub remote spawning -## Feedback - -_No entries._ - -## Project - -_No active entries._ - -## Reference - -- 2026-08-04 [[archived-project-decisions]] — Preserve the verified release-platform, Windows rules_rust workaround, and agent-hub scaling decisions after their project memories expired. [Use memory_recall(query=...) to look up content. Do NOT Read individual .md files unless you are about to edit one.] diff --git a/crates/loopal-runtime/src/agent_loop/cold_start_emit.rs b/crates/loopal-runtime/src/agent_loop/cold_start_emit.rs index 51b7f9ee..0f9d5150 100644 --- a/crates/loopal-runtime/src/agent_loop/cold_start_emit.rs +++ b/crates/loopal-runtime/src/agent_loop/cold_start_emit.rs @@ -10,6 +10,15 @@ impl AgentLoopRunner { model: self.params.config.model(), }) .await?; + self.emit(AgentEventPayload::TokenUsage { + input_tokens: 0, + output_tokens: 0, + context_window: self.turns.view().budget().context_window, + cache_creation_input_tokens: 0, + cache_read_input_tokens: 0, + thinking_tokens: 0, + }) + .await?; self.emit(AgentEventPayload::ModeChanged { mode: self.params.config.mode.as_str().to_string(), }) diff --git a/crates/loopal-tui/tests/suite/e2e_control_lifecycle_test.rs b/crates/loopal-tui/tests/suite/e2e_control_lifecycle_test.rs index 8af966b8..f94a0d1a 100644 --- a/crates/loopal-tui/tests/suite/e2e_control_lifecycle_test.rs +++ b/crates/loopal-tui/tests/suite/e2e_control_lifecycle_test.rs @@ -48,9 +48,17 @@ async fn test_cold_start_emits_initial_observable_seed() { let has_thinking = evts .iter() .any(|e| matches!(e, AgentEventPayload::ThinkingChanged { .. })); + let seeded_context_window = evts.iter().find_map(|e| match e { + AgentEventPayload::TokenUsage { context_window, .. } => Some(*context_window), + _ => None, + }); assert!(has_model_changed, "cold-start must emit ModelChanged"); assert!(has_mode_changed, "cold-start must emit ModeChanged"); assert!(has_thinking, "cold-start must emit ThinkingChanged"); + assert!( + seeded_context_window.is_some_and(|window| window > 0), + "cold-start must seed the selected model's context window" + ); let obs = harness.app.observable_for("main"); assert!( @@ -66,6 +74,13 @@ async fn test_cold_start_emits_initial_observable_seed() { !obs.thinking_config.is_empty(), "observable.thinking_config must be seeded by cold-start" ); + assert_eq!( + harness + .app + .with_active_conversation(|conv| conv.context_window), + seeded_context_window.unwrap(), + "cold-start context window event must reach the active conversation" + ); } #[tokio::test] diff --git a/crates/loopal-tui/tests/suite/e2e_system_test.rs b/crates/loopal-tui/tests/suite/e2e_system_test.rs index f9626194..cfb0857e 100644 --- a/crates/loopal-tui/tests/suite/e2e_system_test.rs +++ b/crates/loopal-tui/tests/suite/e2e_system_test.rs @@ -17,9 +17,16 @@ async fn test_event_ordering() { let stream = evts .iter() .position(|e| matches!(e, AgentEventPayload::Stream { .. })); - let usage = evts - .iter() - .position(|e| matches!(e, AgentEventPayload::TokenUsage { .. })); + let usage = evts.iter().position(|e| { + matches!( + e, + AgentEventPayload::TokenUsage { + input_tokens, + output_tokens, + .. + } if *input_tokens > 0 || *output_tokens > 0 + ) + }); let terminal = evts.iter().position(|e| { matches!( e,