You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 7d90367
Browse filesBrowse the repository at this point in the historyBrowse files
feat: enforce framing deviation at the call site (#149)
check_framing no longer accepts deviation=. measure_framing_deviation returns the score so bleed compositions fail at the call site. modular-kit-snap asserts a projection fill-over cap; socket-attach-points drops the flag and leaves --falsify unenforced.
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy file name to clipboardExpand all lines: CLAUDE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -140,7 +140,7 @@ Stage with **explicit paths only** — never `git add -A` or `git add .`. Cursor
140
140
## Quality Gates for Example Runs
141
141
142
142
-`docs/VISUAL-STYLE.md` is the **binding** render standard; deviations are defects.
143
-
-**Framing gate:** Layer 1 framing is measured, not eyeballed — the example's `--output` render path calls the shared helper `examples/gallery_framing.py` (`check_framing`, exit 10 on violation) before writing the still: hero fill 0.70–0.90 of frame in at least one axis, every element that matters clearing all four edges by ≥ 0.02. The check-only path never invokes it, so smoke runtimes are unaffected. Documented framing deviations (VISUAL-STYLE Layer 1) call `check_framing(..., deviation="reason")` — the helper reports instead of enforcing, and the reason string is required.
143
+
-**Framing gate:** Layer 1 framing is measured, not eyeballed — the example's `--output` render path calls the shared helper `examples/gallery_framing.py` (`check_framing`, exit 10 on violation) before writing the still: hero fill 0.70–0.90 of frame in at least one axis, every element that matters clearing all four edges by ≥ 0.02. The check-only path never invokes it, so smoke runtimes are unaffected. The helper measures; call sites enforce. Bleed compositions call `measure_framing_deviation` and assert their own cap at the call site — `check_framing` has no `deviation=` flag.
144
144
-**Contact-sheet gate:** composite the candidate hero beside the pinned calibration set — currently `armature-bend`, `damped-track-aim`, `bmesh-gear` — commit the composite under `docs/gallery/contact-sheets/`, link it in the PR body, and report per-criterion verdicts (stage darkness, wedge warmth, subject fill, saturation, thumbnail legibility) including mean luminance versus the calibration images. A claim without the committed composite is not acceptable evidence. **This list is the canonical home of the pinned set** — update it here when a new example outclasses a member; `docs/new-example-prompt.md` points here rather than naming members. The longer "calibration references" list in `docs/VISUAL-STYLE.md` is a style reference, not this contact-sheet set.
145
145
- **Asset-sheet gate (asset-type examples — game props/kits):** composite the hero asset rendered alone (neutral three-quarter view, plain studio lighting, no staging tricks, no labels, no comparison props) beside the pinned asset-quality reference set — currently `collision-hull-proxy`, `custom-normals-shade`, `vertex-weight-limit`, `lod-decimate-chain` — rendered the same way; commit under `docs/gallery/asset-sheets/`, link it in the PR body, and report a verdict. The asset ships only if it is not identifiable as the least-designed object in that lineup — a strong scene can carry a weak model; this gate removes the scene. **This list is the canonical home of the reference set** — update it here when a new asset outclasses a member. The measurable floors behind the gate (naming, material variation, edge treatment) live in `examples/gallery_asset_quality.py` — render path only, same call pattern as `gallery_framing`, exit 11 on violation — with the calibration table and dropped-floor evidence in `docs/VISUAL-STYLE.md` § Asset quality.
146
146
-**Falsification:** every check must be proven to fail once — break the contract, observe the non-zero exit, restore — with the probe and the measured error reported in the PR body. An assertion that cannot fail witnesses nothing.
Copy file name to clipboardExpand all lines: docs/gallery/modular-kit-snap/index.html
+37-17Lines changed: 37 additions & 17 deletions
Original file line number
Diff line number
Diff line change
@@ -267,15 +267,16 @@ <h1>modular-kit-snap</h1>
267
267
<p><strong>What each check catches on failure</strong> (probed with an unsnapped variant built by the same code minus the snap pass — 3 mm end-ring skew, 2 mm y-nudge on two verts): boundary verts off the end planes, worst <strong>3.000e-03 m</strong> (exit 3); opposing rings displaced <strong>2.000e-03</strong> (exit 4); tiled joint gap/overlap (exit 5); bbox off the declared tile by <strong>3.000e-03</strong> (exit 6); boundary edges torn off the rim (exit 7); non-watertight detail (exit 8); detail escaping the tile (exit 9); unapplied transforms, default names, or wandering origins (exit 11).</p>
268
268
<p><strong>Version witness:</strong> check output is byte-identical on Blender 4.5.11 LTS and 5.1.2 — same counts, same zero measured deviations.</p>
269
269
<p><strong>Render as proof:</strong> a four-segment run — the joints vanish. The falsification variant (<code>--falsify</code>) accumulates a 120 mm gap, 50 mm lateral jogs, and 40 mm floor steps at each joint: floor plates split with dark seams and the trim rails visibly break. The check measures the same failure class at 3 mm; the render exaggerates it to read at frame scale. The render path also gates the asset through <code>examples/gallery_asset_quality.py</code> (naming, material variation, edge treatment — exit 11). An earlier revision shipped flat grey wall panels and was remodeled under that gate: each panel is now an assembly (backing plate + inset panel + four bolt heads), the palette shifted teal-slate so the card does not twin with <code>lightmap-uv-channel</code>'s warm cart, and mean luminance was brought into the calibration range (82.7 → 66.1, ceiling 77.7) — no luminance deviation needed.</p>
270
-
<p><strong>Framing deviation:</strong> the still is an interior corridor run — the envelope surrounds the camera on five sides and the tiling joints are the proof, so the subject reads as extending past the frame (the radiating-architecture class of VISUAL-STYLE Layer 1). <code>check_framing</code> measures and reports (fill 1.000/1.000, all-edge bleed) without enforcing, with the reason string at the call site.</p>
270
+
<p><strong>Framing deviation:</strong> the still is an interior corridor run — the envelope surrounds the camera on five sides and the tiling joints are the proof, so the subject reads as extending past the frame. The helper measures; this example enforces a projection-space fill-over cap (<code>FRAME_DEV_MAX = 8.0</code>). Gallery camera scores ~5.06 (pass). <code>--close-camera</code> scores ~30.9 and exits 10. Silhouette saturates at fill 1.0, so the cap is measured with <code>strategy="projection"</code>.</p>
<p>Per-script sequential checks. <code>9</code> is a valid check code; there is no rule against it. <code>10</code> is the shared framing helper. <code>11</code> is the shared asset-quality helper.</p>
277
-
<p>| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Uncaught exception (FATAL wrapper) | | 2 | argparse / usage | | 3 | Boundary vert count or end-plane membership | | 4 | End rings do not partition evenly, or opposing loops differ | | 5 | Tiled instances do not share boundary positions | | 6 | Shell or whole-asset bbox off the declared tile | | 7 | Boundary edge count, non-manifold edges, or rim off the end planes | | 8 | Detail part not watertight | | 9 | Detail part reaches a tile boundary; also <code>--output</code> produced no file | | 11 | Kit part count, unapplied scale, namespace, or origin; also gallery asset-quality violation |</p>
278
-
<p>The <code>blender-smoke</code> workflow runs the check on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the <code>needs-5.1</code> PR label, or manual dispatch). Smoke does not pass <code>--output</code>or <code>--falsify</code>.</p>
277
+
<p>Per-script sequential checks. <code>9</code> is a valid check code; there is no rule against it. <code>10</code> is this example's framing-deviation cap (call site, not the shared Layer 1 helper). <code>11</code> is the shared asset-quality helper.</p>
278
+
<p>| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Uncaught exception (FATAL wrapper) | | 2 | argparse / usage | | 3 | Boundary vert count or end-plane membership | | 4 | End rings do not partition evenly, or opposing loops differ | | 5 | Tiled instances do not share boundary positions | | 6 | Shell or whole-asset bbox off the declared tile | | 7 | Boundary edge count, non-manifold edges, or rim off the end planes | | 8 | Detail part not watertight | | 9 | Detail part reaches a tile boundary; also <code>--output</code> produced no file | | 10 | Framing deviation score exceeds cap (<code>--close-camera</code>) | | 11 | Kit part count, unapplied scale, namespace, or origin; also gallery asset-quality violation |</p>
279
+
<p>The <code>blender-smoke</code> workflow runs the check on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the <code>needs-5.1</code> PR label, or manual dispatch). Smoke does not pass <code>--output</code>, <code>--falsify</code>, or <code>--close-camera</code>.</p>
279
280
</section>
280
281
<sectionclass="detail-section src">
281
282
<h2>Source</h2>
@@ -324,6 +325,7 @@ <h2>Source</h2>
324
325
blender --background --python modular_kit_snap.py -- # check only
p.add_argument(<spanclass="s">"--output"</span>, default=<spanclass="k">None</span>, help=<spanclass="s">"optional: render a still PNG here"</span>)
<p>Smoke does not pass <code>--output</code> or <code>--skip-decimate</code>.</p>
275
275
<h2>Exit codes</h2>
276
-
<p>File-local. <code>9</code> is a valid check code. <code>10</code> is reserved for <code>gallery_framing.check_framing</code> on the <code>--output</code> path (no <code>deviation=</code>).</p>
276
+
<p>File-local. <code>9</code> is a valid check code. <code>10</code> is reserved for <code>gallery_framing.check_framing</code> on the <code>--output</code> path.</p>
277
277
<p>| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Uncaught exception (FATAL wrapper) | | 2 | argparse / usage | | 3 | Mesh did not build / no UV layer | | 4 | Base triangle count outside range | | 5 | Material count ≠ 2 distinct slots | | 6 | UVs outside 0..1 | | 7 | UV AABB overlap above tolerance | | 8 | World AABB off declared outer size | | 9 | LOD ratio band (<code>--skip-decimate</code> lands here) | | 10 | Framing gate (render path only) | | 11 | Collider triangle count above ceiling | | 12 | Bake did not finish or image has no data | | 13 | Export file missing or empty | | 14 | <code>--output</code> produced no file |</p>
0 commit comments