| 123456789101112131415161718192021222324252627282930313233 |
- """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))
|