Merge gh/main 08ad7b81 into fix/wpxr-empty-record-view
Every write the merged PRs added now names a view, chosen deliberately: - The keyboard commit names OpenedCell::view, captured when the editor opened, as EditTarget does for the mouse (context/code/clients.md). - RenameRecordCoordinate names no view. Its record must hold cells, so it resolves in the store alone: NamedRecord::Stored, as does the rename destination records_at_stake adds. named_records replaces cells_named as the exhaustive list records_named is read off. - #252/#265's non_item_refusal moves into Grids::unwritable. The strict view lookup (a missing view is RecordGone) and the Grids memo are kept. - Test fixtures name a view their document has: Default for host() and host_on_a_fold(), the records view for the rename pair, and the viewing client's own view in browser_round_trip. Evidence files: both sides kept, every heading of both parents verified present. Test names: the merge holds every test of both parents. 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:
@@ -1192,6 +1192,49 @@ compares **content in order**: the drawn keys rows must equal
|
||||
injection now fails. What still passes is a bypass that draws exactly what the
|
||||
builders asked for, in the order they asked — which is harmless by definition.
|
||||
|
||||
### tile_select_opens_on_a_regular_category_even_when_a_virtual_holds_row
|
||||
|
||||
improvise-52od. `opening_tile`'s rule is "the best-ranked tile", and in every
|
||||
earlier fixture its top rank, the first Regular tile, was also the first tile on
|
||||
Row. So the rival `position(|t| t.axis == Axis::Row).unwrap_or(0)`, which needs
|
||||
no wire field at all, passed the whole workspace. The fixture is a records-shaped
|
||||
bar: `_Index` on Row, `_Dim` on Column, `_Measure` on None, `Region` on Page and
|
||||
`Product` on Row. The rule answers 3 (`Region`). The Row rival answers 0
|
||||
(`_Index`), and a "first Regular on Row" rival answers 4 (`Product`), so all
|
||||
three are separated. Injected: the Row rival fails this test.
|
||||
|
||||
### with_no_regular_category_tile_select_opens_on_measure_not_index
|
||||
|
||||
improvise-bqm0. #231's rule, `position(regular).unwrap_or(0)`, fell back to tile
|
||||
0, which is `_Index`, when a view has no Regular category, which is exactly the
|
||||
bug #231 fixed. The fixture is `_Index`, `_Dim`, a Label and `_Measure`. The rule
|
||||
answers 3 (`_Measure`), then 2 (the Label) with `_Measure` removed, and 0 for an
|
||||
empty bar. Injected: #231's rule answers 0 and fails. The Row rival fails too.
|
||||
|
||||
### a_frame_whose_group_level_names_no_category_does_not_deserialize
|
||||
|
||||
improvise-e265, ChatGPT Codex's P2 on #250. A `FrameGroup.level` arrives over
|
||||
the wire, and `AxisFrame::groups` sizes its open-run stack with
|
||||
`open.resize(g.level, None)`. A frame carrying `level: 4294967295` therefore
|
||||
drove a multi-gigabyte allocation in the client instead of being refused. At
|
||||
`e44b1491` the frame deserialized without complaint. The fix checks every level
|
||||
against `cats.len()` as the frame arrives: `context/code/protocol.md` §3b.
|
||||
|
||||
The test serializes a well-formed two-category frame and checks that it reads
|
||||
back equal. That is the control. It then injects two faults into the JSON, one
|
||||
at a time: an oversized group level on the **second** marker, and a `GroupEnd`
|
||||
one level past `cats`. For each fault it asserts two things. The mutated text is
|
||||
still well-formed JSON. And the refusal names the level ("names no category"),
|
||||
so the frame is refused for its level and not for its shape. The collapsed,
|
||||
item-free frame keeps the fixture independent of `FrameEntry::Item`'s shape,
|
||||
which #275 changes.
|
||||
|
||||
Rivals, each run:
|
||||
- The `try_from` attribute removed: `unwrap_err` panics, because the frame
|
||||
parses.
|
||||
- Only the first marker checked (`.next().filter(..)` instead of `.find(..)`):
|
||||
it fails the same way, because the first marker is in range.
|
||||
|
||||
### every_composed_cell_write_names_the_view_the_client_is_on
|
||||
|
||||
improvise-wpxr: a `SetCell`/`ClearCell` now names the view whose grid drew the
|
||||
@@ -1209,3 +1252,10 @@ the Enter commit.
|
||||
- **Rival** (`clear-cell` naming `"Default"`): fails **only** this test, at the
|
||||
`clear-cell` assertion. `clear-cell` and `paste` build their command in
|
||||
`resolve` itself rather than through `typed_cell_command`.
|
||||
- **After the merge with gh/main `08ad7b81`,** the Enter commit writes the cell
|
||||
its editor OPENED on (improvise-8xq0), so the test now opens the editor on
|
||||
`Other`, moves the client to `Later`, and only then commits. The view comes
|
||||
from `OpenedCell::view`, captured at open.
|
||||
- **Rival** (the commit naming `state.view.active_view`, the view at
|
||||
`Enter`), run across the whole workspace: fails **only** this test, with
|
||||
`["Later"]` against `["Other"]`.
|
||||
|
||||
Reference in New Issue
Block a user