Period: 2026-09-30 โ 2026-10-05 (checkpoint taken 05/10/2026 ~11:57 AEDT) Participants: Andrew.human & Claude.ai Follows: OVERSEER_Checkpoint_2026-09-30.md and OVERSEER_Transcript_2026-09-30.md
Times marked "Live" are Live's own clock (Singapore, SGT = UTC+8). Sydney moved to daylight saving (AEDT = UTC+11) on 4 Oct, so Live is now 3 hours behind Sydney.
COI_Chain 1.0.2 is installed on Live and its test suite passes 14/14 on Live. Its first real runs were checked line by line against SMF's own DB and disk: the search-file findings were all real, and they were faults in ISE's .json files, never in the forum. The SMF-side findings (orphan files, rows with no owner) are SMF's business and COI 1.0.3 will stop reporting them. Along the way a Python break on Live (ResultFormatter / zoneinfo) blinded both COI and PDF search for a morning; it is fixed. Dev's Python 3.8 was rebuilt with SSL and given a source-built 32-bit PyMuPDF, and a new 32-bit PDF indexer (v8.6.0) now works on Dev where the old one silently indexed nothing. Live's search files are currently behind the forum (see ยง6) and need indexer runs before the next mirror is a good copy.
| Version | What changed | Status |
|---|---|---|
| 1.0.1 | Absolute paths after the move to Collabware/OVERSEER |
superseded |
| 1.0.2 | Test suite only: one row per INSERT (CentOS 6 SQLite 3.6.20 has no multi-row VALUES); parked test files kept inside /tmp/coitest/parked; test prints its own and COI's version; whole bundle carries one number |
installed on Live, 14/14 on Live |
| 1.0.3 | Not built โ see ยง4 | planned |
--snapshot (Live only) froze 5054 attachments, 1680 posts, 345 members, 2 folders on 5 Oct.STALE-SNAPSHOT uses epoch seconds, so timezone and daylight-saving differences cannot affect it.Settings.php itself.COI_Chain_v1.0.2.zip.Andrew's coichecks (a script, not an alias) runs snapshot โ check โ compares counts with the previous report in /backup/coi_*.txt.
Open: coichecks sends the snapshot's output to /dev/null, so a failed snapshot silently falls back to the old picture. Add a guard:
python3 COI_Chain.py --snapshot > /dev/null || { echo "SNAPSHOT FAILED -- check not run"; return 1; }
Every COI claim was checked SMF-first, never against ISE's own files alone:
SELECT โฆ FROM smf209_attachments WHERE id_attach IN (โฆ)ls -l /var/www/html/attachments*/<id>_*SELECT โฆ FROM smf209_messages WHERE body LIKE '%attach=<id>%'.json file?Example โ 2419: no row, no file, no post โ SMF has no trace; only media_store.json still listed it โ ISE's file was wrong. Andrew removed the entry.
All 59 search-file claims from the first run (24 "in ISE but gone from the forum", 35 "on the forum but missing from ISE") were confirmed this way on 1 Oct. The 4 that later read as indexed were picked up by an ISEpdf run at 00:17 Live, after the report.
Lesson recorded: Claude must not present guesses about why a fault exists as findings, and must not claim what SMF's own tools check without reading their code (the claim that SMF's "Attachment Integrity Check" covers the same ground was wrong โ it reported "No errors were found!").
| # | Decision | Notes |
|---|---|---|
| D1 | SMF is gospel for its own territory. COI stops judging SMF's folders and rows (files with no row, rows with no owner, missing files, etc.) | SMF's own integrity check says "No errors were found!". These lines stay in 1.0.2 output until 1.0.3. |
| D2 | RC 8 = error; clean up before continuing (Andrew chose option A) | With D1 in place, the remaining RC is driven by ISE's files only. |
| D3 | The chain is a web, not a loop โ every pair of things that should agree gets its own test | Pairs listed in ยง5. |
| D4 | Add image checks: every image/video in media_store must have an embedding and a caption; leftovers for deleted attachments are faults; captions MediaProcessor gave up on (3 failures) are information only |
Treat embeddings/captions "like media/audio" โ a second layer built from media_store, checked both ways. |
| D5 | Prove COI by breaking Dev after copying its DB, attachments and ISE_Data; then restore/mirror back |
Dev owns no stores, so it is the safe machine to break. |
| D6 | Don't reinvent SMF's checks โ tie each .json entry back through its DB row, its post, and the physical file; extra fields may be added to the .json entries to make that possible |
Added fields are a fingerprint for comparing, never a second source of truth. |
| D7 | Delivery rules made standing in preferences (version/date bump, manual history entry, version printed at start, dotted never-reused zip names, xmllint, unasked changes listed before making them, release card) |
Saved 30 Sep; extended 4 Oct to "every executable". |
embeddings_store.json / captions_store.json.Drop: every SMF-territory check (D1).
Pairs to test (D3):
| Pair | Must agree on |
|---|---|
| attachment row โ post | post exists (id_msg โ messages) |
| attachment row โ member | member exists (avatars) |
| attachment row โ file | file in the folder id_folder names, at the row's size |
| attachment row โ each store | entry exists iff it should |
| post โ store entry | entry's recorded post matches (needs added field) |
| file โ store entry | entry's recorded hash/size match (needs added fields) |
media_store โ audio_store |
every audio entry is an mp3/wav also in media_store |
pdf_store โ file |
file really is a PDF by content |
media_store โ embeddings โ captions |
D4 |
Also in 1.0.3:
Settings.php (no PDFsearch import).โฆ_thumb): currently expected in media_store; if MediaIndexer skips them on purpose, COI's rule changes.embeddings_store.json may be large โ check its size before deciding how COI reads it: ls -lh /var/www/html/ISE_Data/embeddings_store.json /var/www/html/ISE_Data/captions_store.json.Still needed from Andrew before building: one entry per store (read-only command was given), plus the embeddings/captions sizes.
| ISE file | Missing (on forum, not in file) | Stale (in file, gone from forum) | Cause |
|---|---|---|---|
media_store |
50 (7042โ7125), incl. 6 thumbnails | 1 (2963) | MediaIndexer not run since; plain run (no args) rebuilds from SMF and drops 2963 |
audio_store |
5 (6941, 6954, 7105, 7107, 7118) | โ | Clone's job, then json_push_audio_Clone_to_Live |
pdf_store |
18: 7 stuck (below) + 7132, 7134 + 7123โ7144 | 4 (6970, 7033, 7041, 7049) | pdf_store.json dated 4 Oct 18:18 Live โ older than the 03:25 indexing โ a restore put back an older copy. 7144 confirmed a real PDF (file: PDF document 1.4), so a normal/--fastest run will pick these up |
misc_store |
1 (5461 Groq.json) | โ | stuck (below) |
| SMF side | 47 rows with no post/member | โ | SMF's territory (D1) |
Stuck โ skipped by every run, full or not (needs the --single trace):
Ways to clear the stale entries (Andrew's choice):
media_store: plain python3 MediaIndexer.py.pdf_store: --fresh (takes hours) or the targeted drop one-liner (removes the IDs from both pdf_store.json and word_index_pdf.json, temp-file-and-swap, then chown apache:apache). Tested on dummy copies.media_store. Every future deletion leaves a stale entry until a full rebuild. (Possible future change: make the normal run drop entries for deleted attachments โ Andrew's call.)MegaIndexer.sh does not call MediaIndexer, and no indexer is in Live's crontab โ new media is never indexed unless run by hand.file --brief process per attachment (~5,000) โ minutes per run; --fastest skips already-indexed ones.apache; files they write must stay apache:apache (run with sudo -u apache โฆ or chown afterwards).Symptom: --snapshot failed (No module named 'backports', then 'zoneinfo'), so every check compared against an old snapshot โ giving false lines (86 "files with no row", stale entries for anything uploaded after 30 Sep). PDF search itself could not load either.
Cause:
ResultFormatter.py was replaced at 06:26 Live (version 7.4.4, but @date still 2026-09-14 โ the header did not show the change). It imported zoneinfo, which exists only from Python 3.9.python3 is 3.6.3, while pip3 installs into 3.8 โ two different Pythons./backup/var/www/html/ISE_Data also put back the 30 Sep chain_snapshot.json and the 4 Oct pdf_store.json.Fix applied on Live:
python3.6 -m pip install backports.zoneinfotry:
from zoneinfo import ZoneInfo
except ImportError:
from backports.zoneinfo import ZoneInfo
(backup: ResultFormatter.py.bak)
--snapshot โ RC 0.Open: the same change must go into Andrew's master with a version/date bump, or the next deploy undoes it. Note: 7.4.3 in the v9.9 zip also imports zoneinfo unconditionally โ rolling back to it would not help.
python3 โ 3.6.3; pip3 โ 3.8. Both have PyMuPDF 1.19.2, pypdf 3.1.0, backports.zoneinfo; ISE and COI load on 3.8.ocrmypdf) keep their own Python in their first line, so they keep working after a switch.ln -sf python3.8 /usr/local/bin/python3
ln -sf pip3.8 /usr/local/bin/pip3
Never touch /usr/bin/python (CentOS 6's Python 2.6 โ yum depends on it).
python3='python3.8', pip3='pip3.8', py36, py38โฆ) only apply to typed commands โ cron lines and scripts don't see them (Live's crontab runs python3 โฆ/query_log_reader.py and read_searches_log.py).backports.zoneinfo installed into both 3.6 and 3.8; package lists now match Live's exactly (only the torch build string differs โ Clone's own build).python3 is 3.8 (Andrew migrated it earlier)./usr/local/openssl11 (system OpenSSL untouched); Python configured --with-openssl=/usr/local/openssl11 with -rpath; cert.pem linked to /etc/pki/tls/certs/ca-bundle.crt; installed with make altinstall. Backup of the old binary: /usr/local/bin/python3.8.nossl. Keep /usr/local/openssl11 โ the new Python depends on it. /tmp/devsrc and /tmp/pm can be deleted./usr/local/lib/libmupdf.a, headers in /usr/local/include/mupdf). No ready-made 32-bit build exists for 3.8 at any version; PyMuPDF 1.11.2 would not build (headers are 1.14.0).find /root/.cache/pip/wheels -name "PyMuPDF-1.14.21-*.whl" -exec cp {} /backup/ 0getText() only โ no get_text().| Zip | Contents | Notes |
|---|---|---|
COI_Chain_v1.0.2.zip |
COI_Chain.py, test, manual, .htaccess | installed on Live |
ISE_Indexers_v9.9.1.zip |
--single ID_ATTACH added to PDFIndexer 8.6.0, MiscIndexer 7.5.0, MediaIndexer ISE v9.9.1 (code added only) |
installed on Live. PDFIndexer's --single still pays the full-disk file sweep (minutes) โ proposed fix 8.6.1, not built |
PDF-32bit-Indexer_v8.6.0.zip |
superseded โ its manual was an older copy | don't use the manual from it |
PDF-32bit-Indexer_v8.6.0.1.zip |
PDF-32bit-Indexer.py v8.6.0 + Andrew's latest manual with one entry added | see below |
get_text() / getText(); banner PDF-32bit-Indexer.py v8.6.0; child output read from its last line.get_text() call doesn't exist in Dev's fitz).attachments + attachments2; the old one scanned only attachments (763).--dry-run it writes Dev's own pdf_store / word_index_pdf (Dev is meant to write nothing).python3.8 โฆ), not an alias.apache:apache, and the folder had lost its execute bit (drw-r--r--).find โฆ -prune โฆ and /bin/clrcache both skip OVERSEER (verified โ prints 0); attachme only chowns the file it copies; chownhtml is an alias of the same pruned find. Likely the prune was added after 30 Sep.chown -R root:root โฆ/OVERSEER ran 17:26 Live on 4 Oct. Confirm ls -la shows root root and drwxr-xr-x on . (run chmod 755 on the folder if not). fixdir holds the fix commands.Collabware itself is drwxrwxrwx (world-writable) โ anyone on the box could rename/replace OVERSEER. Worth tightening.Collabware/ (the md5 baseline would flag them); /backup is the place./backup/ISE_Data_20260929-222747.tar.gz is 47 MB vs ~102 MB for the rest โ test with gzip -t before ever restoring from it.--fastest is quick), plain MediaIndexer, clear the 4 stale PDF entries.--single.python3/pip3 links to 3.8 (Clone the same, when ready)./backup.coichecks.--single without the full-disk sweep (if wanted).orphan_check) to temp-file-and-swap โ still open from 30 Sep.ls diff and daily cron (after 1.0.3, so RC 8 means something).Collabware permissions; confirm OVERSEER ownership held.OVERSEER Checkpoint 2026-10-05, ~11:57 AEDT