feat: framing deviation clause + triage of the out-of-band thirteen#108
Merged
Conversation
PR #107's survey put 13 of 22 measured examples outside the band, including a pinned calibration member whose edge bleed is the design, so the band gains the same structure the stage rules have: presumption by default, documented deviation when the bleed or the scale is the point. check_framing takes deviation=<reason>: with a non-empty reason string it measures and prints the numbers with the reason but reports instead of enforcing; an empty or whitespace reason raises ValueError so a deviation cannot be taken silently. The docstring also scopes the helper: it measures the (scene, camera) pair it is handed, so multi-scene examples pass the still's scene explicitly, and world/atmosphere-subject examples report rather than enforce because the matte has no renderable hero to isolate. Both current callers keep the enforcing default; verified unchanged on 5.1.2 and 4.5.11 (0.803/0.733 and 0.816/0.678) and falsified both ways (reasoned deviation reports with exit 0; empty reason ValueErrors with exit 1). Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
Layer 1 framing now mirrors the stage rules' structure: the 70-90 fill band and the 2 percent margin floor remain the presumption, and a composition may deviate when the bleed or the scale is the design — radiating subjects, edge-to-edge fields, world or atmosphere contracts. A deviation requires a one-line README note under a Framing deviation heading and the helper call switches to check_framing(deviation=reason) so it reports with the reason printed rather than enforcing; an undocumented deviation is still a defect, and an empty reason raises. The CLAUDE.md quality-gates bullet inherits the clause by reference. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
The smoke workflow floats: it resolves the highest published point release of each series at run time, so CI ran Blender 4.5.12 LTS on PR #107 while local .scratch held 4.5.11 — CLAUDE.md now says the series floats and a local point release may lag, with the exact-reported-version rule unchanged. Also records the Playwright lesson from #107 next to the gallery-capture gate: Chromium scroll-anchoring defeats scrollTo(0, 0) after lazy-load, so captures are full-page, not scroll-then-shoot. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
Full-size and card-scale review of each surveyed hero against its README and contract. Two are legitimate deviations and now carry the one-line README Framing deviation note: damped-track-aim (radiating composition — the spikes read as converging from beyond the frame; it is a pinned calibration member and the gallery's reference standard stays) and wave-displace (edge-to-edge field — the fill is the point). sky-texture-sun-elevation is a measurement artifact: the hero is the sky itself, so the matte only saw the cone props; its README now documents report-only. vse-cut-list is in scope — its still renders from the Bay scene with BayCam, and the README records that the (scene, camera) pair must be passed explicitly. The remaining ten are genuine defects (clipped subjects, over-fill, dead space) and land on the ROADMAP candidate pool as a restage worklist with measured numbers. No re-renders in this pass. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
TMHSDigital
added a commit
that referenced
this pull request
Jul 22, 2026
…es) (#109) * fix: target the passed scene in gallery_framing matte renders _matte_render called bpy.ops.render.render(write_still=True) bare, which renders the ACTIVE context scene — silently wrong for any example that stills from a non-context scene (vse-cut-list renders its gallery hero from a dedicated Bay scene via the operator's scene= kwarg). The matte now renders the scene it was handed, matching that idiom. Both current callers use the context scene and measure unchanged (0.803/0.733 on 5.1.2 and 4.5.11); the corrected survey that exposed this now captures each example's rendered scene via a persistent render_pre handler and re-measured all 38 examples against the scene and camera each actually renders from. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: nudge curve-bevel-arc framing into the band and gate it Right cap sat 0.012 from the right edge, under the 0.02 floor. Camera moves from (2.4,-3.4,1.7) to (2.55,-3.62,1.78) — a pure pull-back, no restage — landing fill 0.738x/0.633y with margins L0.219 R0.044 B0.083 T0.283. The render path now calls gallery_framing.check_framing before the beauty render (exit 10); check code and closed forms untouched (eval_verts=1044, eval_faces=1028, x_span=3.292 all print unchanged). Gate falsified at lens 65 (margins FAIL, exit 10, no artifact) and restored. Identical framing numbers on 4.5.11. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: nudge driver-wave framing into the band and gate it Sixteen-column skyline over-filled the frame at 0.969x with side margins 0.016. Camera pulls back from (0,-13.5,2.0) to (0,-15.0,2.0) — pure distance, no restage — landing fill 0.869x/0.333y with margins L0.066 R0.066 B0.367 T0.300. Render path gated with check_framing (exit 10); check values unchanged (driven_range 0.404..2.399, flushed_to_original). Gate falsified at lens 55 (fill 0.994 FAIL, exit 10) and restored. Identical numbers on 4.5.11. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: nudge shader-node-group framing into the band and gate it Sphere pair over-filled the frame at 0.969x with side margins 0.016. Camera pulls back from (0,-7.8,2.6) to (0,-8.7,2.6) — pure distance, no restage — landing fill 0.869x/0.650y with margins L0.066 R0.066 B0.256 T0.094. Render path gated with check_framing (exit 10); check values unchanged (group users=2, distinct instance tints). Gate falsified at lens 72 (fill 1.000 FAIL, exit 10) and restored. Identical numbers on 4.5.11. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: nudge swatch-grid framing into the band and gate it The ortho grid over-filled vertically at 0.944y. ortho_scale 7.8 -> 8.4 (height 4.39 -> 4.73 for the 4.14-unit grid) lands fill 0.769x/0.878y with margins L0.116 R0.116 B0.061 T0.061. verify_png's third/half cell-center sampling tolerates the scale change — distinct_regions=6 and max_pixel=1.000 confirmed at 1280 default and at the smoke invocation (640, cycles, 8 samples) on 5.1.2 and 4.5.11. Render path gated with check_framing (exit 10); falsified at ortho_scale 6.5 (fill 1.000 FAIL, exit 10) and restored. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: lift png-exr-alpha plinth off the bottom edge and gate it The shared display plinth touched the bottom frame edge (margin 0.000). A pull-back first overshot (fill 0.672 under-band), so the fix is an aim drop instead: aim z 1.65 -> 1.38 at unchanged camera distance pitches the composition up, landing fill 0.725x/0.628y with margins L0.122 R0.056 B0.028 T0.150 — distance and composition otherwise untouched. Render path gated with check_framing (exit 10); falsified at lens 64 (fill 0.916 FAIL, exit 10) and restored. Identical numbers on 4.5.11. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: nudge gp-lineart-contour framing into the band and gate it The neon vessel over-filled vertically at 0.978y with its base cropped by the bottom edge. Camera pulls back from (3.4,-4.2,2.4) to (3.95,-4.9,2.62) — pure distance, no restage — landing fill 0.463x/0.867y with margins L0.272 R0.266 B0.044 T0.089 (an intermediate stop landed y at exactly 0.900, on the band ceiling, so the pull-back goes one step further for cross-version slack). Render path gated with check_framing (exit 10); check values unchanged (strokes=10, points=34, restore recovers both). Gate falsified at lens 62 (fill 1.000 FAIL, exit 10) and restored. 4.5.11 matches (0.469x/0.867y). Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: reframe vse-cut-list bay into the band and gate the Bay scene The corrected survey (render_pre capture) measured this hero for the first time: the monitor top was cropped and the desk bled the bottom edge (fill 1.000y, touch B+T) — the #107 survey had read bpy.context.scene, which is the cut-list scene, not the Bay the still renders from. BayCam pulls back from (2.0,-5.2,1.72) to (3.05,-7.9,2.0) with aim z 1.28 -> 1.20, landing fill 0.506x/0.850y with margins L0.247 R0.247 B0.067 T0.083. This was the most-broken of the seven (frame-filling before), so the composition change is correspondingly larger; the bezel, stand, desk, and on-screen cut list are all fully in frame now. The gate runs on the Bay scene (the helper's scene-targeted matte from the previous commit), falsified at lens 66 (fill 1.000 FAIL, exit 10) and restored. check and --check-pixels both exit 0 on 5.1.2 and 4.5.11 with identical pixel witnesses. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * docs: reduce the framing worklist to the recomposition remainder The corrected survey plus the marginal sweep leaves four examples that need real reframing rather than a camera nudge: depsgraph-export (cube amputated), vertex-weight-limit (off-center, base cropped), text-version-stamp (dead lower third), triangulate-tangents (2x-class move-in). The seven marginal cases are marked swept and gated; deviations and the sky-texture artifact stay as documented in #108. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> --------- Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Framing deviation clause + triage of the #107 out-of-band thirteen
Docs-and-triage follow-up to #107. The survey it produced put 13 of 22 measured examples outside the new framing band — including
damped-track-aim, a pinned calibration member whose radiating needles bleed past the frame edges by design. When more than half the corpus violates a fresh rule and the rule's own reference standard fails it, the rule is at least partly wrong. This pass gives the rule the same presumption/deviation structure the stage rules have, reconciles two runtime facts, and triages all thirteen (plusvse-cut-list) before the helper gets wired gallery-wide. No re-renders.Part 1 — deviation clause + helper signature
docs/VISUAL-STYLE.mdLayer 1: the 70–90 % fill band and the 2 % edge-margin floor remain the presumption; a composition may deviate when the bleed or the scale is the design — radiating subjects, edge-to-edge fields, world/atmosphere contracts. A deviation requires a one-line README note under aFraming deviationheading (exactly as stage deviations); an undocumented deviation is a defect.Mechanical, not honor-system — new helper signature:
deviation=None(default): enforces (exit 10 on violation) — unchanged for both current callers.deviation="<non-empty reason>": measures and prints the numbers with the reason (framing_deviation reason="..." enforcement=report ...), returns 0 — report, not enforce.deviation=""/ whitespace: raisesValueError— a deviation cannot be taken silently.CLAUDE.md's quality-gates bullet inherits the clause by reference. The helper docstring also scopes the tool: it measures the (scene, camera) pair it is handed (multi-scene examples pass the still's scene explicitly), and world/atmosphere-subject examples report rather than enforce because the matte has no renderable hero to isolate.
Part 2 — two reconciled runtime facts (CLAUDE.md)
blender-smoke.ymlresolves the binary withgrep -oE "blender-${series}\.[0-9]+-linux-x64\.tar\.xz" | sort -V | uniq | tail -1on the download.blender.org listing — highest published point release at run time, not a pin. Its 4.5 job ran 4.5.12 LTS on feat: measurable framing gate + restage hygiene/origin heroes into the band #107 while local.scratch/held 4.5.11. CLAUDE.md now says the series floats and a local point release may lag; the rule that agents state the exact version their binary reports is unchanged.<img>tags lazy-load, and Chromium scroll-anchoring defeatsscrollTo(0, 0)after images load (observed on feat: measurable framing gate + restage hygiene/origin heroes into the band #107: scrollY stayed ~3.3–3.5k after the scroll-back) — take full-page captures and crop locally.Part 3 — triage (all thirteen + vse-cut-list)
Each hero reviewed at full size and gallery-card scale against its README and contract. Measured numbers from the #107 survey (silhouette strategy, union-of-renderables).
Bayscene (BayCam); the survey readbpy.context.scene. The helper needs no skip contract — it measures the (scene, camera) pair it is handed. README records the pair explicitly.The ten defects land on the ROADMAP candidate pool as a restage worklist with measured numbers. No example besides the README notes above was touched; nothing was re-rendered or re-staged.
Falsification evidence (deviation path, mesh-hygiene-audit as probe, 5.1.2)
deviation="probe: deliberate under-fill to witness report mode"→framing_fill x=0.481 … FAILprinted,framing_deviation reason="…" enforcement=report fill_ok=Falseprinted, exit 0, artifact written. Restored.deviation=""→ValueError: check_framing deviation requires a non-empty reason string…, exit 1, no artifact. Restored (file byte-identical to main, diff-verified).Verification
check_framingcallers re-run after the signature change, render path, exit 0 with unchanged numbers — 5.1.2: hygiene 0.803x/0.733y (margins L0.100 R0.097 B0.050 T0.122), origin 0.816x/0.678y (L0.084 R0.100 B0.072 T0.183); 4.5.11: identical values.python scripts/build_gallery.pyregenerated; the four regenerated detail pages (damped-track-aim, wave-displace, sky-texture-sun-elevation, vse-cut-list) read character by character — newFraming deviation/Framing measurementsections complete, code spans escaped, no truncation or artifacts..scratch/blender-5.1.2-windows-x64/blender.exe(reports Blender 5.1.2),.scratch/blender-4.5.11-windows-x64/blender.exe(reports Blender 4.5.11 LTS).Live-run vs inspection-only