synthetic-growth-in-glass-68f5/exploration.html

73 lines
450 KiB
HTML
Raw Permalink Normal View History

2026-03-31 01:47:20 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Synthetic growth in glass — exploration</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #0a0a0f; color: #3a3a4a; font-family: ui-monospace, monospace; overflow: hidden; }
#grid { padding: 20px; font-size: 12px; line-height: 1.4; white-space: pre; }
.c { display: inline-block; transition: all 0.3s; }
.c.active { color: #fde68a; text-shadow: 0 0 6px rgba(253,230,138,0.5); }
.c.strong { color: #34d399; text-shadow: 0 0 10px rgba(52,211,153,0.6); font-weight: bold; }
.c.dead { color: #1a1a2a; }
#info { position: fixed; bottom: 10px; left: 20px; color: #3a3a4a; font-size: 11px; }
#controls { position: fixed; top: 10px; right: 20px; color: #666; font-size: 11px; }
#controls span { cursor: pointer; margin-left: 12px; color: #fde68a; }
</style>
</head>
<body>
<div id="grid"></div>
<div id="info">neurameba · physarum exploration</div>
<div id="controls"><span id="play-btn">play</span><span id="reset-btn">reset</span></div>
<script>
const text = "# Changelog\n\n## v0.11.3 — Neurameba v3: Rust/WASM Physarum Organism\n\n- **Rust WASM organism** — replaced JS neural net with a Rust Physarum simulation compiled to WASM via wasm-pack. Dynamic architecture — not a fixed-size network.\n- **Variable neuron pools** — 4-64 neurons per node. Grow on surprise (novel patterns), shrink on familiarity.\n- **Energy economics** — thick tubes cost more to maintain, high activation feeds energy back. Nodes die at zero energy.\n- **Shuttle streaming** — sinusoidal oscillation on extension threshold. Tendrils pulse forward and retract like real Physarum.\n- **Cloning and merging** — organism splits at structural boundaries (headings, rules), merges when different-origin tendrils meet.\n- **Chemical trails** — activation values persisted in SQLite between explorations. The organism remembers where it's been.\n- **Habituation** — repeated text patterns dampen activation over time. Boilerplate gets boring.\n- **Topology metrics** — surviving nodes, branches, loops, max depth, thickness ratio, fractal dimension (box-counting), final energy. All sent to the builder LLM.\n- **Structural family diversity** — builder reports which animation family it chose; last 5 tracked in DB to avoid repetition.\n- **`/neurameba view`** — unified visualization with network-terrain slider. Crossfades between activation dot matrix and text grid with organism overlay.\n\n## v0.11.2 — Module UX1: Folders, Live Feed, Configurable Prefixes\n\n- **Folders** — posts belong to folders (replaces categories). `@username` folder auto-created per user. `random` is the default.\n- **Live feed** — SSE-powered real-time feed updates. New posts appear without refreshing.\n- **Configurable prefixes** — users can set custom command prefix (default `/`) and post prefix via `/settings`. Enables different input modes.\n- **`@username` folders** — auto-created on registration and backfilled for existing users.\n\n## v0.11.0 — Module 11: Neurameba / Voieneur\n\n- **Voieneur rebrand** — Forgejo renamed to Voieneur (voie + voyeur). Clone URLs now `git@voieneur.motd.social:user/repo.git`. Same codebase, new identity.\n- **Neurameba** — autonomous creative organism. Watches the feed, picks threads by its own logic, generates JavaScript canvas animations as abstract visual interpretations.\n- **Three-layer engine** — Layer 1: neural net organism explores text as 2D terrain. Layer 2: LLM tone analyzer extracts 6 emotional dimensions. Layer 3: builder LLM receives only abstract parameters, never sees source text.\n- **Docs as bootstrap** — when no threads with 2+ replies exist, neurameba reads platform docs as fallback input.\n- **Zero-gate publishing** — alive animations ship, dead output disappears silently.\n- **Voieneur repos** — each mushroom published with index.html, exploration.html (slime mold replay), network.json, LICENSE (MIT + origin), README (SEO-optimized).\n- **GitHub mirroring** — repos auto-mirrored to a GitHub org when configured.\n- **Feed announcements** — neurameba posts about each birth, linking back to the source conversation.\n- **GitHub issues** — reads open issues on its repos as secondary creative input.\n\n## v0.10.0 — Module 10: Voie Integration\n\n- **`/voie search`** — search European infrastructure providers via voie.fi API\n- **`/voie topics`**, **`/voie browse`**, **`/voie providers`** — browse the catalog by category\n- **`/voie compare`** — side-by-side comparison of two searches\n- **`/voie stats`** — catalog statistics (1,500+ providers, 36 countries)\n\n## v0.9.0 — Module 9: Three-Column UI\n\n- **Three-column layout** — left panel (content), center (terminal), right (sidebar). Inspired by VS Code. Panels take space from margins, center stays fixed.\n- **Left panel** — `/read` opens docs in side panel, `/view` opens media, `/expand` or `[read more]` opens full posts with replies. Close with `[x]`, `/close`, or Escape.\n- **Right panel** — sidebar becomes a proper column with `/ask` input field, connection statu
const passes = [{"t":0,"r":75,"c":55,"a":"hold","s":0.23420222674406083,"ps":9,"e":100.52361781395248,"pr":1.1},{"t":0,"r":36,"c":67,"a":"extend","s":0.421189054857224,"ps":9,"e":71.41365870720044,"pr":1.1},{"t":0,"r":76,"c":14,"a":"hold","s":0.2464628311165622,"ps":9,"e":100.6217026489325,"pr":1.1},{"t":0,"r":6,"c":19,"a":"extend","s":0.3377645515814301,"ps":9,"e":70.94648148885601,"pr":1.1},{"t":0,"r":134,"c":60,"a":"extend","s":0.33059573980691476,"ps":9,"e":70.90633614291872,"pr":1.1},{"t":1,"r":75,"c":55,"a":"hold","s":0.24877623799872847,"ps":9,"e":101.16382771794231,"pr":1.1},{"t":1,"r":36,"c":67,"a":"extend","s":0.41680691969376604,"ps":8,"e":51.48367984532539,"pr":1.05},{"t":1,"r":76,"c":14,"a":"hold","s":0.25148374068203416,"ps":8,"e":101.43357257438878,"pr":1.05},{"t":1,"r":6,"c":19,"a":"extend","s":0.3874310610501841,"ps":9,"e":50.88715098408023,"pr":1.1},{"t":1,"r":134,"c":60,"a":"extend","s":0.3349178646280815,"ps":8,"e":50.66997534196036,"pr":1.05},{"t":1,"r":36,"c":68,"a":"hold","s":0.2502491388072056,"ps":5,"e":31.857846842114977,"pr":1.2000000000000002},{"t":1,"r":7,"c":19,"a":"hold","s":0.2048527139765445,"ps":5,"e":31.294456635607787,"pr":1.2000000000000002},{"t":1,"r":5,"c":19,"a":"hold","s":0.2663074766739002,"ps":5,"e":31.786094737186634,"pr":1.2000000000000002},{"t":1,"r":134,"c":59,"a":"hold","s":0.3088001484813278,"ps":5,"e":32.10883096338721,"pr":1.2000000000000002},{"t":2,"r":75,"c":55,"a":"retracted","s":0.24877623799872847,"ps":8,"e":101.95403762193214,"pr":1.05},{"t":2,"r":36,"c":67,"a":"extend","s":0.421189054857224,"ps":7,"e":37.66223459892822,"pr":1},{"t":2,"r":76,"c":14,"a":"retracted","s":0.2464628311165622,"ps":7,"e":102.35527522332127,"pr":1},{"t":2,"r":6,"c":19,"a":"extend","s":0.37823859813941674,"ps":8,"e":36.89914183843689,"pr":1.05},{"t":2,"r":134,"c":60,"a":"hold","s":0.3173947820623295,"ps":7,"e":52.15913359845899,"pr":1},{"t":2,"r":36,"c":68,"a":"hold","s":0.26805208921951174,"ps":4,"e":33.40226355587107,"pr":1.1500000000000001},{"t":2,"r":7,"c":19,"a":"hold","s":0.32029975323950105,"ps":5,"e":33.1068546615238,"pr":1.2000000000000002},{"t":2,"r":5,"c":19,"a":"hold","s":0.26664234158526473,"ps":5,"e":33.16923346986875,"pr":1.2000000000000002},{"t":2,"r":134,"c":59,"a":"extend","s":0.3856677576318202,"ps":4,"e":24.21592111710924,"pr":1.1500000000000001},{"t":2,"r":36,"c":66,"a":"extend","s":0.37171716848048014,"ps":5,"e":17.001720097088306,"pr":1.1500000000000001},{"t":2,"r":6,"c":18,"a":"hold","s":0.15657499636608643,"ps":5,"e":22.311378964105934,"pr":1.2000000000000002},{"t":2,"r":6,"c":20,"a":"hold","s":0.15587936924500662,"ps":5,"e":22.305813947137295,"pr":1.2000000000000002},{"t":2,"r":133,"c":60,"a":"extend","s":0.3973117012204267,"ps":5,"e":16.900938129422496,"pr":1.1500000000000001},{"t":2,"r":134,"c":61,"a":"hold","s":0.194559412458991,"ps":5,"e":22.52217901765494,"pr":1.1500000000000001},{"t":3,"r":36,"c":67,"a":"hold","s":0.36248714781998903,"ps":6,"e":39.662131781488135,"pr":0.95},{"t":3,"r":6,"c":19,"a":"hold","s":0.3154024938973889,"ps":8,"e":38.222361789616,"pr":1.05},{"t":3,"r":134,"c":60,"a":"hold","s":0.3067380129088559,"ps":7,"e":53.56303770172984,"pr":1},{"t":3,"r":36,"c":68,"a":"retracted","s":0.2502491388072056,"ps":4,"e":34.80425666632872,"pr":1.1},{"t":3,"r":7,"c":19,"a":"retracted","s":0.3140676373730403,"ps":4,"e":35.01939576050812,"pr":1.1500000000000001},{"t":3,"r":5,"c":19,"a":"retracted","s":0.2623071841961841,"ps":4,"e":34.667690943438224,"pr":1.1500000000000001},{"t":3,"r":134,"c":59,"a":"hold","s":0.2959330409299324,"ps":4,"e":25.9833854445487,"pr":1.1},{"t":3,"r":36,"c":66,"a":"extend","s":0.41192588523059626,"ps":5,"e":13.682989025253152,"pr":1.1500000000000001},{"t":3,"r":6,"c":18,"a":"extend","s":0.4083068071305151,"ps":6,"e":17.27448339480504,"pr":1.3000000000000003},{"t":3,"r":6,"c":20,"a":"hold","s":0.16949205958652147,"ps":5,"e":22.911750423829467,"pr":1.2000000000000002},{"t":3,"r":133,"c":60,"a":"extend","s":0.3858979797685903,"ps":4,"e":13.571685377299852,"pr":1.1},{"t":3,"r":134,"c":61,"a":"hold","s":0.16072650793135118,"ps":4,"e":2
const lines = text.split('\n');
const gridEl = document.getElementById('grid');
const charEls = [];
for (let r = 0; r < lines.length; r++) {
const row = [];
for (let c = 0; c < lines[r].length; c++) {
const s = document.createElement('span');
s.className = 'c';
s.textContent = lines[r][c];
row.push(s);
gridEl.appendChild(s);
}
charEls.push(row);
gridEl.appendChild(document.createTextNode('\n'));
}
let tick = -1, playing = false, iv;
function apply(t) {
for (const r of charEls) for (const e of r) e.className = 'c';
const active = new Map();
for (const p of passes) {
if (p.t > t) break;
const k = p.r+','+p.c;
if (p.a === 'died' || p.a === 'retracted') active.set(k, 'dead');
else if (p.ps > 16) active.set(k, 'strong');
else active.set(k, 'active');
}
for (const [k, cls] of active) {
const [r, c] = k.split(',').map(Number);
if (charEls[r]?.[c]) charEls[r][c].className = 'c ' + cls;
}
document.getElementById('info').textContent = 'tick ' + t + ' · ' + [...active.values()].filter(v=>v!=='dead').length + ' alive';
}
function play() {
if (playing) return;
playing = true;
document.getElementById('play-btn').textContent = 'pause';
const max = passes.length > 0 ? passes[passes.length-1].t : 0;
iv = setInterval(() => { tick++; if (tick > max) { pause(); return; } apply(tick); }, 900);
}
function pause() { playing = false; clearInterval(iv); document.getElementById('play-btn').textContent = 'play'; }
function reset() { pause(); tick = -1; for (const r of charEls) for (const e of r) e.className = 'c'; document.getElementById('info').textContent = 'neurameba'; }
document.getElementById('play-btn').addEventListener('click', () => playing ? pause() : play());
document.getElementById('reset-btn').addEventListener('click', reset);
setTimeout(play, 1000);
</script>
</body>
</html>