WIP: docs and evidence for h3y7 forward guard, hkbc and c7mu

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-22 20:56:44 -07:00
parent 1b76fa5355
commit 77c2471bcc
3 changed files with 114 additions and 10 deletions
+30 -10
View File
@@ -218,14 +218,33 @@ its verdict. The list is checked in **both** directions, so an entry that starts
being composed fails just as loudly as one that stops
(`doctrine(a_stale_list_of_what_is_missing_is_worse_than_no_list)`).
Two limits are worth stating, because the check is a source scan.
`#[cfg(test)]` items are dropped by a line scan that relies on rustfmt putting
an item's closing brace at the attribute's own indentation; over-stripping would
**fail** the test rather than pass it, which is the safe direction. And a
`Command::X` inside `matches!` or `if let` is read as a construction rather than
a pattern, which can only make the check *weaker* for that variant — never raise
a false alarm. A variant nothing composes at all is immune to both, since its
only pattern occurrence is its own fold arm, which `=>` identifies.
The check is a source scan, and **what counts as source has one home**:
`improvise_protocol::source_scan::production_code`, shared with the forward
guard below (improvise-c7mu). It removes three things a scan must not see.
- **Comments and literals.** Both are blanked, and newlines are kept. Before
this, a `// TODO: Command::SetYanked(...)` left where the real composer had
been deleted still passed all four tests. That is the *weaker* direction, the
one a scan weakness was supposed to be unable to go. It was live in a small
way: a `///` in `project.rs` named `Command::SwitchView`, which has real
composers, so no verdict was wrong yet. It also had a mirror: a comment
explaining that a `NOT_COMPOSED` variant is held back would have raised a
false "stale entry" alarm.
- **Test items inside a file.** A line scan that relies on rustfmt putting an
item's closing brace at the attribute's own indentation. It treats
`cfg(any(test, …))` as test code and `cfg(not(test))` as production.
Over-stripping **fails** the test rather than passing it, which is the safe
direction.
- **Test-only files.** A `#[cfg(test)] mod x;` makes `x.rs` and everything under
`x/` test code, even though nothing inside the file says so. Before
improvise-c7mu, this checker's own file and `improvise-io`'s
`roundtrip_tests.rs` were scanned as production.
One limit remains. A `Command::X` inside `matches!` or `if let` is read as a
construction rather than a pattern. That can only make the check *weaker* for
that variant; it never raises a false alarm. A variant nothing composes at all
is immune, since its only pattern occurrence is its own fold arm, which `=>`
identifies.
### And forwards: every effect is on the wire or has a verdict (improvise-h3y7)
@@ -254,8 +273,9 @@ kinds, and the check verifies each kind:
improvise-2mqz).
The list is also checked in reverse. An entry that is now on the wire fails,
and so does an entry that names no effect. A test-only fake effect is scanned
on purpose. It fails loudly and never passes silently.
and so does an entry that names no effect. The scan is `production_code`, so
the comments, strings and test fakes that name an effect do not count as
effects. If they did, a stale verdict could outlive the effect it names.
What it does **not** check is whether a same-named pair *agrees*: whether
`reduce_view`'s arm does what the effect does. The name match is the
+24
View File
@@ -4903,3 +4903,27 @@ The control for the test above, and it is stated separately rather than folded
in so that a change making the fixture's load stop rebasing fails *here*, where
the message says what actually broke, rather than turning the rollback test
green by emptying it.
### ui::reduce::vocabulary_is_complete::every_effect_is_on_the_wire_or_has_a_verdict
improvise-h3y7, the forward direction of the vocabulary derivation. It is the
direction `ViewBack`/`ViewForward` failed: they were missing, so no client ever
had a back history. The test scans this crate's production `src/` for
`impl Effect for X` and `simple_effect!(X`. That covers both spellings, and the
h3y7 audit's brace-matcher missed nine effects by seeing only the first. It
then requires each name to be a `Command` or `ModelCommand` variant (read off
serde's derive) or to carry a `NOT_ON_THE_WIRE` verdict.
Faults injected, together: `HelpPageNext`'s verdict replaced by one for
`SetSelected`. This test failed naming `HelpPageNext`, and
`the_verdict_list_names_nothing_that_is_on_the_wire` failed naming
`SetSelected`. Separately, `HelpPageSet`'s verdict was pointed at
`Command::HelpPag`, and
`the_verdict_list_names_only_real_effects_and_real_variants` failed.
`the_scan_reaches_every_way_an_effect_is_declared` pins one effect of each
spelling plus `SetTransientPrefix` (which lives in `command/keymap.rs`). A
broken walk therefore fails that test instead of shrinking the set.
`an_effect_named_only_in_a_comment_or_string_is_not_an_effect` shares
improvise-c7mu's fault. With `code_only` made the identity, it failed with
`["SaveAs", "ExportCsv", "Real", "SetYanked", "AlsoReal"]`.
+60
View File
@@ -969,3 +969,63 @@ That assertion is the discriminating one: a fold arm that removed the key would
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.
### 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
over raw source text, so any `Command::X` counted as a composer, including one
inside a comment or a string. The review deleted the real `Command::SetYanked`
composer from `resolve.rs`, left `// TODO: Command::SetYanked(value)` in its
place, and all four tests passed. The test feeds the whole per-file pipeline a
line comment, a block comment and a string that each name a variant, and
asserts that none of them counts. A positive control asserts that a real
construction still does.
Fault injected: `code_only` made the identity function. This test failed with
`["SetYanked", "SetSearchMode", "ChangeMode"]`, and so did
`source_scan::tests::comments_and_literals_are_blanked_and_code_is_kept`. The
four whole-tree tests stayed green under that fault. This confirms the review's
finding that no live comment gives a wrong verdict *today*, and it is the
reason the property has to be pinned on a fixture rather than on the tree.
The fault on the real tree (deleting `resolve.rs`'s composer) was not rerun
here. `resolve.rs` is outside this lane, and the edit was refused as another
agent's ground.
### source_scan::tests::a_test_only_module_file_is_not_production_code
improvise-c7mu, the second half. `#[cfg(test)] mod x;` makes a whole file test
code, and nothing inside the file says so. The old scan saw it as production,
and that included this checker's own file. The test builds a fixture tree:
`lib.rs` declares `mod p;` and `#[cfg(test)] mod t;`, and `t.rs` declares a
nested `mod deeper;`. It asserts that `production_code` returns exactly
`lib.rs` and `p.rs`.
Fault injected: the file filter in `production_code` made always-true. This
test failed with `["lib.rs", "p.rs", "t.rs", "t/deeper.rs"]`. Before this
fixture existed, the `improvise-protocol` and `improvise-command` lib suites
**stayed green** under the same fault, and so did
`test_only_items_and_modules_are_not_production`, which checks the helpers one
by one. The wiring between them was untested until this fixture existed.
### reduce::tests::every_model_command_field_is_position_free
improvise-hkbc. improvise-6nsd's "a stale layout tier cannot misdirect a
mutation" holds only while no `ModelCommand` carries a row or column. The guard
is the signature of `position_free`. It destructures every variant with no `..`,
down into `RecordCell`, and hands each field to a function that accepts only
`&str`, a path, a `RecordHash`, a `CellValue`, an `Axis` or an optional name.
The `#[test]` only keeps that signature compiled and reached.
Faults injected, one per half, each compiling only `improvise-protocol`:
- A new variant `ScrollTo { row: usize }`, also added to `records_named`'s
or-pattern the way an author would. The lib built. The test build failed
with `non-exhaustive patterns: ScrollTo` **at `position_free` and nowhere
else**.
- The same variant classified as `ScrollTo { row } => name(row)`. The test
build failed with `expected &str, found &usize`.
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`.