Skip to content

fix(engine): match negative-range int params so they round-trip - #3

Merged
travisccook merged 1 commit into
mainfrom
fix/negative-int-param-matcher
Jul 6, 2026
Merged

fix(engine): match negative-range int params so they round-trip#3
travisccook merged 1 commit into
mainfrom
fix/negative-int-param-matcher

Conversation

@travisccook

Copy link
Copy Markdown
Owner

Found by the automated review of PR #1 (the R2 Uppity Spinner ALT board).

Bug: _buildTemplateMatcher built the regex for non-enum int params unconditionally as (\d+), which can't match a leading -. The first library commands with a negative int range — uppity.rotary.spin (:PR{speed}, min -100) and uppity.rotary.rel (:PD{degrees}, min -180) — failed to re-parse their own documented negative examples (:PR-80, :PD-90): match() returned null and parseWCBValue fell back to a raw step instead of a structured, editable one. encode() was unaffected.

Fix: (-?\d+) for int-param groups. Adds a regression test (match(':PR-80')uppity.rotary.spin/speed -80; :PD-90uppity.rotary.rel/degrees -90). Engine version 2.1.0 → 2.1.1; catalog libraryVersion unchanged.

Full suite: 137 passing; validator green.

_buildTemplateMatcher built the regex for non-enum int params unconditionally as
(\d+), which cannot match a leading '-'. The first commands in the library to use a
negative int range — uppity.rotary.spin (:PR{speed}, min -100) and uppity.rotary.rel
(:PD{degrees}, min -180) — therefore failed to re-parse their own documented negative
examples (:PR-80, :PD-90): match() returned null and parseWCBValue fell back to a raw
step instead of a structured, editable one. encode() was unaffected (string interp).

Fix: use (-?\d+) for int-param groups. Adds a regression test asserting match(':PR-80')
=> uppity.rotary.spin/speed='-80' and match(':PD-90') => uppity.rotary.rel/degrees='-90'.
Bumps engine version 2.1.0 -> 2.1.1 (catalog libraryVersion unchanged; no board data).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review — PR #3 (fix(engine): match negative-range int params so they round-trip)

Scope: engine-only change. No libraries/boards/*.json files are touched, so the manifest/releases.json versioning rules and safety-class checks in CONTRIBUTING.md don't apply here — nothing to flag on that front, and no safety-mislabeling risk (no safety: fields touched).

1. Checks — all green

  • npm ci: clean install, 272 packages, no errors (1 moderate audit advisory, pre-existing/unrelated).
  • npm run validate: ✓ all 9 boards + manifest + cross-file checks pass.
  • npm test: 7 suites / 137 tests passed, including the new regression test in test/web.test.js.

2. The fix itself

src/droidnet-command-library.js:233-235_buildTemplateMatcher now emits (-?\d+) instead of (\d+) for non-enum int params, so tokens like :PR-80 (uppity.rotary.spin, min -100) and :PD-90 (uppity.rotary.rel, min -180) parse into structured steps instead of falling back to raw.

Nice catch on why this was invisible before: test/web.test.js's existing "examples round-trip" check only exercises examples[0] per command, and both affected commands' examples[0] (:PR0, :PD180) are non-negative — so the round-trip invariant buildWCBValue(parseWCBValue(v)) === v was silently satisfied via the raw-step fallback (raw text is preserved byte-for-byte) even though match() was failing to structure negative values. The new test/web.test.js block explicitly asserts commandId/params are populated, closing that gap. Good, targeted regression test.

3. One design concern worth a follow-up (non-blocking)

The new (-?\d+) is applied unconditionally to every template int param across all boards, not just ones whose range permits negatives. Several params elsewhere declare min: 0 (e.g. hcr-native.json<MN{seconds}>/<MX{seconds}> "muse gap" params at ~line 314/334, and the WAV file/fileFrom/fileTo params at ~line 359/387/394, all min: 0, max: 9999, pad: 4). With the broadened regex, a malformed/unexpected token containing a literal - immediately before the digits of one of these commands would now be consumed as a structured step with an out-of-range negative value, rather than safely falling through to a raw step as before.

Suggestion: gate the -? on the param's declared range, e.g. (p.min !== undefined && p.min < 0) ? '(-?\\d+)' : '(\\d+)', so only params that can actually go negative accept a leading -. No test currently exercises this edge case and none of the shipped boards trigger it today, so it's not a merge blocker — just tightening for the general case.

4. Versioning

package.json bumped 2.1.02.1.1 (patch) for the engine bug fix — appropriate for a behavior-preserving-for-valid-input fix. libraries/manifest.json libraryVersion (2.2.0) and releases.json are correctly left untouched since no catalog/board content changed.

Overall: solid, well-tested bug fix. Recommend considering the range-gated regex (#3 above) before or shortly after merge, but nothing here blocks it.

@travisccook
travisccook merged commit ab7bff7 into main Jul 6, 2026
2 checks passed
@travisccook
travisccook deleted the fix/negative-int-param-matcher branch July 6, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant