kb: a Record is the settable arm, not the unsettable one

invariant(shipped_demo_cells_are_settable_or_derived) described the
CellId::Record arm as "editable false". The boolean in the cited test is
expected_derived, not editability, and the assertion message beside it says
the two raw columns "must be Records the page offers" -- so a Record is
precisely the SETTABLE arm and the clause stated the inverse permission.

That is the failure doctrine(a_stale_gotcha_asserts_the_negation) names: a
wrong doc does not merely omit, it tells the reader not to assume the thing
that is true. Costly here because ADR 002 makes permission a fact about the
CellId variant, so a reader trusting this clause had both permissions backwards.

The replacement names the error rather than only avoiding it, so it cannot
come back quietly. Verified against tests/web_demo_model.rs, not from memory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
This commit is contained in:
Edward Langley
2026-09-20 15:54:00 -07:00
parent 206c12b98f
commit 2d22b65d1f
+1 -1
View File
@@ -93,7 +93,7 @@ invariant(grid_extent_is_the_whole_grid,'project::grid_of reads GridExtent from
invariant(client_frame_commands_is_a_batch,'One keypress resolved client-side is SetSelected plus the offsets viewport_effects returns; a host that folds one and not the other projects the wrong window. Since improvise-955n a frame is answered WHOLE by CheckedBatch::against before anything is applied, so Applied::Rejected is unreachable through Host::commands. Clause 4 (all-or-nothing on an apply-time failure) is NOT delivered: App::apply_effects aborts without undoing.').
invariant(opfs_index_holds_documents_not_entries,'OpfsFs::list joins dir like the other two backends, so storage_contract takes dir as a parameter and the three agree at EVERY directory (improvise-vhcz), not only where joining is the identity. The index holds DOCUMENTS: attach indexes nothing (what it creates is zero bytes), write indexes the name and un-queues a pending delete, refresh rebuilds from OPFS skipping zero-byte entries but counting an unmeasurable one as a document, since the only cause is another tab holding the exclusive handle (improvise-vvl3).').
invariant(async_seam_does_not_survive_boxing,'OpfsFs::open/attach/refresh/commit_deletes are on the struct, not on Storage, and App::storage is a Box<dyn Storage>: handing the backend to the App puts the seam permanently out of reach. The host holds the concrete backend and gives the App a shared handle, which is impl<T: Storage + ?Sized> Storage for Rc<T> in improvise-io (improvise-hmws) -- there because the trait is local there, blanket because nothing about it is OPFS-shaped, and Rc not Arc because wasm32 has one thread.').
invariant(shipped_demo_cells_are_settable_or_derived,'web/demo.improv projects CellId::Record for its two raw measure columns and CellId::Derived for Profit, which a formula owns -- never an Aggregate. Guarded twice and two-sidedly, in tests/web_demo_model.rs against grid_of (the two arms are CellId::Record(_) with editable false and CellId::Derived{target} with target == \"Profit\") and in post_message.rs against the real seed-VFS-open-connect-Snapshot chain. Before improvise-ir7l both guards said \"every cell is a Record\" and PASSED while that was false for a third of the landing-page grid.').
invariant(shipped_demo_cells_are_settable_or_derived,'web/demo.improv projects CellId::Record for its two raw measure columns and CellId::Derived for Profit, which a formula owns -- never an Aggregate. A Record is precisely the SETTABLE arm; Derived is the one no write is constructible for. Guarded twice and two-sidedly, in tests/web_demo_model.rs against grid_of and in post_message.rs against the real seed-VFS-open-connect-Snapshot chain. Read that test boolean carefully: it is expected_derived, NOT editability, so the arms are (CellId::Record(_), expected_derived false) and (CellId::Derived{target}, expected_derived true, target == \"Profit\") -- describing the first as \"editable false\" states the inverse permission, which is what this clause said until it was corrected. Before improvise-ir7l both guards said \"every cell is a Record\" and PASSED while that was false for a third of the landing-page grid.').
invariant(matching_cells_yields_insertion_order,'DataStore::matching_cells/matching_values return the primary IndexMap order. Measured at 18,000 cells: +20% worst case on matching_values, matching_cells 7% FASTER because sorted positions resolve CellKeys with better locality.').
invariant(a_stored_fit_names_only_what_the_document_holds,'fitted_formula refuses a tree splitting on a feature Model::find_item_category cannot resolve. It asks the DOCUMENT, not the name shape: a measure literally named Region=North is legal and indistinguishable from a one-hot as a string.').
invariant(the_frame_is_answered_once_not_the_command,'Since improvise-955n, CheckedBatch::against answers a whole ClientFrame::Commands before anything is applied. The two DOCUMENT tiers (document_generation, layout_version) hoist to the frame; the RECORD tier does not, because which records are at stake is a property of the command (records_named). Hoisting all three was a lost update: [SetCell(North), SetCell(South)] overwrote a South another client had moved, silently, invisible to the other two tiers because a SetCell is CellData. Every mutation answers for its own records against the FRAMEs basis -- never its own field, or a later command could claim a fresher picture than the frame was composed under.').