ApplyAndClearDrill walked pending_edits, a HashMap, and applied each edit on
its own. A rename moves the row's cells, so a measure edit replayed after it
wrote the old key. That left a ghost record there and a stale value in the moved
record. A second rename on the same row always found nothing and was dropped.
Across rows, a swap lost one record's data in either order.
RecordRewrite::of builds each row's final record once. It reads unedited values
off the model before anything is written, and applies every rename to every
cell. RecordRewrite::merged puts every clear before every write, in snapshot row
order. The plain records path calls the same function with its one edit, so
rename_record_coordinate and the drill's own copy are gone (gotcha 19).
Reasoning: context/code/command.md, RecordRewrite.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
The required Browser harness check comes from a job that needs: build, so for
a moment per push every registered check is green and GitHub says
MERGEABLE/BLOCKED. #186 at 128a2a0 refused that and exited 1 on healthy PRs.
BLOCKED with no failed check is now waited on (exit 3 if it never clears).
Adds the gap sequence from PR #189's real rollup, and a head moving during
the UNKNOWN wait. Corrects tooling.md's claim that nothing else produces
BLOCKED, the evidence entry's rival-2 claims, and the fixture wording.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
CellValue's Display writes a non-whole number {:.4}, and every editor seed
was that string, so i then Enter on an untouched 1.23456789 stored 1.2346,
in the TUI (pivot and records) and in the browser, which seeds from the
projected edit_text. CellValue::edit_text is now the one home of the seed:
the shortest decimal that reads back as the same f64 (non-finite values
take the core.md §16 token). display_value_in's two arms and
cell_display's records arm all go through it; the now-orphaned
GridLayout::resolve_display is removed.
Text that reads as a number (007) is exact in the seed but still
reclassified by typed(); filed as improvise-ixxx.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
The restated list said cargo fmt --all --check, which reaches one of two
workspace roots, and omitted direnv exec, checkers.sh and node-test.sh.
agent-rules gains two rules from PRs #176 and #177.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
Only the .agents copy is edited: .claude/skills/pr-watch becomes a symlink to
it in the improvise-5fzx PR, and editing both here would make that PR's merge
a modify/delete conflict.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
GitHub reports UNKNOWN for a while after the base moves, and PRs #172 and
#179 both exited 0 there. UNKNOWN is now waited on (exit 3 on timeout), a
failed check or CONFLICTING ends the wait, and the pass condition is
MERGEABLE with CLEAN, UNSTABLE or HAS_HOOKS. BLOCKED, DIRTY, BEHIND, DRAFT
and any unshipped state fail closed. The suite enumerates the whole table.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
grouped.spec.js asserted a collapsed group contributes no rows (8 data rows).
It now contributes one per Store (10), labelled Upland, and its cells are
not editable. The editable assertion was checked against cell_id without
folds_a_group: it fails with 6 editable cells where 0 are expected.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
gh/main's vocabulary_is_complete requires every effect to be on the wire or
named with a verdict. Refuse's portable half is its status text; the flag is
one host batch's outcome (context/code/cli.md §10).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
delete-formula-at-cursor, switch-view-at-cursor and delete-view-at-cursor
were asserted with the cursor at 0 of a one-element list, where the item
under the cursor and the first item are one item. A DeleteFormulaAtCursor
hard-wired to index 0 passed the whole workspace. Now each cursor sits at
index 1 of a longer list; the index-0 rivals fail.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
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