← Commit history

web control: land the progress bar on the real outcome (was painting red stopped over a green 3/3 pass)

John Lauer ·fc51f8495f ·1mo ago ·parent 7a73a5d
1 file changed +22−10
web-control-demo.html+22−10
@@ -1054,12 +1054,24 @@ for (const w of mine) {   // left". The verb finished between polls, so the last frame was mid-flight and   // nothing ever superseded it.   //-  // The outcome is read from the card's own result class rather than assumed, so a-  // FAILED run does not get a triumphant 100% - it lands red and says stopped.-  function finishSurfaceBar(c) {+  // A FAILED run does not get a triumphant 100% - it lands red and says stopped.+  //+  // PASS THE OUTCOME IN. This used to read it off the card's result class, which+  // sounds honest ("read, don't assume") but is a race in disguise: every caller+  // lands the bar BEFORE it calls setRes, so the class was still "running" and+  // every successful run painted a red "stopped" bar under a green "Done - all 3+  // library artifacts opened" header (John, 2026-08-25). The AI-thread card had+  // the same bug for the same reason. The outcome is knowable at the call site,+  // so it is an argument now.+  //+  // `ok` omitted falls back to the class read - correct ONLY for the poll loop,+  // which runs after the card has already settled.+  function finishSurfaceBar(c, ok) {     if (!c._sawProgress) return;               // no bar was ever drawn; nothing to land     c._sawProgress = false;                    // once per run-    var ok = c.res && c.res.classList && c.res.classList.contains("ok");+    if (typeof ok !== "boolean") {+      ok = !!(c.res && c.res.classList && c.res.classList.contains("ok"));+    }     renderProgressBlock(c.card, ok       ? { percent: 100, stepLabel: "done", etaSec: 0 }       : { percent: 100, stepLabel: "stopped", failed: true });@@ -1779,16 +1791,16 @@ for (const w of mine) {         });       }, Promise.resolve());     }).then(function () {-      finishSurfaceBar(c);       var good = results.filter(function (r) { return r.ok; }).length;       var missing = results.filter(function (r) { return !r.ok; }).map(function (r) { return r.label; });+      finishSurfaceBar(c, good === 3);       if (good === 3) setRes(c.res, "ok", "Done - all 3 library artifacts opened",         "symbol + footprint + 3D model, each captured below");       else setRes(c.res, "err", good + "/3 library artifacts opened",         "missing: " + missing.join(", ") + " - a library is only proven when all three open");       c.btn.disabled = false;     }).catch(function (e) {-      finishSurfaceBar(c);+      finishSurfaceBar(c, false);       setRes(c.res, "err", "library proof failed", (e && e.message) || String(e));       c.btn.disabled = false;     });@@ -1962,7 +1974,7 @@ for (const w of mine) {       reason: "A wiki page asked to open an AI thread with a written prompt"     }).then(function (res) {       var j = res.j || {};-      finishSurfaceBar(cAi);+      finishSurfaceBar(cAi, !!(j.ok || j.success));       cAi.btn.disabled = false;       if (!j.ok && !j.success) {         cAi.res.className = "res bad";@@ -1989,7 +2001,7 @@ for (const w of mine) {         }).catch(function () { clog(cAi, "evidence saved on the PC: " + j.evidence); });       }     }).catch(function (e) {-      finishSurfaceBar(cAi);+      finishSurfaceBar(cAi, false);       cAi.btn.disabled = false;       cAi.res.className = "res bad";       cAi.res.textContent = "failed: " + e;@@ -2141,16 +2153,16 @@ for (const w of mine) {         });       }, Promise.resolve());     }).then(function () {-      finishSurfaceBar(c);       var good = results.filter(function (r) { return r.ok; }).length;       var missing = results.filter(function (r) { return !r.ok; }).map(function (r) { return r.label; });+      finishSurfaceBar(c, good === 3);       if (good === 3) setRes(c.res, "ok", "Done - all 3 library artifacts opened",         "symbol + footprint + 3D package, each captured below");       else setRes(c.res, "err", good + "/3 library artifacts opened",         "missing: " + missing.join(", ") + " - a library is only proven when all three open");       c.btn.disabled = false;     }).catch(function (e) {-      finishSurfaceBar(c);+      finishSurfaceBar(c, false);       setRes(c.res, "err", "library proof failed", (e && e.message) || String(e));       c.btn.disabled = false;     });