Expose formula integrity in the Brain HUD

#8
static/3d/brain.html CHANGED
@@ -66,6 +66,11 @@
66
  #hud .row .dot{width:9px;height:9px;border-radius:50%;box-shadow:0 0 7px currentColor;flex:0 0 auto}
67
  #hud .row .right{display:flex;align-items:center;gap:6px}
68
  #hud .row .val{color:#eef3f6}
 
 
 
 
 
69
  #hud .note{color:#6d7d8a;font-size:10.5px;line-height:1.45;margin-top:2px;border-top:1px solid #15212c;padding-top:6px}
70
  #hud .plainbtn{font:11px ui-monospace,monospace;padding:5px 11px;border-radius:7px;border:1px solid var(--proof);
71
  background:#08140f;color:var(--proof);cursor:pointer;width:fit-content;margin-top:2px}
@@ -199,8 +204,15 @@ const LOBES = [
199
  dir: [0, 0.55, 0.95], url: "https://github.com/" + GH_ORG + "/a11oy/blob/22b084d4a74abb4d5911ca9dc303c35d222bd284/proofs/lutar-lean/Lutar/Puriq/Formulas/ProvedFormulas.lean",
200
  fetchStat: async () => {
201
  const s = requireLive(await EVIDENCE, "formulas");
 
 
 
 
 
202
  const n = s.theorem_count;
203
  return { text: n + " theorems", honesty: "MEASURED",
 
 
204
  caption: "Frontal lobe · " + n + " `theorem` declarations counted server-side from a commit-pinned " +
205
  "ProvedFormulas.lean artifact · SHA-256 " + s.content_sha256.slice(0, 12) + "… VERIFIED · " +
206
  "MEASURED via same-origin bounded evidence route · click to read the pinned proofs" };
@@ -560,7 +572,23 @@ function buildHud() {
560
  hud[key] = { val, chip };
561
  };
562
 
563
- LOBES.forEach((l) => mkRow(l.key, l.name, l.color));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564
 
565
  const note = document.createElement("div");
566
  note.className = "note";
@@ -601,6 +629,14 @@ function setRow(key, text, honesty) {
601
  label.updateChip(r.chip, honesty);
602
  }
603
 
 
 
 
 
 
 
 
 
604
  // ---------------------------------------------------------------------------
605
  // pointer picking — hover to caption a lobe, click to open its live source.
606
  // (Only in orbit mode; mold mode owns the pointer.)
@@ -664,6 +700,7 @@ async function main() {
664
  try {
665
  const s = await lobe.fetchStat();
666
  setRow(lobe.key, s.text, s.honesty);
 
667
  refreshLobeLabel(lobe.key, s.honesty, lobe.name + " \u00b7 " + s.text);
668
  const lm = lobeMarkers[lobe.key];
669
  if (lm) lm.marker.userData.caption = s.caption;
@@ -672,6 +709,9 @@ async function main() {
672
  } catch (e) {
673
  console.warn("[brain] " + lobe.key + " unavailable:", e && e.message);
674
  setRow(lobe.key, "NO-LIVE-DATA", "STRUCTURAL-ONLY");
 
 
 
675
  refreshLobeLabel(lobe.key, "STRUCTURAL-ONLY", lobe.name + " \u00b7 NO-LIVE-DATA");
676
  const lm = lobeMarkers[lobe.key];
677
  if (lm) lm.marker.userData.caption = lobe.name + " \u00b7 NO-LIVE-DATA \u2014 this feed is unreachable right now; nothing is guessed in its place.";
 
66
  #hud .row .dot{width:9px;height:9px;border-radius:50%;box-shadow:0 0 7px currentColor;flex:0 0 auto}
67
  #hud .row .right{display:flex;align-items:center;gap:6px}
68
  #hud .row .val{color:#eef3f6}
69
+ #hud .attestation{display:block;color:#9fb1bf;font-size:9.5px;line-height:1.45;padding:5px 7px;
70
+ margin:-2px 0 1px 16px;border-left:2px solid #375464;background:rgba(8,20,15,.58);
71
+ overflow-wrap:anywhere;word-break:break-word}
72
+ #hud .attestation[data-state="VERIFIED"]{color:var(--proof);border-left-color:var(--proof)}
73
+ #hud .attestation[data-state="UNAVAILABLE"]{color:#e08a8a;border-left-color:#e08a8a}
74
  #hud .note{color:#6d7d8a;font-size:10.5px;line-height:1.45;margin-top:2px;border-top:1px solid #15212c;padding-top:6px}
75
  #hud .plainbtn{font:11px ui-monospace,monospace;padding:5px 11px;border-radius:7px;border:1px solid var(--proof);
76
  background:#08140f;color:var(--proof);cursor:pointer;width:fit-content;margin-top:2px}
 
204
  dir: [0, 0.55, 0.95], url: "https://github.com/" + GH_ORG + "/a11oy/blob/22b084d4a74abb4d5911ca9dc303c35d222bd284/proofs/lutar-lean/Lutar/Puriq/Formulas/ProvedFormulas.lean",
205
  fetchStat: async () => {
206
  const s = requireLive(await EVIDENCE, "formulas");
207
+ if (s.integrity_state !== "VERIFIED" || s.mutable_reference !== false ||
208
+ !/^[0-9a-f]{40}$/.test(s.source_commit || "") ||
209
+ !/^[0-9a-f]{64}$/.test(s.content_sha256 || "")) {
210
+ throw new Error("formula integrity contract incomplete");
211
+ }
212
  const n = s.theorem_count;
213
  return { text: n + " theorems", honesty: "MEASURED",
214
+ attestation: "proof artifact · immutable commit " + s.source_commit +
215
+ " · SHA-256 " + s.content_sha256 + " · " + s.integrity_state,
216
  caption: "Frontal lobe · " + n + " `theorem` declarations counted server-side from a commit-pinned " +
217
  "ProvedFormulas.lean artifact · SHA-256 " + s.content_sha256.slice(0, 12) + "… VERIFIED · " +
218
  "MEASURED via same-origin bounded evidence route · click to read the pinned proofs" };
 
572
  hud[key] = { val, chip };
573
  };
574
 
575
+ LOBES.forEach((l) => {
576
+ mkRow(l.key, l.name, l.color);
577
+ if (l.key === "formulas") {
578
+ const proof = document.createElement("a");
579
+ proof.id = "formula-attestation";
580
+ proof.className = "attestation";
581
+ proof.href = l.url;
582
+ proof.target = "_blank";
583
+ proof.rel = "noopener";
584
+ proof.setAttribute("aria-live", "polite");
585
+ proof.dataset.state = "PENDING";
586
+ proof.textContent = "proof artifact · integrity verification pending…";
587
+ proof.title = "Open the immutable formula source artifact";
588
+ hudEl.appendChild(proof);
589
+ hud[l.key].attestation = proof;
590
+ }
591
+ });
592
 
593
  const note = document.createElement("div");
594
  note.className = "note";
 
629
  label.updateChip(r.chip, honesty);
630
  }
631
 
632
+ function setFormulaAttestation(text, state) {
633
+ const proof = hud.formulas && hud.formulas.attestation;
634
+ if (!proof) return;
635
+ proof.textContent = text;
636
+ proof.dataset.state = state;
637
+ proof.title = text;
638
+ }
639
+
640
  // ---------------------------------------------------------------------------
641
  // pointer picking — hover to caption a lobe, click to open its live source.
642
  // (Only in orbit mode; mold mode owns the pointer.)
 
700
  try {
701
  const s = await lobe.fetchStat();
702
  setRow(lobe.key, s.text, s.honesty);
703
+ if (lobe.key === "formulas") setFormulaAttestation(s.attestation, "VERIFIED");
704
  refreshLobeLabel(lobe.key, s.honesty, lobe.name + " \u00b7 " + s.text);
705
  const lm = lobeMarkers[lobe.key];
706
  if (lm) lm.marker.userData.caption = s.caption;
 
709
  } catch (e) {
710
  console.warn("[brain] " + lobe.key + " unavailable:", e && e.message);
711
  setRow(lobe.key, "NO-LIVE-DATA", "STRUCTURAL-ONLY");
712
+ if (lobe.key === "formulas") {
713
+ setFormulaAttestation("proof artifact · integrity UNAVAILABLE · no theorem count trusted", "UNAVAILABLE");
714
+ }
715
  refreshLobeLabel(lobe.key, "STRUCTURAL-ONLY", lobe.name + " \u00b7 NO-LIVE-DATA");
716
  const lm = lobeMarkers[lobe.key];
717
  if (lm) lm.marker.userData.caption = lobe.name + " \u00b7 NO-LIVE-DATA \u2014 this feed is unreachable right now; nothing is guessed in its place.";
test/test_holographic_zero_cdn.py CHANGED
@@ -84,6 +84,16 @@ class HolographicZeroCdnTests(unittest.TestCase):
84
  self.assertEqual(len(holographic._BRAIN_FORMULA_COMMIT), 40)
85
  self.assertEqual(len(holographic._BRAIN_FORMULA_SHA256), 64)
86
 
 
 
 
 
 
 
 
 
 
 
87
  def test_formula_hash_mismatch_is_unavailable_not_measured(self):
88
  payload = holographic.brain_evidence(
89
  fetch_json=self._json,
 
84
  self.assertEqual(len(holographic._BRAIN_FORMULA_COMMIT), 40)
85
  self.assertEqual(len(holographic._BRAIN_FORMULA_SHA256), 64)
86
 
87
+ def test_formula_integrity_is_persistently_visible_not_hover_only(self):
88
+ brain = (Path(__file__).parents[1] / "static" / "3d" / "brain.html").read_text(encoding="utf-8")
89
+ self.assertIn('proof.id = "formula-attestation"', brain)
90
+ self.assertIn('proof.setAttribute("aria-live", "polite")', brain)
91
+ self.assertIn('s.source_commit', brain)
92
+ self.assertIn('s.content_sha256', brain)
93
+ self.assertIn('s.integrity_state', brain)
94
+ self.assertIn('setFormulaAttestation(s.attestation, "VERIFIED")', brain)
95
+ self.assertIn('integrity UNAVAILABLE · no theorem count trusted', brain)
96
+
97
  def test_formula_hash_mismatch_is_unavailable_not_measured(self):
98
  payload = holographic.brain_evidence(
99
  fetch_json=self._json,