Keep current upstream UI behavior and the later detector contract checks. Validate candidate models before replacing working weights and records, with a synthetic regression that failed before the fix. Remove the unrelated GPU equivalence-test relaxation. All seven quality gates pass with the pinned hosted fonts.
Generated with Codex.
Photo > Detect Faces runs the YuNet detector (a small pure-Rust interpreter over the ONNX graph, no
runtime dependency) and adds the faces it finds as unnamed face regions in one undo step. The detector
and the recognition models are opt-in downloads: Settings > Faces shows each model's licence and
training-data note, Download stays disabled until the terms are accepted, and the file is fetched over
https with lightcraft-fetch from the model's own repository at a commit-pinned address, checked against
its recorded size and SHA-256 and then installed. Detect Faces offers the detector's download the first
time it is used. No model file is part of the repository (the real-model tests read LC_YUNET_MODEL; two
ignored tests download from the real hosts).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The model list marked the YuNet detector as bundled with LightCraft and installed, but no model ships
inside LightCraft (the weights are opt-in downloads or files the user adds). Drop the notion: a
model is installed when its folder is, it can be removed like any other, and the licence notice no
longer says it is bundled.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
`faces.models.list / inspect / install / remove / select` and `faces.enable`, all
reachable from the UI, CLI, control channel and MCP. Models live in a folder the
host provides (`Session::face_models_dir`): one subfolder each with the model, its
manifest and a record of what the user accepted, plus settings.json.
- install needs `acknowledged: true` (the user has been shown the licence), copies
the file under a .part name, checks the copy's SHA-256 against the original, then
renames; a failure leaves nothing behind.
- ids are validated before they become folder names (and a manifest that disagrees
with its folder is ignored); remove only ever deletes a folder that has a model
manifest. A manifest id can no longer be `.`, `..` or start with a dot.
- inspect describes any .onnx without writing anything; unusable files are an
answer ("unsupported" with the reason), not a crash.
- the list says plainly that running a model is not built in yet.
`faces::synthetic` makes a minimal valid ONNX for tests (and the later self-check).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>