Files
MoFin/scripts/inspect_third_db.py
T
hmo 4f83ee8a01 feat(hygiene): anti-redundancy enforcement — spec rules + weekly audit
Root cause analysis of the 2026-07-20 redundancy incident:
1. No single-source-of-truth rule -> same file legitimately lived in 4+
   locations, diverging silently
2. Relative path resolution (Path(__file__).parent/'data') -> each
   hardlinked copy of mofin_db.py pointed to a DIFFERENT database
3. 'Backup habit' left .bak/legacy files in production dirs, which
   monitoring then scanned and reported as false alarms
4. Half-done migrations: DB tables created but old JSON writers/readers
   stayed (price_events), old files stayed
5. Dead modules never got buried: xiaoguo 'dead' but bot ran 8 days
   as root eating 2.5GB
6. Monitoring checked 'does it exist' not 'is it alive' -> stale file
   mtime reported as 'pipeline stalled 14 days' (false alarm)
7. No 'system hygiene' as a check category at all

Prevention implemented:
- dev-spec.md v2.0: 五条红线 -> 十条红线
  #6 single source of truth (hardlink only, no independent copies)
  #7 absolute data paths only (no __file__-relative data resolution)
  #8 no backups/legacy in production data dirs (archive immediately)
  #9 dead module burial checklist (6 mandatory steps)
  #10 monitor liveness (DB table freshness) not existence
- File Location Constitution: canonical location per content type
- NEW system_hygiene_audit.py: weekly Monday 07:30 cron checking
  diverged copies / broken hardlinks / zombie processes / orphan data
  files / dead cron scripts / DB freshness -> hygiene_report.json + XMPP
- specs/hygiene.json: module spec per red line #1
- Verified: audit found 5 real issues on first run, all fixed, re-run clean
2026-07-20 19:04:05 +08:00

33 lines
1.2 KiB
Python

import sqlite3
from datetime import datetime
THIRD = '/home/hmo/.hermes/profiles/position-analyst/scripts/data/mofin.db'
MAIN = '/home/hmo/MoFin/data/mofin.db'
t = sqlite3.connect(THIRD, timeout=10)
m = sqlite3.connect(MAIN, timeout=30)
m.execute('PRAGMA busy_timeout=30000')
for table in ['sector_snapshots', 'market_snapshots', 'todos', 'capital_flow_cache']:
try:
tcols = [r[1] for r in t.execute(f"PRAGMA table_info({table})")]
mcols = [r[1] for r in m.execute(f"PRAGMA table_info({table})")]
print(f'{table}: third_cols={tcols}')
print(f' main_cols={mcols}')
tcnt = t.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
mcnt = m.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
print(f' third={tcnt} rows, main={mcnt} rows')
except Exception as e:
print(f'{table}: ERR {e}')
print()
# sector_snapshots schema in both
print('sector_snapshots sample (third):')
for r in t.execute("SELECT * FROM sector_snapshots ORDER BY rowid DESC LIMIT 2"):
print(' ', str(r)[:200])
print('sector_snapshots sample (main):')
for r in m.execute("SELECT * FROM sector_snapshots ORDER BY rowid DESC LIMIT 2"):
print(' ', str(r)[:200])
t.close()
m.close()