native-ui: refresh the vendored Claude Code token and verb lists on harness upgrades #239

Closed
opened 2026-08-06 20:21:00 +00:00 by coilyco-ops · 1 comment
Member

internal/nativeui is coupled to two lists extracted from the Claude Code binary at version 2.1.221:

  • the dark base theme token names, asserted in nativeui_test.go
  • the 184 default spinner verbs, vendored at internal/nativeui/testdata/harness-default-verbs.txt

Both exist because the harness fails quietly. An unknown theme token is dropped with no error, and a verb that duplicates a default simply reads as the default. The tests turn both silences into failures.

The actual risk

The tests only catch drift when someone runs them after a harness upgrade. Nothing today notices that 2.1.221 has been superseded, so a token rename could sit green until a user reports a role that stopped looking like itself.

Scope

  • Record the pinned harness version next to the vendored data so the coupling is legible.
  • Decide whether refreshing is a manual chore on upgrade or something the repo detects.

Notes

Both lists were extracted by reading the shipped binary, not from documentation, since neither is a published contract. Treat the extraction method as part of what needs recording.

Done when

A harness upgrade has an obvious, documented path to refreshing both lists.

`internal/nativeui` is coupled to two lists extracted from the Claude Code binary at version 2.1.221: * the `dark` base theme token names, asserted in `nativeui_test.go` * the 184 default spinner verbs, vendored at `internal/nativeui/testdata/harness-default-verbs.txt` Both exist because the harness fails quietly. An unknown theme token is dropped with no error, and a verb that duplicates a default simply reads as the default. The tests turn both silences into failures. ## The actual risk The tests only catch drift when someone runs them after a harness upgrade. Nothing today notices that 2.1.221 has been superseded, so a token rename could sit green until a user reports a role that stopped looking like itself. ## Scope * Record the pinned harness version next to the vendored data so the coupling is legible. * Decide whether refreshing is a manual chore on upgrade or something the repo detects. ## Notes Both lists were extracted by reading the shipped binary, not from documentation, since neither is a published contract. Treat the extraction method as part of what needs recording. ## Done when A harness upgrade has an obvious, documented path to refreshing both lists.
Author
Member

Landed on main as 6cfbb56 and 3a1bf5f. Detection by content, not by version.

It found the drift it was built for, on the first run

The vendored verb list held 184 entries. The harness ships 186. The original extraction dropped Flambéing and Sautéing, both written Flamb\xE9ing and Saut\xE9ing in the bundle, so a naive quoted-string read never decoded them.

That is exactly the silent failure this issue describes. Under replace mode a role verb equal to a harness default reads as the default and does no identity work, and the guard against that was blind to two of them. No authored verb collides with either today, so nothing was broken in practice, but the guard was weaker than it claimed for as long as it existed.

What ships

Three vendored files under internal/nativeui/testdata/:

  • harness-default-verbs.txt - now 186.
  • harness-theme-tokens.txt - 72 token names, new. This replaces the inline knownTokens map, which had no refresh path at all.
  • harness-version.txt - 2.1.221 (Claude Code), recorded but deliberately not asserted.

TestVendoredHarnessDataMatchesTheInstalledBinary re-extracts both lists from the binary on PATH and compares content. It skips when claude is absent, so CI and any machine without the harness stay green. ward exec harness-refresh rewrites all three.

The two decisions this issue asked for

Manual or detected? Detected, keyed on content. A version-string gate would fail every checkout the moment Claude Code self-updates, which is often, and would be bypassed inside a week. Comparing content means a version bump that changes neither list is silent, and a bump that changes one is loud.

How the coupling is recorded. docs/harness-vendoring.md, with a pointer in the testdata directory. It states the extraction anchors, the refresh command, and the one honest limitation below.

The limitation, stated plainly

The token file is the union across all six base themes, not the dark set alone. The six bases (dark, light, dark-ansi, light-ansi, and both daltonized) are keyed identically, and the mapping from base name to its object is not recoverable from a plain read of the bundle, so extracting the dark set specifically is not possible without a second fragile parser.

The union is weaker in one direction: a token that exists only in a light base would now pass the emit check. It is not weaker in the direction that matters, because a renamed token leaves every base at once, which is the failure being guarded. nativeui emits a fixed 22-slot map that other tests pin independently.

If the anchors ever break, the extractor errors rather than returning an empty list, so a bundler layout change fails loudly instead of reporting agreement.

Landed on `main` as 6cfbb56 and 3a1bf5f. Detection by content, not by version. ## It found the drift it was built for, on the first run The vendored verb list held **184** entries. The harness ships **186**. The original extraction dropped `Flambéing` and `Sautéing`, both written `Flamb\xE9ing` and `Saut\xE9ing` in the bundle, so a naive quoted-string read never decoded them. That is exactly the silent failure this issue describes. Under `replace` mode a role verb equal to a harness default reads as the default and does no identity work, and the guard against that was blind to two of them. No authored verb collides with either today, so nothing was broken in practice, but the guard was weaker than it claimed for as long as it existed. ## What ships Three vendored files under `internal/nativeui/testdata/`: * `harness-default-verbs.txt` - now 186. * `harness-theme-tokens.txt` - 72 token names, new. This replaces the inline `knownTokens` map, which had no refresh path at all. * `harness-version.txt` - `2.1.221 (Claude Code)`, recorded but deliberately not asserted. `TestVendoredHarnessDataMatchesTheInstalledBinary` re-extracts both lists from the binary on `PATH` and compares content. It skips when `claude` is absent, so CI and any machine without the harness stay green. `ward exec harness-refresh` rewrites all three. ## The two decisions this issue asked for **Manual or detected?** Detected, keyed on content. A version-string gate would fail every checkout the moment Claude Code self-updates, which is often, and would be bypassed inside a week. Comparing content means a version bump that changes neither list is silent, and a bump that changes one is loud. **How the coupling is recorded.** [docs/harness-vendoring.md](https://forgejo.coilysiren.me/coilyco-flight-deck/agent-compose/src/branch/main/docs/harness-vendoring.md), with a pointer in the testdata directory. It states the extraction anchors, the refresh command, and the one honest limitation below. ## The limitation, stated plainly The token file is the **union across all six base themes**, not the dark set alone. The six bases (`dark`, `light`, `dark-ansi`, `light-ansi`, and both daltonized) are keyed identically, and the mapping from base name to its object is not recoverable from a plain read of the bundle, so extracting the dark set specifically is not possible without a second fragile parser. The union is weaker in one direction: a token that exists only in a light base would now pass the emit check. It is not weaker in the direction that matters, because a renamed token leaves every base at once, which is the failure being guarded. `nativeui` emits a fixed 22-slot map that other tests pin independently. If the anchors ever break, the extractor errors rather than returning an empty list, so a bundler layout change fails loudly instead of reporting agreement.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agent-compose#239
No description provided.