native-ui: refresh the vendored Claude Code token and verb lists on harness upgrades #239
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-compose#239
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
internal/nativeuiis coupled to two lists extracted from the Claude Code binary at version 2.1.221:darkbase theme token names, asserted innativeui_test.gointernal/nativeui/testdata/harness-default-verbs.txtBoth 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
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.
Landed on
mainas6cfbb56and3a1bf5f. 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éingandSautéing, both writtenFlamb\xE9ingandSaut\xE9ingin the bundle, so a naive quoted-string read never decoded them.That is exactly the silent failure this issue describes. Under
replacemode 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 inlineknownTokensmap, which had no refresh path at all.harness-version.txt-2.1.221 (Claude Code), recorded but deliberately not asserted.TestVendoredHarnessDataMatchesTheInstalledBinaryre-extracts both lists from the binary onPATHand compares content. It skips whenclaudeis absent, so CI and any machine without the harness stay green.ward exec harness-refreshrewrites 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.
nativeuiemits 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.