install.sh now installs the newest published tag by default instead of
tracking the master branch, so 'curl ... | sh' installs a real release and
reports its version. The tag is resolved from the Gitea tags API, falling
back to master if the lookup fails. MOVE_VERSION still pins an explicit ref.
Interactive installer: prompt before replacing an existing install or
overwriting an existing config, reading answers from /dev/tty so it works
under 'curl ... | sh'. Falls back to the prior non-interactive contract
when no terminal is available. MOVE_FORCE=1 skips all prompts; new
MOVE_RESEED_CONFIG=1 reseeds the config unattended (old file kept as .bak).
Fix: install.sh no longer wipes a working install before downloading. The
tree is built in a staging dir and swapped into place only once complete,
so a failed download/extract/build leaves the existing install intact.
The stepCount and stepSize knobs were two controls for one quantity users
actually care about (reach), and the number of steps is an implementation
detail nobody meaningfully tunes. Each pattern has a natural size and
resolution — a jitter is inherently small, an arc a broad curve — so those
now live as constants in each strategy rather than as global config.
- strategies.ts: each pattern defines its own step count and size; MoveContext
drops `config` down to pure geometry (start/width/height/rng), and the
module no longer imports Config at all (dissolving the type-only-import
cycle workaround). line stays byte-for-byte: 250 one-pixel steps.
- executor.ts: executePath takes `config` for pacing (stepDelay); the path
itself needs nothing from it.
- config.ts / cli.ts / move.ts / config.default.json: drop stepCount and
stepSize from the type, seed, validation, resolver, CLI flags (-n, -s),
and help. stepDelay stays as the one pacing lever.
- configFile.ts: tolerate the removed keys instead of rejecting them — every
pre-1.3.0 install seeded stepCount, so a hard "unknown key" failure on
upgrade is avoided. They're ignored with a one-line stderr notice; genuine
unknown keys still error.
The -n/--step-count CLI flag (shipped since 1.0.0) is now an unknown option;
config files degrade gracefully, command lines don't. Stays in the unpushed
1.3.0 release. 64 tests pass.
Turn the hardcoded straight-line sweep into a strategy system behind three
seams so new patterns are easy to add and, for the first time, testable
without nut.js or a real screen:
- src/device.ts: injectable Device seam over nut.js (autoDelayMs lives
here now); the only module that touches the native lib.
- src/strategies.ts: pure per-pattern path generators + registry + lenient
name resolution. Ships line, diagonal, jitter, walk,
arc, figureEight.
- src/executor.ts: single executePath driver owning bounds policy
(abort/clamp/reflect), pacing, interrupt detection, and
restore-on-clean.
keeper.ts's simulateActivity now selects a strategy and delegates to the
executor; the default `line` pattern is byte-for-byte the previous behavior.
New config surface, layered CLI > file > default with strict validation:
- -p/--pattern <name> movement strategy (names matched case/-/_-insensitive)
- -s/--step-size <px> pixels per step; stepCount is now a step *count*
Robustness for the new edge-seeking patterns: interrupt detection compares
against the last commanded (rounded) point with a 2px tolerance, and
clamp/reflect stay a couple pixels off the screen edge, so sub-pixel cursor
placement on scaled/multi-monitor displays isn't misread as user activity.
jitter's radius scales with sweep length so it moves at the default stepSize.
Tests: new suites for strategies, the executor (all bounds policies,
rounding, interrupt, tolerance, pacing), and the keeper loop; config and
configFile suites extended for pattern/stepSize. editor.test.ts moved to
tests/ for consistency. 64 pass.