Skip to content

feat(audit): ruvector audit log panel (#3)#5

Open
Tovli wants to merge 3 commits into
shaal:mainfrom
Tovli:feature/add-audit-section
Open

feat(audit): ruvector audit log panel (#3)#5
Tovli wants to merge 3 commits into
shaal:mainfrom
Tovli:feature/add-audit-section

Conversation

@Tovli
Copy link
Copy Markdown

@Tovli Tovli commented May 29, 2026

Closes #3.

Adds a live Audit log that surfaces every interaction the presentation layer has with ruvector — exactly the search / store / vote (+ embed) vocabulary the issue describes — to help people learn the edge API (and, by extension, the server edition that exposes the same verbs).

What you get

A collapsible 📡 ruvector audit log section inside the 🧪 Experiments panel. Each event is one row (op badge · clock · summary · latency) that expands to the raw request payload sent to ruvector. Off by default; enable via the toggle or ?audit=1.

Audit op Bridge call Notes
search recommendSeeds / findSimilarCircuits HNSW k-NN over brains/tracks
store archiveBrain insert into the vector DB
vote observe EMA credit that biases future recall
embed embedTrack CNN → 512-dim track vector

How it works

  • ruvectorBridge.js — an audit tap at the bridge boundary (so it also captures non-main.js callers like cross-tab re-entry). Public API: setAuditEnabled / isAuditEnabled / subscribeAudit / getAuditLog / clearAuditLog, mirroring the existing setFederationCapturer pattern. Bounded ring buffer (200) of {seq,t,op,args,result,raw,ms}. The raw field is the literal request — flattened brain / track / image payloads included — with vectors rendered as head-truncated previews (e.g. Float32Array(512)[0.12, -0.03, …]) so the buffer stays small. No-op (single boolean check) when disabled, so the hot path is byte-identical.
  • uiPanels.js — the audit row in the Experiments disclosure, ?audit=1 preset, and a poll-until-ready wiring that survives a slow sidecar import.
  • style.css — per-op styling for the list.

Design rationale: docs/plan/ruvector-audit-panel.md (ADR-001).

Verification

Driven headlessly against the real WASM bridge: all four ops record and stream to subscribers; raw payloads carry head-truncated brain/track/image previews; the ?audit=1 panel mounts and populates; and the bridge wires up correctly even when it appears ~2.5 s late. No console errors.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an audit log panel to track and display ruvector interactions (search, store, vote, embed) with per-op accents and styles.
    • Audit controls: enable/disable, subscribe/unsubscribe, view/clear the read-only in-memory log, and a lightweight preview of payloads; capped at 200 events.
    • UI: Experiments toggle / ?audit=1 wiring, backfill and live updates, and reuse of cached last recommendation when applicable.
  • Documentation

    • Added ADR documenting the audit panel design and APIs.
  • Bug Fixes

    • Reset now clears cached recommendation to avoid stale audit/state.

Surface every presentation-layer interaction with ruvector — search,
store, vote, embed — in a live, collapsible "Audit log" section of the
Vector Memory panel, each row expandable to the raw request payload.

- ruvectorBridge.js: audit tap behind setAuditEnabled / subscribeAudit /
  getAuditLog / clearAuditLog; bounded ring buffer of
  {seq,t,op,args,result,raw,ms}; raw request includes the flattened
  brain / track / image payloads with head-truncated vector previews.
  Byte-identical hot path when disabled (one boolean check).
- uiPanels.js: 📡 audit-log row in the 🧪 Experiments disclosure; ?audit=1
  preset; poll-until-ready bridge wiring that survives a slow sidecar.
- style.css: per-op styling for the audit list.

Implements ADR-001 (docs/plan/ruvector-audit-panel.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f17c0e8-b65a-4dad-bcc9-f608e72f5d37

📥 Commits

Reviewing files that changed from the base of the PR and between 046fb92 and d07c837.

⛔ Files ignored due to path filters (1)
  • .swarm/memory.db is excluded by !**/*.db
📒 Files selected for processing (6)
  • .swarm/memory.db-shm
  • .swarm/memory.db-wal
  • AI-Car-Racer/ruvectorBridge.js
  • AI-Car-Racer/style.css
  • AI-Car-Racer/uiPanels.js
  • docs/plan/ruvector-audit-panel.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/plan/ruvector-audit-panel.md
  • AI-Car-Racer/uiPanels.js
  • AI-Car-Racer/ruvectorBridge.js

📝 Walkthrough

Walkthrough

Adds an off-by-default audit tap to ruvectorBridge that records presentation-layer interactions (search/store/vote/embed) into a bounded in-memory ring buffer, exposes subscribe/get/clear controls, wraps exported entry points with optional auditing, and adds a collapsible Audit Panel in Experiments with CSS and an ADR.

Changes

Ruvector Audit Panel

Layer / File(s) Summary
Audit Panel Architecture Decision Record
docs/plan/ruvector-audit-panel.md
ADR defining problem, bridge-boundary instrumentation, bounded ring buffer record shape, subscription/log/clear APIs, UI gating (Experiments + ?audit=1), and constraints.
Bridge Audit Infrastructure & Controls
AI-Car-Racer/ruvectorBridge.js
Disabled-by-default audit subsystem with 200-event ring buffer, vector-aware serialization/truncation, exception-shielded subscriber fan-out, audited wrappers for exports (recommendSeeds, findSimilarCircuits, archiveBrain, observe, embedTrack), audit management exports (setAuditEnabled, isAuditEnabled, subscribeAudit, getAuditLog, clearAuditLog), and debug reset clearing of cached last recommendation.
Refactored API Implementations
AI-Car-Racer/ruvectorBridge.js
Extracted internal implementations (recommendSeedsImpl, findSimilarCircuitsImpl, embedTrackImpl, observeImpl) and adjusted exported functions to call impls directly when audit is disabled or to wrap calls with audit recording when enabled.
UI Panel and Experiments Disclosure Integration
AI-Car-Racer/uiPanels.js
Audit panel DOM and rendering (reverse-chronological entries, per-op counters, Clear button), Experiments checkbox/subbody wiring, polling-based bridge wiring that enables audit, backfills via getAuditLog, subscribes for live updates, and tears down/unsubscribes on disable; peekLastRecommendation() usage added to reduce redundant recommendSeeds calls.
Audit Log UI Styling
AI-Car-Racer/style.css
CSS for audit container, header/counts/clear control, scrollable list, per-entry layout, raw log area, and per-op accent color variants.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

  • shaal/VrumVector#2: Both PRs modify the Experiments disclosure UI wiring in AI-Car-Racer/uiPanels.js and related styling; #2 alters the disclosure structure that this PR extends with the audit panel.

Poem

🐰 A little rabbit watched the bridge,

It logged the vectors on the ridge.
A ring of two-hundred whispers kept,
So seekers see what once was swept.
Hop, subscribe — the audit's prepped!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(audit): ruvector audit log panel (#3)' directly and clearly summarizes the main change: adding an audit log panel feature for the ruvector bridge.
Linked Issues check ✅ Passed All coding requirements from issue #3 are met: audit panel surfaces search/store/vote/embed interactions, lists interactions in UI, and exposes raw request payloads for inspection.
Out of Scope Changes check ✅ Passed All changes directly support the audit panel feature: bridge instrumentation, UI rendering, styling, and documentation. The peekLastRecommendation optimization prevents redundant queries—a necessary optimization to avoid inflating audit logs with duplicate operations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AI-Car-Racer/ruvectorBridge.js`:
- Around line 529-584: The audit records are exposed as live objects—fix
_recordAudit, getAuditLog, and subscribeAudit usage so callers never get
references to the internal objects: when creating rec in _recordAudit, push a
shallow-cloned copy (e.g. clone = Object.assign({}, rec) or structuredClone when
available) into _auditLog and iterate _auditSubscribers with a fresh clone for
each fn (so subscribers cannot mutate the stored record); change getAuditLog()
to return an array of clones (e.g. _auditLog.map(r => Object.assign({}, r)))
instead of the stored references; keep using _auditSubscribers and
subscribeAudit unchanged except that subscribers now receive clones.

In `@AI-Car-Racer/style.css`:
- Line 2291: Replace the deprecated CSS declaration "word-break: break-word" in
AI-Car-Racer/style.css with modern wrapping rules: remove "word-break:
break-word;" and add "overflow-wrap: anywhere;" plus a compatible word-break
value such as "word-break: normal;". Update the rule that currently contains
"word-break: break-word" to use "overflow-wrap: anywhere; word-break: normal;"
so linters accept the file and text wrapping behaviour is preserved.

In `@docs/plan/ruvector-audit-panel.md`:
- Around line 91-100: The ADR text claiming the tap is a "no-op when there is no
subscriber" is out of sync with the implementation which appends to _auditLog
whenever _auditEnabled is true; either update the ADR to explicitly state that
_auditLog is recorded while _auditEnabled is true (supporting
late-mount/backfill), or change the implementation so recording to _auditLog
only occurs when there is at least one subscriber (e.g. check subscriber list
before pushing) and keep subscribeAudit/getAuditLog/clearAuditLog behaviour
intact; reference the symbols _auditEnabled, _auditLog, subscribeAudit,
getAuditLog, clearAuditLog, and the existing
_federationCapturer/_crosstabOnReceive semantics when making the edit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3ca65dd7-4aee-496e-a2af-d59c8db5208e

📥 Commits

Reviewing files that changed from the base of the PR and between ea1a317 and 046fb92.

📒 Files selected for processing (4)
  • AI-Car-Racer/ruvectorBridge.js
  • AI-Car-Racer/style.css
  • AI-Car-Racer/uiPanels.js
  • docs/plan/ruvector-audit-panel.md

Comment thread AI-Car-Racer/ruvectorBridge.js
Comment thread AI-Car-Racer/style.css Outdated
Comment thread docs/plan/ruvector-audit-panel.md Outdated
The training loop (main.js buildBrainsBuffer) already runs
recommendSeeds(trackVec, 10) once per generation; the panel's tick was
re-running the identical query just to paint the badge/list, so every
generation logged the search twice.

The bridge now stashes its most-recent result (peekLastRecommendation);
the panel reuses it when the query matches (same trackVec identity + at
least its k) and only issues its own search when the loop hasn't seeded
the current track yet (e.g. a track finalised in phase 3 before training).
_debugReset clears the stash. Verified: one search per generation while a
track trains; the panel still queries for a freshly finalised track.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Tovli
Copy link
Copy Markdown
Author

Tovli commented May 29, 2026

@shaal note that I've also insert a small fix that caused a redundant call to "search" on each new generation

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.

Adding ruvector audit panel

1 participant