/** * scripts/verify-challenger-m2-tooltip.ts * * Empirical Challenger Verification & Stress Test Suite for Milestone M2. * Validates: * 1. M2 Interface & Data Contracts in `src/ui/inventory.ts`. * 2. Canonical 1.13c STARTER_EQUIPPED_GEAR & STARTER_BAG_ITEMS data integrity. * 3. Stateful Dye Persistence across equip slot pickup, cursorItem, and bag grid operations. * 4. 5-Tier Fallback Resolution in `resolveItemSpriteRect` (Tiers 0..5). * 5. Boundary cases: missing codes, invalid dimensions, case variance, empty items. * 6. Adversarial Fuzzing Stress Test (10,000 randomized mock items). */ import { InventoryPanel, resolveItemSpriteRect, STARTER_BAG_ITEMS, STARTER_EQUIPPED_GEAR, type ResolvableItem, type SpriteRect, type UiInventoryItem, type EquipSlotId, } from '../src/ui/inventory.ts' import { BAKED_UI_MANIFEST } from '../src/ui/baked-ui-meta.ts' interface Section { name: string assertions: number failures: string[] } const sections: Section[] = [] let currentSection: Section | null = null function startSection(name: string) { currentSection = { name, assertions: 0, failures: [] } sections.push(currentSection) console.log(`\n=== [${name}] ===`) } function assert(condition: boolean, msg: string) { if (!currentSection) throw new Error('No active section') currentSection.assertions++ if (!condition) { currentSection.failures.push(msg) console.error(` FAIL: ${msg}`) } else { console.log(` PASS: ${msg}`) } } // --------------------------------------------------------------------------- // 1. Static Metadata & Atlas Contract Verification // --------------------------------------------------------------------------- startSection('1. Static Manifest & Atlas Rects Verification') const itemRects = BAKED_UI_MANIFEST.itemRects assert(Object.keys(itemRects).length > 300, `itemRects has ${Object.keys(itemRects).length} registered entries`) const dyedKeys = ['invcap_cgrn', 'invgth_dpur', 'invtgl_lgry', 'invvbl_blac'] for (const key of dyedKeys) { const rect = itemRects[key] assert(rect !== undefined, `Dyed rect '${key}' exists in itemRects`) if (rect) { assert( rect.x >= 0 && rect.y >= 0 && rect.w > 0 && rect.h > 0 && rect.x + rect.w <= BAKED_UI_MANIFEST.atlasWidth && rect.y + rect.h <= BAKED_UI_MANIFEST.atlasHeight, `Rect '${key}' [${rect.x}, ${rect.y}, ${rect.w}, ${rect.h}] within atlas bounds [${BAKED_UI_MANIFEST.atlasWidth}, ${BAKED_UI_MANIFEST.atlasHeight}]` ) } } assert(BAKED_UI_MANIFEST.codeToInvFile['Harlequin Crest'] === 'invcap_cgrn', 'codeToInvFile maps "Harlequin Crest" -> "invcap_cgrn"') assert(BAKED_UI_MANIFEST.codeToInvFile["Tal Rasha's Guardianship"] === 'invgth_dpur', 'codeToInvFile maps "Tal Rasha\'s Guardianship" -> "invgth_dpur"') assert(BAKED_UI_MANIFEST.codeToInvFile['Magefist'] === 'invtgl_lgry', 'codeToInvFile maps "Magefist" -> "invtgl_lgry"') assert(BAKED_UI_MANIFEST.codeToInvFile['Arachnid Mesh'] === 'invvbl_blac', 'codeToInvFile maps "Arachnid Mesh" -> "invvbl_blac"') // --------------------------------------------------------------------------- // 2. STARTER_EQUIPPED_GEAR Canonical 1.13c Data Parity // --------------------------------------------------------------------------- startSection('2. STARTER_EQUIPPED_GEAR Canonical 1.13c Parity') // 2.1 Helm (Harlequin Crest) const shako = STARTER_EQUIPPED_GEAR.helm assert(shako !== undefined, 'STARTER_EQUIPPED_GEAR.helm is defined') if (shako) { assert(shako.invtransform === 'cgrn', `Shako invtransform is 'cgrn' (got: ${shako.invtransform})`) assert(shako.defense === 141, `Shako defense is 141 (got: ${shako.defense})`) assert(shako.durability?.current === 12 && shako.durability?.max === 12, `Shako durability is 12/12`) assert(shako.reqStr === 50, `Shako reqStr is 50 (got: ${shako.reqStr})`) assert(shako.reqLevel === 62, `Shako reqLevel is 62 (got: ${shako.reqLevel})`) assert(shako.stats.length === 6, `Shako has exactly 6 canonical stats (got: ${shako.stats.length})`) const shakoSprite = resolveItemSpriteRect(shako, itemRects) assert(shakoSprite === itemRects['invcap_cgrn'], 'Shako sprite resolves to invcap_cgrn') } // 2.2 Armor (Tal Rasha's Guardianship) const talArmor = STARTER_EQUIPPED_GEAR.armor assert(talArmor !== undefined, 'STARTER_EQUIPPED_GEAR.armor is defined') if (talArmor) { assert(talArmor.invtransform === 'dpur', `Tal Armor invtransform is 'dpur' (got: ${talArmor.invtransform})`) assert(talArmor.defense === 941, `Tal Armor defense is 941 (got: ${talArmor.defense})`) assert(talArmor.durability?.current === 55 && talArmor.durability?.max === 55, 'Tal Armor durability is 55/55') assert(talArmor.reqStr === 84, `Tal Armor reqStr is 84 (got: ${talArmor.reqStr})`) assert(talArmor.reqLevel === 71, `Tal Armor reqLevel is 71 (got: ${talArmor.reqLevel})`) assert(talArmor.setPieces !== undefined && talArmor.setPieces.length === 5, 'Tal Armor declares 5 setPieces') assert(talArmor.setBonuses !== undefined && talArmor.setBonuses.length === 4, 'Tal Armor declares 4 setBonuses') const armorSprite = resolveItemSpriteRect(talArmor, itemRects) assert(armorSprite === itemRects['invgth_dpur'], 'Tal Armor sprite resolves to invgth_dpur') } // 2.3 Gloves (Magefist) const magefist = STARTER_EQUIPPED_GEAR.gloves assert(magefist !== undefined, 'STARTER_EQUIPPED_GEAR.gloves is defined') if (magefist) { assert(magefist.invtransform === 'lgry', `Magefist invtransform is 'lgry' (got: ${magefist.invtransform})`) assert(magefist.defense === 25, `Magefist defense is 25 (got: ${magefist.defense})`) assert(magefist.durability?.current === 14 && magefist.durability?.max === 14, 'Magefist durability is 14/14') assert(magefist.reqStr === 45, `Magefist reqStr is 45 (got: ${magefist.reqStr})`) assert(magefist.reqLevel === 23, `Magefist reqLevel is 23 (got: ${magefist.reqLevel})`) const glovesSprite = resolveItemSpriteRect(magefist, itemRects) assert(glovesSprite === itemRects['invtgl_lgry'], 'Magefist sprite resolves to invtgl_lgry') } // 2.4 Belt (Arachnid Mesh) const arach = STARTER_EQUIPPED_GEAR.belt assert(arach !== undefined, 'STARTER_EQUIPPED_GEAR.belt is defined') if (arach) { assert(arach.invtransform === 'blac', `Arachnid Mesh invtransform is 'blac' (got: ${arach.invtransform})`) assert(arach.defense === 138, `Arachnid Mesh defense is 138 (got: ${arach.defense})`) assert(arach.durability?.current === 12 && arach.durability?.max === 12, 'Arachnid Mesh durability is 12/12') assert(arach.reqStr === 50, `Arachnid Mesh reqStr is 50 (got: ${arach.reqStr})`) assert(arach.reqLevel === 80, `Arachnid Mesh reqLevel is 80 (got: ${arach.reqLevel})`) const beltSprite = resolveItemSpriteRect(arach, itemRects) assert(beltSprite === itemRects['invvbl_blac'], 'Arachnid Mesh sprite resolves to invvbl_blac') } // 2.5 Weapons & Other Equipped Slots const oculus = STARTER_EQUIPPED_GEAR.weapon1 assert(oculus !== undefined, 'STARTER_EQUIPPED_GEAR.weapon1 is defined') if (oculus) { assert(oculus.damage === '18 - 42', `Oculus damage is '18 - 42'`) assert(oculus.durability?.current === 50 && oculus.durability?.max === 50, 'Oculus durability is 50/50') assert(oculus.speedText === '法球类 - 普通攻击速度', `Oculus speedText is '法球类 - 普通攻击速度'`) assert(oculus.reqLevel === 42, `Oculus reqLevel is 42`) assert(resolveItemSpriteRect(oculus, itemRects) === itemRects['invbst'], 'Oculus resolves to invbst via Tier 1 invFile') } const spirit = STARTER_EQUIPPED_GEAR.weapon2 assert(spirit !== undefined, 'STARTER_EQUIPPED_GEAR.weapon2 is defined') if (spirit) { assert(spirit.quality === 'rune', `Spirit quality is 'rune'`) assert(spirit.runewordRunes === "'TalThulOrtAmn'", `Spirit runewordRunes is "'TalThulOrtAmn'"`) assert(spirit.defense === 148, `Spirit defense is 148`) assert(spirit.durability?.current === 148 && spirit.durability?.max === 148, 'Spirit durability is 148/148') assert(spirit.reqStr === 156, `Spirit reqStr is 156`) assert(spirit.reqLevel === 54, `Spirit reqLevel is 54`) assert(spirit.sockets === 4, `Spirit sockets is 4`) assert(resolveItemSpriteRect(spirit, itemRects) === itemRects['invtow'], 'Spirit resolves to invtow via Tier 1 invFile') } const boots = STARTER_EQUIPPED_GEAR.boots assert(boots !== undefined, 'STARTER_EQUIPPED_GEAR.boots is defined') if (boots) { assert(boots.defense === 139, `War Traveler defense is 139`) assert(boots.durability?.current === 48 && boots.durability?.max === 48, 'War Traveler durability is 48/48') assert(boots.reqStr === 95, `War Traveler reqStr is 95`) assert(boots.reqLevel === 42, `War Traveler reqLevel is 42`) assert(resolveItemSpriteRect(boots, itemRects) === itemRects['invtbt'], 'War Traveler resolves to invtbt via Tier 1 invFile') } // --------------------------------------------------------------------------- // 3. STARTER_BAG_ITEMS Canonical 1.13c Data Parity // --------------------------------------------------------------------------- startSection('3. STARTER_BAG_ITEMS Canonical 1.13c Parity') const ctaPlacement = STARTER_BAG_ITEMS.find(p => p.item.id === 'bag-cta') assert(ctaPlacement !== undefined, 'Call to Arms placement found in STARTER_BAG_ITEMS') if (ctaPlacement) { const cta = ctaPlacement.item assert(cta.runewordRunes === "'AmnRalMalIstOhm'", `CTA runewordRunes is "'AmnRalMalIstOhm'"`) assert(cta.damage === '17 - 52', `CTA damage is '17 - 52'`) assert(cta.durability?.current === 20 && cta.durability?.max === 20, `CTA durability is 20/20`) assert(cta.reqStr === 43, `CTA reqStr is 43`) assert(cta.reqLevel === 57, `CTA reqLevel is 57`) assert(cta.sockets === 5, `CTA sockets is 5`) assert(cta.speedText === '剑类 - 极快的攻击速度', `CTA speedText is '剑类 - 极快的攻击速度'`) assert(cta.stats.length === 11, `CTA has exactly 11 canonical stats (got: ${cta.stats.length})`) const ctaSprite = resolveItemSpriteRect(cta, itemRects) assert(ctaSprite === itemRects['invcrs'], 'CTA sprite resolves to invcrs') } const bagTorch = STARTER_BAG_ITEMS.find(p => p.item.id === 'bag-torch')?.item assert(bagTorch?.reqLevel === 75, 'Hellfire Torch reqLevel is 75') assert(bagTorch?.stats.length === 5, 'Hellfire Torch has 5 stats') assert(bagTorch ? resolveItemSpriteRect(bagTorch, itemRects) === itemRects['invtrch'] : false, 'Torch resolves to invtrch') const bagAnni = STARTER_BAG_ITEMS.find(p => p.item.id === 'bag-anni')?.item assert(bagAnni?.reqLevel === 70, 'Annihilus reqLevel is 70') assert(bagAnni?.stats.length === 4, 'Annihilus has 4 stats') assert(bagAnni ? resolveItemSpriteRect(bagAnni, itemRects) === itemRects['invmss'] : false, 'Annihilus resolves to invmss') const bagGheeds = STARTER_BAG_ITEMS.find(p => p.item.id === 'bag-gheeds')?.item assert(bagGheeds?.reqLevel === 62, "Gheed's Fortune reqLevel is 62") assert(bagGheeds?.stats.length === 3, "Gheed's Fortune has 3 stats") assert(bagGheeds ? resolveItemSpriteRect(bagGheeds, itemRects) === itemRects['invsst'] : false, "Gheed's Fortune resolves to invsst") // --------------------------------------------------------------------------- // 4. Stateful Dye Persistence Simulation across UI Operations // --------------------------------------------------------------------------- startSection('4. Stateful Dye Persistence across Equip / Bag / Cursor') const inv = new InventoryPanel() const slotsToTest: { slot: EquipSlotId; expectedDye: string; expectedSprite: string }[] = [ { slot: 'helm', expectedDye: 'cgrn', expectedSprite: 'invcap_cgrn' }, { slot: 'armor', expectedDye: 'dpur', expectedSprite: 'invgth_dpur' }, { slot: 'gloves', expectedDye: 'lgry', expectedSprite: 'invtgl_lgry' }, { slot: 'belt', expectedDye: 'blac', expectedSprite: 'invvbl_blac' }, ] for (const { slot, expectedDye, expectedSprite } of slotsToTest) { const itemBefore = inv.equipped[slot] assert(itemBefore?.invtransform === expectedDye, `Slot ${slot} starts with invtransform '${expectedDye}'`) // Pick up to cursor const picked = inv.clickEquipSlot(slot) assert(picked === true, `Picked up item from slot ${slot}`) assert(inv.cursorItem !== null, `Cursor holds picked item`) assert(inv.cursorItem?.invtransform === expectedDye, `CursorItem retains invtransform '${expectedDye}'`) const cursorSprite = resolveItemSpriteRect(inv.cursorItem!, itemRects) assert(cursorSprite === itemRects[expectedSprite], `CursorItem resolves sprite ${expectedSprite}`) // Re-equip back to slot const reEquipped = inv.clickEquipSlot(slot) assert(reEquipped === true, `Re-equipped item to slot ${slot}`) assert(inv.cursorItem === null, `Cursor empty after re-equipping`) const itemAfter = inv.equipped[slot] assert(itemAfter?.invtransform === expectedDye, `Re-equipped slot ${slot} retains invtransform '${expectedDye}'`) const afterSprite = resolveItemSpriteRect(itemAfter!, itemRects) assert(afterSprite === itemRects[expectedSprite], `Re-equipped slot ${slot} resolves sprite ${expectedSprite}`) } // --------------------------------------------------------------------------- // 5. Stress-Testing Fallback Tiers (resolveItemSpriteRect) // --------------------------------------------------------------------------- startSection('5. Stress-Testing Fallback Tiers (resolveItemSpriteRect)') // Tier 0: Transformed dyed item lookup // 5.1 Case sensitivity of invFile and invtransform const mixedCaseItem: ResolvableItem = { invFile: 'InvCap', invtransform: 'CGRN', } const mixedCaseSprite = resolveItemSpriteRect(mixedCaseItem, itemRects) assert(mixedCaseSprite === itemRects['invcap_cgrn'], 'Tier 0 handles mixed-case InvCap + CGRN -> invcap_cgrn') // 5.2 Invalid invtransform falls back to Tier 1 base invFile const badTransformItem: ResolvableItem = { invFile: 'invcap', invtransform: 'nonexistent_dye_xyz', } const badTransformSprite = resolveItemSpriteRect(badTransformItem, itemRects) assert(badTransformSprite === itemRects['invcap'], 'Invalid invtransform falls back to Tier 1 base invFile (invcap)') // 5.3 Empty string invtransform falls back to Tier 1 const emptyTransformItem: ResolvableItem = { invFile: 'invcap', invtransform: '', } const emptyTransformSprite = resolveItemSpriteRect(emptyTransformItem, itemRects) assert(emptyTransformSprite === itemRects['invcap'], 'Empty invtransform falls back to Tier 1 base invFile (invcap)') // Tier 1: Direct invFile const tier1Item: ResolvableItem = { invFile: 'invgth' } assert(resolveItemSpriteRect(tier1Item, itemRects) === itemRects['invgth'], 'Tier 1 resolves direct invFile invgth') const tier1UpperItem: ResolvableItem = { invFile: 'INVGTH' } assert(resolveItemSpriteRect(tier1UpperItem, itemRects) === itemRects['invgth'], 'Tier 1 resolves uppercase INVGTH') // Tier 2: Unique/set name in codeToInvFile assert(resolveItemSpriteRect({ name: 'Harlequin Crest' }, itemRects) === itemRects['invcap_cgrn'], 'Tier 2 resolves "Harlequin Crest" -> invcap_cgrn') assert(resolveItemSpriteRect({ name: 'Magefist' }, itemRects) === itemRects['invtgl_lgry'], 'Tier 2 resolves "Magefist" -> invtgl_lgry') assert(resolveItemSpriteRect({ name: "Tal Rasha's Guardianship" }, itemRects) === itemRects['invgth_dpur'], 'Tier 2 resolves "Tal Rasha\'s Guardianship" -> invgth_dpur') assert(resolveItemSpriteRect({ name: 'Arachnid Mesh' }, itemRects) === itemRects['invvbl_blac'], 'Tier 2 resolves "Arachnid Mesh" -> invvbl_blac') // Tier 3: Base item code in codeToInvFile const tier3Item: ResolvableItem = { code: 'hax' } assert(resolveItemSpriteRect(tier3Item, itemRects) === itemRects['invhax'], 'Tier 3 resolves base code "hax" -> invhax') assert(resolveItemSpriteRect({ code: 'cm1' }, itemRects) === itemRects['invchm'], 'Tier 3 resolves base code "cm1" -> invchm') // Tier 4: Canonical code overrides (codes without base codeToInvFile collisions) const tier4Overrides: [string, string][] = [ ['tbk', 'invbbk'], ['ibk', 'invrbk'], ['box', 'invbox'], ['cube', 'invbox'], ['anni', 'invmss'], ['torch', 'invtrch'], ['gheeds', 'invsst'], ['crs', 'invcrs'], ['cta', 'invcrs'], ] for (const [code, expectedInvFile] of tier4Overrides) { const item: ResolvableItem = { code } const res = resolveItemSpriteRect(item, itemRects) assert(res === itemRects[expectedInvFile], `Tier 4 code override '${code}' -> '${expectedInvFile}'`) } // Tier 4: Name-based overrides assert(resolveItemSpriteRect({ name: 'Annihilus Charm' }, itemRects) === itemRects['invmss'], 'Tier 4 name containing "Annihilus" -> invmss') assert(resolveItemSpriteRect({ name: 'Hellfire Torch' }, itemRects) === itemRects['invtrch'], 'Tier 4 name containing "Torch" -> invtrch') assert(resolveItemSpriteRect({ name: "Gheed's Fortune" }, itemRects) === itemRects['invsst'], "Tier 4 name containing \"Gheed\" -> invsst") assert(resolveItemSpriteRect({ name: 'Call to Arms Sword' }, itemRects) === itemRects['invcrs'], 'Tier 4 name containing "Call to Arms" -> invcrs') // Tier 5: Dimension-based fallbacks (w x h) const dimensionCases: [number, number, string[]][] = [ [1, 1, ['invchm', 'invrin', 'invcap']], [1, 2, ['invtrch', 'invbbk', 'invglv']], [1, 3, ['invsst', 'invclb', 'invwnd']], [1, 4, ['invbst', 'invstf']], [2, 1, ['invvbl', 'invlbl']], [2, 2, ['invbox', 'invcap']], [2, 3, ['invcrs', 'invgth']], [2, 4, ['invhxb', 'invpst']], ] for (const [w, h, candidates] of dimensionCases) { const item: ResolvableItem = { invWidth: w, invHeight: h } const res = resolveItemSpriteRect(item, itemRects) const matchedCandidate = candidates.some(c => itemRects[c] && res === itemRects[c]) assert(matchedCandidate, `Tier 5 dimension fallback (${w}x${h}) matched candidate in [${candidates.join(', ')}]`) } // --------------------------------------------------------------------------- // 6. Boundary Cases & Invalid Dimensions // --------------------------------------------------------------------------- startSection('6. Boundary Cases & Invalid Dimensions') // 6.1 Empty item object const emptyItem: ResolvableItem = {} const emptyRes = resolveItemSpriteRect(emptyItem, itemRects) assert(emptyRes !== null, 'Empty item {} resolves to non-null default (1x1 fallback)') // 6.2 Unusual / Invalid dimensions const invalidDimensionItems: ResolvableItem[] = [ { invWidth: 0, invHeight: 0 }, { invWidth: -1, invHeight: -2 }, { invWidth: 3, invHeight: 3 }, { invWidth: 10, invHeight: 10 }, { invWidth: NaN, invHeight: NaN }, { invWidth: Infinity, invHeight: Infinity }, { invWidth: -Infinity, invHeight: -Infinity }, { invWidth: 1.5, invHeight: 2.7 }, ] for (const invalidItem of invalidDimensionItems) { let thrown = false let res: SpriteRect | null = null try { res = resolveItemSpriteRect(invalidItem, itemRects) } catch (e) { thrown = true } assert(!thrown, `Invalid dimensions (w: ${invalidItem.invWidth}, h: ${invalidItem.invHeight}) does not throw`) assert(res !== null, `Invalid dimensions returns non-null fallback SpriteRect`) } // 6.3 Empty itemRects object const emptyRectsRes = resolveItemSpriteRect({ code: 'crs' }, {}) assert(emptyRectsRes === null, 'Empty itemRects returns null without throwing') // --------------------------------------------------------------------------- // 7. Adversarial Fuzzing Stress Test (10,000 Random Mock Items) // --------------------------------------------------------------------------- startSection('7. Adversarial Fuzzing Stress Test (10,000 Randomized Items)') function pseudoRandom(seed: number): () => number { let s = seed return () => { s = (s * 1664525 + 1013904223) % 4294967296 return s / 4294967296 } } const rng = pseudoRandom(0xfeedface) const sampleCodes = [undefined, '', 'uap', 'uth', 'tgl', 'ulc', 'crs', 'tbk', 'ibk', 'cm1', 'cm2', 'cm3', 'xyz_unknown', '@@@$$$'] const sampleNames = [undefined, '', 'Harlequin Crest', "Tal Rasha's Guardianship", 'Magefist', 'Arachnid Mesh', 'The Oculus', 'Spirit Monarch', 'Call to Arms', 'Unknown Item', 'Random Name 123'] const sampleInvFiles = [undefined, '', 'invcap', 'invgth', 'invtgl', 'invvbl', 'invcrs', 'invbbk', 'nonexistent_file', 'INV_CAP_UPPER'] const sampleTransforms = [undefined, '', 'cgrn', 'dpur', 'lgry', 'blac', 'unknown_dye', 'CGRN', 'DPUR'] const sampleDimensions = [undefined, 0, 1, 2, 3, 4, -1, -5, 10, NaN, Infinity, 1.5] let fuzzIterations = 10000 let fuzzSuccessCount = 0 let dyedHitCount = 0 for (let i = 0; i < fuzzIterations; i++) { const mockItem: ResolvableItem = { code: sampleCodes[Math.floor(rng() * sampleCodes.length)], name: sampleNames[Math.floor(rng() * sampleNames.length)], invFile: sampleInvFiles[Math.floor(rng() * sampleInvFiles.length)], invtransform: sampleTransforms[Math.floor(rng() * sampleTransforms.length)], invWidth: sampleDimensions[Math.floor(rng() * sampleDimensions.length)], invHeight: sampleDimensions[Math.floor(rng() * sampleDimensions.length)], } let rect: SpriteRect | null = null try { rect = resolveItemSpriteRect(mockItem, itemRects) } catch (err: any) { assert(false, `Fuzz item ${i} threw error: ${err.message}`) break } // Verification 1: Must never return undefined if (rect === undefined) { assert(false, `Fuzz item ${i} returned undefined`) break } // Verification 2: With populated itemRects, fallback chain guarantees non-null SpriteRect if (rect === null) { assert(false, `Fuzz item ${i} returned null unexpectedly`) break } // Verification 3: Bounding box validity if ( !Number.isFinite(rect.x) || !Number.isFinite(rect.y) || !Number.isFinite(rect.w) || !Number.isFinite(rect.h) || rect.w <= 0 || rect.h <= 0 || rect.x < 0 || rect.y < 0 || rect.x + rect.w > BAKED_UI_MANIFEST.atlasWidth || rect.y + rect.h > BAKED_UI_MANIFEST.atlasHeight ) { assert(false, `Fuzz item ${i} returned invalid SpriteRect: [${rect.x}, ${rect.y}, ${rect.w}, ${rect.h}]`) break } // Verification 4: If exact dyed match, it MUST resolve the dyed rect if (mockItem.invFile && mockItem.invtransform) { const expectedDyedKey = `${mockItem.invFile}_${mockItem.invtransform}`.toLowerCase() if (itemRects[expectedDyedKey]) { if (rect !== itemRects[expectedDyedKey]) { assert(false, `Fuzz item ${i} had dyed match ${expectedDyedKey} but resolved different rect`) break } dyedHitCount++ } } fuzzSuccessCount++ } assert(fuzzSuccessCount === fuzzIterations, `All ${fuzzIterations} fuzzed items resolved safely without crashes or invalid rects`) console.log(` (Fuzzed: ${fuzzSuccessCount} safe resolutions, ${dyedHitCount} dyed hits)`) // --------------------------------------------------------------------------- // Summary // --------------------------------------------------------------------------- console.log('\n======================================================') console.log('CHALLENGER VERIFICATION SUMMARY') console.log('======================================================') let totalAssertions = 0 let totalFailures = 0 for (const sec of sections) { totalAssertions += sec.assertions totalFailures += sec.failures.length const status = sec.failures.length === 0 ? 'PASS' : `FAIL (${sec.failures.length})` console.log(`- ${sec.name}: ${status} [${sec.assertions} assertions]`) } console.log('------------------------------------------------------') console.log(`Total assertions: ${totalAssertions}`) console.log(`Total failures: ${totalFailures}`) console.log('======================================================') if (totalFailures > 0) { process.exit(1) } else { console.log('ALL EMPIRICAL CHALLENGER TESTS PASSED.') process.exit(0) }