Explorar el Código

say where effect names cannot come from, and that naming one is the user's

The README asserted a policy — no fallback to VIA's built-in menu — and
never said the underlying problem is unsolved. A user whose board falls
in that hole was told what the tool would not do and not what nobody
knows how to do, and the two are different sentences.

The new section states the measured answer: no programmatic,
deterministic route to the spelling of an effect for a board whose
manufacturer never wrote one down, with a table of the eight routes and
what each yields. Two are spelled out because they look like they should
work. The vendor's own firmware image holds no names: 76 KB of Thumb
code, 735 strings, not one readable word, because the preprocessor
consumes them to build an enum and never emits them. And a majority vote
over the collection is not a name: 95 of the 122 definitions listing an
rgb_matrix effect are one manufacturer's, and where definitions disagree
they disagree about which effect a number is rather than how to spell it.

The section also says what *is* answerable. Writing above the top and
reading back the clamp gives a channel's highest effect ID, so a board
with no names can still be told how many effects it has and set by
number — and that is the half the new command writes down.

AGENTS.md gains the rule that the two halves stay separate, why a
generated file must not carry a name, and why the candidates live in a
sidecar note with their counts rather than in the definition.
Paul-Dieter Klumpp hace 1 semana
padre
commit
0b3fefbb48
Se han modificado 2 ficheros con 128 adiciones y 6 borrados
  1. 43 0
      AGENTS.md
  2. 85 6
      README.md

+ 43 - 0
AGENTS.md

@@ -319,6 +319,42 @@ board, which is worth knowing before adding one for the Impact 80: the vendor's
 file stops at ID 45, so no name for ID 46 is reachable while that file is
 present, built in or placed. README.md carries the user-facing half of this.
 
+**Naming an effect nobody named is the user's job, and the tool's job is to
+refuse to pretend otherwise.** The measured answer is that no programmatic,
+deterministic route exists to the spelling of an effect for a board whose vendor
+never wrote one down, and README says so in a section of its own rather than
+filling the gap. What *is* answerable is the slots: writing above the top and
+reading back what the firmware kept gives the channel's highest effect ID, because
+QMK clamps rather than rejects. `EffectTop` in `internal/via/channel.go` is that
+probe, and it is four round trips, not a search.
+
+So a board with no names is a normal case, not an error, and the two halves are
+separate: the **slots** come from the keyboard and are measured, the **names**
+come from a file and are only ever as good as whoever wrote it. `keyboard
+definitions generate` writes the first and leaves the second open, and a name it
+wrote itself would be indistinguishable from the manufacturer's, because nothing in
+a file can be read back off a keyboard to check it.
+
+The names other keyboards use are evidence and travel with their counts.
+`internal/spotted/spotted.json` is generated by `internal/spotted/generate` from a
+checkout of VIA's collection and carries the commit it was measured from. Three
+things about it are not to be undone:
+
+- It is **generated, never hand-edited**, and regenerating it is a documented
+  command rather than a patch.
+- Every name comes with **how many boards wrote it and which manufacturer most of
+  them were**. That is not decoration: 95 of the 122 definitions listing an
+  rgb_matrix effect are one manufacturer's, so a bare majority is one house style,
+  and where definitions disagree they disagree about which effect a number *is* —
+  ID 7 is `rainbow_moving_chevron` on 95 boards and `cycle_out_in` on 8. Drop the
+  counts and the note becomes the guess this section exists to prevent.
+- The names live in a **`.spotted.txt` note beside the definition, not in it**.
+  JSON cannot hold a comment: the tool would have to read one and VIA's parser
+  would reject the file. An option with an **empty name** is a slot without a name
+  and the parser skips it, so a generated file reports `0 effects` until the user
+  fills the names in. That is the honest state, and it is the one the board was
+  already in.
+
 There is no shared database of effect names to be had, and do not plan around
 one. The closest thing is VIA's collection, `the-via/keyboards`, and a board's
 names live in an `id_qmk_rgb_matrix_effect` dropdown under `menus` — not under a
@@ -428,6 +464,13 @@ twice; several are counts of a collection that moves.
 | What | Measured | Where |
 |---|---|---|
 | VIA's collection | 2029 definitions, one per unique VID/PID | `the-via/keyboards`, tree API |
+| …that carry an effect list with names | 161 | as above, `internal/spotted/generate` |
+| …that name one of VIA's built-in menus | 947 (`qmk_rgblight` 452, `qmk_backlight_rgblight` 220, `qmk_rgb_matrix` 179, `qmk_backlight` 94, `qmk_audio` 7) | as above |
+| …that have no lighting section at all | 865 | as above |
+| …listing an `id_qmk_rgb_matrix_effect` dropdown | 122, of which 95 are one manufacturer | as above |
+| Where the collection disagrees, it disagrees about the effect | ID 7: `rainbow_moving_chevron` 95×, `cycle_out_in` 8× | as above |
+| Effect names in the vendor's own firmware image | **0**, in 76 KB of Cortex-M code, 735 strings, none readable | Wobkey `impact_80.bin`, `strings` |
+| QMK's `rgb_matrix_effects.inc` order | the effect ID *is* the line number; inserted twice since 2021, renumbering everything after | `quantum/rgb_matrix/animations/rgb_matrix_effects.inc`, "order determines enum order" |
 | …name VIA's built-in `qmk_rgb_matrix` menu | 179 boards | as above |
 | …ship their own `id_qmk_rgb_matrix_effect` dropdown | 163 boards, of which 10 are an exact prefix of the built-in 45 | as above |
 | …of those, write names as QMK enum identifiers | 11; the other 152 use display labels | as above |

+ 85 - 6
README.md

@@ -2,7 +2,8 @@
 
 Control the RGB lighting on QMK-compatible keyboards. Any keyboard running QMK with a
 lighting channel and VIA support is driven; the Impact 80's effect names are built in,
-every other board's are fetched with `keyboard fetch`.
+every other board's are fetched with `keyboard fetch`, and a board with no
+definition file gets one written with `keyboard definitions generate`.
 
 Cross-platform CLI for Linux, macOS, and Windows. Designed for automation, scripting, and agent consumption.
 
@@ -499,11 +500,88 @@ Error: the VIA definition for GMMK Pro names no effects, so no effect name can b
 names are not in the file, and an effect is set by number with `effect <zone> <index>`
 ```
 
-`0 effects` next to a saved definition is that answer, not a failed fetch. The 45
-names are public, and this tool does not fall back to them: a transcribed list is
-the second copy of a name a per-board file exists to be, and the spellings do not
-line up anyway — `All Off` and `Band Sat.` reach neither `none` nor `band_sat`.
-See [Compatibility Aliases](#compatibility-aliases) for what such a board accepts.
+`0 effects` next to a saved definition is that answer, not a failed fetch.
+
+## Where Effect Names Cannot Come From
+
+**No programmatic, deterministic way has been found or documented to learn the
+spelling of an effect for a keyboard whose manufacturer never wrote one down.**
+That is the state of the art as of 2026-10-01, and this tool does not paper over
+it. Every route was measured rather than assumed:
+
+| Route | Effect IDs | Effect names |
+|---|---|---|
+| The board's own definition file | 161 of 2029 files in VIA's collection | yes |
+| VIA's built-in menu, if the file is pinned | the 947 files naming one | yes, 45 positions |
+| Writing above the top and reading back the clamp | yes, 4 round trips per channel | no |
+| A firmware `.bin`, read for its string table | — | **no: 0 names** |
+| The most-used spelling per ID across all files | no | **no: 95 of 122 are one vendor** |
+| The QMK version the firmware was built from | no | no |
+| Vial's `vialrgb_get_supported` | yes, with `VIALRGB_ENABLE` | no, the GUI holds them |
+| QMK XAP | not merged; dormant since 2023 | — |
+
+Two of those are worth spelling out, because they are the ones that look like
+they should work.
+
+**The firmware image holds no names.** The Impact 80's own `impact_80.bin`, 76 KB
+of Cortex-M Thumb code, has 735 strings of four characters or more and not one
+readable word among them. The names are consumed by the preprocessor to build an
+enum and never emitted, because the firmware has no use for them — it speaks
+numbers. A `.bin` can be disassembled to recover *how many* effects are compiled
+in, which is the one number a clamp already returns in four round trips, and it
+carries no name for any of them.
+
+**A majority vote over the collection is not a name.** Of the 122 definitions in
+VIA's collection that file an `rgb_matrix` effect list, 95 are Keychron's, so the
+most-used spelling of nearly every ID is one manufacturer's house style rather
+than a community consensus. And where definitions disagree, they disagree about
+*which effect* a number is, not how to spell it: ID 7 is `rainbow_moving_chevron`
+on 95 boards and `cycle_out_in` on 8. Those are different effects. There is no
+majority to compute, because there is no shared referent.
+
+**What is answerable is the slots.** Writing above the top and reading back what
+the firmware kept gives the highest ID a channel takes, because QMK clamps rather
+than rejects — `quantum/rgb_matrix/rgb_matrix.c` maps a mode at or above
+`RGB_MATRIX_EFFECT_MAX` down to `EFFECT_MAX - 1`. So a board with no names can
+still be told how many effects it has, and an effect set by number works on it
+today.
+
+### Naming Them Yourself
+
+`keyboard definitions generate` is what a board with no definition file is for.
+It asks the keyboard how many effect IDs each channel takes, writes a definition
+with one **unnamed** option per slot, and writes the spellings other keyboards'
+definitions use for the same numbers into a `.spotted.txt` note beside it.
+
+The generated definition names no effect on purpose. A name the tool wrote would
+be indistinguishable from the manufacturer's, because nothing in a file can be
+read back off a keyboard to check it — and a wrong name is worse than none, since
+the tool would then report an effect as set when it has set something else. An
+option with an empty name is a slot without a name, so the channel reports
+`0 effects` until a name is filled in, which is the honest state and the one the
+board was already in. Open the file, write a name into each `options` entry, and
+the channel resolves from then on.
+
+The note carries every candidate with the number of boards that wrote it and the
+manufacturer behind most of them, because that is what separates a name from a
+guess:
+
+```
+rgb_matrix (channel 3), IDs 0 to 7
+  ID 0   seen on 122 boards: none (104), all_off (17), led_off (1)   most of them keychron (95)
+  ID 7   seen on 122 boards: rainbow_moving_chevron (95), cycle_out_in (8), band_val (4)   most of them keychron (95)
+```
+
+Those numbers come from `internal/spotted/spotted.json`, generated by
+`internal/spotted/generate` from a checkout of [VIA's collection](https://github.com/the-via/keyboards)
+and carrying the commit it was measured from. It is a snapshot of a collection
+that moves, so a name in it ages; the commit is what says how far.
+
+The 45 names of VIA's built-in menu are public, and this tool does not fall back
+to them: a transcribed list is the second copy of a name a per-board file exists
+to be, and the spellings do not line up anyway — `All Off` and `Band Sat.` reach
+neither `none` nor `band_sat`. See [Compatibility Aliases](#compatibility-aliases)
+for what such a board accepts.
 
 The other 153 deviate, and not only in how many effects they compile in. MonsGeek's
 M1 uses QMK's enum identifiers and its own 19: `SOLID_COLOR`, `BREATHING`,
@@ -882,6 +960,7 @@ board", and that file is gone, so the field would have been unanswerable:
 | `qmk-rgb-tool effect <zone>`           | With no name, list the effects that zone has; `effect all` lists every channel |
 | `qmk-rgb-tool keyboard fetch`         | Download the VIA definition for the connected keyboard. A definition already stored for that board is not replaced, because it may be one you have edited; `--force` overwrites it |
 | `qmk-rgb-tool keyboard definitions`   | List every definition in use, from the per-user directory and built into the binary, each marked with which it is |
+| `qmk-rgb-tool keyboard definitions generate` | Ask the keyboard how many effect IDs each channel takes and write a definition with one **unnamed** option per slot, plus a `.spotted.txt` note naming the spellings other keyboards' definitions use for the same numbers. The names are yours to write in; see [Where Effect Names Cannot Come From](#where-effect-names-cannot-come-from) |
 | `qmk-rgb-tool brightness <zone> <val>` | Set brightness (0–255) on the named zones, verified by read-back |
 | `qmk-rgb-tool speed <zone> <val>`     | Set effect speed (0–255) on the named zones, verified by read-back; on `logo` and `side` only 0, 1 and 4 are reachable |
 | `qmk-rgb-tool color <zone> <hex>`     | Set color (e.g. `ff0000`) on the named zones |