fix(ui): resolve black canvas webgl issues and link darkxside school playlist - #1677
POWERFULMOVES wants to merge 12 commits into
Conversation
Adds a --paths-only mode to ghcr_local_prepublish.py that checks all in-repo matrix context/dockerfile paths exist without running Docker. Submodule paths under pmoves/integrations/ are initialized shallowly before the check. Exits non-zero with a per-entry PASS/FAIL table. Wires the check into hardening-validation.yml (required pre-merge gate) and adds .github/workflows/integrations-ghcr.matrix.json to trigger paths so the gate fires whenever the matrix is edited. Adds make ghcr-matrix-paths-check for local dev use. This gate would have caught the archon-ui-main/ staleness (PR #1635) before it reached CI. Depends on #1635 to pass on main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nk bump If a PR only bumps the Archon submodule gitlink without editing the matrix JSON, the path gate wouldn't fire. Add pmoves/integrations/archon to the hardening-validation trigger so gitlink-only bumps still run the check. Uses the specific gitlink path rather than integrations/** to avoid firing on unrelated routine submodule bumps. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reject absolute paths upfront and verify that resolved context/dockerfile paths are still under repo_root after resolution. Prevents ../- or absolute-path entries in the matrix JSON from silently passing the existence check. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…start target - find_db_container.sh: prefer pmoves-supabase-db-1 over legacy DoX supabase-db container (two-pass grep to fix docker ps ordering issue) - Makefile: add supabase-bootstrap-no-start target that applies migrations+seeds against an already-running DB, bypassing supa-start; detects POSTGRES_USER from container env, uses -h 127.0.0.1 TCP auth - Makefile: supa-start line 400 now uses --profile supabase-local when force-recreating the pooler, preventing name-conflict on supabase-pooler - Makefile: add tier-data/api/supabase-patch-missing targets (idempotent key append for compose :? required vars) and pooler-recreate target Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Summary step used bash [[ ]] syntax without `shell: bash`, causing PowerShell parse failures on the Windows 4090 self-hosted runner. The main sync step (which has shell: bash) succeeded and uploaded the artifact correctly, but the cosmetic Summary step crashed the job. Also: update Pattern B pull instructions to show both Unix + Windows paths and reference secrets-funnel-sync-from-bundle (which preserves the CI bundle instead of overwriting it from local env.shared). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…studios Three new Makefile targets for Cloudflare Pages lifecycle management: - cf-pages-create: one-time project bootstrap (production-branch=main) - cf-pages-deploy: wrangler pages deploy with CF_PAGES_BRANCH=main default - cf-pages-status: list projects to verify state CF_PAGES_BRANCH Make variable (default: main) ensures deploys always land on the production URL (cataclysmstudios.pages.dev) not a branch preview. Credentials flow through LOAD_ENV_SHARED from the CHIT-materialized tier files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Serves deploy/cataclysmstudios/ at localhost:8788 (configurable via CF_PAGES_PORT) using wrangler pages dev before committing to a prod deploy. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- website/wrangler.toml: name=pmoves-ai, compatibility_date=2026-05-28 - pmoves/Makefile: pmoves-ai-dev/create/deploy/status targets with PMOVES_AI_PROJECT/DIR/BRANCH/PORT Make variables - Deployed to https://pmoves-ai.pages.dev (production branch: main) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s.ai - website/assets/gallery/: 3 hologram MP4s (C1/C3/C5) from beats_to_cgp pipeline + CHIT hero/mindmap images from session gallery - website/hyperdim/: full Hyperdimensions Three.js viewer with all 28 saves including beats_constellation.json + chit_manifold.json PMOVES presets - website/index.html: new #gallery section with autoplay looping video cards and pipeline note; Demos section Hyperdimensions card (badge-live); Gallery nav link added - website/styles.css: .gallery-grid, .gallery-item, .gallery-pipeline-note, .badge-live styles Live at https://pmoves-ai.pages.dev Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ds to fix 1920x1080 scaling - Bypassed the stubbed Remotion 2D generator which required DGX SPARK. - Upgraded website/hyperdim/index.html with URL parameter parsing. - Generated three distinct parametric topology presets derived from beats_constellation.json. - Replaced the three static <video> elements in website/index.html gallery with <iframe> embeds. - Appended ANTIGRAVITY-GEMINI claim and ACK to AGNOTE4482.md.
📝 WalkthroughWalkthroughThis PR delivers a comprehensive interactive 3D visualization web application (Hyperdimensions), strengthens infrastructure CI/CD with GHCR path validation gates, and improves build/deployment automation. It adds 30+ parametric surface presets, integrates the viewer into the main website gallery, and updates workflow/make targets for secrets synchronization and Supabase operations. ChangesInfrastructure Hardening and CI/CD
Hyperdimensional Visualization Web App
Main Website Gallery Integration
Documentation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d34ae948ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -0,0 +1,46 @@ | |||
| { | |||
| "surfaceFn": "function surface(input) {\n const u = (input.u - 0.5) * 10;\n const v = (input.v - 0.5) * 10;\n const eps = input.epsilon || 0.0;\n \n const z = Math.sin(u)*Math.cos(v) * eps;\n \n return {\n x: u, \n y: v, \n z: z, \n r: 0.5, \n g: 0.5, \n b: 0.5, \n a: 0.8\n };\n}", | |||
There was a problem hiding this comment.
Convert chit manifold preset to the current save schema
This preset is saved with legacy keys (surfaceFn, params, animatedParams), but the new Hyperdimensions loader reads cfg.surface.code, cfg.parameters, and cfg.extraParameters before falling back to the default placeholder surface. Because the landing page advertises chit_manifold, selecting it will silently ignore the intended manifold function/epsilon animation and render the default surface instead of the CHIT manifold.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 11
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
.github/workflows/sync-secrets-local.yml (1)
360-367:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRecompute or persist
CGP_FILE,ENV_FILE, andPYbefore printing the summary.These names are shell locals from the previous step, so this step prints empty paths and an unusable decode command. The sync can succeed while the operator instructions are still wrong.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sync-secrets-local.yml around lines 360 - 367, The summary echo prints empty CGP_FILE, ENV_FILE, and PY because those shell locals are out of scope in this step; update the workflow step to recompute or import/persist these variables before the echoes (e.g., re-source the script that sets them or read them from prior step outputs/exports into the environment) so that CGP_FILE, ENV_FILE and PY contain the correct values when printing the summary and when showing the PMOVES_CGP_FILE decode command.website/index.html (1)
317-328:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winThe two school cards now route to the same playlist.
Lines 317 and 328 point to the identical YouTube playlist even though the cards describe different schools. Unless both brands intentionally share one playlist, the Cloudflare CTA now sends users to the wrong curriculum.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/index.html` around lines 317 - 328, The two article elements with class "card card-school" both use the same YouTube playlist href; update the href on the incorrect anchor so each school card points to its intended playlist. Locate the <article class="card card-school"> that contains the heading text for the other school (e.g., "CLOUDFLARE'S School of ...") and change its <a class="btn btn-ghost" href="..."> href to the correct YouTube playlist URL for that school, keeping rel="noopener noreferrer" and target="_blank" unchanged; then verify the two anchors now point to two distinct playlist URLs.
🟡 Minor comments (10)
pmoves/docs/AGENTS/AGNOTE4482.md-1181-1186 (1)
1181-1186:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUnrelated handoff item in Lane Status.
The "Custom Domain Linking" row (line 1185) mentions manual Cloudflare domain configuration, which is not described in the Context, Work Performed, or PR objectives. If this is unrelated to the A2UI hologram scaling fix work, it should be removed from this audit entry or explained in the Work Performed section.
Also: Fix table formatting
Static analysis flags missing blank lines around the table (MD058):
### Lane Status + | Lane | Status | Notes | |------|--------|-------| | A2UI Hologram Scaling | Resolved (Live WebGL) | DGX SPARK dependency bypassed. Rendering now happens live in the browser via Three.js. | | Custom Domain Linking | Handoff | Operator to configure `pmoves.ai` domain in Cloudflare dashboard manually. | + ### PR Readiness🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pmoves/docs/AGENTS/AGNOTE4482.md` around lines 1181 - 1186, The "Lane Status" table contains an unrelated "Custom Domain Linking" row referencing manual Cloudflare configuration—either remove that row from the Lane Status table or add a short explanation in the Work Performed / Context sections clarifying why domain work is part of this audit (refer to the "Lane Status" table and the "Work Performed" section headings to locate the content); also fix MD058 by ensuring there is a blank line before and after the markdown table so the linter stops flagging formatting errors.pmoves/mk/codex.mk-105-108 (1)
105-108:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid hardcoding
4090in the recovery command.The workflow publishes
chit-bundle-${target}-${run_id}, and the current default target isspark, so this hint points operators at the wrong artifact name in the common case. Make the example generic or parameterize it with the actual target.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pmoves/mk/codex.mk` around lines 105 - 108, The example recovery command hardcodes "4090" which misnames the published artifact; update the hint to use the actual target variable or a generic placeholder so operators pick the right artifact name. Replace the literal "chit-bundle-4090-<RUN_ID>" with the workflow's artifact name pattern (e.g., "chit-bundle-${target}-${RUN_ID}" or use Makefile's target variable such as "$(target)"/ "$(TARGET)"/ a clear "<TARGET>" placeholder) and ensure the dirname call still references "$(CHIT_EXPORT_PATH)"; update the echo line near the CHIT_EXPORT_PATH check to reflect this parameterized artifact name..github/workflows/sync-secrets-local.yml-375-380 (1)
375-380:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse a real Windows command variant for the 4090 pull instructions.
The text explicitly targets a Windows-native node, but
"$APPDATA/pmoves/chit"is Bash syntax. In PowerShell the copy-paste form is$env:APPDATA\pmoves\chit, otherwise the documented recovery path is misleading.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sync-secrets-local.yml around lines 375 - 380, The Windows example uses Bash-style "$APPDATA/pmoves/chit" which is incorrect for PowerShell; update the Windows (4090) echo block (the lines that print the gh run download command and the subsequent materialize instruction) to show a proper PowerShell path variant using $env:APPDATA with backslashes (e.g. $env:APPDATA\pmoves\chit) and appropriate quoting/escaping so Windows users can copy-paste the command; keep the existing gh run download invocation and the make -C pmoves secrets-funnel-sync-from-bundle instruction but replace the path token to the PowerShell form in that echo.website/hyperdim/saves/breather_surface.json-31-66 (1)
31-66:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winExpose the animation parameter this surface actually reads.
The surface uses
input.time, but this save only definesscale,colorPhase,hueRange, andsaturation. The viewer does not inject an implicit clock field, sophasestays at0and this preset loads as static instead of animated.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/hyperdim/saves/breather_surface.json` around lines 31 - 66, The surface function reads input.time (used to compute phase) but the save's extraParameters array doesn't expose a "time" (or "phase") runtime parameter, so the preset loads static; add a new extraParameters entry (e.g., name: "time", min: 0, max: 60, step: 0.01, runtime: 60) to the extraParameters array so the viewer will drive input.time at runtime and enable the animation referenced by the phase variable inside function surface.website/hyperdim/saves/cosmic_bloom.json-90-90 (1)
90-90:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winNormalize hue before the HSL-to-RGB branch.
thetacan go negative once the animated twist term outweighsu, sohue1/huealso go negative because JS%preserves sign. That feeds a negativehPrimeinto the conversion code and returns negative RGB channels, which the renderer clamps to black. Use a positive modulo form like((value % 1) + 1) % 1before converting.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/hyperdim/saves/cosmic_bloom.json` at line 90, The hue calculation can be negative because theta includes a twist, so in function surface normalize hue1/hue to [0,1] before converting to RGB: replace the current hue1/hue expressions (which use % 1) with a positive-modulo normalization ((value % 1) + 1) % 1 for hue1, hue2 and the combined hue so hPrime = h/60 is always non-negative and the HSL-to-RGB branch never receives negative hPrime; update references to hue1, hue2, and hue accordingly.website/hyperdim/saves/dini_surface.json-49-49 (1)
49-49:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winKeep the Dini color channels in the valid
[0, 1]range.
r_colandg_colcan drop to-0.4here, so large regions will be clipped instead of shaded as intended. Re-center the sine wave into[0, 1]or clamp the channels before returning them.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/hyperdim/saves/dini_surface.json` at line 49, The color channels r_col and g_col in function surface can drop below 0 (e.g., -0.4); update their calculation to keep values in [0,1] by re-centering the sine output (e.g., use 0.5 + 0.5 * Math.sin(...)) for r_col and g_col, and optionally add a clamp using Math.max(0, Math.min(1, ...)) before returning to guarantee valid channel ranges; reference the surface function and the r_col/g_col variables when applying the change.website/hyperdim/saves/hypersphere.json-24-29 (1)
24-29:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
uMaxdoes not match the hypersphere parametrization.The code treats
phi1 = input.uand even documents it as[0, PI], but the preset letsurun to2π. That double-covers the surface and introduces overlapping geometry instead of a single sweep. Either capuMaxat3.14159or change the parametrization so the first angle is truly periodic.Also applies to: 58-58
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/hyperdim/saves/hypersphere.json` around lines 24 - 29, The preset's uMax currently equals 6.28318 which double-covers the hypersphere because the code treats phi1 = input.u as [0, PI]; change uMax to 3.14159 (PI) in the JSON entries where uMax appears (also update the second occurrence mentioned) so that phi1=input.u runs 0..PI and the surface isn't overlapped; keep vMax as 3.14159 and leave uSegs/vSegs as-is unless you want different resolution.website/hyperdim/saves/torus.json-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winWrap the torus hue before RGB sector selection.
w4rcan pushhueabove360, sohp = hue / 60exceeds6and the finalelsebranch colors that slice as if it were always sector 5. Normalize the hue into[0, 360)(orhpinto[0, 6)) before the branch.🎨 Suggested fix
- const hue = (w4r + 0.5) * 360; + const hue = (((w4r + 0.5) * 360) % 360 + 360) % 360; const s = 0.8; const l = 0.5 + 0.2 * Math.sin(u + v);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/hyperdim/saves/torus.json` at line 42, The hue computed from w4r can exceed 360 causing hp to be >=6 and hit the wrong RGB branch; inside function surface normalize the hue (or hp) into the proper range before the sector selection—e.g., reduce hue into [0,360) (or compute hp = ((hue/60) % 6 + 6) % 6) so the subsequent if/else ladder using hp selects the correct RGB sector; update the code around variables hue and hp in function surface to perform this wrap.website/hyperdim/saves/trefoil_knot.json-88-88 (1)
88-88:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winNormalize
hueinto[0, 1)before computinghp(JS%keeps negatives)
hueRaw = u / 6.283 + hueOffset + irid * Math.sin(v * 2 + u * 3)can be negative with valid parameter ranges (uMin=0,hueOffset∈[0,1],iridescence∈[0,2],sin∈[-1,1]→hueRawdown to about-2). In JS,(hueRaw % 1)becomes negative, makinghpnegative and selecting the wrong HSL sector.🎨 Suggested fix
- const hue = (u / 6.283 + hueOffset + irid * Math.sin(v * 2 + u * 3)) % 1.0; + const hueRaw = u / 6.283 + hueOffset + irid * Math.sin(v * 2 + u * 3); + const hue = ((hueRaw % 1) + 1) % 1;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/hyperdim/saves/trefoil_knot.json` at line 88, The hue calculation can be negative because JS % preserves sign; inside function surface compute hueRaw = u / 6.283 + hueOffset + irid * Math.sin(v * 2 + u * 3) then normalize it into [0,1) before deriving hp (e.g., hue = hueRaw - Math.floor(hueRaw) or use ((hueRaw % 1) + 1) % 1) so hp = hue * 6 is always non-negative; update the hue usage where hp is computed and ensure subsequent HSL-to-RGB logic uses this normalized hue.pmoves/Makefile-1890-1894 (1)
1890-1894:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse the configured branch variables during Pages project creation.
These targets define
CF_PAGES_BRANCHandPMOVES_AI_BRANCH, but thepages project createcommands still hardcodemain. If an operator overrides the branch variables, project creation and deploy will disagree about the production branch.Suggested fix
- npx wrangler pages project create "$(CF_PAGES_PROJECT)" \ - --production-branch main 2>&1; \ + npx wrangler pages project create "$(CF_PAGES_PROJECT)" \ + --production-branch "$(CF_PAGES_BRANCH)" 2>&1; \ ... - npx wrangler pages project create "$(PMOVES_AI_PROJECT)" \ - --production-branch main 2>&1; \ + npx wrangler pages project create "$(PMOVES_AI_PROJECT)" \ + --production-branch "$(PMOVES_AI_BRANCH)" 2>&1; \Also applies to: 1942-1946
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pmoves/Makefile` around lines 1890 - 1894, The Makefile invokes `npx wrangler pages project create "$(CF_PAGES_PROJECT)" --production-branch main` which hardcodes "main" instead of using the configured variables `CF_PAGES_BRANCH` (or `PMOVES_AI_BRANCH` where applicable), causing mismatch when branches are overridden; update the `wrangler pages project create` invocations to use `$(CF_PAGES_BRANCH)` (or `$(PMOVES_AI_BRANCH)` in the ai-specific targets) for the `--production-branch` flag so project creation and deploy use the configured branch variables consistently.
🧹 Nitpick comments (2)
website/hyperdim/saves/mlp.json (1)
39-39: ⚡ Quick winCache the generated network instead of rebuilding it per vertex.
seed,hidden_layers,neurons, andactivationdo not vary across a mesh rebuild, but this function regenerates the same weights for every(u, v)sample. That makes this preset scale with vertex count and becomes the dominant cost once users raise the layer/neuron sliders.Suggested direction
// Build once per parameter set, then reuse inside surface() const key = `${nHidden}:${nNeurons}:${actType}:${Math.floor(input.seed)}`; surface._cache ||= {}; let network = surface._cache[key]; if (!network) { network = buildNetwork(...); surface._cache = { [key]: network }; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/hyperdim/saves/mlp.json` at line 39, The surface function rebuilds the entire MLP per vertex; cache the generated network weights keyed by seed, hidden_layers, neurons and activation so you only build once per parameter set: create a key from nHidden, nNeurons, actType and Math.floor(input.seed), store built weights on surface._cache[key], and if absent run a one-time build step (extract the weight/ bias generation logic currently inside the per-vertex loop into a buildNetwork phase) then reuse the cached network to compute outputs for each (u,v); ensure surface clears or updates the cache when any of those parameters change.website/styles.css (1)
402-408: ⚡ Quick winStyle the iframe previews here too.
The gallery now renders
iframes, but this selector still only targetsvideo, so the preview sizing/background rules are duplicated inline inwebsite/index.html. Moving the iframe presentation into this stylesheet will keep the gallery layout from drifting again.♻️ Proposed cleanup
-.gallery-item video { +.gallery-item iframe, +.gallery-item video { width: 100%; aspect-ratio: 16 / 9; - object-fit: cover; display: block; background: `#000`; + border: 0; } + +.gallery-item video { + object-fit: cover; +}Based on learnings: "Replace static gallery video elements with Hyperdimensions viewer
iframeembeds (to avoid the 1920x1080 scaling issue)."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@website/styles.css` around lines 402 - 408, The CSS currently styles .gallery-item video but not the new iframe previews, causing duplicated inline styles in website/index.html; update the stylesheet by adding a matching rule for .gallery-item iframe (or combine into a single selector like .gallery-item video, .gallery-item iframe) with the same properties (width:100%; aspect-ratio:16/9; object-fit:cover; display:block; background:`#000`) and then remove the duplicated inline presentation styles from the iframe embeds in website/index.html so presentation is centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/hardening-validation.yml:
- Around line 10-11: The paths filter for the workflow currently lists the
non-recursive path 'pmoves/integrations/archon' which won't match changes in
nested files; update both occurrences of that path in the workflow's on:
push/pull_request: paths array to a recursive glob like
'pmoves/integrations/archon/**' so subdirectory changes trigger the GHCR matrix
validation (leave the existing '.github/workflows/integrations-ghcr.matrix.json'
entry and the prepublish step 'python3 pmoves/tools/ghcr_local_prepublish.py
--paths-only' unchanged).
In `@pmoves/docs/AGENTS/AGNOTE4482.md`:
- Around line 1167-1180: Update the AGNOTE4482 audit entry to reconcile the
mismatch between the "identical pink dot" context and the PR summary by
explicitly documenting both UI fixes: include the "black canvas fix" details
(ensure the default nautilus fallback evaluates the surface function and force
the Three.js renderer to recalculate geometry when the sidebar collapses in
ui=none mode) and note the playlist link change (replace the TODO with the
requested YouTube playlist link for DARKXSIDE'S School); adjust the Context and
Work Performed sections so they mention both the gallery iframe replacement and
these two core technical fixes so the audit trail accurately reflects all
changes in this PR.
- Around line 1165-1196: Update the shared AGNOTE4482_SIGNOFF_CHECKLIST to
record section-level ACKs for this PR: add entries naming the validated sections
(e.g., "A2UI Hologram Scaling", "Custom Domain Linking"), include the agent
identifier ANTIGRAVITY-GEMINI and the signature
ACK::ANTIGRAVITY-GEMINI::A2UI-HOLOGRAM-SCALING-FIX with the timestamp
2026-05-30, and mark which specific checklist items this agent
reviewed/validated (only the items actually executed), so the checklist reflects
multi-agent merge readiness rather than a single-agent vibe check.
In `@pmoves/Makefile`:
- Around line 665-668: The current shell chain conflates SQL execution failure
and history-insert failure (using _psql < "$$migration" && _psql -c "INSERT INTO
public.pmoves_bootstrap_history(...)" || echo ...) so an insert failure will be
treated as a non-fatal warning; change the flow so you first run _psql <
"$$migration" and if that fails print the warning and continue, but if it
succeeds then run the INSERT into pmoves_bootstrap_history and if that INSERT
fails exit non-zero (stop the target). Update the block around the _psql
invocation and the INSERT (and the analogous block at lines 680-683) to use an
if/then/else or separate conditional commands that only continue on a failed SQL
apply, and abort when the history INSERT (pmoves_bootstrap_history,
filename/migration variables, _psql -c) fails.
- Around line 426-430: The pooler-recreate Makefile target currently always
recreates supabase-pooler; guard it the same way as supa-start by checking
SUPABASE_RUNTIME (or invoking the same guard target used by supa-start) and fail
fast unless SUPABASE_RUNTIME is "compose"; specifically update the
pooler-recreate target to verify SUPABASE_RUNTIME (or call the existing guard
target/function) before running @$(DC) --profile supabase-local up -d
--force-recreate supabase-pooler and print a clear error and non-zero exit when
the runtime is not compose.
In `@pmoves/tools/ghcr_local_prepublish.py`:
- Around line 231-239: Currently the code only checks existence of context_path
and dockerfile_path; change the checks to enforce types: verify
context_path.is_dir() (fail with a ValidationResult and a message like "context
not a directory: {context_rel}") and verify dockerfile_path.is_file() (fail with
a ValidationResult and a message like "dockerfile not a file:
{dockerfile_rel}"), keeping the same return shape (ValidationResult(name=name,
tag=tag, build_ok=False, trivy_ok=None, note=...)) and the same [FAIL]/[PASS]
prints; maintain the final success return (ValidationResult(..., build_ok=True,
note="paths-only")) when both checks pass.
In `@website/hyperdim/index.html`:
- Around line 35-39: The clickable header divs (e.g., elements with IDs
learnMoreHeader, learnMoreCaret and their paired section bodies like
learnMoreBody) must be converted into semantic, keyboard-operable controls:
replace the clickable div with a <button> (or make it role="button" tabbable)
and add aria-expanded and aria-controls attributes pointing to the associated
section body ID so keyboard users can toggle the panel; update the caret state
when toggling and ensure any click handler on the old div is wired to the new
button's click so the same toggle logic runs (apply the same change pattern to
the other headers referenced in the comment).
In `@website/hyperdim/saves/chit_manifold.json`:
- Around line 1-45: The preset uses the old keys surfaceFn, params,
surfaceInput, and animatedParams which the viewer no longer reads; migrate it to
the new save schema by moving the surface function string into surface.code,
convert params into parameters (preserving uMin/uMax/vMin/vMax/uSegs/vSegs),
move surfaceInput values into extraParameters (including
epsilon/curvature/current u/v), and translate animatedParams into display or
extraParameters.animation format expected by the viewer; ensure display includes
camera, shininess, globalSaturation and meta stays intact so the viewer can
restore the scene when _list.json advertises chit_manifold.json.
In `@website/hyperdim/saves/mandelbulb.json`:
- Line 90: getDist can return negative distances which cause the ray step logic
in the main marching loop to push the sample outward; after calling getDist(px,
py, pz) in the ray march loop (where variable d is assigned) clamp d to a
non-negative value (e.g., d = Math.max(d, 0.0)) before performing the hit test
(if (d < epsilon)) and before adjusting r (the r -= d*0.5 and r -= d lines) so
negative DEs won't drive the ray outward; update the code around the main
for-loop that calls getDist to apply this clamp to d.
In `@website/hyperdim/styles.css`:
- Around line 29-43: The collapsed-state CSS doesn't hide the preset/load UI
under .header-panel/.header-panel-row, so update the collapsed selectors
(`#sidebar-wrapper.collapsed` ...) to also target .header-panel and
.header-panel-row (and/or specific header panel descendants that render inputs)
and set display: none so the "button only" state truly removes header controls;
apply this change alongside the existing rules that hide `#controlsBody`,
.control-row, .sidebar-header h2, and `#sidebar-footer` so embeds using
ui=none/preset=... don't leave inputs visible.
In `@website/index.html`:
- Around line 250-280: Add a restrictive sandbox attribute to the gallery
iframes (the <iframe> elements loading src="/hyperdim/...") to prevent those
same-origin viewer pages from reaching the parent origin or storage; if the live
viewer needs to run JS, grant only allow-scripts (do NOT add allow-same-origin
or allow-top-navigation), otherwise use a fully sandboxed iframe with no
allowances or replace with a static preview and communicate via postMessage if
needed.
---
Outside diff comments:
In @.github/workflows/sync-secrets-local.yml:
- Around line 360-367: The summary echo prints empty CGP_FILE, ENV_FILE, and PY
because those shell locals are out of scope in this step; update the workflow
step to recompute or import/persist these variables before the echoes (e.g.,
re-source the script that sets them or read them from prior step outputs/exports
into the environment) so that CGP_FILE, ENV_FILE and PY contain the correct
values when printing the summary and when showing the PMOVES_CGP_FILE decode
command.
In `@website/index.html`:
- Around line 317-328: The two article elements with class "card card-school"
both use the same YouTube playlist href; update the href on the incorrect anchor
so each school card points to its intended playlist. Locate the <article
class="card card-school"> that contains the heading text for the other school
(e.g., "CLOUDFLARE'S School of ...") and change its <a class="btn btn-ghost"
href="..."> href to the correct YouTube playlist URL for that school, keeping
rel="noopener noreferrer" and target="_blank" unchanged; then verify the two
anchors now point to two distinct playlist URLs.
---
Minor comments:
In @.github/workflows/sync-secrets-local.yml:
- Around line 375-380: The Windows example uses Bash-style
"$APPDATA/pmoves/chit" which is incorrect for PowerShell; update the Windows
(4090) echo block (the lines that print the gh run download command and the
subsequent materialize instruction) to show a proper PowerShell path variant
using $env:APPDATA with backslashes (e.g. $env:APPDATA\pmoves\chit) and
appropriate quoting/escaping so Windows users can copy-paste the command; keep
the existing gh run download invocation and the make -C pmoves
secrets-funnel-sync-from-bundle instruction but replace the path token to the
PowerShell form in that echo.
In `@pmoves/docs/AGENTS/AGNOTE4482.md`:
- Around line 1181-1186: The "Lane Status" table contains an unrelated "Custom
Domain Linking" row referencing manual Cloudflare configuration—either remove
that row from the Lane Status table or add a short explanation in the Work
Performed / Context sections clarifying why domain work is part of this audit
(refer to the "Lane Status" table and the "Work Performed" section headings to
locate the content); also fix MD058 by ensuring there is a blank line before and
after the markdown table so the linter stops flagging formatting errors.
In `@pmoves/Makefile`:
- Around line 1890-1894: The Makefile invokes `npx wrangler pages project create
"$(CF_PAGES_PROJECT)" --production-branch main` which hardcodes "main" instead
of using the configured variables `CF_PAGES_BRANCH` (or `PMOVES_AI_BRANCH` where
applicable), causing mismatch when branches are overridden; update the `wrangler
pages project create` invocations to use `$(CF_PAGES_BRANCH)` (or
`$(PMOVES_AI_BRANCH)` in the ai-specific targets) for the `--production-branch`
flag so project creation and deploy use the configured branch variables
consistently.
In `@pmoves/mk/codex.mk`:
- Around line 105-108: The example recovery command hardcodes "4090" which
misnames the published artifact; update the hint to use the actual target
variable or a generic placeholder so operators pick the right artifact name.
Replace the literal "chit-bundle-4090-<RUN_ID>" with the workflow's artifact
name pattern (e.g., "chit-bundle-${target}-${RUN_ID}" or use Makefile's target
variable such as "$(target)"/ "$(TARGET)"/ a clear "<TARGET>" placeholder) and
ensure the dirname call still references "$(CHIT_EXPORT_PATH)"; update the echo
line near the CHIT_EXPORT_PATH check to reflect this parameterized artifact
name.
In `@website/hyperdim/saves/breather_surface.json`:
- Around line 31-66: The surface function reads input.time (used to compute
phase) but the save's extraParameters array doesn't expose a "time" (or "phase")
runtime parameter, so the preset loads static; add a new extraParameters entry
(e.g., name: "time", min: 0, max: 60, step: 0.01, runtime: 60) to the
extraParameters array so the viewer will drive input.time at runtime and enable
the animation referenced by the phase variable inside function surface.
In `@website/hyperdim/saves/cosmic_bloom.json`:
- Line 90: The hue calculation can be negative because theta includes a twist,
so in function surface normalize hue1/hue to [0,1] before converting to RGB:
replace the current hue1/hue expressions (which use % 1) with a positive-modulo
normalization ((value % 1) + 1) % 1 for hue1, hue2 and the combined hue so
hPrime = h/60 is always non-negative and the HSL-to-RGB branch never receives
negative hPrime; update references to hue1, hue2, and hue accordingly.
In `@website/hyperdim/saves/dini_surface.json`:
- Line 49: The color channels r_col and g_col in function surface can drop below
0 (e.g., -0.4); update their calculation to keep values in [0,1] by re-centering
the sine output (e.g., use 0.5 + 0.5 * Math.sin(...)) for r_col and g_col, and
optionally add a clamp using Math.max(0, Math.min(1, ...)) before returning to
guarantee valid channel ranges; reference the surface function and the
r_col/g_col variables when applying the change.
In `@website/hyperdim/saves/hypersphere.json`:
- Around line 24-29: The preset's uMax currently equals 6.28318 which
double-covers the hypersphere because the code treats phi1 = input.u as [0, PI];
change uMax to 3.14159 (PI) in the JSON entries where uMax appears (also update
the second occurrence mentioned) so that phi1=input.u runs 0..PI and the surface
isn't overlapped; keep vMax as 3.14159 and leave uSegs/vSegs as-is unless you
want different resolution.
In `@website/hyperdim/saves/torus.json`:
- Line 42: The hue computed from w4r can exceed 360 causing hp to be >=6 and hit
the wrong RGB branch; inside function surface normalize the hue (or hp) into the
proper range before the sector selection—e.g., reduce hue into [0,360) (or
compute hp = ((hue/60) % 6 + 6) % 6) so the subsequent if/else ladder using hp
selects the correct RGB sector; update the code around variables hue and hp in
function surface to perform this wrap.
In `@website/hyperdim/saves/trefoil_knot.json`:
- Line 88: The hue calculation can be negative because JS % preserves sign;
inside function surface compute hueRaw = u / 6.283 + hueOffset + irid *
Math.sin(v * 2 + u * 3) then normalize it into [0,1) before deriving hp (e.g.,
hue = hueRaw - Math.floor(hueRaw) or use ((hueRaw % 1) + 1) % 1) so hp = hue * 6
is always non-negative; update the hue usage where hp is computed and ensure
subsequent HSL-to-RGB logic uses this normalized hue.
---
Nitpick comments:
In `@website/hyperdim/saves/mlp.json`:
- Line 39: The surface function rebuilds the entire MLP per vertex; cache the
generated network weights keyed by seed, hidden_layers, neurons and activation
so you only build once per parameter set: create a key from nHidden, nNeurons,
actType and Math.floor(input.seed), store built weights on surface._cache[key],
and if absent run a one-time build step (extract the weight/ bias generation
logic currently inside the per-vertex loop into a buildNetwork phase) then reuse
the cached network to compute outputs for each (u,v); ensure surface clears or
updates the cache when any of those parameters change.
In `@website/styles.css`:
- Around line 402-408: The CSS currently styles .gallery-item video but not the
new iframe previews, causing duplicated inline styles in website/index.html;
update the stylesheet by adding a matching rule for .gallery-item iframe (or
combine into a single selector like .gallery-item video, .gallery-item iframe)
with the same properties (width:100%; aspect-ratio:16/9; object-fit:cover;
display:block; background:`#000`) and then remove the duplicated inline
presentation styles from the iframe embeds in website/index.html so presentation
is centralized.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ae42a471-e152-41e6-a4d6-bc01d93dd50e
⛔ Files ignored due to path filters (4)
website/assets/gallery/chit_hero_and_mindmap.pngis excluded by!**/*.pngwebsite/assets/gallery/group_c1_hologram.mp4is excluded by!**/*.mp4website/assets/gallery/group_c3_hologram.mp4is excluded by!**/*.mp4website/assets/gallery/group_c5_hologram.mp4is excluded by!**/*.mp4
📒 Files selected for processing (44)
.github/workflows/hardening-validation.yml.github/workflows/sync-secrets-local.ymlpmoves/Makefilepmoves/docs/AGENTS/AGNOTE4482.mdpmoves/mk/codex.mkpmoves/scripts/supabase/find_db_container.shpmoves/tools/ghcr_local_prepublish.pywebsite/assets/gallery/chit_mindmap.webpwebsite/hyperdim/index.htmlwebsite/hyperdim/saves/_list.jsonwebsite/hyperdim/saves/beats_c1.jsonwebsite/hyperdim/saves/beats_c3.jsonwebsite/hyperdim/saves/beats_c5.jsonwebsite/hyperdim/saves/beats_constellation.jsonwebsite/hyperdim/saves/breather_surface.jsonwebsite/hyperdim/saves/chit_manifold.jsonwebsite/hyperdim/saves/cosmic_bloom.jsonwebsite/hyperdim/saves/dini_surface.jsonwebsite/hyperdim/saves/donut.jsonwebsite/hyperdim/saves/fourier.jsonwebsite/hyperdim/saves/hopf_fibration.jsonwebsite/hyperdim/saves/hotdog.jsonwebsite/hyperdim/saves/hypersphere.jsonwebsite/hyperdim/saves/jellyfish.jsonwebsite/hyperdim/saves/klein_bottle.jsonwebsite/hyperdim/saves/mandelbulb.jsonwebsite/hyperdim/saves/mlp.jsonwebsite/hyperdim/saves/mobius_strip.jsonwebsite/hyperdim/saves/nautilus.jsonwebsite/hyperdim/saves/ocean_planet.jsonwebsite/hyperdim/saves/perceptron.jsonwebsite/hyperdim/saves/planet.jsonwebsite/hyperdim/saves/rose.jsonwebsite/hyperdim/saves/shells.jsonwebsite/hyperdim/saves/sphere_tutorial.jsonwebsite/hyperdim/saves/taylor.jsonwebsite/hyperdim/saves/torus.jsonwebsite/hyperdim/saves/torus_knot.jsonwebsite/hyperdim/saves/trefoil_knot.jsonwebsite/hyperdim/saves/weierstrass.jsonwebsite/hyperdim/styles.csswebsite/index.htmlwebsite/styles.csswebsite/wrangler.toml
| - '.github/workflows/integrations-ghcr.matrix.json' | ||
| - 'pmoves/integrations/archon' |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/hardening-validation.yml"
echo "=== File existence / size ==="
ls -l "$FILE" || true
echo
echo "=== Lines 1-80 ==="
nl -ba "$FILE" | sed -n '1,120p'
echo
echo "=== Search for specific path entries ==="
rg -n "integrations-ghcr\.matrix\.json|pmoves/integrations/archon" "$FILE" || true
echo
echo "=== Search for ghcr_local_prepublish step ==="
rg -n "ghcr_local_prepublish\.py|--paths-only" "$FILE" || true
echo
echo "=== Lines around ghcr_local_prepublish invocation (if found) ==="
# If we found a match, print a window around the first match line
LINE=$(rg -n "ghcr_local_prepublish\.py" "$FILE" | head -n1 | cut -d: -f1 || true)
if [[ -n "${LINE:-}" ]]; then
START=$((LINE-40))
END=$((LINE+60))
nl -ba "$FILE" | sed -n "${START},${END}p"
else
echo "No ghcr_local_prepublish.py invocation found."
fi
echo "=== Search for StepSecurity presence ==="
rg -n "StepSecurity|stepsecurity|security" "$FILE" || trueRepository: POWERFULMOVES/PMOVES.AI
Length of output: 272
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/hardening-validation.yml"
echo "=== File existence / size ==="
ls -l "$FILE" || true
echo
echo "=== Lines 1-140 ==="
nl -ba "$FILE" | sed -n '1,160p'
echo
echo "=== Search for specific path entries ==="
rg -n "integrations-ghcr\.matrix\.json|pmoves/integrations/archon" "$FILE" || true
echo
echo "=== Search for ghcr_local_prepublish step ==="
rg -n "ghcr_local_prepublish\.py|--paths-only" "$FILE" || true
echo
echo "=== Lines around ghcr_local_prepublish invocation ==="
LINE=$(rg -n "ghcr_local_prepublish\.py" "$FILE" | head -n1 | cut -d: -f1 || true)
if [[ -n "${LINE:-}" ]]; then
START=$((LINE-60))
END=$((LINE+80))
nl -ba "$FILE" | sed -n "${START},${END}p"
fi
echo "=== Search for StepSecurity presence ==="
rg -n "StepSecurity|stepsecurity|step-security|Step Security" "$FILE" || trueRepository: POWERFULMOVES/PMOVES.AI
Length of output: 273
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/hardening-validation.yml"
echo "=== Lines 1-140 (with line numbers via awk) ==="
awk '{printf "%d\t%s\n", NR, $0}' "$FILE" | sed -n '1,140p'
echo
echo "=== Search for specific path entries ==="
rg -n "integrations-ghcr\.matrix\.json|pmoves/integrations/archon" "$FILE" || true
echo
echo "=== Search for ghcr_local_prepublish step ==="
rg -n "ghcr_local_prepublish\.py|--paths-only" "$FILE" || true
echo
echo "=== Show StepSecurity/secret-hardening markers ==="
rg -n "StepSecurity|stepsecurity|step-security|secrets|token|registry" "$FILE" || true
echo
echo "=== Show context around first match for ghcr_local_prepublish.py ==="
MATCH_LINE=$(rg -n "ghcr_local_prepublish\.py" "$FILE" | head -n1 | cut -d: -f1 || true)
if [[ -n "${MATCH_LINE:-}" ]]; then
START=$((MATCH_LINE-60))
END=$((MATCH_LINE+60))
awk '{printf "%d\t%s\n", NR, $0}' "$FILE" | sed -n "${START},${END}p"
fiRepository: POWERFULMOVES/PMOVES.AI
Length of output: 12580
🌐 Web query:
GitHub Actions workflow trigger paths filter match directory without wildcard paths: - some/dirvssome/dir/**``
💡 Result:
In GitHub Actions, the behavior of path filters depends on the glob pattern provided, as the system follows standard glob matching rules [1][2]. Using paths: - some/dir When you specify a directory path without a wildcard, GitHub Actions interprets this as a pattern that matches the directory itself and any files located exactly within that directory [2]. However, it does not automatically include files in nested subdirectories [2]. For example, some/dir will trigger on some/dir/file.txt but will not trigger on some/dir/subdir/file.txt. Using paths: - some/dir/ The `` wildcard is the recursive glob operator [13]. By appending /, you explicitly instruct the filter to match all files within the specified directory and all of its nested subdirectories, regardless of depth [2]. This is the standard way to ensure that any change within a directory tree triggers the workflow. Summary of Differences: - `some/dir`: Matches files directly inside `some/dir` only. - `some/dir/`: Matches files inside `some/dir` and all files in any subdirectories recursively. If your goal is to trigger the workflow whenever any file changes within a directory tree, `some/dir/` is the correct and necessary syntax [2]. Both patterns are treated as glob expressions evaluated relative to the root of the repository [2].
Citations:
- 1: https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions
- 2: https://github.com/github/docs/blob/main/content/actions/reference/workflows-and-actions/workflow-syntax.md
Broaden Archon path filter so nested changes trigger the GHCR matrix validation
The workflow on: push/pull_request: paths entries add only pmoves/integrations/archon (lines 11 and 19). That non-recursive glob won’t trigger on changes in subdirectories under pmoves/integrations/archon/, so the new GHCR path gate can be skipped for the Archon changes it’s meant to validate. The added python3 pmoves/tools/ghcr_local_prepublish.py --paths-only step is otherwise wired correctly, and StepSecurity hardening remains present.
Suggested fix
- - 'pmoves/integrations/archon'
+ - 'pmoves/integrations/archon/**'
...
- - 'pmoves/integrations/archon'
+ - 'pmoves/integrations/archon/**'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - '.github/workflows/integrations-ghcr.matrix.json' | |
| - 'pmoves/integrations/archon' | |
| - '.github/workflows/integrations-ghcr.matrix.json' | |
| - 'pmoves/integrations/archon/**' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/hardening-validation.yml around lines 10 - 11, The paths
filter for the workflow currently lists the non-recursive path
'pmoves/integrations/archon' which won't match changes in nested files; update
both occurrences of that path in the workflow's on: push/pull_request: paths
array to a recursive glob like 'pmoves/integrations/archon/**' so subdirectory
changes trigger the GHCR matrix validation (leave the existing
'.github/workflows/integrations-ghcr.matrix.json' entry and the prepublish step
'python3 pmoves/tools/ghcr_local_prepublish.py --paths-only' unchanged).
| ## Antigravity CLI A2UI Hologram Scaling Fix (2026-05-30) | ||
|
|
||
| ### Context | ||
| Operator requested fixing the "identical pink dot" gallery issue stemming from the pending `A2UI Remotion hologram viewport scaling (1920x1080 viewport)` ticket. The `geometry_mesh` element in `a2ui-renderer` was stubbed out and required DGX SPARK physical access. | ||
|
|
||
| This work ran on the local workspace `3fd5d899-f774-45da-bae1-ef349bf01951` targeting branch `fix/ghcr-matrix-paths-gate` in the parent PMOVES repo. | ||
|
|
||
| ### Work Performed | ||
| - Bypassed the stubbed Remotion 2D generator and implemented a live interactive 3D WebGL solution on the landing page. | ||
| - Upgraded `website/hyperdim/index.html` with URL parameter parsing (`?preset=` and `?ui=none`) for headless preset embedding. | ||
| - Generated three distinct parametric topology presets derived from `beats_constellation.json`: | ||
| - `beats_c5.json`: Allegro Balanced Bright (High tempo, bright color) | ||
| - `beats_c3.json`: Allegro Balanced Deep (Moderate tempo, deep color) | ||
| - `beats_c1.json`: Cluster 1 (High fitness, tight curvature, very bright) | ||
| - Replaced the three static `<video>` elements in `website/index.html` gallery with `<iframe>` embeds targeting the Hyperdimensions viewer, successfully resolving the 1920x1080 scaling issue via live rendering. | ||
|
|
||
| ### Lane Status | ||
| | Lane | Status | Notes | | ||
| |------|--------|-------| | ||
| | A2UI Hologram Scaling | Resolved (Live WebGL) | DGX SPARK dependency bypassed. Rendering now happens live in the browser via Three.js. | | ||
| | Custom Domain Linking | Handoff | Operator to configure `pmoves.ai` domain in Cloudflare dashboard manually. | | ||
|
|
||
| ### PR Readiness | ||
| The branch is ready to commit the UI changes. Proposed logical commit: | ||
| `feat(website): replace A2UI mp4s with live Hyperdimensions WebGL embeds to fix 1920x1080 scaling` | ||
|
|
||
| ### Agent ACK | ||
| - Agent: `ANTIGRAVITY-GEMINI` | ||
| - Signature: `ACK::ANTIGRAVITY-GEMINI::A2UI-HOLOGRAM-SCALING-FIX` | ||
| - Timestamp: `2026-05-30` | ||
|
|
||
| <!-- GRAPHITI_MARK: ANTIGRAVITY-GEMINI::A2UI-HOLOGRAM-SCALING-FIX::2026-05-30 --> |
There was a problem hiding this comment.
Missing AGNOTE4482 signoff checklist update.
The AGNOTE4482 lane protocol requires updating the shared signoff gate (AGNOTE4482_SIGNOFF_CHECKLIST.md) with section-level ACKs. This audit entry documents completed work but doesn't reference which signoff checklist sections were validated or marked complete.
Per the protocol defined at lines 19-23: "Each participating agent signs only for the sections they actually reviewed or executed. Merge readiness is a multi-agent decision, not a single-agent vibe check."
Suggested addition
Add after line 1189:
The branch is ready to commit the UI changes. Proposed logical commit:
`feat(website): replace A2UI mp4s with live Hyperdimensions WebGL embeds to fix 1920x1080 scaling`
+### Signoff Checklist Status
+Updated `AGNOTE4482_SIGNOFF_CHECKLIST.md`:
+- ✅ §[X.X] [Description of relevant checklist section]
+- ✅ §[Y.Y] [Description of relevant checklist section]
+
### Agent ACKBased on coding guidelines: agents must update the shared signoff gate (AGNOTE4482_SIGNOFF_CHECKLIST) with section-level ACKs.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 1182-1182: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pmoves/docs/AGENTS/AGNOTE4482.md` around lines 1165 - 1196, Update the shared
AGNOTE4482_SIGNOFF_CHECKLIST to record section-level ACKs for this PR: add
entries naming the validated sections (e.g., "A2UI Hologram Scaling", "Custom
Domain Linking"), include the agent identifier ANTIGRAVITY-GEMINI and the
signature ACK::ANTIGRAVITY-GEMINI::A2UI-HOLOGRAM-SCALING-FIX with the timestamp
2026-05-30, and mark which specific checklist items this agent
reviewed/validated (only the items actually executed), so the checklist reflects
multi-agent merge readiness rather than a single-agent vibe check.
| ### Context | ||
| Operator requested fixing the "identical pink dot" gallery issue stemming from the pending `A2UI Remotion hologram viewport scaling (1920x1080 viewport)` ticket. The `geometry_mesh` element in `a2ui-renderer` was stubbed out and required DGX SPARK physical access. | ||
|
|
||
| This work ran on the local workspace `3fd5d899-f774-45da-bae1-ef349bf01951` targeting branch `fix/ghcr-matrix-paths-gate` in the parent PMOVES repo. | ||
|
|
||
| ### Work Performed | ||
| - Bypassed the stubbed Remotion 2D generator and implemented a live interactive 3D WebGL solution on the landing page. | ||
| - Upgraded `website/hyperdim/index.html` with URL parameter parsing (`?preset=` and `?ui=none`) for headless preset embedding. | ||
| - Generated three distinct parametric topology presets derived from `beats_constellation.json`: | ||
| - `beats_c5.json`: Allegro Balanced Bright (High tempo, bright color) | ||
| - `beats_c3.json`: Allegro Balanced Deep (Moderate tempo, deep color) | ||
| - `beats_c1.json`: Cluster 1 (High fitness, tight curvature, very bright) | ||
| - Replaced the three static `<video>` elements in `website/index.html` gallery with `<iframe>` embeds targeting the Hyperdimensions viewer, successfully resolving the 1920x1080 scaling issue via live rendering. | ||
|
|
There was a problem hiding this comment.
Inconsistency between audit entry and PR scope.
The Context section describes fixing an "identical pink dot" gallery issue (line 1168), but the PR title and summary state this PR "resolves black WebGL canvas issues in the default and embed viewers." The Work Performed section lists gallery iframe replacements but omits the core technical fixes mentioned in the PR summary:
- Black canvas fix: "ensuring the default nautilus fallback evaluates the surface function and forcing the Three.js renderer to recalculate geometry when the sidebar collapses in ui=none mode"
- Playlist link update: PR summary mentions "replaces a TODO with the requested YouTube playlist link for DARKXSIDE'S School"
The audit trail should accurately reflect all work performed in this PR. Either reconcile the "pink dot" vs "black canvas" discrepancy or document both issues if they're related.
Suggested additions to Work Performed
Add after line 1173:
### Work Performed
+- Fixed black WebGL canvas rendering issues in Hyperdimensions viewer:
+ - Ensured default nautilus preset evaluates the surface function properly
+ - Added geometry recalculation trigger when sidebar collapses in `ui=none` embed mode
- Bypassed the stubbed Remotion 2D generator and implemented a live interactive 3D WebGL solution on the landing page.Add after line 1179:
- `beats_c1.json`: Cluster 1 (High fitness, tight curvature, very bright)
- Replaced the three static `<video>` elements in `website/index.html` gallery with `<iframe>` embeds targeting the Hyperdimensions viewer, successfully resolving the 1920x1080 scaling issue via live rendering.
+- Updated Cloudflare School playlist button URL to link DARKXSIDE'S School playlist.Based on coding guidelines: AGNOTE4482 protocol requires documenting UI fixes as trail entries. As per coding guidelines, the documented fix direction includes recording additional UI fixes applied.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pmoves/docs/AGENTS/AGNOTE4482.md` around lines 1167 - 1180, Update the
AGNOTE4482 audit entry to reconcile the mismatch between the "identical pink
dot" context and the PR summary by explicitly documenting both UI fixes: include
the "black canvas fix" details (ensure the default nautilus fallback evaluates
the surface function and force the Three.js renderer to recalculate geometry
when the sidebar collapses in ui=none mode) and note the playlist link change
(replace the TODO with the requested YouTube playlist link for DARKXSIDE'S
School); adjust the Context and Work Performed sections so they mention both the
gallery iframe replacement and these two core technical fixes so the audit trail
accurately reflects all changes in this PR.
| .PHONY: pooler-recreate | ||
| pooler-recreate: ## Force-recreate supabase-pooler container to pick up env file changes (non-disruptive) | ||
| @echo "→ Force-recreating supabase-pooler with current env..." | ||
| @$(DC) --profile supabase-local up -d --force-recreate supabase-pooler | ||
| @echo "✓ pooler recreated — give it 30s for health check" |
There was a problem hiding this comment.
Guard pooler-recreate against CLI runtime.
Lines 427-429 always start supabase-pooler through compose. If SUPABASE_RUNTIME=cli, this bypasses the existing runtime-guard flow and creates mixed Supabase state on the same machine. This target should fail fast unless the runtime is compose, or call the same guard used by supa-start.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pmoves/Makefile` around lines 426 - 430, The pooler-recreate Makefile target
currently always recreates supabase-pooler; guard it the same way as supa-start
by checking SUPABASE_RUNTIME (or invoking the same guard target used by
supa-start) and fail fast unless SUPABASE_RUNTIME is "compose"; specifically
update the pooler-recreate target to verify SUPABASE_RUNTIME (or call the
existing guard target/function) before running @$(DC) --profile supabase-local
up -d --force-recreate supabase-pooler and print a clear error and non-zero exit
when the runtime is not compose.
| echo " APPLY: $$name"; \ | ||
| _psql < "$$migration" && \ | ||
| _psql -c "INSERT INTO public.pmoves_bootstrap_history(kind,filename) VALUES('migration','$$name') ON CONFLICT DO NOTHING;" || \ | ||
| echo " WARN: $$name failed — continuing"; \ |
There was a problem hiding this comment.
Don’t treat “applied but not recorded” as a warning.
The apply && insert-history || warn chain collapses two different failures into one path. If the SQL applies successfully but the pmoves_bootstrap_history insert fails, the target continues and the next run will replay that already-applied file against a mutated database.
Split the flow so only SQL execution failures are skippable; once a file has been applied, failure to record it should stop the target.
Also applies to: 680-683
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pmoves/Makefile` around lines 665 - 668, The current shell chain conflates
SQL execution failure and history-insert failure (using _psql < "$$migration" &&
_psql -c "INSERT INTO public.pmoves_bootstrap_history(...)" || echo ...) so an
insert failure will be treated as a non-fatal warning; change the flow so you
first run _psql < "$$migration" and if that fails print the warning and
continue, but if it succeeds then run the INSERT into pmoves_bootstrap_history
and if that INSERT fails exit non-zero (stop the target). Update the block
around the _psql invocation and the INSERT (and the analogous block at lines
680-683) to use an if/then/else or separate conditional commands that only
continue on a failed SQL apply, and abort when the history INSERT
(pmoves_bootstrap_history, filename/migration variables, _psql -c) fails.
| <div class="section-header" id="learnMoreHeader"> | ||
| <span class="section-caret" id="learnMoreCaret">▶</span> | ||
| <span class="section-title">Learn More</span> | ||
| </div> | ||
| <div class="section-body" id="learnMoreBody"> |
There was a problem hiding this comment.
Use semantic buttons for the collapsible section headers.
These headers are clickable divs, so they are not focusable or keyboard-operable. That blocks keyboard-only users from opening collapsed panels like Display, Surface function, and Outputs.
Also applies to: 59-63, 142-145, 200-203, 217-220
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/hyperdim/index.html` around lines 35 - 39, The clickable header divs
(e.g., elements with IDs learnMoreHeader, learnMoreCaret and their paired
section bodies like learnMoreBody) must be converted into semantic,
keyboard-operable controls: replace the clickable div with a <button> (or make
it role="button" tabbable) and add aria-expanded and aria-controls attributes
pointing to the associated section body ID so keyboard users can toggle the
panel; update the caret state when toggling and ensure any click handler on the
old div is wired to the new button's click so the same toggle logic runs (apply
the same change pattern to the other headers referenced in the comment).
| { | ||
| "surfaceFn": "function surface(input) {\n const u = (input.u - 0.5) * 10;\n const v = (input.v - 0.5) * 10;\n const eps = input.epsilon || 0.0;\n \n const z = Math.sin(u)*Math.cos(v) * eps;\n \n return {\n x: u, \n y: v, \n z: z, \n r: 0.5, \n g: 0.5, \n b: 0.5, \n a: 0.8\n };\n}", | ||
| "params": { | ||
| "uMin": 0, | ||
| "uMax": 1, | ||
| "vMin": 0, | ||
| "vMax": 1, | ||
| "uSegs": 150, | ||
| "vSegs": 150 | ||
| }, | ||
| "surfaceInput": { | ||
| "u": 0, | ||
| "v": 0, | ||
| "curvature": 0.0, | ||
| "epsilon": 0.44662856918050364 | ||
| }, | ||
| "animatedParams": [ | ||
| { | ||
| "name": "epsilon", | ||
| "playing": true, | ||
| "min": 0.24662856918050363, | ||
| "max": 0.6466285691805036, | ||
| "step": 0.01, | ||
| "time": 5, | ||
| "phase": 0 | ||
| } | ||
| ], | ||
| "camera": { | ||
| "position": { | ||
| "x": 5, | ||
| "y": 5, | ||
| "z": 2 | ||
| }, | ||
| "target": { | ||
| "x": 0, | ||
| "y": 0, | ||
| "z": 0 | ||
| } | ||
| }, | ||
| "shininess": 150, | ||
| "globalSaturation": 1.5, | ||
| "meta": { | ||
| "inferred_shape": "Flat", | ||
| "delta_proxy": 0.44662856918050364 | ||
| } |
There was a problem hiding this comment.
Migrate this preset to the current save schema before shipping it in the load menu.
The viewer now loads surface.code, parameters, extraParameters, and display, but this file still uses the old surfaceFn / params / surfaceInput / animatedParams layout. Because _list.json still advertises chit_manifold.json, choosing it will not restore the saved manifold scene.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/hyperdim/saves/chit_manifold.json` around lines 1 - 45, The preset
uses the old keys surfaceFn, params, surfaceInput, and animatedParams which the
viewer no longer reads; migrate it to the new save schema by moving the surface
function string into surface.code, convert params into parameters (preserving
uMin/uMax/vMin/vMax/uSegs/vSegs), move surfaceInput values into extraParameters
(including epsilon/curvature/current u/v), and translate animatedParams into
display or extraParameters.animation format expected by the viewer; ensure
display includes camera, shininess, globalSaturation and meta stays intact so
the viewer can restore the scene when _list.json advertises chit_manifold.json.
| } | ||
| ], | ||
| "surface": { | ||
| "code": "function surface(input) {\n const u = input.u; // Theta\n const v = input.v; // Phi\n \n // Optimized access to params\n const power = input.Power;\n const maxIter = input.Iterations;\n const bailout = input.Bailout;\n const bailoutSq = bailout * bailout;\n const detail = input.Detail;\n \n // Dynamic epsilon based on detail\n const epsilon = 1.0 / (detail * 10);\n const maxRaySteps = 100;\n \n const cx = input.Cx;\n const cy = input.Cy;\n const cz = input.Cz;\n \n const sinU = Math.sin(u);\n const dx = sinU * Math.cos(v);\n const dy = sinU * Math.sin(v);\n const dz = Math.cos(u);\n \n let r = 2.0;\n let hit = false;\n \n // Inlined GetDist for performance (avoids function call overhead in tight loop)\n // Improved Derivative Logic to reduce spikes\n function getDist(x, y, z) {\n let zx = x, zy = y, zz = z;\n let dr = 1.0;\n let r2 = zx*zx + zy*zy + zz*zz;\n \n for (let i = 0; i < maxIter; i++) {\n if (r2 > bailoutSq) break;\n \n // Optimize: use raw math, minimize object creation\n let rad = Math.sqrt(r2);\n // Safe acos for theta (clamp to -1..1)\n let theta = Math.acos(Math.max(-1, Math.min(1, zz / rad)));\n let phi = Math.atan2(zy, zx);\n \n let zr = Math.pow(rad, power);\n let thetaP = theta * power;\n let phiP = phi * power;\n \n // Julia Derivative: dr = power * r^(power-1) * dr\n // We can optimize pow calls\n dr = Math.pow(rad, power - 1) * power * dr + 1.0;\n \n const sinThetaP = Math.sin(thetaP);\n zx = zr * sinThetaP * Math.cos(phiP);\n zy = zr * sinThetaP * Math.sin(phiP);\n zz = zr * Math.cos(thetaP);\n \n zx += cx;\n zy += cy;\n zz += cz;\n \n r2 = zx*zx + zy*zy + zz*zz;\n }\n \n const rad = Math.sqrt(r2);\n // Soften the DE to reduce sharp spikes (over-stepping)\n // Multiplying by 0.5 * log(r) * r / dr is standard, but we cap dr to avoid infinite spikes\n if (dr < 1.0) dr = 1.0;\n return 0.5 * Math.log(rad) * rad / dr;\n }\n\n for(let i=0; i<maxRaySteps; i++) {\n const px = dx * r;\n const py = dy * r;\n const pz = dz * r;\n \n let d = getDist(px, py, pz);\n \n // Spike Fix: Clamp maximum step size to prevent overshooting into the shape\n // especially when near complex details\n if (d > 0.2) d = 0.2;\n\n if (d < epsilon) {\n hit = true;\n r -= d * 0.5;\n break;\n }\n \n r -= d;\n if (r < 0) { r = 0; break; }\n }\n \n const finalX = dx * r;\n const finalY = dy * r;\n const finalZ = dz * r;\n \n // Coloring (Compute Trap)\n let trap = 1e20;\n let iters = 0;\n \n if (hit) {\n let zx = finalX, zy = finalY, zz = finalZ;\n let r2 = 0;\n for (let i = 0; i < maxIter; i++) {\n r2 = zx*zx + zy*zy + zz*zz;\n if (r2 > bailoutSq) break;\n \n trap = Math.min(trap, r2);\n \n let rad = Math.sqrt(r2);\n let theta = Math.acos(Math.max(-1, Math.min(1, zz / rad)));\n let phi = Math.atan2(zy, zx);\n \n let zr = Math.pow(rad, power);\n let thetaP = theta * power;\n let phiP = phi * power;\n \n const sinThetaP = Math.sin(thetaP);\n zx = zr * sinThetaP * Math.cos(phiP);\n zy = zr * sinThetaP * Math.sin(phiP);\n zz = zr * Math.cos(thetaP);\n \n zx += cx;\n zy += cy;\n zz += cz;\n iters = i;\n }\n }\n\n let red, green, blue;\n if (hit) {\n const t = Math.sqrt(trap);\n const col = t * 0.8 + (iters / maxIter) * 0.2;\n red = 0.5 + 0.5 * Math.cos(col * 4 + 0.5);\n green = 0.5 + 0.5 * Math.cos(col * 4 + 1.5);\n blue = 0.5 + 0.5 * Math.cos(col * 4 + 2.5);\n } else {\n red = 0; green = 0; blue = 0;\n }\n \n const alpha = hit ? 1.0 : 0.0;\n \n return { x: finalX, y: finalY, z: finalZ, r: red, g: green, b: blue, a: alpha };\n}" |
There was a problem hiding this comment.
Clamp signed distances before the hit test.
getDist() can return a negative value after the ray steps inside the fractal. The current if (d < epsilon) path treats that as a hit and then does r -= d * 0.5, which actually pushes the sample back outward. That makes the returned point depend on overshoot rather than the surface and will show up as unstable shells/artifacts near the bulb boundary.
Suggested fix
- let d = getDist(px, py, pz);
+ let d = getDist(px, py, pz);
+ if (!Number.isFinite(d)) break;
- if (d > 0.2) d = 0.2;
+ if (d < 0) d = 0;
+ if (d > 0.2) d = 0.2;
- if (d < epsilon) {
+ if (d <= epsilon) {
hit = true;
- r -= d * 0.5;
break;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/hyperdim/saves/mandelbulb.json` at line 90, getDist can return
negative distances which cause the ray step logic in the main marching loop to
push the sample outward; after calling getDist(px, py, pz) in the ray march loop
(where variable d is assigned) clamp d to a non-negative value (e.g., d =
Math.max(d, 0.0)) before performing the hit test (if (d < epsilon)) and before
adjusting r (the r -= d*0.5 and r -= d lines) so negative DEs won't drive the
ray outward; update the code around the main for-loop that calls getDist to
apply this clamp to d.
| /* Collapsed state: only show the button, no panel visuals */ | ||
| #sidebar-wrapper.collapsed #sidebar { | ||
| width: auto; | ||
| height: auto; | ||
| padding: 0; | ||
| background: transparent; | ||
| border: none; | ||
| overflow: visible; | ||
| } | ||
|
|
||
| #sidebar-wrapper.collapsed #controlsBody, | ||
| #sidebar-wrapper.collapsed .sidebar-header h2, | ||
| #sidebar-wrapper.collapsed .control-row, | ||
| #sidebar-wrapper.collapsed #sidebar-footer { | ||
| display: none; |
There was a problem hiding this comment.
Collapsed mode still leaves header controls visible.
This rule hides #controlsBody, h2, .control-row, and #sidebar-footer, but the preset/load UI lives under .header-panel / .header-panel-row, so the embed can still render inputs over the canvas in ui=none. Hide the header panel too, otherwise the “button only” collapsed state is never fully reached.
💡 Proposed fix
`#sidebar-wrapper.collapsed` `#controlsBody`,
`#sidebar-wrapper.collapsed` .sidebar-header h2,
+#sidebar-wrapper.collapsed .header-panel,
+#sidebar-wrapper.collapsed .header-panel-row,
`#sidebar-wrapper.collapsed` .control-row,
`#sidebar-wrapper.collapsed` `#sidebar-footer` {
display: none;
}Based on learnings: "Ensure URL parameter support for embedding/headless mode: preset=... and ui=none should be parsed and applied."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /* Collapsed state: only show the button, no panel visuals */ | |
| #sidebar-wrapper.collapsed #sidebar { | |
| width: auto; | |
| height: auto; | |
| padding: 0; | |
| background: transparent; | |
| border: none; | |
| overflow: visible; | |
| } | |
| #sidebar-wrapper.collapsed #controlsBody, | |
| #sidebar-wrapper.collapsed .sidebar-header h2, | |
| #sidebar-wrapper.collapsed .control-row, | |
| #sidebar-wrapper.collapsed #sidebar-footer { | |
| display: none; | |
| /* Collapsed state: only show the button, no panel visuals */ | |
| `#sidebar-wrapper.collapsed` `#sidebar` { | |
| width: auto; | |
| height: auto; | |
| padding: 0; | |
| background: transparent; | |
| border: none; | |
| overflow: visible; | |
| } | |
| `#sidebar-wrapper.collapsed` `#controlsBody`, | |
| `#sidebar-wrapper.collapsed` .sidebar-header h2, | |
| `#sidebar-wrapper.collapsed` .header-panel, | |
| `#sidebar-wrapper.collapsed` .header-panel-row, | |
| `#sidebar-wrapper.collapsed` .control-row, | |
| `#sidebar-wrapper.collapsed` `#sidebar-footer` { | |
| display: none; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/hyperdim/styles.css` around lines 29 - 43, The collapsed-state CSS
doesn't hide the preset/load UI under .header-panel/.header-panel-row, so update
the collapsed selectors (`#sidebar-wrapper.collapsed` ...) to also target
.header-panel and .header-panel-row (and/or specific header panel descendants
that render inputs) and set display: none so the "button only" state truly
removes header controls; apply this change alongside the existing rules that
hide `#controlsBody`, .control-row, .sidebar-header h2, and `#sidebar-footer` so
embeds using ui=none/preset=... don't leave inputs visible.
| <iframe | ||
| src="/hyperdim/?preset=beats_c5.json&ui=none" | ||
| title="Hologram Cluster 5 — Allegro Balanced Bright" | ||
| style="width: 100%; height: 100%; min-height: 300px; border: none; aspect-ratio: 16/9; pointer-events: none; border-radius: 8px;" | ||
| loading="lazy"> | ||
| </iframe> | ||
| <figcaption> | ||
| <strong>808 SIGNS / RAKS SLOW</strong> | ||
| <span>Cluster 5 · Allegro Balanced Bright</span> | ||
| </figcaption> | ||
| </figure> | ||
|
|
||
| <figure class="gallery-item"> | ||
| <iframe | ||
| src="/hyperdim/?preset=beats_c3.json&ui=none" | ||
| title="Hologram Cluster 3 — Allegro Balanced Deep" | ||
| style="width: 100%; height: 100%; min-height: 300px; border: none; aspect-ratio: 16/9; pointer-events: none; border-radius: 8px;" | ||
| loading="lazy"> | ||
| </iframe> | ||
| <figcaption> | ||
| <strong>THE ALIEN IN THE WINDOW</strong> | ||
| <span>Cluster 3 · Allegro Balanced Deep</span> | ||
| </figcaption> | ||
| </figure> | ||
|
|
||
| <figure class="gallery-item"> | ||
| <iframe | ||
| src="/hyperdim/?preset=beats_c1.json&ui=none" | ||
| title="Hologram Cluster 1" | ||
| style="width: 100%; height: 100%; min-height: 300px; border: none; aspect-ratio: 16/9; pointer-events: none; border-radius: 8px;" | ||
| loading="lazy"> |
There was a problem hiding this comment.
Sandbox the Hyperdimensions preview iframes.
These gallery previews load a same-origin page that executes substantial viewer logic. Without a sandbox, any script execution bug inside /hyperdim/ can reach the landing-page DOM and origin storage through window.top. Lock the previews down to the minimum capabilities they actually need, or switch the gallery to a static preview if the live viewer requires broader privileges.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/index.html` around lines 250 - 280, Add a restrictive sandbox
attribute to the gallery iframes (the <iframe> elements loading
src="/hyperdim/...") to prevent those same-origin viewer pages from reaching the
parent origin or storage; if the live viewer needs to run JS, grant only
allow-scripts (do NOT add allow-same-origin or allow-top-navigation), otherwise
use a fully sandboxed iframe with no allowances or replace with a static preview
and communicate via postMessage if needed.
|
Closing as superseded. Audited commit-by-commit against
Branch retained (not deleted) for reference per repo convention. Nothing else here needs to land. |
…DO (#1682) The live site showed a "TODO(founder): replace with DARKXSIDE'S School playlist URL" string as the Cloudflare School card's button text with href="#". Point it at the existing DARKXSIDE playlist (same list used by the DARKXSIDE School card) so visitors get a working link instead of a placeholder. Salvaged from the superseded #1677 (fix/ghcr-matrix-paths-gate); all of that branch's other changes — website gallery/viewer, deploy targets, GHCR matrix paths gate + tool, sync-secrets shell:bash, supabase pooler fix — are already on main via #1655/#1672/#1675/#1678 and prior CI merges. This playlist link was the only piece not yet on main. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This PR resolves the black WebGL canvas issues in the default and embed viewers for hyperdimensions. It ensures the default nautilus fallback evaluates the surface function, and forces the Three.js renderer to recalculate geometry when the sidebar collapses in ui=none mode. It also replaces the TODO with the requested YouTube playlist link for DARKXSIDE'S School.
Summary by CodeRabbit
New Features
Documentation
Style