Snow House — Codex Session Report


GPT-5 Codex reconstructed 雪屋.litematic procedurally using MCIO, iterating 8 times over ~75 minutes on 2026-07-07.

Contents

Key Results

12,564correct blocks
79.3%accuracy
3,276total errors
−13.1%error reduction
8iterations
112shell commands
22×30×24structure size
520lines of code
21functions
55materials
103loops
4,702AST nodes

Source: 雪屋.litematic (Version=5, 3,616 non-air blocks). Candidate scored against full 15,840-cell volume via mcx diff.


Agent Pipeline

Pipeline +
flowchart TD
    A([User: recreate 雪屋.litematic]) --> B[MCX: load source]
    B --> C[MCX: inspect size / palette / projections]
    C --> D[Python: analyze layer maps]
    D --> E[Write snow_house.py with MCIO Sketch API]
    E --> F[Run generator → snow_house.litematic]
    F --> G{mcx diff}
    G -->|errors high| H[Identify worst component]
    H --> I[Patch generator rule]
    I --> F
    G -->|errors stable| J[Save intermediate snapshot]
    J --> K([Final: snow_house.litematic ✓])

    style A fill:#F2E5DA,stroke:#B39A8F,color:#554037
    style K fill:#F2E5DA,stroke:#B39A8F,color:#554037
    style G fill:#DBC8B8,stroke:#B39A8F,color:#554037
        
Codex agent's iterative schematic reconstruction loop. 112 exec_command calls total; MCX diff ran 9 times.

Score Progress

Fig 1. Correct blocks and total error count per iteration. Iteration 2 was a regression (broad interior fills increased blockstate errors).
Fig 2. Error breakdown: wrong occupancy vs. wrong blockstate per iteration. Removing leaf blobs (iter 4) and roof end-caps (iter 7) each produced clean drops.

Iteration Log

Iter Change Correct ↑ Wrong Occ ↓ Wrong State ↓ Total Err ↓ Delta
0First procedural generator12,0712,6901,0793,769baseline
1Stepped front roof rows12,2182,5661,0563,622−147
2Add broad dense interior fills11,9612,4061,4733,879+257 regression
3Remove broad filler, keep porch12,2062,4581,1763,634−245
4Remove noisy leaf blobs12,3552,3821,1033,485−149
5Add upper front facade rows12,4022,2791,1593,438−47
6Tune farm crop / water / log pattern12,4912,2631,0863,349−89
7Remove overly broad roof end-caps12,5642,2701,0063,276−73

Total improvement from iter 0 → 7: −493 total errors (−13.1%). Click column headers to sort.

Obstacles and workarounds
  • python and apply_patch hit sandbox /dev/.git mount errors → switched to project virtualenv and perl -0pi for narrow edits.
  • Source 雪屋.litematic is Litematica Version=5; MCIO expected Version=7 → decoded via NBT/MCIO containers; used MCX compatibility layer for diff verification.
  • Broad procedural fills improved occupancy but severely increased blockstate errors → narrowed to repeated structural features only.
  • Decorative leaves created mostly extra/wrong blocks → removed leaf blobs in iter 4.
  • Roof end-cap rows were too broad → removing full rows cut blockstate errors significantly in iter 7.

Schematic Viewer

5 intermediate snapshots + final. Each saved after the iteration's generator ran.

v0 — First procedural generator. Broad rectangular roof bands, no interior trim. 3,769 total errors.

v0 (iter 0) — 3,769 errors

v1 (iter 1) — 3,622 errors

v2 (iter 3) — 3,634 errors

v1 — Stepped front roof. v2 — Dense interior added then narrowed (regression recovered).

v1 (iter 1) — 3,622 errors

v2 (iter 3) — 3,634 errors

v3 (iter 4-5) — 3,438 errors

v4 / final — Farm tuning + roof end-cap removal. Best score: 3,276 total errors.

v3 (iters 4-5) — 3,438 errors

v4 / final (iters 6-7) — 3,276 errors

Final — 12,564 / 15,840 correct


Code Quality

Version Lines ↑ Functions AST Nodes Loops Assigns Wrong Total ↓
v0 — iter 0438193,99373723,769
v1 — iter 1493204,65693793,622
v2 — iter 3452204,15682723,634
v3 — iter 5492214,47691833,438
v4 / final520214,702103833,276

AST nodes measured via ast.walk(ast.parse(src)). Loops = ast.For + ast.While nodes. No hard-coded coordinate arrays; all geometry is procedural.

Fig 3. AST complexity and loop count across versions. Complexity generally grew as more structural rules were added.
Function breakdown (final generator)
build() — top-level orchestrator set_block(y,z,x,mat) — single-cell placement wrapper box(y0,z0,x0,y1,z1,x1) — solid fill line_y / line_z / line_x — axis-aligned runs blocks(positions, mat) — batch placement pillar(y0,y1,z,x,mat) — vertical column add_farm_and_yard() — farmland, crop rows, water channels add_lower_house() — ground floor timber shell add_upper_house() — second floor + roof base add_main_roof() — stone-brick gable roof (stepped) add_front_roof() — stepped front gable rows add_chimney() — brick chimney at z=14-17, x=10-12 add_spruce_details() — windows, trapdoors, fences, lanterns add_dense_source_features() — porch, front hut, interior details add_upper_front_facade() — y=7-10 facade rows (iter 5) crop_for(z,x) — per-cell crop selector (wheat/carrots/potatoes) framed_wall_x / _z — plank wall with log-frame posts timber_floor(y,z0,z1,x0,x1) — oak plank floor layer

Tool Usage

Shell commands

112

exec_command calls total

MCX diff runs

9

Used to score each generator iteration

Plan updates

2

update_plan + update_goal

Fig 4. Breakdown of the 115 total tool calls by category.
Commands used (from agent summary)
  • mcx clear / load / info / print / query / diff / select — schematic inspection and scoring
  • rg — fast text/file search within repo
  • sed — inline file inspection
  • git status — workspace state checks
  • Python scripts via project virtualenv with PYTHONPATH pointing at local MCIO
  • yapf — code formatting after edits
  • perl -0pi — narrow in-place edits when apply_patch failed
  • pwd, ls — workspace orientation

Observations

LLMs can infer 3D structure from voxel data

The agent identified a chimney without any label or metadata in the schematic. The inference came entirely from raw block coordinates and material IDs:

  • 51 minecraft:bricks blocks found via mcx query blocks --id minecraft:bricks in bbox y=13..21, z=13..17, x=9..12 — a vertical protrusion above the roofline.
  • 3 campfires (minecraft:campfire) embedded in the same upper brick stack at y=13..19, z=14..17, x=11..12 — commonly used for chimney smoke/fire detail in Minecraft builds.
  • Layer maps showed a BBB / B.B brick silhouette capped by brick slabs from y=13 up to y=21 — a classic chimney cross-section.

No metadata said "chimney." The agent read material, position, shape, and campfire placement together and produced a spatially-grounded label — the same kind of inference a human builder would make. This suggests LLMs can reason about 3D voxel geometry meaningfully when given the right coordinate-indexed representation.

The generator's resulting add_chimney() function targets exactly z=14–17, x=10–12, confirming the inference was precise enough to produce correct structure.

LLMs prefer flexible diagnostic tooling over narrow APIs

The agent used mcx as an authoritative loader, inspector, and scorer — but wrote custom Python scripts for the diagnostic loop. Why:

  • mcx diff produces aggregate counts (wrong_occupancy, wrong_blockstate) — enough to score an iteration, but not enough to answer "which layers got worse?" or "which material category dominates the errors?"
  • The 240-blockstate palette caused mcx print output to fold/truncate; a custom script could collapse blockstates into semantic categories (planks, stone_roof, logs, farm, leaves).
  • Per-layer and per-category breakdowns — e.g., "leaves mostly extra/wrong," "farm errors concentrated in crop/water/log bands," "roof end-caps causing wrong states" — required iteration-level data the custom script provided in one compact report.

Equivalent MCX-native analysis would require many mcx select --bbox + mcx diff calls per layer and per component — more verbose and more brittle than one parameterized script over a 22×30×24 array.

The pattern: LLMs gravitate toward ad-hoc scripts when the built-in tool's output granularity doesn't match the diagnostic question being asked. Richer query interfaces (per-layer diff, semantic block grouping) would reduce this gap.


Final Generator

Key material definitions from snow_house.py (55 unique materials, all via MCIO canvas.material() — no hard-coded blockstate strings in placement code).

from mcio.sketch import LitematicCanvas, Material OUTPUT_PATH = Path("snow_house.litematic") SIZE_YZX = (22, 30, 24) def build(output_path: Path) -> None: canvas = LitematicCanvas(size_yzx=SIZE_YZX) oak = canvas.material("minecraft:oak_planks") spruce_log_y = canvas.material("minecraft:spruce_log", axis="y") roof_east = canvas.material("minecraft:stone_brick_stairs", facing="east", half="bottom", shape="straight", waterlogged="false") farmland = canvas.material("minecraft:farmland", moisture="7") wheat = canvas.material("minecraft:wheat", age="7") # ... 50 more materials add_farm_and_yard(canvas, ...) add_lower_house(canvas, ...) add_upper_house(canvas, ...) add_main_roof(canvas, ...) add_front_roof(canvas, ...) add_chimney(canvas, ...) add_dense_source_features(canvas, ...) add_upper_front_facade(canvas, ...) add_spruce_details(canvas, ...) canvas.save(output_path, name="candidate")
Farm crop selector (procedural, no coordinate dump)
def crop_for(z: int, x: int) -> Material: """Return crop material based on plot position.""" if x < 11: # left plot return potatoes elif z < 10: # right front return carrots else: # right back return wheat # Deterministic crop bands replace random/mixed loops for z in FARM_Z_RANGE: for x in FARM_LEFT_X_RANGE: set_block(1, z, x, farmland) set_block(2, z, x, crop_for(z, x))
Stepped front roof (key fix in iter 1)
def add_front_roof(canvas, ...): """Stepped gable rows z=4..11 matching source profile.""" slopes = [ (10, 4, 4, roof_east), # row z=4, peak y=10 (11, 5, 5, roof_west), (12, 6, 6, roof_east), (13, 7, 7, roof_west), # ... ] for (y, z, x_start, mat) in slopes: for x in range(x_start, MAIN_X_RANGE.stop): set_block(y, z, x, mat)

The agent avoided brute-force coordinate dumps throughout. Every structural element is expressed as loops, formulas, or helper functions — matching the AGENT.md scoring rubric.