Metadata-Version: 2.4
Name: 3dqa
Version: 1.0.0
Summary: Validate and auto-heal 3D assets (.glb/.gltf/.obj/.ply/.stl) — the stateless QA & repair layer for pipeline and AI-generated content.
Author: 3D Pipeline QA Engine
License: 3dqa Free-Use License (Source-Available, No Redistribution)
        Copyright (c) 2026 3D Pipeline QA Engine. All rights reserved.
        
        This license applies to the software distributed as the "3dqa" package
        (the "Software"): the files `cli.py`, `geometry_linter.py`, `repair_engine.py`,
        `qa_profiles.py`, `usd_loader.py`, and `env_boot.py`, and any compiled or
        packaged form of them (including the PyPI wheel/sdist).
        
        1. GRANT OF USE
           Subject to the terms below, the copyright holder grants any person who
           obtains the Software a worldwide, royalty-free, non-exclusive,
           non-transferable license to RUN and USE the Software, unmodified, for any
           purpose, including commercial purposes, without requiring an account,
           registration, license key, or network connection.
        
        2. RESTRICTIONS
           Except as expressly permitted in Section 1, no permission is granted to:
             a. redistribute the Software, in whole or in part, verbatim or modified,
                in source or compiled form, to any third party;
             b. modify, adapt, translate, or create derivative works based on the
                Software;
             c. sublicense, rent, lease, or otherwise transfer any rights in the
                Software to a third party;
             d. remove or alter any copyright, trademark, or other proprietary notice
                contained in the Software.
           These restrictions apply regardless of whether the Software is obtained
           directly from the copyright holder or from a package index, mirror, or
           any other distribution channel.
        
        3. OWNERSHIP
           The Software is licensed, not sold. The copyright holder retains all
           right, title, and interest in and to the Software, including all
           intellectual property rights therein.
        
        4. NO WARRANTY
           THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
           IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
           FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
           THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY,
           WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF,
           OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
           SOFTWARE.
        
        5. TERMINATION
           This license terminates automatically if you breach any of its terms.
           Upon termination you must cease all use of the Software and destroy all
           copies in your possession.
        
        6. THIRD-PARTY DEPENDENCIES
           The Software depends on third-party libraries (e.g. numpy, trimesh, scipy,
           fast-simplification, xatlas) distributed under their own permissive
           licenses (BSD/MIT/Apache-2.0). This license does not apply to those
           dependencies; see each dependency's own license terms.
        
Project-URL: Homepage, https://github.com/alza123123/3dqa-benchmark
Keywords: 3d,gltf,glb,mesh,qa,validation,repair,pipeline,trimesh
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Classifier: Environment :: Console
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: trimesh>=4.0
Provides-Extra: fast
Requires-Dist: scipy>=1.10; extra == "fast"
Provides-Extra: repair
Requires-Dist: fast-simplification>=0.1.7; extra == "repair"
Requires-Dist: xatlas>=0.0.9; extra == "repair"
Requires-Dist: networkx>=3.0; extra == "repair"
Provides-Extra: usd
Requires-Dist: usd-core>=23.0; extra == "usd"
Provides-Extra: all
Requires-Dist: scipy>=1.10; extra == "all"
Requires-Dist: fast-simplification>=0.1.7; extra == "all"
Requires-Dist: xatlas>=0.0.9; extra == "all"
Requires-Dist: networkx>=3.0; extra == "all"
Requires-Dist: usd-core>=23.0; extra == "all"
Dynamic: license-file

# 3dqa — free local CLI

Validate and auto-heal 3D assets from the command line. Same deterministic,
stateless core as the dashboard and API — but it runs **entirely on your machine**:
$0, offline, no account, no upload, no API key.

Supports `.glb` `.gltf` `.obj` `.ply` `.stl`.

## Install

```bash
pip install 3dqa               # core (linter + repair, numpy + trimesh)
pip install "3dqa[all]"        # + scipy fast path, decimation, UV unwrap/bake
```

Prefer a single file? The `3dqa.pyz` bundle packs the whole engine into one
executable zipapp — `python 3dqa.pyz lint model.glb` (needs `numpy` + `trimesh`
in the environment; add `scipy`/`xatlas`/`fast-simplification` for the fast path
and full heal).

## Use

```bash
# Audit one asset. Exit code is a CI gate: 0 = PASS, 1 = FAIL, 2 = error.
3dqa lint model.glb --pretty

# Audit a whole export folder (recursed), one line per asset.
3dqa lint ./exports --quiet

# Gate against target engines from a single scan.
3dqa lint ./exports --targets unreal_5,unity_mobile,three_js_web
3dqa lint ./exports --config 3dqa.config.json

# Non-destructively auto-heal — writes <name>_repaired.glb, never touches input.
3dqa heal model.glb
3dqa heal ./exports --out-dir ./healed --targets unity_mobile

# See exactly what WOULD be repaired, writing nothing.
3dqa heal ./exports --dry-run --pretty

# The closed loop: heal, RE-RENDER the healed artifact, RE-RUN the vision pass
# on it, and emit ONE certificate proving it is geometrically AND visually clean.
3dqa verify model.glb --pretty
3dqa verify ./exports --targets unity_mobile --out-dir ./healed --quiet

# Same loop, keyless and free — the mock visual backend proves the wiring at $0.
3dqa verify model.glb --vision mock --dry-run --pretty

# Compact integration schema for a pipeline hook to branch on.
3dqa verify model.glb --compact

# Half the model spend: skip the pre-heal pass when you only need the
# after-verdict and not the before/after attribution.
3dqa verify ./exports --no-baseline
```

## What you get

`lint` emits a JSON **Quality Certificate** — a machine-readable pass/fail verdict
with a finding per check (poly budget, non-manifold edges, watertightness,
normals, UVs, floating debris, appearance) plus optional per-target compatibility.

`heal` runs the repair loop *lint → fix → re-lint* and emits a before/after report
with `fixed` / `unfixable` / `introduced` lists and a healing `efficacy`. A fix is
only reported as fixed after an independent re-lint of the exported `.glb`
confirms it. Nothing that can’t be safely repaired is hidden.

`verify` closes the loop. It heals, re-renders the **healed** artifact headless,
re-runs the vision pass on that render, and returns ONE certificate:

```
verdict        PASS | FAIL | UNVERIFIED
claims         geometrically_clean · visually_clean · target_compatible · closed_loop
attestation    one sentence stating exactly what was proven
visual.delta   resolved / persisted / introduced defect classes, before vs after
```

It is honest about the case that matters: if healing fixes the math but
**introduces** a visual defect — decimation smearing a texture, an unwrap
opening a seam — `visual.delta.introduced` names it and the verdict is FAIL even
though the geometry certificate passes. And if the visual pass could not
actually run (no headless GL, `--vision none`), the verdict is `UNVERIFIED`, never
a silent PASS: a certificate only claims "visually clean" when a render was
really audited.

### Rendering needs nothing installed

The visual pass renders through three tiers and stops at the first that produces
frames: **pyrender** (offscreen GL), **trimesh** (pyglet), then a **pure-numpy
software rasterizer**. The last tier needs no GL, no display and no driver, so
`verify` works on a stock laptop or CI runner. The tier that ran is recorded in
`visual.render.backend` — a software render is a real render, but you always know
which one you got. It is roughly an order of magnitude slower than GL (measured:
7 views at 1024² in 0.76 s for 1.3k faces, 4.8 s for 82k); lower `--resolution`
if that matters.

`--compact` emits the integration schema instead of the full certificate:

```json
{"asset_id": "...", "status": "PASSED",
 "repartition_delta": {"initial_defects": ["NORMALS_INVERTED"],
                       "repaired_defects": ["NORMALS_INVERTED"],
                       "residual_visual_delta": 0.0},
 "execution_time_ms": 91.4}
```

`residual_visual_delta` is the fraction of visual defect classes still present
after healing (0.0 = visually clean). It is `null` — never `0.00` — when the
visual pass could not run, because 0.00 there would assert a cleanliness nobody
measured.

### Cost

`verify` runs the vision backend **twice** — once on the arriving asset, once on
the healed one — because the before pass is what lets the certificate say a
defect was *introduced* by healing rather than merely present. Two levers:

| Setting | Model calls | Pixels sent |
|---|---:|---:|
| `--resolution 1024` + baseline | 2 | 14.7 MPx |
| default (512, baseline) | 2 | 3.7 MPx |
| `--no-baseline` at 512 | 1 | 1.8 MPx |

`--no-baseline` buys that saving with attribution, and says so: `delta.baseline`
becomes `"skipped"` and every comparative field (`resolved`, `persisted`,
`introduced`, `regression`) is **`null`, not `false`**. The healed asset is
still fully audited — you just can no longer tell whether a defect it shows was
caused by the heal.

## Guarantees

- **Non-destructive**: your input file is never modified.
- **Deterministic**: same input → same certificate and same repaired bytes.
- **Permissive-licensed**: MIT/BSD/Apache-2.0 dependencies only (CI-gated).
- **Stateless & offline**: no network, no telemetry, nothing leaves your box.

## Exit codes

| Code | Meaning |
|---:|---|
| 0 | every asset PASSes (and passes all targets) |
| 1 | at least one asset FAILs |
| 2 | a load/engine error |

For `verify`, an `UNVERIFIED` certificate gates like a FAIL (exit 1). Pass
`--allow-unverified` to accept a geometry-only pass on a box with no headless GL.
