clearcote 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/humanize.d.ts +3 -0
- package/dist/humanize.d.ts.map +1 -1
- package/dist/humanize.js +71 -46
- package/dist/humanize.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/motion.d.ts +106 -0
- package/dist/motion.d.ts.map +1 -0
- package/dist/motion.js +311 -0
- package/dist/motion.js.map +1 -0
- package/dist/motionscore.d.ts +57 -0
- package/dist/motionscore.d.ts.map +1 -0
- package/dist/motionscore.js +215 -0
- package/dist/motionscore.js.map +1 -0
- package/dist/release.js +9 -9
- package/package.json +1 -1
package/dist/motion.js
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
// Human motion core — the trajectory/timing model shared by every humanized input path.
|
|
2
|
+
//
|
|
3
|
+
// PURE (no Playwright, no I/O): given a start point, a target, and a seeded `Persona`, it returns a
|
|
4
|
+
// list of `Step`s (absolute cursor coordinates + a post-step sleep). The wrapper (humanize.ts)
|
|
5
|
+
// walks the steps with the engine's NATIVE mouse.move + an off-protocol sleep, so the whole path is
|
|
6
|
+
// trusted input. Keeping the math here (a) unifies Node/Python so they can't drift, (b) makes it
|
|
7
|
+
// unit-testable offline, and (c) lets motionscore.ts score generated paths without a browser.
|
|
8
|
+
//
|
|
9
|
+
// Model — why these choices (mapped to what behavioral collectors actually measure):
|
|
10
|
+
// • Minimum-jerk submovements. A human reach is a primary ballistic submovement plus 1–2 corrective
|
|
11
|
+
// ones (Meyer's optimized-submovement model), each following the minimum-jerk profile
|
|
12
|
+
// s(τ)=10τ³−15τ⁴+6τ⁵ (speed 30τ²(1−τ)², peaking at τ=0.5). Composing them yields the mid-path
|
|
13
|
+
// velocity peak, the decelerating Fitts homing phase, and natural overshoot→correction reversals —
|
|
14
|
+
// none of which a single ease curve produces. (A single bezier peaks at the wrong place and has
|
|
15
|
+
// exactly one submovement — a structural tell.)
|
|
16
|
+
// • Fitts's law duration. Movement time = a + b·log2(D/W+1), not ∝ distance, so duration is
|
|
17
|
+
// statistically human across short-big vs long-small targets (a distribution detectors check).
|
|
18
|
+
// • Colored noise. Sub-pixel jitter = slow Ornstein–Uhlenbeck drift + a band-limited 8–12 Hz
|
|
19
|
+
// physiological tremor, not flat white gauss (whose flat spectrum is itself detectable).
|
|
20
|
+
// • Seeded persona. One motor signature (mean speed, tremor, overshoot, handedness bias, cadence)
|
|
21
|
+
// is drawn per identity from the fingerprint seed, so behavior is consistent WITHIN a session and
|
|
22
|
+
// unlinkable across seeds — the same coherence model as the rest of the persona.
|
|
23
|
+
// • Endpoint dwells. Grab hesitation after mouse.down and a pre-release settle before mouse.up (the
|
|
24
|
+
// two worst slider tells: real ~130–360 ms grab / ~90–230 ms release vs a scripted few ms).
|
|
25
|
+
//
|
|
26
|
+
// NOTE on the 2/3 power law: it governs continuous CURVED drawing, not discrete point-to-point
|
|
27
|
+
// reaches, so imposing it on a reach would corrupt the min-jerk profile. We deliberately do NOT apply
|
|
28
|
+
// it during generation; motionscore.ts reports power-law residual only as a diagnostic.
|
|
29
|
+
export function mulberry32(seedInt) {
|
|
30
|
+
let a = seedInt >>> 0;
|
|
31
|
+
return () => {
|
|
32
|
+
a = (a + 0x6d2b79f5) | 0;
|
|
33
|
+
let t = Math.imul(a ^ (a >>> 15), 1 | a);
|
|
34
|
+
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
35
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** FNV-1a hash of an arbitrary seed (string or number) to a 32-bit int for the persona RNG. */
|
|
39
|
+
export function hashSeed(seed) {
|
|
40
|
+
if (seed === undefined || seed === null)
|
|
41
|
+
return (Math.random() * 0xffffffff) >>> 0;
|
|
42
|
+
if (typeof seed === "number" && Number.isFinite(seed))
|
|
43
|
+
return (Math.abs(seed) * 2654435761) >>> 0;
|
|
44
|
+
const s = String(seed);
|
|
45
|
+
let h = 0x811c9dc5;
|
|
46
|
+
for (let i = 0; i < s.length; i++) {
|
|
47
|
+
h ^= s.charCodeAt(i);
|
|
48
|
+
h = Math.imul(h, 0x01000193);
|
|
49
|
+
}
|
|
50
|
+
return h >>> 0;
|
|
51
|
+
}
|
|
52
|
+
/** Standard-normal sample (Box–Muller) from a given RNG. */
|
|
53
|
+
export function gaussFrom(rng) {
|
|
54
|
+
let u = 0, v = 0;
|
|
55
|
+
while (u === 0)
|
|
56
|
+
u = rng();
|
|
57
|
+
while (v === 0)
|
|
58
|
+
v = rng();
|
|
59
|
+
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
|
|
60
|
+
}
|
|
61
|
+
const lerp = (a, b, t) => a + (b - a) * t;
|
|
62
|
+
/** Derive a stable motor persona from a fingerprint seed (or random when unseeded). */
|
|
63
|
+
export function makePersona(seed) {
|
|
64
|
+
const seedInt = hashSeed(seed);
|
|
65
|
+
const r = mulberry32(seedInt);
|
|
66
|
+
return {
|
|
67
|
+
seed: seedInt,
|
|
68
|
+
deviceHz: Math.round(lerp(110, 155, r())),
|
|
69
|
+
tremorHz: lerp(8, 12, r()),
|
|
70
|
+
tremorAmp: lerp(0.12, 0.5, r()),
|
|
71
|
+
driftAmp: lerp(0.1, 0.4, r()),
|
|
72
|
+
driftTau: lerp(60, 160, r()),
|
|
73
|
+
jitter: lerp(0.25, 0.7, r()),
|
|
74
|
+
fittsA: lerp(90, 150, r()),
|
|
75
|
+
fittsB: lerp(120, 190, r()),
|
|
76
|
+
primaryFrac: lerp(0.84, 0.94, r()),
|
|
77
|
+
overshoot: lerp(0.03, 0.08, r()),
|
|
78
|
+
maxCorrections: r() < 0.15 ? 3 : r() < 0.6 ? 2 : 1,
|
|
79
|
+
approachBias: (r() - 0.5) * 0.5,
|
|
80
|
+
grabMinMs: 130,
|
|
81
|
+
grabMaxMs: 360,
|
|
82
|
+
releaseMinMs: 90,
|
|
83
|
+
releaseMaxMs: 230,
|
|
84
|
+
clickHoldMinMs: 60,
|
|
85
|
+
clickHoldMaxMs: 150,
|
|
86
|
+
keyDwellMinMs: 45,
|
|
87
|
+
keyDwellMaxMs: 120,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/** A human mousedown→mouseup click hold (ms), right-skewed (most clicks brief, some linger). Fixes
|
|
91
|
+
* the ~2 ms instant-press tell shared by clicks. */
|
|
92
|
+
export function clickHold(p, rng = Math.random) {
|
|
93
|
+
return p.clickHoldMinMs + Math.min(1, Math.abs(gaussFrom(rng)) * 0.5) * (p.clickHoldMaxMs - p.clickHoldMinMs);
|
|
94
|
+
}
|
|
95
|
+
/** A human per-key keydown→keyup dwell (ms), right-skewed (a floor + occasional longer holds — the
|
|
96
|
+
* empirical human dwell shape). Fixes the ~2–3 ms instant-keystroke tell. */
|
|
97
|
+
export function keyDwell(p, rng = Math.random) {
|
|
98
|
+
return p.keyDwellMinMs + Math.min(1, Math.abs(gaussFrom(rng)) * 0.45) * (p.keyDwellMaxMs - p.keyDwellMinMs);
|
|
99
|
+
}
|
|
100
|
+
const log2 = (x) => Math.log(x) / Math.LN2;
|
|
101
|
+
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
102
|
+
/** Cubic bezier point at parameter e (0..1). */
|
|
103
|
+
function bez(p0, c1, c2, p1, e) {
|
|
104
|
+
const m = 1 - e;
|
|
105
|
+
return m * m * m * p0 + 3 * m * m * e * c1 + 3 * m * e * e * c2 + e * e * e * p1;
|
|
106
|
+
}
|
|
107
|
+
/** Minimum-jerk easing s(τ)=10τ³−15τ⁴+6τ⁵ (position fraction; speed 30τ²(1−τ)²). */
|
|
108
|
+
export function minJerk(tau) {
|
|
109
|
+
const t = clamp(tau, 0, 1);
|
|
110
|
+
return t * t * t * (10 + t * (-15 + 6 * t));
|
|
111
|
+
}
|
|
112
|
+
/** Sample ONE min-jerk submovement a→b along a slightly bowed path, adding colored noise. Appends to
|
|
113
|
+
* `out`. `t0` is the absolute clock (ms) at the start (for tremor phase continuity). Returns the
|
|
114
|
+
* absolute clock at the end. `land` = put the final sample exactly on b with no noise. */
|
|
115
|
+
function sampleSubmove(out, a, b, durMs, p, rng, t0, drift, jit, tremorPhase, land) {
|
|
116
|
+
const dx = b.x - a.x, dy = b.y - a.y;
|
|
117
|
+
const dist = Math.hypot(dx, dy) || 1e-6;
|
|
118
|
+
const stepMs = 1000 / p.deviceHz;
|
|
119
|
+
// Cap the sample count so a very long move can't emit thousands of steps (defends the Fitts cap).
|
|
120
|
+
const n = Math.min(180, Math.max(4, Math.round(durMs / stepMs)));
|
|
121
|
+
// perpendicular unit for the path bow; sign follows the persona's handedness bias
|
|
122
|
+
const nx = -dy / dist, ny = dx / dist;
|
|
123
|
+
const bowSign = p.approachBias >= 0 ? 1 : -1;
|
|
124
|
+
const bow = bowSign * (0.04 + Math.abs(gaussFrom(rng)) * 0.05) * Math.min(dist, 260) * (0.5 + Math.abs(p.approachBias));
|
|
125
|
+
const c1x = a.x + dx * 0.33 + nx * bow, c1y = a.y + dy * 0.33 + ny * bow;
|
|
126
|
+
const c2x = a.x + dx * 0.66 + nx * bow, c2y = a.y + dy * 0.66 + ny * bow;
|
|
127
|
+
let t = t0;
|
|
128
|
+
for (let i = 1; i <= n; i++) {
|
|
129
|
+
const e = minJerk(i / n);
|
|
130
|
+
let px = bez(a.x, c1x, c2x, b.x, e);
|
|
131
|
+
let py = bez(a.y, c1y, c2y, b.y, e);
|
|
132
|
+
const last = i === n;
|
|
133
|
+
if (!(last && land)) {
|
|
134
|
+
// Ornstein–Uhlenbeck drift (colored, low-frequency)
|
|
135
|
+
const k = stepMs / p.driftTau;
|
|
136
|
+
drift.x += -k * drift.x + Math.sqrt(2 * k) * p.driftAmp * gaussFrom(rng);
|
|
137
|
+
drift.y += -k * drift.y + Math.sqrt(2 * k) * p.driftAmp * gaussFrom(rng);
|
|
138
|
+
// 8–12 Hz physiological tremor: absolute-clock phase (continuous across submovements), a slow
|
|
139
|
+
// amplitude "breathing", and a slightly DETUNED/phase-offset y axis — real tremor is not a
|
|
140
|
+
// fixed-amplitude tone locked in exact 90° quadrature.
|
|
141
|
+
const tAmp = p.tremorAmp * (0.7 + 0.3 * Math.sin((2 * Math.PI * t) / 850 + tremorPhase));
|
|
142
|
+
const trX = tAmp * Math.sin(tremorPhase + (2 * Math.PI * p.tremorHz * t) / 1000);
|
|
143
|
+
const trY = tAmp * Math.sin(tremorPhase + 1.0 + (2 * Math.PI * (p.tremorHz * 0.93) * t) / 1000);
|
|
144
|
+
// Sub-pixel jitter as a COLORED AR(1) process, not i.i.d. white noise — white noise adds a fresh
|
|
145
|
+
// speed reversal every sample, manufacturing spurious "submovements" and a flat noise spectrum.
|
|
146
|
+
jit.x = 0.7 * jit.x + gaussFrom(rng) * p.jitter * 0.22;
|
|
147
|
+
jit.y = 0.7 * jit.y + gaussFrom(rng) * p.jitter * 0.22;
|
|
148
|
+
px += drift.x + trX + jit.x;
|
|
149
|
+
py += drift.y + trY + jit.y;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
px = b.x;
|
|
153
|
+
py = b.y;
|
|
154
|
+
}
|
|
155
|
+
// device sampling is quite regular (a sharp cadence mode); keep per-sample jitter small so the
|
|
156
|
+
// dt distribution has a mode, unlike a rand(a,b) band. Pauses come from the inter-submovement gap.
|
|
157
|
+
const sleepMs = stepMs * lerp(0.88, 1.12, rng());
|
|
158
|
+
out.push({ x: px, y: py, sleepMs });
|
|
159
|
+
t += sleepMs;
|
|
160
|
+
}
|
|
161
|
+
return t;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Plan a free cursor move `from`→`to` as a sum of minimum-jerk submovements (primary + corrections)
|
|
165
|
+
* with Fitts-scaled duration and colored noise. Returns the samples to dispatch.
|
|
166
|
+
*/
|
|
167
|
+
export function planMove(from, to, p, opts = {}) {
|
|
168
|
+
const rng = opts.rng ?? Math.random;
|
|
169
|
+
const W = Math.max(6, opts.targetW ?? 24);
|
|
170
|
+
const D = Math.hypot(to.x - from.x, to.y - from.y);
|
|
171
|
+
const out = [];
|
|
172
|
+
if (D < 1.5) {
|
|
173
|
+
out.push({ x: to.x, y: to.y, sleepMs: 1000 / p.deviceHz });
|
|
174
|
+
return out;
|
|
175
|
+
}
|
|
176
|
+
// Fitts movement time (ms) + a little log-normal-ish noise; short hops get a small floor. The floor
|
|
177
|
+
// is itself capped at the 1700 ms ceiling so a very long move can't invert the clamp (lo > hi) and
|
|
178
|
+
// silently blow past the cap.
|
|
179
|
+
const id = log2(D / W + 1);
|
|
180
|
+
const mtLo = Math.min(1700, Math.max(70, 40 + D * 0.6));
|
|
181
|
+
const mt = clamp((p.fittsA + p.fittsB * id) * (0.85 + 0.3 * rng()), mtLo, 1700);
|
|
182
|
+
// Submovement targets: primary lands near `to` with a small over/undershoot; corrections close the
|
|
183
|
+
// residual error, each covering ~55–80% of what's left.
|
|
184
|
+
const targets = [];
|
|
185
|
+
if (D >= 40) {
|
|
186
|
+
const f = p.primaryFrac;
|
|
187
|
+
const spread = Math.min(16, D * p.overshoot);
|
|
188
|
+
targets.push({
|
|
189
|
+
x: from.x + (to.x - from.x) * f + gaussFrom(rng) * spread,
|
|
190
|
+
y: from.y + (to.y - from.y) * f + gaussFrom(rng) * spread,
|
|
191
|
+
});
|
|
192
|
+
// 1 correction usually, occasionally 2 (a 3rd is rare) — keeps the corrective-submovement count
|
|
193
|
+
// in the human 1–3 band rather than over-generating homing bumps.
|
|
194
|
+
const nCorr = rng() < 0.08 * p.maxCorrections ? 2 : 1;
|
|
195
|
+
let cur = targets[0];
|
|
196
|
+
for (let i = 0; i < nCorr; i++) {
|
|
197
|
+
const close = lerp(0.55, 0.8, rng());
|
|
198
|
+
const nx = { x: cur.x + (to.x - cur.x) * close, y: cur.y + (to.y - cur.y) * close };
|
|
199
|
+
// tiny lateral error so corrections aren't perfectly collinear
|
|
200
|
+
nx.x += gaussFrom(rng) * 1.2;
|
|
201
|
+
nx.y += gaussFrom(rng) * 1.2;
|
|
202
|
+
targets.push(nx);
|
|
203
|
+
cur = nx;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
targets.push({ x: to.x, y: to.y });
|
|
207
|
+
// Allocate MT: primary ~62%, remaining split across corrections (each shorter).
|
|
208
|
+
const segDur = [];
|
|
209
|
+
if (targets.length === 1) {
|
|
210
|
+
segDur.push(mt);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Primary gets ~78% of the time (min-jerk peaks at its own mid-point ⇒ global peak lands ~0.35–0.4,
|
|
214
|
+
// the human sweet spot slightly before the whole-gesture midpoint), corrections share the rest.
|
|
215
|
+
segDur.push(mt * 0.78);
|
|
216
|
+
const rest = mt * 0.22;
|
|
217
|
+
const nc = targets.length - 1;
|
|
218
|
+
for (let i = 0; i < nc; i++)
|
|
219
|
+
segDur.push((rest / nc) * lerp(0.8, 1.2, rng()));
|
|
220
|
+
}
|
|
221
|
+
const drift = { x: 0, y: 0 };
|
|
222
|
+
const jit = { x: 0, y: 0 };
|
|
223
|
+
const tremorPhase = rng() * 2 * Math.PI;
|
|
224
|
+
let a = from, t = 0;
|
|
225
|
+
for (let s = 0; s < targets.length; s++) {
|
|
226
|
+
const b = targets[s];
|
|
227
|
+
const last = s === targets.length - 1;
|
|
228
|
+
t = sampleSubmove(out, a, b, Math.max(20, segDur[s]), p, rng, t, drift, jit, tremorPhase, last && !opts.settle);
|
|
229
|
+
if (!last && out.length)
|
|
230
|
+
out[out.length - 1].sleepMs += lerp(40, 120, rng()); // motor re-planning gap
|
|
231
|
+
a = b;
|
|
232
|
+
}
|
|
233
|
+
if (opts.settle) {
|
|
234
|
+
// A couple of tiny sub-pixel seating jiggles, then land exactly (slider handle "clunk" into place).
|
|
235
|
+
const jig = 1 + Math.floor(rng() * 2);
|
|
236
|
+
for (let i = 0; i < jig; i++) {
|
|
237
|
+
out.push({ x: to.x + gaussFrom(rng) * 1.4, y: to.y + gaussFrom(rng) * 1.4, sleepMs: lerp(30, 90, rng()) });
|
|
238
|
+
}
|
|
239
|
+
out.push({ x: to.x, y: to.y, sleepMs: 1000 / p.deviceHz });
|
|
240
|
+
}
|
|
241
|
+
return out;
|
|
242
|
+
}
|
|
243
|
+
/** Grab/release dwell times (ms) for a held-button drag, drawn from the persona window. */
|
|
244
|
+
export function dragDwell(p, rng = Math.random) {
|
|
245
|
+
return {
|
|
246
|
+
grabMs: lerp(p.grabMinMs, p.grabMaxMs, rng()),
|
|
247
|
+
releaseMs: lerp(p.releaseMinMs, p.releaseMaxMs, rng()),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/** A human click point inside `box`: a 2D gaussian around center, nudged toward the approach side
|
|
251
|
+
* (people undershoot toward where the cursor came from), clamped a couple px inside the edges. */
|
|
252
|
+
export function clickPoint(box, from, p, rng = Math.random) {
|
|
253
|
+
const cx = box.x + box.width / 2, cy = box.y + box.height / 2;
|
|
254
|
+
const dx = cx - from.x, dy = cy - from.y;
|
|
255
|
+
const d = Math.hypot(dx, dy) || 1;
|
|
256
|
+
// undershoot bias: pull ~12% of the half-width back toward the approach direction
|
|
257
|
+
const ux = -dx / d, uy = -dy / d;
|
|
258
|
+
const bx = ux * box.width * 0.12, by = uy * box.height * 0.12;
|
|
259
|
+
const x = cx + bx + gaussFrom(rng) * box.width * 0.16;
|
|
260
|
+
const y = cy + by + gaussFrom(rng) * box.height * 0.16;
|
|
261
|
+
// For a box narrower/shorter than the 4 px inset the clamp bounds would invert (lo > hi) and return
|
|
262
|
+
// a point OUTSIDE the element — just use the center for such tiny targets.
|
|
263
|
+
return {
|
|
264
|
+
x: box.width >= 4 ? clamp(x, box.x + 2, box.x + box.width - 2) : cx,
|
|
265
|
+
y: box.height >= 4 ? clamp(y, box.y + 2, box.y + box.height - 2) : cy,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Plan ambient / pre-challenge cursor activity: idle drift + a few non-goal moves within the viewport,
|
|
270
|
+
* so a behavioral collector sees non-zero pointer entropy BEFORE the first goal action (the single
|
|
271
|
+
* biggest reason a challenge/slider is shown to headless automation). Returns ~`ms` of samples.
|
|
272
|
+
*/
|
|
273
|
+
export function planAmbient(from, vp, p, ms, rng = Math.random) {
|
|
274
|
+
const out = [];
|
|
275
|
+
let cur = from;
|
|
276
|
+
let elapsed = 0;
|
|
277
|
+
const budget = Math.max(200, ms);
|
|
278
|
+
// keep motion inside a comfortable central band (people don't fling the cursor to the extremes)
|
|
279
|
+
const bx0 = vp.width * 0.12, bx1 = vp.width * 0.88;
|
|
280
|
+
const by0 = vp.height * 0.14, by1 = vp.height * 0.8;
|
|
281
|
+
while (elapsed < budget && out.length < 4000) {
|
|
282
|
+
const target = { x: lerp(bx0, bx1, rng()), y: lerp(by0, by1, rng()) };
|
|
283
|
+
const seg = planMove(cur, target, p, { targetW: 80, rng });
|
|
284
|
+
for (const s of seg) {
|
|
285
|
+
out.push(s);
|
|
286
|
+
elapsed += s.sleepMs;
|
|
287
|
+
}
|
|
288
|
+
// rest with a little drift between excursions (hand idling on the mouse)
|
|
289
|
+
const restMs = lerp(120, 600, rng());
|
|
290
|
+
const drift = { x: 0, y: 0 };
|
|
291
|
+
const stepMs = 1000 / p.deviceHz;
|
|
292
|
+
let held = 0;
|
|
293
|
+
const tphase = rng() * 2 * Math.PI;
|
|
294
|
+
while (held < restMs) {
|
|
295
|
+
const k = stepMs / p.driftTau;
|
|
296
|
+
drift.x += -k * drift.x + Math.sqrt(2 * k) * p.driftAmp * gaussFrom(rng);
|
|
297
|
+
drift.y += -k * drift.y + Math.sqrt(2 * k) * p.driftAmp * gaussFrom(rng);
|
|
298
|
+
const ph = tphase + (2 * Math.PI * p.tremorHz * held) / 1000;
|
|
299
|
+
out.push({
|
|
300
|
+
x: target.x + drift.x + p.tremorAmp * Math.sin(ph),
|
|
301
|
+
y: target.y + drift.y + p.tremorAmp * Math.sin(ph + Math.PI / 2),
|
|
302
|
+
sleepMs: stepMs * lerp(0.9, 1.4, rng()),
|
|
303
|
+
});
|
|
304
|
+
held += stepMs;
|
|
305
|
+
elapsed += stepMs;
|
|
306
|
+
}
|
|
307
|
+
cur = target;
|
|
308
|
+
}
|
|
309
|
+
return out;
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=motion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motion.js","sourceRoot":"","sources":["../src/motion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export interface Sample {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
t: number;
|
|
5
|
+
buttons?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface MotionFeatures {
|
|
8
|
+
n: number;
|
|
9
|
+
durationMs: number;
|
|
10
|
+
/** Fraction of the movement at which peak speed occurs. Human ≈ 0.3–0.45 (fast ballistic rise, slow
|
|
11
|
+
* homing). A single analytic ease curve is SYMMETRIC (peak ≈ 0.5); pure ease-out peaks ≈ 0.15. */
|
|
12
|
+
peakVelFrac: number;
|
|
13
|
+
/** Time-weighted skewness of the speed profile. Human > 0 (long decelerating homing tail); a
|
|
14
|
+
* symmetric single-curve motion ≈ 0. */
|
|
15
|
+
velSkew: number;
|
|
16
|
+
/** Corrective submovements = prominent interior speed minima (human 1–3; a single curve = 0). */
|
|
17
|
+
submovements: number;
|
|
18
|
+
/** Net displacement / path length (1 = perfectly straight). */
|
|
19
|
+
straightness: number;
|
|
20
|
+
/** Diagnostic only (NOT scored): residual of the whole speed profile vs a SINGLE min-jerk bell.
|
|
21
|
+
* A real multi-submovement reach does not fit one bell, so this is high for human motion too. */
|
|
22
|
+
minJerkResidual: number;
|
|
23
|
+
/** Inter-sample dt mean / std (ms) and a uniformity flag (i.i.d.-uniform dt is a tell). */
|
|
24
|
+
dtMeanMs: number;
|
|
25
|
+
dtStdMs: number;
|
|
26
|
+
dtUniform: boolean;
|
|
27
|
+
/** Lag-1 autocorrelation of the sub-pixel jitter residual. White noise ≈ 0; colored motor noise
|
|
28
|
+
* (1/f drift + 8–12 Hz tremor) ≈ 0.2–0.8. */
|
|
29
|
+
jitterAutocorr: number;
|
|
30
|
+
/** 2/3 power-law fit quality (diagnostic only — not generated): correlation of log speed vs
|
|
31
|
+
* −1/3·log curvature. ~0 for straight paths (undefined curvature); informative on curved ones. */
|
|
32
|
+
powerLawR: number;
|
|
33
|
+
/** Drag endpoint timing (only when a held-button segment is present), else null. */
|
|
34
|
+
grabMs: number | null;
|
|
35
|
+
releaseMs: number | null;
|
|
36
|
+
}
|
|
37
|
+
export declare function extractFeatures(s: Sample[]): MotionFeatures;
|
|
38
|
+
export interface MotionScore {
|
|
39
|
+
score: number;
|
|
40
|
+
flags: string[];
|
|
41
|
+
features: MotionFeatures;
|
|
42
|
+
}
|
|
43
|
+
/** Score 0..1 (higher = more human) with human-readable flags for the tells that fire. */
|
|
44
|
+
export declare function scoreMotion(s: Sample[], opts?: {
|
|
45
|
+
drag?: boolean;
|
|
46
|
+
}): MotionScore;
|
|
47
|
+
/** Turn a Step list (absolute coords + post-step sleep) into timestamped Samples for scoring.
|
|
48
|
+
* `buttonsDuring` marks the held-button (drag) span [startIdx, endIdx) with buttons=1. */
|
|
49
|
+
export declare function stepsToSamples(steps: {
|
|
50
|
+
x: number;
|
|
51
|
+
y: number;
|
|
52
|
+
sleepMs: number;
|
|
53
|
+
}[], buttonsDuring?: {
|
|
54
|
+
start: number;
|
|
55
|
+
end: number;
|
|
56
|
+
}): Sample[];
|
|
57
|
+
//# sourceMappingURL=motionscore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motionscore.d.ts","sourceRoot":"","sources":["../src/motionscore.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,MAAM;IAAG,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAAE;AAE9E,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB;sGACkG;IAClG,WAAW,EAAE,MAAM,CAAC;IACpB;4CACwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB;qGACiG;IACjG,eAAe,EAAE,MAAM,CAAC;IACxB,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB;iDAC6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB;sGACkG;IAClG,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AA8BD,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,cAAc,CAwH3D;AAED,MAAM,WAAW,WAAW;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAC;CAAE;AAE1F,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,WAAW,CA8BnF;AAED;0FAC0F;AAC1F,wBAAgB,cAAc,CAC5B,KAAK,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,EAClD,aAAa,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC7C,MAAM,EAAE,CASV"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Detector-emulator — extracts the feature vector a behavioral collector (DataDome/PerimeterX-class)
|
|
2
|
+
// would compute from a pointer stream and scores how human it looks. This is a VALIDATION tool: it
|
|
3
|
+
// lets us prove, offline and deterministically, that the motion core (motion.ts) improves the features
|
|
4
|
+
// that matter, instead of eyeballing trajectories or burning scarce clean-IP end-to-end runs.
|
|
5
|
+
//
|
|
6
|
+
// It is intentionally an APPROXIMATION of what real collectors do (their exact models are private);
|
|
7
|
+
// treat the score as a relative signal (old vs new), not an absolute pass/fail.
|
|
8
|
+
function speeds(s) {
|
|
9
|
+
const v = [], tMid = [];
|
|
10
|
+
for (let i = 1; i < s.length; i++) {
|
|
11
|
+
const dt = Math.max(1e-3, s[i].t - s[i - 1].t);
|
|
12
|
+
v.push(Math.hypot(s[i].x - s[i - 1].x, s[i].y - s[i - 1].y) / dt);
|
|
13
|
+
tMid.push((s[i].t + s[i - 1].t) / 2);
|
|
14
|
+
}
|
|
15
|
+
return { v, tMid };
|
|
16
|
+
}
|
|
17
|
+
/** Smooth a series with a small moving average (window w). */
|
|
18
|
+
function smooth(a, w = 3) {
|
|
19
|
+
const out = [];
|
|
20
|
+
for (let i = 0; i < a.length; i++) {
|
|
21
|
+
let s = 0, c = 0;
|
|
22
|
+
for (let j = Math.max(0, i - w); j <= Math.min(a.length - 1, i + w); j++) {
|
|
23
|
+
s += a[j];
|
|
24
|
+
c++;
|
|
25
|
+
}
|
|
26
|
+
out.push(s / c);
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function mean(a) { return a.length ? a.reduce((x, y) => x + y, 0) / a.length : 0; }
|
|
31
|
+
function std(a) {
|
|
32
|
+
if (a.length < 2)
|
|
33
|
+
return 0;
|
|
34
|
+
const m = mean(a);
|
|
35
|
+
return Math.sqrt(mean(a.map((x) => (x - m) ** 2)));
|
|
36
|
+
}
|
|
37
|
+
export function extractFeatures(s) {
|
|
38
|
+
const n = s.length;
|
|
39
|
+
const durationMs = n > 1 ? s[n - 1].t - s[0].t : 0;
|
|
40
|
+
const { v, tMid } = speeds(s);
|
|
41
|
+
const sv = smooth(v, 2);
|
|
42
|
+
// peak velocity position
|
|
43
|
+
let peakIdx = 0;
|
|
44
|
+
for (let i = 1; i < sv.length; i++)
|
|
45
|
+
if (sv[i] > sv[peakIdx])
|
|
46
|
+
peakIdx = i;
|
|
47
|
+
const peakVelFrac = durationMs > 0 ? (tMid[peakIdx] - s[0].t) / durationMs : 0;
|
|
48
|
+
// velocity skewness (positive for a human's fast-rise/slow-decay profile; ~0 for a symmetric curve)
|
|
49
|
+
const vmean = mean(sv), vstd = std(sv) || 1e-9;
|
|
50
|
+
const velSkew = mean(sv.map((x) => ((x - vmean) / vstd) ** 3));
|
|
51
|
+
// corrective submovements: prominent interior local minima (a real dip that recovers), not jitter.
|
|
52
|
+
// Require the min to sit below 0.5·vmax and be a true valley between two higher shoulders, with a
|
|
53
|
+
// minimum index separation so a single correction isn't counted several times.
|
|
54
|
+
const vmax = Math.max(...sv, 1e-9);
|
|
55
|
+
let submovements = 0, lastMin = -10;
|
|
56
|
+
for (let i = 2; i < sv.length - 2; i++) {
|
|
57
|
+
const valley = sv[i] < sv[i - 1] && sv[i] <= sv[i + 1] && sv[i] < sv[i - 2] && sv[i] < sv[i + 2];
|
|
58
|
+
if (valley && sv[i] < 0.5 * vmax && i - lastMin >= 3) {
|
|
59
|
+
submovements++;
|
|
60
|
+
lastMin = i;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// straightness
|
|
64
|
+
let pathLen = 0;
|
|
65
|
+
for (let i = 1; i < n; i++)
|
|
66
|
+
pathLen += Math.hypot(s[i].x - s[i - 1].x, s[i].y - s[i - 1].y);
|
|
67
|
+
const netDisp = n > 1 ? Math.hypot(s[n - 1].x - s[0].x, s[n - 1].y - s[0].y) : 0;
|
|
68
|
+
const straightness = pathLen > 1e-6 ? netDisp / pathLen : 1;
|
|
69
|
+
// min-jerk residual: compare the normalized speed profile to 30τ²(1−τ)²
|
|
70
|
+
let minJerkResidual = 1;
|
|
71
|
+
if (sv.length >= 4 && durationMs > 0) {
|
|
72
|
+
const area = sv.reduce((acc, val, i) => acc + val * (i === 0 ? 0 : tMid[i] - tMid[i - 1]), 0) || 1;
|
|
73
|
+
let res = 0, norm = 0;
|
|
74
|
+
for (let i = 0; i < sv.length; i++) {
|
|
75
|
+
const tau = (tMid[i] - s[0].t) / durationMs;
|
|
76
|
+
const ideal = 30 * tau * tau * (1 - tau) * (1 - tau); // ∫ over τ = 1
|
|
77
|
+
const obs = (sv[i] * durationMs) / area; // normalize so ∫ obs dτ ≈ 1
|
|
78
|
+
res += (obs - ideal) ** 2;
|
|
79
|
+
norm += ideal ** 2;
|
|
80
|
+
}
|
|
81
|
+
minJerkResidual = norm > 0 ? Math.sqrt(res / norm) : 1;
|
|
82
|
+
}
|
|
83
|
+
// dt stats + uniformity (uniform-i.i.d. dt has std/mean near that of U(a,b) and low autocorrelation)
|
|
84
|
+
const dts = [];
|
|
85
|
+
for (let i = 1; i < n; i++)
|
|
86
|
+
dts.push(s[i].t - s[i - 1].t);
|
|
87
|
+
const dtMeanMs = mean(dts), dtStdMs = std(dts);
|
|
88
|
+
// A real device stream has a sharp cadence MODE (most samples near the median) with a heavy tail of
|
|
89
|
+
// pauses; a rand(a,b) band has NO mode (roughly flat), so few samples cluster near the median.
|
|
90
|
+
// Measure the fraction within ±20% of the median: high ⇒ has a mode; low ⇒ looks uniform/flat.
|
|
91
|
+
const sorted = [...dts].sort((a, b) => a - b);
|
|
92
|
+
const median = sorted.length ? sorted[Math.floor(sorted.length / 2)] : 0;
|
|
93
|
+
const coreFrac = median > 0 ? dts.filter((d) => d >= 0.8 * median && d <= 1.2 * median).length / dts.length : 0;
|
|
94
|
+
const dtUniform = coreFrac < 0.5;
|
|
95
|
+
// jitter color: lag-1 autocorrelation of the sub-pixel residual (position minus a smoothed trend).
|
|
96
|
+
// White gauss ≈ 0; colored motor noise (slow drift + band-limited tremor) ≈ 0.2–0.8.
|
|
97
|
+
let jitterAutocorr = 0;
|
|
98
|
+
if (n >= 8) {
|
|
99
|
+
const xs = s.map((p) => p.x), ys = s.map((p) => p.y);
|
|
100
|
+
const sx = smooth(xs, 3), sy = smooth(ys, 3);
|
|
101
|
+
const rx = xs.map((x, i) => x - sx[i]), ry = ys.map((y, i) => y - sy[i]);
|
|
102
|
+
const ac = (r) => {
|
|
103
|
+
let num = 0, den = 0;
|
|
104
|
+
for (let i = 1; i < r.length; i++)
|
|
105
|
+
num += r[i] * r[i - 1];
|
|
106
|
+
for (let i = 0; i < r.length; i++)
|
|
107
|
+
den += r[i] * r[i];
|
|
108
|
+
return den > 1e-9 ? num / den : 0;
|
|
109
|
+
};
|
|
110
|
+
jitterAutocorr = (ac(rx) + ac(ry)) / 2;
|
|
111
|
+
}
|
|
112
|
+
// 2/3 power law (diagnostic): correlation between log speed and −(1/3) log curvature
|
|
113
|
+
let powerLawR = 0;
|
|
114
|
+
if (n >= 6) {
|
|
115
|
+
const lv = [], lc = [];
|
|
116
|
+
for (let i = 1; i < n - 1; i++) {
|
|
117
|
+
const ax = s[i].x - s[i - 1].x, ay = s[i].y - s[i - 1].y;
|
|
118
|
+
const bx = s[i + 1].x - s[i].x, by = s[i + 1].y - s[i].y;
|
|
119
|
+
const cross = Math.abs(ax * by - ay * bx);
|
|
120
|
+
const segA = Math.hypot(ax, ay), segB = Math.hypot(bx, by);
|
|
121
|
+
const curv = cross / (Math.pow(segA * segB * Math.hypot(bx + ax, by + ay), 1) + 1e-9);
|
|
122
|
+
const sp = (segA + segB) / 2 / Math.max(1e-3, (s[i + 1].t - s[i - 1].t) / 2);
|
|
123
|
+
if (curv > 1e-6 && sp > 1e-6) {
|
|
124
|
+
lv.push(Math.log(sp));
|
|
125
|
+
lc.push(Math.log(curv));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (lv.length >= 4) {
|
|
129
|
+
const mv = mean(lv), mc = mean(lc);
|
|
130
|
+
let num = 0, dv = 0, dc = 0;
|
|
131
|
+
for (let i = 0; i < lv.length; i++) {
|
|
132
|
+
num += (lv[i] - mv) * (lc[i] - mc);
|
|
133
|
+
dv += (lv[i] - mv) ** 2;
|
|
134
|
+
dc += (lc[i] - mc) ** 2;
|
|
135
|
+
}
|
|
136
|
+
powerLawR = dv > 0 && dc > 0 ? num / Math.sqrt(dv * dc) : 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// drag endpoint timing: within the buttons==1 (held) segment. The `up` is the first sample AFTER
|
|
140
|
+
// the held span (buttons back to 0); grab = down→first-movement, release = last-movement→up.
|
|
141
|
+
let grabMs = null, releaseMs = null;
|
|
142
|
+
const heldIdx = [];
|
|
143
|
+
for (let i = 0; i < n; i++)
|
|
144
|
+
if ((s[i].buttons ?? 0) & 1)
|
|
145
|
+
heldIdx.push(i);
|
|
146
|
+
if (heldIdx.length) {
|
|
147
|
+
const d0 = heldIdx[0];
|
|
148
|
+
let firstMoveT = s[d0].t;
|
|
149
|
+
for (const i of heldIdx) {
|
|
150
|
+
if (Math.hypot(s[i].x - s[d0].x, s[i].y - s[d0].y) > 1) {
|
|
151
|
+
firstMoveT = s[i].t;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
grabMs = firstMoveT - s[d0].t;
|
|
156
|
+
let lastMoveIdx = d0;
|
|
157
|
+
for (let k = 1; k < heldIdx.length; k++) {
|
|
158
|
+
const i = heldIdx[k], j = heldIdx[k - 1];
|
|
159
|
+
if (Math.hypot(s[i].x - s[j].x, s[i].y - s[j].y) > 1)
|
|
160
|
+
lastMoveIdx = i;
|
|
161
|
+
}
|
|
162
|
+
const lastHeld = heldIdx[heldIdx.length - 1];
|
|
163
|
+
const upT = lastHeld + 1 < n ? s[lastHeld + 1].t : s[lastHeld].t;
|
|
164
|
+
releaseMs = upT - s[lastMoveIdx].t;
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
n, durationMs, peakVelFrac, velSkew, submovements, straightness, minJerkResidual,
|
|
168
|
+
dtMeanMs, dtStdMs, dtUniform, jitterAutocorr, powerLawR, grabMs, releaseMs,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** Score 0..1 (higher = more human) with human-readable flags for the tells that fire. */
|
|
172
|
+
export function scoreMotion(s, opts = {}) {
|
|
173
|
+
const f = extractFeatures(s);
|
|
174
|
+
const flags = [];
|
|
175
|
+
let score = 1;
|
|
176
|
+
const penalize = (cond, amt, flag) => { if (cond) {
|
|
177
|
+
score -= amt;
|
|
178
|
+
flags.push(flag);
|
|
179
|
+
} };
|
|
180
|
+
// peak velocity should be asymmetric-human: penalize pure ease-out (very early) AND a too-symmetric
|
|
181
|
+
// single-curve peak sitting right at the midpoint.
|
|
182
|
+
penalize(f.peakVelFrac < 0.15, 0.15, `peak-velocity-ease-out(${f.peakVelFrac.toFixed(2)})`);
|
|
183
|
+
penalize(f.peakVelFrac > 0.48, 0.12, `peak-velocity-too-symmetric(${f.peakVelFrac.toFixed(2)})`);
|
|
184
|
+
// velocity profile should have the human right-skew (long homing tail), not a symmetric bell
|
|
185
|
+
penalize(f.velSkew < 0.1, 0.12, `velocity-symmetric(skew=${f.velSkew.toFixed(2)})`);
|
|
186
|
+
// at least one corrective submovement (Fitts homing); a single analytic curve has none
|
|
187
|
+
penalize(f.submovements < 1, 0.2, "no-corrective-submovement");
|
|
188
|
+
// …but not TOO many: an over-corrected, velocity-reversal-heavy reach (many interior speed minima)
|
|
189
|
+
// is as non-human as a single smooth curve — real homing settles in 1–3 corrections.
|
|
190
|
+
penalize(f.submovements > 4, 0.12, `too-many-submovements(${f.submovements})`);
|
|
191
|
+
// dt should NOT look i.i.d.-uniform (real device sampling has a cadence mode)
|
|
192
|
+
penalize(f.dtUniform, 0.15, "uniform-dt-cadence");
|
|
193
|
+
// colored (not white) sub-pixel noise
|
|
194
|
+
penalize(f.jitterAutocorr < 0.1, 0.1, `white-noise-jitter(${f.jitterAutocorr.toFixed(2)})`);
|
|
195
|
+
// path shouldn't be a ruler-straight line
|
|
196
|
+
penalize(f.straightness > 0.9995, 0.08, "perfectly-straight-path");
|
|
197
|
+
if (opts.drag) {
|
|
198
|
+
penalize(f.grabMs != null && f.grabMs < 60, 0.2, `grab-hesitation-too-short(${f.grabMs}ms)`);
|
|
199
|
+
penalize(f.releaseMs != null && f.releaseMs < 40, 0.2, `release-delay-too-short(${f.releaseMs}ms)`);
|
|
200
|
+
}
|
|
201
|
+
return { score: Math.max(0, score), flags, features: f };
|
|
202
|
+
}
|
|
203
|
+
/** Turn a Step list (absolute coords + post-step sleep) into timestamped Samples for scoring.
|
|
204
|
+
* `buttonsDuring` marks the held-button (drag) span [startIdx, endIdx) with buttons=1. */
|
|
205
|
+
export function stepsToSamples(steps, buttonsDuring) {
|
|
206
|
+
const out = [];
|
|
207
|
+
let t = 0;
|
|
208
|
+
for (let i = 0; i < steps.length; i++) {
|
|
209
|
+
const held = buttonsDuring && i >= buttonsDuring.start && i < buttonsDuring.end ? 1 : 0;
|
|
210
|
+
out.push({ x: steps[i].x, y: steps[i].y, t, buttons: held });
|
|
211
|
+
t += steps[i].sleepMs;
|
|
212
|
+
}
|
|
213
|
+
return out;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=motionscore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motionscore.js","sourceRoot":"","sources":["../src/motionscore.ts"],"names":[],"mappings":"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"}
|