Skip to content

Measure the capability list instead of maintaining it - #25

Merged
tannevaled merged 1 commit into
mainfrom
capability-list-guard
Oct 4, 2026
Merged

tannevaled merged 1 commit into
mainfrom
capability-list-guard

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

The package doc and the README each list the optional capability interfaces, and
both had drifted three behind: ModifiedClicker and ModifiedKeyer were added
last without updating either, and NativeControlProvider had been missing for
longer.

A capability list that is wrong is worse than no list — a reader who counts six
does not go looking for a seventh, and NativeControlProvider was invisible to
anyone reading the doc rather than run.go.

So both lists are measured now

TestEveryCapabilityIsNamedInThePackageDoc walks the package for type assertions
off a Handler and insists each exported interface it finds is named where each
document lists them. "A capability" is not a judgement in that test: it is an
exported interface this package type-asserts, which is exactly what makes it
optional.

⛔ The first version of the check was blind, and an ablation found it

It searched the whole text. The README names ModifiedKeyer twice — once in
the list, once in a paragraph explaining why it exists — so removing it from the
list left the prose to keep the check quiet:

✗ README: une entrée retirée de la LISTE (nommée ailleurs) — LE GARDE NE VOIT RIEN

It now narrows to the paragraph that does the listing, and the same ablation
fails as it should.

Four rules, four witnesses, each verified to fail when its rule is ablated,
including the one that previously passed.

Also written down

Why those two capabilities exist at all, in the README: Handler has nowhere to
put a modifier key — MouseDown(x, y int) carries no Shift, and Key's own
contract says it has "no room to say which modifiers were held" — so without
them a Shift-click or a Shift-arrow cannot reach the widget underneath whatever
that widget supports.

Everything outside the documented native-run-loop exclusion stays at 100.0%.

🤖 Generated with Claude Code

The package doc and the README each list the optional capability interfaces, and
both had drifted THREE behind: ModifiedClicker and ModifiedKeyer were added last
without updating either, and NativeControlProvider had been missing for longer.

A capability list that is wrong is worse than no list -- a reader who counts six
does not go looking for a seventh, and NativeControlProvider was invisible to
anyone reading the doc rather than run.go.

So both lists are now checked against the code.
TestEveryCapabilityIsNamedInThePackageDoc walks the package for type assertions
off a Handler and insists each exported interface it finds is named where each
document lists them. "A capability" is not a judgement in that test: it is an
exported interface this package type-asserts, which is exactly what makes it
optional.

⛔ The first version of the check was blind, and an ablation found it. It
searched the WHOLE text, and the README names ModifiedKeyer twice -- once in the
list, once in a paragraph explaining why it exists -- so removing it from the
LIST left the prose to keep the check quiet. It now narrows to the paragraph
that does the listing.

Four rules, four witnesses, each verified to fail when its rule is ablated,
including the one that previously passed.

Also written down, in the README, why those two capabilities exist at all:
Handler has nowhere to put a modifier key, so without them a Shift-click or a
Shift-arrow cannot reach the widget underneath whatever that widget supports.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit a3cc707 into main Oct 4, 2026
5 checks passed
@tannevaled
tannevaled deleted the capability-list-guard branch October 4, 2026 14:27
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