smodusermc/offline-games / _tools /finalize_verification.py
smodusermc's picture
download
raw
13.7 kB
"""Publish human-reviewed verification outcomes, manifests, and small reproducibility tools."""
import os,json,collections,hashlib
from pathlib import Path
from huggingface_hub import HfApi
H=Path('/home/user/game-archive');R=H/'reports';B='smodusermc/offline-games';api=HfApi(token=os.environ['HF_TOKEN'])
menus={1,2,5,9,14,15,16,19,32,40,47,49,55,90,152,153,154}
intro={8,13,20,43,45,57,62,63,68,69,70,75,82,91,112}
ui={6,18,42,115}
notes={
7:'External CDN-hosted build, not a locally hosted complete game. Reclassified for exclusion.',
23:'Startup throws ytgame is not defined; platform SDK dependency unresolved.',
25:'Only the Angry Birds startup splash was reached within the test window.',
28:'Emulator startup stalled the host; no gameplay verified.',
31:'Canvas remained predominantly black; no recognizable menu verified.',
33:'All 49 Content.tar and 4 Dialog.tar source-declared chunks are now recorded. The browser test preceded this repair and stopped on a missing chunk; no successful post-repair runtime test.',
38:'Required Build/Build.data returns source HTTP 404; a guessed split path returned an HTML fallback, not valid game data. Not fabricated or replaced.',
42:'Balatro mod-manager UI renders. This is not evidence that the game itself launched.',
44:'Dynamic base URL points to a CDN-hosted build. Reclassified for exclusion.',
53:'Recovered many dynamically requested assets, but startup fails on missing Firebase/platform services.',
56:'Fixed one malformed UTF-8/base64 decoder regex, with original JS backed up. Remaining startup block involves external GameDistribution services.',
58:'Required ISO exceeded the safe capture/test limit and is not staged; emulator reports a missing ROM.',
59:'Captured all 31 consecutive BATIM.data.001–031 source chunks; .032 returns an HTML fallback. HEAD support fixed in the test mirror. No successful post-repair runtime test; payload exceeds test memory allowance.',
64:'Startup reports missing index.wasm.part01; no completed game launch.',
66:'Startup throws PokiSDK is not defined; external SDK dependency unresolved.',
85:'Installer shell only; game files were not installed during this test.',
88:'Only a downloading screen was reached; game launch unverified.',
89:'Download/launch shell only; source warns of around 1.6 GB runtime RAM plus a roughly 700 MB asset download.',
101:'Cookie click increased the counter from 0 to 1. This tests one action, not progression, saving, or all assets.',
106:'Emulator shell only; failed external dependency fetch. No game launch verified.',
112:'Rendered the port warning/Continue screen, but also logged an audio-worklet syntax error.',
115:'Added missing jQuery and icon-font CSS dependencies; initial UI renders without the former $-undefined error. No clicker progression test.',
136:'Space changed Runner.instance_.playing from false to true; runner scene rendered.',
149:'Recovered 57 local dependencies and a fallback image, but required branding images still fail and loading does not finish.',
152:'Selected the local Flash version and captured its page/SWF/runtime; reached Duck Life Play menu.',
153:'Reached the Duck Life 2 Play screen after waiting past the Flash preloader. Ads were blocked.',
154:'Reached the Duck Life 3 Start screen after waiting past the Flash preloader. Ads were blocked.'}
results=[]
for p in sorted(R.glob('verification-*.json')):
j=json.loads(p.read_text());i=j['id'];auto=j.get('status','unknown');j['automated_status']=auto
if auto=='input_smoke_passed':review='Input smoke passed'
elif i in menus:review='Menu/start screen observed'
elif i in intro:review='Intro/splash only'
elif i in ui:review='UI observed; gameplay untested'
elif i in (7,44):review='Exclude: external game build'
elif i in (33,59):review='Archive repaired; runtime unverified'
elif 'resource_limit' in auto or auto=='runtime_deferred_memory_limit':review='Inconclusive: resource limit'
elif auto in ('browser_crashed','startup_error','verification_exception','verification_process_failed'):review='Test failed/inconclusive'
else:review='Blocked or not ready'
j['reviewed_outcome']=review;j['review_note']=notes.get(i,'Narrow startup observation only; no full playthrough or save/reload test.')
j['full_playthrough_verified']=False
if i in menus|intro|ui:j['visual_review']='Screenshot manually reviewed; classification does not rely solely on a canvas existing.'
p.write_text(json.dumps(j,indent=2));results.append(j)
counts=dict(collections.Counter(x['reviewed_outcome'] for x in results))
# Refresh inventory while preserving all unrelated catalog entries.
api.download_bucket_files(B,[('_reports/inventory.json',R/'inventory.json')],raise_on_missing_files=True)
inv=json.loads((R/'inventory.json').read_text());byid={x['id']:x for x in results}
for item in inv:
i=item['id']
if i in byid:
item['verification_outcome']=byid[i]['reviewed_outcome'];item['verification_report']=f'_verification/games/{i:04d}.json'
mp=R/f'game-{i}.json'
if mp.exists():
m=json.loads(mp.read_text());item['captured_files']=len(m['files']);item['captured_bytes']=sum(f['bytes'] for f in m['files'])
if i in (7,44):item['status']='skipped_external_game_assets';item['skip_note']=notes[i]
(R/'inventory.json').write_text(json.dumps(inv,indent=2))
info=api.bucket_info(B)
summary={'entries_reviewed':len(results),'existing_entries_reviewed':66,'new_entries_captured_and_reviewed':7,'new_entry_ids':[112,115,136,149,152,153,154],'outcomes':counts,'pending_catalog_candidates':sum(x['status']=='pending_not_captured' for x in inv),'oversized_entry_pages_deferred':sum(x['status']=='deferred_large_entry' for x in inv),'bucket_bytes_before_report_upload':info.size,'bucket_objects_before_report_upload':info.total_files,'full_playthroughs_verified':0,'scope':'Network-blocked local HTTP mirror. Not a file:// or standalone-HTML test. Repair phase may retrieve source dependencies; offline phase cannot.'}
(R/'verification-summary.json').write_text(json.dumps(summary,indent=2))
lines=['# Game archive — verification and repair report','',f'**[Public Hugging Face Bucket](https://huggingface.co/buckets/{B})**','',f"Reviewed **{len(results)} entries**: the original 66 plus 7 new entries. The bucket is approximately **{info.size/1e9:.2f} GB**. **{summary['pending_catalog_candidates']} catalog candidates remain pending**, plus two oversized entry pages deferred.",'','## What actually passed','', '- **Input checks:** 1 and 2048 responded to arrow keys; Cookie Clicker increased its cookie count from 0 to 1; Dinosaur started running after Space.', '- **Menu/startup examples:** 1 on 1 Soccer, 10 Minutes Till Dawn, 20 Minutes Till Dawn, Achievement Unlocked 1–3, Ages of Conflict, Apes vs Helium, Bad Time Simulator, Baldur’s Gate II, Basket Random, Celeste 3D, and Duck Life 1–3.', '- A menu, intro, or loading screen is **not** a full gameplay verification. No full playthroughs, reliable save/reload checks, or complete level coverage are claimed.','', '## Repairs and audit','', '- Captured browser-observed missing runtime files, modules, images, and audio that the initial static crawler missed.', '- Retrieved all 49 declared Apotheon content chunks and its 4 dialogue chunks. Archived all 31 contiguous Bendy game-data chunks. These archive repairs still need successful post-repair runtime tests.', '- Corrected the temporary test server to support HEAD requests used by split-file loaders and explicit JavaScript UTF-8 responses.', '- Repaired Basketball Stars’ malformed base64-decoder regex, preserving the original file under `_originals/`. External service dependencies still prevent a verified offline launch.', '- Added missing jQuery support for CSGO Clicker and captured the local Flash version for Duck Life 1.', '- Reconciled 11 stale entry-page manifest hashes/sizes to existing bucket edits, without replacing those entry pages.', '- The final storage audit covered all 73 recorded game manifests: **zero missing referenced bucket objects and zero size mismatches**. This only checks the recorded file set, not undiscovered assets. SHA-256 checks were performed when staging test assets, not claimed for every object in the bucket.','', '## Scope and limitations','', '**Tests used a local HTTP mirror with external browser requests blocked.** Absolute source URLs and selected runtime-library URLs were routed to local copies in the test responses. This is not proof that unmodified HTML opens directly from `file://`, or that these games are self-contained HTML files.', '', 'The test host has about 2 GiB RAM. Heavy games were deferred or stopped by memory/time watchdogs; that does not prove they are broken on a stronger device. Some source files return real 404s or HTML fallbacks; those were not fabricated. Other games require external SDKs, servers, or missing ROMs.','', '## Outcome totals','', '| Outcome | Entries |','|---|---:|']
for k,v in counts.items():lines.append(f'| {k} | {v} |')
lines+=['','## Per-game results','','| Game | Outcome | Notes |','|---|---|---|']
for j in results:lines.append('| '+j['name'].replace('|','/')+' | '+j['reviewed_outcome']+' | '+j['review_note'].replace('|','/')+' |')
lines+=['','## Files and next steps','', '- `_verification/games/`: detailed per-game test reports; `_verification/evidence/`: screenshots.', '- `_reports/games/`: updated captured-file manifests and checksums.', '- `_tools/`: credential-free collection, repair, and verification scripts.', '- Local game assets and bulky caches are removed after batching; small reports and scripts remain in this workspace.', '- Geometry Dash was not changed.','']
md='\n'.join(lines);(H/'VERIFICATION.md').write_text(md)
root='''# Game-file archive and verification\n\nPublic storage bucket requested by the account owner. Source catalog: https://garbsoftball.com/g\n\n## Current status\n\n'''+f"**{len(results)} entries reviewed (66 existing + 7 new). {summary['pending_catalog_candidates']} candidates remain pending.**\n\n"+'''Start with `_verification/verification-summary.md` and `_verification/verification-summary.json`.\n\nFour narrow input checks passed: **1, 2048, Cookie Clicker, Dinosaur**. Several other titles reached menus, but **not every folder is a complete or playable game**. No complete playthroughs are claimed.\n\n- `site/`: captured game/server-relative files, plus documented repairs.\n- `_vendor/`: captured supporting runtime/library files.\n- `_originals/`: backed-up bytes for files deliberately patched in this repair pass.\n- `_reports/`: catalog and file manifests.\n- `_verification/`: test results, screenshots, storage audit, and repair notes.\n- `_tools/`: scripts; tokens are supplied through environment variables, not embedded.\n\n## Downloading\n\n```sh\nhf buckets sync hf://buckets/smodusermc/offline-games/site ./game-files\n```\n\nThis downloads several GB. Some entries also require `_vendor/` files and a local hosting/routing setup. Downloading only an HTML page is not enough. These are not automatically converted self-contained HTML releases. Bucket storage is not a configured live game server. Browser verification used a network-blocked local HTTP mirror with URL routing; it was not a file:// test.\n\n## Important limitations\n\nThe test host has about 2 GiB RAM; resource-limited results do not establish that a game is broken. Source 404s, external SDK dependencies, unfinished downloads, and missing assets are explicitly recorded. Geometry Dash remains excluded and its separate dataset was left untouched.\n\nOriginal games/assets retain their owners' rights; no new redistribution license is granted. This bucket was made public at the account owner's request. Revoke access tokens shared in chat after authorized uploads are finished.\n'''
(H/'BUCKET-README.md').write_text(root)
# Update reusable collectors so future collection does not overwrite the verification landing page.
for name in ['collect_next.py','previous-collector.py']:
p=H/'tools'/name
if p.exists():
s=p.read_text().replace("(readme.encode(),'README.md')","(readme.encode(),'_reports/collector-method.md')").replace('No runtime testing; see individual manifests. Pending entries were not captured.','This collection pass does not run browser tests. See _verification for separate test results. Pending entries were not captured.')
p.write_text(s)
# Preserve existing JSON report paths; publish all fresh evidence and source records without credentials.
adds=[(H/'BUCKET-README.md','README.md'),(H/'VERIFICATION.md','_verification/verification-summary.md'),(R/'verification-summary.json','_verification/verification-summary.json'),(R/'inventory.json','_reports/inventory.json')]
for p in R.glob('verification-*.json'):
if p.name=='verification-summary.json':continue
ident=int(p.stem.split('-')[1]);adds.append((p,f'_verification/games/{ident:04d}.json'))
for p in (R/'evidence').glob('*.jpg'):adds.append((p,'_verification/evidence/'+p.name))
for p in (H/'tools').glob('*.py'):adds.append((p,'_tools/'+p.name))
adds.extend([(H/'tools/collect_next.py','_tools/resume-collector.py'),(H/'WORKLOG.md','_verification/WORKLOG.md')])
for i in range(0,len(adds),30):api.batch_bucket_files(B,add=adds[i:i+30])
# Refresh obsolete top-level collection summary/status while retaining its separate collection record.
api.batch_bucket_files(B,add=[(R/'verification-summary.json','_reports/summary.json'),(H/'VERIFICATION.md','_reports/status.md')])
verify={f.path:f for f in api.get_bucket_paths_info(B,[dest for _,dest in adds])}
for src,dest in adds:assert dest in verify and verify[dest].size==src.stat().st_size
print(json.dumps(summary,indent=2));print('Published and size-verified',len(adds),'report/evidence/tool objects')

Xet Storage Details

Size:
13.7 kB
·
Xet hash:
f504d000df0f93814857cdf4b510984e0dc5329dded470e8d0b2f2f76c9bdf2b

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.