DW0452/DW0453: a puppet may only make moves its own body can make - #316
DW0452/DW0453: a puppet may only make moves its own body can make#316stellarfeline wants to merge 4 commits into
Conversation
…body can make Island round 21, two owner sightings of the flock, one surface (`move-actor`) and two different root causes. `clearance` proves where a body IS; nothing proved what it DID to get there. Through (DW0452, error). The mountain pen's gate shipped `oak_fence_gate[facing=east,open=false]` and sixteen walked legs crossed it, in a cell the owner herself could not walk through. The occupancy model excludes use-gates from `is_occupied` because a closed gate IS passable — for the player, who right-clicks it — and scripted walks were routed on the player's rules on the stated ground that "the beat's fiction controls the gate". Nothing proved that fiction, and nothing could: a tp'd puppet performs no interaction and no runtime verb changes a gate's block state. Capabilities now come from the entity (`Traversal::of_entity`), so the rule is "this body cannot", not "no body may" — a spider routed over a wall stays correct. Over (DW0453, warning). The beach fold's ring is `cobblestone_wall` on two sides and full-cube `mossy_cobblestone` along the middle of the others, so the router hopped the low course and twelve legs left the pen over its wall instead of through its opening. With `resample`'s L-shaped step-up — a vertical translation in place — that renders as an animal climbing a stone wall. Advisory: the move is legal, and only the author knows whether a one-block course is a kerb, a stile or an enclosure. Also: `edit::write_cell` now honours `open=true`. `Assembled::open_gates` was fed only by the prefab read and cleared on every edit write, so a stage-7 edit could ship `oak_fence_gate[open=true]` in the world and have every proof model it shut — the model contradicting its own emitted bytes, and the one available fix for DW0452 unauthorable. `validation/traversal-gate.json` states the binding count per locomotion class, and declares `jump_reach` unbound on purpose: per-entity JUMP_STRENGTH is server-code attribute data, so a table of it would be invented precision. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjQ5p1Kv5MrkGPumi7yXWL
|
Planner review: approved on content, HELD for the owner's playtest batch, paired with content #29. You corrected both of us, and that is the findingI framed finding A twice and was wrong twice — first as a coverage gap for full blocks, then, after the owner's correction, as a route going over a wall block. It is neither. The fold's ring is mixed:
Nine cells impassable, five cells a step. That sentence is the actual defect, and neither the owner's sighting nor my two theories would have produced it. It came from measuring 26 legs against the assembled model instead of reasoning about block classes. Finding B is worse than reported, and the reason it survived is the important part
And the reason nothing caught it is the kind of thing worth writing on a wall:
A The engine fix you found on the way
Three judgment calls I want on the record as right
What is held, and whyThe paired content fix is campaign content, so this is hers to clear. The proposed Both go into the batch with #314 and the l10n holes, which is also the v1.1 batch. |
… may skip it Owner correction, island round 21: a flying body may skip the climbing/surmounting checks; the collision check it must still owe. The exemption was on the wrong axis. `check_traversal` did one early `continue` over the whole body before BOTH rules, which conflated two different questions: - DW0452 is COLLISION-AND-INTERACTION. The gate leaf spans the full cell across one axis, the planned route runs down the cell's centre line, and the puppet performs no right-click — and not one of those three facts changes because the body has wings. A tp-driven puppet is moved along the planned cell route whatever its body is. So the rule binds to EVERY body, and the only thing that can excuse it is `opens_gates`, which is why that is a per-body field and not a constant. - DW0453 is LOCOMOTION. Going over a line is what a climber does, and a flier makes no ground step-up. This is the rule locomotion governs, and the only one. The exemption is now expressed per rule (`exempt_from_gate_rule`, `exempt_from_surmount_rule`) rather than per body, so a future edit that wires locomotion back into the error tier has to delete an assertion. The ledger's `gate_use.cells` counts every non-gate-opening body regardless of class, so the binding count itself shows the rule is total. Table, re-derived (planner review). `breeze` was listed a flier and is not: it hovers on the surface and leaps, and cannot ascend (minecraft.wiki/w/Breeze) — it walks, so it is checked. `Aquatic` now reads vanilla's own `#minecraft:aquatic` tag instead of a hand list that was missing `turtle`, `nautilus` and `zombie_nautilus`; it carries no exemption at all, so its membership can never cost a proof. `Climber` and `Flier` stay hand-listed with their tests stated, permitted only because they gate the advisory tier; `#minecraft:fall_damage_immune` is NOT a flight signal (it holds `breeze`, `chicken`, `cat`, `iron_golem`, `shulker`). The vendored entity-tag table moves to `registry`, beside the other vanilla tables. Red->green: `a_flier_walked_through_a_closed_gate_is_still_dw0452` fails under the old early-`continue` structure and passes under this one. The unknown-id fallback — the module's load-bearing safety claim, previously only a comment — is now pinned end to end: a body the table never heard of is checked, not skipped. Every hand-listed species is CI-required to exist in the pinned registry. Player-facing output byte-identical to the pre-review build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjQ5p1Kv5MrkGPumi7yXWL
Island round 21, two owner sightings of the flock. Both are
move-actorpuppetscrossing geometry, both were invisible to every existing proof, and they are
two different root causes on one surface — reported as such rather than
forced into one story.
compiler::clearanceproves where a body is. Nothing proved what it didto get there. This PR adds that proof, and the capability model it has to rest on.
Per-leg route table (binding count: 26 legs, 1672 route cells, 82 rises)
Every walked leg of
nobodys-cave-island, its computed A* route intersectedagainst the assembled voxel model.
move-actorlegs: 14 (12 sheep + 2actor/polyphemus-herdsman), matching the campaign's declaration.move-npclegs: 12. All 26 are
Locomotion::Ground; zero climber, zero flier, zeroaquatic — stated because a proof written for walking bodies would be unbound
over exactly the bodies it understands least.
oak_fence_gate[facing=east,open=false][18, 73, -63]mossy_cobblestonecourse of the fold's north wall, comes down the far side[7, 63, -10], barrier[8, 63, -10]Finding A: reproduced, but not as either of us framed it
It is not a wall block, and nothing passes through anything. The fold's ring
is
cobblestone_walldown the east and west sides and at the north corners, andfull-cube
mossy_cobblestone(one block high) along the middle of the north andsouth edges. A wall block is a 1.5-tall barrier the router may neither pass nor
stand on —
standable_fprequires solid ground below andis_occupiedcounts
tallas impassable, and both rules hold. A full cube is an ordinaryone-block ledge every body in the dims table can hop.
So the enclosure the eye reads as one wall is, to the route planner, impassable
at nine cells and a step at five. The sheep hugs the pen's east face at
[7, 63, -9], rises a block straight up —nav::resample's step-up L is avertical translation in place, by design, because it is what keeps a body out of
the step block's corner — crosses the north wall's top at
[7, 64, -10]anddrops into the meadow at
[7, 63, -11]. The pen's real opening at[6, 63, -6]is never used. Twelve legs do it. From a camera cutting away, an animal walking
up a stone wall.
The move itself is legal: a one-block rise is inside the player-class jump every
body here has. What is wrong is that the line the content drew as an enclosure is
not the enclosure the router sees.
Finding B: reproduced, and worse than reported
[18, 73, -63]shippedoak_fence_gate[facing=east,open=false]in a fence linethat runs east-west. A gate whose facing is on the X axis gets vanilla's
X_SHAPE— thin in X, spanning the cell's full depth in Z — so the leaf standsedge-on in the doorway. Walking straight through is impossible and offsetting
to x≈18.0 squeezes past the leaf: exactly what the owner described, and it
confirms the orientation is wrong independently of the open/closed question.
Why nothing stopped it:
is_occupieddeliberately excludesuse_gates, becausea closed gate is passable — for the player, who opens it with an
adventure-legal right-click. Scripted walks were routed on the player's rules,
justified in
plan_moves' own doc as "the beat's fiction controls the gate".Nothing proved that fiction, and nothing could have: a scripted walk is a
tppolyline whose puppet performs no interaction at all, and no runtime verb
changes a fence gate's block state, so a gate that ships
open=falseis shutfor the whole delve.
DW0451fired sixteen times and called it advisory on the grounds that a barriercell "is a narrow post or panel, so whether the body interpenetrates depends on
sub-block shape the compiler does not carry". That reasoning is about a body at
rest. It is the wrong question for a body in motion, and this PR does not
change
DW0451's severity — it adds the proof that asks the right question.The general form, closed as two diagnostics
New module
compiler::traversal, mirroring theDW0450/DW0451tier split:the body physically cannot, vs. the compiler can measure but must not adjudicate.
DW0452— error. A walked leg's route contains a move the body cannot make.One bound rule today: the route enters a closed fence-gate cell and the body does
not open gates.
DW0453— warning. A walked leg goes over a barrier line across a full-cubecourse of it: it steps onto a cell whose support is a full cube standing level
with and orthogonally beside a 1.5-tall fence/wall cell, and comes back down
within 4 route steps. A partial floor (slab,
dirt_path) beside a fence is nevera course — that is floor detail, not a wall.
Two rules, two questions, two exemption axes
Owner correction (round 21), and it is the structural point: a flying body may
skip the climbing/surmounting checks; the collision check it must still owe.
DW0452is a collision-and-interaction question. The gate leaf spans thefull cell across one axis, the planned route runs down the cell's centre line,
and the puppet performs no right-click — and not one of those three facts
changes because the body has wings or claws. A tp-driven puppet is moved along
the planned cell route whatever its body is. So the rule binds to every
body; the only thing that can excuse it is
opens_gates, which is why that isa per-body field and not a constant. Locomotion does not touch this rule.
DW0453is a locomotion question. "Did this body go over a line it may notgo through?" is a defect only for a body whose way past a wall is round it.
Climbers and fliers are exempt — from this rule and nothing else.
The exemption is expressed per rule (
exempt_from_gate_rule,exempt_from_surmount_rule) rather than as an early skip over the whole body. Anearlier draft did the latter and let a flying body walk through a closed gate in
silence.
gate_use.cellsin the ledger counts route cells for everynon-gate-opening body regardless of class, so the binding count itself shows the
rule is total.
Capabilities come from the entity, and the table is built to fail safe
Spiders really do climb, so the rule cannot be "no body crosses a wall".
Traversal::of_entityderivesLocomotionfrom the entity id under one statedmembership rule, built around an asymmetry: a too-strict classification costs a
false positive the owner dismisses in a minute; a too-loose one costs a body that
is never examined and reports green.
Groundis the default AND the checked class. Every id vanilla data doesnot positively answer lands there — unrecognised ids included. Ambiguity
resolves to Ground.
answer, or a closed cited list whose exemption is advisory-tier. Nothing is
ever exempt from the error tier.
Re-derived on review, every non-
Groundentry:GroundClimberSpiderand its subclasses —spider,cave_spider, the only mobs whoseonClimbable()is true on horizontal collisionDW0453onlyFlierDW0453onlyAquatic#minecraft:aquatictag, read from the vendored registryTwo corrections came out of that pass.
breezewas listed a flier and isnot — it "moves around by hovering on the surface and by leaping" and cannot
ascend (wiki); it walks, so it is checked.
#minecraft:fall_damage_immuneis the tag that looks like a flight signal and isnot — it holds
breeze,chicken,cat,iron_golem,shulker. And theaquatic hand list was wrong by three: eleven entries against vanilla's
fourteen, missing
turtle,nautilus,zombie_nautilus. It is now read fromthe tag, and it exempts nothing, so its membership can never cost a proof. The
vendored entity-tag table moved to
registry, beside the other vanilla tables,so
DW0496and this proof read one copy.Every hand-listed species is CI-required to exist in the pinned entity registry,
so a typo or a rename at the next MC pin is a red rather than a class that
silently stopped matching.
Deliberately not modelled: per-entity jump reach. Every rise is measured
against the player's apex for every body, because real
JUMP_STRENGTHdefaultslive in server code rather than any registry the compiler reads.
validation/traversal-gate.jsoncarries that axis as declared-unbound with itsreason rather than leaving a reader to infer it from silence.
Proposed, NOT implemented — an authored override
New DSL surface needs an owner-approved spec, so this is a proposal only. Shape:
an optional
traversalobject on a stage-5 actor (and stage-2 NPC), besideentity—{"climbs": true}/{"flies": true}— overriding theentity-derived default, so a "spider sheep" is a declared creative choice with a
proof behind it. Note
opens_gatesis deliberately not in that shape: nobody opens a gate, and the fix for a gate is to ship the gate open. The instance
fix here does not need any of it; nothing in this PR blocks on it.
Instance fix (content repo)
Content PR:
stellarfeline/delvewright-campaigns#fix/puppet-route-geometry.Two
world-editsbatches, no engine widening:batch/fold-ring-one-material— the fold's ring becomes one material on bothgreenfield pieces (the prefab is drawn twice, like
batch/fold-clear). Thesouth doorway and the south-west corner gap stay air, so the fold still has a
way in and out, and it is now the only way.
batch/pen-gate-open— the pen gate ships open and square to its fence line.An open fence gate has no collision at all, so the same route becomes honest
for puppet and player alike.
One engine fix the instance fix needed
edit::write_cellnow honoursopen=true.Assembled::open_gates— the side setoccupancy_ofreads to tell a closed gate from an open one — was populated onlyby the prefab palette read, and every edit write unconditionally cleared it. So a
stage-7 edit could write
oak_fence_gate[open=true], ship exactly that block inthe world, and still have every proof downstream model the cell as shut: the model
contradicting the bytes it emitted, and the only available fix for
DW0452unauthorable. Its own red→green is
the_same_gate_shipped_open_is_silent.What CI now proves
DW0452fires on a walk whose only crossing is a closed fence gate, names thecell and the capability the route assumed, and is silent when the same gate
ships open.
DW0452— theowner's correction, as a test. It fails under the rejected early-
continuestructure and passes under this one.
fixture that flags a sheep, so the silence is evidence rather than an absent
code path.
end, through a real build, for
minecraft:mannequin(the body every skinnedNPC wears) and
minecraft:breeze. That safety claim previously lived only in acomment.
and fliers only from the advisory tier. A future edit that wires locomotion
back into
DW0452has to delete an assertion to do it.DW0453fires on a wall line pierced only by a full-cube course, and is silentwhen the same line has a real opening;
barrier_coursetreats a slab beside afence as floor detail, not a wall.
and names every locomotion class.
fmt/clippy -D warningsclean,
check-dw-codes.pybidirectional (209 codes, all covered).Machine red→green, and re-running the general form against the current build
DW0452error, exit 3DW0453(with the gate fixed, ring not yet)[7, 63, -10]DW0451leg advisories[18, 73, -63]The 6 that remain are
DW0498(pool repeat) and the PolyphemusDW0359/DW0451pair the owner has already rejected — untouched, as instructed. Her note that
DW0359's threshold reads as too cautious is recorded here and not acted on.Re-run against the current build turned up nothing further. Both codes bind
to exactly the two reported instances and nothing else across the island's 26
legs. One honest gap:
hollow-vigil, the only other live campaign, is red atstage 6 on
DW0331(two over-wide dialogue labels) onmainalready — it neverreaches emission, so the traversal proof is unbound there and cannot be said
to have checked it. That is a finding, not a pass.
Merge gate
Campaign content is player-experienceable, so this does not merge on green —
it goes into the owner's next playtest batch, paired with the content PR. What to
look for: the flock files out of the beach fold through its opening rather than
over the wall, and the mountain pen's gate stands open and square to the fence,
with her own character able to walk straight through it.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AjQ5p1Kv5MrkGPumi7yXWL