← Commit history

2.13.0 (doc only): split the two dashboard lifecycles - a bridge-served app has no retirement path to rehearse; and a JSON round trip fabricates failures from non-JSON bodies

John Lauer ·84c9b0462a ·1mo ago ·parent b2990f3
2 files changed +34−1
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-ui-design",-  "version": "2.12.0",+  "version": "2.13.0",   "type": "skill",   "description": "The Adom UI Design System plus a bundle of focused UI skills (tooltips, floating-windows, toasts, responsive-ui, app-shell, ai-driven-apps, clickable-paths, dark-default, input-feedback, settings-layout). One install drops the whole set of skill files onto your container, plus shared icon assets (the settings cog) so every Adom app draws the same glyph.",   "dependencies": {},
skills/newbie-panel/SKILL.md+33
@@ -158,6 +158,13 @@ It checks three things, and all three are failures a 200-probe sails past: | a non-200 status survives (upstream 207 returned as 207) | a hand-built `200 {ok:true}` wrapper | | an unproxied path under the same prefix returns YOUR 404 | blanket-proxying the control API | +**A JSON round trip is lossy in three ways that all look harmless.** pup's relay used+`JSON.parse` then `JSON.stringify`, not serde, so it did not alphabetise and therefore looked+fine. It still: **loses precision on an integer past 2^53**, turns **`1.0` into `1`**, and+worst, turns a **NON-JSON upstream body into an invented `{"error":...}` object** — converting+a valid response into a fabricated failure that no status code contradicts. That third one is+the reason "it returns 200" proves nothing about a proxy.+ **PARSE FOR WHAT YOU DECIDE. NEVER PARSE FOR WHAT YOU HAND BACK.** parts-search's rule, from fixing its own route: it still parses the upstream JSON for its own decisions, and forwards the response bytes untouched with the `Content-Type` carried through. Those are two different@@ -1090,8 +1097,34 @@ actually holds: The general form, worth more than the panel: **on a shared resource, a handoff is not complete when the holder lets go. It is complete when the next holder has been told, by the holder.** +## FIRST: WHICH LIFECYCLE IS YOUR DASHBOARD ON? THEY ARE NOT THE SAME PROBLEM.++**A container-served dashboard** runs as its own process. `pkg install` replaces the binary and+leaves the old process running, so it needs the retirement path below, and that path is+usually untested.++**A bridge-served dashboard** (pup) is served by the DESKTOP bridge, not by a container+process. The container helper only prints the bridge's URL, so **installing the package+updates a helper that serves nothing.** What actually retires it is `bridge_install`, which ab+kills and respawns. That path is the opposite of untested: pup has driven it eight times in a+day and watched the version move each time.++**Establish which one you are before rehearsing anything**, or you will practise a path you do+not have while skipping the check you do. pup's `/api/status` showed 2.0.345 against a+container package of 2.0.348, which looks exactly like the stale-process symptom and is a+different mechanism with a different fix.++**What a bridge restart does to open windows, measured:** normal windows SURVIVE, tab and URL+intact, because the browser is detached and the new bridge re-adopts it over the debugging+port. pup has a 94-minute-old window that lived through at least two `bridge_install`s.+**The exception is a dialog-blocked tab, which does NOT survive** — the modal holds the target+in a state the reconnect cannot drive. So restarting the bridge is a usable last-resort unwedge+for a stuck native dialog, and it costs you exactly the window that was stuck.+ ## ⛔ REHEARSE YOUR UPGRADE AGAINST YOUR REAL PREDECESSOR. THE INPUT IS THE OLD BUILD'S OUTPUT. +**This section is for container-served dashboards.**+ Since the dock installs without restarting (below), every app needs a `serve` that RETIRES the running instance. Almost every app will have tested that against itself and therefore tested only the idempotent branch.