THE HUNT (the deterministic rig repro made it a two-hour arc):
1. cdb write-watch armed from the Torso ctor (bp plants `ba w4 this+0x21c`
per torso -- ASLR-proof). The poison reproduced (atUpd=-1250 this run;
-3750 and int-15-as-float before)... and the watch stayed SILENT. Nobody
writes the garbage. The field is never INITIALIZED.
2. Confirmed in our ctor reconstruction: it inits every neighbour but skips
targetTwist @0x218 and twistAtUpdate @0x21C (the function that zeroes
them is a death-reset handler, not the ctor).
3. Confirmed in the BINARY: the real ctor @004b6b0c contains no store to
either offset -- a genuine 1995 latent bug (uninitialized read on the
copy path).
4. Why the pod never showed it: MemoryBlock arenas carve fresh OS-zeroed
pages, one pool per type, low churn -- first allocations read as zero.
The engine's own DEBUG_NEW_ON NaN-fill proves the developers knew the
hazard class. Why WE show it: mechrecon.hpp's Memory::Allocate shim
("a plain heap allocation is behaviour-equivalent" -- false) recycles
dirty heap. Replicant torsos spawned with garbage twist targets; the
limit clamp turned any garbage into FULL TWIST -- rendered "twisted full
right while not using TT" to every peer (playtest night 4, 3 reporters).
THE FIX -- environmental, class-wide, byte-faithful to the binary's code:
Memory::Allocate / AllocateArray / Alloc now ZERO-FILL, reproducing the pod's
EFFECTIVE allocation semantics for every never-stored field in every
reconstructed factory at once (Torso, Reservoir, all of them). No ctor gains
stores the binary lacks.
PROVEN on the rig: the replicant thor now spawns cur=0 target=0 atUpd=0
(was cur=-3.31613 = hard against the limit). Teardown clean.
Ships with part 1 (the dead-reckoning clock fix) in the next zip. Remaining
on #67 for the next games night: live confirmation that twist TRACKING looks
right in play, and whether the fire-from-centre facet (very plausibly the same
never-stored-field class, now zeroed) is cured with it.
Tools kept: scratchpad/torso_watch.cdb + rig_watch.ps1 (the ctor-armed
write-watch pattern -- reusable for any "who wrote this field" hunt).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
50 lines
2.1 KiB
PowerShell
50 lines
2.1 KiB
PowerShell
# Watch-rig: pod B runs UNDER cdb with the torso write-watch script.
|
|
$repo = 'C:\git\bt411'
|
|
$content = Join-Path $repo 'content'
|
|
$scratch = 'C:\Users\EPILECTRIK\AppData\Local\Temp\claude\C--git-bt411\89ab96e9-6cf0-4555-939d-05bf3708745a\scratchpad'
|
|
$exe = Join-Path $repo 'build\Release\btl4.exe'
|
|
$cdb = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe'
|
|
if (-not (Test-Path $cdb)) { $cdb = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe' }
|
|
$relaylog = Join-Path $scratch 'watch_relay.log'
|
|
$pidfile = Join-Path $scratch 'watch_pids.txt'
|
|
|
|
if (@(Get-NetTCPConnection -State Listen -LocalPort 1520 -ErrorAction SilentlyContinue).Count -gt 0) {
|
|
"ABORT: port 1520 in use"; exit 1
|
|
}
|
|
Remove-Item $relaylog, (Join-Path $scratch 'cdb_torso.log') -ErrorAction SilentlyContinue
|
|
$pids = @()
|
|
|
|
$relay = Start-Process -FilePath 'python' `
|
|
-ArgumentList '-u', (Join-Path $repo 'tools\btconsole.py'), '--relay', '1520',
|
|
(Join-Path $content '_TWIST.EGG'), '--bind', '127.0.0.1', '--manual-launch' `
|
|
-WorkingDirectory $content -PassThru `
|
|
-RedirectStandardOutput $relaylog -RedirectStandardError (Join-Path $scratch 'watch.err')
|
|
$pids += $relay.Id
|
|
Start-Sleep -Seconds 3
|
|
|
|
$env:BT_START_INSIDE = '1'
|
|
$env:BT_DEV_GAUGES = '1'
|
|
$env:BT_RELAY = '127.0.0.1:1520'
|
|
$env:BT_MATCHLOG = '0'
|
|
$env:BT_LOG_APPEND = '1'
|
|
$env:BT_TORSO_LOG = '1'
|
|
|
|
# pod A: normal (the master we ignore)
|
|
$env:BT_LOG = 'w_a.log'; $env:BT_SELF = '127.0.0.1:1502'
|
|
$a = Start-Process -FilePath $exe -ArgumentList '-egg','_TWIST.EGG','-net','1502' `
|
|
-WorkingDirectory $content -PassThru
|
|
$pids += $a.Id
|
|
Start-Sleep -Seconds 2
|
|
|
|
# pod B: UNDER CDB with the write-watch (its replicant torso is the victim)
|
|
$env:BT_LOG = 'w_b.log'; $env:BT_SELF = '127.0.0.1:1602'
|
|
$b = Start-Process -FilePath $cdb `
|
|
-ArgumentList '-logo', (Join-Path $scratch 'cdb_torso.log'),
|
|
'-cf', (Join-Path $scratch 'torso_watch.cdb'),
|
|
'-o', $exe, '-egg', '_TWIST.EGG', '-net', '1602' `
|
|
-WorkingDirectory $content -PassThru
|
|
$pids += $b.Id
|
|
|
|
Set-Content -Path $pidfile -Value $pids
|
|
"relay=$($relay.Id) podA=$($a.Id) cdb=$($b.Id)"
|