Skip to content

Revalidate and harden configurable AI models folder - #153

Draft
Blackspirits wants to merge 1 commit into
upl/review-base-dda1from
audit/ai-models-folder-dda1
Draft

Blackspirits wants to merge 1 commit into
upl/review-base-dda1from
audit/ai-models-folder-dda1

Conversation

@Blackspirits

@Blackspirits Blackspirits commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Purpose

Current-main revalidation of #113 ("Port and harden configurable AI models folder"), originally derived from upstream SubtitleEdit#14029.

Upstream SubtitleEdit#14029 was closed without merge. The earlier audit PR #113 remains useful historical evidence, but its base c77c4b428649ce7030e6cf218b4d7c384b955232 is now 154 upstream commits behind the current tree. This PR reconstructs the audited model-root contract on the current upstream main instead of pretending that the old port is still current.

Current upstream base: dda1fce8f9d4a605b1b6732acc072c7109dc6323.

Revalidation method

The #113 patch was replayed file-by-file against current main with an exact-context gate:

The resulting current-main diff is 68 files / +782 / -124.

Model-root contract preserved

The setting remains an optional root for downloaded/local AI model data, not a replacement for Subtitle Edit application data.

  • empty setting preserves historical paths;
  • relative hand-edited roots fail closed to the historical layout;
  • equivalent data-folder paths do not create a false custom root;
  • executables, logs, settings, dictionaries, themes and normal engine state stay in application data;
  • changing the setting does not automatically move or delete old models.

Speech-to-text

Covered current model owners include:

  • OpenAI Whisper cache;
  • CTranslate2 / Hugging Face cache;
  • WhisperX Hugging Face cache;
  • Whisper.cpp / Const-me / cuBLAS / Vulkan families;
  • Purfview Faster-Whisper-XXL models;
  • current CrispASR STT backends;
  • Qwen3 ASR C++.

CrispASR native auto-downloads

When a custom root is selected, every audited CrispASR launch receives:

  • CRISPASR_MODELS_DIR=<ModelsFolder>/CrispASR/models
  • CRISPASR_CACHE_DIR=<ModelsFolder>/CrispASR/models

This prevents native --auto-download from escaping to ~/.cache/crispasr.

Legacy mode does not overwrite caller-provided environment variables, and cache reuse follows CrispASR's own precedence.

Text-to-speech

Covered current locally-owned model families include:

  • CrispASR-backed TTS engines, including PocketTTS, dots.tts and Confucius4;
  • audio.cpp IndexTTS 2.5, FireRedTTS3, Fish Audio S2 Pro and Higgs Audio v3;
  • Qwen3 TTS C++;
  • Kokoro TTS C++;
  • OmniVoice TTS C++;
  • Piper voice model/config files.

Piper's runtime executable and PiperVoices.json catalog deliberately remain in application data. Only voice model/config files use the selected models root.

OCR / shared model consumers

  • PaddleOCR models;
  • CrispEmbed models;
  • Tesseract tessdata;
  • llama.cpp models.

Services whose models are owned by another service/server (Ollama, cloud APIs, etc.) remain out of scope.

New current-tree drift finding fixed

After #113's old base, Subtitle Edit added TtsVoiceInstaller.

The current per-voice Piper download path, after applying #113, correctly writes to:

<ModelsFolder>/TextToSpeech/Piper/models

but the newly added cancel/failure cleanup still deleted from Piper.GetSetPiperFolder(), i.e. the runtime folder.

With a custom models root that could leave partial .onnx / .onnx.json files behind on the selected external model disk after a canceled download.

This current revalidation fixes that by centralizing Piper voice cleanup paths on Piper.GetSetModelsFolder().

Regression coverage proves the cleanup paths resolve to the configured custom model root rather than the runtime folder.

Post-base owner audit

Model-related code added/changed since the #113 base was reviewed for new storage ownership:

  • current CrispASR / Whisper download services download runtimes or use caller-supplied destinations;
  • CrispEmbed model destination remains controlled by the audited engine path;
  • Apple Vision OCR uses the OS framework and owns no downloaded model set;
  • Ollama remains externally owned;
  • Voice Manager voice packs are WAV reference recordings + transcripts imported into each cloning engine's voice store, not AI weight/model caches, so they intentionally do not become part of the global ModelsFolder contract.

No additional current-tree local model owner was found outside this patch.

Regression coverage

The current tree retains focused coverage for:

  • legacy locations with empty setting;
  • relative-root fail-closed behavior;
  • custom root does not move application data;
  • Whisper / Hugging Face / WhisperX cache routing;
  • CrispASR model/cache environment and legacy precedence;
  • all current audio.cpp TTS model families;
  • Piper runtime/model separation;
  • current Piper canceled-download cleanup targeting the model root;
  • llama.cpp / OCR model routing.

No production model is downloaded by these tests.

Scope / branch state

Acceptance

  • full restore/build/test suite must pass on this exact HEAD;
  • no new warnings attributable to this tranche;
  • retry step must remain unused;
  • final adversarial review must re-check runtime/model separation, external cache environment handling and current-tree owner coverage;
  • upstream drift must be checked again before freeze.

AI assistance: ChatGPT was used to reconstruct #113 against current main, hunk-audit all upstream overlaps, audit new model-owning code, identify the post-#113 Piper cleanup drift, design its regression, and perform final coverage review.

Final CI

Authoritative run: SubtitleEdit#299 on efb737cf63d4c8af61cf6bae15e0dea2ef17d6a1

  • SeConv: 505 passed / 2 skipped / 0 failed
  • LibUiLogic: 918 passed / 0 skipped / 0 failed
  • LibSE: 2030 passed / 0 skipped / 0 failed
  • UI: 5422 passed / 10 skipped / 0 failed
  • build: 0 errors / 8 pre-existing warnings
  • retry step skipped
  • failure-artifact upload skipped

All 8 warnings are outside the #153 changed-file set.

Final drift gate

Upstream main was rechecked at dda1fce8f9d4a605b1b6732acc072c7109dc6323, exactly the base used by this current-main reconstruction. No post-base drift exists to invalidate the owner/model-path audit.

Final adversarial review was performed on this exact HEAD after CI; no blocker found.

@Blackspirits Blackspirits left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final adversarial review on efb737cf63d4c8af61cf6bae15e0dea2ef17d6a1 after CI SubtitleEdit#299: no blocker found. Rechecked ModelsFolder absolute/fail-closed semantics, legacy-layout preservation, CrispASR cache/model environment precedence, runtime-vs-model separation, Piper runtime/catalog vs voice-model ownership, canceled Piper download cleanup, and current-tree model-owner coverage. All eight build warnings are outside the changed-file set. Upstream main is still exactly the audited base dda1fce8.... No merge/promotion performed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant