Stage D trial 5 reference model and fresh sample 5
pauljd/davidson-ci: Davidson CI / quality (push) Failing after 2m21s
pauljd/davidson-ci: Davidson CI / ai-review (push) Failing after 1m39s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-11-04 23:50:22 +00:00
co-authored by Claude Opus 5.5
parent 4ea4e19a95
commit 48a50daf21
3 changed files with 6899 additions and 0 deletions
@@ -0,0 +1 @@
{"7992616":[],"8055740":["Vortex",""],"8017129":["Dark Files"],"7994839":[],"7810527":["","Orbit Romance"],"8001330":[],"8005695":[],"8054732":["Orbit Action","Orbit Premiere"],"8068393":[],"8014272":[],"8062422":[],"8015848":[],"8002168":["","After Dark","Orbit Horror"],"7994621":[],"8020569":[],"7994727":[],"8063747":["","Detour"],"8006397":["","Vortex"],"8055413":["Ring X"],"8057405":[],"7996086":["Orbit Romance"],"8020476":["","Orbit 1"],"8068548":[],"7989454":[],"8065773":["","Orbit Romance"],"8000853":[],"8016802":["After Dark","Orbit Horror"],"8018860":[],"8055247":[],"7990898":["Orbit Action"],"8003286":[],"8036571":[],"8006051":["Ring X"],"8014593":[],"7996098":["","Orbit 2"],"8007859":["","Dark Files"],"8058146":[],"8001871":[],"8008064":[],"8067816":[],"8068818":[],"8000824":[],"8068195":["","Evidence"],"7990789":[],"7991287":[],"8067869":[],"8060483":["Dark Files",""],"8003369":["","Orbit 2"],"8014831":[],"8058811":[],"8065674":["","After Dark","Orbit Horror","Orbit Sci-Fi"],"8067819":[],"8069941":[],"8058439":[],"8019411":["Orbit Romance"],"7993206":["Evidence"],"8014542":["","Orbit Action"],"8000114":["Ring X"],"8059745":["Dark Files"],"8064062":[]}
File diff suppressed because it is too large Load Diff
+162
View File
@@ -0,0 +1,162 @@
import json,re,math,collections,sys,glob,sqlite3
S,R=sys.argv[1],sys.argv[2]
ev={}
for l in open(f'{S}/evidence-0.jsonl'):
r=json.loads(l); ev[r['id']]=r
c=sqlite3.connect(f'file:{S}/cat-now/catalogue.db?mode=ro',uri=True)
UK=re.compile(r'United Kingdom|England|Scotland|Wales|\bUK\b')
UKSTUDIO=re.compile(r'\bBBC\b|\bITV\b|Channel 4|Film4|Sky\b|Working Title|Ealing|Hammer|Aardman',re.I)
def W(*words): return re.compile(r'\b('+'|'.join(words)+r')',re.I)
# Each channel's brief from docs/channels and Paul's 4 November definitions: what it carries, themes for and against, era, ratings, origin.
B={
'101':dict(name='Orbit 1',kind={'Series'},genres_any={'Comedy'},themes=W('sitcom','family','household','neighbou?r','roommate','parents','dad','mum','mom','sisters','brothers','college','workplace'),against=W('murder','killer','documentary','wedding of','engagement'),era=(1970,2026),kids=False,need_theme=True),
'102':dict(name='Orbit 2',kind={'Series'},genres_any={'Game Show','Reality','Comedy','Talk'},themes=W('quiz','game show','contestants','panel','challenge','teams compete'),against=W('murder','documentary'),era=(1960,2015),kids=False,uk=True),
'103':dict(name='Orbit Three',kind={'Series'},genres_any={'Comedy'},themes=W('sketch','cult comedy','surreal','dark comedy','scottish'),against=W('documentary'),era=(1990,2026),kids=False,uk=True),
'104':dict(name='Orbit Gold',kind={'Series'},genres_any={'Comedy'},themes=W('sitcom','classic comedy'),against=W('documentary'),era=(1960,1999),kids=False,uk=True),
'105':dict(name='Riot',kind={'Series'},genres_any={'Animation','Comedy'},need_any={'Animation'},themes=W('adult','irreverent','raunchy','satir','dysfunctional'),against=W('preschool','children learn'),era=(1988,2026),kids=False),
'106':dict(name='Paradox',kind={'Series'},genres_any={'Science Fiction','Fantasy','Mystery','Horror'},themes=W('supernatural','paranormal','alien','time travel','parallel','ghost','vampire','demon','monster','mysterious','strange','unexplained','dimension','future','space','dystopia','cult','prophecy','witch'),against=W('documentary','reality','romance','cooking'),era=(1955,2026),kids=False),
'107':dict(name='Evidence',kind={'Series'},genres_any={'Crime','Mystery'},themes=W('detective','inspector','police','forensic','pathologist','homicide','murder','sergeant','DCI','sleuth','constable','cop','FBI','NCIS','agent','crime scene'),against=W('documentary','true story of','real-life','archive footage','interviews','lawyer','law firm','solicitor','attorney','barrister','courtroom','divorce','legal'),need_theme=True,era=(1965,2026),kids=False,scripted=True),
'201':dict(name='Terra',kind={'Series'},genres_any={'Documentary'},themes=W('wildlife','animal','ocean','sea','reef','planet','nature','ecosystem','species','forest','jungle','predator','habitat','natural world','migration'),against=W('murder','killer','crime','war','music','celebrity','royal','politic','AI','robot','superhero'),era=(1975,2026),kids=False,need_theme=True),
'202':dict(name='Odyssey',kind={'Series'},genres_any={'Documentary','History'},themes=W('space','universe','astronom','science','engineer','scientist','history of','historian','ancient','archaeolog','exploration','explorer','technolog','invention','journey across','civilisation','civilization','planet earth'),against=W('murder','killer','crime','celebrit','reality','athlete','boxer','comedian','sitcom','band','singer','fame','star of'),era=(1950,2026),kids=False,need_theme=True),
'203':dict(name='Orbit Wild',kind={'Series'},genres_any={'Reality','Documentary','Adventure'},themes=W('surviv','wilderness','expedition','endurance','remote','frontier','alone in','hunt','fishing','mountain','arctic','jungle','desert'),against=W('murder','dating','cooking','makeover','celebrit','villa','luxury','cash prize','contestants compete'),era=(1985,2026),kids=False,need_theme=True),
'204':dict(name='Dark Files',kind={'Series'},genres_any={'Documentary','Crime','Mystery'},need_any={'Documentary'},themes=W('murder','killer','disappear','missing','true crime','unsolved','investigat','case','paranormal','haunt','unexplained','cult','conspiracy','serial','detective','victim','trial'),against=W('wildlife','cooking'),era=(1975,2026),kids=False,need_theme=True),
'301':dict(name='Orbit Premiere',kind={'Movie'},genres_any={'Action','Adventure','Science Fiction','Fantasy'},themes=W('epic','hero','battle','world','mission','superhero','franchise'),against=W('documentary','concert'),era=(1975,2026),kids=False,current=True,need_theme=True),
'302':dict(name='Orbit Action',kind={'Movie'},genres_any={'Action'},themes=W('cop','agent','assassin','heist','fight','mercenar','revenge','martial','spy','chase','soldier'),against=W('documentary','concert','UFC','WWE'),era=(1960,2026),kids=False,current=True),
'303':dict(name='Orbit Sci-Fi',kind={'Movie'},genres_any={'Science Fiction'},need_any={'Science Fiction'},themes=W('alien','space','future','robot','planet','time','dystopia','android','galaxy'),against=W('documentary'),era=(1950,2026),kids=False,current=True),
'304':dict(name='Orbit Horror',kind={'Movie'},genres_any={'Horror'},need_any={'Horror'},themes=W('haunt','demon','possess','killer','evil','terror','ghost','curse','slasher','nightmare'),against=W('documentary'),era=(1960,2026),kids=False,current=True),
'305':dict(name='After Dark',kind={'Movie'},genres_any={'Horror','Thriller','Science Fiction'},themes=W('cult','bizarre','strange','exploitation','b-movie','grindhouse','creature','mutant','zombie','cannibal','obscure','surreal','underground'),against=W('documentary','romcom','family'),era=(1955,2018),kids=False,intl_bonus=True),
'306':dict(name='Orbit VHS',kind={'Movie'},genres_any={'Comedy','Adventure','Fantasy','Family','Science Fiction'},themes=W('kids','teen','adventure','summer','gang','treasure'),against=W('documentary'),era=(1980,1995),kids=False),
'307':dict(name='Orbit Romance',kind={'Movie'},genres_any={'Romance'},need_any={'Romance'},themes=W('love','romance','romantic','falls for','fall in love','wedding','sweetheart','kiss','date'),against=W('documentary','murder','horror','outlaw','gunfight','sheriff','war'),need_theme=True,era=(1930,2026),kids=False,current=True),
'308':dict(name='Detour',kind={'Movie'},genres_any={'Comedy'},need_any={'Comedy'},themes=W('road trip','party','college','bachelor','wild night','spring break','frat','hangover','vegas'),against=W('documentary','animated'),era=(1990,2026),kids=False,current=True,need_theme=True),
'309':dict(name='BritX',kind={'Movie'},genres_any={'Crime','Comedy','Drama','Thriller'},themes=W('gangster','gang','criminal','crime','heist','drug','hooligan','council estate','thug','con','robbery','dealer'),need_theme=True,against=W('documentary'),era=(1965,2026),kids=False,uk=True,current=True),
'401':dict(name='Ring X',kind={'Movie','Series'},genres_any={'Sport','Action','Documentary'},themes=W('wrestl','WWE','AEW','TNA','UFC','MMA','mixed martial','title match','pay-per-view','bout'),against=W('romance'),era=(1980,2026),kids=False,current=True,need_theme=True),
'601':dict(name='Vortex',kind={'Series','Movie'},genres_any={'Animation','Action','Anime'},need_any={'Animation','Anime'},themes=W('anime','fight','power','warrior','battle','hero','martial','saiyan','ninja','mecha','demon'),against=W('preschool','sitcom'),era=(1980,2026),kids=False,need_theme=True),
'602':dict(name='Heroes',kind={'Series'},genres_any={'Animation','Action'},need_any={'Animation'},themes=W('superhero','batman','spider','x-men','justice','villain','powers'),against=W('preschool'),era=(1980,2015),kids=True),
'603':dict(name='Orbit X',kind={'Series'},genres_any={'Animation','Action','Adventure'},need_any={'Animation','Children','Family'},themes=W('rangers','robot','team','evil','power','adventure','toy'),against=W('preschool','adult'),era=(1980,2002),kids=True),
'604':dict(name='Rewind',kind={'Series'},genres_any={'Animation','Comedy'},need_any={'Animation'},themes=W('cartoon','kids','adventures','friends'),against=W('adult','preschool'),era=(1990,2015),kids=True),
'605':dict(name='ToonZ',kind={'Series'},genres_any={'Animation','Comedy'},need_any={'Animation'},themes=W('cartoon','classic'),against=W('adult'),era=(1928,2005),kids=True),
'611':dict(name='Orbit Junior',kind={'Series'},genres_any={'Children','Family','Animation','Comedy'},need_any={'Children','Kids','Family'},themes=W('children','kids','school','friends','adventure'),against=W('adult','murder'),era=(1955,2026),kids=True,uk=True),
'612':dict(name='Wonder',kind={'Movie'},genres_any={'Animation','Family','Fantasy'},need_any={'Animation'},themes=W('princess','magic','fairy','kingdom','adventure','tale'),against=W('adult','horror','preschool','junior','Disney Jr','Spidey'),era=(1935,2026),kids=True),
'613':dict(name='PixelZ',kind={'Movie'},genres_any={'Animation','Family','Comedy'},need_any={'Animation'},themes=W('adventure','friends','family','toy','journey'),against=W('adult','horror'),era=(1995,2026),kids=True,current=True),
'614':dict(name='Tots',kind={'Series'},genres_any={'Children','Animation','Family'},need_any={'Children','Kids'},themes=W('preschool','little','learn','friends','gentle','toddler','young children'),against=W('adult','violence','fight','battle'),era=(1980,2026),kids=True),
}
KIDS_OK={'G','PG','TV-Y','TV-Y7','TV-G','TV-PG','U','TV-Y7-FV','E','0+','3+','6+','7+'}
ADULT={'R','TV-MA','NC-17','18','18+','X','NR18','SG-R21','SG-M18','GB-18'}
SYN={'Anime':'Animation','Martial Arts':'Action','Sci-Fi & Fantasy':'Science Fiction','Action & Adventure':'Action','Kids':'Children','Suspense':'Thriller','Sports':'Sport'}
def gen(r): return {SYN.get(g,g) for g in (r.get('genres') or [])}
# Channel text profiles: TF-IDF of their titles' descriptions, so a candidate is also compared with what the channel actually shows.
STOP=set('a an the and or of to in on for with his her their its is are was be by as at from this that he she they it into who when after one two new life series film show story world'.split())
def toks(t): return [w for w in re.findall(r"[a-z][a-z'-]{2,}",(t or '').lower()) if w not in STOP]
pools={}
for f in glob.glob(f'{R}/episodes-*.json'):
ch=f.split('-')[-1][:-5]
if ch in B: pools[ch]=[s['id'] for s in json.load(open(f))['series']]
docs={ch:[ev[i] for i in ids if i in ev and ev[i].get('overview')] for ch,ids in pools.items()}
df=collections.Counter(w for ch in docs for d in docs[ch] for w in set(toks(d['overview'])))
N=sum(len(v) for v in docs.values())
def vec(text):
tf=collections.Counter(toks(text)); return {w:(1+math.log(n))*math.log((N+1)/(df.get(w,0)+1)) for w,n in tf.items()}
def norm(v):
s=math.sqrt(sum(x*x for x in v.values())) or 1; return {k:x/s for k,x in v.items()}
cent={}
for ch,ds in docs.items():
acc=collections.Counter()
for d in ds:
for k,x in norm(vec(d['overview'])).items(): acc[k]+=x
cent[ch]=norm(dict(acc))
def cos(a,b): return sum(x*b.get(k,0) for k,x in a.items())
ENGLISH=re.compile(r'United States|United Kingdom|Canada|Australia|Ireland|New Zealand|England|Scotland|Wales')
def original(i):
row=c.execute('select original_title,title from items where id=?',(i,)).fetchone()
return row or ('','')
BOARD=re.compile(r'^(SG|BR|PL|KR|JP|DE|FR|IT|ES|NL|TR|IN|MX|CN|HK|TW|TH|PH|MY|ID|RU|SE|NO|DK|FI|AR|CL|CO|PT|CZ|HU|RO|GR|IL|EG|SA|AE|VN)-',re.I)
def foreign(r):
if BOARD.search(r.get('rating') or ''): return True,'rated by a non-English-language board ('+r['rating']+')'
o,t=original(r['id'])
nonlatin=bool(re.search(r'[^\x00-\u024f\s\d\W]',o or ''))
countries=' '.join(r.get('countries') or [])
if nonlatin: return True,'original title not in English'
if countries and not ENGLISH.search(countries): return True,'made in '+countries.split()[0]
if o and t and o.strip().lower()!=t.strip().lower() and not re.search(r'[A-Za-z]{3}',o): return True,'original title differs'
return False,''
INTL={'305','601','401'}
ANIMATED_CH={'105','601','602','603','604','605','611','612','613','614'}
DOC_CH={'201','202','203','204','401'}
FICTION_CH={'101','103','104','105','106','107','301','302','303','304','305','306','307','308','309','601','602','603','604','605','612','613'}
LIVE=re.compile(r'\b(stand-up|standup|comedian|comedy special|unruly set|in this set|live from|in concert|tour film|takes aim at)\b',re.I)
def score(r,ch):
b=B[ch]; e=[]; typ=r.get('type'); g=gen(r); ov=r.get('overview') or ''; year=r.get('year'); rating=r.get('rating') or ''
text=ov+' '+(r.get('name') or '')+' '+' '.join(r.get('taglines') or [])
if typ not in b['kind']: return 0,['wrong kind']
if b.get('kids') and rating in ADULT: return 0,[f'rated {rating}']
s=0.
# Format, as a hard limit: animation, documentary and fiction each have their own channels; live specials have none but Ring X's events.
animated='Animation' in g
doc=bool(g & {'Documentary'})
if animated and ch not in ANIMATED_CH: return 0,['animation, not for this channel']
if not animated and ch in ANIMATED_CH and g and ch not in ('611','601'): return 0,['live action, not for this channel']
if doc and ch in FICTION_CH: return 0,['a documentary, not fiction']
if g and not doc and ch in DOC_CH and ch!='401' and not (g & {'Reality'} and ch in ('203','204')): return 0,['fiction, not factual']
if ch=='107' and (doc or g & {'Reality'}): return 0,['factual, and Evidence is scripted only']
if LIVE.search(ov) and ch!='401': return 0,['a live or stand-up special']
# Genres: only as one part of the evidence; missing genres are not held against it.
if g:
if b.get('need_any') and not (g & b['need_any']): return 0,[f'not {"/".join(sorted(b["need_any"]))}']
gh=len(g & b['genres_any'])
s+=.25*min(1,gh/1.5); e.append(f'genres {", ".join(sorted(g & b["genres_any"])) or "none of its"}')
else: s+=.1; e.append('no genres given (not held against it)')
# Themes from the description, for and against.
pos=sorted(set(m.group(0).lower() for m in b['themes'].finditer(text)))
neg=sorted(set(m.group(0).lower() for m in b['against'].finditer(text)))
if ov:
s+=.35*min(1,len(pos)/2); e.append(('themes: '+', '.join(pos[:4])) if pos else 'no brief themes in its description')
if neg: s-=.25*min(1,len(neg)/2); e.append('against: '+', '.join(neg[:3]))
sim=cos(norm(vec(ov)),cent.get(ch,{})) if ch in cent else 0
short=len(ov)<200
# A short description says little: lean on the defining genre and its themes instead of word similarity.
if short and g and (g & (b.get('need_any') or b['genres_any'])) and (pos or b.get('need_any')): s+=.4*max(min(1,sim/.25),.6); e.append(f'short description, matched on genre ({sim:.2f})')
else: s+=.4*min(1,sim/.25); e.append(f'description like its titles ({sim:.2f})')
else: s+=.15; e.append('no description (not held against it)')
if year:
lo,hi=b['era']
if year<lo-3 or year>hi+3: s*=.3 if not b.get('current') else 1; e.append(f'{year} outside its era {lo}-{hi}' if not b.get('current') else '')
if ch=='101' and g & {'Game Show','Reality','Talk'}: return 0,['a game, reality or talk show, not a sitcom']
if ch=='309':
verified=bool(UK.search(' '.join(r.get('countries') or []))) or bool(UKSTUDIO.search(' '.join(r.get('studios') or [])))
if not verified: return 0,['British origin not verified' if not (r.get('countries') or r.get('studios')) else 'not British by its countries or studios']
if b.get('uk'):
uk=bool(UK.search(' '.join(r.get('countries') or []))) or bool(UKSTUDIO.search(' '.join(r.get('studios') or [])))
if uk: s+=.1; e.append('British')
elif r.get('countries') or r.get('studios'): s*=.6; e.append('not British by its studios or countries')
if b.get('kids') and rating and rating not in KIDS_OK: s*=.5; e.append(f'rated {rating}')
if b.get('kids') and not rating: s*=.8; e.append('no rating to confirm it suits children')
if 'Horror' in g and ch in ('304','305') : s+=.12; e.append('a horror film')
if 'Horror' in g and ch in ('308','307','612','613'): s*=.5; e.append('horror is not for this channel')
if b.get('need_any') and g & b['need_any'] and len(ov)<160: s+=.1; e.append('short description, its defining genre carries more')
if b.get('need_theme') and not pos: s*=.5; e.append('none of its themes')
# Paul, 4 November 2026: made-for-TV romances (the Hallmark kind) aren't Orbit material.
if 'TV Movie' in g: s*=.4; e.append('a made-for-TV film')
if ch=='301' and 'Action' in g and not re.search(r'superhero|epic|franchise|saga|blockbuster',text,re.I): s*=.8; e.append('action, but not an event film')
f,why=foreign(r)
if f and ch not in INTL: s*=.5; e.append(why+' (this channel is English-language)')
return max(0,s),[x for x in e if x]
def place(r):
sc=sorted(((score(r,ch),ch) for ch in B),key=lambda x:-x[0][0])
(s1,e1),c1=sc[0]; (s2,e2),c2=sc[1]
if s1<.45: v='no clear home'
elif s2>=s1*.85: v='ambiguous'
else: v='suggested'
tier='routine' if v=='suggested' and s1>=.7 and s2<s1*.7 else ('editorial' if v=='suggested' else ('needs evidence' if v=='ambiguous' else 'no action'))
return dict(id=r['id'],title=r.get('name'),year=r.get('year'),type=r.get('type'),genres=sorted(gen(r)),verdict=v,tier=tier,top=B[c1]['name'],s1=round(s1,2),second=B[c2]['name'],s2=round(s2,2),evidence='; '.join(e1))
if __name__=='__main__':
ids=[row[0] for row in c.execute("select id from items where premiere between '2026-09-05' and '2026-11-04' and provider_ids like '%Imdb%'")]
seen=set(); out=[]
carried={i for v in pools.values() for i in v}
for i in ids:
if i not in ev or i in carried: continue
r=ev[i]; key=(r.get('name'),r.get('year'))
if key in seen: continue
seen.add(key); out.append(place(r))
json.dump(out,open(f'{S}/staged5.json','w'),indent=0,ensure_ascii=False)
print(len(out),collections.Counter(o['verdict'] for o in out),collections.Counter(o['tier'] for o in out))
print(collections.Counter(o['top'] for o in out if o['verdict']=='suggested').most_common())