Army Men same-surface BltFast conformance, 2026-10-20

The source-phase account below is historical. The subsequent full-VM validation and two adjacent test-fixture corrections are recorded at the end.

Base: origin/main fetched and resolved to 515897841fde86f9b2e0274387aff10cc9add405. Isolated sparse worktree: /tmp/wa-army-bltfast-oct20, branch task/army-bltfast-conformance-oct20. No shared HEAD/index changes, workers, game rerun, browser, full build, binary copies, deployment, Claude panes, laptop scheduler or Heroes II changes.

Result

The baseline production no-color-key row loop passes all 192 cases using the eight traced geometries (each separately and in a synthetic sequence, at four pixel sizes and three pitches). It fails a separate downward same-surface overlap control. Top-down row copies overwrite the next source row before reading it. Per-row $memcpy uses overlap-safe memory.copy, so horizontal overlap within a row is already protected.

The change copies bottom-up only when the backing pointers are equal and the destination starts below the source within its vertical span. Upward, horizontal, identity and vertically disjoint copies retain their row order. The changed production row body passes 276 snapshot cases. This is a demonstrated synthetic overlap bug, not an explanation or fix claim for Army Men's visible stripes: every captured copy moves upward.

Original evidence and boundaries

Read retained scratch/runs/20261019-army-men-scroll-entry-remote-v1/: review.json, child.json, controller.js, pins.json and trace plan. Controller SHA-256: 7c70e72d68cb2d7c2b184c557178e00892bc2938c84fa6d85c3f38a0ddf6ffa7. Pinned historical module: 7fd02a77ec01e5e18065d112b1da434886a0dba3fcadd7ff043d1e2ddca41f33. The historical controller records child43272/controller42566 and original pre-push observations, not current execution or a BltFast return value.

Same source/destination 0x08221080, flags 0x10; source rectangles: (3,1,640,386), (4,1,640,386), (5,1,640,386), (4,2,640,386), (3,2,640,386), (2,2,640,386), (1,3,640,386), (0,3,639,386). Destination (0,0) except final (1,0). Pitch, pixel format, backing pointer and returned HRESULT remain unknown. No pitch was inferred from an image. The synthetic sequence omits intervening guest rendering and is not a replay.

The Microsoft BltFast reference describes source-copy/color-key transfers and excludes clipping. These cases are valid, in-bounds, no-color-key copies; they do not extend clipping, color-key, compression, aliasing-between-distinct-objects or error semantics.

Test architecture and proof

test/test-directdraw-bltfast-overlap.js uses only Node built-ins. It extracts and interprets the actual folded WAT no-color-key row body, with explicit supported operations and an execution budget. $memcpy maps to overlap-safe Uint8Array.copyWithin; a source assertion checks the production primitive still uses memory.copy. This avoids testing only a handwritten model of the implementation, but is not compiler or full-handler runtime validation.

The oracle independently maps destination pixels from an immutable pre-call snapshot, including each byte of multi-byte pixels. Two literal pixel matrices check the oracle for horizontal and downward overlap. Entire buffer comparison also checks row padding, untouched pixels and allocation guards. Fixtures use synthetic 640x386 surfaces, bytes/pixel 1/2/3/4 and pitches 640 * bytesPerPixel + {0,4,28}. None is asserted to be Army Men's actual pitch or format. Additional controls exercise left, right, down, down-left, down-right, identity and vertically disjoint copies.

Baseline reproduction, using the new test against the old source:

git show 515897841fde86f9b2e0274387aff10cc9add405:src/09a8-handlers-directx.wat > /tmp/army-bltfast-baseline.wat
node test/test-directdraw-bltfast-overlap.js /tmp/army-bltfast-baseline.wat

Expected baseline result: 192 traced-geometry cases pass, then exit1 at down/1/0, byte1312, actual165 versus expected254. This corresponds to the second destination row reading an already overwritten source row.

Current source:

node test/test-directdraw-bltfast-overlap.js
node tools/check-wat-fragments.js src/09a8-handlers-directx.wat
node tools/check-parens.js src/09a8-handlers-directx.wat --no-diff
node tools/check-wat-logical-and.js
node --check test/test-directdraw-blt-clipping.js
git diff --check

All pass. The label checker reports existing large-depth-change warnings, with balanced parentheses and labels in scope.

test/test-directdraw-blt-clipping.js already uses bootRenderHarness, which compiles the full module. Its fixture now supports padded pitch and adds five actual BltFast same-surface cases with flags0x10, full pixel/padding snapshots and HRESULT assertions. Only syntax checked here: running it and normal build gates is pending a separately admitted full VM validation lane. No gameplay or performance claim follows from the source-level tests.

Small evidence and check receipts: scratch/runs/20261020-army-bltfast-conformance/receipt.json, baseline.log, conformance.log, fragments.log, labels.log, logical.log, syntax-conformance.log, syntax-runtime.log, diff.log. The receipt records input/source hashes; Git retains tests and this recovery recipe, not ignored run evidence. Free disk at the receipt was 2,318,901,248 bytes, above the 2GiB floor.

Next diagnostic, requiring a new assignment

The authored full-handler regression has now passed in the admitted environment recorded below. For Army Men itself, a future bounded diagnostic should observe the same actual call at handler entry and return: surface identity, resolved backing, width/height/bpp/pitch, source RECT/destination/flags, returned HRESULT, and small pre/post pixel samples that distinguish a packed row from a pitched row. Compare bytes against a pre-call snapshot before attributing corruption to BltFast. Include the first sample before the copy to detect pre-existing corruption. The existing pre-push trace alone cannot establish that the copy executed successfully or that incorrect bytes originated in this handler. No such runtime was performed or authorized in this assignment.

Runtime context verification limitation

Before source edits, read ~/.codex/AGENTS.md, project CLAUDE.md, app notes and latest messageboard. Runtime session ID: 01a158cb-20d2-7981-b2fd-fd8339d624f3. Read-only logs_2.sqlite queries found no per-thread compaction/200000 records; a bounded recent-global query only showed coordinator48000 BodyAfterPrefix rows. Thus 200000 total could not be verified from available runtime evidence. This limitation was appended to the shared messageboard before edits. No config-only verification claim or repeated probing followed.

Full-VM validation, 2026-10-20 10:34–10:38 UTC

The coordinator assigned bx_b7sxrkh9 exclusively for this synthetic validation. No game, benchmark, held diagnostic or local full build ran. Source was 9951a1d83d98b80418cb72e053242cbb5b09e659, streamed with git archive --format=tar.gz through the documented Boat Files upload API. All 6,864 regular source files were SHA-256 verified before and after the initial tests. Archive SHA-256: 4ff05820a2b8c884b1c33e50bffa4f691f6317f16e0e2133f5ab5bc4700ed638. Fresh origin/main remained 515897841fde86f9b2e0274387aff10cc9add405; no merge was performed.

Remote root: /home/user/army-validation/source. Node v24.18.1, npm 11.16.0. Setup and normal build both exited zero:

timeout -k 10s 300s npm ci --ignore-scripts --omit=optional
timeout -k 10s 480s bash tools/build.sh

Normal tail-call module: 1,874,813 bytes, SHA-256 76ff73ed52bce2cbc60bf7234eced7aa9963b4dd2ff2a309299cc6225c28e638. Compatibility module: 1,877,386 bytes, SHA-256 d70adaf6c634931a93766ffb6ef8159107897d473990a78012daf01a86422a71. All normal build gates passed, including compiled data-segment overlap checks.

Each test ran serially using:

timeout -k 10s 180s node \
  --require /home/user/army-validation/observe-compile.js test/TEST.js

The retained external observer wraps compileSrcWasm, saves and hashes its returned bytes, and returns those same bytes unchanged. The tests compile the full source closure with their own test exports, so their module hashes differ from the normal build. No handler or host behavior was replaced.

Test Result
test-directdraw-blt-clipping.js PASS clipping and five real-handler same-surface/padded-pitch cases, including down and down-right
test-directdraw-ckey-blit.js PASS 3,640 cases, 8/16/24/32bpp
test-directdraw-blt-status.js PASS surface/query validation
test-directdraw-dxt-blt.js Initially FAIL at Lock, then PASS after fixture correction
test-directdraw-palette-format.js Initially FAIL at GetSurfaceDesc, then PASS after fixture correction

Both initial failures were E_INVALIDARG (0x80070057). Substituting only the pre-patch DirectDraw fragment from 515897841 reproduced both exact failures; the fixed fragment was then restored and hash-verified. The DXT test filled the output descriptor with 0xcc, including dwSize; the palette test left dwSize zero. Existing $dx_surface_desc_valid requires the legacy descriptor size, 108. Each correction initializes that one field before calling the real handler. Both corrected tests passed with their original assertions intact, using the same compiled module hashes as their initial failing runs. Production source was unchanged. Final source verification found exactly these two test-file differences from the archived commit.

Evidence recovered and SHA-256 verified on the host: scratch/runs/20261020-army-bltfast-fullvm-validation-2/. recovered/ contains the full build/install/test logs, original failures, baseline controls, corrected results, source postflights, exact test commands and artifact-manifest.json with all normal/harness module hashes. source-manifest.json, upload receipts, exec receipts, stage.py, observe-compile.js, run-tests.py, baseline-check.py, and corrected-tests.py retain the source and reproduction procedure. The recovered evidence archive is 6,958 bytes, SHA-256 5914e5b1fe698145b31d5a5c06405bda800a42ff9944dc1f39cbb223d98970ed. Module binaries remain remote; they were not duplicated onto the disk-limited host. Rebuild from the pinned commit and use the retained observer to reproduce the listed hashes.

This validates the synthetic downward self-overlap fix. The 192 captured upward-geometry source cases already passed the baseline; Army Men's terrain stripes remain unexplained, and no gameplay improvement is claimed.

Integration review, 2026-10-20

Fresh origin/main was still 515897841fde86f9b2e0274387aff10cc9add405, the laptop Warcraft III commit and ancestor of both reviewed commits. An isolated sparse checkout fast-forwarded through 9951a1d83 to 3b4330ef5; production source is identical to the tested source. Independent review verified all 47 local evidence hashes, all 6,864 source manifest entries against Git blobs, baseline handler identity, both corrected fixture hashes, original/baseline failure logs and successful test/build logs. The observer returns the compiled bytes unchanged; initial and corrected DXT/palette harness hashes match. Binary hashes are retained remote observations, not a claim of locally recovered module binaries.

The canonical shared Army task text matched main before the scoped ledger update. Unrelated shared ledger edits, HEAD/index and laptop work were left untouched. Only static evidence/ancestry/diff review ran during integration; no new build, runtime, browser or deployment. Exact task/main push receipts are recorded on the append-only shared messageboard.