Przeglądaj źródła

web windows: maximized window drops its titlebar too — header carries the title plus restore/minimize/close for that window

Alexander Korolev 1 miesiąc temu
rodzic
commit
5c54bf0af5

+ 55 - 0
docker-images/glm53-jovian-r27/profiles/jovian-r37-ds41.env

@@ -0,0 +1,55 @@
+# Version profile: DeepSeek-V4.1-Flash r37 (jovian-judgement, qualified 2026-09-13).
+#
+# rtx6kpro models/deepseek-v4.1-flash.md ("R37 dispatch and projection
+# qualification"; image localinferencelab/vllm:
+# jovian-judgement-community-20260913-r37). Two-layer image like r36: the GLM
+# entrypoint (our r35 lane) + the DS4.1 entrypoint. We build the same source
+# composition here for GB10 sm_121a (the published image's native extension is
+# sm_120 / CUDA 13.3 x86).
+#
+# What R37 claims over its public-source control (their RTX quartet, TP4/DCP1,
+# RAM Engram, DSpark K7/adaptive, batch 4096):
+#   uncached 32K prefill 14,896 -> 21,399 tok/s (+43.65%)
+#   C1 output (budget 50, three-cell median) 238.8 -> 281.1 tok/s (+17.70%)
+#   C1 verifier 99.0 -> 110.8 steps/s (+11.92%); Sieve 385.2 -> 416.7 (+8.17%)
+# Cause (their changelog): removes repeated CPU argument-list expansion,
+# mutable-schema inspection, scalar dtype allocations and tensor-equality calls
+# during kernel dispatch — no quantization/sampling approximation — plus
+# measured B12X projection tiles, four FP32 projection partials, visible
+# index-score tiles, compact mHC prefill config, removed attention-output
+# copies, bounded short-index scratch. Also corrects the named reasoning
+# budget `high` from 50 to 75 (a behavior change, not just speed: our dev65
+# benches set reasoning_effort explicitly, so expect no surprise there) and
+# adds the B12X small-tile barrier fix (#363) + TP3 prefill-head support
+# (TP3 not serving-qualified).
+#
+# Pinned by commit + tree hash (gated per repo in the Dockerfile). Delta vs
+# the r36 profile (jovian-r36-ds41.env):
+#   vLLM  202a11a98eb -> c687594b8a8 (composed "release/ds41-optimized-r37":
+#         JJ b40673cd + #740/#743/#742/#744)
+#   B12X  323107ff    -> f1c4e9dd5b1 (clean master 05d2c43b + #364/#367/#366/#365)
+#   LMCache 29bc5a2e — UNCHANGED; FlashKDA 3b225bf2 + in-tree patch — UNCHANGED
+#   DeepGEMM 8b1392b9 (nv_dev) — UNCHANGED (verified in the r37 tree's
+#     tools/install_deepgemm.sh)
+#   requirements/cuda.txt (r37 tree) — torch 2.13.0, flashinfer 0.6.17:
+#     SAME as our r35/r36 GB10 pins (CUDA 13.2 aarch64 / cu130 base, the
+#     documented deviation from their cu133 x86 runtime). cmake/
+#     external_projects listing identical to r36 (no dep add/remove), so
+#     fetch-deps.sh needs no resync.
+#   liburing 2.5 (+ -dev headers) already in locks/apt-packages.txt since r36.
+VLLM_PIN=c687594b8a8082e18af9fe2f64eb5f9ee442e251
+VLLM_TREE=3fb88fdfd0b5acdd4460076c6443a4299e5edf7d
+VLLM_PRETEND_VERSION=0.26.1rc0+glm53.r37.vllmc687594b
+
+B12X_PIN=f1c4e9dd5b1d841c10cda70ee49c3190cf3db0be
+B12X_TREE=480ea232d52fff4271b0412470d4ec340196735a
+B12X_PRETEND_VERSION=0.1.dev0+glm53b12x.r37.f1c4e9dd
+
+LMCACHE_PIN=29bc5a2efde737c436b04499eb62cd1776cebeec
+LMCACHE_TREE=5a88a1ea9d2627c76288d056e7193f7454669b64
+LMCACHE_VERSION=0.5.5.dev0+glm53checkpoints.29bc5a2e
+
+# Same r35/r36 behavior: empty on purpose — the r37 tree gates FlashKDA on the
+# packed-checkpoint API and applies its own in-tree patch (same pin 3b225bf2;
+# our r27 unpatched checkout would fail the gate).
+FLASH_KDA_SRC_DIR=

+ 4 - 3
specs/tech-architecture/web-dashboard.md

@@ -158,9 +158,10 @@ UI outgrows ~2–3k lines.)
   titlebar, corner resize, `▢` **maximize** (fills the window layer minus
   the dock strip; a second click restores the exact previous geometry),
   minimize → dock chip → restore, close. Maximized = **frameless fill**: no
-  border/radius/shadow, the window *is* the layer (flush to the dock strip,
-  which is a sibling below it and stays usable) and its title moves into the
-  header with a restore button (`#max-restore`); exactly one window can be
+  border/radius/shadow **and no titlebar** — the window *is* the layer (flush
+  to the dock strip, which is a sibling below it and stays usable), while its
+  title *and* controls move into the header (`#maxinfo`: `⛶ <title>`, then
+  `❐` restore / `–` minimize / `×` close for that window); exactly one window can be
   maximized. Window geometry is px, so `fitToLayer()` clamps windows back
   into the layer whenever the dock appears/disappears or the page resizes
   (run at the *end* of `renderDock` — at boot the dock is `:empty`, i.e.

+ 13 - 5
src/web/ui.html

@@ -57,7 +57,7 @@
   /* maximized: the frame disappears and the window IS the layer; its title
      moves into the header (with a restore button) */
   .win.max { border: 0; border-radius: 0; box-shadow: none; }
-  .win.max .win-resize { display: none; }
+  .win.max .win-bar, .win.max .win-resize { display: none; }
   #maxinfo { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); }
   #maxinfo .maxtitle { color: var(--fg); font-weight: 600; }
   .win-bar {
@@ -357,7 +357,9 @@
 <header>
   <h1>sm121</h1>
   <div id="maxinfo" hidden><span>⛶</span><span class="maxtitle" id="max-title"></span>
-    <button class="tbtn" id="max-restore" title="restore window size">❐</button></div>
+    <button class="wbtn" id="max-restore" title="restore window size">❐</button>
+    <button class="wbtn" id="max-min" title="minimize">–</button>
+    <button class="wbtn" id="max-close" title="close">×</button></div>
   <div class="spacer"></div>
   <div class="ssec" id="sse"><span class="dot"></span><span id="sse-t">connecting…</span></div>
   <button class="tbtn" id="theme">◐</button>
@@ -418,7 +420,9 @@ function sameSnapshot(a, b) {
 // --- theme ---------------------------------------------------------------
 const root = document.documentElement;
 root.dataset.theme = localStorage.getItem("sm121-theme") || (matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark");
-$("#max-restore").onclick = () => { if (maxedHandle) maxedHandle.unmaximize(); };
+$("#max-restore").onclick = () => maxedHandle?.unmaximize();
+$("#max-min").onclick = () => maxedHandle?.minimize();
+$("#max-close").onclick = () => maxedHandle?.close();
 $("#theme").onclick = () => {
   root.dataset.theme = root.dataset.theme === "dark" ? "light" : "dark";
   localStorage.setItem("sm121-theme", root.dataset.theme);
@@ -486,11 +490,12 @@ function makeWin({ id, title, short, x, y, w, h, bodyHtml, onClosed, extraCls, r
   win.append(bar, body, rz);
   $("#winlayer").appendChild(win);
   const closed = { value: false };
-  bar.querySelector('[data-act="min"]').onclick = () => {
+  const doMin = () => {
     unmax(); // minimize a normal-shaped window; the dock chip restores it
     win.style.display = "none";
     renderDock();
   };
+  bar.querySelector('[data-act="min"]').onclick = doMin;
   // maximize = drop the frame and fill the window layer (the dock is a
   // sibling below it, so it stays usable); the title moves to the header
   const maxBtn = bar.querySelector('[data-act="max"]');
@@ -517,7 +522,7 @@ function makeWin({ id, title, short, x, y, w, h, bodyHtml, onClosed, extraCls, r
     maxBtn.title = "restore size";
     showMaxTitle(handle);
   };
-  bar.querySelector('[data-act="close"]').onclick = () => {
+  const doClose = () => {
     if (removeOnClose) win.remove(); // log windows die with their attach
     else win.style.display = "none";
     closed.value = true;
@@ -526,6 +531,7 @@ function makeWin({ id, title, short, x, y, w, h, bodyHtml, onClosed, extraCls, r
     renderDock();
     if (onClosed) onClosed();
   };
+  bar.querySelector('[data-act="close"]').onclick = doClose;
   bar.addEventListener("pointerdown", (e) => {
     if (e.target.closest(".wbtn") || win.classList.contains("max")) return;
     front(win);
@@ -549,6 +555,8 @@ function makeWin({ id, title, short, x, y, w, h, bodyHtml, onClosed, extraCls, r
     win, body, title,
     label: short || title,
     unmaximize: unmax,
+    minimize: doMin,
+    close: doClose,
     restore() { win.style.display = ""; closed.value = false; front(win); renderDock(); },
     isMinimized: () => win.style.display === "none",
     isClosed: () => closed.value,

+ 26 - 0
src/web/ui.playwright.mjs

@@ -380,6 +380,21 @@ ok(
   JSON.stringify(m),
 );
 ok("recipes: maximized window has no frame", m.border === "0px" && m.radius === "0px", `${m.border} / ${m.radius}`);
+ok(
+  "recipes: maximized window keeps no titlebar (title lives in the header)",
+  (await page.evaluate(() => getComputedStyle(document.querySelector("#win-recipes .win-bar")).display)) === "none",
+);
+ok(
+  "recipes: maximized content starts at the layer top",
+  await page.evaluate(
+    () =>
+      Math.abs(
+        document.querySelector("#win-recipes .win-body").getBoundingClientRect().top -
+          document.querySelector("#winlayer").getBoundingClientRect().top,
+      ) < 2,
+  ),
+);
+ok("recipes: header carries the window controls", (await page.locator("#maxinfo .wbtn").count()) === 3);
 ok("recipes: maximized title moves into the header", m.label === "Recipes", m.label);
 // the dock stays reachable under a maximized window
 ok(
@@ -401,6 +416,17 @@ ok(
   "recipes: header label cleared after restore",
   await page.evaluate(() => document.querySelector("#maxinfo").hidden),
 );
+// header controls must work while the window has no titlebar of its own
+await page.click("#win-recipes .win-bar .wbtn[data-act='max']");
+await page.waitForTimeout(400);
+await page.click("#max-min");
+await page.waitForTimeout(200);
+ok(
+  "recipes: header minimize hops to the dock",
+  (await page.locator('#dock .dock-chip:has-text("Recipes")').count()) === 1,
+);
+await page.click('#dock .dock-chip:has-text("Recipes")');
+await page.waitForTimeout(400);
 await page.evaluate(() => document.querySelector("#win-recipes").style.display = "none");
 
 // the map is a fixed-aspect drawing: its window is sized to it, otherwise