Problem
Phase 1 of the UI bridge (PR #793) shipped with cooperative cancel only: Esc/Ctrl-C closes the dialog modal and returns NULL/false to the dispatched script. The script handles the cancel however it wants — typically by aborting the operation.
The original design (planning/phase_c/BOXEN_USERTALK_UI_BRIDGE.md decision #3 v1) called for hard kill via flthreadkilled — Ctrl-C would cancel the dialog AND interrupt the running script. Investigation during /gate review (2026-06-23) revealed:
flthreadkilled is per-thread; boxen REPL dispatches scripts on the main thread, so setting it would also halt the main loop without careful reset semantics
- The legacy Mac Frontier mechanism (Esc-kills-thread) was acknowledged-imprecise once the runtime became multi-threaded
- All currently-known scripts (
jump, keycodes, etc.) check the dialog return and abort gracefully on cancel
JES + AI decided 2026-06-23 to defer hard-kill and revisit when a concrete script demonstrates the need.
When to revisit
Open this issue when:
- A dispatched script ignores
dialog.* cancel returns and keeps running (waste of user's intent)
- A long-running CPU-bound dispatched script needs to be killable via Ctrl-C
- A user reports "I cancelled the dialog but the script kept going"
Implementation sketch (when we get to it)
Two options:
Option A: Per-modal abort flag. Bridge sets boxen_ui_script_abort_requested = true on Ctrl-C; a hook in headless_backgroundtask (or a new yield-point check) calls langerror(abortedscripterror) if the flag is set AND the current thread is the one that opened the modal. Per-thread tracking via a tracked_thread_id field on the bridge's state.
Option B: Spawn dispatched scripts on a dedicated thread. Then flthreadkilled on THAT thread works cleanly without touching the main loop. Bigger refactor; changes the GIL access pattern for dispatch.
Option A is smaller; Option B is more architecturally clean. Pick when the concrete need arrives.
Context
Acceptance (when implemented)
Problem
Phase 1 of the UI bridge (PR #793) shipped with cooperative cancel only: Esc/Ctrl-C closes the dialog modal and returns NULL/false to the dispatched script. The script handles the cancel however it wants — typically by aborting the operation.
The original design (
planning/phase_c/BOXEN_USERTALK_UI_BRIDGE.mddecision #3 v1) called for hard kill viaflthreadkilled— Ctrl-C would cancel the dialog AND interrupt the running script. Investigation during /gate review (2026-06-23) revealed:flthreadkilledis per-thread; boxen REPL dispatches scripts on the main thread, so setting it would also halt the main loop without careful reset semanticsjump,keycodes, etc.) check the dialog return and abort gracefully on cancelJES + AI decided 2026-06-23 to defer hard-kill and revisit when a concrete script demonstrates the need.
When to revisit
Open this issue when:
dialog.*cancel returns and keeps running (waste of user's intent)Implementation sketch (when we get to it)
Two options:
Option A: Per-modal abort flag. Bridge sets
boxen_ui_script_abort_requested = trueon Ctrl-C; a hook inheadless_backgroundtask(or a new yield-point check) callslangerror(abortedscripterror)if the flag is set AND the current thread is the one that opened the modal. Per-thread tracking via atracked_thread_idfield on the bridge's state.Option B: Spawn dispatched scripts on a dedicated thread. Then
flthreadkilledon THAT thread works cleanly without touching the main loop. Bigger refactor; changes the GIL access pattern for dispatch.Option A is smaller; Option B is more architecturally clean. Pick when the concrete need arrives.
Context
planning/phase_c/BOXEN_USERTALK_UI_BRIDGE.mddecision docs: UTF-8 transition plan #3 (revised)Acceptance (when implemented)
test_06_ui_bridge.pyexercises the abort path