"""Seal the reviewed removals, source bindings and protected records.""" import hashlib import json from pathlib import Path import sys import os ROOT=Path(__file__).resolve().parents[1] sys.path.insert(0,str(ROOT/'server/voc-library')) import research_cleanup as cleanup WORK=ROOT/os.environ.get('KSF_CLEANUP_WORK','work/library-cleanup-20261111') inventory=json.loads((WORK/'inventory-result.json').read_bytes())['body']['result'] audit=json.loads((WORK/'audit-proposals.json').read_bytes()) protected=set() for b in ['five-topics-public-01','five-topics-public-02','five-topics-public-03']: protected.update(r['id'] for r in json.loads((ROOT/'work/database-enrichment-20261110/batches'/b/'expected-records.json').read_bytes())) social={r['id']:r for r in inventory['social']} def original(row): result={k:v for k,v in row.items() if k not in ('payload_sha256','source_payload','_ksf_source_rowid')} fields=next(t['columns'] for t in inventory['manifest']['tables'] if t['name']=='social_posts') for f in fields: if result.get(f['name']) is not None and 'INT' in f['type'].upper():result[f['name']]=int(result[f['name']]) return result plan={'schema':cleanup.SCHEMA,'baseGeneration':inventory['generation'], 'removals':audit['proposedRemovals'],'repairs':audit['proposedRepairs'], 'protectedSocial':[{'id':id,'recordSha256':cleanup.digest(original(social[id]))} for id in sorted(protected)], 'reviewCriteria':audit['limits'],'scope':audit['scope']} plan_sha=cleanup.digest(plan) cleanup.validate(plan,plan_sha) out={'plan':plan,'planSha256':plan_sha} (WORK/'sealed-plan.json').write_text(json.dumps(out,ensure_ascii=False,indent=2),encoding='utf8') print(json.dumps({'planSha256':plan_sha,'removals':len(plan['removals']),'repairs':len(plan['repairs']), 'protected':len(protected),'implementationSha256':hashlib.sha256((ROOT/'server/voc-library/research_cleanup.py').read_bytes()).hexdigest()},ensure_ascii=False))