diff --git a/src/ace/sidecar/dashboard_render.py b/src/ace/sidecar/dashboard_render.py index 54576a9..41c952e 100644 --- a/src/ace/sidecar/dashboard_render.py +++ b/src/ace/sidecar/dashboard_render.py @@ -1148,6 +1148,7 @@ def _refs(d: Dict[str, Any]) -> Dict[str, Any]: .modebar button.on{background:#14301f;color:#4ade80} .modebar button.on[data-mode=prod]{background:#3a2216;color:#f0a868} .modebar button:hover:not(.on){color:#adbac7;background:#12161a} +.lvh{font:9px/1.4 ui-monospace,monospace;color:#6e7681;letter-spacing:.08em;text-transform:uppercase;margin:9px 0 4px;padding-top:8px;border-top:1px solid #1c2126} .modenote{font:10px/1.5 ui-monospace,monospace;color:#6e7681;margin-top:5px} """ @@ -1249,9 +1250,17 @@ def _mode_js() -> str: ""+shown+" ("+pct.toFixed(1)+"%) via "+(m.by||'')+""; }); } + // Persisted, because the page reloads itself every REFRESH_SECONDS. Without this the + // control silently snapped back to OFF a few seconds after every click -- which reads as a + // broken toggle rather than as the page refreshing, and is exactly how it was reported. + // localStorage is the right store for it: a per-viewer display preference, not state + // anyone else needs, and it survives the reload that caused the problem. + var KEY='ace.skillmode'; + function save(m){ try{ localStorage.setItem(KEY,m); }catch(e){} } + function load(){ try{ return localStorage.getItem(KEY)||'off'; }catch(e){ return 'off'; } } document.querySelectorAll('#modebar button').forEach(function(b){ - b.addEventListener('click',function(){apply(b.dataset.mode);});}); - apply('off'); + b.addEventListener('click',function(){ save(b.dataset.mode); apply(b.dataset.mode); });}); + apply(load()); })(); """ @@ -2422,14 +2431,21 @@ def _lever_rail(d: Dict[str, Any]) -> str: if not rows: # No sessions in scope. The published corpus figures would fit here and would be a # lie about this machine, so the rows render with the number withheld. + # Installed levers are appended here too. Whether a package registered one has + # nothing to do with whether there are sessions to score it against, and an empty + # scope was silently hiding the only evidence that a lever package was present. return "".join( - f"
" - f"{i + 1}{n}" - f"
" - f"
" - f"
not scoredPHASE 2
" - for i, n in enumerate(_LEVER_NAMES) + [ + f"
" + f"{i + 1}{n}" + f"
" + f"
" + f"
not scoredPHASE 2
" + for i, n in enumerate(_LEVER_NAMES) + ] + + _measured_rows(d) + + _installed_rows(d) ) top = max((r["usd"] for r in rows), default=0.0) out = [] @@ -2457,9 +2473,59 @@ def _lever_rail(d: Dict[str, Any]) -> str: f"{risk or '—'}" ) out.extend(_measured_rows(d)) + out.extend(_installed_rows(d)) return "".join(out) +def _installed_rows(d: Dict[str, Any]) -> List[str]: + """Levers a package registered but which have not produced a number yet. + + Without these an imported skill is INVISIBLE. Discovery finds it, the payload carries it, + every mode resolves it — and the rail renders only the simulated headroom rows and the + measured ones, so a developer who installs a lever package sees no evidence it worked. + That was the state until now: `installed` was in the payload and read by nothing. + + They carry no figure on purpose. A registered lever that is `off` has produced neither a + measurement nor a simulation, and inventing a number for it here would put a third claim + on a rail that already has to keep two apart. What it shows instead is what a developer + actually needs: that the package is present, which levers came with it, their declared + risk, and the one word standing between the lever and doing something. + """ + lv = d.get("levers") or {} + installed = lv.get("installed") or [] + if not installed: + return [] + modes = lv.get("modes") or {} + scored = {r.get("lever") for r in ((lv.get("measured") or {}).get("by_lever") or [])} + + rows = ["
Installed levers
"] + for item in sorted(installed, key=lambda i: i.get("id") or ""): + lid = item.get("id") or "?" + if lid in scored: + continue # already has a measured row above + mode = modes.get(lid, "off") + risk = escape((item.get("risk") or "").replace("*", "")) + needs = " · needs the proxy path" if item.get("requires_content") else "" + tip = ( + f"Registered by {item.get('dist') or 'an installed package'} through the " + f"ace.sidecar.levers entry-point group. Mode is {mode.upper()}, read from " + f"~/.ace/config.json — installing a lever never enables it. " + f"Declared risk {risk or 'unstated'}." + + (" This lever needs the actual tool-result bytes, so it only runs on a proxied " + "turn, never on a transcript scan." if item.get("requires_content") else "") + ) + cls = "on" if mode != "off" else "z" + rows.append( + f"
" + f"
" + f"{escape(item.get('label') or lid)}" + f"{escape(mode.upper())}
" + f"
{escape(item.get('dist') or '')}{needs}" + f"{risk or '—'}
" + ) + return rows if len(rows) > 1 else [] + + def _measured_rows(d: Dict[str, Any]) -> List[str]: """Rows for levers that actually ran, appended to the same rail. diff --git a/tests/test_lever_shadow.py b/tests/test_lever_shadow.py index e9ec1d8..463c61e 100644 --- a/tests/test_lever_shadow.py +++ b/tests/test_lever_shadow.py @@ -773,3 +773,63 @@ def blocked(name, *a, **k): new_raw, info = runner.actuate(json.dumps(body).encode(), body) assert new_raw is None, "no splice mechanics means the original bytes go out" assert any("ace-skills is not installed" in r for r in info["refused"]) + + +# -- the rail must show a lever that was installed but has produced no number ---------------- + + +def test_an_installed_lever_is_visible_even_with_no_measurement(store): + """The bug this covers: discovery found the levers, the payload carried them, every mode + resolved them — and the rail rendered only simulated headroom and measured rows, so a + developer who installed a lever package saw no evidence of it anywhere on the page.""" + from ace.sidecar.dashboard_render import _lever_rail + + d = { + "scorecards": {"standalone": []}, + "levers": { + "status": "all_off", + "installed": [ + {"id": "tail_truncation", "label": "Cap oversized tool results", + "risk": "LOW", "dist": "ace-skills", "requires_content": False}, + {"id": "image_stripping", "label": "Strip stale screenshots from history", + "risk": "MEDIUM", "dist": "ace-skills", "requires_content": True}, + ], + "modes": {"tail_truncation": "off", "image_stripping": "shadow"}, + "measured": {}, + }, + } + html = _lever_rail(d) + assert "Cap oversized tool results" in html + assert "Strip stale screenshots from history" in html + assert "ace-skills" in html, "the providing package must be named" + assert "OFF" in html and "SHADOW" in html, "the resolved mode is the actionable part" + assert "needs the proxy path" in html, "a content-requiring lever must say so" + + +def test_a_measured_lever_is_not_listed_twice(store): + """It already has a row above with a real figure; repeating it as 'installed' would imply + two levers.""" + from ace.sidecar.dashboard_render import _lever_rail + + d = { + "scorecards": {"standalone": []}, + "levers": { + "status": "measured", + "installed": [{"id": "tail_truncation", "label": "Cap oversized tool results", + "risk": "LOW", "dist": "ace-skills", "requires_content": False}], + "modes": {"tail_truncation": "shadow"}, + "measured": {"by_lever": [ + {"lever": "tail_truncation", "turns": 3, "removed_tokens": 900, "usd": 0.5, + "unpriced_turns": 0, "revisit_candidates": 0, "revisits": 0, + "revisits_paginated": 0}]}, + }, + } + html = _lever_rail(d) + assert html.count("Cap oversized tool results") == 1 + assert "MEASURED" in html + + +def test_nothing_installed_adds_nothing(store): + from ace.sidecar.dashboard_render import _lever_rail + html = _lever_rail({"scorecards": {"standalone": []}, "levers": {}}) + assert "Installed levers" not in html