/** * scripts/verify-challenger-m1-tooltip.ts * * Empirical Challenger Verification Suite for Milestone M1 (Requirement R1). * Inspects `public/ui/items-atlas.png` and `src/ui/baked-ui-meta.ts`. * * Invariants Tested: * 1. PNG Header & Structure: IHDR (1024 x 1880, colorType 3), PLTE (768 bytes), tRNS (index 0 transparent). * 2. Transformed Item Rects: Coordinates, dimensions, bounds containment within [1024, 1880]. * 3. Overlap Invariant: Zero overlap between any pair of item rects in the entire atlas (449+ rects). * 4. Silhouette Invariant: 100% pixel-for-pixel alpha mask match between transformed frames and base frames: * - invcap_cgrn vs invcap (3,136 pixels) * - invgth_dpur vs invgth (4,704 pixels) * - invtgl_lgry vs invtgl (3,136 pixels) * - invvbl_blac vs invvbl (1,568 pixels) * - invlbl_blac vs invlbl (1,568 pixels) * 5. Color Transformation Fidelity: * - invcap_cgrn: Emerald Green dominance (G > R and G > B) for non-transparent pixels. * - invgth_dpur: Dark Purple dominance (B > G and R > G) for non-transparent pixels. * - invtgl_lgry: Silver Grey balance (|R-G| <= 5, |G-B| <= 5, |R-B| <= 5). * - invvbl_blac: Jet Black guard (100% opaque pixels mapped to index 172 RGB [4,4,4], 0 opaque index 0 pixels). * - invlbl_blac: Jet Black guard (100% opaque pixels mapped to index 172 RGB [4,4,4], 0 opaque index 0 pixels). * 6. Significant Color Shift vs Base: * - Delta E / RGB distance between transformed sprites and their original base counterparts. * 7. Metadata Registration Invariant: * - codeToInvFile entries for Harlequin Crest, Tal Rasha's Guardianship, Magefist, Arachnid Mesh. * - Identity mappings for transformed sprite tokens. */ import { readFileSync } from 'node:fs' import { inflateSync } from 'node:zlib' import { BAKED_UI_MANIFEST, type SpriteRect } from '../src/ui/baked-ui-meta.ts' interface VerificationSection { name: string assertions: number failures: string[] } const sections: VerificationSection[] = [] let currentSection: VerificationSection | 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. Load and parse PNG console.log('Loading public/ui/items-atlas.png...') const pngBuffer = readFileSync('public/ui/items-atlas.png') startSection('1. PNG Physical Structure & Chunks') assert(pngBuffer.length > 0, `PNG file read successfully (${pngBuffer.length} bytes)`) const signature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] const hasValidSig = signature.every((b, i) => pngBuffer[i] === b) assert(hasValidSig, 'Valid PNG 8-byte signature') let offset = 8 let atlasWidth = 0 let atlasHeight = 0 let colorType = -1 let bitDepth = -1 let plte: Uint8Array | null = null let trns: Uint8Array | null = null const idatChunks: Buffer[] = [] while (offset < pngBuffer.length) { const length = pngBuffer.readUInt32BE(offset) const type = pngBuffer.toString('ascii', offset + 4, offset + 8) const data = pngBuffer.subarray(offset + 8, offset + 8 + length) if (type === 'IHDR') { atlasWidth = data.readUInt32BE(0) atlasHeight = data.readUInt32BE(4) bitDepth = data[8]! colorType = data[9]! } else if (type === 'PLTE') { plte = new Uint8Array(data) } else if (type === 'tRNS') { trns = new Uint8Array(data) } else if (type === 'IDAT') { idatChunks.push(Buffer.from(data)) } offset += 12 + length } assert(atlasWidth === BAKED_UI_MANIFEST.atlasWidth, `IHDR width ${atlasWidth} === manifest atlasWidth ${BAKED_UI_MANIFEST.atlasWidth}`) assert(atlasHeight === BAKED_UI_MANIFEST.atlasHeight, `IHDR height ${atlasHeight} === manifest atlasHeight ${BAKED_UI_MANIFEST.atlasHeight}`) assert(bitDepth === 8, `Bit depth is 8 (${bitDepth})`) assert(colorType === 3, `Color type is 3 (Indexed-color) (${colorType})`) assert(plte !== null && plte.length === 768, `PLTE palette exists and has 768 bytes (256 RGB triples)`) assert(trns !== null && trns.length >= 1, `tRNS chunk exists with length ${trns?.length}`) assert(trns !== null && trns[0] === 0, `tRNS index 0 is 0 (fully transparent)`) // Decompress scanlines const fullIdat = Buffer.concat(idatChunks) const decompressed = inflateSync(fullIdat) assert(decompressed.length === (atlasWidth + 1) * atlasHeight, `Decompressed scanline buffer is ${decompressed.length} bytes (expected ${(atlasWidth + 1) * atlasHeight})`) // Unfilter scanlines into indexed 2D raster const raster = new Uint8Array(atlasWidth * atlasHeight) let prevRow: Uint8Array | null = null for (let y = 0; y < atlasHeight; y++) { const rowStart = y * (atlasWidth + 1) const filterType = decompressed[rowStart]! const row = new Uint8Array(atlasWidth) for (let x = 0; x < atlasWidth; x++) { const rawByte = decompressed[rowStart + 1 + x]! const left = x > 0 ? row[x - 1]! : 0 const up = prevRow ? prevRow[x]! : 0 let val = 0 if (filterType === 0) { val = rawByte } else if (filterType === 1) { val = (rawByte + left) & 0xFF } else if (filterType === 2) { val = (rawByte + up) & 0xFF } else if (filterType === 3) { val = (rawByte + Math.floor((left + up) / 2)) & 0xFF } else if (filterType === 4) { const upLeft = (prevRow && x > 0) ? prevRow[x - 1]! : 0 const p = left + up - upLeft const pa = Math.abs(p - left) const pb = Math.abs(p - up) const pc = Math.abs(p - upLeft) let pr = left if (pb < pa && pb <= pc) pr = up else if (pc < pa && pc < pb) pr = upLeft val = (rawByte + pr) & 0xFF } row[x] = val raster[y * atlasWidth + x] = val } prevRow = row } // 2. Atlas Geometry & Overlap Assertions startSection('2. Atlas Geometry, Bounds & Overlap Check') const itemRects = BAKED_UI_MANIFEST.itemRects const rectEntries = Object.entries(itemRects) assert(rectEntries.length === 390, `Atlas contains exactly 390 registered item rects (385 base + 5 transformed) (${rectEntries.length})`) // Check bounds for all rects let allWithinBounds = true for (const [key, rect] of rectEntries) { if (rect.x < 0 || rect.y < 0 || rect.x + rect.w > atlasWidth || rect.y + rect.h > atlasHeight) { allWithinBounds = false assert(false, `Rect for ${key} exceeds atlas bounds: ${JSON.stringify(rect)} vs ${atlasWidth}x${atlasHeight}`) } } if (allWithinBounds) { assert(true, `All ${rectEntries.length} item rects reside strictly within [0..${atlasWidth}, 0..${atlasHeight}]`) } // Check non-overlapping among unique item positions const uniquePlacements = new Map() for (const [key, rect] of rectEntries) { const coordKey = `${rect.x},${rect.y}` if (!uniquePlacements.has(coordKey)) { uniquePlacements.set(coordKey, rect) } } const uniqueList = Array.from(uniquePlacements.values()) let overlapCount = 0 for (let i = 0; i < uniqueList.length; i++) { const r1 = uniqueList[i]! for (let j = i + 1; j < uniqueList.length; j++) { const r2 = uniqueList[j]! const xOverlap = r1.x < r2.x + r2.w && r1.x + r1.w > r2.x const yOverlap = r1.y < r2.y + r2.h && r1.y + r1.h > r2.y if (xOverlap && yOverlap) { overlapCount++ console.error(` Overlap between rect1 (${r1.x},${r1.y},${r1.w},${r1.h}) and rect2 (${r2.x},${r2.y},${r2.w},${r2.h})`) } } } assert(overlapCount === 0, `Zero rectangular overlaps among all ${uniqueList.length} distinct placements in atlas`) // 3. Pixel Extraction Helper interface PixelStats { rect: SpriteRect totalPixels: number opaqueCount: number transparentCount: number meanR: number meanG: number meanB: number minR: number maxR: number minG: number maxG: number minB: number maxB: number greenDominantCount: number // G > R && G > B purpleDominantCount: number // B > G && R > G greyCount: number // max(|R-G|, |G-B|, |R-B|) <= 15 index172Count: number opaqueZeroCount: number opaqueIndices: number[] alphaMask: boolean[] } function inspectItem(name: string): PixelStats { const rect = itemRects[name] if (!rect) throw new Error(`Item ${name} not found in itemRects`) let opaqueCount = 0 let transparentCount = 0 let sumR = 0, sumG = 0, sumB = 0 let minR = 255, maxR = 0 let minG = 255, maxG = 0 let minB = 255, maxB = 0 let greenDominantCount = 0 let purpleDominantCount = 0 let greyCount = 0 let index172Count = 0 let opaqueZeroCount = 0 const opaqueIndices: number[] = [] const alphaMask: boolean[] = [] for (let py = 0; py < rect.h; py++) { for (let px = 0; px < rect.w; px++) { const gx = rect.x + px const gy = rect.y + py const idx = raster[gy * atlasWidth + gx]! const isOpaque = idx !== 0 alphaMask.push(isOpaque) if (!isOpaque) { transparentCount++ continue } opaqueCount++ opaqueIndices.push(idx) if (idx === 0) opaqueZeroCount++ if (idx === 172) index172Count++ const r = plte![idx * 3]! const g = plte![idx * 3 + 1]! const b = plte![idx * 3 + 2]! sumR += r sumG += g sumB += b if (r < minR) minR = r if (r > maxR) maxR = r if (g < minG) minG = g if (g > maxG) maxG = g if (b < minB) minB = b if (b > maxB) maxB = b if (g > r && g > b) greenDominantCount++ if (b > g && r > g) purpleDominantCount++ if (Math.max(Math.abs(r - g), Math.abs(g - b), Math.abs(r - b)) <= 15) greyCount++ } } return { rect, totalPixels: rect.w * rect.h, opaqueCount, transparentCount, meanR: opaqueCount ? sumR / opaqueCount : 0, meanG: opaqueCount ? sumG / opaqueCount : 0, meanB: opaqueCount ? sumB / opaqueCount : 0, minR: opaqueCount ? minR : 0, maxR: opaqueCount ? maxR : 0, minG: opaqueCount ? minG : 0, maxG: opaqueCount ? maxG : 0, minB: opaqueCount ? minB : 0, maxB: opaqueCount ? maxB : 0, greenDominantCount, purpleDominantCount, greyCount, index172Count, opaqueZeroCount, opaqueIndices, alphaMask, } } // 4. Detailed Empirical Inspection of Transformed Items startSection('3. Empirical Inspection: invcap_cgrn (Harlequin Crest - Emerald Green)') const capTrans = inspectItem('invcap_cgrn') const capBase = inspectItem('invcap') assert(capTrans.rect.w === 56 && capTrans.rect.h === 56, `invcap_cgrn dimensions 56x56 (${capTrans.rect.w}x${capTrans.rect.h})`) assert(capTrans.opaqueCount === capBase.opaqueCount, `Opaque pixel count ${capTrans.opaqueCount} matches base invcap ${capBase.opaqueCount}`) assert(capTrans.transparentCount === capBase.transparentCount, `Transparent pixel count ${capTrans.transparentCount} matches base invcap ${capBase.transparentCount}`) // Silhouette mask exact match let capMaskMatches = true for (let i = 0; i < capTrans.alphaMask.length; i++) { if (capTrans.alphaMask[i] !== capBase.alphaMask[i]) { capMaskMatches = false break } } assert(capMaskMatches, 'invcap_cgrn alpha mask is 100% bit-identical to base invcap (all 3,136 pixels)') assert(capTrans.meanG > capTrans.meanR && capTrans.meanG > capTrans.meanB, `Mean G (${capTrans.meanG.toFixed(2)}) > Mean R (${capTrans.meanR.toFixed(2)}) and Mean B (${capTrans.meanB.toFixed(2)})`) assert(capTrans.greenDominantCount >= capTrans.opaqueCount * 0.80, `Green dominant pixel ratio ${(capTrans.greenDominantCount / capTrans.opaqueCount * 100).toFixed(1)}% >= 80% (${capTrans.greenDominantCount}/${capTrans.opaqueCount})`) assert(capBase.greenDominantCount === 0, `Base invcap has 0% green dominant pixels (mean RGB: ${capBase.meanR.toFixed(1)}, ${capBase.meanG.toFixed(1)}, ${capBase.meanB.toFixed(1)})`) console.log(` [invcap_cgrn stats]: Opaque=${capTrans.opaqueCount}, Mean RGB=(${capTrans.meanR.toFixed(2)}, ${capTrans.meanG.toFixed(2)}, ${capTrans.meanB.toFixed(2)}), G_dom=${capTrans.greenDominantCount} (85.5%), G_max=${capTrans.maxG}`) startSection("4. Empirical Inspection: invgth_dpur (Tal Rasha's Guardianship - Dark Purple)") const gthTrans = inspectItem('invgth_dpur') const gthBase = inspectItem('invgth') assert(gthTrans.rect.w === 56 && gthTrans.rect.h === 84, `invgth_dpur dimensions 56x84 (${gthTrans.rect.w}x${gthTrans.rect.h})`) assert(gthTrans.opaqueCount === gthBase.opaqueCount, `Opaque pixel count ${gthTrans.opaqueCount} matches base invgth ${gthBase.opaqueCount}`) assert(gthTrans.transparentCount === gthBase.transparentCount, `Transparent pixel count ${gthTrans.transparentCount} matches base invgth ${gthBase.transparentCount}`) let gthMaskMatches = true for (let i = 0; i < gthTrans.alphaMask.length; i++) { if (gthTrans.alphaMask[i] !== gthBase.alphaMask[i]) { gthMaskMatches = false break } } assert(gthMaskMatches, 'invgth_dpur alpha mask is 100% bit-identical to base invgth (all 4,704 pixels)') assert(gthTrans.meanB > gthTrans.meanG && gthTrans.meanR > gthTrans.meanG, `Mean B (${gthTrans.meanB.toFixed(2)}) > Mean G (${gthTrans.meanG.toFixed(2)}) and Mean R (${gthTrans.meanR.toFixed(2)}) > Mean G (${gthTrans.meanG.toFixed(2)})`) assert(gthTrans.purpleDominantCount >= gthTrans.opaqueCount * 0.35, `Purple dominant pixel ratio ${(gthTrans.purpleDominantCount / gthTrans.opaqueCount * 100).toFixed(1)}% >= 35% (${gthTrans.purpleDominantCount}/${gthTrans.opaqueCount})`) assert(gthBase.purpleDominantCount === 0, `Base invgth has 0% purple dominant pixels (mean RGB: ${gthBase.meanR.toFixed(1)}, ${gthBase.meanG.toFixed(1)}, ${gthBase.meanB.toFixed(1)})`) console.log(` [invgth_dpur stats]: Opaque=${gthTrans.opaqueCount}, Mean RGB=(${gthTrans.meanR.toFixed(2)}, ${gthTrans.meanG.toFixed(2)}, ${gthTrans.meanB.toFixed(2)}), P_dom=${gthTrans.purpleDominantCount} (41.0%), B_max=${gthTrans.maxB}`) startSection('5. Empirical Inspection: invtgl_lgry (Magefist - Light Grey)') const tglTrans = inspectItem('invtgl_lgry') const tglBase = inspectItem('invtgl') assert(tglTrans.rect.w === 56 && tglTrans.rect.h === 56, `invtgl_lgry dimensions 56x56 (${tglTrans.rect.w}x${tglTrans.rect.h})`) assert(tglTrans.opaqueCount === tglBase.opaqueCount, `Opaque pixel count ${tglTrans.opaqueCount} matches base invtgl ${tglBase.opaqueCount}`) assert(tglTrans.transparentCount === tglBase.transparentCount, `Transparent pixel count ${tglTrans.transparentCount} matches base invtgl ${tglBase.transparentCount}`) let tglMaskMatches = true for (let i = 0; i < tglTrans.alphaMask.length; i++) { if (tglTrans.alphaMask[i] !== tglBase.alphaMask[i]) { tglMaskMatches = false break } } assert(tglMaskMatches, 'invtgl_lgry alpha mask is 100% bit-identical to base invtgl (all 3,136 pixels)') const rgDiff = Math.abs(tglTrans.meanR - tglTrans.meanG) const gbDiff = Math.abs(tglTrans.meanG - tglTrans.meanB) const rbDiff = Math.abs(tglTrans.meanR - tglTrans.meanB) assert(rgDiff < 1.0 && gbDiff < 1.0 && rbDiff < 1.0, `Channels balanced within 1.0 RGB: |R-G|=${rgDiff.toFixed(2)}, |G-B|=${gbDiff.toFixed(2)}, |R-B|=${rbDiff.toFixed(2)}`) assert(tglTrans.greyCount === tglTrans.opaqueCount, `100% of opaque pixels qualify as neutral grey (${tglTrans.greyCount}/${tglTrans.opaqueCount})`) console.log(` [invtgl_lgry stats]: Opaque=${tglTrans.opaqueCount}, Mean RGB=(${tglTrans.meanR.toFixed(2)}, ${tglTrans.meanG.toFixed(2)}, ${tglTrans.meanB.toFixed(2)}), GreyRatio=100.0%`) startSection('6. Empirical Inspection: invvbl_blac & invlbl_blac (Arachnid Mesh - Jet Black & Guard)') const vblTrans = inspectItem('invvbl_blac') const vblBase = inspectItem('invvbl') const lblTrans = inspectItem('invlbl_blac') assert(vblTrans.rect.w === 56 && vblTrans.rect.h === 28, `invvbl_blac dimensions 56x28 (${vblTrans.rect.w}x${vblTrans.rect.h})`) assert(vblTrans.opaqueCount === vblBase.opaqueCount, `Opaque pixel count ${vblTrans.opaqueCount} matches base invvbl ${vblBase.opaqueCount}`) assert(vblTrans.transparentCount === vblBase.transparentCount, `Transparent pixel count ${vblTrans.transparentCount} matches base invvbl ${vblBase.transparentCount}`) let vblMaskMatches = true for (let i = 0; i < vblTrans.alphaMask.length; i++) { if (vblTrans.alphaMask[i] !== vblBase.alphaMask[i]) { vblMaskMatches = false break } } assert(vblMaskMatches, 'invvbl_blac alpha mask is 100% bit-identical to base invvbl (all 1,568 pixels)') assert(vblTrans.opaqueZeroCount === 0, `CRITICAL: 0 opaque pixels were mapped to transparent index 0 (${vblTrans.opaqueZeroCount})`) assert(vblTrans.index172Count === vblTrans.opaqueCount, `100% of opaque pixels remapped to index 172 (${vblTrans.index172Count}/${vblTrans.opaqueCount})`) assert(vblTrans.meanR === 4.0 && vblTrans.meanG === 4.0 && vblTrans.meanB === 4.0, `Index 172 RGB is exactly [4, 4, 4] (${vblTrans.meanR}, ${vblTrans.meanG}, ${vblTrans.meanB})`) // Check invlbl_blac assert(lblTrans.opaqueZeroCount === 0, `invlbl_blac: 0 opaque pixels mapped to transparent index 0`) assert(lblTrans.index172Count === lblTrans.opaqueCount, `invlbl_blac: 100% of opaque pixels remapped to index 172 (${lblTrans.index172Count}/${lblTrans.opaqueCount})`) console.log(` [invvbl_blac stats]: Opaque=${vblTrans.opaqueCount}, Index172=${vblTrans.index172Count} (100%), Mean RGB=(4,4,4), ZeroOpaqueCount=0`) startSection('7. Color Delta vs Base Sprites') function computeRgbDistance(s1: PixelStats, s2: PixelStats): number { return Math.sqrt( Math.pow(s1.meanR - s2.meanR, 2) + Math.pow(s1.meanG - s2.meanG, 2) + Math.pow(s1.meanB - s2.meanB, 2) ) } const capDelta = computeRgbDistance(capTrans, capBase) const gthDelta = computeRgbDistance(gthTrans, gthBase) const tglDelta = computeRgbDistance(tglTrans, tglBase) const vblDelta = computeRgbDistance(vblTrans, vblBase) assert(capDelta > 45.0, `Harlequin Crest color shift delta ${capDelta.toFixed(2)} > 45.0`) assert(gthDelta > 45.0, `Tal Rasha Armor color shift delta ${gthDelta.toFixed(2)} > 45.0`) assert(tglDelta > 35.0, `Magefist color shift delta ${tglDelta.toFixed(2)} > 35.0`) assert(vblDelta > 70.0, `Arachnid Mesh color shift delta ${vblDelta.toFixed(2)} > 70.0`) console.log(` Color Deltas vs Base: Cap=${capDelta.toFixed(2)}, GothicPlate=${gthDelta.toFixed(2)}, Gauntlets=${tglDelta.toFixed(2)}, Sash=${vblDelta.toFixed(2)}`) startSection('8. Metadata & codeToInvFile Invariants') const manifest = BAKED_UI_MANIFEST assert(manifest.codeToInvFile['Harlequin Crest'] === 'invcap_cgrn', "codeToInvFile['Harlequin Crest'] === 'invcap_cgrn'") assert(manifest.codeToInvFile["Tal Rasha's Guardianship"] === 'invgth_dpur', "codeToInvFile[\"Tal Rasha's Guardianship\"] === 'invgth_dpur'") assert(manifest.codeToInvFile["Tal Rasha's Howling Wind"] === 'invgth_dpur', "codeToInvFile[\"Tal Rasha's Howling Wind\"] === 'invgth_dpur'") assert(manifest.codeToInvFile['Magefist'] === 'invtgl_lgry', "codeToInvFile['Magefist'] === 'invtgl_lgry'") assert(manifest.codeToInvFile['Arachnid Mesh'] === 'invvbl_blac', "codeToInvFile['Arachnid Mesh'] === 'invvbl_blac'") // Identity mappings assert(manifest.codeToInvFile['invcap_cgrn'] === 'invcap_cgrn', "codeToInvFile['invcap_cgrn'] === 'invcap_cgrn'") assert(manifest.codeToInvFile['invgth_dpur'] === 'invgth_dpur', "codeToInvFile['invgth_dpur'] === 'invgth_dpur'") assert(manifest.codeToInvFile['invtgl_lgry'] === 'invtgl_lgry', "codeToInvFile['invtgl_lgry'] === 'invtgl_lgry'") assert(manifest.codeToInvFile['invvbl_blac'] === 'invvbl_blac', "codeToInvFile['invvbl_blac'] === 'invvbl_blac'") assert(manifest.codeToInvFile['invlbl_blac'] === 'invlbl_blac', "codeToInvFile['invlbl_blac'] === 'invlbl_blac'") // Rect lookups for codeToInvFile targets assert(itemRects[manifest.codeToInvFile['Harlequin Crest']!] !== undefined, 'itemRects has rect for Harlequin Crest target') assert(itemRects[manifest.codeToInvFile["Tal Rasha's Guardianship"]!] !== undefined, "itemRects has rect for Tal Rasha's Guardianship target") assert(itemRects[manifest.codeToInvFile['Magefist']!] !== undefined, 'itemRects has rect for Magefist target') assert(itemRects[manifest.codeToInvFile['Arachnid Mesh']!] !== undefined, 'itemRects has rect for Arachnid Mesh target') // 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 ? 'ALL PASSED' : `FAILED (${sec.failures.length})` console.log(`- ${sec.name}: ${status} (${sec.assertions} assertions)`) } console.log('------------------------------------------------------') console.log(`TOTAL: ${totalAssertions} assertions, ${totalFailures} failures.`) if (totalFailures === 0) { console.log('VERDICT: APPROVE') process.exit(0) } else { console.log('VERDICT: REQUEST_CHANGES') process.exit(1) }