35 payloads move to tooling/scripts/blender/ and stay outside package scope. They run under Blender's bundled Python, which cannot see the repo venv, so they physically cannot import tooling.core — holding them to the D-263 contract would either fail the gate forever or force the contract to be weakened for everyone, and the second is how a gate stops meaning anything. Count verified by import rather than filename: 33 import bpy/bmesh directly, and the two that do not are still payloads per their own usage lines. garment-fit/make_logo.py is the one genuine non-payload and stays for T-1290. The bash wrapper is retired rather than kept. Keeping it would have put the install-resolution logic in two places, which is the duplication T-1286 had just finished collapsing three copies of. domains/blender/service.py owns the decisions — resolve_blender (native beats flatpak, ordering preserved), resolve_payload, absolutise — and only run_payload performs. test_blender.py pins all of them without launching Blender, which matters here more than usual: the thing being launched is a 200 MB GUI application that writes GLBs. `reach blender run` takes a registered payload name OR a path to any script, because the wrapper served both — the spikes and the glb-gen skill hand it one-off scripts of their own. An unknown name enumerates all 35 and exits 2. The exclusion now defends itself. check_carve_out_stays_carved fails if `scripts` is added to PACKAGE_ROOTS, if the payload directory empties (an empty exclusion proves nothing), or if an __init__.py appears there (which would make the payloads importable — the coupling the carve-out exists to prevent). All three arms mutation-proved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
17 lines
876 B
Python
17 lines
876 B
Python
"""The Blender carve-out — the one sanctioned exception to the reach rule.
|
|
|
|
D-263 says tooling lives in the package and every verb carries `@command`.
|
|
`tooling/scripts/blender/` does not, and cannot: those 35 files run under
|
|
Blender's BUNDLED Python interpreter, which has no access to the repo venv and
|
|
therefore cannot `import tooling.core` at all. They are payloads handed to
|
|
another program, not modules this package imports.
|
|
|
|
So the split is: the payloads stay dumb and stay out of package scope, and
|
|
everything that can be decided in our own interpreter — which Blender to use,
|
|
which payload a name refers to, which paths need absolutising — lives here and
|
|
is testable. The user-facing form is still a normal verb.
|
|
|
|
The conformance test excludes `tooling/scripts/` for this reason, and says so
|
|
inline. It is an exception with a stated cause, not an oversight.
|
|
"""
|