Skip to content

Commit 98fbd22

Browse files
TMHSDigitalclaude
andcommitted
fix(examples): reserve exits 2/10/11 and make falsifiers reach behavioral checks
Exit codes are how smoke and the falsifiers tell which check fired. Twenty examples spent argparse's 2 or the render gates' 10/11 on their own checks, so those contracts could never be falsifier targets or were misattributed; gltf-skin-roundtrip's gates even returned the same 10/11 as its armature and bone checks. exit-pre-sidecar's --force-run returned 2 on both its expected and its unexpected branch (now 3 and 4). check_exit_code_readme now rejects a literal 2/10/11 at an example's exit site and any 2/10/11 table row that is not the reserved meaning or adds "also" (#473). Twelve falsifiers stopped at a read-back of the value their own flag had just written, so the behavioral check was never reached and could be deleted with smoke still green. Each read-back is gone or runs after the behavioral check as a diagnostic; shader-node-group gains a tiny Cycles probe in a throwaway scene and text-version-stamp compares evaluated glyphs against a reference TextCurve. Every row was re-proven by deleting its behavioral check: the falsifier then misses its expected exit (#469). png-exr-alpha no longer sets scene image_settings that Image.save() ignores, inside a silent except. gn-sdf-remesh gains --no-set-material, swatch-grid gains --invert-engine-id and --no-specular-shim and asserts the specular value. Bulk per-element writes become foreach_set / foreach_get, and check_example_rules covers .loops/.edges/.data on mesh and attribute layers (#474). Signed-off-by: TMHSDigital <tmhospitalitystrategies@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 4aeb805 commit 98fbd22

98 files changed

Lines changed: 913 additions & 439 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CONTRIBUTING.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,17 @@ file-local and are not portable. `no-mesh` is `2` in
240240
`templates/ai-asset-pipeline-template/`; both are correct. Copy a template's
241241
own table from that template, not from this paragraph.
242242

243+
**Reserved in examples/.** Three codes mean one thing in every example. `2`
244+
is argparse's usage exit only, never a check. `10` is the gallery framing
245+
gate (`gallery_framing.EXIT_FRAMING`) and `11` is the asset-quality gate
246+
(`gallery_asset_quality.EXIT_ASSET_QUALITY`). An example returns the
247+
helper's constant or check call for those, and gives its own checks other
248+
numbers. A shared code makes a falsifier impossible to target (catalog
249+
falsifiers may not expect 2) or misattributes which check fired.
250+
`tests/check_exit_code_readme.py` rejects a literal 2, 10 or 11 at an
251+
example's exit site, and an Exit codes row for them that says anything
252+
else or adds "also".
253+
243254
**FATAL wrapper.** `sys.exit(1)` on an uncaught exception in the `__main__`
244255
guard. Uniform across the examples. `1` means crashed, never a named check.
245256

‎docs/gallery/car-mirror-symmetry/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ <h2 id="run">Run<a class="anchor" href="#run" aria-label="Link to this section">
8080
blender --background --python car_mirror_symmetry.py -- --output car.png --engine cycles</code></pre>
8181
<h2 id="exit-codes">Exit codes<a class="anchor" href="#exit-codes" aria-label="Link to this section">#</a></h2>
8282
<p>Per-script sequential checks. <code>9</code> is a valid check code; there is no rule against it.</p>
83-
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Body datablock is not the authored half</td></tr><tr><td>4</td><td>Authored centerline vert count ≠ 28</td></tr><tr><td>5</td><td>Evaluated verts ≠ <code>2n − c</code> (<code>--no-mirror</code> lands here)</td></tr><tr><td>6</td><td>Evaluated on-plane verts ≠ centerline; also <code>--output</code> produced no file</td></tr><tr><td>7</td><td>Evaluated Euler characteristic ≠ 2</td></tr><tr><td>8</td><td>Non-manifold edges in the evaluated shell</td></tr><tr><td>9</td><td>Evaluated verts lack a mirrored partner</td></tr><tr><td>10</td><td>Mirror partner deviation above tolerance</td></tr><tr><td>11</td><td>Evaluated bbox not symmetric about X</td></tr><tr><td>12</td><td>Mirrored-part origin off the plane</td></tr><tr><td>13</td><td>Mirrored-part datablock is not the authored half (verts, faces, on-plane verts)</td></tr><tr><td>14</td><td>Mirrored-part evaluated counts ≠ <code>2n − weld</code> / <code>2f</code>, or on-plane verts ≠ weld</td></tr><tr><td>15</td><td>Mirrored-part partner check failed</td></tr><tr><td>16</td><td>Mirrored-part evaluated mesh stayed on one side</td></tr><tr><td>17</td><td>Gallery framing violation (<code>--output</code> path only; <code>gallery_framing</code> returns 10, remapped)</td></tr><tr><td>18</td><td>Asset-quality floor violation (<code>--output</code> path only; <code>gallery_asset_quality</code> returns 11, remapped)</td></tr></tbody></table></div>
83+
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Body datablock is not the authored half</td></tr><tr><td>4</td><td>Authored centerline vert count ≠ 28</td></tr><tr><td>5</td><td>Evaluated verts ≠ <code>2n − c</code> (<code>--no-mirror</code> lands here)</td></tr><tr><td>6</td><td>Evaluated on-plane verts ≠ centerline; also <code>--output</code> produced no file</td></tr><tr><td>7</td><td>Evaluated Euler characteristic ≠ 2</td></tr><tr><td>8</td><td>Non-manifold edges in the evaluated shell</td></tr><tr><td>9</td><td>Evaluated verts lack a mirrored partner</td></tr><tr><td>10</td><td>Gallery framing violation (<code>--output</code> path only; <code>gallery_framing</code>)</td></tr><tr><td>11</td><td>Asset-quality floor violation (<code>--output</code> path only; <code>gallery_asset_quality</code>)</td></tr><tr><td>12</td><td>Mirrored-part origin off the plane</td></tr><tr><td>13</td><td>Mirrored-part datablock is not the authored half (verts, faces, on-plane verts)</td></tr><tr><td>14</td><td>Mirrored-part evaluated counts ≠ <code>2n − weld</code> / <code>2f</code>, or on-plane verts ≠ weld</td></tr><tr><td>15</td><td>Mirrored-part partner check failed</td></tr><tr><td>16</td><td>Mirrored-part evaluated mesh stayed on one side</td></tr><tr><td>17</td><td>Mirror partner deviation above tolerance</td></tr><tr><td>18</td><td>Evaluated bbox not symmetric about X</td></tr></tbody></table></div>
8484
<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>. Its catalog falsifier is <code>--no-mirror</code> (expects exit 5).</p>
8585
</section>
8686
<section class="detail-section src" id="source">

‎docs/gallery/color-attribute-wheel/index.html‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ <h2 id="run">Run<a class="anchor" href="#run" aria-label="Link to this section">
7777
blender --background --python color_attribute_wheel.py -- --output wheel.png --engine cycles</code></pre>
7878
<h2 id="exit-codes">Exit codes<a class="anchor" href="#exit-codes" aria-label="Link to this section">#</a></h2>
7979
<p>Per-script sequential checks. <code>9</code> is a valid check code; there is no rule against it.</p>
80-
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Topology ≠ closed form</td></tr><tr><td>4</td><td>Color attribute missing</td></tr><tr><td>5</td><td>Domain/type ≠ CORNER/FLOAT_COLOR (<code>--point-domain</code> lands here)</td></tr><tr><td>6</td><td>Attribute sized to verts, not loops</td></tr><tr><td>7</td><td><code>active_color</code> not set</td></tr><tr><td>8</td><td>Probe loop color off HSV closed form</td></tr><tr><td>9</td><td><code>--output</code> produced no file</td></tr><tr><td>10</td><td>Framing gate violation on the <code>--output</code> path (<code>gallery_framing</code>)</td></tr></tbody></table></div>
81-
<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>. Its catalog falsifier is <code>--point-domain</code> (expects exit 5).</p>
80+
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Topology ≠ closed form</td></tr><tr><td>4</td><td>Color attribute missing</td></tr><tr><td>5</td><td>Domain/type ≠ CORNER/FLOAT_COLOR (diagnostic, checked last)</td></tr><tr><td>6</td><td>Attribute sized to verts, not loops (<code>--point-domain</code> lands here)</td></tr><tr><td>7</td><td><code>active_color</code> not set</td></tr><tr><td>8</td><td>Probe loop color off HSV closed form</td></tr><tr><td>9</td><td><code>--output</code> produced no file</td></tr><tr><td>10</td><td>Framing gate violation on the <code>--output</code> path (<code>gallery_framing</code>)</td></tr></tbody></table></div>
81+
<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>. Its catalog falsifier is <code>--point-domain</code> (expects exit 6).</p>
8282
</section>
8383
<section class="detail-section src" id="source">
8484
<h2>Source</h2>

‎docs/gallery/compositor-glare/index.html‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,16 @@ <h2 id="run">Run<a class="anchor" href="#run" aria-label="Link to this section">
6868
<pre tabindex="0"><code># Cheap correctness check (two tiny renders) — the CI check:
6969
blender --background --python compositor_glare.py --
7070

71-
# Falsifier: Threshold=10.0. Must exit non-zero (Threshold==1.0).
71+
# Falsifier: Threshold=1000.0, above the brightest ring (18). Must exit non-zero (no halo pixels, exit 4).
7272
blender --background --python compositor_glare.py -- --threshold-high
7373

7474
# Also render a still (EEVEE on a GPU host; use --engine cycles on GPU-less hosts):
7575
blender --background --python compositor_glare.py -- --output rings.png
7676
blender --background --python compositor_glare.py -- --output rings.png --engine cycles</code></pre>
7777
<h2 id="exit-codes">Exit codes<a class="anchor" href="#exit-codes" aria-label="Link to this section">#</a></h2>
7878
<p>Per-script sequential checks. <code>9</code> is a valid check code; there is no rule against it.</p>
79-
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Compositor tree / Glare / Threshold / link-chain contract (<code>--threshold-high</code> lands here)</td></tr><tr><td>4</td><td>Check render missing, tube dark, no halo, or halo does not fall off</td></tr><tr><td>5</td><td>Halo present with compositing off</td></tr><tr><td>6</td><td><code>--output</code> produced no file</td></tr><tr><td>10</td><td>Gallery framing violation (render path; checked before the beauty render)</td></tr></tbody></table></div>
80-
<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>. Its catalog falsifier is <code>--threshold-high</code> (expects exit 3).</p>
79+
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Compositor tree / Glare / link-chain contract</td></tr><tr><td>4</td><td>Check render missing, tube dark, no halo, or halo does not fall off (<code>--threshold-high</code> lands here)</td></tr><tr><td>5</td><td>Halo present with compositing off</td></tr><tr><td>6</td><td><code>--output</code> produced no file</td></tr><tr><td>10</td><td>Gallery framing violation (render path; checked before the beauty render)</td></tr></tbody></table></div>
80+
<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>. Its catalog falsifier is <code>--threshold-high</code> (expects exit 4).</p>
8181
</section>
8282
<section class="detail-section src" id="source">
8383
<h2>Source</h2>

‎docs/gallery/cross-version-property-delete/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ <h2 id="run">Run<a class="anchor" href="#run" aria-label="Link to this section">
7878
<p>The <code>--output</code> render path measures framing against the Layer 1 band via <code>examples/gallery_framing.py</code> (exit 10 on violation) before writing the still.</p>
7979
<h2 id="exit-codes">Exit codes<a class="anchor" href="#exit-codes" aria-label="Link to this section">#</a></h2>
8080
<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.</p>
81-
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage; also an active object existed after the data-API build</td></tr><tr><td>3</td><td>Custom ID property did not land</td></tr><tr><td>4</td><td><code>property_unset</code> on a custom ID key did not TypeError, or it deleted the key</td></tr><tr><td>5</td><td><code>del</code> did not report removal</td></tr><tr><td>6</td><td>Keep lamp lost the ID property</td></tr><tr><td>7</td><td>Clear lamp still has the ID property (<code>--skip-delete</code> / <code>--unset-instead</code> land here)</td></tr><tr><td>8</td><td>Registered-prop contract broke: attribute/<code>property_unset</code> failed, the prop sits on the wrong side of the 5.0 ID-property split, or <code>scene[&quot;name&quot;]</code> raised <code>KeyError</code> (<code>--subscript-registered</code> on 5.0+; exits 0 on 4.5, where subscript access still works)</td></tr><tr><td>10</td><td>Gallery framing violation</td></tr><tr><td>12</td><td><code>--output</code> produced no file</td></tr></tbody></table></div>
81+
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Custom ID property did not land</td></tr><tr><td>4</td><td><code>property_unset</code> on a custom ID key did not TypeError, or it deleted the key</td></tr><tr><td>5</td><td><code>del</code> did not report removal</td></tr><tr><td>6</td><td>Keep lamp lost the ID property</td></tr><tr><td>7</td><td>Clear lamp still has the ID property (<code>--skip-delete</code> / <code>--unset-instead</code> land here)</td></tr><tr><td>8</td><td>Registered-prop contract broke: attribute/<code>property_unset</code> failed, the prop sits on the wrong side of the 5.0 ID-property split, or <code>scene[&quot;name&quot;]</code> raised <code>KeyError</code> (<code>--subscript-registered</code> on 5.0+; exits 0 on 4.5, where subscript access still works)</td></tr><tr><td>9</td><td>An active object existed after the data-API build (checked first)</td></tr><tr><td>10</td><td>Gallery framing violation</td></tr><tr><td>12</td><td><code>--output</code> produced no file</td></tr></tbody></table></div>
8282
<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>. Its catalog falsifiers are <code>--skip-delete</code> (expects exit 7); <code>--unset-instead</code> (expects exit 7); <code>--subscript-registered</code> (expects exit 8; 5.0+ only; SKIP on older Blender).</p>
8383
</section>
8484
<section class="detail-section src" id="source">

0 commit comments

Comments
 (0)