Files
cubelinux/harness_cube_panel.py
T
luulu 2223a2631f cube-names: the name tier at the edge, and the live cutover
The daemon no longer interprets names, so something must — outside the process
that holds the store, because that was the divergence: §5 puts the language in
the daemon, index.html says the coordinate layer is not layered on top and has
no translation step inside the OS.

- cube-names: accepts the name-addressed protocol the machine's services already
  speak, maps it with cube_core::Coord::named, and runs the resulting command
  against cubed through cube-client. Stateless, decides nothing, and deliberately
  outside §5's crate set: it is the edge, not the substrate. `guard` is refused by
  name rather than half-carried — policy is a decision, not a translation.
- cube-command: `cell put|get|del` — the byte plane, which writes no header.
  Without it a remote store could not be a faithful `Store`: `put` writes a
  payload *and* its header, so every header-tier write through a socket acquired
  a header of its own, and a record's kind/visibility was overwritten on the next
  write. Now `DaemonStore` maps to the cell verbs and behaves exactly like a
  local store, and the header tier on top of it works.
- cube-client: `cell_put/cell_get/cell_delete`; a record of zero bytes reads back
  as a record, not as absence (the verb's words carry that distinction, and a
  filesystem above this needs it).
- cube-cli/control plane: the in-repo Python tools default to the name tier.
- Live cutover performed: translator unit installed, CUBED_SOCKET set for the five
  name-addressed units, cubed restarted on the language, store checkpointed, guest
  path (TCP :9231 → bridge → translator → daemon) verified end to end, watchdog
  probe taught both spellings so it can never restart a healthy daemon over a
  protocol change. Details, including the pre-existing knowledge-api 203/EXEC
  breakage, in CUTOVER-language-protocol.md.
- deploy/: cubed-names.service, verify-name-tier.sh (the whole path on /tmp
  sockets, writing nothing to the live store).

156 tests green, no clippy warnings; pinned image verifies (8,399,506 bytes
expected and actual); cube-core still builds for thumbv7em-none-eabihf.
2026-09-18 18:48:33 -04:00

150 lines
6.8 KiB
Python

#!/usr/bin/env python3
"""
harness_cube_panel.py - REAL verification harness for the CUBE (Squared Plus)
control-panel circuit. Asserts on every check; exits non-zero on any failure.
Circuit exercised (end-to-end, against the LIVE system):
A. FRONTEND - both consoles served; renamed to CUBE; HTML well-formed
(validated by stdlib HTMLParser; node is root-only here).
B. BACKEND - full worker-profile loop via /api/cube-vm/*:
create -> list(shows) -> read(matches) -> status(running)
-> delete -> list(gone).
C. PERSIST - schematic DUAL-CUBE-WORKING-PLAN title == CUBE (Squared Plus);
project-continuity registry seeded.
D. SYSTEMD - both refresh timers enabled+active; last service fire exit 0.
"""
import os, sys, json, base64, subprocess, urllib.request, datetime, socket
from html.parser import HTMLParser
API = "http://127.0.0.1"
SOCK = (
os.environ.get("CUBE_SOCKET") or "/run/user/1000/cubelinux/cubed-names.sock"
)
NS_SCHEMA = "cube-schematic"
NS_PROJ = "project-continuity"
TEST_ID = "_harness_%d" % os.getpid()
results = []
def check(name, ok, detail=""):
results.append((name, ok, detail))
line = (" PASS " if ok else " FAIL ") + name
if (not ok) and detail:
line += " -- " + detail
print(line)
return ok
def cubed_rpc(req, timeout=5):
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM); s.settimeout(timeout)
s.connect(SOCK); s.sendall((json.dumps(req) + "\n").encode())
buf = b""
while b"\n" not in buf:
c = s.recv(4096)
if not c: break
buf += c
s.close(); return json.loads(buf.split(b"\n", 1)[0])
def get_json(path):
return json.loads(urllib.request.urlopen(API + path, timeout=5).read().decode())
def post_json(path, body):
req = urllib.request.Request(API + path, data=json.dumps(body).encode(),
headers={"Content-Type": "application/json"}, method="POST")
return json.loads(urllib.request.urlopen(req, timeout=10).read().decode())
def html_well_formed(url):
"""Real HTML well-formedness via stdlib HTMLParser (tag balance, no stray closes)."""
class V(HTMLParser):
def __init__(s):
super().__init__(convert_charrefs=True)
s.void = {'meta','link','br','img','input','hr','area','base',
'col','embed','source','track','wbr','!doctype'}
s.stack = []; s.errs = []
def handle_starttag(s, t, a):
if t not in s.void: s.stack.append(t)
def handle_endtag(s, t):
if t in s.void: return
if s.stack and s.stack[-1] == t: s.stack.pop()
elif t in s.stack:
while s.stack and s.stack.pop() != t: pass
else: s.errs.append(t)
try:
data = urllib.request.urlopen(url, timeout=10).read().decode("utf-8", "replace")
except Exception:
return False
v = V(); v.feed(data)
return (not v.stack) and (not v.errs)
def systemd_state(unit):
en = subprocess.run(["systemctl", "--user", "is-enabled", unit],
capture_output=True, text=True).stdout.strip()
ac = subprocess.run(["systemctl", "--user", "is-active", unit],
capture_output=True, text=True).stdout.strip()
res = subprocess.run(["systemctl", "--user", "show", "-p", "Result",
unit.replace(".timer", ".service")],
capture_output=True, text=True).stdout.strip()
return en, ac, res
def circuit():
ok_all = True
print("\n[A] FRONTEND")
idx = urllib.request.urlopen(API + "/", timeout=5).read().decode()
vm = urllib.request.urlopen(API + "/cube-vm.html", timeout=5).read().decode()
ok_all &= check("console served + renamed CUBE⊞",
"CUBE⊞ · Squared Plus · AI Command Center" in idx,
"title mark missing")
ok_all &= check("panel served + renamed CUBE⊞",
"<h1>CUBE⊞</h1>" in vm, "h1 mark missing")
ok_all &= check("console HTML well-formed", html_well_formed(API + "/"))
ok_all &= check("panel HTML well-formed", html_well_formed(API + "/cube-vm.html"))
print("\n[B] BACKEND worker-profile loop")
prof = {"name": "Harness Worker", "tools": ["read_file", "shell_ro"],
"model": "local-default",
"expert": {"domain": "test", "prompt": "x", "knowledge": "y"},
"recall": {"coords": [], "namespaces": ["hermes"]},
"runtime": {"vcpus": 2, "mem_mb": 2048}}
r = post_json("/api/cube-vm/config", {"id": TEST_ID, "profile": prof})
ok_all &= check("create profile", r.get("ok") is True, str(r))
cfgs = get_json("/api/cube-vm/configs").get("profiles", [])
ok_all &= check("profile appears in roster", any(p["id"] == TEST_ID for p in cfgs))
rd = get_json("/api/cube-vm/config/" + TEST_ID)
ok_all &= check("individual read matches",
rd.get("profile", {}).get("name") == "Harness Worker", str(rd))
st = get_json("/api/cube-vm/status")
ok_all &= check("VM status reports running", st.get("running") is True,
str(st.get("boot_state")))
d = post_json("/api/cube-vm/delete", {"id": TEST_ID})
ok_all &= check("delete profile", d.get("ok") is True)
cfgs2 = get_json("/api/cube-vm/configs").get("profiles", [])
ok_all &= check("profile gone after delete",
not any(p["id"] == TEST_ID for p in cfgs2))
print("\n[C] PERSISTENCE (CUBE store)")
sch = cubed_rpc({"cmd": "read", "namespace": NS_SCHEMA, "name": "DUAL-CUBE-WORKING-PLAN"})
title = json.loads(base64.b64decode(sch["value"]).decode()).get("title", "")
ok_all &= check("schematic title == CUBE⊞ (Squared Plus) in cube",
"CUBE⊞ (Squared Plus)" in title, title[:40])
sop = cubed_rpc({"cmd": "read", "namespace": NS_PROJ, "name": "SOP"})
ok_all &= check("project-continuity SOP seeded", sop.get("ok") is True)
plist = cubed_rpc({"cmd": "list", "namespace": NS_PROJ})
ok_all &= check("project-continuity registry populated",
len(plist.get("entries", [])) >= 5,
str(len(plist.get("entries", []))))
print("\n[D] SYSTEMD timers")
for unit in ("cube-schematic-refresh.timer", "project-continuity-refresh.timer"):
en, ac, res = systemd_state(unit)
ok_all &= check("%s enabled+active (Result=%s)" % (unit, res),
en == "enabled" and ac == "active", "%s/%s" % (en, ac))
return ok_all
if __name__ == "__main__":
print("=== CUBE harness run @ %s ===" % datetime.datetime.now().isoformat(timespec="seconds"))
print("TEST_ID=%s" % TEST_ID)
ok = circuit()
npass = sum(1 for _, o, _ in results if o)
nfail = len(results) - npass
print("\n=== SUMMARY: %d/%d checks passed, %d failed ===" % (npass, len(results), nfail))
sys.exit(0 if ok else 1)