From 61dcf6305aa6151d125cb91230def6cd8c27f5b4 Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Wed, 21 Oct 2026 02:00:54 -0700 Subject: [PATCH] fix(workspace): one inert handle for aborted history and prompt-block mounts An aborted parent no longer gets a separate never-called stub per method: mountRecordedHistory returns its hoisted openRun (it answers false before reading later state), and mountPromptBlocks returns one shared no-op for update, setState, setTitle and dispose. This keeps the history.mjs and prompt-blocks.mjs function-coverage floors (98) without lowering them. Tests: test:coverage (Chromium and touch, 922 workflows) passes for all 61 files; it failed before on history.mjs 94.44 and prompt-blocks.mjs 93.75 function coverage. --- web/js/workspace/history.mjs | 3 ++- web/js/workspace/prompt-blocks.mjs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/web/js/workspace/history.mjs b/web/js/workspace/history.mjs index a3eef46..d7e65c0 100644 --- a/web/js/workspace/history.mjs +++ b/web/js/workspace/history.mjs @@ -31,7 +31,8 @@ function place(parent, node, before) { export function mountRecordedHistory(container, {api, positiveId, parentScope, sender, visit = {}, onParentRevalidate, onRecordedCount}) { const scope = createScope(), dispose = () => scope.dispose(); - if (parentScope.signal.aborted) {dispose();return {dispose, openRun:() => false};} + // openRun is a hoisted declaration: on an aborted parent it answers false before reading any later state. + if (parentScope.signal.aborted) {dispose();return {dispose, openRun};} parentScope.signal.addEventListener('abort', dispose, {once:true}); scope.cleanup(() => parentScope.signal.removeEventListener('abort', dispose)); const section = el('section', undefined, 'library-surface recorded-history'); diff --git a/web/js/workspace/prompt-blocks.mjs b/web/js/workspace/prompt-blocks.mjs index ed05730..08f827a 100644 --- a/web/js/workspace/prompt-blocks.mjs +++ b/web/js/workspace/prompt-blocks.mjs @@ -41,7 +41,9 @@ export function mountPromptBlocks(container, {prompts, sender, parentScope, role // The title is mutable so a saved title edited in place (setTitle below, #249 F1) renames the actions. let currentTitle = title || ''; const actionName = (verb, role, rest = '') => `${verb} ${action(role)}${rest}${currentTitle ? `: ${currentTitle}` : ''}`; - if (parentScope.signal.aborted) return {update() {}, setState() {}, setTitle() {}, dispose() {}}; + // An aborted parent gets one inert handle; every method is the same no-op. + const inert = () => {}; + if (parentScope.signal.aborted) return {update:inert, setState:inert, setTitle:inert, dispose:inert}; const scope = childScope(parentScope); container.classList.add('prompt-inspector'); scope.listen(container, 'click', async event => {