improvise-c5ip, improvise-udt2: exit 1 on a refusal, never on an abort

The headless exit code read `last_batch_aborted()`, which answers "did a chain
stop", not "did the request happen" — wrong both ways. `commit-cell-edit` at
bottom-right lands its write, saves, and then `EnterAdvance`'s `AbortChain`
exited 1 (c5ip); `add-item` into a missing category refuses without aborting
and exited 0 (udt2).

`App` gains a per-batch `batch_refused`, reset beside `batch_aborted` and
written only by `App::refuse(msg)`, which sets the status and the flag
together; commands reach it through `effect::refuse`. `main.rs` exits 1 on
`last_batch_refused()` only. Not a severity on `status_msg`: that would be
portable ViewState and would go stale across its ~60 writers.

Strays into ui/app.rs (four small additions) — flagged in the hand-back.
Unconverted refusals are filed as improvise-i3o5; headless `q` as improvise-ep5o.

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 21:28:44 -07:00
parent 487f0b6fef
commit ffe8aed6b4
14 changed files with 281 additions and 53 deletions
+50
View File
@@ -498,3 +498,53 @@ fn a_script_writes_the_same_record_whatever_terminal_ran_it() {
"the same script hid a different record at a different terminal size"
);
}
/// Evidence: `context/test-evidence/cli.md`.
#[test]
fn a_commit_whose_advance_has_nowhere_to_go_still_exits_zero() {
let scratch = Scratch::new("commit-tail");
let doc = three_cells(&scratch, "tail.improv");
let out = run_cmd(
&["move-selection 2 0 . commit-cell-edit editing 9 Region/South"],
&doc,
);
assert_eq!(
value_of(&doc, "South").as_deref(),
Some("9"),
"the write did not land"
);
assert!(
out.status.success(),
"the write landed and was saved, yet the run exited non-zero: {:?}",
stderr_of(&out)
);
let empty = scratch.path("empty.improv");
let out = run_cmd(
&["add-category Foo . commit-cell-edit editing 5 Foo/x"],
&empty,
);
assert!(
out.status.success(),
"a commit on an empty grid landed and exited non-zero: {:?}",
stderr_of(&out)
);
}
/// Evidence: `context/test-evidence/cli.md`.
#[test]
fn a_refusal_that_only_writes_a_status_exits_non_zero() {
let scratch = Scratch::new("refusal-exit");
let doc = seeded(&scratch, "m.improv");
let out = run_cmd(&["add-item Nonexistent Thing"], &doc);
assert!(
stderr_of(&out).contains("Nonexistent"),
"the refusal was not reported, so its exit code proves nothing: {:?}",
stderr_of(&out)
);
assert!(
!out.status.success(),
"a refused command exited 0: {:?}",
stderr_of(&out)
);
}