test(dialects): guard the catalogue against a proposal's two limits
DialectCatalogueSizeTest, modelled on ChapterProposalSizeTest and measured the way the manager measures it -- the real encoding rather than an estimate. Neither limit is checked anywhere a reviewer would see it: proposeSigningBatch enforces both with a require, so the first sign of the catalogue outgrowing a batch would be a wave that split in two, or one that threw. Somebody adding a language has no reason to be thinking about FROST. The third assertion changed shape while being written. "A wave is small rather than just legal", as a fraction of MAX_PROPOSAL_BYTES, failed: the catalogue encodes to 16,832 bytes and a quarter of the budget is 16,384. The quarter was a guess. What actually wants guarding is the cost of one dialect -- 301 bytes, bounded here at twice that -- because that is the number that would drift if a dialect event grew something large, and unlike a fraction it does not move every time a language is added. The size test's failure message says not to trim the catalogue. The view model already chunks by MAX_BATCH_SIZE, so a larger catalogue is two sessions rather than a bug; what would be lost is a group adopting the whole list answering once, and that is a decision rather than a repair. Also records the plan as built, with a table of the seven places the build chose differently, and indexes it in docs/README.md. One of those entries is a finding rather than a choice: m3-touch-targets.py reads comments as code, so a KDoc explaining that a row used a clickable Card "rather than a Modifier.clickable" broke a zero budget and with it ./gradlew check. The comment was reworded, which is the wrong fix. m3-audit.sh already solves this for the colour check and says why, at NOT_A_COMMENT. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
226653d282
commit
dd405e90e5
3 files changed
+186
-1
No files matched your search
@@ -5,7 +5,14 @@ spoken in Africa instead of typing each one into a three-field form, and how
|
||||
admins top that list up later — proposing only what is still missing, in waves,
|
||||
without two of them proposing the same wave twice.
|
||||
|
||||
**Not built.** This is the plan. Seven phases, one commit each.
|
||||
**Built.** All seven phases are in, one commit each, and the phases below are
|
||||
kept as written -- they are the reasoning, and the code is easier to read against
|
||||
the argument it came from than against a summary of itself. Where the
|
||||
implementation chose differently the table at the end says so.
|
||||
|
||||
`AfricanLanguages.ALL` is the catalogue, `DialectScaffold` answers what a room is
|
||||
missing, and `AddDialectsFromCatalogueScreen` is the picker, reached from the
|
||||
group's detail screen beside "Add dialect".
|
||||
|
||||
Two facts shape every phase and are stated before them, because both are easy to
|
||||
design around and expensive to discover afterwards.
|
||||
@@ -480,3 +487,31 @@ is, not a convenience method.
|
||||
**No automatic wave.** Nothing proposes the catalogue on a room's behalf when it
|
||||
is created. A dialect is a statement the group signs about what it will
|
||||
translate into, and fifty of them arriving unasked is a statement nobody made.
|
||||
|
||||
---
|
||||
|
||||
## Where the build chose differently
|
||||
|
||||
| the plan said | the build does | why |
|
||||
|---|---|---|
|
||||
| "about fifty entries" | 56 — 53 African, 3 European | the fan-out across countries landed there. 8 under `MAX_BATCH_SIZE`, which is thinner than it reads; phase 7's test is the tripwire |
|
||||
| one `african` list | two, `african` and `european`, with `ALL` their sum | the ordering test needs a list that is actually grouped by country, and appending the three European entries breaks that grouping. It also makes "drop them" one edit, which is what the plan promised |
|
||||
| `missingFrom(existing, pending, catalogue)` | that, plus a public `DialectScaffold.Key` and three `keyOf` overloads | the identity rule has four callers — the scaffold, the row classifier, the selection and the view model's unpick — and spelling `(code, country)` four times is four chances to forget `trim()` |
|
||||
| phase 4 ships the picker with its FAB | phase 4 shows and picks, phase 5 proposes | a commit whose FAB calls a method written in the next commit does not compile. Split so each commit does something whole |
|
||||
| `proposeSelectedDialects(localChatRoom, selected, …)` | the selection is read internally | the view model owns `selected`; passing it back in lets a caller pass something else, and nothing needs to |
|
||||
| `CatalogueRow.rowsOf` computes the three standings | it derives them from `missingFrom` | two functions deciding what is proposable is one too many. MISSING is whatever that function says, and held-versus-in-flight is a label on what it already excluded |
|
||||
| a wave "is small rather than just legal" — under a quarter of `MAX_PROPOSAL_BYTES` | at most 602 bytes *per entry* | the catalogue encodes to 16,832 bytes, which is 25.7% of the budget — the quarter was a guess and it failed. The per-entry cost is the thing that would actually drift, and it does not move when a language is added |
|
||||
|
||||
### One thing found on the way
|
||||
|
||||
`docs/scripts/m3-touch-targets.py` reads comments as code. A KDoc line on the
|
||||
picker's row composable explaining that it used a clickable `Card` "rather than a
|
||||
`Modifier.clickable`" was counted as a bare clickable chain, which breaks a zero
|
||||
budget and so breaks `./gradlew check`. The comment was reworded to get around
|
||||
it, which is the wrong fix -- the sentence was right.
|
||||
|
||||
`m3-audit.sh` already solves this for the colour check and says why, at
|
||||
`NOT_A_COMMENT`: "a note *about* a hardcoded colour counts as one -- which
|
||||
happened the first time a call site was fixed and the commit explained what it
|
||||
had replaced." The touch-target checker wants the same treatment, and
|
||||
`m3-title-case.py` should be looked at too, since it scans whole files.
|
||||
Reference in new issue
Block a user