Skip to content

Add engine recent-activity ring buffer ([C3] / #26) - #59

Merged
ammar-s847 merged 2 commits into
mainfrom
claude/hebb-issues-prs-FQagq-c3-ring-buffer
May 28, 2026
Merged

Add engine recent-activity ring buffer ([C3] / #26)#59
ammar-s847 merged 2 commits into
mainfrom
claude/hebb-issues-prs-FQagq-c3-ring-buffer

Conversation

@ammar-s847

Copy link
Copy Markdown
Contributor

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-only recent_spikes agent 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 broadcast channel 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 — bounded VecDeque<SpikeEvent> with chronological-order reads, optional since_t_ms time filter, oldest-first eviction.
  • Held inside the engine actor task — single-owner, no Mutex / RwLock. Same shape as every other introspection path.
  • Capacity defaults to 8 192 events (~196 KB) and can be overridden via HEBB_RECENT_ACTIVITY_CAPACITY. A bad value logs a warning and falls back to the default rather than failing boot.
  • Written from every site that produces spikes: the tick loop, ForceSpike, and run_engine_for.
  • Voltage / arbitrary domain-event history are deliberately out of scope here — those warrant their own sibling buffers (sampling vs. event-driven). The type is named RecentActivityBuffer, not SpikeBuffer, so the module can grow.

Commits

  1. Add engine recent-activity ring buffer ([C3] / #26) — type + actor wiring + env-var capacity + unit tests on the buffer.
  2. Add engine actor tests for recent_spikes ([C3] / #26) — integration tests through a live SimHandle.

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

claude added 2 commits May 28, 2026 03:20
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.
@ammar-s847
ammar-s847 merged commit da4b3e1 into main May 28, 2026
2 checks passed
@ammar-s847
ammar-s847 deleted the claude/hebb-issues-prs-FQagq-c3-ring-buffer branch May 28, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[C3] Engine recent-activity ring buffer

2 participants