Let the candidate restore the starter code

Merged
RW
1d ago
+1990-19

Adds a restore control beside the language picker that puts the current language's starter back, as accepted in #348.

The starter goes in through insertText over just the span that differs, so one Ctrl+Z restores the previous buffer. A browser without that command, or one that refuses it, would have to assign the buffer and leave nothing to undo; there the first press leaves the code alone and only arms the control, and a second press confirms. Chromium redoes a replaced selection that ends in a newline wrongly, so for the restore only, that newline is removed by a forward delete in the same undo step. Undo does not survive a language switch, which holds for any edit and is #365's subject. The control is disabled while paused and in the behavioral round, and does nothing once coding is closed.

The reset is an ordinary code_update, so no message type, recording kind or contract version changes. A Test credit already recorded survives it: reconcile_received_test (src/agent.rs:2776) appends a Test row only while test_recordable (src/agent.rs:2171) holds, and nothing removes a recorded row, since evict_one_observation (src/agent.rs:1515) never takes a phase's only one. A reset before the run is recorded stops it, so the candidate must write and run again.

Screenshots, from a page with no interview running: an edited buffer, the code after one press, after Ctrl+Z, the control dimmed while paused, a 390 px wide screen, and the prompt shown by a browser without insertText
1-edited-code
2-after-one-press
3-after-ctrl-z
4-toolbar-paused-disabled
5-narrow-390px-after-one-press
6-fallback-first-press-armed-simulated

Validation: restore-starter.test.js adds 52 tests, and each deliberate breakage I tried fails at least one. ./scripts/test.sh passes with 1599 browser and 1886 Rust tests; skipped locally are commentflow, actionlint and the Linux-only Clang fetch. I also restored the starter in every offered language of all 151 problems (747 cases): one press restores, and undo and redo are exact. A live LiveKit and Gemini session was run on an earlier revision, where the first press armed, and not repeated.

Limits: the toolbar wraps to a second row at 590 to 620 px, and the icon-only control relies on its tooltip and aria-label. In Playwright's WebKit a restore joins the typing before it, so one Cmd+Z undoes both. Safari's click-without-focus behaviour is modelled in a test, not tried in real Safari. Firefox could not be launched here, so it is unchecked whether it records the insert and the forward delete as one undo step.

Closes #348


Summary by cubic

Adds a Restore starter button to the editor toolbar so a candidate can put the current language's starter code back and start over. The reset goes through the browser's editing command over just the differing span, so one Ctrl+Z (Cmd+Z on Mac) restores the previous buffer; a trailing newline is handled separately to avoid a Chromium redo bug. In browsers without a working editing command, the first press only arms the control and a second press confirms, both in the toolbar. Only the current language's buffer changes, the reset sends as a normal code_update, and the button is inert while paused, in the behavioral round, or after coding closes. Closes #348.