feat(dsl,compiler): valley + cherry-valley horizon — surround generator, biome layer, tree layer (spec-0026 W-B, task #155) - #259
Conversation
|
CI attribution (verified by reproducing each red at the foundation tip, 4599ad2, with this slice absent — all four fail there identically):
Nothing in this slice's own surface is red: clippy |
…isson tree layer, tile NBT synthesis (spec-0026 W-B) Standalone core for the valley/cherry-valley horizon base, ahead of the foundation branch's plug-in contract: - crates/compiler/src/surround.rs: the mountain-annulus generator. Smoothed- rectangle radial profile with domain-warped distance, Musgrave-style ridged multifractal rim (in-house value-noise family, ideas-only composition), flat gap floor, even-step height quantization (no 1-block risers exist anywhere, so no standable staircase can form — by construction), plus a generator-side flood proof that the gap floor never reaches beyond the crest line (trees included as solids). - Tree layer: deterministic Bridson-family Poisson-disk sampling (ideas-only, no trig — libm sin/cos is not bit-stable across hosts; ring candidates come from square rejection sampling), trees only outward of the crest line. - Cherry-valley is a parameter row: flora/palette are parallel id tables on one code path; a unit test asserts a same-seed cherry emission maps back to the oak emission byte-parallel (positions/states identical, ids mapped). - Tiles: ≤48×48 XZ, vertically sliced to ≤48, air-inclusive vanilla structure NBT, gzip mtime 0 (ADR-0006); per-band /fillbiome rects exported. - edit.rs noise primitives (mix64/hash01/fade/value_noise) become pub(crate) so the surround module composes the one noise family instead of forking it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tifractal (ideas-only, spec-0026 valley) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…f helper, vista camera - Tree domain is now exact: a trunk is accepted only if every cell of its canopy footprint clears the crest line — no guessed slack racing the domain-warp gradient (the folklore margin red-flagged by its own test), and no canopy is ever sheared by a clip. - Crest band biased grassier so the tree line crowns the rim silhouette the scene actually sees (for cherry-valley: 山上的樱花树 as the vista). - ValleySurround::verify_unclimbable(&nav::World): the spec §5 empirical proof over the assembled world (flood from gap-floor starts; any standable cell beyond the crest line is the violation) — plus a unit test that runs it over the decoded serialized tiles. - ValleySurround::vista_camera(): establishing-vista eye/look pair for the render plan (spec §6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ugh plan/emit/assembled, biome paint, DW0369, vista (spec-0026 W-B) Plug the valley surround generator into the W-A foundation contract: - horizon.rs: base_implemented(valley)=true; valley walk_ref_y = 64 (gap floor top 63 — like flatland, a valley relocates nothing vs void). - validate.rs: DW0141 reserved arm deleted for valley/cherry-valley (summit/sky stay reserved), per the contract's slice procedure. - plan.rs: Plan.surround (SurroundPlan) — tiles generated at plan time from stream 'horizon/valley', deliberately NOT an AreaPlacement so boundary-region derivation, lighting scope, anchors and analysis never see them; Plan::placed_pieces() is the explicit placement/model iterator. - emit.rs: tiles ship/forceload/place/verify through the existing bootstrap; per-band /fillbiome in setup_finish wrapped in a gamerule max_block_modifications raise/restore; DW0369 un-climbability proof (nav flood from the gap floor over the assembled — edited when a stage-7 script exists — world). - assembled.rs/main.rs: surround tiles enter the voxel model and the structures map (generated bytes, never disk). - render_plan.rs: one establishing 'vista' shot per surround build. - tools/check-flora-parity.py + tests/v09_valley.rs: criterion 6 (cherry-valley is a parameter row — same-seed emission diff confined to flora/palette block ids + biome id; manifest.json exempt as a declaration mirror) and criterion 1 valley row (double-build byte-identity), both process-level. - docs/reference/compiler.md: DW0369 catalog row + valley behavior section. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… stack is green The foundation commit (4599ad2) landed the horizon surface with 'tests/docs follow'; PR CI red-flagged exactly that debt. Paid here, on the stacked branch, so the pair is verifiable as a unit: - fmt: crates/dsl/{lib,stages}.rs + prefabs/tidal-keep-generator (workspace and generator fmt --check both clean again). - cli::version_line: asserts dsl 0.9.0 (spec-0026 raised it). - docs/reference/compiler.md: DW0364 / DW0366 / DW0367 catalog rows; tools/check-dw-codes.py fully green (191 codes documented + covered). - New coverage fixtures (spec-0026 acceptance criterion 2, by code): DW0366 (valley ratio 5 → validation exit 1), DW0367 (walk_y stripped from prefab metadata → build exit 3), DW0364 (the #149 shape: lying walk_y=5 floods the interior with no waterline_y declared → build exit 3). - cli::ocean_areas_sit_on_the_sea_level_datum: hello-room (walk_y 1) now correctly lands at 62 (walk plane 63, dry — the very placement the #149 class got wrong); the island row (walk_y 3 → 60) needs a real island fixture and is noted as covered by the nobodys-cave content build — a doctored hello-room asserting walk_y 3 is a lie DW0364 rightly refuses. - cli::ocean_waterline DW0344: the datum-consistent declaration is waterline_y = walk_y − 1 (hello-room: 0). - edit::edit_ocean_breach_strands_the_player_dw0322: the datum fix retired the old scenario shape (a floor breach at 63 is the canonical escapable beach); rebuilt as a cliff piece (walk_y 0 → breach lip at 64, a wall to a swimmer) so the stranding proof is still exercised — and DW0364 stays green because nothing stands below the flood line. No check weakened: every changed assertion now states the spec-0026 law instead of the retired global-datum folklore. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ws, pin the valley un-reservation The foundation's final commit (370a45b) landed its own DW0364/0366/0367 catalog rows and datum-test fixes (converging on the same walk_y-0 cliff fixture this branch had built): its versions win, the duplicates this branch carried are dropped. Its reserved-bases test still asserted valley reserved; per the plug-in contract the arm's deletion belongs to this slice, so the test now pins BOTH directions: summit/sky reserved (DW0141), valley/cherry-valley landed and not reserved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ult 208, blend_width 1..=16 (PR #261) Planner design ruling, resolving the foundation's flagged contradiction (default 176 < the spec's own view-distance floor): - summit.vista_radius is now DEFINED as measured outward from the scene bounding-box edge; floor 192 (shipped summit view-distance 12 × 16, so peaks never pop out at the fog line); default raised to 208 (one chunk of margin). DW0366 below the floor. - flatland.blend_width range 1..=16 (0 is a hard material wall — the exact no-pedestal outcome the interpenetration ruling forbids; past 16 the dither outgrows the seam). Default 6 unchanged. DW0366 outside it. - HorizonSpec/horizon_defaults doc comments updated; DW0366 catalog row updated in the same PR; code-asserting cases added to the v09_horizon range test (DW-coverage gate). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0be289d to
b357ec3
Compare
… obstacles, or light blockers (task #157 finding 1) The hollow-vigil construction round red-flagged the class: assembled's collision fallback modelled vanilla NO-COLLISION vegetation (grass tufts, flowers, petals, saplings, crops, vines, ...) as full cubes. Consequences, both directions: - rejects-valid: a short_grass tuft on a valley terrace was a phantom standable cell splitting the 2-block riser into two climbable 1-block steps — DW0369 fired on a world that is not climbable in vanilla; the same phantom ladders made the annulus perimeter 'reachable' and DW0322 fired on hundreds of outer-edge columns. - accepts-invalid (worse): any walkability proof that ever stood a player ON a plant cell was unsound, and any flower cell measured light 0 as if opaque (false DW0210 the moment feet could legally occupy it). Fix, at the class level (never the three ids one generator uses): - assembled::is_no_collision_plant — the vanilla empty-collision-shape vegetation class; collision_top_16 returns 0 for it, so occupancy walks through it and stands on what is below. Lookalikes that DO collide (azalea, big_dripleaf, bamboo, cactus, pointed_dripstone, sea_pickle, leaves) deliberately stay conservative full cubes. Fidelity consequence: plant cells no longer dam the water-flood model (vanilla water flows into and breaks them). - light::passes_light gains the same class (the occupancy-coupling invariant: nav-passable feet cells must not be opaque; the whole class is filterLight=0 in vanilla). - surround: understory decor moves from the tile slicer into the GENERATION phase, and the generator's own un-climbability proof now runs over the finished tile contents (terrain + trees + decor, collision-classified via the one shared model) — the ordering gap that let the generator proof and DW0369 disagree is structurally closed. Proofs: - assembled unit tests pin the class (collision 0 + walked-through) and the colliding lookalikes; occupancy test: plants are neither floors nor obstacles. - surround's nav-flood tests now decode every serialized tile and classify through the REAL occupancy model — no manual 'skip the tufts' list (the filter that masked this defect); the doctored-staircase DW0369 red case rides the same path. - v09_open_scene_onto_gap_floor_builds_green: the #157 staging shape — a synthesized 48x48 scene fully open onto the gap floor — builds green (finding 2 resolved: DW0322 no longer fires; the un-climbable rim bounds the reachable set; no outer-containment design ruling needed). - light unit test: the plant class passes light. Existing-campaign note: repo fixtures are byte-identical (edit double-build green); proofs only become MORE permissive (no phantom obstacles/floors/ darkness). One vanilla-fidelity behavior change: water no longer dams at plant cells — plant-adjacent water features (tidal-keep shores, greenfield) should be rebuilt in the next content round to confirm no fluid-model verdict shifts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e vista (task #157 round 2) Three follow-ups from the hollow-vigil ladder run, per the planner's design ruling: 1. CLIFF-BAND DEGRADATION (ruling, implemented as specified). Hollow-vigil is 94x27: the short-axis band (20) cannot fit gap 12 + slope 18, so the rim never rose there and the perimeter ended as a walkable shelf over the void — DW0322 fired on 346 outer columns, and no legal ratio cleared it. The profile now derives per-column band width B = d/p (the exact side length on the faces, a smooth blend at corners): B >= 30 keeps the open valley; B < 30 keeps a >= 6-wide walkable gap floor and spends the rest on a near-vertical stepped cliff to full rim height — risers quantized >= 3 (stricter than the 2-block terraces), no outer decay, so the perimeter is unreachable cliff-top and DW0322 holds WITHOUT exemption. Quantization families (2 / 6 / 3) are separated by a 6-quantized seam strip so no 1-block riser can form at a family boundary; the warp amplitude shrinks with the gap so a 6-wide floor cannot be warp-pinched shut. Spec-0026 §5 amended in this PR (owner-review class — the planner surfaces the text change in chat); compiler.md updated. 2. INNER-SLOPE BLOSSOM. The vista framed zero cherry blocks: trees planted only past the crest. A second Poisson pass now stands trees on the inner slopes of non-degenerate bands, thinned sparse-near-floor to denser-upslope, every canopy LEANING two columns toward the valley (the greenfield lean idiom) so no leaf platform sits within hop-on/hop-off range of two upslope terraces; cliff bands carry the species as a sapling understory (no-collision class — zero proof impact). Tree positions stay flora-independent; oak_sapling<->cherry_sapling joins the parity map (script + tests). The un-climbability proofs (generator flood + DW0369) run unchanged over the new trees through the shared collision model. 3. VISTA CAMERA. Was 1.5 blocks off the scene edge staring at a wall. Now: eye at the campaign spawn cell (walkable by construction; scene-centre fallback) at player eye height, pitched up over the nearest scene edge at a point above the rim — the frame composes gap floor, blossomed slope, crest, sky. Deterministic from scene bbox + walk plane + per-side band params; fixed tie order. Proofs (all green): - degenerate_axis_degrades_to_an_unclimbable_cliff_band: 94x27 fixture — gap floor survives, cliff risers >= 3, full height at the tile edge, nav flood over the serialized tiles (decor + saplings included). - no_one_block_riser_exists_and_ridge_never_opens: NO adjacent annulus columns differ by exactly 1, across all quantization-family seams. - blossom_reaches_the_inner_slope_and_cliff_bands: cherry tree cells inward of the crest; sapling understory on the hollow-proportioned cliff bands. - v09_hollow_proportioned_open_scene_builds_green: the ACTUAL degenerate aspect, fully open onto the gap floor — builds green, DW0322/DW0369 silent (no containment invention needed). - flora parity (unit + check-flora-parity.py) green with the sapling pair. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…wner ruling, 2026-08-04) The owner overruled the cliff-band design with a simpler containment: the surround band width never scales below what the rim physically needs. Per axis, band = max((ratio-1)/2 x scene_axis, gap 12 + slope 18) - a hard floor of 30 columns. The valley simply grows to contain any scene shape: hollow-vigil's 94x27 short axis takes the floor while the long axis keeps its proportional band (asymmetry accepted and expected); ONE rim profile runs unchanged on every axis; no cliff geometry, no second proof path. All cliff-band code from the previous commit is deleted, not kept as a dead mode; the RadialParams machinery collapses back to the pinned constants. One profile consequence: the outer decay now keys on the band remaining PAST the crest (not raw annulus progress), so a band-floored axis ends full-height at its tile edge - the perimeter is unreachable crest-top, never a walkable shelf over the void, and DW0322 holds purely by construction on the #157 open-carve staging shape. Items 2 and 3 of the round ride along unchanged: inner-slope blossom (valley-leaning canopies, density ramp) and the spawn-eye vista camera. The cliff-only sapling understory is gone with the cliff bands (whole trees fit everywhere now); the sapling parity pair is removed from tools/check-flora-parity.py and the tests. Proofs (all green): - short_axis_band_floors_at_the_full_rim: 94x27 - long axis proportional, short axis floored at 30; gap floor survives; a real crest rises; nav flood over the serialized tiles. - v09_hollow_proportioned_open_scene_builds_green: the ACTUAL degenerate aspect fully open onto the gap floor builds green (DW0322/DW0369 silent). - a_carved_staircase_up_the_inner_slope_is_dw0369: the saboteur is now a carved notch (stone steps + air headroom) - the shape an edit batch could really cut - and is still caught. - no-1-block-riser invariant, blossom_reaches_the_inner_slope, flora parity (script + unit), determinism, tile envelope: green. Spec-0026 amendment text updated to the band-floor formula (owner-review class - the planner surfaces it in chat); compiler.md updated in the same PR. vista_radius/view-distance interplay untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The band floor (29e9432) replaced cliff-band degradation entirely, but three comments and the vista expect string still described the abandoned design. Render review would have hunted for a stepped cliff that cannot exist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…— their generator lands in this PR
…ene-rect moat fill (task #157 round 3) 1. SNAPSHOT PALETTE. block_color had no cherry entries, so 2044 cherry cells painted oak-green through the `_leaves` suffix family — the whole point of cherry-valley is that these read pink in every render. Explicit 1.21.11 texture-average entries: cherry_leaves [229,158,187], cherry_log [92,58,58] (bark-dominant), pink_petals [224,168,190] (was falling to the magenta UNKNOWN fallback). Sweep: those three were the only gaps in the surround emission id set; a test pins the pinks against the suffix families and the whole emission palette off-fallback. 2. VISTA FOV (planner ruling). A spawn eye 40 blocks from a 48-high rim subtends ~52 degrees — no fixed FOV frames floor + crest + sky. The vista camera now aims at MID-rim on the nearest crest line and carries a per-shot vertical FOV derived from the geometry: frame bottom <= -15 degrees elevation (gap floor in frame), top >= crest-top + 8 degrees of sky, clamped <= 110. Plumbing verified end to end: render_plan emits camera.fov (the existing pov_camera channel) and delve-render's Chunky scene emission honors it (scene.rs, default 70 when absent) — a new scene.rs test proves the field is never silently dropped, and a surround test asserts the 94x27 spawn-eye case frames floor AND crest-top arithmetically. 3. SCENE-RECT MOAT (planner design ruling). The #157 walls-down probe found DW0322 void exposure INSIDE the scene rect: the rect is the keep blob's bounding box, and columns outside every piece footprint were void. Scene-rect columns with ZERO piece-authored blocks now receive ambient gap-floor ground at floor_top_y with the gap floor's own surface dapple (world-coordinate noise - the pattern runs seamlessly from the annulus through the interior); columns with any authored block are untouched (pieces own their columns; authored overhangs/voids are intentional). Emitted as row-strip tiles (horizon/valley/m<n>) so no tile ever carries an air cell over a piece column; attached at the read_structures choke point (the authored-column set needs the piece bytes), so build, snapshot, blocking and the render plan all see the same completed surround; the un-climbability flood seeds on moat cells too. Fixtures with full plates emit zero moat tiles - existing emissions byte-identical. Proofs (all green): snapshot palette test; scene.rs per-shot fov test; vista_fov_frames_floor_and_crest_on_hollow_proportions; the_moat_fills_only_unauthored_scene_columns (L-blob, authored columns untouched, every unauthored column surfaced, byte-deterministic); v09_blob_scene_with_void_moat_builds_green (walls-down irregular blob in a 94x27 rect - no DW0322 at the rect edge or interior). Spec-0026 amendment text (short) + compiler.md same PR. Note: the bot tier on this branch is stale-red only because the branch predates merged #263; the batch integration branch carries the fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…round 4) The scene-rect moat decided ownership of a column by asking "does a placed piece author ANY block here", projecting authorship to 2D with no vertical predicate. That reads a VERTICAL scene wrong: hollow-vigil's keep climbs, so its later corridors, stairs and boss hall sit 4/8/12/16 blocks above the gap-floor datum and author nothing at floor level — yet claimed their columns. The moat skipped them and the gap-floor plane stayed void under the entire elevated footprint (476 columns), with DW0322 firing along every seam where filled ground met that void (159 columns, 165 violations on the walls-down staging). A column is now FLOORED only when a piece authors a block there at or below the gap-floor top; floored columns stay untouched (the piece owns its ground, holes and basements included, and the fill can never overwrite authored blocks), while a column whose piece content is entirely above the gap floor is filled — the valley floor runs on underneath it, exactly as under a column no piece mentions. The rotation-aware transform is unchanged and matches both the voxel model and vanilla's `place template … <rotation>` pivot. Proof: - new process-level regression `v09_elevated_storey_over_void_builds_green`: an open-air scene with a wing authored only on an upper storey. Red on the parent commit (DW0322, 126 columns at the wing edge), green with the fix. - the same fixture path now WRITES a stage-7 batch, because boundary safety is only proven on the edit path — the three pre-existing open-scene tests asserted "no DW0322" over a build that never ran the check. They still pass, now for real. - unit tests for `Plan::ground_columns`: footprint per rotation (3x5, all four), elevated storey floors nothing, overhang floors only the pillar, sub-datum cells still floor their column. - hollow-vigil cherry-valley walls-down staging: 165 DW0322 errors -> exit 0. Double build byte-identical (ADR-0006), walls-up and walls-down. docs/reference/compiler.md and spec-0026's continuity amendment restated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnrGdWS7ADsjCoJfiJc6GC
… kill tally (task #178) (#268) * chore(harness): pick #263 (dsl_version allowlist covers 0.9.0) onto this base worker/spec-0026-valley predates the fix, so the bot tier refuses every 0.9.0 campaign from this base and no ladder run is possible here. Identical patch to the one already on main; it drops out on rebase/merge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnrGdWS7ADsjCoJfiJc6GC * fix(compiler,harness): the wave countdown is a liveness census, not a kill tally (task #178) A `kill` objective asks for the wave to be DOWN. The emitted countdown asked for something else — one player-credited kill per mob — and a mob has many ways to die that credit nobody: burning in daylight, falling out of the world, drowning, another mob. Every such death took a mob out of the world and left the countdown above zero, asking the party to kill something that no longer existed. No rest, no retry and no route recovers from that. hollow-vigil shipped it (owner playtest 2026-08-05). Its opening beat's roof and two walls come off for the open-air rule, the world is pinned at `time set noon`, and the first wave walked out through the carved wall and burned — `空洞步卒 burned to death`, reproduced live on the shipped datapack. Countdown stuck at 3 with nothing alive, so `obj/purge` never completed, `flag/halls-quiet` never set, `quest/the-barrow-key` never armed, and the barrow key's chest was never placed anywhere in the world. Design change, in two halves. **Emission.** `tick` now reconciles the countdown against the world, once per wave a `kill` objective adjudicates: execute if score #<w> dw.wave matches 1.. store result score #<w> dw.wave \ if entity @e[tag=dw_wave_<w>] Vanilla's own answer to "how many are left", so no new primitive and no bookkeeping to keep honest. `matches 1..` does both guard jobs: before the spawn the counter is unset, so an empty selector can never read as "cleared"; after a legitimate zero the line stops firing, so a finished wave stays finished and a `respawns_on_rest` re-seat re-arms it cleanly. The `player_killed_entity` decrement stays as a fast path — a mob the player just killed is still matched by `@e` through its death animation. **Harness.** `kill` was the one objective-bearing step that never called `requireObjective`; it graded itself on mob-side evidence and returned. That is why an all-green ladder shipped a softlock: `passed: true`, both encounters census-cleared, and the delve considered the objective open forever. The census still decides when to stop swinging; it no longer decides whether the step is proven. `critical-path.json` format 2 already DOCUMENTED this contract — `kill` simply did not implement it. Ladder proof (same world both sides, `hollow-vigil` @ ce82515): * generated PackTest `kill_uncredited` — `verb_kill` minus the hand-fed `k_reward_<wave>` calls. Shipped datapack: 19/20, `Expected #party dw.o_warden to match 1, but got 0`. Fixed datapack: 20/20. * bot tier on the fixed build: `critical path 'hollow-vigil' PASSED`. * live rcon on both builds: countdown 3→3→3 (stuck, 0 alive, no chest) vs 3→1→0 tracking the burn exactly. Determinism: two builds byte-identical; the datapack diff against the staged build is exactly the two census lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnrGdWS7ADsjCoJfiJc6GC --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…am, not by this slice The DW0366 row claimed `summit.vista_radius`'s floor was unenforceable because the spec contradicted itself (floor 192 vs default 176). That was true when the foundation slice reported it and stopped being true on 2026-08-04: the spec-0026 amendment (PR #261, on `main` for 66 commits now) resolved both open params — `vista_radius` measured from the scene bounding box, floor 192, default 208; and `blend_width` 1..=16. Enforcement is deliberately NOT added here. Both params configure surrounds this slice does not emit, and the valley slice (task #155 W-B, PR #259, based on this branch) already carries the checks and the corrected default verbatim. Implementing them twice would put a duplicate in the dependent branch's path for no behaviour gained. The row now says what is true: the ambiguity is resolved, the enforcement is owed, and which slice owes it. No behaviour change: `dsl::validate::horizon_rules` and `horizon_defaults` are byte-identical to this branch's pre-merge state. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjQ5p1Kv5MrkGPumi7yXWL
…slice Three conflicts, and the interesting damage was in what merged CLEAN. main.rs (x2): the base added a `print_diags` of the placement stage's own advisories to the view commands; this branch changed `read_structures` to take `&mut Plan` (it calls `attach_valley_moat`). Both kept. compiler.md (x2): the DW0141 reserved-surface row and DW0366's range row had each moved on both sides. Took the base's rows (they carry everything main added since this branch forked) and removed `valley`/`cherry-valley` from the reserved list, since this is the PR that lands them. scene.rs: NO conflict, and broken anyway. main renamed a scene file from `<shot>.json` to `<campaign>_<shot>.json` (one stem per scene, so two campaigns cannot share a cache key); this branch carries a test written against the old name. Different regions of one file, so git merged the new production code with the old assertion and reported success. Only running it noticed. The test now derives its name from `scene_file_stem` instead of spelling it, so the next rename cannot repeat this, and it names the scenes it did find when it fails.
The worktree was created from the stale LOCAL branch rather than origin/, so it lacked the wave-countdown census fix (#268) and the valley moat's elevated-footprint fix (#157 round 4). Merged forward, never force-pushed: a force-push here would have deleted both. Doc conflicts (compiler.md x3, tools.md x1) were two branches editing the same table anchor, each a different row: #268 rewrote `kill` (the countdown is a liveness census, not a kill tally), main rewrote `collect` (v0.8 container adoption). Each row taken from the side that changed it — either pick would silently revert real work. The third was disjoint prose about one bot contract (the cast-ledger `pos`, and `kill` finally honouring the objective); both kept. And one more that git merged with NO conflict and broke anyway — the same class as the scene.rs rename in the previous commit: `DW0185` (i18n v2, spec-0029, from main) makes any authored player-visible string emitted outside a text component an error, naming generated PackTest sources as a permitted exclusion WHEN read through `dsl::l10n::plain`. #268's new `kill_uncredited` PackTest source, written before that rule existed, interpolated `c.world.content.title` raw. Every sibling header already used `artifact_title(c)`, which is exactly that lowering; this one now does too. Four CLI tests were red, including the byte-identity gate. The pattern worth carrying: textual mergeability says nothing about semantic compatibility, and neither of these would have been caught by reviewing either branch alone.
Task #176 — measured, root-caused, fixed, and gatedThe owner's verdict was that the cherry valley "reads as a quarry". Measured on the
Seven trees in an entire valley, and the trees themselves were fine — 4–5 block trunks, ~44 leaves each. Never malformation, and never the density constant. Root causeBridson grows from its active list by jumps in Seeding from every in-domain lattice column costs one domain evaluation per lattice cell, is exactly as deterministic (positional order, The defect degrades with scale, which is why review missed it. On the 96×96 test scene the single-seed sampler still produced 1050 trees / 42.9%. It collapses on a narrow, speckled annulus — a small campaign, which is what was played. Density — measured, and a proposal, not a decisionWith the sampler fixed,
4.0 is half-covered, so the crest silhouette still reads and the grove still has gaps to walk through. Density is an aesthetic call and belongs to the owner — say a number and it changes. What bounds it mechanically is The regression gate took two attempts to bind
Also on this branch
Full workspace green: tests, clippy |
spec-0026 slice W-B (task #155): the VALLEY + CHERRY-VALLEY surround generator, biome layer and tree layer, plugged into the W-A foundation's horizon contract. This is the engine work the hollow-vigil
{base:"valley", flora:"cherry"}construction round needs; do not merge before the owner has viewed that round (player-experienceable — owner playtest is the gate; base branch =worker/spec-0026-foundation, which must land first anyway).What this adds, at design level
Surround generator (
crates/compiler/src/surround.rs, new). A valley is a mountain annulus of total footprintratio× the scene's union XZ bounds (2..=3, default 2.5): flat walkable gap floor (top y=63 → valleywalk_ref_y64 — like flatland, a valley relocates nothing vsvoid), then a domain-warped, ridged-multifractal rim (rim_heightdefault 48, ridge floor 0.3 so the ring never opens). Composed entirely from the in-house position-addressed value-noise family (edit.rsprimitives madepub(crate); Musgrave ridge composition + Bridson Poisson disk are ideas-only re-implementations — ledger rows added to ACKNOWLEDGEMENTS). Everything derives fromstream_seed(seed, "horizon/valley"); no trig anywhere (libmsin/cosis not bit-stable across hosts — the Poisson sampler uses square rejection instead).Un-climbability is proven twice, promised never (spec §5).
DW0369(build, exit 3) — a nav walk flood seeded on every gap-floor cell must never stand outward of the crest line, over the assembled (and, when a stage-7 script exists, edited) world. The generator also runs its own conservative flood (unlimited drops, tree solids included) and dies at generation if it ever regresses.Biome layer. Per-band
/fillbiomeinsetup_finish(afterplace_verify, so the chunks provably exist) — vanilla's own tint/ambience channel, no resource pack.flora: oak⇒minecraft:windswept_forest,cherry⇒minecraft:cherry_grove. The pass wraps ingamerule max_block_modifications <largest band volume>(1.21.11's renamed commandModificationBlockLimit) and restores the 32768 default; one command per band, so paint can never half-apply. Flatland note: flatland needs no fillbiome — its superflat generator already declaresminecraft:plains; the fillbiome channel is surround-only.Tree layer. Deterministic Bridson-family Poisson-disk scatter (r=7) over the crest band and outer face — 树在山上: never in the gap floor, never in the scene, never on the inner wall. One parameterized tree shape (the greenfield hand-shaped small tree grown a storey taller); species ids come from the flora table.
Cherry-valley is a parameter row, not a fork (criterion 6). One code path; flora/palette are positionally-parallel id tables (
oak_log→cherry_log,oak_leaves→cherry_leaves, understoryshort_grass/fern → pink_petals/short_grass; rock ids shared). Proven at two levels: a generator test decodes same-seed oak/cherry tiles and asserts positions/states identical with ids mapped; process-level,tools/check-flora-parity.py(new) diffs two full emissions and fails on anything beyond flora/palette block ids + the biome id (manifest.jsonis exempt as a declaration mirror — it embeds the campaign declaration hash).Plumbing (the W-A plug-in contract, followed to the letter).
base_implemented(Valley)→true; valleywalk_ref_yarm; DSLDW0141reserved arm for valley/cherry-valley deleted (summit/sky stay reserved). Tiles are NOT anAreaPlacement:Plan.surroundis a separate field,Plan::placed_pieces()is the explicit placement/model iterator — emit (structures, sentinels, forceload,place_all,place_verify),read_structuresand the assembled voxel model opt in; boundary-region derivation, lighting scope, anchors and analysis keep readingplan.areasand never see the surround (spec §5 exclusion by construction). Render plan gains onevistashot (scene edge looking outward at the rim — the establishing shot of spec §6).What CI now proves (all green locally)
v09_valley_builds_byte_identical_and_ships_surround: double-build byte-identity for the valley fixture (criterion 1 valley row); tiles shipped + placed; fillbiome + gamerule wrap present; vista shot present; void ambient in server.properties.v09_cherry_valley_is_a_parameter_row: same-seed valley vs cherry-valley emission,check-flora-parity.pygreen (criterion 6).surround::tests(10): determinism; ≤48×48×48 tile envelope + exact annulus coverage; even-step heights + ridge-never-opens; oak/cherry byte-parallelism at generator level; trees-stay-on-the-mountains; Poisson spacing; param-range refusal; build-range + no-gravity-block palette; nav flood over decoded serialized tiles;DW0369red on a deliberately carved staircase (doctored world).docs/reference/compiler.md:DW0369catalog row + a valley behavior section, same PR;check-dw-codes.pyfully green (191 codes documented + covered).DW0366(valleyratio: 5→ validation exit 1),DW0367(walk_ystripped → build exit 3),DW0364(the feat(dsl,compiler): map editor L2 massing verbs — swap/insert/remove/rewire/reseed-piece (spec-0017 PR 3) #149 shape — a lyingwalk_y: 5floods the interior with nowaterline_ydeclared → build exit 3).Visual parameters chosen (for the owner's 和谐 judgment — the vista shot + hollow-vigil round will show them)
Known limits (recorded in compiler.md)
DW0320) remains the enforcement, as for every horizon. The generator-level tests use full-size scenes.check-world-settings.shneeded no valley case: valley ships the existing void superflat literal, already covered.Stack sync + amendment (post-rebase onto the finished foundation, 370a45b)
walk_y: 0cliff fixture for the ocean-breach stranding test — DW catalog rows, fmt), the foundation's versions win and this branch's duplicates were dropped.DW0141; valley/cherry-valley landed and NOT reserved.horizon_rules):summit.vista_radiusis defined as measured outward from the scene bounding-box edge, floor 192 (shipped summit view-distance 12 × 16), default 208 (was 176 — the foundation had escalated the default/floor contradiction rather than resolve it by invention);flatland.blend_widthrange1..=16(0 is the forbidden hard material wall), default 6 unchanged. BothDW0366, with code-asserting range tests.Machine red→green for the motivating scenario:
worker/spec-0026-foundationalone refuseshorizon:"valley"with DW0141 (red); with this branch the same campaign builds green with the surround shipped, and the doctored-staircase test is the DW0369 red→green pair.🤖 Generated with Claude Code