        golden={'A':'A-01: 19.50元','B':'B-02: 7.0%','C':'C-03: 100件'};texts=output.get('texts',[]);by_id={r.get('id'):str(r.get('text','')) for r in texts};check('三张原图各有一份转录',set(by_id)==set(golden) and len(texts)==3);rows=[]
        for key,reference in golden.items():
            hypothesis=by_id.get(key,'');strict=_alignment(reference,hypothesis);normalized=_alignment(norm(reference),norm(hypothesis));rows.append({'id':key,'reference':reference,'hypothesis':hypothesis,'strict':strict,'normalized':normalized})
        total_chars=sum(r['strict']['referenceCharacters'] for r in rows);errors=sum(r['strict']['distance'] for r in rows);result={'rows':rows,'strictMicroCER':errors/total_chars if total_chars else None,'referenceCharacters':total_chars,'editErrors':errors,'normalizedMicroCER':sum(r['normalized']['distance'] for r in rows)/sum(r['normalized']['referenceCharacters'] for r in rows)};check('数字/小数点错误在规范化后仍计错',_alignment(norm('19.50元'),norm('19.60元'))['distance']==1);check('严格CER使用总编辑数除总参考字符',result['strictMicroCER']==errors/total_chars)
        table='<table><tr><th>ID</th><th>参考</th><th>实际转录</th><th>替换/删/增</th><th>CER</th></tr>'
        for r in rows:table+='<tr>'+''.join('<td>'+html.escape(str(v))+'</td>' for v in [r['id'],r['reference'],r['hypothesis'],r['strict']['counts'],r['strict']['cer']])+'</tr>'
        table+='</table>';text_html(artifact('ocr-alignment.html'),'真实视觉转录与字符错误率',[(r['id']+' · 对齐',r['strict']['alignment']) for r in rows]);page=(folder/'ocr-alignment.html').read_text();(folder/'ocr-alignment.html').write_text(page.replace('</h1>','</h1>'+table,1));dump(artifact('ocr-metrics.json'),result)
