docs: S4b contract — port the retail resting pair (tangent walkable rest + bare push-out + AD-69)
The suspect line is pinned at scoping: our ValidateWalkable measures the sphere's VERTICAL bottom against the plane (planted rest, perp = r*N.z) while our AdjustSphereToPlane is already a faithful tangent port — we mix the two geometries today and the planted one wins on terrain. D0 byte-pins retail's validate_walkable distance basis with an explicit STOP if it refutes the premise; D2 retests the #341 harness flip ten ways under the mechanism's stability prediction; the gate teaches the user that slightly hovering feet on steep slopes is the CORRECT retail look. Queued behind S1B and S2 — one physics slice in flight at a time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
eec50bbd24
commit
e1beb7d31f
1 changed files with 99 additions and 0 deletions
99
docs/research/2026-08-07-s4b-tangent-rest-contract.md
Normal file
99
docs/research/2026-08-07-s4b-tangent-rest-contract.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# S4b contract (Campaign S) — port the retail resting pair: tangent walkable rest + bare-radius push-out
|
||||
|
||||
**Date:** 2026-08-07. **User decision, same day: "port the retail pair."**
|
||||
**Implementer:** one Sonnet agent, AFTER S1B and S2 have landed (one physics
|
||||
slice in flight at a time; build slots). **Review:** dual Opus. **Gate:** the
|
||||
user's eyes on a slope — feet are EXPECTED to hover slightly (authentic
|
||||
retail): ~3 cm at 30°, up to ~20 cm near the walkable limit.
|
||||
|
||||
## The mechanism, settled by measurement + two decompilers (#341)
|
||||
|
||||
Retail's walkable placement (`CPolygon::adjust_sphere_to_plane` @0x00538210,
|
||||
BN pseudo-C 322032 + Ghidra cross-confirm) solves
|
||||
`t = (dist ∓ r) / dot(N, stepDir)` — the sphere rests TANGENT to the slope,
|
||||
perpendicular distance = radius. Its `adjust_offset` push-out uses the BARE
|
||||
radius (AD-66's byte evidence) and is therefore structurally inert at rest.
|
||||
acdream rests PLANTED (perp = r·N.z) and its substituted r·N.z trigger is
|
||||
inert here by the same algebra. The user's live capture: bare trigger vs our
|
||||
rest would fire on 84% of grounded slope ticks (2,471/2,955), lifts 2–88 mm.
|
||||
**The pair ports together or not at all.**
|
||||
|
||||
## The suspect line, pinned at scoping
|
||||
|
||||
`Transition.ValidateWalkable` (TransitionTypes.cs ~3652) computes
|
||||
`lowPoint = sphereCenter − (0,0,radius)` — the sphere's VERTICAL bottom — and
|
||||
`dist = dot(lowPoint, N) + D + waterDepth`, pushing up by `dist/N.z` until
|
||||
the FEET clear the plane. Resting identity: `dot(center,N)+D = r·N.z`.
|
||||
Meanwhile our `AdjustSphereToPlane` (BSPQuery.cs:364 and its FlatBspQuery
|
||||
twin) is ALREADY a faithful tangent port of @0x00538210 — so acdream today
|
||||
mixes tangent (BSP walk solve) with planted (ValidateWalkable) and the
|
||||
planted one wins the resting height on terrain.
|
||||
|
||||
## Deliverables, in order
|
||||
|
||||
**D0 — byte-pin retail's `OBJECTINFO::validate_walkable` FIRST.** Grep the
|
||||
named pseudo-C; disassemble the distance basis from the PDB-paired binary if
|
||||
BN is ambiguous (the flag-idiom artifact class). The ONE question: does
|
||||
retail measure the perpendicular sphere clearance
|
||||
(`dot(center,N)+D − radius` — tangent semantics) or a vertical foot point?
|
||||
Cross-check ACE's `ObjectInfo.ValidateWalkable`. Write the pseudocode doc.
|
||||
**If retail's validate_walkable turns out to ALSO use a vertical foot point,
|
||||
STOP — the whole slice premise changes and the session lead re-decides.**
|
||||
The waterDepth term's exact placement in retail's expression must be pinned
|
||||
too (AP-10's sink-in behaviour must survive byte-for-byte).
|
||||
|
||||
**D1 — port the pair, one commit:**
|
||||
1. `ValidateWalkable`'s distance basis → retail's (per D0's pin).
|
||||
2. `AdjustOffset`'s push-out → bare radius in trigger AND numerator (the
|
||||
exact diff that was withheld — its two `[Skip]`-ed conformance tests in
|
||||
`S4AdjustOffsetConformanceTests` un-skip and must pass unchanged).
|
||||
3. **AD-69 rides along:** the same block's `dist` gains retail's
|
||||
`LandDefs::get_block_offset` cell-relative correction (the plane's cell
|
||||
frame vs the mover's), per that row's citations.
|
||||
|
||||
**D2 — the #341 harness anomaly retest.** With the pair in, run
|
||||
`RuntimeRemoteUphillProgressTests` TEN times (mixed single/class filters,
|
||||
one full bin/obj clean-room among them) and report every outcome. The
|
||||
mechanism predicts the absorbed-tick latch becomes STABLE at the tangent
|
||||
rest (no lift — the settle leaves perp = r, bare trigger inert). If the
|
||||
flip persists, capture per-tick positions inside the test (temporary
|
||||
prints) and report the matrix — do NOT recalibrate goldens on a flipping
|
||||
measurement.
|
||||
|
||||
**D3 — conformance + regression:**
|
||||
- Exact-value tests for the new resting identity on a tilted plane
|
||||
(perp = r), the flat-ground case (unchanged: N.z=1 makes planted and
|
||||
tangent identical — this is why the suite never saw the difference), and
|
||||
the water sink-in cases (AP-10's 0.1/0.45/0.9 depths, unchanged
|
||||
behaviourally per D0's waterDepth pin).
|
||||
- The uphill no-flap guard (`Uphill_NoContactFlapAcrossTicks`) must stay
|
||||
green — the mechanism predicts it does (tangent rest + bare trigger =
|
||||
retail's own stable pair).
|
||||
- Sabotage: revert ONLY the ValidateWalkable half — the un-skipped AD-66
|
||||
exact-value tests stay green but the new resting-identity test reds AND
|
||||
a re-run of the user's capture analysis script over a synthetic planted
|
||||
rest shows the 84% fire pattern returning. Report verbatim.
|
||||
|
||||
**D4 — bookkeeping (session lead does the register/ISSUES edits):** AD-66
|
||||
retires with the pair; AD-69 retires; #341 closes; the AD-65 register
|
||||
retirement gains a sibling note.
|
||||
|
||||
## Scope — OUT
|
||||
|
||||
The sliding/crease arm, the #331 absorb semantics (crease arm — untouched
|
||||
by this pair), any scaling change (AP-156's question is separate), indoor
|
||||
EnvCell walkable paths beyond what D0 proves shares the same
|
||||
validate_walkable, S1B's files.
|
||||
|
||||
## Acceptance
|
||||
|
||||
Full suite clean-room green (all bin/obj deleted first — this family has
|
||||
burned three verdicts on stale artifacts); D2's ten-run matrix reported;
|
||||
nothing committed. Absolute paths, no subagents, contradictions → STOP.
|
||||
|
||||
## The gate (user, ~3 min)
|
||||
|
||||
Same slope run as this morning's G1, plus: stand still on a steep slope and
|
||||
LOOK DOWN — feet slightly above the surface is CORRECT (retail's look).
|
||||
Downhill speed must remain the post-AD-65 feel. Any per-tick jitter,
|
||||
bouncing, or Falling-animation flicker on slopes = FAIL, revert the slice.
|
||||
Loading…
Add table
Add a link
Reference in a new issue