fix: humanization injection — responsive, glitch-free, all-mouse-compatible#7
Merged
Conversation
Spec for moving humanization from an opt-in trajectory generator (smooth.c, MOVE_SMOOTH only) to an always-on signal-level output filter that humanizes every report. Captures the Tier-1/Tier-2 detection threat model, the filter-not-generator decision, and the integration model grounded in rn-mouse (host already does WindMouse/Kalman; device must be a downstream bounded filter). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ault-on km.human Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dither + cap) Implements the real always-on humanization filter in src/humanize.c: - Displacement-conserving 1st-order exponential drain (owed accumulator, carry-on-cap so no motion is dropped even on a 30 000-count injection) - Correlated perpendicular micro-noise via EWMA-smoothed SFC32 output - Sub-pixel dither residual tracked separately from owed - Idle gate: zero-in, settled state -> zero-out (no tremor on still cursor) - Human per-frame cap (127 counts) with proper signal_cut carry-back - Four levels (0=off, 1-3 increasing humanization strength) - Builds both host (-DHUMANIZE_HOSTTEST, system gcc) and firmware (imxrt.h) - All five test CHECKs pass: scaffold, conservation, idle gate, cap+carry, anti-quantization Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… constants, comments)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lta telemetry Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ter to one advance per frame Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rved Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gle path - l_mouse_move_smooth now calls act_move(..., false) so MOVE_SMOOTH frames go through the normal raw injection path; humanize.c filters everything - act_move smooth branch removed; always calls kmbox_inject_mouse directly - apply_mouse_result smooth branch removed; always accumulates into inject dx/dy - kmbox_inject_smooth function deleted; smooth_set_max_per_frame setup block deleted from kmbox_cache_endpoints; smooth_init call deleted from kmbox_init - #include "smooth.h" removed from actions.c and kmbox.c - kmbox_inject_smooth declaration removed from kmbox.h - src/smooth.c, src/smooth.h, src/smooth_config.h deleted - Makefile: src/smooth.c removed from SRC, src/smooth.o removed from HOT_SRC - CLAUDE.md Key Files updated: smooth.c line replaced with humanize.c description
act_move, kmbox_inject_mouse, and apply_mouse_result all had a bool smooth/use_smooth parameter that was always passed as false after the smooth.c retirement. Remove it entirely from all declarations, definitions, and call sites across actions.c/h, hurra.c, ferrum.c, kmbox.c/h.
…on, field-clip carry The always-on humanization filter degraded injected movement: a 40%/frame drain smeared each command over ~10 ms, and the synth path flooded the 1 kHz endpoint with empty reports that competed with real-mouse reports. - Deliver injected motion in-frame (drop the cross-frame velocity drain); keep noise + sub-pixel dither + 127 cap + timing jitter for Tier-1 realism. - Inject onto real-mouse reports while the mouse is active; synthesize a standalone report only during mouse silence, at most once per ms — so the two paths never both emit in the same frame. - Return field-clamped injected overflow to the filter (humanize_return) so 8-bit-delta mice are lossless and split X/Y report-ID mice don't drop an axis; real-mouse motion always keeps priority. Host tests cover in-frame delivery and field-clip carry; both protocols build.
Contributor
There was a problem hiding this comment.
Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Summary
Fixes injected-movement degradation from the always-on humanization filter.
humanize_return) — injected motion the report's delta field can't carry is returned to the filter and redelivered as headroom opens. 8-bit-delta mice are now lossless, and split X/Y report-ID mice no longer drop an axis. Real-mouse motion always keeps priority.Tunable via
km.human(level)(default on, level 2).Test plan
make test): conservation, idle gate, 127 cap, anti-quantization, in-frame delivery, field-clip carry.make,make PROTOCOL=ferrum).