Add engine recent-activity ring buffer ([C3] / #26) - #59
Merged
Conversation
Spikes are broadcast on a tokio `broadcast` channel that only delivers to currently-subscribed receivers. The agent harness needs to ask "what spiked recently?" without holding a WS subscription open, and the read-only `recent_spikes` tool ([B2] / #15) is built directly on this seam. The buffer lives inside the engine actor task (single-owner, no lock), is bounded by capacity, and is written from every site that produces spikes — the tick loop, `ForceSpike`, and `run_engine_for`. Capacity defaults to 8 192 events and can be overridden via `HEBB_RECENT_ACTIVITY_CAPACITY` so an operator can resize without recompiling; a bad value logs a warning and falls back to the default rather than failing boot. New surface: - `core::engine::recent_activity::RecentActivityBuffer` — bounded ring with chronological-order reads, `since_t_ms` time filter, and zero-limit short-circuit. - `EngineCommand::RecentSpikes { limit, since_t_ms, reply }`. - `SimHandle::recent_spikes(limit, since_t_ms)` — async accessor consumed by the upcoming agent tool ([B2] / #15). Voltage and arbitrary domain-event history are deliberately out of scope here: sampling vs. event-driven semantics warrant separate sibling buffers in this module, which is why the type is named `RecentActivityBuffer` rather than `SpikeBuffer`.
Cover the read path end-to-end against a live `SimHandle`: - A `ForceSpike` with no broadcast subscriber still lands in the buffer and is visible via `recent_spikes`. This is the agent-tool shape — the harness will call `recent_spikes` without keeping a WS receiver alive. - `since_t_ms` filters by engine clock, so callers can ask "anything after the last cursor I saw" cheaply. `run_for` advances the clock between two forced spikes and the midpoint cutoff drops the older event.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #26.
Summary
Bounded ring buffer of recent spike events held inside the engine actor task, with
EngineCommand::RecentSpikes+SimHandle::recent_spikes(limit, since_t_ms)for read access. Unblocks the read-onlyrecent_spikesagent tool ([B2] / #15) — that tool can land directly on this seam instead of subscribing to the spike broadcast.Why
Spikes are broadcast on a tokio
broadcastchannel that only delivers to currently-subscribed receivers. The agent harness needs to ask "what spiked recently?" without holding a WS subscription open — the channel can't answer that. A bounded ring buffer in the actor is the cheapest place to keep the answer.Design
core::engine::recent_activity::RecentActivityBuffer— boundedVecDeque<SpikeEvent>with chronological-order reads, optionalsince_t_mstime filter, oldest-first eviction.Mutex/RwLock. Same shape as every other introspection path.HEBB_RECENT_ACTIVITY_CAPACITY. A bad value logs a warning and falls back to the default rather than failing boot.ForceSpike, andrun_engine_for.RecentActivityBuffer, notSpikeBuffer, so the module can grow.Commits
Add engine recent-activity ring buffer ([C3] / #26)— type + actor wiring + env-var capacity + unit tests on the buffer.Add engine actor tests for recent_spikes ([C3] / #26)— integration tests through a liveSimHandle.Test plan
cargo test -p core engine::— 23 passed (21 existing + 2 new actor-level tests).cargo test -p core recent_activity— 7 buffer unit tests pass.cargo test -p core— 101 passed, 1 ignored (the existing Gemini live smoke).Generated by Claude Code