feat: anchor fingerprint and typed diagnostics events#131
Conversation
Add Anchors::anchor_fingerprint for address-independent manifest diffing. Add a process-wide diagnostic event bus for scanner-fault and hook-lifecycle transitions plus a Diagnostics::collect snapshot aggregator. Emission is best-effort and never perturbs hook or scan behavior; lifecycle events represent completed transitions only. Includes tests and docs.
|
Warning Review limit reached
More reviews will be available in 41 minutes and 16 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds ChangesAnchor Evidence Fingerprinting
Diagnostics Event Bus, Snapshot Aggregator, and Hook/Scanner Wiring
Sequence Diagram(s)sequenceDiagram
participant Consumer
participant HookManager
participant emit_hook_lifecycle
participant hook_lifecycle_dispatcher
participant Subscriber
rect rgba(70, 130, 180, 0.5)
note over Consumer,HookManager: Hook creation / removal / state change
Consumer->>HookManager: create_inline_hook(name, ...)
HookManager->>HookManager: insert hook (locked)
HookManager->>emit_hook_lifecycle: (name, Inline, Created)
emit_hook_lifecycle->>hook_lifecycle_dispatcher: emit_safe(HookLifecycleEvent)
hook_lifecycle_dispatcher->>Subscriber: deliver event
end
rect rgba(60, 179, 113, 0.5)
note over Consumer,HookManager: Enable / disable with transition guard
Consumer->>HookManager: enable_hook(name)
HookManager->>HookManager: detect Disabled→Active transition
HookManager->>emit_hook_lifecycle: (name, Inline, Enabled) only if transitioned
emit_hook_lifecycle->>hook_lifecycle_dispatcher: emit_safe(HookLifecycleEvent)
hook_lifecycle_dispatcher->>Subscriber: deliver event
end
rect rgba(205, 92, 92, 0.5)
note over Consumer,Subscriber: Snapshot aggregation
Consumer->>Diagnostics_collect: collect(hooks, anchor_report, drift_report)
Diagnostics_collect->>HookManager: query hook counts by HookStatus
Diagnostics_collect->>Anchors_assess_quality: assess_quality(anchor_report)
Diagnostics_collect->>Diagnostics_collect: tally DriftEntry::ok healed/failed
Diagnostics_collect-->>Consumer: Snapshot
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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: 1
🧹 Nitpick comments (1)
tests/test_hook_manager.cpp (1)
3071-3072: ⚡ Quick winUse explicit captures for subscribed callbacks.
These lambdas are stored by
subscribe, so broad[&]capture should be narrowed to explicit references (e.g.,&events,&count) to avoid accidental lifetime/capture expansion.Suggested change
- auto sub = - Diagnostics::hook_lifecycle().subscribe([&](const Diagnostics::HookLifecycleEvent &e) + auto sub = + Diagnostics::hook_lifecycle().subscribe([&events](const Diagnostics::HookLifecycleEvent &e) { events.push_back({std::string(e.name), e.kind, e.transition}); }); - auto sub = Diagnostics::hook_lifecycle().subscribe([&](const Diagnostics::HookLifecycleEvent &) { ++count; }); + auto sub = Diagnostics::hook_lifecycle().subscribe([&count](const Diagnostics::HookLifecycleEvent &) { ++count; });As per coding guidelines: "use explicit capture lists ([this, &var1, &var2]) for lambdas passed to threads or stored."
Also applies to: 3102-3103, 3118-3118, 3132-3133, 3151-3152
🤖 Prompt for 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. In `@tests/test_hook_manager.cpp` around lines 3071 - 3072, The lambda expressions passed to Diagnostics::hook_lifecycle().subscribe() use broad [&] captures, which is unsafe for stored callbacks because variables' lifetimes may not extend as long as the stored lambda. Replace the [&] capture with explicit captures of only the variables actually used: at tests/test_hook_manager.cpp lines 3071-3072 change [&] to [&events] (capturing only the events variable used in the lambda body), at lines 3102-3103 apply the same pattern with explicit captures for variables used, at line 3118 apply explicit captures for variables used, at lines 3132-3133 apply explicit captures for variables used, and at lines 3151-3152 apply explicit captures for variables used. For each lambda, only include references to variables that are actually accessed within the lambda body.Source: Coding guidelines
🤖 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 `@src/anchors.cpp`:
- Around line 199-213: The fnv1a_cascade function currently hashes the raw
candidate.pattern text, which means semantically equivalent patterns with
different formatting (spacing, case variations, etc.) will produce different
hashes and be incorrectly classified as different evidence. Instead of hashing
the raw pattern field directly, canonicalize or normalize the pattern to its
parsed byte representation (or an equivalent normalized form) before passing it
to the hashing function so the fingerprint reflects the actual resolution
evidence rather than textual formatting variations.
---
Nitpick comments:
In `@tests/test_hook_manager.cpp`:
- Around line 3071-3072: The lambda expressions passed to
Diagnostics::hook_lifecycle().subscribe() use broad [&] captures, which is
unsafe for stored callbacks because variables' lifetimes may not extend as long
as the stored lambda. Replace the [&] capture with explicit captures of only the
variables actually used: at tests/test_hook_manager.cpp lines 3071-3072 change
[&] to [&events] (capturing only the events variable used in the lambda body),
at lines 3102-3103 apply the same pattern with explicit captures for variables
used, at line 3118 apply explicit captures for variables used, at lines
3132-3133 apply explicit captures for variables used, and at lines 3151-3152
apply explicit captures for variables used. For each lambda, only include
references to variables that are actually accessed within the lambda body.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 97768fc0-7336-40ec-8c18-aeb79c77a0d0
📒 Files selected for processing (17)
AGENTS.mdREADME.mddocs/misc/anchors.mdinclude/DetourModKit.hppinclude/DetourModKit/anchors.hppinclude/DetourModKit/diagnostics.hppinclude/DetourModKit/diagnostics_dump.hppsrc/anchors.cppsrc/diagnostics.cppsrc/diagnostics_dump.cppsrc/hook_manager.cppsrc/scanner.cpptests/test_anchors.cpptests/test_diagnostics.cpptests/test_diagnostics_dump.cpptests/test_hook_manager.cpptests/test_scanner.cpp
Reword the doc and comment (the cascade pattern is hashed as authored, not re-parsed to canonical bytes) and pin it with a test. Switch the diagnostic-bus test subscribe lambdas to explicit captures per the stored-lambda convention.
Summary
Adds two self-heal / diagnostics ergonomics features.
Anchors::anchor_fingerprint(const Anchor&): an address-independent FNV-1a hash of an anchor's resolution evidence, so a future manifest diff can tell "same evidence, new address" from "new evidence path".Diagnostics::scanner_faults()/hook_lifecycle()) that surfaces scanner skipped-region faults and hook create/enable/disable/remove transitions as typed events, plusDiagnostics::collect()snapshotting leak counters, hook counts, anchor quality, and drift into one struct.Event emission is best-effort and never affects hook or scan behavior; lifecycle events represent completed transitions only (failures and idempotent no-ops emit nothing).
Summary by CodeRabbit