Spaces:
Running on Zero
Running on Zero
Download visuallearning-handover.html from KwabsHug/VisualLearningIdea: direct link, hf CLI and curl.
- Browser
- Download file 26.6 kB
-
https://huggingface.co/spaces/KwabsHug/VisualLearningIdea/resolve/main/visuallearning-handover.html
- Command line
-
hf download hf://spaces/KwabsHug/VisualLearningIdea/visuallearning-handover.html
-
curl -L -o visuallearning-handover.html https://huggingface.co/spaces/KwabsHug/VisualLearningIdea/resolve/main/visuallearning-handover.html
26.6 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>VisualLearningIdea β Setup Handover</title> | |
| <style> | |
| :root{ | |
| --bg:#0f1117; --panel:#171a23; --panel2:#1d212e; --border:#2a3040; | |
| --text:#e6e9f0; --muted:#9aa3b5; --accent:#4f9cf9; --accent2:#7ee0a3; | |
| --warn:#f0b429; --danger:#f26d6d; --code:#12141c; | |
| } | |
| *{box-sizing:border-box} | |
| body{margin:0;background:var(--bg);color:var(--text);font:15px/1.6 -apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;padding:0 0 80px} | |
| .wrap{max-width:960px;margin:0 auto;padding:32px 24px} | |
| header{border-bottom:1px solid var(--border);padding-bottom:24px;margin-bottom:32px} | |
| h1{font-size:26px;margin:0 0 6px} | |
| .sub{color:var(--muted);font-size:14px} | |
| .badge{display:inline-block;background:var(--panel2);border:1px solid var(--border);border-radius:6px;padding:2px 10px;font-size:12px;color:var(--muted);margin-right:6px;margin-top:8px} | |
| h2{font-size:20px;margin:40px 0 12px;padding-bottom:6px;border-bottom:1px solid var(--border)} | |
| h3{font-size:16px;margin:24px 0 8px;color:var(--accent)} | |
| p{margin:8px 0} | |
| .panel{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:16px 20px;margin:16px 0} | |
| .warn{border-left:4px solid var(--warn)} | |
| .ok{border-left:4px solid var(--accent2)} | |
| .info{border-left:4px solid var(--accent)} | |
| table{width:100%;border-collapse:collapse;margin:14px 0;font-size:14px} | |
| th,td{text-align:left;border:1px solid var(--border);padding:8px 12px;vertical-align:top} | |
| th{background:var(--panel2);color:var(--muted);font-weight:600} | |
| code{background:var(--code);border:1px solid var(--border);border-radius:4px;padding:1px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;color:#a8d3ff} | |
| pre{background:var(--code);border:1px solid var(--border);border-radius:8px;padding:14px 16px;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.55;color:#d7e3f4} | |
| pre code{background:none;border:none;padding:0;color:inherit} | |
| .task{display:flex;gap:10px;align-items:flex-start;padding:8px 0;border-bottom:1px dashed var(--border)} | |
| .task:last-child{border-bottom:none} | |
| .task input{margin-top:4px;accent-color:var(--accent2)} | |
| .task label{cursor:pointer} | |
| .task .why{color:var(--muted);font-size:13px;display:block} | |
| .phase{color:var(--muted);font-size:12px;letter-spacing:1px;text-transform:uppercase;margin:20px 0 4px} | |
| a{color:var(--accent);text-decoration:none} | |
| a:hover{text-decoration:underline} | |
| ul{margin:8px 0;padding-left:22px} | |
| .kicker{color:var(--accent2);font-weight:600} | |
| .flow{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:14px 0} | |
| .flow .node{background:var(--panel2);border:1px solid var(--border);border-radius:8px;padding:8px 12px;font-size:13px} | |
| .flow .arrow{color:var(--muted)} | |
| footer{margin-top:48px;color:var(--muted);font-size:12px;border-top:1px solid var(--border);padding-top:16px} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="wrap"> | |
| <header> | |
| <h1>π VisualLearningIdea β Setup Handover</h1> | |
| <div class="sub">Handover doc for Claude Code / Codex Β· Owner: <b>KwabsHug</b> Β· Prepared 2026-10-23</div> | |
| <span class="badge">hf.co/spaces/KwabsHug/VisualLearningIdea</span> | |
| <span class="badge">SDK: Gradio 6.27.0</span> | |
| <span class="badge">Python 3.12</span> | |
| <span class="badge">MCP target</span> | |
| </header> | |
| <h2>1. Mission</h2> | |
| <div class="panel info"> | |
| <p><span class="kicker">Core idea:</span> treat the <b>morphism between representations as a language</b> β i.e., comprehension. A natural-language sentence goes in; the system returns a <b>serial, ordered list of decision items</b>; that serial form is discussable/refinable in conversation; and it ultimately resolves into a <b>natural 3D configuration</b>.</p> | |
| <p><span class="kicker">The comprehension gradient (why this matters):</span> take <i>"the cat sat and the sun shone."</i></p> | |
| <ul> | |
| <li><b>Reading is decision-free</b> β comprehension happens implicitly. Every mini-decision (how big is the cat? facing where? how high is the sun?) is resolved silently by convention, defaults, and priors. Nothing surfaces.</li> | |
| <li><b>Drawing forces decisions to surface</b> β you cannot make a mark without committing to position, pose, scale, proportion. The drawing is a ledger of forced decisions.</li> | |
| <li><b>3D goes further: it allows configurations, not separate images.</b> A 3D scene is a web of relations where decisions propagate. A cat on a ground plane plus a sun in the sky become <i>coupled</i>: the sun's elevation fixes the shadow's direction; the cat's orientation determines the shadow's shape; support and occlusion relations emerge that the sentence never stated and no individual 2D view could contain. The 3D result holds information beyond any single rendering of it.</li> | |
| </ul> | |
| <pre><code>Sentence β DECISION LEDGER (serial, ordered, dependency-aware, with unresolved choices surfaced) | |
| β [discussion / refinement loop: interrogate the unresolved decisions] | |
| β 3D CONFIGURATION (the UNDERSTANDING PROXY: relational scene β geometry + light + | |
| support + orientation β not separate images) | |
| β MATERIALIZATION (the LAST step: physical items for each word / the whole scene β | |
| papercraft nets, origami crease patterns, printable parts, | |
| electronic components + wiring, or a mix)</code></pre> | |
| <p>The serial order is not cosmetic β it is the <b>narrative order the sentence itself imposes</b> (and folding is inherently sequential too). The item list IS the intermediate representation (IR) of the language: a record of the decisions that reading hides. The 3D configuration must be derivable from the serial form alone β and it must encode <b>relations between items</b>, not just items.</p> | |
| <p><span class="kicker">Materialization is downstream of understanding, not part of it:</span> origami/papercraft is a <b>reality output</b> β one fabrication channel chosen <i>after</i> the 3D proxy has done its job of making comprehension inspectable. The same ledger can materialize differently: pure papercraft (fold a net per item), an Arduino project with papercraft/origami props (electronic components for behavior + folded sheets for form), 3D-printed parts, or a mix. The ledger must therefore stay materialization-agnostic; materialization routes are chosen per item in the final stage.</p> | |
| </div> | |
| <h2>2. Current state (verified 2026-10-23)</h2> | |
| <table> | |
| <tr><th>Item</th><th>Status</th></tr> | |
| <tr><td>Space repo exists</td><td><code>hf://spaces/KwabsHug/VisualLearningIdea</code></td></tr> | |
| <tr><td>README</td><td><code>sdk: gradio</code>, <code>sdk_version: 6.27.0</code>, <code>python_version: '3.12'</code>, <code>app_file: app.py</code>, pinned: false. Short description: "Visualisation and speed of input attempt" (may be updated).</td></tr> | |
| <tr><td>app.py</td><td><b>Does not exist yet</b> β repo contains only README + .gitattributes</td></tr> | |
| <tr><td>Owner account</td><td>PRO account β ZeroGPU available (40 min/day quota), can host up to 10 ZeroGPU Spaces</td></tr> | |
| <tr><td>Existing assets to reuse</td><td>Sibling Space <code>KwabsHug/GameConfigIdea</code> (Gradio, ZeroGPU, uses gradio_client + InferenceClient + local Kokoro) β reference for patterns that already work on this account</td></tr> | |
| </table> | |
| <h2>3. Target tool surface (MCP)</h2> | |
| <p>The Space must launch with <code>demo.launch(mcp_server=True)</code> so each public function becomes an MCP tool callable from HuggingChat / Claude / Codex. Tool exposure is controlled by <b>type hints + docstrings</b> (they become the tool description the LLM reads). Set <code>api_name=False</code> on every helper function that should NOT become a tool.</p> | |
| <h3>Planned tools (v1 contract)</h3> | |
| <pre><code>def parse_sentence_to_items(sentence: str) -> str: | |
| """Decompose a natural-language sentence into a serial, ordered ledger | |
| (the intermediate representation of the morphism). The output drives BOTH | |
| views of the reference UI: a flat serial token reading and a 3D scene. | |
| Structure (shaped by the cat-sun reference build β see section 9): | |
| tokens: [{word, index, commits: [item_indices], opens: [question_ids]}] | |
| β per-token attribution. Determiners commit nothing but open | |
| unresolved "?" entries. One word may commit several items | |
| (lexical compression: "sat" β surface + pose + support). | |
| items: [{index, kind, description, | |
| decision: {chosen, alternatives_considered}, | |
| params, depends_on, stage_direction}] | |
| β stage_direction is the reveal payload the renderer plays: | |
| {action: "spawn"|"move"|"orient"|"couple"|"mark", | |
| target, from, to, couples: [item_indices], ...}. | |
| Without it the player must be hand-coded per sentence. | |
| unresolved:[{id, token_index, question, default_chosen, alternatives}] | |
| β the discussion loop's agenda. | |
| Args: | |
| sentence: A plain-English sentence or scene description. | |
| Returns: | |
| JSON string with keys: tokens, items, unresolved. | |
| """ | |
| def items_to_fold(items_json: str) -> str: | |
| """Convert serial construction items into a crease pattern in FOLD format. | |
| Args: | |
| items_json: JSON string produced by parse_sentence_to_items. | |
| Returns: | |
| JSON string: {"fold": {...FOLD document...}, "warnings": [...]} | |
| """ | |
| def simulate_fold(fold_json: str) -> str: | |
| """Simulate folding a FOLD-format crease pattern and export the folded | |
| 3D state as OBJ/STL (plus a foldability report). | |
| Args: | |
| fold_json: FOLD-format JSON (from items_to_fold or user upload URL). | |
| Returns: | |
| File path/URL of the folded mesh + foldability diagnostics. | |
| """ | |
| def unfold_mesh_to_papercraft(mesh_url: str) -> str: | |
| """Reverse morphism: unfold a 3D mesh (STL/OBJ/PLY/OFF URL) into a | |
| 2D papercraft net (SVG files with fold direction markings). | |
| Args: | |
| mesh_url: Public http(s) URL to the mesh file. | |
| Returns: | |
| File paths/URLs of the generated SVG components. | |
| """ | |
| def materialize_scene(items_json: str, route: str = "papercraft") -> str: | |
| """Materialize a validated scene ledger into physical outputs β the LAST | |
| step of the morphism: real items for each word / the whole scene. | |
| Args: | |
| items_json: JSON string produced by parse_sentence_to_items (or refined | |
| via the discussion loop). | |
| route: fabrication route β "papercraft" (unfold nets from the 3D | |
| configuration and lay out sheets), "origami" (crease patterns), | |
| "print3d" (STL per item), "electronics" (component list + wiring | |
| notes for Arduino-type props), or "mixed". | |
| Returns: | |
| JSON string: {"parts": [{item_index, route, files: [urls], notes}], | |
| "bom": [...bill of materials for electronic/physical components...]} | |
| """</code></pre> | |
| <div class="panel warn"> | |
| <b>File I/O rule:</b> MCP clients pass files as <b>public http(s) URLs</b>, never local paths. Every tool must download its input itself and return files (Gradio converts outputs to URLs automatically). Return formats: JSON strings or file outputs β avoid bare numpy arrays. | |
| </div> | |
| <h2>4. Architecture</h2> | |
| <div class="flow"> | |
| <div class="node">Sentence</div><div class="arrow">β</div> | |
| <div class="node">parse_sentence_to_items<br><small>LLM (InferenceClient) β serial IR</small></div><div class="arrow">β</div> | |
| <div class="node">items_to_fold<br><small>deterministic β FOLD doc</small></div><div class="arrow">β</div> | |
| <div class="node">simulate_fold<br><small>OrigamiSimulator solver β STL/OBJ</small></div> | |
| </div> | |
| <div class="flow"> | |
| <div class="node">Mesh (STL/OBJ URL)</div><div class="arrow">β</div> | |
| <div class="node">unfold_mesh_to_papercraft<br><small>paperfoldmodels β SVGs</small></div> | |
| </div> | |
| <p><b>FOLD format is the interchange hub</b> (OrigamiSimulator reads/writes it; rtori converts it; Ori Studio imports/exports it). Every pipeline becomes "X β FOLD β Y".</p> | |
| <h2>5. Phased work plan</h2> | |
| <div class="phase">Phase 0 β Scaffolding</div> | |
| <div class="task"><input type="checkbox" id="t1"><label for="t1"><b>Create <code>app.py</code></b> with a trivial Gradio UI + <code>demo.launch(mcp_server=True)</code><span class="why">Verify MCP badge appears on the Space page before adding real logic. Check endpoint: <code>https://kwabshug-visuallearningidea.hf.space/gradio_api/mcp/schema</code></span></label></div> | |
| <div class="task"><input type="checkbox" id="t2"><label for="t2"><b>Create <code>requirements.txt</code></b>: <code>gradio[mcp]</code>, <code>numpy</code>, <code>networkx</code>, <code>openmesh</code>, <code>huggingface_hub</code><span class="why">openmesh needs CMake + C++ at build time; if pip build fails on Spaces, pin a prebuilt wheel or vendor OpenMesh bindings (see pitfalls)</span></label></div> | |
| <div class="task"><input type="checkbox" id="t3"><label for="t3"><b>Vendor or pip-install <code>paperfoldmodels</code></b> (felixfeliz/paperfoldmodels, MIT) β copy the module into the repo for reproducibility<span class="why">3 deps only: numpy, OpenMesh, networkx. Algorithm: MST of dual graph β unfold β cut self-intersections</span></label></div> | |
| <div class="phase">Phase 1 β Reverse morphism first (easiest, no GPU)</div> | |
| <div class="task"><input type="checkbox" id="t4"><label for="t4"><b>Implement <code>unfold_mesh_to_papercraft(mesh_url)</code></b><span class="why">Download mesh URL β OpenMesh load β unfold β return SVG file(s). Test input: Stanford bunny STL. Prefer OBJ polygonal input over STL (see pitfalls)</span></label></div> | |
| <div class="task"><input type="checkbox" id="t5"><label for="t5"><b>Acceptance test:</b> call the tool via MCP from HuggingChat with a bunny OBJ URL; receive valid SVG(s)<span class="why">This alone makes the Space useful and proves the whole MCP chain</span></label></div> | |
| <div class="phase">Phase 2 β The language: sentence β serial items</div> | |
| <div class="task"><input type="checkbox" id="t6"><label for="t6"><b>Define the serial-item IR schema</b> (JSON) β a <b>decision ledger</b>, not an assembly list. Each item: <code>{index, kind, description, decision: {chosen, alternatives_considered}, params, depends_on}</code><span class="why">kinds v1: <code>sheet</code>, <code>fold</code> (mountain/valley, angle), <code>join</code> (glue/tab), <code>attach</code>, <code>repeat</code> β plus <b>scene-configuration kinds</b>: <code>ground_plane</code>, <code>light_source</code> (position/elevation), <code>pose</code>, <code>orient</code>, <code>relation</code> (<code>on</code>, <code>near</code>, <code>facing</code>, <code>under-light-of</code>, <code>supported-by</code>). Keep the vocabulary SMALL β it is the grammar of the language. Every implicit choice the sentence skipped becomes an explicit decision item or an <code>unresolved</code> entry.</span></label></div> | |
| <div class="task"><input type="checkbox" id="t7"><label for="t7"><b>Implement <code>parse_sentence_to_items</code></b> using <code>InferenceClient</code> (pattern already proven in GameConfigIdea)<span class="why">Prompt the LLM to emit ONLY the IR schema; return <code>unresolved</code> ambiguities so the chat can discuss them β this is the "discussion β more natural 3D" loop entry point</span></label></div> | |
| <div class="task"><input type="checkbox" id="t8"><label for="t8"><b>Unit-test determinism:</b> same sentence + same seed β identical item list</td></label></div> | |
| <div class="task"><input type="checkbox" id="t16"><label for="t16"><b>Add a ledger validator step</b> before items_to_fold / scene build<span class="why">Lesson from the reference build: the hand-written ledger missed a propagation decision (sky color stayed daytime-blue when sun elevation dropped to 5Β°). An LLM-generated ledger will have similar gaps. The validator checks that every parameter affected by a coupling (item 7) is either declared in some item's stage_direction or explicitly marked independent β and fails loudly otherwise</span></label></div> | |
| <div class="phase">Phase 3 β Serial items β FOLD β 3D</div> | |
| <div class="task"><input type="checkbox" id="t9"><label for="t9"><b>Implement <code>items_to_fold</code></b>: deterministic mapper item-kind β FOLD geometry<span class="why">Start with prisms/boxes/waterbomb base; grow the mapping table item-by-item</span></label></div> | |
| <div class="task"><input type="checkbox" id="t10"><label for="t10"><b>Implement <code>simulate_fold</code></b>: port or wrap the OrigamiSimulator FOLD solver (amandaghassei/OrigamiSimulator, MIT) β or shell out to <code>rtori-cli simulate</code><span class="why">GPU shaders β consider ZeroGPU <code>@spaces.GPU(duration=β¦)</code> with realistic durations; CPU fallback acceptable for v1</span></label></div> | |
| <div class="task"><input type="checkbox" id="t11"><label for="t11"><b>Acceptance tests:</b> (a) "make a box with a lid" β items β FOLD β folded OBJ opens in a viewer; (b) <b>"the cat sat and the sun shone"</b> β decision ledger containing: <code>ground_plane</code> (implicit!), cat <code>sheet/form</code> + <code>pose: sat</code> + <code>position</code> + <code>orient/facing</code>, <code>light_source: sun</code> with elevation, and a <code>relation</code> coupling sunβcat that derives shadow direction in the 3D stage. The <code>unresolved</code> list must name the skipped mini-decisions (which cat form? facing where? sun elevation?) β that list is the discussion loop's agenda<span class="why">Test (b) is the conceptual acceptance test: if the 3D stage can compute shadow direction FROM the ledger's relations without extra prompt information, the configuration idea is working</span></label></div> | |
| <div class="phase">Phase 4 β Materialization (reality output)</div> | |
| <div class="task"><input type="checkbox" id="t13"><label for="t13"><b>Implement <code>materialize_scene</code> route "papercraft" first</b>: take the 3D configuration (from simulate_fold / scene stage), run unfold per item, lay out sheets, return SVGs<span class="why">This reuses Phase 1's unfolding work β but now driven by the scene, not a raw mesh URL. The 3D proxy output feeds the fabricator</span></label></div> | |
| <div class="task"><input type="checkbox" id="t14"><label for="t14"><b>Extend the IR with a <code>component</code> kind</b> for physical/electronic parts implied by the scene (LED, servo, motor, buzzerβ¦)<span class="why">Enables the Arduino-with-papercraft-props case: the ledger names components ("glowing collar" β LED + battery), materialize_scene emits a BOM + wiring notes, and papercraft props come from the geometry items</span></label></div> | |
| <div class="task"><input type="checkbox" id="t15"><label for="t15"><b>Acceptance test:</b> "the cat sat and the sun shone" with route "papercraft" β one papercraft sheet-set covering cat + ground plane (+ optional sun disc), with fold markings; route "mixed" additionally returns a BOM if a light-emitting variant is requested</label></div> | |
| <div class="phase">Phase 5 β Hub integration</div> | |
| <div class="task"><input type="checkbox" id="t12"><label for="t12"><b>Add VisualLearningIdea to HF MCP settings</b> (huggingface.co/settings/mcp) and/or a future ToolHub Space alongside <code>GameConfigIdea</code> (gradio_client proxy) and <code>Language-Learn-Idea</code> (Docker β REST proxy)<span class="why">Once registered, chat agents can chain: sentence β items β FOLD β 3D β unfold β papercraft SVG</span></label></div> | |
| <h2>6. Known pitfalls (discovered this session)</h2> | |
| <div class="panel"> | |
| <ul> | |
| <li><b>Coplanar triangles are NOT merged</b> by paperfoldmodels β an octagon face becomes 6 triangles with useless virtual fold lines (<a href="https://github.com/felixfeliz/paperfoldmodels/issues/4">repo issue #4</a>). <b>Accept OBJ with polygonal facets first</b>; STL suffers most. Coplanar merging is a later enhancement (reference: osresearch/papercraft unfold.c).</li> | |
| <li><b>No glue tabs</b> β paperfoldmodels only flattens. Tabs are a separate step (Inkscape Tabgen pattern) β plan as a <code>kind: join</code> item in the IR.</li> | |
| <li><b>OpenMesh build</b> β <code>pip install openmesh</code> requires cmake + g++ + pybind11. If the Space build fails, pin prebuilt binaries (Inkscape MightyScape docs document per-OS workarounds).</li> | |
| <li><b>Tool flooding</b> β every API endpoint becomes an MCP tool. Explicitly set <code>api_name=False</code> on all internal helpers. Keep the public tool count β€ 6.</li> | |
| <li><b>ZeroGPU quota attribution</b> β GPU calls inside the Space consume the caller's quota (PRO = 40 min/day). Declare realistic <code>@spaces.GPU(duration=N)</code> values; quota is reserved per <i>requested</i> duration, not actual runtime. Reset is 24h from first GPU use.</li> | |
| <li><b>Return JSON strings, not objects</b> β Gradio MCP converts outputs; strings and files are the reliable formats.</li> | |
| <li><b>Queue</b> β set <code>queue=True</code> on long-running events (progress notifications), <code>queue=False</code> for fast ones (10Γ throughput).</li> | |
| </ul> | |
| </div> | |
| <h2>7. Key references</h2> | |
| <table> | |
| <tr><th>Resource</th><th>URL</th></tr> | |
| <tr><td>Gradio MCP server guide</td><td><a href="https://gradio.app/guides/building-mcp-server-with-gradio">gradio.app/guides/building-mcp-server-with-gradio</a></td></tr> | |
| <tr><td>Spaces as MCP servers (HF docs)</td><td><a href="https://huggingface.co/docs/hub/en/spaces-mcp-servers">huggingface.co/docs/hub/en/spaces-mcp-servers</a></td></tr> | |
| <tr><td>paperfoldmodels</td><td><a href="https://github.com/felixfeliz/paperfoldmodels">github.com/felixfeliz/paperfoldmodels</a></td></tr> | |
| <tr><td>OrigamiSimulator (FOLD solver)</td><td><a href="https://github.com/amandaghassaei/OrigamiSimulator/">github.com/amandaghassaei/OrigamiSimulator</a></td></tr> | |
| <tr><td>osresearch/papercraft (coplanar reference)</td><td><a href="https://github.com/osresearch/papercraft">github.com/osresearch/papercraft</a></td></tr> | |
| <tr><td>rtori (FOLD convert/simulate CLI)</td><td><a href="https://github.com/origami-code/rtori">github.com/origami-code/rtori</a></td></tr> | |
| <tr><td>Ori Studio (UX reference)</td><td><a href="https://oristudio.dev/">oristudio.dev</a></td></tr> | |
| </table> | |
| <h2>8. Verification checklist for the coding agent</h2> | |
| <div class="panel ok"> | |
| <ol> | |
| <li>Space builds and UI loads at <code>kwabshug-visuallearningidea.hf.space</code></li> | |
| <li><code>/gradio_api/mcp/schema</code> lists exactly the 4 planned tools (no helper leakage)</li> | |
| <li><code>unfold_mesh_to_papercraft</code> on a bunny OBJ returns valid SVG(s)</li> | |
| <li><code>parse_sentence_to_items("make a box with a lid")</code> returns valid serial IR with β₯1 <code>unresolved</code> ambiguity note</li> | |
| <li><code>items_to_fold</code> on that IR produces a FOLD doc that <code>simulate_fold</code> accepts</li> | |
| <li>Tool appears in HuggingChat MCP panel after adding the Space in settings</li> | |
| </ol> | |
| </div> | |
| <h2>9. Lessons from the reference UI build (serial player + scene artifact)</h2> | |
| <div class="panel"> | |
| <p>The cat-sun demo (serial reading tab + scene tab, Three.js) was built end-to-end in the preview sandbox. These lessons are now folded into the contract above:</p> | |
| <ul> | |
| <li><b>The serial reading is the product, not a sidebar.</b> The flat tokenβitem timeline ("the β ?", "cat = model", "sat β pose + surface + support") is the deliverable format of <code>parse_sentence_to_items</code>; the 3D scene is downstream. Both views render from the <b>same ledger</b>; each view has its own independent stepper. Default view: serial.</li> | |
| <li><b>Every item needs a <code>stage_direction</code>.</b> The demo's choreography was hand-coded β possible only because the sentence was known in advance. A generic player requires each item to carry its reveal payload (spawn / move / orient / couple / mark). Now in the tool contract.</li> | |
| <li><b>Model builders must be factories, not sculptures.</b> The demo shares <code>buildForm / buildPose / buildSupport</code> between the live scene and per-word snapshot images. The Space equivalent must be data-driven parameterization (item params β geometry). Otherwise every new sentence requires hand-modeling β <b>the biggest current gap</b> and the reason Phase 2's IR schema must be designed for buildability, not just describability.</li> | |
| <li><b>Per-word model snapshots are cheap and powerful.</b> Static images rendered once via an offscreen renderer give each token card a visible model (form-only cat for "cat", posed cat on ground for "sat", sun disc for "sun", full shadowed configuration for "shone"). The Space can pre-render snapshots server-side, or the static front end renders them client-side from the same builders.</li> | |
| <li><b>Attribute commits to tokens.</b> "sat" commits three items; determiners commit none but open unresolved "?" entries. Without per-token attribution the serial view is unreadable β this is why <code>tokens</code> is now a first-class output key.</li> | |
| <li><b>Separate "exists" from "relates".</b> The demo deliberately pauses between "sun exists" (item 6) and "shone β coupling ON" (item 7): light without relation is not a configuration. Keep these as distinct items β the pause is where 2D and 3D thinking diverge.</li> | |
| <li><b>LLM ledgers will be incomplete β validator needed.</b> The demo's sky color did not follow sun elevation. A schema check catches this deterministically; hence the new validator task.</li> | |
| <li><b>Unresolved "?" entries are the discussion agenda.</b> Each determiner opened a question with a recorded default and alternatives β that list is what the conversation loop interrogates before trusting the 3D.</li> | |
| <li><b>Front end is covered; deploy it as <code>sdk: static</code>.</b> The player UI is proven in-browser (Three.js via CDN works in both the preview sandbox and static Spaces, which are free and run no compute). The Space's only job is to emit the items the browser cannot make. See companion doc: General Tool Space handover (artifact: toolhub-handover).</li> | |
| </ul> | |
| </div> | |
| <footer>Generated from a working session between KwabsHug and HuggingChat Β· Facts verified against live HF Hub state on 2026-10-23 Β· Revised after reference UI build Β· Checkbox state is session-local (reloads reset it)</footer> | |
| </div> | |
| </body> | |
| </html> | |