Landing now has two entries again: "Quick Start →" (restored Start → Lab with
seeded parents) and "✏️ Build from scratch" (re-added). Both route through the
Lab before any splice can happen, which mounts the lazily-mounted screen_lab and
fixes the blank-screen bug on the reveal's "← Back" (next_btn → screen_lab: an
unmounted Lab, half-mounted by do_fuse's slots_view/tree_view writes, rendered
blank).
Splice Bench input box is now fully model-free in both runtimes: LlamaCpp
generate_creature (pick_exemplar only) and edit_creature (keyword → assemble_part,
dropped the _freeform_edit_creature model fallback) match MockRuntime. The only
model call left in the app is fuse_creatures (Splice).
Reveal Share/Back are hidden over the fuse loading state via CSS
(.screen:has(.buddy-reveal-row) .buddy-reveal-actions) instead of gr.update(
visible=), which races on the freshly-revealed lazy column.
Docs/wiki: README hook + "How it works" + How-to-play and wiki system-overview /
index / log / grad…
feat(landing): Start opens the from-scratch bench, drop the second button
The landing "✏️ Build from scratch" button is removed; Start → now runs the
FreeLand chain (freeland_open → freeland_fill), opening the Splice Bench with
both slots empty instead of the Lab pick screen. Dead #buddy-freeland-btn CSS
dropped; the in-Lab Build-from-scratch button is unchanged.
Docs follow the code: rewrite README "How to play" and correct the wiki
(system-overview, index) to drop the long-removed "🪄 Freeform Lab" screen
(do_freeform / free_enter_lab no longer exist) — drawing-from-text now happens
in the bench's per-side box.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore(rename): point Space URL/remote at build-small-hackathon/hatchimera
The Space was renamed build-buddy -> hatchimera. Update SPACE_URL (the
share/OG target for X, Facebook, LinkedIn, native share), the wiki Deployment
note, and the CLAUDE.md verification wrapper URL.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
refactor(runtime): single Gemma 4 12B model + Hatchimera rename
Drop the dual Qwen2.5-3B / SmolLM2-1.7B recipe-model setup. Every AI moment —
freeform generation and hatch fusion — now runs through a single model,
Gemma 4 12B, the only family that draws hard voxel forms in the model-selection
spike. LlamaRuntimeConfig defaults and env overrides collapse onto the freeform
model; the now-dead fallback-model fields and Qwen/SmolLM references are removed.
Retitle the project to "Hatchimera — Voxel Pet Fusion" across the README and
wiki, and align the wiki (deployment, hackathon, overview, local-dev, voice)
with the single-model story.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(wiki): dot-grid multiply fix + the two bench hint vocabularies
- voxel-rendering: the scissor canvas occludes the dot-grid on real Chrome;
mix-blend-mode:multiply is the fix.
- system-overview: bench chips run the edit path (match_part -> parts catalog)
while empty-slot input/placeholder run the generate path (pick_exemplar, 6
shapes, quadruped fallback); verify hint text against the matching function.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(wiki): record client-side selection badge + the FAB parent-Column reset
Two Gradio embed rules verified while merging the FreeLand branch:
- on_select never re-renders the tree; the A/B badge is applied client-side so
selecting does not reset the canvas pan or reboot the live-3D nodes (no flash).
- A child visible=False bundled with its parent Column's visible-toggle is
dropped (the bench FAB reappears on reveal/share Back); fix is a chained .then.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
merge: bring main's part-assembly-edit feature into the FreeLand branch
Merges main (the parallel parts-catalog + keyword/parametric assembler edit
path, single-context scissor tree rendering, runtime selector rework) into the
FreeLand-from-scratch / Random / draft-creature / canvas-and-nav-polish branch.
fusion_ui.py and voxel_embed.py auto-merged cleanly (the two efforts edited
disjoint regions); wiki/log.md was the only content conflict (append-only on
both sides, kept both). Two semantic artifacts the line-merge could not catch,
both fixed and verified locally:
- Canvas pan dead-zone: this branch's installCanvasPan suppressed panning when a
drag began on a node (it assumed per-node OrbitControls to rotate). main's
scissor renderer draws the tree through ONE pointer-events:none context with
auto-rotate, so node-drag rotated nothing AND no longer panned. Now a drag
anywhere pans (matches main's installTreeInteractions intent); the __buddyPanned
threshold still keeps a clean tap selecting.
- Splice Bench FAB resurrected on reveal -> Lab Back: …
docs(wiki): record part fusion/accumulation + symmetric straddle
system-overview.md: parts fuse not stack (_part/_pc tags survive the
freeform_genome -> Lineage round-trip; display cfg strips them harmlessly), and
symmetric parts straddle the body by mirroring across the body centre.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
voxel-rendering.md: rewrite the WebGL context-cap strategy around one shared
context drawn via the scissor test (tree installTreeScissor + report pages'
voxel-cards.js), with the three load-bearing gotchas (canvas behind content,
full clear per frame, re-key on real canvas child). system-overview.md: record
the box-edit path going model-free (keyword parser + parametric assembler,
MiniCPM selector removed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build a buddy from scratch and splice it, reworking the Lab/bench flow.
- FreeLand: landing "Build from scratch" button opens the bench with both
slots empty; each empty slot generates a freeform creature from a typed
description (runtime.generate_creature, exemplar fallback). The bench is now
the single A/B workspace: a slot is either a tree-picked creature or one
built from scratch.
- Advance relaxed from two picks to >=1: the unselected side becomes a
from-scratch panel; splice is gated until both slots are filled.
- 🎲 Random per slot: fills with a random Compendium template, kept distinct
from the other slot (no duplicate sides).
- Draft creatures: bench candidates (Random / from-scratch) are drafts hidden
from the family tree until a splice commits their two parents, so re-rolling
no longer litters the tree with orphan "ancestors" (Creature.draft, serialized).
- Bench Back returns to its origin (landing for FreeLand, Lab otherwise) via a
bench_origin State, ins…
docs(wiki): record measured Gemma-4-12B freeform timing on ZeroGPU
deployment-strategy.md: add "Freeform 12B timing" — reload ~3s, ~17-22 tok/s
with grammar (25-41s/call), grammar ~2x cost (16.7->35.9 on/off, intrinsic to
grammar-constrained decode), the duration=30->60 abort fix, the 1500-token >60s
edge, and that ZeroGPU aborts a 3rd GPU acquisition stacked in one demo.load
handler. Bump wrapper list to three @spaces.GPU wrappers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test+docs: repair edit_creature 4-tuple test; wiki for canvas + one-call tweak
A parallel commit landed the single-call edit_creature change (now returns
(genome, boxes, tweaks, status)) but left test_freeform_edit.py unpacking the
old 3-tuple, so the committed test failed. Update the unpack + assert the 4
returned tweaks. Full suite: 81 passed.
Wiki:
- voxel-rendering.md: "Lab canvas: pan + viewport-pooled live 3D" (live nodes
kept under the WebGL context cap by cullCanvasNodes; the setPointerCapture
click-swallow trap; cached pan offset + dot-grid shift; JS bench-x centering),
refreshed the context-cap failure mode, added the 0x0 size-guard fix (blank
Splice Bench) + culled-stage disposal, retired the obsolete inspect-modal note.
- deployment-strategy.md: "A bench tweak is ONE GPU call, not two" — edit_creature
returns geometry + 4 hints from a single completion (combined EDIT_SCHEMA),
removing the per-tweak suggest_tweaks GPU call (likely "Running on ZERO" stuck
cause), with the fallback top-up and revert path.
Co-Authored-By: Claude Opus 4.8 (…
docs(wiki): note the English-only exception for fallback.py CJK match tables
Document that voice_edit_genome / edit_boxes_fallback match input against
keyword tables holding CJK synonyms (load-bearing data, not comments), so a
future English-only sweep does not strip them and break Chinese command input.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(ui): unify live render with share GIF, recolor text, simplify Lab
Render (live setupVoxel now matches buildBloodlineGif):
- bright hemisphere/key/fill rig + exposure 1.4; head crown no longer dark
- solid=true build mesh so cube-by-cube assembly is solid, not a hollow shell
- real PCFSoft shadow map + ShadowMaterial catcher (thumbnails keep the blob)
- near-frontal "hero" initial camera (0.46/0.40/1.16) instead of 3/4 isometric
Fixes:
- inspect modal passes boxes through, so freeform creatures render their real
geometry instead of falling back to the archetype chick ("purple chicken")
- suppress Gradio's stuck orange .generating border (kill the pulse keyframe
animation, not just border-color)
Lab/UI:
- remove "Draw a new buddy" and the whole Freeform Lab screen (+ handlers/CSS)
- remove the visible A/B slot cards; keep a hidden data-ready carrier for
auto-advance; selection shown by the tree A/B badges
- add "Open the Splice Bench" button for manual (re-)entry after Back
- center the Compendium action; restyle the inspect magnifier button
- …
- voxel-rendering.md: new "Freeform path (box-layout) — granularity is fixed,
composition is the AI's" section. The AI emits rectangular boxes (not voxels);
resolution is system-fixed (integer grid, unit 0.96^3 cubes, no sub-voxel
detail); two distinct size limits — per-box hard 1-8 (boxes.repair_boxes _MAX=8)
vs whole-creature soft ~16 cells (prompt guidance, unenforced) — with the LEGO
brick-vs-model analogy. AI controls composition/detail, never resolution.
- model-selection-spike.md: "Breadth validation" — Gemma 4 12B through the
production code path passes all three AI features (20/20 species, 5/5 freeform
fusions, 5/5 mainline genome-edit tweaks on Gemma).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(wiki): clarify Sharing is Caring bonus quest (any trace accepted)
Record the official Discord clarification (organizer Dean + HF/Gradio's pngwn,
2026-06-08): the ideal trace is from the model running at runtime, but any
trace (local dev, coding-agent, or runtime) is accepted and a runtime agent
trace is not required. Add the Discord thread to sources.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(wiki): describe the report's two views (Gallery + Matrix)
The Reusable tooling note in model-selection-spike predated the Matrix view and
only described the live-context Gallery strategy. Document both views and the
two rendering strategies (Gallery: live WebGL contexts + reconcile; Matrix:
static offscreen-renderer snapshots), and bump the sweep to 20 models.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consolidate the throwaway scratch/voxel-spike/ exploration (11 scripts,
scattered HTML viewers) into a tracked, reusable tool so the next model
test does not start from zero.
tools/voxel-model-eval/:
- core.py: pure base (SYS prompt, 8 themes, BOX_SCHEMA, extract_json,
voxelize, metrics); no model loading, llama_cpp never imported here.
- models.py: the editable (label, repo) list.
- exemplars.py: few-shot reference layouts for --fewshot.
- eval.py: single CLI; one model at a time (download -> grammar-enforced
test -> optional --delete-after -> merge); llama_cpp imported lazily so
the pytest suite runs without the sibling venv.
- report.html: Three.js viewer with a theme filter; live WebGL contexts
are reconciled by distance-to-viewport-center on scroll (fixes the
evict-furthest blanking bug where still-visible cards never re-mounted).
- report_data.js: committed 19-model x 8-theme sweep so the report opens
populated.
Align voxelize() to JS Math.round (round half up) so P…
Add an opt-in freeform path where the model draws raw box-layout geometry
({name, boxes:[{x,y,z,w,h,d,color}]}) instead of the recipe, so creatures can
take cross-form shapes (five arms, a house on the head) the closed recipe
vocabulary cannot express. Gemma 4 12B (the model-selection spike winner),
grammar-enforced, seeded with a hand-authored reference exemplar.
Freeform creatures are first-class: they enter the family tree and breed. A
splice routes to a Gemma "merge two creatures" call when either parent carries
boxes (freeform x freeform and freeform x recipe both yield a box child);
otherwise the recipe fuse runs. Fallbacks (fake runtime / model failure) use a
reference exemplar or a deterministic box merge, so the app never renders empty.
- genome: optional Genome.boxes + freeform_genome(); round-trips, recipe
creatures stay box-free
- prompts: BOX_SCHEMA, build_freeform_messages, build_freeform_fuse_messages
- runtime: generate_creature / fuse_creatures on Gemma via per-cal…
docs(wiki): consolidate official award info in hackathon-context
Record the Field Guide's official wording for the six bonus badges and the
named sponsor prizes (Best MiniCPM Build / Best Use of Codex / Nemotron
Hardware Prize / Best Use of Modal) with their one-line requirements and
amounts. Drop the project-side eligibility analysis; keep this page to
official information only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(wiki): verify submission cutoff against official Field Guide
The Field Guide app's live countdown reads "Jun 15 · 23:59 UTC",
authoritatively confirming the 23:59 UTC submission cutoff already
recorded. Added the Field Guide URL to sources and logged the check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- response_format must be {"type":"json_object","schema":...}; the OpenAI-style
"json_schema" is silently ignored by llama-cpp-python, leaving fuse/tweak
unconstrained and forcing every edit onto the keyword editor.
- Default model is now Qwen2.5-3B (6/7 schema incl. Chinese on the pinned
0.3.19; Llama-3.2-3B scored 0/7 even after the fix). Recorded the 3B-vs-7B
trade-off and that Qwen2.5 runs on 0.3.19 with no llama-cpp upgrade.
- Documented ZeroGPU quota-exhaustion symptoms (warmup failures, CPU drop to
~1.9 tok/s). Verified against live Space run logs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix: dedupe coincident voxel cells to kill Z-fighting
voxelsFromGenome layers body + features + parts by pushing cubes, and several
land on the same cell (e.g. the earsnout snout + its dark nose at (0,hyB,frontZ);
a horn part on the ears cell). Two cubes at one position are fully coplanar, so
the depth buffer flickers — the stripes seen on a dog. De-dupe cells by x,y,z
before returning (last writer wins, so parts layer over features), removing the
coincident geometry. Verified: 0 coincident positions across dog/chick/turtle/
horse; clean render. Documented in wiki/voxel-rendering.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(wiki): theme-independence replaces the light-redirect lock
Rewrote gradio-theme-locking.md to the no-redirect, token-pinning approach
(identical light/dark render), keeping the replaceState trap and head= delivery
notes; updated the index line; logged the change and the .screen-landing
:not(.hide) regression fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs: always verify on the Space via the wrapper URL; wiki backdrop updates
- CLAUDE.md Phase 5: when verifying on the Space, always open the wrapper URL
(huggingface.co/spaces/...), never the bare *.hf.space iframe origin. The bare
origin runs in a fixed viewport outside the auto-resizing iframe and masks
iframe-context bugs (e.g. the min-height:100vh runaway only reproduces in the
wrapper). Interact with the cross-origin iframe via Playwright frame locators.
- wiki/voxel-rendering.md: corrected the backdrop section to the final fixed
full-bleed design (keeping the 20px-collapse and 100vh-runaway as cautionary
history), the prose margin:auto centering trap, and the gated-reveal fade.
- wiki/log.md: logged the above.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(wiki): record HF-verified backdrop, tweak no-op, and Playwright fixes
- voxel-rendering: landing backdrop collapse (host .block -> 20px strip) +
the screen-landing/full-bleed-host fix; note this Gradio build has no
.gradio-container (root is .main.fillable.app).
- system-overview: AI tweak silently kept the original genome on a valid-but-
empty real-model edit; _same_look fallback fix. Plus driving the live Space
with Playwright via the cross-origin *.hf.space iframe origin.
- gradio-embed-integration: correct the stale modal-tweak-bridge claim; the
tweak is now an inline gr.Textbox.submit and the modal is inspect-only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(wiki): record game-flow redesign, bridges, mount race, landing backdrop
- system-overview: three-screen flow + selection data flow; drop stale
voice/asr.py; add mount-race and Git-LFS gotchas; link related pages.
- gradio-embed-integration: selection/tweak JS->Python bridges; the
visible-toggle + write-value mount race (-> split into .then(populate)).
- voxel-rendering: offline transparent-PNG export (window voxelizer hooks +
alpha renderer) and the landing infinite drifting grid backdrop.
- index + log updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore: delete dead asr.py; rewrite voice wiki for text command input
asr.py (faster-whisper wrapper) was never imported by the app — dead code
since the initial commit. Voice input was already replaced by a text command
box (in b9035f4), so remove the unused module. Its deps were dropped in
edbaf97.
Rewrite wiki/voice-input-asr.md → "Command Input — Text": the live path is a
visible textbox + Apply button reusing on_command (LLM interpret), verified
locally via Playwright. Update index.md and log.md to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat: rebrand to Hatchimera with daytime light UI
UI / theming:
- Lock the app to Gradio's light theme (was dark); daytime palette across
the chrome — panels, genome card, family tree, command bar.
- Voxel stages now render the creature against a gradient sky background
only; removed the dark backdrop, grass/podium, clouds, bushes, and
contact shadow per design iteration. Single-creature framing per stage.
Rename:
- Buddy Splice Lab -> Hatchimera across the header H1, browser tab title,
social share text, and the README / HF Space title.
- Add a one-line subtitle: "A small local AI splices two voxel critters
into a one-of-a-kind chimera."
Input:
- Left-parent tweak runs through a typed natural-language command box
(Enter or Apply), interpreted by the model.
Docs / wiki:
- Update gradio-theme-locking (dark -> light lock; mechanism unchanged)
and append to the wiki log.
- Add brainstorming specs for the stage backdrop and the text command.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore: drop unused faster-whisper/ctranslate2/requests deps
Voice posing runs entirely in the browser via the Web Speech API
(fusion_ui.BROWSER_VOICE_JS); the server-side faster-whisper path in
src/buddy_fusion/asr.py is never imported by the app (verified: grep finds
no `import asr`, git history shows fusion_ui never imported it). The
faster-whisper / ctranslate2 / requests pins only served that dead code, so
remove them as dead weight on the Space image. requirements.txt keeps a
restore recipe in comments.
Document the finding in wiki/voice-input-asr.md (corrects an earlier draft
that wrongly claimed the Space runs faster-whisper).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix: spin voxel creatures around their own center, not the world origin
The live turntable rotated `mesh.rotation.y`, but the mesh sits at the
world origin while the camera aims at the bounding-box center. Asymmetric
archetypes (e.g. the horse, whose long body + front-protruding head puts
its centroid at z~2) orbited the origin as they spun and slid off-frame —
visibly jamming the horse against the right edge of its stage.
Wrap the mesh in a pivot Group at `center` with the mesh offset by
-center, and rotate/scale the pivot in all three render paths (live
turntable, reveal pop, static thumbnail). The creature now spins and
pops in place around its own center.
Also add wiki/voxel-rendering.md documenting the voxelizer, the
bounds-driven camera, the turntable pivot rule, and the thumbnail
shared-renderer context cap; link it from the wiki index.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore: port AI/dev tooling and wiki knowledge from build-a-buddy-hf
Fill the gaps the wiki automation system depends on and bring over the
reusable Gradio/HF Space knowledge, adapted to the buddy_fusion package.
- Add CLAUDE.md (workflow rules: English-only, never-auto-push to the
Space, brainstorm->plan->worktree->execute->verify, local launch
scripts), AGENTS.md, and templates/wiki-page.md.
- Add five reusable wiki pages adapted to this project's files:
hackathon-context, local-dev-runtimes, deployment-strategy,
gradio-embed-integration, gradio-css-scoping, gradio-theme-locking.
- Link the new pages into wiki/index.md; log the change in wiki/log.md.
- Drop two dead env vars (BUDDY_CONTROLLER_DNA_MAX_TOKENS,
BUDDY_ACCIDENT_REPORT_MAX_TOKENS) left over from the old game in
scripts/start-local-real-model.sh; the current runtime never reads them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Install the llm-project-wiki knowledge system into the repo:
- Claude Code + Codex SessionStart/Stop hooks and PreToolUse write gate
- wiki-review skill for both agents
- wiki/ seeded with a real Build Buddy system overview + index
Set write_policy to "auto" and translate the gate's user-facing
messages from zh-TW to English.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>