import sqlite3,json,datetime
DB='/opt/struktur/youtube-research/knowledge.db'; now=datetime.datetime.now(datetime.timezone.utc).isoformat()
ids=[198,245,253,263]
c=sqlite3.connect(DB,timeout=30); c.row_factory=sqlite3.Row; c.execute('PRAGMA busy_timeout=30000'); c.execute('BEGIN IMMEDIATE')
rows=c.execute("SELECT e.job_id,e.video_id,e.youtube_id,e.status,v.transcript_status,length(trim(coalesce(v.transcript,''))) n FROM e2e_jobs e JOIN videos v ON v.id=e.video_id WHERE e.job_id IN (198,245,253,263) ORDER BY e.job_id").fetchall()
assert len(rows)==4 and all(r['status']=='supadata_retry' and r['transcript_status']=='retry' and r['n']==0 for r in rows)
for jid in ids:
st='access_restricted' if jid==263 else 'video_unavailable'
cur=c.execute("UPDATE videos SET transcript_status='unavailable',transcript_source=NULL,transcript_updated_at=? WHERE id=(SELECT video_id FROM e2e_jobs WHERE job_id=?) AND (transcript IS NULL OR trim(transcript)='')",(now,jid)); assert cur.rowcount==1
cur2=c.execute("UPDATE e2e_jobs SET status=?,step='terminal',completed_at=?,updated_at=?,lease_until=NULL,error_code=error_code,error_message=error_message WHERE job_id=? AND status='supadata_retry'",(st,now,now,jid)); assert cur2.rowcount==1
# All existing native-unavailable jobs become terminal at transcript layer only; e2e status remains unchanged.
cur3=c.execute("UPDATE videos SET transcript_status='unavailable',transcript_updated_at=? WHERE id IN (SELECT video_id FROM e2e_jobs WHERE status='supadata_native_unavailable') AND (transcript IS NULL OR trim(transcript)='') AND transcript_status='retry'",(now,)); native_changed=cur3.rowcount
c.commit(); c.close(); print(json.dumps({'special_jobs_updated':4,'native_unavailable_transcript_rows_updated':native_changed,'checked_at_utc':now}))