Collapse bounds policies to reflect-only; drop abort and clamp
The executor kept every commanded point on-screen via a per-strategy
BoundsPolicy of abort / clamp / reflect. Measured against the real
strategies, the other two earned nothing: abort truncated a sweep at the
first edge (line on a narrow screen ran only 90 of 250 steps), and clamp
could park the cursor against an edge (a monotonic ramp stalled 162 steps
in a row) -- both counter to the program's whole purpose of keeping the
cursor moving. reflect bounces off the edge and keeps going, and is
already what line/diagonal need in loop mode. arc's declared clamp was
provably dead code (it clamps its own endpoint, so no sample ever leaves
the screen).
Collapse to reflect-only:
- strategies.ts: remove the BoundsPolicy type and the `bounds` field from
the interface and all six strategies. Keep the local clamp() helper --
it's arc's endpoint geometry, not an on-screen policy; docstring says so.
- executor.ts: resolveTarget loses its policy parameter and its null
return and just reflects both axes; delete clampInt; SweepOutcome drops
"aborted"; ExecuteOptions drops `bounds`; remove the Out of bounds log.
- keeper.ts: loopOpts is now { restore: false, loop: true } -- the
reflect override added with loop mode is redundant.
- tests: drop the abort-outcome, clamp, and bounds-override tests; simplify
fixed() to take no policy; add a regression test that a monotonic ramp
past an edge never yields two identical points in a row (the guarantee
that motivated removing clamp).
Behavior is unchanged for every pattern at normal cursor positions
(verified: line's normal sweep is byte-identical). The only differences
are at a screen edge, where motion now bounces instead of stopping. No
config keys, flags, or pattern names changed.
Docs updated to match, including in-code comments, the README strategies
table (Bounds column removed) and verbose description, the sequence
diagram (resolveTarget signature + getPosition/width ordering + a loop-mode
note), and a CHANGELOG Changed entry.
This commit is contained in:
@@ -121,7 +121,7 @@ Options:
|
||||
One of: line, diagonal, jitter, walk, arc,
|
||||
figureEight. Each pattern defines its own
|
||||
size and speed.
|
||||
-V, --verbose Log every sweep, interrupt, and bounds event
|
||||
-V, --verbose Log every sweep and interrupt
|
||||
(default prints only the startup banner).
|
||||
-l, --loop Loop mode: once a sweep is triggered,
|
||||
keep moving until you move the mouse (or
|
||||
@@ -138,8 +138,8 @@ internally.
|
||||
|
||||
Logging is **quiet by default**: only the startup banner ("Teams Status
|
||||
Keeper started…") and any error from an unhandled rejection print on a
|
||||
default run. `-V` / `--verbose` opens up per-sweep, user-interrupt, and
|
||||
out-of-bounds events.
|
||||
default run. `-V` / `--verbose` opens up per-sweep and user-interrupt
|
||||
events.
|
||||
|
||||
Invalid input (unknown flag, missing value, non-positive number) prints an
|
||||
error to `stderr` and exits with code `2`.
|
||||
@@ -244,12 +244,12 @@ move --pattern diagonal --loop # roaming-DVD bounce around the screen
|
||||
move --pattern figureEight --loop # traces the eight over and over
|
||||
```
|
||||
|
||||
In loop mode the cursor is never restored between iterations, and every
|
||||
pattern's bounds policy is forced to `reflect`, so `line` and `diagonal`
|
||||
bounce edge-to-edge across the whole screen instead of ending at the first
|
||||
edge. Interruption is detected via mouse movement only — there is no
|
||||
keyboard hook — so if you resume by typing without touching the mouse, the
|
||||
cursor keeps cycling until you nudge it or stop the process.
|
||||
In loop mode the cursor is never restored between iterations, so `line` and
|
||||
`diagonal` bounce edge-to-edge across the whole screen (the executor keeps
|
||||
every pattern on-screen by reflecting off the edges) instead of ending at
|
||||
the first edge. Interruption is detected via mouse movement only — there is
|
||||
no keyboard hook — so if you resume by typing without touching the mouse,
|
||||
the cursor keeps cycling until you nudge it or stop the process.
|
||||
|
||||
### Known limitation: `verbose` and `loop` can be turned on but not off from the CLI
|
||||
|
||||
@@ -289,8 +289,8 @@ and everything but the raw nut.js call is unit-testable:
|
||||
of target points given a start, screen size, config, and RNG — plus the
|
||||
registry and name validation. Adding a pattern is one pure function.
|
||||
- `src/executor.ts` is the single `executePath` driver: it rounds targets,
|
||||
applies the strategy's bounds policy, paces steps, detects real-user
|
||||
interruption, and restores the cursor on a clean sweep.
|
||||
reflects any off-screen coordinate back inside, paces steps, detects
|
||||
real-user interruption, and restores the cursor on a clean sweep.
|
||||
|
||||
Defaults live in `src/config.ts` as `DEFAULT_CONFIG`:
|
||||
|
||||
@@ -321,8 +321,8 @@ to milliseconds before handing the resolved `Config` to `runKeeper`.
|
||||
up `config.pattern` in the strategy registry, and builds a `MoveContext`.
|
||||
2. It hands the strategy and context to `executePath`, which drives the
|
||||
sweep. For each target the strategy yields:
|
||||
- Round to whole pixels and apply the strategy's bounds policy
|
||||
(`abort` / `clamp` / `reflect`) to keep it on-screen.
|
||||
- Round to whole pixels and reflect any off-screen coordinate back inside
|
||||
the travel range, so the cursor bounces off the edges and keeps moving.
|
||||
- Move the cursor there, sleep `config.stepDelay`.
|
||||
- Re-read the cursor. If it isn't at the point we *just commanded*, the
|
||||
user moved it — log (when `--verbose`) and return early without
|
||||
@@ -335,37 +335,40 @@ In loop mode (`--loop`) step 2 repeats until the user interrupts: a
|
||||
pattern with an infinite `loopPath` (`line`, `diagonal`) runs that single
|
||||
never-ending path, while the others chain their finite path cycle after
|
||||
cycle. The restore in step 3 is skipped so successive cycles flow from where
|
||||
the last left off, and the bounds policy is forced to `reflect` for every
|
||||
pattern so edge-seeking motion bounces instead of stopping.
|
||||
the last left off.
|
||||
|
||||
Comparing against the last commanded (rounded) point — not the strategy's
|
||||
ideal, possibly fractional target — is what lets curved and stochastic
|
||||
patterns run without every rounded step looking like user activity. The
|
||||
comparison also allows a small (2px) tolerance, and the `clamp`/`reflect`
|
||||
patterns stay a couple of pixels off the screen edge, so sub-pixel cursor
|
||||
placement on scaled or multi-monitor displays isn't misread as the user
|
||||
grabbing the mouse. `line` uses the `abort` policy and is unaffected.
|
||||
comparison also allows a small (2px) tolerance, and the travel range stays a
|
||||
couple of pixels off the screen edge, so sub-pixel cursor placement on scaled
|
||||
or multi-monitor displays isn't misread as the user grabbing the mouse.
|
||||
|
||||
### Movement strategies
|
||||
|
||||
`config.pattern` selects one of the generators in `src/strategies.ts`:
|
||||
|
||||
| Name | Motion | Steps | Size | Bounds |
|
||||
| ------------- | ------------------------------------------------------------- | ----- | -------- | --------- |
|
||||
| `line` | Straight horizontal sweep (the original behavior). | 250 | 250px | `abort` |
|
||||
| `diagonal` | Straight line on both axes toward the roomiest corner. | 250 | 250px/axis | `clamp` |
|
||||
| `jitter` | Small random hops within a tight radius of the start. | 80 | 30px radius | `clamp` |
|
||||
| `walk` | Cumulative random walk; bounces off the screen edges. | 200 | ±4px/step | `reflect` |
|
||||
| `arc` | Smooth quadratic-Bézier curve to a random on-screen point. | 120 | ~300px | `clamp` |
|
||||
| `figureEight` | Traces a figure-eight (lemniscate) and returns to the start. | 90 | ~250px wide | `clamp` |
|
||||
| Name | Motion | Steps | Size |
|
||||
| ------------- | ------------------------------------------------------------- | ----- | ----------- |
|
||||
| `line` | Straight horizontal sweep (the original behavior). | 250 | 250px |
|
||||
| `diagonal` | Straight line on both axes toward the roomiest corner. | 250 | 250px/axis |
|
||||
| `jitter` | Small random hops within a tight radius of the start. | 80 | 30px radius |
|
||||
| `walk` | Cumulative random walk; bounces off the screen edges. | 200 | ±4px/step |
|
||||
| `arc` | Smooth quadratic-Bézier curve to a random on-screen point. | 120 | ~300px |
|
||||
| `figureEight` | Traces a figure-eight (lemniscate) and returns to the start. | 90 | ~250px wide |
|
||||
|
||||
Every pattern is kept on-screen the same way: the executor reflects any
|
||||
coordinate that would fall past a screen edge back inside, so motion bounces
|
||||
instead of stopping. Strategies therefore never bound their own output —
|
||||
they emit ideal geometry and let the executor confine it.
|
||||
|
||||
Each pattern owns its geometry — how many steps it takes and how far it
|
||||
reaches — as constants in `src/strategies.ts`. Those are properties of the
|
||||
pattern, not user preferences, so there is no knob for sweep size or step
|
||||
count; `stepDelay` (the per-step pause) is the only pacing lever, and it
|
||||
scales every pattern's total duration. To add a pattern, write one pure
|
||||
generator and register it — the executor supplies bounds, pacing, interrupt,
|
||||
and restore for free.
|
||||
generator and register it — the executor supplies on-screen reflection,
|
||||
pacing, interrupt, and restore for free.
|
||||
|
||||
### Why `mouse.config.autoDelayMs = 0`
|
||||
|
||||
@@ -421,7 +424,7 @@ move --help
|
||||
| `src/keeper.ts` | Idle-watch loop + per-sweep glue (selects a strategy, calls the executor). |
|
||||
| `src/device.ts` | `Device` I/O seam over nut.js (`Point`, `createNutDevice`); the only nut.js importer. |
|
||||
| `src/strategies.ts` | Pure movement-pattern generators, the strategy registry, and name validation. |
|
||||
| `src/executor.ts` | `executePath` driver: bounds policy, pacing, interrupt detection, restore. |
|
||||
| `src/executor.ts` | `executePath` driver: on-screen reflection, pacing, interrupt detection, restore. |
|
||||
| `docs/execution-happy-path.md` | Sequence diagram + invariants for a clean sweep. |
|
||||
| `package.json` | Bun project manifest. Single runtime dep: `@nut-tree-fork/nut-js`. |
|
||||
| `tsconfig.json` | Strict TypeScript config tuned for Bun (ESNext, bundler resolution). |
|
||||
|
||||
Reference in New Issue
Block a user