Give the phone the model it had no way to obtain
Face indexing was compiled into the APK all along — dr-ui takes dr-face with `inference` on every target, so SCRFD, alignment, MBF, calibration and clustering were all in there. What was missing was the weights, and on Android there was no way to supply them. Route C (docs/faces.md §2.2) says the user obtains the model and the app loads it. On a desktop that is a real gesture: drop two files in ~/.local/share/darkroom/models/ and indexing starts working. On Android it is not a gesture at all. `internal_data_path` is app-private, `run-as` needs a debuggable build, and the in-app fetch route C specifies was never built — so the settings page reported "no face model is installed" on every launch with nothing behind the message. Not "off until you supply weights"; off. So the shape-fixed pair goes into LFS under the APK's assets, assemble-apk.sh copies it into the package, and `android_main` unpacks it to the shared models directory before anything asks whether a model is present. Three things that are not incidental: The models directory is now shared across accounts rather than per-account. Weights are identified by `faces.model_id`, not by who is signed in, so two accounts had no reason to hold two copies — and the unpack runs before any session exists to key a per-account path off. `face_models` still prefers a per-account directory when one is populated, so anyone mid-migration keeps the ability to pin one library to its own pair. The unpack writes under a temporary name and renames. `face_models` decides availability on `is_file()` alone, so a copy truncated by the process being killed would leave a file that passes that test and fails inside tract — reported to the user as a broken model rather than a missing one. assemble-apk.sh refuses an LFS pointer. At ~130 bytes it looks exactly like a model to `cp`, and unchecked it reaches the device and fails in the graph loader instead of telling someone to run `git lfs pull` — the same guard dr-segment's build script applies to yolo26n-seg.onnx. The licensing half is unchanged and recorded in §2.2a: the InsightFace grant is research-only, this is a private repository and a self-installed build, and these files come back out before anything is published. The weights are still not a cargo build input — dr-face has no `models/` directory and no `embedded-model` feature, and nothing in the build reads them. The APK assembly step copies two files and is the only thing in the tree that knows they exist. Verified on device: both models unpack on first launch (2524817 and 13616095 bytes) and the APK carries them at assets/models/. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+35
-2
@@ -113,8 +113,9 @@ own release page, which is where the grant attaches:
|
||||
DarkRoom is GPL-3.0-or-later. A non-commercial field-of-use restriction is not a GPL-compatible
|
||||
grant, so:
|
||||
|
||||
- these weights **cannot be committed to this repository**, the way `yolo26n-seg.onnx` is (D14);
|
||||
- they cannot ship inside an APK, a Flatpak, or an F-Droid build;
|
||||
- these weights are **not redistributable under this project's licence**, so they cannot go into a
|
||||
*published* build — an APK, a Flatpak, or an F-Droid entry — and could not go into a repository
|
||||
intended to be one (§2.2a records what was actually decided here, and why the two differ);
|
||||
- and the restriction binds the *user*, not only the project — a professional photographer using
|
||||
DarkRoom commercially is outside the grant even if they fetched the file themselves.
|
||||
|
||||
@@ -158,6 +159,38 @@ swapping in a permissive model later is a new `model_id` and a re-index, not a m
|
||||
- **Indexing stays off until a model is present and verified**, and disabling it deletes nothing —
|
||||
that is a separate control (NFR-SEC-5, §11).
|
||||
|
||||
### 2.2a Android, which route C forgot
|
||||
|
||||
Route C says "the user obtains the model and the app loads it". On a desktop that is a real gesture:
|
||||
the files go in `~/.local/share/darkroom/models/` and face indexing starts working. **On Android that
|
||||
gesture does not exist.** `internal_data_path` is app-private, `adb shell run-as` needs a debuggable
|
||||
build, there is no picker and no fetch in the app, and so a phone could not acquire a model by any
|
||||
means at all. Face indexing was not "off until the user supplies weights" there; it was off, full
|
||||
stop, and the settings page said so on every launch with no action available behind the message.
|
||||
|
||||
**Decision, 2026-08-27: the shape-fixed pair is committed to LFS at
|
||||
`apps/darkroom-android/android/assets/models/`, and `assemble-apk.sh` bundles it into the APK.**
|
||||
`android_main` unpacks it to the shared models directory on first launch, before anything asks
|
||||
whether a model is present. This is a personal project on a private Gitea; the grant restricts
|
||||
redistribution, and a private repository and a self-installed APK are not that.
|
||||
|
||||
What that does and does not settle:
|
||||
|
||||
- **It does not make §2.1's route A available.** The moment this project publishes — an F-Droid
|
||||
entry, a release APK, a Flatpak — these files come back out and route C's unbuilt half (the fetch,
|
||||
the licence screen, the pinned checksum) has to exist first. §2.1's table stands as the answer for
|
||||
a *published* build; this is the answer for the author's own phone.
|
||||
- **It does not make the weights a build input.** `dr-face` still has no `models/` directory and no
|
||||
`embedded-model` feature, and nothing in the cargo build reads these files — §2.2's first bullet
|
||||
guards against a flag someone flips in a packaging script, and that remains guarded. The APK
|
||||
assembly step copies two files; it is the only thing in the tree that knows they exist.
|
||||
- **It does not bind only the project.** §2's last bullet is unchanged and is the one with teeth: the
|
||||
research-only grant restricts the *user*, so commercial photography with a DarkRoom that has these
|
||||
weights in it is outside the grant no matter who put them there.
|
||||
|
||||
The in-app fetch, the licence screen, and the pinned checksum that §2.2 specifies are still unbuilt,
|
||||
on every platform. When they are built, this becomes redundant and the assets directory empties.
|
||||
|
||||
### 2.3 Before S14 writes any code
|
||||
|
||||
Three questions to answer by reading, in this order, and to record with the date they were checked —
|
||||
|
||||
Reference in New Issue
Block a user