Merge remote-tracking branch 'gh/main' into fix/help-keys-checks

# Conflicts:
#	context/test-evidence/clients.md
#	context/test-evidence/protocol.md
This commit is contained in:
Edward Langley
2026-09-22 22:30:19 -07:00
41 changed files with 2717 additions and 460 deletions
+76 -5
View File
@@ -557,7 +557,7 @@ the evidence that nothing was relying on the permissive parse.
### render::tests::two_runs_under_two_headers_of_one_name_are_two_runs
### render::tests::the_two_headers_are_equal_as_values_so_comparing_cat_and_name_cannot_split_them
### render::tests::the_two_headers_are_equal_as_values_so_comparing_them_cannot_split_them
improvise-h0iv. `group_runs` coalesced adjacent positions by group **name**, so
two runs under two different headers sharing a name read as one and both front
@@ -571,10 +571,12 @@ and nothing ungrouped between the runs. Before the fix it returns
at the precondition rather than pass with a single run.
The second test exists because the ticket proposed the wrong fix and a reader
will propose it again. h0iv says `FrameGroup` carries `cat` and "comparing the
pair would fix it" — but its own reachability case is a single category nested
under an outer one, so both headers are `(Month, Q1)`, equal as values. The test
asserts that equality directly. What actually separates them is that they are
will propose it again. h0iv said `FrameGroup` carried `cat` and that "comparing
the pair would fix it". But its own reachability case is a single category
nested under an outer one, so both headers are `(Month, Q1)`, equal as values.
The test asserts that equality directly. Since improvise-7xyx removed
`FrameGroup::cat`, it asserts equality of the whole header, which is stronger:
no field-wise comparison can separate two equal values. What actually separates them is that they are
two distinct entries in `self.entries`, which `std::ptr::eq` on the borrowed
header states exactly.
@@ -970,6 +972,27 @@ give `None` and fail. Asserting only that `"command"` survived would pass under
either behaviour, which is what the old spelling amounted to for the cleared
key.
### render::tests::a_cell_equals_another_exactly_when_the_wire_cannot_tell_them_apart
`CellDisplay`'s equality is what the grid diff and the seed property run on
(improvise-4w09). It compares `value` by `same_on_the_wire`: bits, except that
every NaN is equal. It pins both clauses, since `a_grid_holding_nan_quiesces`
can see only one of them. That test compares a NaN with its own bits,
in-process.
- A NaN with the sign bit set, the shape `0.0 / 0.0` produces on x86, equals
`f64::NAN`, the shape `parse_nonfinite("nan")` gives a client. Both go out as
the one token `"nan"`.
- `0.0` differs from `-0.0`: serde_json writes them as `0.0` and `-0.0`, so a
change between them is real and must be sent.
- `Number(7.0)` differs from `Text("7")`, and a value differs from none.
**Faults injected:**
- `f64 ==` (the pre-fix semantics). Fails at the NaN case.
- Bit equality only. Fails at the NaN case, while `a_grid_holding_nan_quiesces`
**passes**, which is why this test exists.
- `f64 ==` plus the NaN clause. Fails at the `0.0`/`-0.0` case.
### vocabulary_is_composed::a_variant_named_only_in_a_comment_or_string_is_not_composed
improvise-c7mu, found by the post-merge review of PR #160. `constructed_in` ran
@@ -1030,6 +1053,54 @@ A field added to an existing variant is caught too, but not in isolation,
because every constructor of that variant also fails. Reverted with
`git restore`.
### source_scan::tests::a_test_only_item_hides_nothing_after_it
improvise-59q8, found by the PR #172 review. The scanner's line-based
`strip_test_items` looked for `}` at the attribute's indentation, or for an item
line ending in `;`. So three shapes were never bounded, and it dropped
**everything to the end of the file**:
- a test-only `const … = &[\n … \n];`;
- a `#[cfg(test)] let x = foo(\n 1,\n);` statement;
- a one-line `#[cfg(test)] use foo::bar;`, where the attribute's own line is
also the item line.
In `vocabulary_is_complete` that silently hides every effect after such an
item. Each shape is a case here, asserting that the production code after it
(`Hidden1`, `Visible`) survives. Against the line scan all three failed; the
first printed `"impl X {\n"` and nothing else. They now pass because items are
bounded by balanced brackets on the blanked code.
`an_unbounded_test_only_item_is_refused_not_swallowed` pins the other half of
the acceptance criteria: an item that cannot be bounded panics instead of
consuming the rest of the file. Against the line scan it failed, because
nothing panicked.
### source_scan::tests::a_test_only_cfg_is_recognised_whatever_its_spelling
improvise-59q8, the other direction: test code counted as production, which
makes `vocabulary_is_composed` weaker. `cfg(all(test, not(target_arch =
"wasm32")))` was kept because the old rule rejected any line containing
`not(`. A leading `#![cfg(test)]` was kept because only `#[cfg(` was
recognised. An attribute split across lines was not seen at all. All three
failed against the old scanner. The predicate is now parsed and evaluated in
three-valued logic (`context/code/protocol.md` §2). The controls
(`cfg(not(test))`, `cfg(any(test, feature = "serde"))` and `cfg(target_arch =
…)`) must stay production, so a scanner that dropped every `cfg` item could
not pass.
A consequence to know about: `cfg(any(test, feature = "x"))` for an ordinary
feature is now production. Only `feature = "test-support"`, the one test
feature this repo has, counts as a test build.
`test_only_items_and_modules_are_not_production` was updated to that spelling.
### source_scan::tests::a_c_string_literal_is_blanked
improvise-59q8's minor case. In `cr#"x" Command::InRawC(2) "y"#` the `r` has a
word character before it, so the literal was lexed as two ordinary strings,
and the text between the inner quotes leaked. It failed as
`InRawC survived`. `c"…"` and `cr#"…"#` are now literals. A first version of
this test used a C string with no inner quotes and passed against the bug,
because the ordinary lexing happened to blank it too.
### help::tests::no_help_row_spells_a_key_by_hand
improvise-wk18. The help pages had one kind of row whose keys the keymap never