{"record":{"id":"7418e12d0a11596c","repo":"Hmbown/CodeWhale","slug":"app-icon-blob-has-unexpected-height-edge","errorCode":null,"errorMessage":"app-icon blob has unexpected height: {edge}","messagePattern":"app-icon blob has unexpected height: (.+?)","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"scripts/brand/braille-mark.py","lineNumber":164,"sourceCode":"                        and y0 <= ny < y1\n                        and not seen[ny * width + nx]\n                        and is_navy(pixels[nx, ny])\n                    ):\n                        seen[ny * width + nx] = 1\n                        stack.append((nx, ny))\n            if len(blob) > len(best):\n                best = blob\n    if len(best) < 10_000:\n        raise SystemExit(\"app-icon blob not found in the founder sheet\")\n    bx0 = min(x for x, _ in best)\n    bx1 = max(x for x, _ in best)\n    by0 = min(y for _, y in best)\n    by1 = max(y for _, y in best)\n    # The white whale cuts the blob's left side, but its full height shows:\n    # the icon is square, so the edge is the height.\n    edge = by1 - by0 + 1\n    if not 150 <= edge <= 260:\n        raise SystemExit(f\"app-icon blob has unexpected height: {edge}\")\n    cx = (bx0 + bx1) // 2\n    cy = (by0 + by1) // 2\n    half = edge // 2 + ICON_PAD\n    box = (cx - half, cy - half, cx + half, cy + half)\n    print(\n        f\"// app-icon navy blob x {bx0}-{bx1} y {by0}-{by1}, \"\n        f\"square crop {box[0]},{box[1]}-{box[2]},{box[3]}\",\n        file=sys.stderr,\n    )\n    square = image.crop(box).convert(\"RGBA\")\n    sw, sh = square.size\n    ink = square.load()\n    flood = bytearray(sw * sh)\n\n    def is_bg(x: int, y: int) -> bool:\n        r, g, b = ink[x, y][:3]\n        return min(r, g, b) > BG_CUTOFF\n","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/scripts/brand/braille-mark.py#L146-L182","documentation":"After finding the app-icon blob, icon_square computes its height (edge = by1 - by0 + 1) and asserts it falls within 150–260 pixels, because the icon is known to be square and this height defines the crop box. A height outside this range means the located blob is not the app icon (wrong image, changed art, or wrong scale), and the resulting crop would be wrong.","triggerScenarios":"Running write_png -> icon_square on a founder sheet where the largest navy blob's vertical extent is <150 or >260 px — e.g. sheet rendered at a different DPI/scale, icon replaced with new art of different size, or a non-icon element (banner, splash) became the largest blob.","commonSituations":"Retina/1x resolution mismatch in the asset; icon redesign changing proportions; script pointed at a stale or exported-at-wrong-size PNG; blob including extra antialiased rows from a nearby element.","solutions":["Re-export the founder sheet at the resolution the script expects (edge 150–260)","Confirm the largest blob is the icon, not another design element; adjust the flood-fill target color if needed","Inspect the printed blob bounds and scale the sheet accordingly","If the design legitimately changed, update the 150–260 range in icon_square to the new expected icon height"],"exampleFix":"# before\nif not 150 <= edge <= 260:\n    raise SystemExit(f\"app-icon blob has unexpected height: {edge}\")\n# after\nif not 150 <= edge <= 260:\n    raise SystemExit(\n        f\"app-icon blob has unexpected height: {edge} \"\n        \"(expected 150-260; is the sheet at the right resolution?)\"\n    )","handlingStrategy":"validation","validationCode":"edge = by1 - by0 + 1\nif not (150 <= edge <= 260):\n    raise SystemExit(f\"icon edge {edge}px out of 150-260; re-export sheet\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on one export DPI/scale for the founder sheet and document it","Verify blob bounds visually (print + annotate a debug crop) after any redesign","Keep the expected 150–260 range in a named constant next to the asset spec","Re-run braille-mark.py locally before pushing asset changes"],"tags":["image-processing","size-validation","build-script"],"backgroundTag":"value-out-of-range","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}