Skip to content

Command library 4.4.0: DroidNet fork brightness - #10

Merged
travisccook merged 5 commits into
mainfrom
fork-brightness-4.4.0
Sep 23, 2026
Merged

travisccook merged 5 commits into
mainfrom
fork-brightness-4.4.0

Conversation

@travisccook

Copy link
Copy Markdown
Owner

Minor release 4.4.0: two DroidNet fork boards, each listed right after its stock board.

  • RSeriesLogic · DroidNet fork (droidnet-rseries-logic): Brightness, rseries.cfg.brightness,
    #LEBRI{unit}{level}. The unit is none (both displays), F or R; the level is 1-255. Firmware:
    travisccook/DroidNet-RSeriesLogics @ aa45d79.
  • FlthyHPs · DroidNet fork (droidnet-flthy-hps): Brightness, flthy.led.brightness, H{unit}B{level}.
    The unit is F R T X Y Z A, default A; the level is 1-255. Firmware: travisccook/DroidNet-FlthyHPs @ 75755de.

Both commands are cosmetic, Lighting and community confidence, with no duration suffix. Stock firmware ignores them,
and the level is RAM-only. The stock boards are unchanged. Boards 22 -> 24, commands 500 -> 502. Every example
parses to its own id and round-trips (test/droidnet-forks.test.js), and a test rejects a placeholder
firmware value.

npm run validate exits 0; npm test 425/425 (the branch also carries the storedcommand safety class, approved
separately and added between Tasks 2 and 3; the brief's template here said 423/423 before that task existed).

Design: droidnet-comlink docs/superpowers/specs/2026-09-22-fork-brightness-and-library-design.md, section 4.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VnqRz7vGF5Xusa3WLbo38J

travisccook and others added 4 commits September 23, 2026 09:33
…ness

Two device-native boards, each listed right after its stock board, describe
commands only the DroidNet forks run. Stock firmware ignores both, and the
stock boards are unchanged.

- droidnet-rseries-logic (RSeriesLogic · DroidNet fork): rseries.cfg.brightness,
  #LEBRI{unit}{level}. New enum rseries.unit ("" both, F front, R rear); the
  rseries.target enum cannot be reused, because two digit placeholders side by
  side would parse #LEBRI200 as target 2, level 00.
- droidnet-flthy-hps (FlthyHPs · DroidNet fork): flthy.led.brightness,
  H{unit}B{level}. flthy.designator is copied from flthy-hps; unit default A.
- Both: level int 1-255, required, no default; cosmetic, Lighting, community;
  no duration suffix (the stock Flthy board's |n would otherwise attach).
- firmware keeps <source_commit> until both forks merge their branches.

test/droidnet-forks.test.js checks that each example parses to its own id and
round-trips, that a level-only encode uses the every-unit default, the manifest
placement, that no ! command exists and that rseries.effect stops at 105.
load-node pins 24 components.

npm run validate exits 0; npm test 420/420.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnqRz7vGF5Xusa3WLbo38J
- libraries/manifest.json: libraryVersion 4.4.0; generatedFrom appends
  "DroidNet forks (2026-09)".
- releases.json: latest and libraries[0] -> 4.4.0, releasedAt today, notes
  for the two fork boards (the firmware each needs, RAM-only level, stock
  boards unchanged). Boards 22 -> 24, commands 500 -> 502.
- package.json and package-lock.json (top-level and packages[""]) -> 4.4.0.
- Test pins: load-node and engine libraryVersion 4.4.0, and a new load-node
  test that package.json, package-lock.json and releases.json carry the
  manifest's version (the Signal Booster's vendor-sync test needs all four).

npm run validate exits 0; npm test 421/421.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnqRz7vGF5Xusa3WLbo38J
- schema/library.schema.json: safety enum adds `storedcommand` ("runs a command
  the user stored on the board, whose effect the library cannot see").
- wcb-native.json: config -> storedcommand for wcb.runSeq, wcb.runSeqLong,
  wcb.runSeqLocal, wcb.runSeqLongLocal (;C<key> / ;SEQ<key> run-sequence).
- wcb-dfp.json / wcb-mp3.json: cosmetic -> storedcommand for the ONFIN,<key>
  play+callback commands (dfp.playCb, dfp.folderCb, dfp.mp3FolderCb,
  mp3.playCb, mp3.playFsCb) - ONFIN runs the stored ;C<key> after the track.
  Queries, save, clear, timer and the ONERR setters stay config.
- assets/app.css: .dn-safety-storedcommand joins the movement/power warn rule
  so the reference-page badge isn't grey.
- Docs: CLAUDE.md, docs/BOARD_AUTHORING_GUIDE.md, CONTRIBUTING.md,
  docs/INTEGRATION_GUIDE.md and .github/workflows/claude-review.yml all
  describe the new class; the review workflow gets a rule that flags a
  stored-command runner mislabeled cosmetic/config.
- releases.json: latest.notes records the new class.
- Tests: library.test.js allows storedcommand; wcb-621.test.js pins all 9
  storedcommand ids, pins ten related ids as config, and updates the wcb-dfp
  non-cosmetic list.

npm run validate exits 0; npm test 423/423. grep -rn '"storedcommand"'
libraries/boards | wc -l -> 9.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnqRz7vGF5Xusa3WLbo38J
Both forks merged native-brightness into main and pushed it. Each firmware
field now names the source_commit in that fork's firmware/manifest.json:

- droidnet-rseries-logic: travisccook/DroidNet-RSeriesLogics @ aa45d79
  (on origin/main; contains #LEBRI under src/native/)
- droidnet-flthy-hps: travisccook/DroidNet-FlthyHPs @ 75755de
  (on origin/main; src/main.cpp has the DroidNet native brightness markers)

A new test in droidnet-forks.test.js requires the two fork components'
firmware to match ^travisccook/DroidNet-(RSeriesLogics|FlthyHPs) @ <sha>$, so a
placeholder cannot be merged. The stock boards' firmware strings are free text
and are not checked. releases.json releasedAt is already today's date, so it
has no diff to commit.

npm run validate exits 0; npm test 425/425 (13 suites) - two more than the
423 the brief's Step 6 expected, accounted for by Task S's two storedcommand
tests added to the suite after this brief was validated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnqRz7vGF5Xusa3WLbo38J
@github-actions

Copy link
Copy Markdown

Automated review

Checks: ✅ all pass.

  • npm ci — clean install (272 packages; pre-existing npm audit advisories only, unrelated to this PR).
  • npm run validate — every board file validates (✓ boards/droidnet-flthy-hps.json, ✓ boards/droidnet-rseries-logic.json, plus all pre-existing boards), ✓ cross-file (merged catalog). Only warnings are pre-existing "non-standard category" notices on unrelated boards — none from this PR's files.
  • npm test — 13 suites / 425 tests pass, including the new test/droidnet-forks.test.js (round-trip, comment-label, manifest-position, firmware-commit-format checks for the two new boards) and updated assertions in test/wcb-621.test.js, test/engine.test.js, test/library.test.js, test/load-node.test.js.

Safety-class fix (the required item, #3 in review instructions): correctly done and complete. I grepped every board file for ;C{key}, ;SEQ{key}, and ONFIN,{key} templates and confirmed all 9 are now safety:"storedcommand", none missed:

  • libraries/boards/wcb-native.json:1599,1618,1637,1656 — wcb.runSeq, wcb.runSeqLong, wcb.runSeqLocal, wcb.runSeqLongLocal (previously config)
  • libraries/boards/wcb-dfp.json:39,49,59 — dfp.playCb, dfp.folderCb, dfp.mp3FolderCb (previously cosmetic — this was the more serious mislabel, since these silently ran arbitrary stored content)
  • libraries/boards/wcb-mp3.json:20,29 — mp3.playCb, mp3.playFsCb (previously cosmetic)

Commands that only manage stored sequences (save/list/get/clear, timer, ONERR setters) correctly stay config since they don't execute unknown content — verified via test/wcb-621.test.js's new config: guard test.

The new storedcommand class is threaded consistently through schema (schema/library.schema.json:126), docs (CLAUDE.md, CONTRIBUTING.md, docs/BOARD_AUTHORING_GUIDE.md), UI styling (assets/app.css:39), and a good forward-compat note in docs/INTEGRATION_GUIDE.md telling integrators to treat any unrecognized non-cosmetic value as a warning rather than allow-listing known ones.

New boards (libraries/boards/droidnet-flthy-hps.json, libraries/boards/droidnet-rseries-logic.json): single Brightness command each, correctly safety:"cosmetic" (RAM-only brightness level, no movement/power implication) and confidence:"community" (honest — unverified fork firmware). Each new component slots directly after its stock counterpart in libraries/manifest.json, matches CONTRIBUTING's "list right after the stock board" convention, and is exercised end-to-end by test/droidnet-forks.test.js.

Versioning: libraryVersion bumped 4.3.0 → 4.4.0 (minor) in libraries/manifest.json:3 — correct per CLAUDE.md's semver rule (adds boards/commands, no command-id renames/removals, so no stored-value breakage even though safety semantics changed). package.json, package-lock.json, and releases.json are all in sync at 4.4.0, and a new test (test/load-node.test.js) now asserts that invariant going forward — a nice guardrail against future version-file drift.

src/*.js: unchanged in this PR — nothing to review under item 4.

No issues found. This is a clean, well-tested PR that does exactly what the safety-class rule requires, with no missed cases.

releases.json latest.notes said "The stock boards are unchanged," but this
release changes the safety class (config -> storedcommand) of run-sequence
and play+callback commands on three stock WCB boards (wcb-native, wcb-dfp,
wcb-mp3). Narrow the sentence to the two boards this release actually leaves
untouched: RSeriesLogic and FlthyHPs.

npm run validate exits 0; npm test 425/425 (13 suites).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VnqRz7vGF5Xusa3WLbo38J
@github-actions

Copy link
Copy Markdown

Automated review

1. Checks

  • npm ci — OK (272 packages; only pre-existing npm audit warnings, unrelated to this diff).
  • npm run validate — PASS. Only pre-existing "non-standard category name" warnings on unrelated boards (e.g. flthy-hps: category 'Servo'), nothing from this PR's files.
  • npm test — PASS. 13 suites / 425 tests, including the new test/droidnet-forks.test.js (round-trip, comment-label, manifest-placement, firmware-string checks for both new boards) and the extended test/wcb-621.test.js.

2. Board-contribution rules

  • Every new/changed command has an examples entry (libraries/boards/droidnet-flthy-hps.json:34, droidnet-rseries-logic.json:33), and template/param placeholders match both ways (H{unit}B{level} ↔ unit,level; #LEBRI{unit}{level} ↔ unit,level).
  • param.enum refs (flthy.designator, rseries.unit) resolve to enums defined in the same file.
  • Command ids are new/unique (flthy.led.brightness, rseries.cfg.brightness); validator's cross-file pass confirmed no collisions.
  • libraries/manifest.json libraryVersion bumped 4.3.0 → 4.4.0 (minor — two new boards/commands, no renames/removals), consistent with package.json, package-lock.json (both version fields), and releases.json (latest.libraryVersion + libraries[].libraryVersion + releasedAt updated) — all now enforced by a new regression test in test/load-node.test.js:16-25. Good addition.
  • confidence: "community" on both new boards — appropriately cautious for unverified fork firmware, per CONTRIBUTING.md.

3. Safety-class check (HIGH SEVERITY item) — no mislabeling found, and this PR fixes a prior one

  • The two new commands (flthy.led.brightness, rseries.cfg.brightness, both libraries/boards/droidnet-*-*.json) are RAM-only LED-brightness setters — cosmetic is correct, they don't move anything or touch power.
  • The PR introduces a new storedcommand safety class (schema: schema/library.schema.json:126) specifically for commands that run board-stored content, and retroactively re-labels the commands this rule (item 3 of the review instructions itself, updated at .github/workflows/claude-review.yml:90-94) is about:
    • wcb-native.json: wcb.runSeq, wcb.runSeqLong, wcb.runSeqLocal, wcb.runSeqLongLocal (;C<key> / ;SEQ<key> runs) — moved from config → storedcommand. Correct: the library can't see what a saved WCB sequence does.
    • wcb-dfp.json (dfp.playCb, dfp.folderCb, dfp.mp3FolderCb) and wcb-mp3.json (mp3.playCb, mp3.playFsCb) — the ONFIN,{key} callback variants moved from cosmetic → storedcommand, since they trigger a stored key's callback whose effect is unknown. Correct, and previously these actually were mislabeled cosmetic, which this PR fixes.
    • Existing wcb.seqSave/seqNames/seqGet/seqList/seqClear/seqClearAll and timer/ONERR setters correctly stay config (they save/query, they don't execute stored content) — verified by the new test at test/wcb-621.test.js:130-136.
    • Pre-existing Maestro "Run Subroutine" commands (libraries/boards/maestro.json:127 etc.) are left as movement, not reclassified to storedcommand — this is consistent with the new CLAUDE.md guidance ("if the device itself limits what saved content can do … use that limit's class instead"), since a Pololu Maestro subroutine is servo motion, a known effect class.

4. src/*.js

No changes to src/droidnet-command-library.js or src/droidnet-command-library-ui.js in this diff — engine/UI separation and the buildWCBValue(parseWCBValue(v)) === v round-trip invariant are untouched, and are exercised for the two new boards by test/droidnet-forks.test.js ("round-trips byte-identically").

Minor/non-blocking notes

  • test/wcb-621.test.js's top-level storedcommand list (storedIds, line ~131) only covers wcb.runSeq* + mp3.playCb/mp3.playFsCb; the dfp.*Cb ids aren't in that list, but they are separately asserted storedcommand a few lines down in the wcb-dfp describe block (test/wcb-621.test.js:317), so coverage is complete — just split across two tests, worth a comment if it's ever confusing to a future reader.
  • Both new boards are kind: "device-native" naming a specific fork firmware commit (droidnet-flthy-hps.json:12, droidnet-rseries-logic.json:12) rather than wcb-verb; per CLAUDE.md that's the right kind since the grammar (H{unit}B{level} / #LEBRI{unit}{level}) is the board's own, not an intermediary's.

Overall: clean, well-tested PR. No blocking issues found.

@travisccook
travisccook merged commit 1bfa986 into main Sep 23, 2026
2 checks passed
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