"""Cairn's compute layer for the browser build (Pyodide, no server, no gradio). Why this exists instead of Gradio-lite: gradio-lite imports ``gradio`` *before* it installs the page's requirements, and gradio 5.x currently cannot be resolved against ``huggingface-hub`` 1.x inside Pyodide -- the capped builds fail to install, the uncapped ones import and then die on a missing ``httpcore``. Since the boot order is not ours to change there, we skip the framework and drive Pyodide directly. The page ends up lighter too: no pandas, pydantic or orjson, just numpy, scipy, pillow and the ``cairn`` wheel. Every function here returns plain JSON-able data (HTML fragments and base64 PNG data URIs) which ``index.html`` drops into the DOM. All of the science is imported unchanged from the ``cairn`` package; nothing is reimplemented for the browser. Claim: R/E -- lets anyone check the two headline claims themselves, for free, with no GPU, no install and no account. """ from __future__ import annotations import base64 import io from typing import Any, Dict, List, Tuple import numpy as np from PIL import Image from cairn.runner import CONDITION_NAMES, RunConfig, run_condition from cairn.world import ( make_departure_return_trajectory, make_scene, render, schedule_edit, usable_targets, ) GAP = 6 BASELINES = {"A": "Vanilla", "B": "Context-window", "C": "Compressed-memory"} # -------------------------------------------------------------------------- # rendering helpers # -------------------------------------------------------------------------- def _png(arr: np.ndarray) -> str: """``(H, W, 3)`` float image -> base64 PNG data URI for an ```` tag.""" a = (np.clip(np.asarray(arr), 0.0, 1.0) * 255).astype(np.uint8) buf = io.BytesIO() Image.fromarray(a).save(buf, format="PNG", optimize=True) return "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode("ascii") def _filmstrip(frames: np.ndarray, idx: List[int]) -> str: """Selected frames side by side, separated by pale gutters. Pyodide has no ffmpeg, so there is no video. A strip is arguably the better medium for this claim anyway: "before leaving" and "after returning" sit in one glance instead of several seconds apart in a loop. Claim: R -- the experiment, in one picture. """ idx = [i for i in idx if 0 <= i < len(frames)] if not idx: return _png(np.zeros((8, 8, 3))) h = frames[0].shape[0] gutter = np.full((h, GAP, 3), 0.93, dtype=np.float32) panels: List[np.ndarray] = [] for k, i in enumerate(idx): if k: panels.append(gutter) panels.append(frames[i]) return _png(np.concatenate(panels, axis=1)) def _windows(traj) -> List[int]: return [ 0, max(0, traj.observe_frames[1] - 1), (traj.departure_frame + traj.return_frame) // 2, traj.return_frame + 1, min(len(traj) - 1, traj.return_frame + 7), ] PANEL_CAPTION = ( "opening shot · last frame before leaving · " "looking away · just back · settled after return" ) def _ledger_html(res) -> str: rows = [] for e in res.ledger.entries(include_absent=True): p = e.pose.position state = "present" if e.present else 'REMOVED' rows.append( f"{e.object_id}{p[0]:.2f}{p[2]:.2f}" f"{e.pose.yaw:+.2f}" f"" f"{e.appearance[0]:.2f}, {e.appearance[1]:.2f}, {e.appearance[2]:.2f}" f"{e.n_observations}{e.confidence:.2f}{state}" ) return ( "" "" + "".join(rows) + "
idxzyawrgbseenconfstate
" ) def _cfg(cond: str, seed: int) -> RunConfig: # reference_video=False skips rendering a second full clip that only the # FVD-proxy consumes, and this page never shows that number. Roughly halves # the work per click in the browser. return RunConfig(condition=cond, seed=1000 + int(seed), reference_video=False) def _resolve_target(scene, requested: int, seed: int) -> Tuple[int, str]: """Snap the slider to an object that can actually host an episode. Claim: R -- the demo shows the same well-posed episodes the benchmark scores. """ ok = usable_targets(scene, seed=int(seed)) if not ok: raise ValueError("No object in this room can be left and returned to — try another seed.") if int(requested) in ok: return int(requested), "" chosen = min(ok, key=lambda o: abs(o - int(requested))) return chosen, ( f"

Object #{int(requested)} is permanently hidden behind another object " f"in this room, so it cannot host a leave-and-return episode. Showing object " f"#{chosen} instead.

" ) # -------------------------------------------------------------------------- # public entry points (called from JavaScript) # -------------------------------------------------------------------------- def scene_preview(seed: int, n_objects: int) -> str: """Four views of the room, so you can see what you are about to test.""" from cairn.types import CameraPose scene = make_scene(int(n_objects), seed=int(seed)) cams = [ CameraPose(np.array([5.0, 1.55, 5.0]), a) for a in np.linspace(-np.pi, np.pi, 4, endpoint=False) ] frames = np.stack([render(scene.states(), c, scene.settings).rgb for c in cams]) return _filmstrip(frames, list(range(4))) def _verdict_html(res, label: str) -> str: m = res.metrics drawn = m["return_observed"] > 0.5 ok = m["return_success"] > 0.5 err = "not drawn at all" if not drawn else f"{m['return_self_trans']:.2f} m" badge = ( "consistent" if ok else "inconsistent" ) return ( f"

{label}  {badge}

" ) def compare(seed: int, n_objects: int, absence: int, target: int, baseline: str) -> Dict[str, Any]: """Same scene, same trajectory, same generator seed — only the memory differs. Claim: R -- the interactive form of the headline experiment. """ seed, n_objects, absence = int(seed), int(n_objects), int(absence) scene = make_scene(n_objects, seed=seed) target, note = _resolve_target(scene, int(np.clip(target, 0, n_objects - 1)), seed) traj = make_departure_return_trajectory(scene, target, absence, seed=seed) off = run_condition(scene, traj, _cfg(baseline, seed)) on = run_condition(scene, traj, _cfg("D", seed)) idx = _windows(traj) header = ( f"

Camera left object #{target} at frame {traj.departure_frame} and came back " f"at frame {traj.return_frame} — {traj.absence_frames} frames away. " f"The return viewpoint is deliberately not the departure viewpoint, so neither " f"method can win by replaying its last frame.

" f"

Panels: {PANEL_CAPTION}

{note}" ) return { "header": header, "off_img": _filmstrip(off.frames, idx), "on_img": _filmstrip(on.frames, idx), "off_label": f"Cairn OFF — ({baseline}) {CONDITION_NAMES[baseline]}", "on_label": "Cairn ON — (D) explicit world ledger", "off_verdict": _verdict_html(off, f"Cairn OFF — ({baseline}) {BASELINES[baseline]}"), "on_verdict": _verdict_html(on, "Cairn ON — (D) explicit world ledger"), "ledger": _ledger_html(on), } def edit(seed: int, n_objects: int, absence: int, target: int, kind: str) -> Dict[str, Any]: """Issue an edit while the object is off screen, then score what came back. Claim: E -- the operation conditions A–C cannot express at all. """ seed, n_objects, absence = int(seed), int(n_objects), int(absence) scene = make_scene(n_objects, seed=seed) target, note = _resolve_target(scene, int(np.clip(target, 0, n_objects - 1)), seed) traj = make_departure_return_trajectory(scene, target, absence, seed=seed) ev = schedule_edit(traj, scene, kind, seed=seed) traj.edits = [ev] on = run_condition(scene, traj, _cfg("D", seed)) off = run_condition(scene, traj, _cfg("A", seed)) idx = _windows(traj) if kind == "move": d = float(np.linalg.norm(np.asarray(ev.payload["position"]) - scene.get(target).pose.position)) what = f"move object #{target} {d:.1f} m and turn it" elif kind == "remove": what = f"delete object #{target} from the world" else: v = np.asarray(ev.payload["value"], dtype=float) what = ( f"recolour object #{target} to " f"" f"RGB {np.round(v, 2).tolist()}" ) rows = [] for res, cond in ((off, "A"), (on, "D")): for s in res.edit_scores: expressible = ( "yes" if cond == "D" else "no — no addressable world state" ) if s.complied: v = "yes" elif s.ledger_correct: v = "written, not confirmable" else: v = "no" rows.append( f"({cond}) {CONDITION_NAMES[cond]}{expressible}" f"{v}{s.detail}" ) header = ( f"

Command: {what}

" f"

Issued at frame {ev.frame}, while the object is off screen " f"(frames {traj.departure_frame}–{traj.return_frame}).

" f"

Panels: {PANEL_CAPTION}

{note}" ) table = ( "" "" + "".join(rows) + "
conditioncan express it?obeyed?evidence
" f"

Conditions A–C hold the world implicitly, in activations. There is no " f'row named "object #{target}" to write to, so move/remove/' f"set_attr are not merely hard for them — they are undefined.

" ) return { "header": header, "off_img": _filmstrip(off.frames, idx), "on_img": _filmstrip(on.frames, idx), "table": table, "ledger": _ledger_html(on), } def ledger_view(seed: int, n_objects: int, absence: int, target: int, rewind_to: int) -> Dict[str, Any]: """Show the ledger, its transaction log, and the effect of a rewind. Claim: E -- the world is a table with an audit trail; rewinding is one call. """ seed, n_objects, absence = int(seed), int(n_objects), int(absence) scene = make_scene(n_objects, seed=seed) tgt, _ = _resolve_target(scene, int(np.clip(target, 0, n_objects - 1)), seed) traj = make_departure_return_trajectory(scene, tgt, absence, seed=seed) res = run_condition(scene, traj, _cfg("D", seed)) led = res.ledger before = _ledger_html(res) log_rows = "".join( f"{t.index}{t.t}{t.op}" f"{t.object_id}{t.source}{t.note or ''}" for t in led.log[-40:] ) log = ( "" "" + log_rows + "
#frameopobjectsourcenote
" ) v0 = led.version undone = led.rollback_to_time(int(rewind_to)) note = ( f"

Rewound to frame {int(rewind_to)}: undid {undone} of {v0} transactions. " f"The ledger is now exactly as it stood at that instant, object for object. No learned " f"memory offers this operation — its state is entangled across every object and every " f"timestep at once.

" ) return {"before": before, "log": log, "after": _ledger_html(res), "note": note}