feat(audit): ruvector audit log panel (#3)#5
Conversation
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>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds 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. ChangesRuvector Audit Panel
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (4)
AI-Car-Racer/ruvectorBridge.jsAI-Car-Racer/style.cssAI-Car-Racer/uiPanels.jsdocs/plan/ruvector-audit-panel.md
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>
|
@shaal note that I've also insert a small fix that caused a redundant call to "search" on each new generation |
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.recommendSeeds/findSimilarCircuitsarchiveBrainobserveembedTrackHow it works
ruvectorBridge.js— an audit tap at the bridge boundary (so it also captures non-main.jscallers like cross-tab re-entry). Public API:setAuditEnabled/isAuditEnabled/subscribeAudit/getAuditLog/clearAuditLog, mirroring the existingsetFederationCapturerpattern. Bounded ring buffer (200) of{seq,t,op,args,result,raw,ms}. Therawfield 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=1preset, 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=1panel 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
Documentation
Bug Fixes