Merge gh/main (bb5dfe5c) into collapse-fu/b114

#217 has landed; this PR now carries only b114 and xur5.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Edward Langley
2026-09-23 08:36:48 -07:00
27 changed files with 1943 additions and 169 deletions
+129
View File
@@ -5712,6 +5712,17 @@ cannot see the feature removed from `improvise-command` alone, because
`improvise-io`, a normal dependency, enables it in the same build. That case is
held by `every_crate_that_can_parse_json_enables_float_roundtrip` (`tooling.md`).
### the_grid_and_a_csv_export_agree_on_a_fold_row
The projection-level pin PR #203's review asked to keep. The review's own
scratch test is made permanent here. Q1 = {Jan, Feb, Mar} with March hidden and
funded (50/50), so a fold that covered hidden members would read 90 / 58 / 0.36.
`grid_of` (what a client is sent) and `export_csv_to` (what a file gets) must
both read `40.00, 8.00, 0.80` on the Q1 row. The two go through different
producers (`viewport::grid_body` and `render_csv`), and both reach
`GridLayout::evaluate`. Rival: that evaluation covering every member. This test
fails with `["90.00", "58.00", "0.36"]`.
### p_onto_a_sparse_record_writes_it
improvise-q9eg, a regression introduced by PR #197 and found in its review. In
@@ -5927,3 +5938,121 @@ host's `Normal`, and nothing else different. `install_workbook` needs no
change of its own, because both of its callers (`LoadModel`,
`AcceptWizardModel`) run inside `apply_effects`, which settles after the batch.
### `an_untouched_pivot_edit_of_a_misread_value_writes_nothing`
### `an_untouched_records_edit_of_a_misread_value_writes_nothing`
**improvise-ixxx.** After umi4 the seed was exact, but the commit still ran it
through `typed()`, which reads text and not the cell the text came from. So
`i` then `Enter` with nothing typed stored `Number(7.0)` over `Text("007")`,
and `Text("ERR:boom")` over a raw `Error("boom")`. The values are the ones
where `typed(edit_text(v)) != v`: `"007"`, `"1e3"`, `"inf"`, `"2024"` and a raw
`Error`. They use `no_op_commit`, the umi4 tests' own path: the real key path,
on (West, Revenue), which is row 1 and never the first cell.
Both failed before the fix. With the list as written they failed on
`Text("007")` stored as `Number(7.0)`. With `Error("boom")` moved to the front
they failed on it, stored as `Text("ERR:boom")`, so the error case is red on
its own and not only behind the text one. **Rival:** `untouched` answering
`false` always, i.e. the fix removed. Both fail again.
`no_op_commit` now also asserts that the buffer after `i` is
`value.edit_text()`. **That assertion is what keeps the umi4 tests above
alive.** With ixxx fixed, an untouched commit writes nothing, so a seed
regressed to the rounded `Display` is never written either, and
`an_untouched_{pivot,records}_edit_stores_the_identical_value` pass with umi4
reverted. That was run: with the seed assertion removed and
`display_value_in` seeding from `to_string()`, all six untouched tests pass.
With the assertion in, both umi4 tests fail.
### `an_untouched_edit_does_not_overwrite_a_write_made_while_it_was_open`
The reviewer's first constraint on improvise-ixxx: the seed is the one
**captured when the editor opened**. The test opens the editor on
`Text("007")`, then applies a `SetCell(Number(5.0))` directly, standing in for
another client's write that lands while the editor is open. Then it presses
`Enter` with nothing typed. The cell must still be `5`.
Failed before the fix: the commit wrote `Number(7.0)`. **Rival:**
`commit_at_cursor` taking the seed from `ctx.display_value`, which is
recomputed at commit time, instead of `ctx.opened_editor`. This test fails
alone, with `Number(7.0)`, and every other untouched test passes. So it is the
only guard on the choice of seed, and a fixture where the cell does not move
cannot tell the two seeds apart.
### `an_untouched_commit_still_advances_and_reopens_the_editor`
The reviewer's second constraint: only the **write** is skipped. The fixture
puts `Text("007")` at (West, Cost), row 1 and column 0. `Enter` there advances
to (0, 1) rather than aborting at the corner, which is where (West, Revenue)
sits in pivot mode. The test asserts four things: the cell is unchanged, the
cursor moved to (0, 1), the mode is editing again, and the reopened editor
captured `"2"`, the cell it landed on.
**Rival:** `CommitAndAdvance::execute` returning straight after the mode change
when untouched, which skips the advance along with the write. This test fails,
and so do `tab_on_an_empty_new_measure_column_still_starts_a_record_row` and
`ui::app::tests::tab_on_bottom_right_of_records_inserts_below`. Those two are
the records Tab contract: the empty `+` column's seed is `""`, so an empty Tab
there is now an untouched commit too.
The buffer after `Enter` is **not** asserted. The keymap welds `clear-buffer`
after every commit key, so it empties the buffer `EnterEditAtCursor` has just
seeded, and the reopened editor opens blank while its captured seed is `"2"`.
That is existing behaviour (`enter_commits_the_cell_advances_and_re_enters_editing`
in `clients.md`). An `Enter` there with nothing typed therefore clears the landed cell,
measured here; that is filed as improvise-fy9o rather than fixed here.
### `an_editor_typed_back_to_its_seed_still_writes`
**improvise-2054**, found by the #205 review. `untouched` compared content
only, so an edit that ended back on the seed text was treated as untouched. The
test opens the editor on `Number(7)` at (West, Revenue), which is row 1 and
column 1. It then applies `SetCell(Number(5))` as another client's write,
presses Backspace and `7`, and presses Enter. The cell must be `7`. After the
Backspace alone, the test also asserts `opened_editor.touched` is set.
Failed before the fix: the cell stayed `Number(5.0)`, and nothing told the
user. **Rivals:**
- `untouched` ignoring `touched` fails this test.
- `PopChar` not marking fails this test at the post-Backspace assertion.
- `AppendChar` not marking cannot fail it, because the pop has already marked
the editor. That rival fails `appending_or_popping_marks_the_editor_touched`,
which presses each key on its own.
### `an_editor_opened_by_enter_mode_does_not_inherit_an_earlier_seed`
**improvise-wv3h.** Deleting `SetOpenedEditor(None)` from `EnterMode` failed
no test. The reviewer's repro types `007` after `:enter-mode editing`, and it
no longer discriminates now that improvise-2054 marks the editor on the first
append, so this test commits with **nothing typed**. The steps:
1. `i` on an empty cell, (North, Cost), captures the seed `""`.
2. Esc. `clear-buffer` does not mark the editor, so that stale seed stays
untouched.
3. Move to (West, Revenue), which holds 2.
4. `:enter-mode editing`. That is typed into the `command` buffer, which also
does not mark the cell editor.
5. Enter, with the edit buffer `""`.
The cell must be cleared. **Rival:** the guard deleted. This test fails alone,
leaving `Number(2.0)`: the empty commit was skipped against the earlier
editor's seed.
This test is only possible because `clear-buffer` and keys typed into another
buffer do not mark the editor. A rule that marked on every buffer write would
make the guard redundant, and no test could pin it (`protocol.md` §3).
### `command::cmd::commit::tests::the_editor_an_advance_reopens_starts_untouched`
**improvise-465t**, found by the #205 re-review. Every open resets `touched`,
but no test pinned the reset on the editor that `CommitAndAdvance` reopens
through `EnterEditAtCursor`. The test works on the 2×2 pivot. It presses `i`
on (West, Cost), row 1 and column 0, types `9`, and asserts the first editor
really is touched. Then it presses Enter. The cursor must land on (0, 1), and
the reopened editor must be exactly `OpenedEditor::on("2")`, which means seeded
from the landed cell and untouched.
**Injection:** `EnterEditAtCursor` carrying the previous editor's `touched`
flag. This test fails alone. Every other test stays green, which was the gap.
Once improvise-fy9o re-seeds the reopened editor, a stale `touched` would make
every untouched Tab or Enter write its seed.