Repository navigation
fix(pursuit): a stealth leg is walked crouched, a death on a pursued step is a measurement, and a build is staged only with every story world passed - #1346
Merged
Conversation
configureLeg set the crouch once, at the leg's start. mineflayer-pathfinder clears every control state on setMovements, on every setGoal and on arrival (resetPath / fullStop -> bot.clearControlStates), and walkLeg calls the first two on every hop, so the crouch was gone before the body took a step: a declared stealth leg was walked upright. The crouch is now held on each physicsTick for the whole leg, after the library's steering and before the tick's position packet. A crouched body cannot do three moves a player stands up for: a downward climb (it holds on the ladder, and will not walk off the brink), a step down onto a lower floor, and a declared jump (vanilla's edge back-off, which the client physics reproduces). The hold yields for exactly those hops (climbHop for a down climb, hopStandsUp for the rest). Measured on the real pathfinder over the real client physics (test/sneak-leg.test.ts): with the set-once crouch the body was upright on 83 of 83 ticks of a two-hop sneak leg; with the hold, 0 of the leg's ticks. Held through a one-block step down, the body stops at the brink; with the leg's rule it arrives, crouched on every other tick. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…ked sneaking A trigger step's sneak was always false, and the harness refused a `sneak` key on a trigger row and walked every trigger upright. A trigger the path performs in front of an objective is walked as part of the walk to it, so it now takes the `sneak` of the first step after it that is not a trigger (a spliced link press included); critical-path.json carries `sneak: true` on such a trigger row, the harness accepts it there and every walk of fireTrigger takes it. The warden maze's world/0 walks its 53-block approach to the bridge as a trigger step in front of the walk to Wren; it was walked upright whatever the objective after it declared. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…ith every world passed The gate read the critical-path run report and the written-world record and nothing else, so a build whose branch runs were red was admitted: the warden maze's world/0 died on its step 9 and the gate minted a token for that build. A build whose validation/branch-plan.json names a branch now owes --branch-runs, validation/branch-runs.sh's merged branch-runs.json: every planned world must have a row that ran and passed on THIS build, and a declared branch no world realizes is refused. A build with no plan, or a plan naming no branch, owes none. The record binds to the build: branch-runs.sh stamps each driven row with the manifest_sha256 its bot run stamped, and the gate compares it with the tree's. playtest-server.sh up takes --branch-runs and hands it to the gate; the skill's hand-over and ladder pages name it. tools/tests: 157 passed. With the gate's call to the branch-run check removed, 8 of the 10 new branch tests red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…igger steps, and how the bot holds it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…el hears exactly those moves A sneak leg's crouch now holds, and the warden maze still lost its bot: the one loud move left is the tower ladder's descent, which no body makes crouched, and the bot made it blind. An rcon observer on world/2 read the bot absent from the warden's anger list for about four minutes of crouched walking; its first entry (34) came on the standing slide down the ladder, 14.2 blocks from the warden in three axes, 121 at 5.6, and the bot died at the foot. spec-0132 §5.2, amended: on a pursued step, before each move a crouched body cannot make, the bot waits crouched until every live pursuer whose kind hears stands beyond its reach of the move (least three-axis distance to the move's segment), on the step's own readings; the wait is bounded by the largest forget_ticks (the most anger the kind holds over its decay: the warden's 150 at 1 a second, 3000 ticks), and a spent bound fails the step by name. The route is otherwise unchanged. Criterion 17 states what it asserts. One answer to "which moves are made standing": compiler::waypoints::stand_ups (a climb down, a step to a lower route cell outside any climb, a declared jump), exported on a sneak leg as `stand_ups` and read by the bot (the harness's own y-rule is removed); the sculk model hears exactly the cells those moves stand in (standing_cells -> leg_vibrations). The hearing is delvewright_dsl::senses, one record, carried on the pursuer's row as `hearing`; warden-behaviour.md §8 records the reach and the bound. Tests: dsl senses 1 passed; delvec lib waypoints+sculk 25 passed; it native_entrance+teleport_link 45 passed; harness tsc clean, waypoints, critical-path, movement, sneak-leg and the four wait tests pass. With quietBeforeStanding returning at once, 2 of the 4 wait tests red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
… press in front of it with it obj/cross-the-strait declares `stealth`, so the exported path carries `sneak` on it and on trigger/ferry-tiller performed in front of it: the gallery's element for the sneak marker on an objective step and on a trigger step (spec-0039). The executor's crouchYielded doc names the exported stand_ups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
climbHop's descent aligned the body within 0.25 of the column's centre and then slid "while not on ground"; a body entered from above whose 0.6-wide hitbox still overlapped the floor beside the column stood on that edge, so the loop ended at once and the climb "let go" at the top. The pathfinder's next hop used to finish the descent; with a sneak leg's crouch now held on that hop, a crouched body holds on the ladder and the walk stuck there for the hop's whole timeout (the warden maze's world/2, step 7: "let go at [47.5, 87.0, 48.5]", then stuck at y 86.8). The descent now steps to the column's centre until the body drops into it, and fails by name if it never does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…'s stand-ups are emitted obj/board-the-ferry declares `stealth`; its leg steps down a block and takes the declared jump, so the waypoints export both hops in `stand_ups` (step-down [18,69..70,20], jump [16,69,20]->[12,69,20]) and the path carries `sneak` on it. Measured on the gallery primary (release build of this branch, prefabs by tools/ci/gallery-prefabs.py): with both declarations, `sneak` on steps 27, 28 (trigger/ferry-tiller) and 29, and leg 21's two stand-ups; with board-the-ferry's `stealth` removed, no stand-ups and `sneak` on 28 and 29; with cross-the-strait's removed (previous commit), the two `sneak` lines on 28 and 29 go. The build's vibration lines are identical either way. check-gallery-coverage.py exits 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
The wait (spec-0132 §5.2's amendment, criterion 17, quietBeforeStanding and its forget_ticks bound, and the delvewright_dsl::senses registry and the pursuer row's `hearing` that only it read) is removed. Measured on the warden maze, it cannot work: a warden comes to a body that stands still — three of three waits at the top of the tower spent the bound with the warden 2.5 to 3.3 blocks from the ladder's foot, and two of eight waits at the dais ended with the bot killed while waiting (warden-behaviour.md §8 keeps the record). The shared stand_ups answer, the sculk model's agreement with it, the held crouch, the trigger sneak and the climb's take-hold fix stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…e pursuer row's `hearing`, its parse, and the record The previous commit removed only crates/dsl/src/senses.rs (a pathspec error dropped the rest of the staging); this one carries the remainder, so the tree builds again here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…pawns and walks the step again, and only a death loop is red Owner ruling, a loosening of what `died` asserted (spec-0132 §5.2 and criterion 10, amended in their own words): whether a body survives a vanilla-AI pursuer is the designer's call, and a solo player passes by dying and retrying. judgePursuedStep no longer fails on `died`; each attempt's record states the attacker and the run's line counts deaths (`...; closest approach d; x death(s)`, `deaths` in the report). The sequencer's one recovery after a death (respawnInPlace: wait out the respawn, re-arm where the bot stands — what retryOnDeath already did, now factored and shared) is taken on every death on a pursued step; the executor then rewinds the leg cursor to where the step began and resumes its leg from the proven waypoint nearest the respawn (resumePursuedStep). A life must get further along the step's proven route than every earlier life on it, measured as the furthest proven waypoint reached, leg by leg; one that does not is a death loop and fails the step by name. So a step is walked at most once more than it has proven waypoints: the bound is the route's own length. The climb's take-hold fix gains its test (test/climb-down.test.ts: the real client physics, the tower in miniature; the old descent lets go at [5.5, 87.0, 4.8], the fixed one at [5.5, 64.0, 4.8]). Red->green: the old `died` failure put back reds the death-as-measurement case; the sequencer's pursued-death branch removed reds both sequencer cases; the progress comparison removed reds the death-loop case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…oute has waypoints; progress is never asked The bound guards termination, not survival. Asking each life to get further than the last re-imported the judgement of the pursuer's vanilla will that the owner ruled out. A pursued step now takes at most as many deaths as the proven legs it walks have waypoints, whatever each life reached, and the death past that fails the step by name (death, bound, legs). The executor notes the legs a step's walks match (noteStepLeg) in place of a per-hop progress value. spec-0132 §5.2 and criterion 10, playtest-methodology.md and the skill's ladder page say so. Red->green: with the bound removed, the death-loop case reds (the fifth death on a four-waypoint leg is walked again). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
… never a passed row On the warden maze's world/0 the bot walked its branch to the end and its report recorded every stage passed, but the run exited non-zero because the sculk ear failed it (`darkness 1` that no warden in reach explained). The merge copied the report's `passed: true`, so the staging gate, which reads that row, admitted the build. The exit code is now the verdict: a branch whose run wrote a report and still exited non-zero is merged as not passed, with the exit code in its reason. The harness also prints each darkness it receives, with where the bot stood, the step, the deaths so far and the nearest warden the client saw, so a darkness the ear counts can be read against the deaths and respawns around it. Red->green: tools/tests/test_branch_runs_keeps_bot_report.py's new case (a stub run exits 3 after a passing report) fails without the exit mark, and passes with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…mpose from the engine root
Compose builds through buildx bake, and bake refuses to read a file
outside the working directory unless it is granted an `fs.read`
entitlement. The skill runs the ladder from the content tree, where the
engine's validation/Dockerfile.delve lies outside the working directory, so
the image build was refused before the hatch stand ran:
additional privileges requested: pass "--allow=fs.read=../wt-maze-death/validation/Dockerfile.delve"
The same `bot-run.sh --only-hatch-stand` on the same build passed when run
from the engine root. bot-run.sh, world-save.sh and reset-when-empty-run.sh
now cd into the engine root before compose (branch-runs.sh already did).
Every path they hand compose is absolute or resolved against validation/
first; world-save's --seed is made absolute before the cd.
tools/tests/test_ladder_compose_runs_from_engine_root.py: every script that
exports DELVE_DOCKERFILE changes into the engine root before its COMPOSE
line. It found reset-when-empty-run.sh as a third instance, and it fails
with bot-run.sh's cd removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
…the pursuit census, not the client's entity table The sculk ear excused a darkness when the client saw a warden within 20 blocks. The pulse is applied on the server's positions, and the client's entity table lags them at the edge of the reach. On the warden maze's world/0, one darkness of 34 read past 20 on the client and failed the run. A diagnostic run printed every darkness: the nearest warden the client saw ran up to 19.0 blocks. The excuse is now read off the pursuit census, one source: each reading of a declared warden's actor feeds the ear its server distance to the bot (SculkEar.onWardenReading, from readPursuers). A darkness is a declared warden's when the reading before it or the one after has the warden within 20 blocks and no shriek was heard within a second. No tolerance constant. Where the client and the census disagree about a warden in reach, the run prints the disagreement by name (`[sculk] darkness at <t>: the client …, the census …`); the client never decides. spec-0132 §5.7, compiler.md and playtest-methodology.md say so. Red->green (test/sculk.test.ts): a darkness the client places at 20.5 and the census at 19.5 passes; one the census places at 20.5 and 21 fails, whatever the client saw. Judging on the client flag again reds both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
… standing
A walk declared stealth that crosses a declared sprint jump could not be
walked: `configureLeg` turns `allowSprinting` off for the whole sneak leg, and
mineflayer-pathfinder 2.4.5's parkour move lands at most two cells forward
with sprinting off (`getMoveParkourForward`, `maxD`), so the jump's landing
was no neighbour of its take-off cell and the hop answered `No path to the
goal!`. The compiler already names the jump among the leg's `stand_ups` and
the crouch hold stands the body up for it; the sprint lock was never lifted.
The gallery's ferry walk became stealth on this branch and crosses the broken
plank (`jump/the-broken-plank`, `sprint: true`, a three-wide gap): the gallery
bot stopped at the plank's take-off on `anchor/ferry-deck` waypoint 7/11.
`hopMovements` (harness/src/movement.ts) is the one per-hop setter the leg
calls: the parkour move as before, and sprint on for a plain leg, or for a
sneak leg's hop that is a stand-up of a jump declared `sprint`.
Direction: the defect can only turn a proof red (a stealth leg over a sprint
jump halts); it cannot let anything ship.
Test: test/sneak-leg.test.ts "a sneak leg makes its proven sprint jump
standing, at a sprint, and lands" walks the real pathfinder over the client
physics across a three-wide gap. With the sprint held off on the sneak leg it
reds ("stopped at [9.50, 64.00, 2.50]", the take-off cell); with the fix,
4 of 4 tests in the file pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
A delve's critical-path bot walked every declared stealth leg standing up.
configureLegturned the crouch on once, when the leg started, andmineflayer-pathfinder clears every control state on
setMovements, on everysetGoaland on arrival. The leg calls the first two on every hop, so thecrouch was gone before the first step: on the real pathfinder over the real
client physics, the old code walked a two-hop sneak leg standing on 83 of 83
ticks.
Four more defects were found on the same path:
sneak: false, and the harness refused the key on a trigger row.the sculk model had a shared answer for a climb down, a step down or a jump,
and the sculk model treated a whole sneak leg as silent.
climbHop's descent could end standing at the top of the ladder, on theedge of the floor beside the column. The pathfinder's next hop finished the
descent only while that hop was walked standing; with the crouch held, the
walk got stuck there.
Separately, the staging gate read only the critical-path run report and the
written-world record, so a build whose branch runs were red was still
admitted.
The fix
movement.tsconfigureLeg). Ityields only for the leg's exported
stand_ups.declares (
plan::path). It takes thesneakof the first step after itthat is not a trigger.
compiler::waypoints::stand_upsreturns the climb downs, the steps to alower route cell outside any climb, and the declared jumps. It is exported
on a sneak leg as
stand_upsand read by the bot. The sculk model hearsexactly the cells those moves stand in (
standing_cells→leg_vibrations).criterion 10, amended, and declared as a loosening of what
diedasserted).
deaths:
…; closest approach d; x death(s).respawnInPlace, whichretryOnDeathnow shares. It then walks the stepagain from the respawn: the leg cursor rewinds, and the leg resumes from
the proven waypoint nearest the bot.
at most as many deaths as the proven legs it walks have waypoints, and
the death past that fails the step by name. Whether a life got further
than the last is never asked.
pursuer_lost,unread,staged/restored, and adeath loop.
climbHop). The olddescent could end standing at the top, on the edge of the floor beside the
column.
in
branch-runs.json. A run-level check such as the sculk ear is not areport stage, and the gate reads the row.
the deaths so far and the nearest warden the client sees.
ear's excuse is read off the pursuit census (
SculkEar.onWardenReading):the reading before and the one after the darkness, within 20 blocks, with
no tolerance constant. Where the client and the census disagree, the
disagreement is printed by name.
bot-run.sh,world-save.sh,reset-when-empty-run.sh) run compose from the engineroot. buildx bake refused the engine's
Dockerfile.delvefrom thecontent tree without an
fs.readentitlement.validation/branch-plan.jsonnames a branch owes--branch-runs, andevery planned world must have passed on this build: each row carries the
manifest_sha256its bot run stamped.playtest-server.sh uptakes andpasses the flag.
obj/board-the-ferryandobj/cross-the-straitdeclarestealth, andtrigger/ferry-tillerin front of the crossing inherits it.stand_ups.sneaklines and stand-ups out ofthe emitted path.
Evidence
tsc --noEmitis clean; the whole suite passes, 811 of 811. The docs-job checks pass, exceptcheck-demo-queue, which needs the content checkout.ticks;
climb-down.test.tsfails, letting go at[5.5, 87.0, 4.8] instead of [5.5, 64.0, 4.8];
diedfailure: the death-as-measurement test fails;branch-runs.sh: the new merge case fails;fail (client 20.5 / server 19.5 passes; server beyond 20 fails);
cdremoved frombot-run.sh: the compose-root test fails.delvewright-dsllib: 228 passed.delveclib, waypoints + sculk: 25 passed.tests/it, native_entrance + teleport_link: 45 passed.-D warnings: clean.the gate's call removed, 8 of the 10 new tests fail.
The warden maze on this branch (unreleased build, no override)
Engine
edf9246aa, build manifest613d5d93…. The whole ladder ran from thecontent tree, and it is green. Deaths are the measurement:
world/0world/1world/2--branch-runs)On every darkness, the client and the census agreed about the warden in
reach.
sprint(the gallery's ferry-deck plank).🤖 Generated with Claude Code
https://claude.ai/code/session_019qiQFhKtTpTbYnn9NZBbSd