Files
verstack/scripts/coverage_matrix.py

36 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Join content inventory and versioned validation evidence without upgrading partial coverage."""
import argparse,collections,json,pathlib,re
from inventory_corpus import atomic
def release(name):
match=re.fullmatch(r'(.+)-(\d+(?:_\d+)+)(?:_spike([123]))?\.spk(?:\.zip)?',name,re.I)
if not match:raise ValueError(f'unrecognized package label: {name}')
slug,version,generation=match.groups();slug=slug.lower()
edition='unspecified'
for suffix,label in [('_pro','Pro'),('_le','Premium/LE'),('_elg','ELG'),('_the_pin','The Pin')]:
if slug.endswith(suffix):slug=slug[:-len(suffix)];edition=label;break
names={'got':'Game of Thrones','wn':'Whoa Nellie','wwe':'WrestleMania','elvira3':'Elviras House of Horrors','mando':'The Mandalorian','turtles':'Teenage Mutant Ninja Turtles','sword_of_rage':'Black Knight: Sword of Rage','guardians':'Guardians of the Galaxy','avengers_infinity':'Avengers: Infinity Quest','metallica_spike':'Metallica Remastered','star_wars_elg':'Star Wars ELG'}
return {'game':names.get(slug,slug.replace('_',' ').title()),'game_slug':slug,'edition':edition,'version':version.replace('_','.'),'generation':f'SPIKE {generation}' if generation else 'unconfirmed','label_provenance':'filename; edition grouping and display labels are inferred, not a manifest declaration'}
def matrix(inventory,evidence):
rows=[]
for package in inventory['packages']:
receipt=evidence/(package['name']+'.json');media=evidence/(package['name']+'.media.json')
extraction=json.loads(receipt.read_text()) if receipt.exists() else {}
counts=collections.Counter();families=collections.defaultdict(collections.Counter)
if media.exists():
for asset in json.loads(media.read_text())['assets']:
status=asset['status'];counts[status]+=1
family=asset.get('profile') or ('radium-pcm' if asset.get('section')==8 else 'radium-bitmap' if asset.get('section')==3 else pathlib.PurePosixPath(asset.get('source','')).suffix or 'unclassified')
families[family][status]+=1
wrapper=extraction.get('wrapper',{})
if wrapper and wrapper.get('source_sha256')!=package['sha256']:raise ValueError('receipt source identity differs from content inventory')
rows.append({**package,**release(package['name']),'processing':extraction.get('processing'),'extraction_status':extraction.get('status','not_processed'),'extracted_files':len(extraction.get('inventory',[])),'asset_status_counts':dict(counts),'families':dict(families),'acceptance':'blocked','blockers':['Full family coverage, readback, playback and edition comparison have not all been certified.']})
return {'schema':1,'expected':inventory['expected'],'packages':rows,'accepted_packages':0}
if __name__=='__main__':
p=argparse.ArgumentParser();p.add_argument('inventory',type=pathlib.Path);p.add_argument('evidence',type=pathlib.Path);p.add_argument('output',type=pathlib.Path);a=p.parse_args();m=matrix(json.loads(a.inventory.read_text()),a.evidence);atomic(a.output,m)
lines=['# SPIKE corpus coverage','',f"{len(m['packages'])} packages inventoried; full acceptance remains blocked.",'','| Package | Game | Edition | Generation | Wrapper | Extraction | Files |','| --- | --- | --- | --- | --- | --- | --- |']
for r in m['packages']:lines.append(f"| {r['name']} | {r['game']} | {r['edition']} | {r['generation']} | {r['wrapper']} {r.get('payload_wrapper','')} | {r['extraction_status']} | {r['extracted_files']} |")
a.output.with_suffix('.md').write_text('\n'.join(lines)+'\n')