#!/usr/bin/env python3 """Publish failing color evidence without converting diagnosis into acceptance.""" from datetime import datetime, timezone import hashlib import json from pathlib import Path ROOT=Path(__file__).resolve().parents[2] RESULTS=ROOT/'tests/results/cmyk-lut' def sha(path): with path.open('rb') as stream: return hashlib.file_digest(stream,'sha256').hexdigest() def main(): prior=json.loads((RESULTS/'prior-validation-record.json').read_text()) assert sha(RESULTS/'prior-validation-record.json')=='c80457d32c246e40743f59f5e602ff0f71d59d496b33a72618a97475659c9013' for name,digest in prior['evidenceSha256'].items(): assert sha(ROOT/name)==digest,name sources={str(p.relative_to(ROOT)):sha(p) for directory in ('src','qml','cmake','resources') for p in (ROOT/directory).rglob('*') if p.is_file() and '__pycache__' not in p.parts} sources.update({name:sha(ROOT/name) for name in ('CMakeLists.txt','resources.qrc')}) assert sources==prior['sourceSha256'] for name,digest in prior['builds']['arch']['binaries'].items(): assert sha(ROOT/'build'/name)==digest package=prior['ubuntuPackage'] assert sha(ROOT/'build-ubuntu-vm/packages'/package['archive'])==package['archiveSha256'] diagnosis=json.loads((RESULTS/'diagnosis.json').read_text()) assert diagnosis['diagnosisVerified'] and not diagnosis['renderingAcceptance'] assert not diagnosis['relativeIntentPreserved'] and diagnosis['toleranceUnchanged']==4 assert diagnosis['diagnoserSha256']==sha(ROOT/'tests/cmyk_lut/diagnose.py') reports={} for os_name in ('arch','ubuntu'): report=json.loads((RESULTS/os_name/'report.json').read_text()) assert not report['success'] and report['originalUnchanged'] and report['binariesUnchanged'] assert len(report['scales'])==3 for name,digest in report['evidenceSha256'].items(): assert sha(RESULTS/os_name/name)==digest assert report['binaries']['docview-pdf-worker']==prior['builds'][os_name]['binaries']['docview-pdf-worker'] assert report['runnerSha256']==sha(ROOT/'tests/cmyk_lut/run.py') entry=next(r for r in diagnosis['results'] if r['os']==os_name) assert entry['comparisonReportSha256']==sha(RESULTS/os_name/'report.json') assert entry['failedPdfiumAnalyticProbes']==30 and entry['failedPopplerAnalyticProbes']==0 reports[os_name]=report assert sha(ROOT/'build/pdf-worker-evidence')==reports['arch']['binaries']['pdf-worker-evidence'] assert sha(ROOT/'.deps/pdfium/lib/libpdfium.so')=='08f6ea53a64f6fbb9f5ba8d9c02e0051987c6a9175f3fb5ba25f219174731aaa' reproduced=json.loads((RESULTS/'reproduction.json').read_text()) for name,digest in reproduced['filesByteIdentical'].items(): assert sha(ROOT/'tests/fixtures/pdf/cmyk-lut'/name)==digest==sha(RESULTS/'reproduction'/name) shutdown=json.loads((RESULTS/'shutdown.json').read_text()) assert shutdown['qemuExitCode']==0 and shutdown['guestPowerDownObserved'] assert sha(RESULTS/'shutdown-tail.txt')==shutdown['tailSha256'] gallery=[''' ICC CMYK 描画比較

ICC CMYK の追加描画比較

色の一致は未達です。 Arch・Ubuntu各48点中30点が許容差を超えました。原因の照合は完了していますが、描画の受入や人による承認は完了していません。

相対的な測色を指定した資料に対して、固定PDFiumは知覚的なICC変換を使用します。上2段の右端の暗色に明瞭な差があります。下段はプロファイルを適用しないDeviceCMYKの対照です。

試験条件・原因・未完了事項 / 生成PDF / 数値による原因照合

各画像を開くと元の解像度で確認できます。差分画像は絶対RGB差で、色差の許容性や印刷色を判定する画像ではありません。

'''] for os_name,label in [('arch','Arch Linux'),('ubuntu','Ubuntu 24.04')]: gallery.append('

'+label+'

') for scale in reports[os_name]['scales']: folder=os_name+'/scale-'+str(scale['scale']).replace('.','_') gallery.append(f'

{scale["scale"]:g}倍 / {scale["dpi"]:g} dpi

') for title,name in [('PDFium / 本番隔離ワーカー','pdfium/page-1.png'),('Poppler / 独立した比較','poppler.png'),('絶対RGB差','difference.png')]: path=folder+'/'+name assert (RESULTS/path).is_file() gallery.append(f'
{title}
{title}の描画比較
') gallery.append('
') gallery.append('
') (RESULTS/'index.html').write_text('\n'.join(gallery)) tools=['tests/cmyk_lut/run.py','tests/cmyk_lut/diagnose.py','tests/cmyk_lut/record.py','tests/fixtures/pdf/generate_cmyk_lut.py','tests/render_pdf_worker.cpp'] new_requirement='Resolve or explicitly review the fixed PDFium ICC rendering-intent discrepancy demonstrated by the CMYK CLUT fixture; runtime detection/notice is not yet implemented' record={**prior,'schemaVersion':4,'recordedAtUtc':datetime.now(timezone.utc).isoformat(), 'scope':'Unchanged validation3 product plus a new, failing CMYK ICC rendering comparison on Arch and Ubuntu. ' 'Prior passing functional/package tests remain scoped to their original runs; color acceptance is not achieved.', 'goalComplete':False,'colorRenderingFinding':diagnosis, 'colorRenderingReports':{name:{'path':'tests/results/cmyk-lut/'+name+'/report.json','sha256':sha(RESULTS/name/'report.json')} for name in reports}, 'previousValidation':{'record':'tests/results/cmyk-lut/prior-validation-record.json','sha256':sha(RESULTS/'prior-validation-record.json'), 'scope':'Validation3 package, all prior test executions and their exact product identities. No product bytes changed in the ICC investigation.'}, 'remainingAcceptance':prior['remainingAcceptance']+[new_requirement], 'validationToolsSha256':{**prior['validationToolsSha256'],**{name:sha(ROOT/name) for name in tools}}, 'evidenceSha256':{**prior['evidenceSha256'],**{str(p.relative_to(ROOT)):sha(p) for folder in (RESULTS,ROOT/'tests/fixtures/pdf/cmyk-lut') for p in sorted(folder.rglob('*')) if p.is_file() and p.suffix!='.pyc' and p!=RESULTS/'record.json'}}} encoded=json.dumps(record,ensure_ascii=False,indent=2)+'\n' (RESULTS/'record.json').write_text(encoded); (ROOT/'docs/validation-record.json').write_text(encoded) print(json.dumps({'colorRenderingAcceptance':False,'failedAnalyticProbes':60,'productUnchanged':True,'goalComplete':False})) if __name__=='__main__': main()