// SPDX-License-Identifier: Apache-2.0 // © 2026 Lutar, Stephen P. — SZL Holdings · ORCID 0009-0001-0110-4173 · Doctrine v11 // // surfaces/grpo.js — GRPO REWARD DYNAMICS organ for the holographic frontier // ring (Group Relative Policy Optimization, critic-free RL post-training). // Renders each training step's sampled reward GROUP as points scattering // around a group-mean plane; each point's height above/below the plane is // its group-normalized advantage (proof-teal above the mean, grey below), // a KL-tether line ties the group to a reference-policy anchor, and a HUD // tracks mean_reward + kl_divergence + final_policy_score climbing over the // run, from the live snapshot at /api/killinchu/v1/grpo/reward-dynamics. // Honesty label "MODELED" is read VERBATIM from the JSON and displayed // as-is; it is never upgraded. // // Surface export shape (mirrors specdecode.js / testtime.js exactly): // export default { id, title, endpoints, mount(ctx), unmount() } // ctx = { stage, container, live, label, THREE, szl3d } // // DATA SHOWN (all from live endpoint): // group_size, steps, kl_beta, clip_eps, mean_reward, mean_advantage, // kl_divergence, clip_fraction, final_policy_score, reward_trajectory[], // kl_trajectory[], policy_score_trajectory[], advantage_trajectory[], // clip_fraction_trajectory[] // // LEADERS ADOPTED & CITED (clean-room; NOT claimed as SZL's own): // GRPO (group-relative advantage + PPO-clip + KL-penalty arithmetic // simulated here): // Shao et al. 2024, "DeepSeekMath", arXiv:2402.03300 // https://arxiv.org/abs/2402.03300 // DeepSeek-R1 (large-scale RL post-training using GRPO — reference only): // DeepSeek-AI 2025, arXiv:2501.12948 // https://arxiv.org/abs/2501.12948 // // HONESTY LABELS: MODELED (deterministic simulation of GRPO group-advantage + // PPO-clip + KL arithmetic; NOT a trained policy; NEVER-CLAIMED-AS // DeepSeek-R1/DeepSeekMath training). Read verbatim from JSON; never // upgraded here. // COLOURS: lattice-blue 0x5b8dee (group-mean plane / spine), proof-teal // 0x3af4c8 (above-mean / positive-advantage samples, HUD accent), greys // (below-mean / degraded state). Purple BANNED as UI/background. // 0 RUNTIME CDN. Vendored three.js r170 via page importmap. // DOCTRINE v11: degrades gracefully (grey) on 404/error; honesty label still shown. // Nothing here is in the locked-8. Λ stays Conjecture 1. Trust never 100%. import { createShowcase } from "./_showcase.js"; const ID = "grpo"; const TITLE = "GRPO Reward Dynamics · Group-Relative Advantage (live)"; // Endpoint is hosted on the dedicated killinchu Space (isolated compute), reached // cross-origin (killinchu returns access-control-allow-origin: https://a-11-oy.com). // This keeps the GRPO organ's rebuilds/faults isolated from the flagship. const EP = "https://szlholdings-killinchu.hf.space/api/killinchu/v1/grpo/reward-dynamics?seed=42&group_size=8&steps=200&kl_beta=0.04"; // data-viz hues — purple BANNED const C_PLANE = 0x5b8dee; // lattice-blue (group-mean plane / spine) const C_ABOVE = 0x3af4c8; // proof-teal (above-mean / positive-advantage sample, HUD accent) const C_BELOW = 0x5a6570; // grey (below-mean / negative-advantage sample) const C_DIM = 0x42505d; // grey (degraded / no-live-data) const C_GRID = 0x1b3a44; // floor / link colour const C_KL = 0x8a6bff; // NOTE: reserved slot unused — see doctrine note below // Doctrine v11 colour scope: purple (any hue) is BANNED — the KL-tether line // below intentionally uses lattice-blue (dimmed), never the 0x8a6bff constant // above. The constant is retained ONLY as a documented "never use" marker so // future edits do not accidentally reach for a purple hue for the tether. const C_TETHER = 0x5b8dee; // KL-tether line — lattice-blue, dimmed via opacity // group/step scatter layout geometry const STEP_LEN = 1.9; // world-units between steps along X (training-step axis) const GROUP_SPAN = 3.2; // world-units spread of a group across Z (per-sample jitter) const MAX_STEPS = 14; // number of recent steps rendered along the axis const MAX_SAMPLES = 16; // cap on group_size rendered per step (perf) const ADV_SCALE = 1.6; // world-units of height per unit of |advantage| let _stage = null, _THREE = null, _ctx = null, _group = null, _show = null; let _frameReg = false, _polls = [], _el = {}, _badge = null; // geometry handles let _floor = null; let _plane = null; // THREE.Mesh — translucent group-mean plane let _spine = null; // THREE.Line — training-step axis let _sampleMesh = []; // Array> — [step][sampleIdx] let _tethers = []; // Array — KL-tether per step let _marker = null; // THREE.Mesh — HUD "policy_score" pulsing marker // live state const S = { label: null, groupSize: null, // group_size steps: null, // steps klBeta: null, // kl_beta clipEps: null, // clip_eps meanReward: null, // mean_reward meanAdv: null, // mean_advantage klDiv: null, // kl_divergence clipFrac: null, // clip_fraction policyScore: null, // final_policy_score rewardTraj: null, // reward_trajectory[] klTraj: null, // kl_trajectory[] scoreTraj: null, // policy_score_trajectory[] advTraj: null, // advantage_trajectory[] clipTraj: null, // clip_fraction_trajectory[] state: "init", }; // ============================================================================= // mount(ctx) // ============================================================================= export function mount(ctx) { _ctx = ctx; _stage = ctx.stage; _THREE = ctx.THREE; _group = new _THREE.Group(); _stage.scene.add(_group); _stage.camera.position.set(4, 7, 17); try { if (_stage.controls && _stage.controls.target) { _stage.controls.target.set(6, 1, 0); _stage.controls.update(); } } catch (_) {} try { _stage.setBloom(true); } catch (_) {} _buildFloor(); _buildPlaneAndSpine(); _buildScatterGrid(); _buildMarker(); if (!_frameReg) { _stage.onFrame(_onFrame); _frameReg = true; } _badge = ctx.live.createBadge(); _polls.push(ctx.live.poll(EP, 5000, _onGrpo, { badge: _badge, onState: (m) => { S.state = m.state; _paintOverlay(); } })); _buildOverlay(); return { id: ID, started: true }; } // ============================================================================= // builders // ============================================================================= function _buildFloor() { const THREE = _THREE; const grid = new THREE.GridHelper(40, 40, C_GRID, 0x0f2027); grid.material.opacity = 0.18; grid.material.transparent = true; grid.position.y = -0.01; _group.add(grid); _floor = grid; } // Group-mean plane: a thin, translucent strip along the training-step axis at // y=0 representing "the group mean" for each step — advantage is literally // the height of each sample above/below this plane. function _buildPlaneAndSpine() { const THREE = _THREE; const planeGeo = new THREE.PlaneGeometry(STEP_LEN * (MAX_STEPS - 1) + 1.4, GROUP_SPAN + 0.6); const planeMat = new THREE.MeshBasicMaterial({ color: C_PLANE, transparent: true, opacity: 0.08, side: THREE.DoubleSide, }); _plane = new THREE.Mesh(planeGeo, planeMat); _plane.rotation.x = -Math.PI / 2; _plane.position.set((STEP_LEN * (MAX_STEPS - 1)) / 2, 0, 0); _group.add(_plane); const pts = [new THREE.Vector3(0, 0, 0), new THREE.Vector3(STEP_LEN * (MAX_STEPS - 1) + 1, 0, 0)]; const geo = new THREE.BufferGeometry().setFromPoints(pts); const mat = new THREE.LineBasicMaterial({ color: C_PLANE, transparent: true, opacity: 0.5 }); _spine = new THREE.Line(geo, mat); _group.add(_spine); } // Pre-allocate a fixed grid of sample meshes: MAX_STEPS steps x MAX_SAMPLES // samples per step, plus one KL-tether line per step. We toggle // visibility/color/position in-place as live data arrives (no per-poll // geometry churn). function _buildScatterGrid() { const THREE = _THREE; const sampleGeo = new THREE.SphereGeometry(0.16, 12, 10); for (let s = 0; s < MAX_STEPS; s++) { const stepSamples = []; const x = s * STEP_LEN; for (let t = 0; t < MAX_SAMPLES; t++) { // deterministic-looking jitter across Z for visual spread (purely // layout, not data — actual height/color comes from live advantage) const z = (((t * 2654435761) % 1000) / 1000 - 0.5) * GROUP_SPAN; const mesh = new THREE.Mesh( sampleGeo, new THREE.MeshStandardMaterial({ color: C_ABOVE, emissive: C_ABOVE, emissiveIntensity: 0.25, transparent: true, opacity: 0.0 }), ); mesh.position.set(x, 0, z); mesh.visible = false; _group.add(mesh); stepSamples.push(mesh); } _sampleMesh.push(stepSamples); // KL-tether: vertical line from the plane up to a small anchor point, // whose height encodes that step's KL-divergence-vs-reference estimate. const tetherGeo = new THREE.BufferGeometry().setFromPoints([ new THREE.Vector3(x, 0, GROUP_SPAN / 2 + 0.4), new THREE.Vector3(x, 0.01, GROUP_SPAN / 2 + 0.4), ]); const tetherMat = new THREE.LineBasicMaterial({ color: C_TETHER, transparent: true, opacity: 0.55 }); const tether = new THREE.Line(tetherGeo, tetherMat); tether.visible = false; _group.add(tether); _tethers.push(tether); } } function _buildMarker() { const THREE = _THREE; _marker = new THREE.Mesh( new THREE.IcosahedronGeometry(0.26, 1), new THREE.MeshStandardMaterial({ color: C_ABOVE, emissive: C_ABOVE, emissiveIntensity: 0.5, wireframe: true, transparent: true, opacity: 0.85 }), ); _marker.position.set(0, -0.6, 0); _group.add(_marker); } // ============================================================================= // live data handler // ============================================================================= function _onGrpo(j) { // read honesty label VERBATIM — never upgrade S.label = (j.label || "MODELED").toUpperCase(); S.groupSize = typeof j.group_size === "number" ? j.group_size : null; S.steps = typeof j.steps === "number" ? j.steps : null; S.klBeta = typeof j.kl_beta === "number" ? j.kl_beta : null; S.clipEps = typeof j.clip_eps === "number" ? j.clip_eps : null; S.meanReward = typeof j.mean_reward === "number" ? j.mean_reward : null; S.meanAdv = typeof j.mean_advantage === "number" ? j.mean_advantage : null; S.klDiv = typeof j.kl_divergence === "number" ? j.kl_divergence : null; S.clipFrac = typeof j.clip_fraction === "number" ? j.clip_fraction : null; S.policyScore = typeof j.final_policy_score === "number" ? j.final_policy_score : null; S.rewardTraj = Array.isArray(j.reward_trajectory) ? j.reward_trajectory : null; S.klTraj = Array.isArray(j.kl_trajectory) ? j.kl_trajectory : null; S.scoreTraj = Array.isArray(j.policy_score_trajectory) ? j.policy_score_trajectory : null; S.advTraj = Array.isArray(j.advantage_trajectory) ? j.advantage_trajectory : null; S.clipTraj = Array.isArray(j.clip_fraction_trajectory)? j.clip_fraction_trajectory: null; _updateScatter(); _paintOverlay(); } // ============================================================================= // geometry updater — drives the group scatter / KL-tethers from live data // ============================================================================= function _updateScatter() { const live = S.state === "live"; const groupSize = live && S.groupSize ? Math.min(S.groupSize, MAX_SAMPLES) : 0; // Use the tail of each trajectory (most recent MAX_STEPS points) so the // pipeline always shows the latest training window. const rewardTail = live && S.rewardTraj && S.rewardTraj.length ? S.rewardTraj.slice(-MAX_STEPS) : []; const advTail = live && S.advTraj && S.advTraj.length ? S.advTraj.slice(-MAX_STEPS) : []; const klTail = live && S.klTraj && S.klTraj.length ? S.klTraj.slice(-MAX_STEPS) : []; const nSteps = rewardTail.length; for (let s = 0; s < MAX_STEPS; s++) { const showStep = live && s < nSteps && groupSize > 0; const meanAdvAtStep = showStep ? advTail[s] : 0; const klAtStep = showStep ? klTail[s] : 0; _tethers[s].visible = showStep; if (showStep) { const tetherHeight = Math.min(2.4, 0.3 + klAtStep * 6.0); const pos = _tethers[s].geometry.attributes.position; pos.setXYZ(1, s * STEP_LEN, tetherHeight, GROUP_SPAN / 2 + 0.4); pos.needsUpdate = true; _tethers[s].material.color.setHex(C_TETHER); _tethers[s].material.opacity = 0.55; } for (let t = 0; t < MAX_SAMPLES; t++) { const mesh = _sampleMesh[s][t]; if (!showStep || t >= groupSize) { mesh.visible = false; continue; } mesh.visible = true; // per-sample advantage sign alternates deterministically around the // step's mean |advantage| so the cloud visibly straddles the plane — // exact per-sample values are not re-transmitted by the endpoint // (only the step aggregate is), so this renders the aggregate // magnitude as a symmetric scatter, which is an honest visual proxy. const sign = (t % 2 === 0) ? 1 : -1; const jitter = 0.65 + 0.35 * (((t * 2246822519) % 1000) / 1000); const height = sign * meanAdvAtStep * ADV_SCALE * jitter; mesh.position.y = height; const above = height >= 0; const color = above ? C_ABOVE : C_BELOW; mesh.material.color.setHex(color); mesh.material.emissive.setHex(color); mesh.material.emissiveIntensity = above ? 0.5 : 0.15; mesh.material.opacity = above ? 0.92 : 0.45; } } // plane + spine + marker degrade to grey when not live _plane.material.color.setHex(live ? C_PLANE : C_DIM); _plane.material.opacity = live ? 0.08 : 0.03; _spine.material.color.setHex(live ? C_PLANE : C_DIM); _spine.material.opacity = live ? 0.5 : 0.15; if (_marker) { if (live && S.policyScore != null) { _marker.material.color.setHex(C_ABOVE); _marker.material.emissive.setHex(C_ABOVE); _marker.material.opacity = 0.85; // marker rides along X proportional to final_policy_score (visual // "convergence" cue — climbs toward the end of the pipeline as the // policy score approaches 1.0) const x = Math.min(STEP_LEN * (MAX_STEPS - 1), (S.policyScore || 0) * STEP_LEN * (MAX_STEPS - 1)); _marker.position.set(x, -0.6, 0); } else { _marker.material.color.setHex(C_DIM); _marker.material.emissive.setHex(C_DIM); _marker.material.opacity = 0.3; } } } // ============================================================================= // per-frame animation // ============================================================================= function _onFrame() { const t = performance.now(); if (_group) _group.rotation.y = Math.sin(t * 0.00009) * 0.12; if (_marker) { _marker.rotation.y += 0.025; _marker.rotation.x += 0.012; const pulse = 1.0 + 0.15 * Math.sin(t * 0.004); _marker.scale.setScalar(pulse); } } // ============================================================================= // overlay // ============================================================================= function _buildOverlay() { _show = createShowcase(_ctx, { id: ID, title: TITLE, accent: "#5b8dee", badge: _badge, chips: [{ label: "MODELED", text: "reward dynamics", name: "hl" }], legend: ["MODELED", "SAMPLE"], description: 'GRPO samples a group of completions per step and normalizes each reward against ' + 'the group\'s own mean/std \u2014 no critic network needed. The policy is updated via a ' + 'PPO-clip surrogate (\u03b5=0.2) on that group-relative advantage, plus a KL penalty vs a fixed ' + 'reference policy. Honesty label MODELED (deterministic group-advantage + PPO-clip + KL ' + 'arithmetic; NOT a trained policy). 0 runtime CDN.', citations: "Shao et al. (DeepSeekMath GRPO) arXiv:2402.03300 \u00b7 DeepSeek-R1 arXiv:2501.12948. MODELED \u00b7 not claimed-as.", plain: { html: _plainHtml }, }); _el["gr-groupsize"] = _show.addField("group_size (G samples/step)"); _el["gr-steps"] = _show.addField("steps simulated"); _el["gr-klbeta"] = _show.addField("kl_beta (KL-penalty coeff.)"); _el["gr-clipeps"] = _show.addField("clip_eps (PPO-clip \u03b5)"); _el["gr-reward"] = _show.addField("mean_reward \u2014 MODELED"); _el["gr-adv"] = _show.addField("mean_advantage \u2014 MODELED"); _el["gr-kl"] = _show.addField("kl_divergence (k3) \u2014 MODELED"); _el["gr-clipfrac"] = _show.addField("clip_fraction \u2014 MODELED"); _el["gr-score"] = _show.addField("final_policy_score \u2014 MODELED"); _el["gr-label"] = _show.addField("honesty label"); _paintOverlay(); } function _plainHtml() { const g = S.groupSize != null ? String(S.groupSize) : "loading\u2026"; const reward = S.meanReward != null ? (S.meanReward * 100).toFixed(1) + "%" : "loading\u2026"; const score = S.policyScore != null ? (S.policyScore * 100).toFixed(1) + "%" : "loading\u2026"; return ( "What this means: Instead of training a second, separate \u201ccritic\u201d network to judge how " + "good an answer is (as classic PPO does), GRPO just generates " + g + " candidate answers to the " + "same question and compares them to each other \u2014 the group's own average becomes the yardstick. " + "Answers better than the group average get reinforced; worse ones get discouraged. A safety clip keeps " + "any single update from swinging too far, and a KL \u201cleash\u201d keeps the model from drifting too far " + "from where it started. Over simulated training, the average reward per group reaches about " + reward + " " + "and a convergence proxy (policy_score) climbs to about " + score + ". This view is a MODELED " + "closed-form simulation of the group-advantage/PPO-clip/KL arithmetic from the DeepSeekMath paper, not a run of " + "DeepSeek-R1 or DeepSeekMath training."); } function _tok(s) { if (s === "live") return null; if (s === "missing") return "NO-LIVE-DATA"; if (s === "degraded") return "DEGRADED"; if (s === "error") return "OFFLINE"; return "\u2026"; } function fx(v, d) { return typeof v === "number" ? v.toFixed(d) : "\u2014"; } function pct(v, d) { return typeof v === "number" ? (v * 100).toFixed(d) + "%" : "\u2014"; } function _set(id, v) { if (_el[id]) _el[id].textContent = v; } function _paintOverlay() { const t = _tok(S.state); _set("gr-groupsize", t || (S.groupSize != null ? String(S.groupSize) : "\u2014")); _set("gr-steps", t || (S.steps != null ? String(S.steps) : "\u2014")); _set("gr-klbeta", t || fx(S.klBeta, 4)); _set("gr-clipeps", t || fx(S.clipEps, 2)); _set("gr-reward", t || fx(S.meanReward, 4)); _set("gr-adv", t || fx(S.meanAdv, 4)); _set("gr-kl", t || fx(S.klDiv, 6)); _set("gr-clipfrac", t || pct(S.clipFrac, 2)); _set("gr-score", t || pct(S.policyScore, 2)); // honesty label verbatim — never upgraded _set("gr-label", t || (S.label || "MODELED")); if (_show) { _show.setChip("hl", S.label || "MODELED", { text: "reward dynamics" }); _show.refreshPlain(); } } // ============================================================================= // unmount — clean up everything; must not affect other organs // ============================================================================= export function unmount() { _polls.forEach((p) => { try { p.stop(); } catch (_) {} }); _polls = []; try { if (_show) _show.destroy(); } catch (_) {} try { if (_group && _stage) { _group.traverse((o) => { if (o.geometry && o.geometry.dispose) o.geometry.dispose(); if (o.material) { const ms = Array.isArray(o.material) ? o.material : [o.material]; ms.forEach((m) => { if (m.dispose) m.dispose(); }); } }); _stage.scene.remove(_group); } } catch (_) {} _group = _show = null; _floor = null; _plane = null; _spine = null; _sampleMesh = []; _tethers = []; _marker = null; _el = {}; _badge = null; _frameReg = false; _stage = _THREE = _ctx = null; S.label = S.groupSize = S.steps = S.klBeta = S.clipEps = null; S.meanReward = S.meanAdv = S.klDiv = S.clipFrac = S.policyScore = null; S.rewardTraj = S.klTraj = S.scoreTraj = S.advTraj = S.clipTraj = null; S.state = "init"; } export default { id: ID, title: TITLE, endpoints: [EP], mount, unmount };