Merge design/cloudflare-static-publish into main: Cloudflare static publish + CC credits

Integrates the fully-static Cloudflare publish line (live at
benstull.art/human-experience-simulator) into main: the static build (Pages + R2,
manifest-only media tree, baked API JSON), the "Run simulation" start button, the
public CC-BY/BY-SA credits page with the "License & reuse" CC BY-SA 4.0 derivative
declaration (Option A + D1), the repeatable Cloudflare deploy script, and assorted
load/audio fixes (progressive boot, scaleAudioUrl via mediaBase).

Clean auto-merge with main's per-clip affect/feelings + i18n work — only app.js and
altitude-lock.spec.ts overlapped, both auto-resolved. Verified green on the merged
tree: node 29, pytest 315 passed / 2 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BenStullsBets
2026-06-30 09:42:44 -07:00
30 changed files with 2052 additions and 58 deletions
+51
View File
@@ -0,0 +1,51 @@
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const A = require("../static/alteration.js");
const c = (o) => ({ visual: "on", audio: "off", left: 0, right: 0, dark: 0, light: 0, ...o });
test("identity at zero knobs", () => {
const p = A.plan(c({}));
assert.equal(p.grade.tone, 0);
assert.equal(p.overlay.level, 0);
assert.equal(p.dream.strength, 0);
assert.equal(p.is_identity, true);
});
test("mood tone is signed (light - dark)/KNOB_MAX, clamped", () => {
assert.equal(A.plan(c({ light: 4 })).grade.tone, 1); // full light
assert.equal(A.plan(c({ dark: 4 })).grade.tone, -1); // full dark
assert.equal(A.plan(c({ light: 2 })).grade.tone, 0.5);
});
test("left drives overlay level + intensity; right drives dream + affect", () => {
const p = A.plan(c({ left: 2, right: 4 }));
assert.equal(p.overlay.level, 2);
assert.equal(p.overlay.intensity, 0.5);
assert.equal(p.dream.strength, 4);
assert.equal(p.dream.intensity, 1);
assert.equal(p.affect.strength, 4);
assert.equal(p.affect.intensity, 1);
assert.equal(p.is_identity, false);
});
test("renderAudio: off → null, no coupling", () => {
assert.deepEqual(A.renderAudio("off", "cosmos.mp3", "https://x/"),
{ source: "off", url: null, altitude_coupled: false });
});
test("renderAudio: soundtrack → mediaBase audio url, coupled", () => {
assert.deepEqual(A.renderAudio("soundtrack", "cosmos.mp3", "https://x/"),
{ source: "soundtrack", url: "https://x/audio/cosmos.mp3", altitude_coupled: true });
// no scale audio → null url but still coupled
assert.deepEqual(A.renderAudio("soundtrack", "", "https://x/"),
{ source: "soundtrack", url: null, altitude_coupled: true });
});
test("alteration() composes plan + render with video.shown from visual", () => {
const r = A.alteration(c({ visual: "off", audio: "soundtrack", left: 1 }), "reef.mp3", "https://x/");
assert.equal(r.render.video.shown, false);
assert.equal(r.render.audio.url, "https://x/audio/reef.mp3");
assert.equal(r.plan.overlay.level, 1);
});
+66
View File
@@ -0,0 +1,66 @@
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("node:fs");
const path = require("node:path");
const C = require("../static/credits.js");
const CLIPS = [
{ id: "reef_x", title: "Reef X", license: "CC-BY-SA 4.0 — credit Joe Mabel", source: "Wikimedia <reef>" },
{ id: "cosmos", title: "Cosmic Cliffs", license: "CC-BY-class — credit NASA, ESA, CSA, STScI", source: "NASA SVS 31348" },
{ id: "pd_only", title: "PD clip", license: "public-domain (US Gov, 17 U.S.C. §105)", source: "NASA" },
];
test("creditEntries returns one entry per clip, preserving license/source", () => {
const out = C.creditEntries(CLIPS);
assert.equal(out.length, CLIPS.length, "no clip is silently dropped from the credits");
const reef = out.find((e) => e.id === "reef_x");
assert.equal(reef.license, "CC-BY-SA 4.0 — credit Joe Mabel");
assert.equal(reef.source, "Wikimedia <reef>");
assert.equal(reef.title, "Reef X");
});
test("creditEntries is sorted by id for deterministic output", () => {
const ids = C.creditEntries(CLIPS).map((e) => e.id);
assert.deepEqual(ids, ["cosmos", "pd_only", "reef_x"]);
});
test("creditEntries falls back title->id and tolerates missing fields", () => {
const out = C.creditEntries([{ id: "bare" }]);
assert.deepEqual(out, [{ id: "bare", title: "bare", license: "", source: "" }]);
});
test("creditEntries handles null/empty input", () => {
assert.deepEqual(C.creditEntries(null), []);
assert.deepEqual(C.creditEntries([]), []);
});
test("creditsListHtml renders every clip's attribution and escapes HTML", () => {
const html = C.creditsListHtml(CLIPS);
assert.match(html, /Cosmic Cliffs/);
assert.match(html, /Joe Mabel/);
// free-text source "Wikimedia <reef>" must be escaped, not injected as a tag
assert.match(html, /Wikimedia &lt;reef&gt;/);
assert.doesNotMatch(html, /<reef>/);
// one block per clip
const blocks = html.match(/class="credit"/g) || [];
assert.equal(blocks.length, CLIPS.length);
});
test("credits.html wires config.js + credits.js, the attributions container, and a back link", () => {
const html = fs.readFileSync(path.join(__dirname, "../static/credits.html"), "utf8");
assert.match(html, /<script src="config\.js">/); // static/live media-base + flag
assert.match(html, /<script src="credits\.js">/);
assert.match(html, /id="video-credits"/); // JS fills this
assert.match(html, /href="index\.html"/); // back into the experience
});
test("credits.html carries the CC BY-SA derivative declaration (Option D1)", () => {
const html = fs.readFileSync(path.join(__dirname, "../static/credits.html"), "utf8");
assert.match(html, /CC BY-SA 4\.0/); // the altered work's own license
assert.match(html, /altered/i); // states the footage is modified
// The section is NOT titled "About this work" — that name belongs to the separate
// About page; here the declaration lives under "License & reuse".
assert.doesNotMatch(html, /About this work/i);
assert.match(html, /License &amp; reuse/);
});
+1 -1
View File
@@ -8,7 +8,7 @@ const I = require("../static/i18n.js");
const html = fs.readFileSync(path.join(__dirname, "../static/index.html"), "utf8");
test("index.html includes the i18n script and a language select", () => {
assert.match(html, /<script src="\/i18n\.js">/);
assert.match(html, /<script src="i18n\.js">/); // relative: works at dev-root and under the deploy path prefix
assert.match(html, /id="lang-select"/);
});