One classifier for a typed string, one exhaustive walk over Rejection
improvise-j7v6: the rule turning a typed string into a `CellValue` was written twice — `resolve::typed` (already moved into improvise-protocol since the ticket was filed) and `commit_regular_cell_value`'s if/else-if/else on the host's key path. The host now calls `improvise_protocol::typed`, which is `pub` for that reason. Per doctrine(a_consolidation_that_keeps_its_compatibility_test_is_unfinished), `a_typed_string_is_classified_as_the_host_classifies_it` did not survive as a comparison: type identity replaced its claim. It is re-scoped to the thing this crate still owes — the FRAME the string composes — and renamed `a_typed_string_composes_the_frame_that_carries_it`. The ticket's flagged risk (gotcha 34: a shared classifier that disagrees with the persistence layer is a third answer) is now asserted rather than argued: tests/typed_string_agreement.rs round-trips what `typed` calls text and what it calls a number through format_md/parse_md. Proved discriminating: dropping `pipe_quote` from the writer fails it. improvise-8uj8: `every_rejection_message_says_the_edit_did_not_land` drove a hand-written five of seven `Rejection` variants while claiming the fact held "over all of them". `Rejection::all` (the same cyclic walk `AppMode::all` uses) and `Rejection::refused_an_edit` (exhaustive) now drive it, and its claim is re-scoped to what is true: a rejection that refused an EDIT says nothing was applied, and the two Save answers — which refused no edit — say the document was not written. Renamed `every_rejection_message_says_what_it_refused`. Proved both ways: wording SaveFailed as "hmm" fails the test, which the old list could not have seen; adding a Rejection variant fails the build at basis.rs:101 and :126. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
This commit is contained in:
@@ -318,16 +318,12 @@ mod tests {
|
||||
/// Commit a cell value: a synthetic records key stages into the drill or applies
|
||||
/// directly in plain records mode; a real key writes to the model (gotcha 19).
|
||||
fn commit_regular_cell_value(key: &CellKey, value: &str, effects: &mut Vec<Box<dyn Effect>>) {
|
||||
if value.is_empty() {
|
||||
effects.push(Box::new(effect::ClearCell(key.clone())));
|
||||
} else if let Ok(n) = value.parse::<f64>() {
|
||||
effects.push(Box::new(effect::SetCell(key.clone(), CellValue::Number(n))));
|
||||
} else {
|
||||
effects.push(Box::new(effect::SetCell(
|
||||
key.clone(),
|
||||
CellValue::Text(value.to_string()),
|
||||
)));
|
||||
}
|
||||
// The classification is the protocol's, not a second copy of it: the
|
||||
// browser composes `SetCell` from the same rule (improvise-j7v6).
|
||||
effects.push(match improvise_protocol::typed(value) {
|
||||
Some(value) => Box::new(effect::SetCell(key.clone(), value)) as Box<dyn Effect>,
|
||||
None => Box::new(effect::ClearCell(key.clone())),
|
||||
});
|
||||
}
|
||||
|
||||
/// Stage a synthetic edit in drill state so it can be applied atomically on exit.
|
||||
|
||||
Reference in New Issue
Block a user