referenceUpdated Aug 26, 202641 min read$27

The Character Looked Finished. The Test Harness Said No.

Five fighters passed the editor checks. That did not prove they could fight. The gates that catch wrong builds, misleading screenshots, and missing move behavior.

Jump to evidence
cps2reverse-engineeringmshvsfmarvel-vs-capcomtest-harness
CPS-2 Reverse EngineeringPart 29 of 43
Browse all writing
On this page

P01 editor oracle

Join v5: names and slots closed, live behaviour not claimed

verified is dest cell at the resolved (L1, sub) plus name agree / family / elsewhere. This is editor geometry.

nativeverifiedbridgeddonorpending
routeHIT chainsdest cellsnamesslots
Rogueverified196verified197verifiedverified
Magnetoverified186verified268verifiedverified
Stormverified183verified307verifiedverified
Shumaverified169verified169verifiedverified
Dark Sakuraverified223verified223verifiedverified
live damage lanespendingpendingpendingpending
ORACLE_SCOREBOARD.json. The last row is the original gate: still pending, still fail-closed.

2026-08-25: exact V18b is measured, not percentage-scored

The current private candidate is V18b SHA-256 fe6b487b7f75fe7b562e549892e872a492d92060001956fe0ef34b099195cdc5. Its fixed 97-requirement ledger has 17 ACCEPTED, 1 WAIVED, 63 OPEN, 15 HOLD, and 1 FAIL. That is 79 blockers, not a defensible completion percentage. The accepted rows are bounded: 24/24 walk/body-push; 24/24 stolen-Hadouken metadata, hit, block, chip, and debit; 8/8 combo negatives/positives; 8/8 Goodnight pose/captured-stun; and 8/8 Hadouken/Goodnight team placement. They do not imply complete normals, combos, specials, supers, audio, presentation, stock regression, or manual play.

The exact CATCH 07 scheduler is the one gameplay FAIL: source release is +140, while V18b releases at +136/+137. The sealed all-phase matrix now observes damage, displacement, and both-fighter idle in 32/32 positive Ryu lanes with zero watchdogs. It still lacks seeded damage, stun/pose, ground contact, cleanup, fresh throw-idle, extended play, and negative lanes. Selector, geometry, and launch remain HOLD; the full slam row remains OPEN. Exact V18b already contains record-1 $0100; the old watchdog belongs to an earlier isolated child. Independent review receipt SHA-256: f8f1b2ddc7b35b04c1cd28774cd4efe962c1975c02dedaa609c3f4b193109cac.

The first authority-bound scheduler attempt is invalid, not a gameplay FAIL: its source archive carried the wrong xmvsfj.key, MAME never left startup screens, and the capture root is non-reusable. The R6 static preparer now derives the correct 20-member archive with key SHA-1 65905400f4462c175baa93b43e015e8596def31b, preserves all 19 non-key members, and passes 13/13 adversarial tests. It does not run MAME. A fresh successor authority, independent review, token, lock, and root remain required.

V29: one proven helper rebase, still zero runtime

The harness now has a newer static-head artifact to describe without overstating it. Exact V29 SHA-256 573b7224c2160bc830d53ab5fba55389825727b5ff1ed81828983687333bf14b is a direct child of V28. At $39C19C, it changes JSR $39CF8C—the graft's fail-closed RTS stub—to JSR $014EF2, the uniquely matched native MvC inner reset for the late D4=$08 route. The requested span is six bytes; only three operand bytes differ. No wrapper or code cave is introduced, and only mvc.10 changes.

The static build passes 10/10 focused tests and reproduces the full ZIP byte-for-byte from exact V28. Build receipt SHA-256: 6c422a59b81bb3b793cc2113ac118e1d9d94c55c069f253eb427d245d8163db5. That closes an artifact-construction question only. It does not show a move, score a frame, authorize MAME, or fix the separate class-$48 cleanup order.

The exact-V29 matrix preserves the full denominator: 2,956 ordered future cases in 58 groups—210 source and 2,746 target—covering all 85 runtime-testable ledger lanes. A matched source/current-V28/patched-V29 late-route trace is carried as an additional zero-case scoring obligation. Request, token, command, stage, capture, recording, result, and credit fields remain empty. In harness terms, that is coverage prepared / execution hard-locked / 0 cases, not a pass. A distinct sibling review reconstructs the matrix and passes 30/30 adversarial tests; it approves static catalog adoption only and grants no runtime credit.

The ownership audit also keeps saying no. A carrierless delete-before-set rule can close same-address ABA only after every nonzero or unknown fighter +$267 writer is proved to pass through the acquisition wrapper; that semantic denominator is not closed, and a byte-exact wrapper proof still follows it. The MCP/catalog layer must keep Dual Rogue hard-locked.

The bounded Power Drain e6=$16 helper audit likewise refuses an attractive three-byte patch. Four of eight static gates close, but the inherited subtype-$08 surface matches 12/12 timing/count rows while raw lists/attributes match 0/12 and transforms only 1/12. Until those 12 records have a semantic list/transform/tile/palette/render map, the harness cannot promote timing similarity into a visible Power Drain animation claim.

The successor geometry proof resolves that mismatch through native MvC $181BF6: source bank 3 repacks into target bank 0 with all 303 cells across 12/12 records, matching oriented-cell, alpha, pen, and normalized-palette planes. Target bank 3 fails every record. The next exact defect is therefore V29's $3AB18A: MOVE.B #$06,+$47(A6); the bounded exact-site candidate changes $3AB18D from $06 to native $00. Because that preimage occurs twice, the harness forbids a blind pattern replacement. Independent review, live palette/RGB and cadence, cleanup, owner/player/facing coverage, and stock class-$38 regressions remain open; no ROM, runtime, or parity credit follows.

Native-move R5 now seals a passive observer and fail-closed scorer for 572 fresh MAME processes: 156 stock-XMvSF source point cases, 312 exact-V18b point cases, and 104 contextual-bench cases. The split is 324 transaction cases plus 248 residual cases. Its independent audit passes 42/42 Python tests and 5/5 Lua syntax checks, while the execution front door intentionally exits 3 with zero runtime cases. A reviewed pointer-normalization map, parent clearance, token, exclusive lock, isolated stages, fresh capture root, and continuous guard are still absent. Static receipt SHA-256: 2ff608d42961e81626d01918cf3e66a773010a372c9fa847f563a6d0aea02377.

R6 narrows the first executable proposal to a hard-locked two-case Repeating Punch smoke: one source case and its matching public-V18b case. Its audit and 15/15 tests pass, but every runtime binding remains null; execute exits 3 and cannot launch. Even a future successful smoke could earn infrastructure credit only—not gameplay acceptance or ROM-failure attribution. Receipt SHA-256: c521c20462d1cb0baf2cfe29b3401353dfaae099fcdecbad52d7846ef90b0c48.

The R6 pointer preparation remains HOLD_POINTER_NORMALIZATION_UNBOUND_ROM_NOT_EVALUATED: 0/9 R5 pointer fields is reviewed or statically complete. It also found a schema conflict. R6 proposes an entries map marked EXPLICITLY_REVIEWED_FOR_PHASE_A; R5 requires a fields/roles map marked REVIEWED_EXACT_RELOCATION_MAP_BOUND. R6 requires its reviewed map before the two-case smoke, while map review requires fresh pointer observations first. Receipt SHA-256: 1d7e39c61a229dbf98e05859ef1f5e22ea7186fbbfa1c2b20bee854727fc71b6.

R7 is the fail-closed bootstrap for that circular dependency, not a run. P0 preserves the exact 572-case R5 order and may only record the nine raw pointer fields: no comparison, score, PASS/FAIL, ROM evaluation, or credit. Its static audit and 19/19 tests pass, all 41 runtime/review/scoring bindings are null, and the hard lock exits 3. Runtime cases, captures, reviewed maps, scores, and ledger changes all remain zero. After independent map review, the scored matrix must still recapture all 572 cases. Receipt SHA-256: b271c657a69272f3a86e1132e3983e21a06407c16442cb2213a7a6bcb765c1a8.

R8c is not the activation answer. Its official audit and 35/35 maintained tests pass, but an independent 10/10 suite reproduces six safety blockers: an authority-bypassing public spawn path, an exception gap around spawn, request-controlled non-global locks, unsafe executable paths, no per-case/final identity replay, and non-durable process quarantine. It remains hard-locked and zero-runtime. Rejection receipt SHA-256: 29da3282926370d9fd4242f6fa3cf27d60e57e4de9e3292370e9d097cb6d272f.

R8d is rejected too. Its production front door is hard-locked, but an independent 14/14 adversarial suite reaches all 16 provider methods through a public synthetic lifecycle function that never checks that lock. Provider identity, global lock/nonce state, verified executable objects, fresh identity checks, process-tree absence, and durable keeper transfer remain unbound assertions. R8d remains unactivated and zero-runtime. Rejection receipt SHA-256: b8393d85e0c27ffa67f6e8027855b3ccdd0e38eb1624dff34147cf61cb65a517.

R8e removes that bypass by removing the runtime adapter itself. A whole-package AST audit finds no provider/backend, caller-supplied callable, predecessor import, process/lock/filesystem service, or activation surface. The zero-argument front door is literally return 3, and all 18 future runtime bindings remain null. Agent and independent root replays pass the audit and 16/16 adversarial tests. This is a sealed static tombstone, not an activation successor: runtime, ROM, guard, MAME, gameplay, and ledger counts remain zero. Receipt SHA-256: cea0f0a499a944fa2b2d24470d56c4e3c9a157040ca8165627825123c0b6a8b4.

The exact helper-route census also corrects an earlier shorthand. It accounts for 38 relocated calls across eight helper families: 34 still target RTS and four are promoted. Seven families retain RTS residue. The character-neutral $011600->$014EF2 homolog now has complete static ownership proof for exactly one private experiment at V18b's relocated $39C19C call. That authority does not extend to integration, acceptance, promotion, or any other RTS route.

The one-site experiment now exists only as quarantined private V19. Its ZIP changes mvc.10 and no other member, with exactly three logical data/opcode bytes changed at $39C19F/$39C1A0/$39C1A1. Independent --check, 9/9 focused tests, and archive integrity checks pass. SHA-256 is 31f17a70c4d00fbc0abf7dbd62997329634152ef21bd3e861cd473b4dca01c92; MD5 is be79abcc37985acc705ec849e9f946bf. It is runtime-untested, has zero gameplay/parity/ledger/release credit, and still needs every matched trace, owner/side, watchdog/throw, move, team/assist, and stock-caller gate. V18b—not V19—remains the current candidate at 17/97 accepted and 79 blockers.

Private V20 is a separate direct V18b child for identity-safe Goodnight victim geometry, SHA-256 f327cf7218e5994e0730c1d2b4465084960bbbbb15ee33ba770cb8d8ecc689a6. Its static build/review passes, Ryu remains on its existing route, and runtime credit is zero. The first correlated V20 trace/scorer proposal is rejected: independent 12/12 tests show accepted stale sessions, reversed/interleaved events, wrong tap/PC pairs, and self-consistent manifest substitution. V2 stays hard-locked; rejection receipt SHA-256: 41fca6836ea21471d5be7f94d7d6fa33c6bfdec2b7657060be7235796bc9b5c6.

The append-only V3 replacement now passes its independent static review. It starts at the exact captured-victim leaf $01418E and requires a contiguous, same-frame route through $39F9E0, $3AB000, optional fallback $014236, order-only $014254, and exact A3 checkpoint $014284. It validates every complete repeated session and rejects stale/interleaved streams, self-consistent manifest substitution, and wrong-but-even fallback bases. The denominators remain 64 mapped target lanes, 128 exact-base fallback lanes, and 24 unscored source lanes. Root replay passes 12 generator, 20 scorer, and 10 independent tests plus Lua syntax. This approves only the static selector-route/A3 contract; activation and all runtime/gameplay/ledger credit remain zero. Independent review receipt SHA-256: df2cd63b6a079316d6f881c8b74fae21ece521307638b8d160d34bb558943bec.

The exact-V18b/V20 heart transfer preserves the source Rogue palette, decoded visible tiles, list transforms, normalized animation, motion, constructor, and complete class-$84 surface. No static color patch is authorized; a matched exact-build live matrix remains required. The separate late class-$48 helper is not the visible kiss particle. Static receipt SHA-256: adfc2f0074939918a0386c7e6b2580a4a622a42fa8b5c0e6a7193ae72fe6cf64. An independent 9/9 adversarial replay confirms the source-exact transfer and the no-color-patch boundary; review receipt SHA-256: c4597771aa294d32da8c0f29810d702088c1980a6a7bf9a7e73238fa42d7d736.

Private V21 is a static-only child of exact V20, SHA-256 d5d0cb249afba1c295009cd14214b920e935d4436b64997169180b7f18a2df0e. Across the same 28 class-$38 callsites, its route census changes from 25 RTS / 2 native / 1 Goodnight to 24 RTS / 2 native / 1 Goodnight / 1 Repeating Punch. Target-private $5250 (RP) metadata gates outer router $3AB156; tagged subtype-$08 objects go to translated handler $3AB176, while every non-RP object tail-jumps to the unchanged $39E456 Goodnight router. The translation covers source $066134..$06617B only. $06617C starts the separate class-$3C constructor and was deliberately excluded. Only mvc.10 and mvce.03a differ from V20. Build receipt SHA-256: b7d6f5f13794f91deef70e06bd54d20e71da8ba3b257ec8ff8ccd107307682d7. Maintained 11/11 tests and independent 14/14 adversarial tests pass with verdict APPROVE_PRIVATE_STATIC_ONLY; independent review SHA-256: e3ca0a6d5338657066a817a60687dc59d7502bc834973465f16aeb1928ade652. No emulator ran. All eight live gates remain, this grants zero runtime, gameplay, parity, or ledger credit, and exact V18b remains the 17/97 baseline with 79 blockers.

Private V22 demonstrates what the harness must keep separate. Its exact current QSound package has 35 actions, 28 PCM clips, four common actions, and $8000 sample-window locality. The archive changes only two program members and four QSound members; 7/7 maintained and 14/14 independent static tests pass. But there is no ordinary input→owner post→voice→WAV chain, so the harness records static audio package PASS / audible audio NOT EVALUATED, not “sound fixed.”

Private V23 adds another reusable lifecycle gate. Both pool-C allocators clear only object $00..$5F; Goodnight $4753 and Repeating Punch $5250 live at +$6E, and native free does not clear it. V23 changes one member and 89 logical bytes: both tagged cleanup routes clear +$6E, and RP's class-$3C constructor clears inherited metadata only after allocation success. Its $38 failure branch skips failed A0. Maintained 7/7 and independent 14/14 tests pass while runtime credit remains zero.

The same preservation rule now covers the reported Goodnight carry pose. V23 retains 13 byte-exact program/data surfaces from the accepted V16/V18b Ryu captured-stun lineage and the exact $12->$39FA00->$014254 selector route. But prior captures cannot be relabeled as V23 evidence: V20's selector was unrun and V23 changes cleanup. The harness therefore records implementation preserved / exact-V23 runtime not evaluated, while roster-wide victim choreography stays OPEN.

The prepared V23 lifecycle contract now has exact, non-double-counted arithmetic: 120 inherited RP rows once plus 424 target-only lifecycle rows = 544. The 424 split is 128 reuse/pressure, 96 RP cleanup, 24 Goodnight cleanup, 32 allocation failure, 40 other grafted-Rogue negatives, and 104 stock-native negatives. It balances 320 oriented rows at 40 per public/secret × P1/P2 × facing tuple. Independent 18/18 adversarial tests reject missing/duplicate lanes, unsafe failure, omitted cleanup, command injection, and false credit. Clearance stays null and activation HARD_LOCKED.

The visual harness denominator is now exact too. The static census finds 278 addressable actions per owner, one shared physical tree, 1,488 records, 784 actor lists, and 14,359 mapped tiles. Every mapped tile payload matches and no unexpected Hulk-residue tile is reachable. Seven timing records and six actor- list records form the entire known mismatch set; one EFFECT-00 stub accounts for 19 unreachable Rogue tiles. Nine named hypers are statically exact, but their runtime backgrounds, cut-in routing, palette, ownership, and cleanup are not. The independently reviewed core projection is 126,704 bytes across 20 normalized intervals.

The first exact-V23 visual preparation failed review because it expanded the surface with 578 directory/label bytes while omitting 328 required cut-in bytes. The append-only V2 proof restores both record tails and both portrait palettes, yielding an exact 127,282-byte / 17-interval superset. Its matrix is still 2,628 HOLD rows. Complete developer-menu traversal plus retained-stock injection makes 2,308 rows permanently ineligible for parity credit; only 320 are natural or natural-route-pending. No command, screenshot, recording, or runtime row exists. This is the reusable rule for every port: the secret menu can enumerate data, but only ordinary controls on the exact candidate can accept behaviour.

Audio and speed remain runtime-open. V18b still carries its mixed QSound row; V22/V23 are quarantined static descendants. The owner-post design defines 216 future processes but has executed zero. The split-clock speed design has also executed zero; each owner still needs 120 cumulative within-gameplay-segment host-monotonic seconds and 240 samples under throttled, audio-enabled MAME.

2026-08-22: portable progression, not portable PASSes

The useful parts of this lab are now reusable without copying its conclusions. tools/cps2_progression_v2 is a non-executing validator and planner for one fighter at a time. A profile can end in only HOLD or RUNNABLE. RUNNABLE means its declared inputs exist and match their hashes; only the fighter-specific scorer may later write PASS or FAIL from a fresh emulator run.

That distinction matters because a technically successful launch can still be the wrong game. Every target profile pins the modified archive SHA-256, build manifest, MAME binary, expected driver, and isolated staged name driver.zip. It also carries a stock-ROM denylist. A stock mvsc.zip, stale candidate, wrong driver, reused ROM directory, mismatched harness, or old receipt fails before gameplay evidence can be considered.

LaneRequired executorWhat it may establish
source oraclepinned native backend: MAME or Flycastexpected source behaviour for a scorer
ordinary controlspinned MAME target drivertarget behaviour under normal P1/P2 controls
audiothrottled, audio-enabled MAME targetsample speed, voices, effects, and music behaviour
presentation / stockpinned MAME targetanimation, CSS, intros, effects, and unmodified-game regression
manual windowedwindowed, throttled, audio-enabled MAMEa separate human release receipt
secret menu / editordiagnostic FBNeo or disposable dev ROMtable, box, OCR, pointer, and coordinate data only

The ordinary-control lane repeats four explicit axes: player, facing, public/secret roster ownership, and point/bench team role. Motions require natural spacing and at least one neutral frame; P2 needs a recorded input-port binding. During measurement, fighter action, animation, state, XY, life, and meter are read-only. A harness may write the emulator input port, but it may not manufacture the state it is supposed to test.

The secret-menu collection has the same narrower boundary. Its 15 named profiles now pin the source or dev-ROM SHA-256 and, for XvSF profiles, the key set SHA-256. That makes captures repeatable. It does not make the menu a source oracle for Dreamcast Cable, Neo Geo Zero, CPS3 Ken, audible QSound, walking animation, combos, specials, supers, or throws.

From CHARACTER_SELECT, the reusable preflights are:

python3 experiments/devmenu/check_secret_profile_pins.py
python3 -m unittest discover -s tools/cps2_progression_v2/tests -v
python3 tools/cps2_progression_v2/source_oracle_backends.py --check-files
python3 tools/cps2_progression_v2/progression_contract.py validate PROFILE.json --check-files
python3 tools/cps2_progression_v2/progression_contract.py plan PROFILE.json --check-files

The current catalog has eight full-fighter profiles: Cable, Zero, Dark Sakura, Shuma-Gorath, Magneto, Storm, Dual Rogue, and SF3 Ken. All eight pass structural and filesystem-hash validation. All eight plan as HOLD with actionable reasons and files_verified=true; no profile claims RUNNABLE or gameplay PASS. Each profile now names its destination dev-menu adapter. The five CPS2-source ports also name their separate hash-pinned source adapter; Cable, Ken, and Zero instead retain explicit cross-platform backend contracts. A source editor and a destination editor can therefore share evidence vocabulary without being misrepresented as one executable gameplay harness.

The final Dual Rogue scorer now enforces the same boundary inside the evidence, not just around it. Its 21 release gates map to exactly 33 artifact roles. Each role has a fixed internal schema, candidate and release-run binding, trusted validator hash, nested raw-input pins, and an exact case matrix: Power Drain is 184 cases, raw normals 432, and the advanced HIT menu 392. Duplicate roles, scorer substitution, incomplete matrices, changed raw inputs, and a summary with no matching samples fail. The manual speed gate parses at least 240 timestamped samples and cross-checks their measured minimum and maximum rather than trusting a typed summary.

One complete structured fixture passes that scorer. Sixteen negative mutations fail. Five of the 33 real artifact roles now have source-derived producers: the walk scorer emits separate eight-case public $06 and secret $26 artifacts, and the 810-case paired combat scorer emits the 432-case normals artifact plus 24 child-lifecycle family cases aggregated across every hit/block/whiff variant. The body-push producer adds two stock-source cases and eight public/secret P1/P2/facing target cases. Those producers refuse partial matrices, reused output directories, registry drift, and a mismatched validator hash.

The real release template still reports 0/21 because none of those producers has run against a completed final candidate under one fresh release ID, and the other 28 roles remain unwired or open. Local hashes protect integrity after capture; they are not external attestation against a person deliberately fabricating a fully conforming log.

The planner never launches MAME or FBNeo. Existing per-port runners remain the executors, which lets Cable, Storm, Magneto, Rogue, Zero, Dark Sakura, Shuma-Gorath, and SF3 Ken share identity and evidence rules without pretending their source games or remaining blockers are interchangeable.

The Rogue video audit: separate the real failures from the wrong oracle

The latest complaint was visual and specific: no forward/back walk, an idle body that seemed to hover when another fighter walked into it, broken grabs, a wrong-colored heart, missing air movement, and an XvSF-looking super shell. The right response was not to mark one broad “movement” checkbox. Each observation became a source/target pair with exact candidate identity.

Reported areaLatest evidenceRelease state
forward/back walkexact V18b's combined movement/body-push envelope passes 24/24 across public/secret owners, P1/P2, and both facingsbounded exact-V18b PASS; jumps, dash/super-jump links, broad actions, and manual release review remain open
idle body pushexact V18b preserves the seated collision rows, reciprocal roots, contact span, carry, Y, and vertical-velocity contract within the same 24-case envelopebounded exact-V18b PASS; this does not accept all movement or manual presentation
persistent flight / air movementXvSF Rogue has no persistent flight mode; the real source requirements are jumps, super jump, forward air dash, and air attacks. Private v13 reached source dash states/action and pool-C $003C lifecycle, but that is a different candidate hashhistorical v13 only; exact-V18b jumps, super jump, air dash, complete air attacks, MAME presentation, and release coverage remain OPEN/HOLD pending R5 execution
CATCH 07 throwexact V18b reaches damage, displacement, and both-fighter idle in 32/32 positive Ryu lanes, but releases at +136/+137 versus source +140 and lacks seeded damage/stun/pose/contact/cleanup/negative coveragenarrow functional observation; FAIL scheduler timing; full slam row OPEN
Power Drain heartexact V18b/V20 statically preserve source palette, decoded visible tiles, transforms, animation, motion, and class-$84; no static color patch is authorizedmatched exact-build live matrix required; presentation OPEN and latch/steal HOLD
MvC super presentationone public-v11 capture matched 96 activation tags and PNGs on a different candidateexact-V18b presentation remains OPEN; only bounded Goodnight pose/captured-stun is accepted
MAME smoke / FBNeo move contractprivate-v13 completed 26 historical lanes, but it is not exact V18b. Exact-V18b native-move R5 defines 572 source/target/bench cases and has executed zeroV18b runtime native-move matrix OPEN/HOLD; no deterministic blocker is cleared by static preparation
secret victim IDsfor public Rogue point-side, $2A now reaches Chun-Li $16/HIT $18A236 and $2C reaches Morrigan $1E/HIT $0FCC1Atwo-case connectivity PASS only; damage parity and the 184-case Power Drain matrix remain open
CSS figure densitythe authored 128x224 figure has 22,819 opaque pixels and 96 cells packed into four parts, removing the old 54-sprite ceilingauthored/static evidence only; live v11 CSS and human gates remain open
final releaseno final candidate has all behavior, audio, presentation, team, stock, and human gates0/21 final-release gates

These recordings stay attached to the claim they actually test. Neither clip is a substitute for the ordinary-control move matrix or the final human run.

clip · loops
HISTORICAL DIFFERENT-CANDIDATE PRESENTATION DIAGNOSTIC // Goodnight Sugar reaches its named state and an MvC-native shell in this clip. Exact V18b accepts only a bounded 8/8 pose/captured-stun scope; its cut-in, damage, recovery, both owners, all supers, and manual accessibility remain separate OPEN/HOLD gates.
clip · loops
HISTORICAL DIFFERENT-CANDIDATE DIAGNOSTIC // CATCH 07 latches and returns both fighters to play. This clip does not prove the `$3c` slam or exact-V18b timing; V18b's scheduler is a FAIL and the slam choreography remains OPEN.

The move-matrix correction matters more than the score. The historical shared CPS2 gate cleared defender +$B0/$B1 and +$C0/$C1 as if they were passive controls. In MvC, +$B0/$B1 is live action state and +$C0 is the reciprocal opponent-object pointer; passive input is +$D0/$D1. That gate was changing the game while claiming to observe it. Its completed 26-lane run is now sealed as INVALID_HARNESS_CAPTURE with zero attributed move failures.

The corrected gate preserves those engine-owned fields, samples the expected $00FF3000 pointer every live frame, and fails closed on any drift. That was still not enough: the first pointer-safe serial harness omitted MvC's pool-C head $FFDA44, so its class-$0038/$003C absence claims—and its old 2/24 score—are now sealed as INVALID_HARNESS_CAPTURE, not inherited as Rogue failures.

The isolated pool-C-aware v6 replacement completes all 26 public/secret captures with 26/26 stable pointers, zero invalid lanes, and zero missing lanes. Its honest score is 6 PASS / 2 deterministic FAIL / 18 HOLD_RNG_DISTRIBUTION. Every one of the nine damaging lanes per owner matches the source state set, action set, child-class set, child peak, spawn, and cleanup. All three negative air-input probes pass for each owner. Only the public and secret forward air-dash lanes fail deterministic checks: they do not reach states 02:14, 04:00, or action $3C. Class $003C is present and cleans up in both forward lanes, so it is not the missing mechanic.

The 18 damage holds correct a second bad oracle. Source and target Repeating Punch hit rows are byte-identical, and both select the same Ryu defense row. Their natural RNG streams choose different pre-defense factors: one ground-LP sample used source $21 versus target $1F, producing 7 versus 6 before the same later defense route. A fresh source Rising LP changed from the stored 9,8 sample to 9,9. Exact single-run damage is therefore telemetry, not a parity verdict. The next gate must align RNG seed and call ordinal or compare a predeclared distribution; forcing MvC's global RNG would change unrelated gameplay and is rejected.

The v6 diagnostic is bound to private-v11 SHA-256 a1741b1c…ef061e and remains separate from the 0/21 release gate. Receipt SHA-256 is b6c88a2cd90916d432cee75654899ec92c9bae32f8005358ed0207d813aca76f; capture-manifest SHA-256 is 300478d0c187392bae4e8286b187adef6ca927100ab36c966daf74b0f20ccf46.

The air-dash trace then separated entry from execution. Source $013758 supplies action $3C; the graft had mapped it to a behaviorally incompatible MvC decision routine. A private exact entry veneer restored $3C for both owners while all six back/PP negative probes stayed clean. It was still rejected: the downstream target handler entered wrong state 04:08, produced 183 invalid fighter frames instead of the source 02:06 → 02:14 → 04:00 path. Its old no-$003C observation is inadmissible because that capture used the pool-C-blind harness. The ZIP is retained only under _failed_experiments with a rejection receipt. It is not a candidate, and the next fix belongs in the downstream $3C action/tree transition rather than an input-forcing shortcut.

A private v13 downstream ABI translation repaired that transition without writing fighter state: both owners reached source states 02:14 and 04:00, action $3C, class $003C peak/cleanup, zero invalid frames, and stable opponent pointers; all six negative probes remained exact. The historical first bounded score rejected it for a supposedly target-only action $10. That interpretation was wrong.

The static trace found homologous source and target writers: action $10 is the stock turn/facing transition in both games. The old stabilizer kept only absolute distance. It placed the opponent at Rogue X + 240 until Rogue reached X=660; four pixels later, +240 exceeded the hardcoded arena threshold, so it silently placed the opponent at Rogue X - 240. The recorded distance stayed 240 while the opponent crossed through Rogue. The target then correctly turned and emitted $10; the source sample, which never crossed the threshold, did not. That old capture is incomparable, not evidence of a v13 port defect. Suppressing $10 would break correct behind-opponent behavior.

The v4 replacement seals setup X=$0100, opponent side +1, and signed distance +240. It never changes sides to avoid a boundary: it records an out-of-bounds sample and the scorer fails closed. A fresh serial capture clears all eight public/secret lanes—forward dash, back-dash negative, LP+HP attack negative, and back+LP+HP attack negative—with 8 PASS / 0 FAIL / 0 invalid / 0 missing. Every frame has the correct signed side, no boundary sample, and stable opponent pointers. The signed receipt SHA-256 is ef02f772ccb9108eefd40e10f581f718750182de4da0012f649a41c5ebc12d5d. The static root-cause receipt SHA-256 is dc770cc3cfd2820528e786c768f96f0272bd14506f5853b8754aa8625506801c.

The separately required retained-Ryu regression also passes under MAME 0.287 on exact v13 SHA-256 c1e8f491…a03bc. This clears the bounded air-dash blocker, not the fighter. A new serial run then completes the entire signed 26-lane native-move matrix for both owners: 8 PASS / 0 deterministic FAIL / 18 RNG HOLD / 0 invalid / 0 missing. All 26 preserve X=$0100, the declared positive side, exact source distance, stable opponent pointers, and zero OOB samples. Receipt SHA-256 is 269e9d1d12e775de70977bcf03a11003c401be15d23f71ed748fd28f9174d1f3. The 18 damaging lanes remain HOLD because natural source and target RNG streams are unsynchronized, not because their deterministic move contracts failed. V13 remains quarantined under _failed_experiments: matched-RNG evidence, full Power Drain, combos, grabs, supers, audio, effects, team/stock behavior, and the final recorded human windowed run remain open. No public or player ZIP was regenerated.

A fail-closed matched-seed diagnostic now covers one representative damaging family. Repeating Punch LP uses seed $1357 exactly once after setup and before input, with no later fighter/RNG harness writes. Source, public, and secret all produce damage [7,6,9]; all 92 infrastructure and 81 deterministic checks pass. It remains HOLD_MATCHED_RNG_STREAM_DIVERGENCE, not PASS: source damage stages occur at ordinals 27/28, 42/43, 57/58, while both targets use 34/35, 49/50, 64/65. Receipt SHA-256 is 881c93861d06826e67d77facd52f2e3801ee0ddec42b39779010b72b194858fd.

The fresh v13 walk/body-push result is stronger than a pointer census. Across public and secret Rogue's P1/right lanes, all four forward/back walks match source record/list selection, exact 20-record cycles, animation cadence, velocity/displacement, release, and scheduler behavior. Both idle body-push lanes match the accepted action/animation/geometry trace, preserve all four collision rows, keep zero Y drift, and retain exact native pair carry and opponent ownership. Result: 6/6 PASS, receipt SHA-256 3b95491bca3c7323d1e763ca5e81fea7d823d032d21cf1258c55786a6d72f770. This is P1/right-only runtime evidence; P2, facing-left mirror, human MAME, and release coverage remain open. A stock or stale mvsc.zip cannot answer a bad windowed video.

The push result corrected an assumption in the report. Stock XvSF Rogue is not immovable. Starting 96 pixels apart, Ryu reaches contact and the native resolver carries both fighters together while Rogue's own X/Y velocity stays zero. The source Rogue/Ryu row radii sum to 53 and discrete correction settles at 54. MvC deliberately retains its smaller native Ryu radius, so the correct hybrid destination span is Rogue 26 + MvC Ryu 24 = 50. The target gate therefore requires no pre-contact Rogue movement, fixed Y, zero self-velocity, exact 50-pixel contact, equal post-contact carry, and mirrored public/secret P1/P2 behavior. Comparing the whole trajectory to XvSF Ryu would wrongly replace a stock MvC opponent behavior.

The exact-V18b/V20 static heart transfer now preserves the source Rogue palette, decoded visible tiles, list transforms, normalized animation, motion table, constructor, and complete class-$84 surface. That closes the search for a simple static color edit: none is authorized. It does not relabel the historical private-v11 capture as exact-build evidence; a matched live matrix remains required. The separate late class-$48 helper retains older defects, but it was not the visible kiss particle and cannot be patched without live reachability and owner proof.

Historical CATCH 07 fixtures proved only a latch and bounded return. Exact V18b is now scored separately: all 32 positive Ryu lanes reach damage, displacement, and both-fighter idle with zero watchdogs, but source releases at +140 while V18b releases at +136/+137. Damage RNG was unset and the full seeded damage/stun/pose/contact/cleanup/fresh-throw-idle/extended/negative contract is absent. That scheduler row is a FAIL; selector/geometry/launch are HOLD, and the full slam row remains OPEN. A fixed delay patch is not authorized.

The super-shell diagnosis did produce one exact public-v11 presentation capture. Preserving the native MvC sprite-group ordering and splitting only at Rogue palette boundaries made all 96 activation tags and all 96 captured PNGs byte-identical to the passing MvC structural child. That closes the fault in that bounded capture, not the public/secret/final presentation matrix or the super itself: MAME measures public and secret Goodnight Sugar at 51/9 and 52/9 rather than the source 64/9. Private v11 stays quarantined, and none of these experiments was copied to the public ZIP.

Cable, Ken, and Zero now have honest source backends

The CPS2 target gate remains reusable across Cable, Storm, Magneto, Rogue, Zero, Dark Sakura, Shuma-Gorath, and SF3 Ken. Their source machines are not interchangeable, so source_oracle_backends.json now pins them separately:

FighterOrdinary source routeNative debug/editor lane
Cablecomplete MvC2 USA Dreamcast CUE plus all three tracks under pinned Fightcade Flycastretail WORK CHAIN, HIT FRAME, NML GRID, CPS GRID, and COMBO CK; natural entry unproven, data-only
SF3 Kenverified sfiii3n.zip under pinned MAME, with the current match capture retained as an incomplete diagnosticexecutable OBJECT LOOK/EDIT, HIT JUDGEMENT, CATCH JUDJEMENT, and FRAME code; natural entry unproven, data-only
Zeroverified svc.zip, Neo Geo BIOS/UniBIOS container, and pinned MAMESVC DEBUG OBJE, THROW OFFSET EDIT, SEQ TOOL, collision/velocity/animation/Data/Sound DIP tools; data-only

All three gameplay routes remain HOLD until a fresh-process adapter drives ordinary P1/P2 controls and proves its measurement window is read-only. The shipped Flycast training Lua writes the timer. The current SVC trace writes fighter position, life, and meter. Those are useful diagnostics, never gameplay oracles. The backend validator rejects a debug lane that claims behavior, a gameplay measurement with direct writes, a READY route without a ready adapter, an absent fighter route, or any changed file hash.

The shared CPS2 runner now also pins its reporter hash and understands neutral-observer lanes: most command lanes must leave neutral, while an idle body-push observer may legitimately stay in one action state and defer the actual verdict to its specialized source-derived scorer. That correction is shared with the active Magneto harness pins rather than living as a Rogue-only exception. The same gate preserves live action and reciprocal opponent pointers, writes only MvC's passive input bytes, and treats opponent side as part of the source scenario. It records signed min/max distance, expected side, sample and mismatch counts, setup X, and arena OOB count. At a boundary it skips the unsafe coordinate write; it never crosses the opponent through the measured fighter. Self-tests inject both pointer corruption and player drift: the first stops pointer attribution, and the second must surface an OOB failure.

A six-repository ABI scan propagated the rule instead of fixing one Rogue file. MvC uses +$B0/$B1 for action, +$C0 for the opponent relation, and +$D0/$D1 for passive input. XvSF uses +$A0 for action, +$B0 for the opponent relation, and +$C0/$C1 for input. A follow-up geometry scan found the threshold side swap in four reusable Magneto/Storm observers and four older Rogue live/source scripts. Those are now side-preserving and fail closed; Rogue's walk, body-push, and 830-case combat generators were rebased to inherit the same rule. The 167 generated/historical Lua snapshots that contain the old code were deliberately not rewritten—their inventory digest is d9844cbc47a7ba3dee11e15d2662d2812fce1f02599b0deaa8895103685950f2, and captures made with an exposed lane remain historical evidence only.

No matching threshold stabilizer was found in SF3_MVC, STORM_MVC, PSX_MVC, or CHARACTER_EXPANSION. Matching PSX-side writes were retained only where a probe explicitly declares move-state injection. All eight progression profiles—Cable, Storm, Magneto, Rogue, Zero, Dark Sakura, Shuma, and SF3 Ken—now require manifest-sealed signed side, exact signed telemetry, and OOB failure independently of their source backend. Their secret developer menu lanes remain hash-pinned and data-only; the geometry fix does not turn an editor into a gameplay oracle.

The audit that started it

The parity programs looked complete at the start of this audit. Thirteen dependency-ordered phases, 37 lanes for Magneto, expected evidence named per lane, fail-closed rules for crashes and donor actions. Then I asked each generated audit_plan.json a blunt question: which command closes each phase?

P00 Pin immutable inputs                           cmds=0
P01 Capture source and destination editor oracles  cmds=0
P02 Identity, palette and select presentation      cmds=0
P03 Idle and movement state machine                cmds=0
...
P12 Stock regression and release battery            cmds=0

Every named command in the entire program -- eight of them -- was P00/P01 infrastructure: source editor, destination editor, a similarity comparator, the coverage ledger, two triage probes. The lanes themselves declared requirements without producers:

{"id": "special.hyper_grav_lk_hk",
 "requires": ["command","animation","collision","child_lifecycle",
              "damage","stun","cancel","reaction","audio"],
 "evidence": []}

The dev-menu harness reads editor tables. It cannot observe a move landing on an opponent. So P02 onward was not blocked by hours of work; it was blocked by an acceptance tool that did not exist. Five fighters sat at 0, 1, 1, 1 and 1 closed lanes, and every non-zero entry was the same written "flight is not applicable" waiver.

The v2 contract now defines how those later executors must be pinned and how their evidence must be separated; it does not invent the missing observations. The sentence is still true for damage. It is no longer true for P01. The rest of this article is the original build log for the live gate, then what the editor dump actually became.

One byte, and a diagnosis that was wrong

Before building anything, a capture on the Magneto build reset the machine. The program listed it as a known blocker alongside "CATCH EDITER still exposes the Captain America donor row."

The capture told a cleaner story than the blocker did. The secret menu rendered correctly at frame 775 with the cursor on HIT EDITER; by frame 1060 the board was on the title screen, and all 45 captured screens after that walked the attract loop. The editor object read all zeros because there was no editor.

Three builds, one differing byte at $3FD616:

Buildbytes at $3FD610HIT EDITER
magneto direct16e0c2e00520008667c…resets
stable1 gameplay6e0c2e00520008667c…resets
stable1 native editor v286e0c2e0052000c667c…passes

A branch displacement of $08 landed mid-way through the following absolute JMP. The project's own build_ds_devmenu.py documents the repair: HIT EDITER opens on stock id $00, takes that branch, and raises a CPU exception before drawing its first screen. Dark Sakura's gameplay build fails identically. It was never a Magneto regression.

The donor row was a second wrong diagnosis. The dev menu carries its own 23-entry roster string table at $0DBE72, and MvC ids are index x2, so Magneto's $04 is index $02 -- whose stock string is Captain America's. The identity layer had updated select art, HUD and logo, and never this table. Nothing donor-shaped was leaking into gameplay; a label was stale. Twenty-three bytes fixed both: one for the branch, sixteen for the name, applied to both program pairs because MAME loads the second one.

Do not set CPS2_SECRET_MVC_NATIVE_ROWS=1 on a zip that already has the $3FD610 thunk. Dest profiles keep overlay 0. Names come from HIT OCR.

The gate refuses on purpose

The scorer's most important behaviour is rejection. Feed it a flawless capture -- move came out, opponent took damage, projectile spawned and tore down, audio fired -- and it still fails:

[FAIL] damage   no source-derived expected damage supplied;
                cannot accept a value against nothing

A move that does something is not a move that does the right thing. That single rule is what forced the rest of the live-round work: to accept a damage number you must first measure the source game, and to measure the source game you must know where its health lives.

P01 does not get a pass from this rule. A named HIT cell is not a landed Hyper Grav.

Where MSHvSF keeps its health

Nobody had mapped it. Three attempts failed informatively.

MvC's $FF3000/$FF3400 read as all zeros under MSHvSF -- the map does not transfer. The busiest windows in a work-RAM activity sweep, $FF6800 and $FF6C00, armed and churned heavily but contained no health-like field as a byte or a 16-bit word. "Most active object" turned out to be a poor proxy for "fighter root"; those were effects or partner objects, which is also why their activity ranking reshuffled between runs.

Dropping the base entirely and scanning all 64KB of work RAM for behaviour -- falls in chunks rather than ticking by one, plateaus between hits, rests at full health for a large share of the match -- produced pairs sharing a ceiling at a plausible object stride. One resolved consistently:

$FF3E5B - $FF3C00 = $25B
$FF425B - $FF4000 = $25B
$FF465B - $FF4400 = $25B

Confirmed by direct observation across a live match:

f=1800   s1=144  s2=144  s3=144
f=3600   s1=131  s2=104  s3=144
f=5400   s1=94   s2=104  s3=67
f=7200   s1=0    s2=75   s3=0

Three fighters starting at exactly 144 -- MvC's HEALTH_MAX -- falling monotonically, two reaching zero on KO.

Being wrong twice, and how it got caught

A tag-out probe then reported recoverable life at +$253, on the strength of 33, 79 and 86 "refill rises" across three slots. It was wrong.

A later whole-object state classifier found two offsets behaving identically as health across three slots:

0x251  max=144  distinct=20  up=1  dn=19
0x25B  max=144  distinct=20  up=1  dn=19
gap = $A

MvC's pair is life +$271 / red +$27B -- also $A apart. The structure transfers after all; only the base offset differs. And +$253 classifies as meter-like in the same run: up=183, dn=8. A field rising 183 times is not recoverable life.

The failure was in the metric. Ranking candidates by raw rise count let the loudest field beat the quiet correct one, and $251 was inside the search window the entire time. Three targeted probes got it wrong; one cross-slot behavioural classification got it right in a single pass. When a field only moves during one specific game state, "most active" is precisely the wrong discriminator.

Two bugs a syntax check cannot see

FBNeo embeds Lua 5.1. Both harness scripts were written and validated against 5.4, so goto/::labels:: (5.2+) and the // integer-division operator (5.3+) passed local checks and then failed to compile inside the emulator -- which reports no Lua load error at all. It simply runs the game with no script attached. Two full runs were lost to an empty capture directory before the cause surfaced.

The second was worse, because it was introduced by a fix. Wrapping the main loop in pcall to catch errors and leave a reason is reasonable-looking and fatal: emu.frameadvance() yields the coroutine, and Lua 5.1 cannot yield across a C-call boundary. The diagnostic wrapper killed the script on frame one.

Both classes now have a structural guard, because luac will happily bless either. A third operational rule belongs with them: do not edit a running dump script. That produced a false unexpected EOF and a wasted session.

What actually works, and what does not

Motion inputs were the last blocker on the source-measurement side. Pressing the attack button on the same frame as the final direction produced zero landed specials -- including a projectile, which cannot miss on range alone. Separating the button by one step fixed it: Hadou Ken went from 0/2 to 8/8.

Ground normals now measure cleanly and reproduce across five sessions:

Movedamage
stand LP3
stand MP6
stand HP11–13
crouch HP9–11
stand LK2
stand MK3–4

Honest limits. The damage attribution window measures total life lost across the observation period rather than the first discrete drop, so multi-hit moves and overlapping damage inflate their ranges -- treat tight single-value rows as real and wide spreads as suspect. Meter is narrowed to six cross-slot candidates and not resolved, which makes every super result ambiguous: a super reading zero may mean the port is broken or may mean there was no bar, and the harness now says so explicitly rather than letting a false negative into the ledger.

Nested HIT dumps: what got better

P01 is no longer "cmds=0". The lab dumps Capcom's HIT EDITER the way a database client dumps a table: park on a character, skip to a group, walk subs, OCR the name, snapshot the chain pointer.

Canonical tools:

  • Lua: record/harness/cps2_secret_character_dump.lua
  • Runner: experiments/devmenu/run_cps2_secret_character.sh PROFILE MODE [OUT]
  • Profiles: experiments/devmenu/secret_character_profiles.json
  • Binder: scripts/bind_secret_menu_chains.py (--char-id, --fallback-unlabelled)
  • Join: scripts/join_secret_menu_l1.py (schema secret_menu_l1_join_v5)
  • Scoreboard: scripts/secret_oracle_scoreboard.py

Live id is 2× editor row on XvSF and MSHvSF (Rogue $06, Storm $04, Magneto $0E, Shuma $0A, Dark Sakura $2A from row 15 SAKURA, not 10 SAKURA KINZO). Dest profiles store the dest id as seated.

What the dump learned the expensive way

6 STOPS · 1 CORRECTED · 1 RETRACTIONS · 0 OPEN
  1. overlay 0
    native_rows false
    accept_label from OCR

    secret_character_profiles.json

    01 / 6measuredevery dest profile

    Overlay 0 on MvC dest

    overlay 0native_rows stays off when the thunk exists

    Names come from HIT OCR. Overlay 1 is proven only on XvSF Start×3. A zip that already has $3FD610 must not set CPS2_SECRET_MVC_NATIVE_ROWS=1.

    COVERAGE 20% OF THE ANIMATION TREE

    Read this section
  2. GROUP_SKIP=16  CATCH
    GROUP_SKIP=28  FLY $38
    SUB_STEPS=12   hole depth

    cps2_secret_character_dump.lua env: GROUP_SKIP, SUB_STEPS, REFOCUS, accept_label

    02 / 6measurednested dump

    GROUP_SKIP, then walk subs

    skipdo not sweep many groups after a Right-sub walk

    Jin/Storm dest leave HIT EDIT if you Up across many groups after walking subs. The Lua repark is B4+Right. Skip to the group. SUB_STEPS covers depth. REFOCUS recovers a drifted cursor.

    COVERAGE 40% OF THE ANIMATION TREE

    Read this section
  3. GROUP_KEY=up
    Down from $00 = no-op
    hit_steps=2 Magneto dest

    magneto-mvc / magneto-mvc-magtree profiles

    03 / 6measuredCap $00 is a floor

    Magneto dest axis is Up

    UpDown from $00 does not advance

    Default CHAR_DIRECTION is up. Storm dest still reaches id $18 with hit_steps=12. Magneto dest dumps that used Down from the first group went nowhere.

    COVERAGE 55% OF THE ANIMATION TREE

    Read this section
  4. compact_named skips unknown
    PIYO SLEEP in all_screens
    merge before join

    bind_secret_menu_chains.py; MAGNETO_DEST_NAME_TO_CHAIN.json n=268

    04 / 6correctedbind vs all_screens

    compact_named skips mode unknown

    mergePIYO SLEEP lived only in all_screens

    A compact table that drops unknown-mode rows will under-count FLY and PIYO. Hole cells had to be merged from NAME_TO_CHAIN.json all_screens before join would see them.

    COVERAGE 70% OF THE ANIMATION TREE

    Retracted here
    If it is not in compact_named, it is not in the ROM
    Read this section
  5. accept_label AMERICA
    OCR != MAGNETO
    id $04 still correct

    destination_magtree_hit_axis receipt capture_status FAIL_CAPTURE

    05 / 6measuredaccept_label vs OCR

    FAIL_CAPTURE is a label, not a table

    AMERICAMagneto dest named-row vs MAGNETO

    Rogue dest accepts HULK. Magneto dest OCR is often AMERICA. Bind still runs if receipt.json exists. Id $04 was correct on those FAIL_CAPTURE runs.

    COVERAGE 85% OF THE ANIMATION TREE

    Read this section
  6. map  27 → 30
    edit 27 = TWIN
    edit 28 = FLY  (prefer)

    join_secret_menu_l1.py dest_slot_candidates()

    06 / 6measuredsecret_menu_l1_join_v5

    Join v5 hits editor FLY

    L1 28not mapped 30

    Stock-shape map puts XvSF 27 at MvC 30. Editors print FLY at 28 and TWIN at 27. dest_slot_candidates tries mapped, then editor. Source 27 prefers dest 28.

    COVERAGE 100% OF THE ANIMATION TREE

    Read this section
Operational rules, not a calendar.

Two trees, and disposable editor zips

HIT EDITER dereferences DIR_ANIM. Fight code can run a relocated tree the editor never loads. That is the Magneto wrap: identity zip keeps DIR_ANIM[$04] = $107FF0 (Cap, six CATCH slots). Fight runs MAG_TREE $588000 (nine CATCH slots). Extra Right taps stay on the last live Cap slot. The name table already has CATCH 06. The overlay never reaches it.

The dump that printed the holes is a disposable zip: DIR_ANIM[$04] = $588000, L1 28 sharing Magneto's 18-slot flight table so Char Gp $38 prints FLY. Profile magneto-mvc-magtree, accept_label AMERICA, expect_tree_base 0x588000. md5 3300c58163e358c193680195ab969466. Do not ship it. Select and team need Cap's tree.

Storm dest already points Jin's DIR_ANIM row at STORM_TREE $508000. A second disposable zip shared L1 27 onto L1 28 to print FLY FRONT DOWN END at $38. Same rule: skip to the group. Long Up-sweeps after a Right-sub walk exit HIT EDIT around L1 7.

Fight code remaps flight $36 → $38. HIT EDITER does not. Slot words are group-base relative; you cannot copy an 18-word FLY table to a higher address without recomputing rels, because the chains sit after the table. Sharing L1 27's table onto L1 28 works for editor dumps.

Full Magneto write-up: the unified post.

A hole cell is a chain the ship zip's editor cannot indexDisposable DIR_ANIM retarget. Identity zip still presents Cap's window here.CONFIRMED IN GAME
HIT EDITER magtree dump: Magneto PIYO SLEEP, CG_Ptr $58823C
statePIYO SLEEP
CG_Ptr$0058823C
tree_base$00588000
ship DIR_ANIM[$04]$00107FF0
named-rowFAIL_CAPTURE AMERICA vs MAGNETO

KitRom program RAM is byte-swapped. MAG_TREE / STORM_TREE live in mvc.exp. TRIAGE_ONLY: this proves the editor can print the cell, not that live dispatch requests it.

mvsc_magneto_magtree_editor_dump.zip · do not ship

Join v5: editor L1 is not the stock-shape map

ANIMATION_GROUP_MAP is order-homology across five characters, not HIT EDITER labels. It parks XvSF 26 ETC at MvC 29 and XvSF 27 FLY/TWIN at MvC 30. The editors print ETC at 26, TWIN at 27, FLY at 28.

dest_slot_candidates / lookup_dest_row try mapped L1, then editor L1s. Source 27 prefers dest 28 (FLY) before 27 (TWIN). Source 26 tries 26 then 29.

That closed Rogue's four ETC cells, Shuma and Dark Sakura ETC+TWIN, and Magneto FLY, without inventing dest L1 30. GETUP can family-match (GETUP BACK at XvSF L1 18 sub 2 onto native GETUP FRONT MIDDLE at the same mapped slot). CATCH 06 is not CATCH 00.

Join metrics: import_rate = name_agree + family + elsewhere + diverge; coverage_rate = first three; slot_rate = dest cell at resolved (L1, sub). Boundary on every join JSON: TRIAGE_ONLY. This does not patch a tree or prove the MvC dispatcher requests these coordinates.

The number that moved, and the number that did not

P01 moved. Five fighters, names and slots 100%.

Live behaviour did not. Magneto 0/37. Storm 0/36. Dark Sakura 1/37. Shuma-Gorath 1/36. Zero 1/37. Cable 1/38. SF3 Ken 1/36 with its CPS3 source still on HOLD. Every non-zero entry remains the flight-not-applicable waiver.

A dest HIT row that reads 03 ROGUE instead of 03 HULK is infrastructure access. Its own acceptance boundary still says row access cannot accept fighter behaviour. The machine that can close a damage lane exists. No lane has been closed with it.

The 2026-08-22 work moved the framework, not those parity counts. It made the wrong ROM, wrong emulator role, write-assisted input, stale receipt, and editor-as-gameplay mistakes mechanically rejectable. The next honest number moves only after a pinned source oracle and an ordinary-control MAME target run agree through a fighter-specific scorer.

Magneto and Dual Rogue are the seating stories. This page is the instrument.

Editor's update — August 26, 2026: the harness variants are now one estate, consolidated in a standalone repo

An audit across all ten project repos counted the drift the per-character forks had accumulated: four independent contract engines, five pin preflights, two near-clone MAME launchers, four runner loops and three secret-menu capture forks, plus roughly seven hundred hard-coded machine paths. Each fork was best at something. The Rogue line's catalog-driven Lua gate engine already drives nine ports across three games; the Magneto line owns the only select-surface acceptance harness — cursor routes, committed-body anchors, cut-in palette scripts — with a byte-identical rerun on record; the Omega line has the pixel-exact HUD identity gate and the MAME warning profile that stops Lua autoboot hangs; the Cammy line has the cleanest contract-to-scorer chain and 47 of 49 source lanes proven.

Those best pieces now live in one standalone harness repo. Version one ships the shared kits — a self-hashing lane-contract engine, the one pin verifier, a container census library — plus a unified receipt schema whose evidence classes encode the tier rule this page has always enforced: fast-emulator and editor evidence never closes an ordinary-control, audio or human lane. A machine profile replaces the hard-coded paths. Three brand-new character repos consumed the kits on day one, sixteen pinned-input checks and a census receipt each, so the sixth, seventh and eighth copies of the preflight never got written. The engine, its nine-port catalog, and the select-surface harness family were copied in under a provenance receipt; originals stay sealed where they are.

The consolidation also produced a thirty-two-component coverage matrix across nine imports, and it names the gaps no variant ever covered: no live voice-package gate has ever run, the realtime-speed harness exists only as a locked design, and the story, AI and versus-screen surfaces have builders but no verifier anywhere. Those are the combined harness's next lanes, in that order.

Written by Daniel Plas Rivera · 8,942 words · $27

ShareXLinkedIn