🧹 health-sweep tidy-up: 5 low-severity loose ends (0 broken found)
A 13-agent adversarial whole-app sweep (client controls / runtime / server-auth /
new features / feed-config-honesty, each finding reproduced-or-refuted) found ZERO
broken functions — verdict healthy. Fixed the reachable low-severity edges it did
confirm:
- viz/index.html:1804 — arranger 'grooves' tab threw TypeError (nSel.isNote) when
dests is empty in the cold-connect window (post-sign-in, pre-WS-hello). Guard:
dests.get(arrSelKey) || {isNote:false} (the 'clips' tab already tolerates empty).
- viz/index.html — picking a skin from the sky menu / F4 next-skin / F4 prev while
in ZERO mode force-enabled an invisible, un-toggleable chakraMode (every clear
path is zeroMode-guarded). Added the same !zeroMode guard to all three sites
(byte-identical outside zero — no regression).
- hub.py:117 — GODSTRUMENT_READONLY parse treated any non-empty non-'0' value as
true (so 'false'/'no'/'off' enabled read-only). Now an explicit truthy set
{1,true,yes,on}; prod uses '1' → stays read-only (verified before deploy).
- viz/index.html:2996 — removed a dead else branch in zero 'save as vibe' (its
'vibes land in the next update' placeholder was unreachable; saveVibe is a real
sibling method) → call this.saveVibe(gk) directly.
- transform.py:40 — collapsed a no-op ternary (both branches float(v)).
- viz/manual.html — regenerated (was stale vs build_manual.py; picked up the
admin-panel CSS added in 764e28b; grimoire prose was already in sync).
Left as documented cosmetic: sanitizeVibe caps emoji at 2 code points (can split a
ZWJ/flag glyph on a shared vibe — display only, no XSS). Verified: node --check,
all .py compile, auth --selftest green, app boots into zero clean, console clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
47b51b98ca
commit
9ab1b0f5ae
2
hub.py
2
hub.py
@ -115,7 +115,7 @@ class Hub:
|
||||
# (the ws control channel has no auth — safe to expose publicly this way).
|
||||
# Set via config "readonly": true or env GODSTRUMENT_READONLY=1.
|
||||
self.readonly = bool(cfg.get("readonly")) or \
|
||||
os.environ.get("GODSTRUMENT_READONLY", "") not in ("", "0")
|
||||
os.environ.get("GODSTRUMENT_READONLY", "").strip().lower() in ("1", "true", "yes", "on")
|
||||
|
||||
self.signals: dict[str, Signal] = {}
|
||||
self._raw_lock = threading.Lock()
|
||||
|
||||
@ -37,7 +37,7 @@ class Tweak:
|
||||
if spec:
|
||||
for k, v in spec.items():
|
||||
if k in self.p:
|
||||
self.p[k] = float(v) if not isinstance(v, bool) else float(v)
|
||||
self.p[k] = float(v)
|
||||
self._held: dict[str, float] = {} # freeze holds, keyed by signal name
|
||||
self._lag: dict[str, float] = {} # smoothing state, keyed by signal name
|
||||
self.orbit_lfo = 1.0 # external planetary-orbit gain (hub-set)
|
||||
|
||||
@ -1800,7 +1800,7 @@
|
||||
pick.appendChild(lb);
|
||||
}
|
||||
const hint2 = document.createElement("span"); hint2.className = "albl";
|
||||
const nSel = dests.get(arrSelKey);
|
||||
const nSel = dests.get(arrSelKey) || { isNote: false }; // dests can be empty in the cold-connect window (pre-hello)
|
||||
hint2.textContent = nSel.isNote
|
||||
? "piano roll · " + NOTE_NAMES[gScale.root] + " " + gScale.name.replace("_", " ") + " · click to place · stack 2+ in a column → plays one at random"
|
||||
: "16-step gate · lit steps let the world's signal through";
|
||||
@ -2993,7 +2993,7 @@
|
||||
unp.onclick = () => { for (const src of node.members) this._dropSource(src); this.refreshSockets(); this.persist(); m.remove(); };
|
||||
m.appendChild(unp);
|
||||
const vibe = document.createElement("div"); vibe.textContent = "💾 save as vibe"; vibe.style.cssText = "color:#9fd0ff;cursor:pointer;margin:5px 0";
|
||||
vibe.onclick = () => { m.remove(); if (this.saveVibe) this.saveVibe(gk); else eventTicker.unshift({ text: "💾 vibes land in the next update — build a feeling, save it, hand it to a friend", tAdded: now(), src: "sys" }); };
|
||||
vibe.onclick = () => { m.remove(); this.saveVibe(gk); };
|
||||
m.appendChild(vibe);
|
||||
document.body.appendChild(m);
|
||||
const off = (ev) => { if (!m.contains(ev.target)) { m.remove(); document.removeEventListener("mousedown", off, true); } };
|
||||
@ -6580,7 +6580,7 @@
|
||||
for (const sk of Object.keys(SKINS)) {
|
||||
const it2 = document.createElement("div"); it2.className = "it";
|
||||
it2.textContent = (SKINS[sk].key === activeSkin.key ? "✓ " : "") + SKINS[sk].label;
|
||||
it2.onclick = () => { setSkin(sk); if (!chakraMode) { chakraMode = true; clearTrails(); } closeCtx(); };
|
||||
it2.onclick = () => { setSkin(sk); if (!chakraMode && !zeroMode) { chakraMode = true; clearTrails(); } closeCtx(); };
|
||||
skinSub.appendChild(it2);
|
||||
}
|
||||
ctxItem(performMode ? "leave performance mode" : "performance mode",
|
||||
@ -7170,8 +7170,8 @@
|
||||
grimoire: { label: "open the grimoire (help)", run: () => { const g = document.getElementById("grimoire"); if (g) g.classList.add("open"); } },
|
||||
play: { label: "play / stop the synth", run: () => { if (typeof Synth !== "undefined") Synth.toggle(); } },
|
||||
chakraView:{ label: "chakra / skin view", run: () => { if (zeroMode) return; chakraMode = !chakraMode; if (!chakraMode) { layoutDirty = true; exitMind(); } else clearTrails(); } },
|
||||
skinNext: { label: "next skin", run: () => { setSkin(nextSkinKey()); if (!chakraMode) { chakraMode = true; clearTrails(); } } },
|
||||
skinPrev: { label: "previous skin", run: () => { setSkin(prevSkinKey()); if (!chakraMode) { chakraMode = true; clearTrails(); } } },
|
||||
skinNext: { label: "next skin", run: () => { setSkin(nextSkinKey()); if (!chakraMode && !zeroMode) { chakraMode = true; clearTrails(); } } },
|
||||
skinPrev: { label: "previous skin", run: () => { setSkin(prevSkinKey()); if (!chakraMode && !zeroMode) { chakraMode = true; clearTrails(); } } },
|
||||
moodCycle: { label: "cycle mood (first light / drift / storm)", run: () => cycleMood() },
|
||||
tracks: { label: "tracks / arranger", run: () => { arr.open ? closeArranger() : openArranger(); } },
|
||||
perform: { label: "performance mode", run: () => window.dispatchEvent(new KeyboardEvent("keydown", { key: "p" })) },
|
||||
|
||||
@ -351,6 +351,25 @@
|
||||
padding: 4px 9px; user-select: text; -webkit-user-select: text; transition: background 0.15s; }
|
||||
#account .codechip:hover { background: rgba(124,255,178,0.18); }
|
||||
#account .codechip.copied { color: #fff; border-color: #7cffb2; background: rgba(124,255,178,0.3); }
|
||||
/* admin — user management */
|
||||
#account.wide .box { width: 520px; }
|
||||
#account .userlist { margin-top: 6px; }
|
||||
#account .urow { padding: 8px 0; border-bottom: 1px solid rgba(120,150,200,0.12); }
|
||||
#account .urow .uhead { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
|
||||
#account .urow .uname { color: #eaf1ff; font-size: 13px; font-weight: 600; }
|
||||
#account .urow .umeta { color: rgba(160,180,210,0.6); font-size: 10.5px; }
|
||||
#account .urow .ubadge { font-size: 9.5px; letter-spacing: .5px; text-transform: uppercase; padding: 1px 6px; border-radius: 20px;
|
||||
background: rgba(255,214,92,0.14); color: #ffd65c; border: 1px solid rgba(255,214,92,0.35); }
|
||||
#account .urow .uact { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
|
||||
#account .urow .ubtn { background: rgba(255,255,255,0.05); color: #b9c8e2; border: 1px solid rgba(120,150,200,0.22);
|
||||
border-radius: 7px; padding: 4px 9px; cursor: pointer; font-size: 10.5px; }
|
||||
#account .urow .ubtn:hover { border-color: rgba(150,180,255,0.55); color: #eaf1ff; }
|
||||
#account .urow .ubtn.danger:hover { border-color: rgba(255,120,120,0.6); color: #ffb3b3; }
|
||||
#account .urow .uedit { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
|
||||
#account .urow .uedit input { flex: 1 1 130px; min-width: 0; padding: 5px 8px; border-radius: 7px; font: inherit; font-size: 11px;
|
||||
background: rgba(8,12,24,0.7); color: #eaf1ff; border: 1px solid rgba(120,150,200,0.25); }
|
||||
#account .urow .umsg { font-size: 10.5px; margin-top: 4px; min-height: 12px; }
|
||||
#account .urow .umsg .tmp { font-family: monospace; color: #7cffb2; user-select: text; }
|
||||
|
||||
/* ---- gated landing page (shown until you sign in) ---- */
|
||||
#landing {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user