← back to Ticket System
board: Run Now no longer depends on confirm()/alert() (browser can suppress dialogs → silent no-op); non-blocking two-click arm + inline status
9a172ef3e63f29de45b8058b5e3ed6b250d41056 · 2026-09-02 15:27:33 -0700 · Steve
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkjHuJKiariXaTtFujZxWC
Files touched
Diff
commit 9a172ef3e63f29de45b8058b5e3ed6b250d41056
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Sep 2 15:27:33 2026 -0700
board: Run Now no longer depends on confirm()/alert() (browser can suppress dialogs → silent no-op); non-blocking two-click arm + inline status
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkjHuJKiariXaTtFujZxWC
---
board.html | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/board.html b/board.html
index 0390c2d8..b3f06ed2 100644
--- a/board.html
+++ b/board.html
@@ -134,6 +134,7 @@
<optgroup label="Local · Ollama"><option value="local-qwen-27b">Local Qwen 27B Heretic</option><option value="local-qwen-14b">Local Qwen 14B</option></optgroup>
</select>
<button class="btn run" id="runBtn" title="Open a new iTerm2 window with the selected model, one per selected ticket">▶ Run Now</button>
+ <span id="runmsg" style="margin-left:8px;font-size:12px;opacity:.85"></span>
<button class="btn dtd" id="dtdBtn" title="Batched /dtd — clear yes/no 'run now' verdict per recent ticket">🧠 Analyze w/ DTD</button>
<button class="btn" id="yesBtn" title="Add every ticket DTD said YES to the selection">✅ Select all YES</button>
<button class="btn stop" id="stopBtn" title="TicketStopped — stop forever (reversible)">⛔ Stop Forever</button>
@@ -344,8 +345,14 @@ function selIds(){return [...SEL];}
async function post(url,body){const r=await fetch(location.origin+url,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body||{})});return r.json();}
$('#clearBtn').onclick=()=>{SEL.clear();render();syncBar();};
$('#runProfile').onchange=e=>{RUN_PROFILE=e.target.value;save('tkRunProfile',RUN_PROFILE);};
-$('#runBtn').onclick=async()=>{const ids=selIds();if(!ids.length)return;const label=$('#runProfile').selectedOptions[0].textContent;if(!confirm(`Open ${ids.length} new iTerm2 window(s), each running ${label} on a ticket?`))return;
- $('#runBtn').disabled=true;try{const r=await post('/api/run',{ids,profile:RUN_PROFILE});if(r.error)throw new Error(r.error);alert(`Launched ${((r.launched||[]).length)} ${label} session(s)`+((r.skipped&&r.skipped.length)?`\nSkipped: ${r.skipped.map(s=>s.id+'('+s.why+')').join(', ')}`:''));}catch(e){alert('run failed: '+e.message);}finally{$('#runBtn').disabled=false;SEL.clear();load();}};
+const setRunMsg=t=>{const e=$('#runmsg');if(e)e.textContent=t||'';};
+let runArmedAt=0;
+$('#runBtn').onclick=async()=>{const ids=selIds();if(!ids.length){setRunMsg('select ticket(s) first');return;}
+ const label=($('#runProfile').selectedOptions[0]&&$('#runProfile').selectedOptions[0].textContent)||RUN_PROFILE;
+ // non-blocking two-click arm — confirm() can be suppressed by the browser and silently no-op the run
+ if(Date.now()-runArmedAt>4000){runArmedAt=Date.now();$('#runBtn').textContent=`▶ Run ${ids.length} · click again`;setRunMsg(`opens ${ids.length} iTerm2 ${label} window(s) — click Run again to confirm`);setTimeout(()=>{const b=$('#runBtn');if(b)b.textContent='▶ Run Now';},4000);return;}
+ runArmedAt=0;$('#runBtn').textContent='▶ Run Now';$('#runBtn').disabled=true;setRunMsg('launching '+ids.length+'…');
+ try{const r=await post('/api/run',{ids,profile:RUN_PROFILE});if(r.error)throw new Error(r.error);const sk=(r.skipped&&r.skipped.length)?(' · skipped '+r.skipped.length):'';setRunMsg(`launched ${(r.launched||[]).length}${sk} — windows opening (check the feed if none appear)`);}catch(e){setRunMsg('run failed: '+e.message);}finally{$('#runBtn').disabled=false;SEL.clear();load();}};
$('#stopBtn').onclick=async()=>{const ids=selIds();if(!ids.length)return;if(!confirm(`Stop ${ids.length} ticket(s) FOREVER (TicketStopped)? Reversible via Reopen.`))return;
try{await post('/api/stop',{ids});}catch(e){alert('stop failed: '+e.message);}SEL.clear();load();};
$('#reopenBtn').onclick=async()=>{const ids=selIds();if(!ids.length)return;try{await post('/api/reopen',{ids});}catch(e){alert('reopen failed: '+e.message);}SEL.clear();load();};
← 841b97af Open ticket control from every bar tile
·
back to Ticket System
·
Make popup Run Now single-click 2fa673ea →