๐Ÿ“ Checkpoint_ISEmedia-Bridge-and-Ranking_2026-09-23.mdv4.4 · 2026-09-05

Checkpoint โ€” ISEmedia UI Search: Interpreter/Cache Triple-Bug, Ranking-Consistency Fix, Installer Repair โ€” 23/09/2026

Date: 2026-09-23 Milestone: ISEmedia's UI search bridge goes from "never worked when actually clicked" to a real, verified, end-to-end search path on Live โ€” and a real behavior bug in date-sort ranking gets caught and fixed the same night by the same real-user test that found it. Participants: Andrew (Architect & QA Lead, hands-on-keyboard on Live throughout), Claude (this session)

Files touched: qf_Mediasearch_bridge.php, MediaSearch.py, install_ise.php, plus a new ISE_Data/hf_cache runtime directory on Live (not a source file, a populated data artifact). Final versions: qf_Mediasearch_bridge.php 1.0.0 โ†’ 1.0.2 ยท MediaSearch.py 1.0.0 โ†’ 1.2.0 ยท install_ise.php (unversioned/9.4-era) โ†’ 9.5


1. Problem & Resolution

Problem: The very first real UI-triggered ISEmedia search (/sort newest brown) failed outright: ISE ERROR, then on investigation a raw traceback โ€” ModuleNotFoundError: No module named 'numpy'. This was the first time qf_Mediasearch_bridge.php โ†’ MediaSearch.py had ever actually been exercised through the real web UI; both files were built the same night as the 2026-09-20/21 ISEmedia checkpoint and had only been tested via CLI/mock data before.

Root cause โ€” three independent, stacked environment bugs, each one uncovered only after fixing the one before it:

  1. Wrong Python interpreter. qf_Mediasearch_bridge.php invoked MediaSearch.py via a bare $python = 'python3';, resolved via shell_exec()'s PATH โ€” a much thinner PATH under Apache than an interactive SSH shell's. Confirmed live: sudo -u apache python3.8 ... itself failed with command not found (sudo's own secure_path doesn't include /usr/local/bin either โ€” same bug class, different program). Real path: /usr/local/bin/python3.8. Fixed via resolve_media_python() โ€” checks two common absolute paths, then a command -v python3.8 shell probe, then falls back to the original bare python3 only as a last resort (so it can never fail worse than before).

  2. Torch importable only via a stray PYTHONPATH, not a real install. With the interpreter fixed, numpy and mysql.connector resolved correctly, but import torch still failed for apache. python3.8 -c "import torch; print(torch.__file__)" as root printed /root/pytorch/torch/__init__.py โ€” not a real source checkout (no setup.py, confirmed via ls -la; just the built torch/ package directory on its own), reachable only because root's shell has /root/pytorch on PYTHONPATH. Apache (a different user, locked out of /root entirely โ€” mode 700) could never see it. Fixed by copying the already-built package straight into python3.8's real system site-packages (cp -rf /root/pytorch/torch "$SITE_PACKAGES/") โ€” no rebuild needed, and it stops depending on any one user's shell environment or /root's permissions.

  3. open_clip's CLIP checkpoint cached per-user, and apache had no cache of its own. With torch fixed, the crash moved further in: open_clip.create_model_and_transforms() tries to download its model checkpoint from Hugging Face Hub on first use, caching under the invoking user's home (~/.cache/huggingface). Already cached under root's home from the 2026-09-01 Live CLIP migration โ€” but apache's home is /var/www, which it can't write to, so every UI search tried a live download and died with PermissionError: /var/www/.cache. Fixed by copying root's existing cache to a new shared location apache CAN read/write โ€” ISE_Data/hf_cache (chown -R apache:apache) โ€” and pointing the bridge at it via HF_HOME in the invocation. (One real slip caught and fixed along the way: running the cp twice before the destination existed created a nested hf_cache/hub/hub/ duplicate โ€” harmless functionally since HF only ever looks at hub/models--... directly, but cleaned up with rm -rf regardless.)

Verification: Confirmed at each layer with a real sudo -u apache ... python3.8 -c "import X" test before moving to the next layer โ€” not assumed fixed from reasoning alone. Final proof was the actual UI returning real, non-error results for /sort newest brown (1001 items, later re-tested at 180 after the limit fix).

Separately, same night โ€” real ranking-quality bug, caught by the first genuine user test: once results were flowing, /sort newest brown returned images with no relation to "brown" at all (e.g. a cat photo, clinic paperwork) ranked above genuine "brown" matches. Two layers:

Not yet done: Andrew has the v1.0.2/v1.2.0 files in hand but deployment-to-Live-and-retest of this latest keyword-gate change hadn't been confirmed as of this checkpoint. hf_cache itself is live and confirmed working on Live already (separate from the code files).


2. Risk Analysis

Bug class: All three interpreter/cache bugs are environment/deployment bugs, not logic bugs in the Python/PHP itself โ€” each one only ever manifests when code that was built and tested as root gets invoked as a different user (apache) for the first time. This is a real, recurring risk class for this project specifically, not a one-off: the exact same "confirmed working interpreter: python3.8" gotcha was already documented once before for MediaProcessor.py in the 2026-09-20/21 checkpoint, and this session found two more instances of the same underlying pattern (torch's PYTHONPATH dependency, HF cache's per-user default) that the earlier fix never covered because they hadn't been hit yet.

Residual risk โ€” real, open: ISE_Data/hf_cache is now a permanent runtime dependency with no automated setup path for a fresh environment. install_ise.php v9.5 adds a best-effort check-and-populate step (cached-copy path if run as root, backgrounded fresh-download path otherwise, loud logged instructions as the last resort) โ€” but this has not yet been tested against a real fresh install; it's new, unexercised code as of this checkpoint. If a future Dev/Clone install runs this and both automated paths fail silently in some way not yet anticipated, the failure mode reverts to exactly tonight's original bug, just on a different box.

Residual risk โ€” behavior trade-off, accepted knowingly: v1.2.0's keyword gate is a deliberate, explicit trade-off Andrew chose after being shown the alternative: MediaSearch.py no longer surfaces a genuinely visually-relevant image whose caption never uses the literal query word โ€” the original point of building CLIP semantic search in the first place. This was flagged plainly before implementing, not discovered after the fact. Worth revisiting if this trade-off feels wrong in practice once used for real.

Blast radius if any of tonight's fixes are wrong: Confined entirely to ISEmedia's UI search path (qf_Mediasearch_bridge.php/MediaSearch.py) and the one MediaIndexer.py line in install_ise.php. IndexBuilder.py/PDFIndexer.py/MiscIndexer.py were deliberately left untouched in the installer specifically to avoid this session's fixes risking three already-working jobs.

Scope check โ€” deliberately NOT done tonight: A cross-source consistency audit of search.py/PDFsearch.py/MiscSearch.py/MegaSearch.py/RankingEngine.py/SortEngine.py against tonight's Media findings was requested but deferred โ€” Claude does not have those files' actual source in this session, only changelog/checkpoint descriptions of them, which Andrew's own changelog already flags as unreliable ("per-file version stamps currently inconsistent"). Real audit pending a source upload (Andrew indicated a full ZIP mod bundle is coming).


3. Code Change (summary โ€” see delivered files for full diffs/docblocks)

qf_Mediasearch_bridge.php โ€” 1.0.0 โ†’ 1.0.2

MediaSearch.py โ€” 1.0.0 โ†’ 1.2.0

install_ise.php โ€” โ†’ v9.5

New reference artifact (not source code)

hf_cache_SKELETON.zip โ€” an empty placeholder directory tree matching Hugging Face's real cache layout (blobs/refs/snapshots/.locks), for documentation purposes only; explicitly not meant to be bundled into the distributable mod package (600MB of binary weights, not code).