File size: 11,327 Bytes
6170561
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"""Export allowlisted benchmark fields and aggregates; never copy execution logs."""
import argparse,collections,datetime,hashlib,json,sqlite3
from pathlib import Path
from editorial_guard.dataset import dataset_summary,validate_dataset,write_json
from editorial_guard.protocol import ANNOTATION_VERSION
from editorial_guard.core import public_input
from editorial_guard.blinding import opaque_id

def reference(value):
    return 'evidence-'+hashlib.sha256(value.encode()).hexdigest()[:24]


def quality_index(rows):
    """Keep exclusions and unresolved judgments visible without manufacturing consensus."""
    output=[]
    for row in rows:
        annotations=[v['annotation'] for v in row['annotation_records']]
        reasons=[]
        if len(annotations)<2:reasons.append('insufficient_independent_annotations')
        if annotations and all(not a['valid_task'] for a in annotations):reasons.append('all_available_reviewers_reject_task')
        elif any(not a['valid_task'] for a in annotations):reasons.append('task_validity_disputed')
        if any(a['language_scope_status']!='supported' for a in annotations):reasons.append('language_scope_unvalidated')
        if any(a['source_fidelity']=='fail' for a in annotations):reasons.append('original_source_fidelity_contested')
        if any(a['source_fidelity']=='uncertain' or a['task_satisfied']=='uncertain' for a in annotations):reasons.append('semantic_uncertainty')
        missing=[value for value in row['constraints'].get('literal_required',[]) if value not in row['input_text']]
        if missing:reasons.append('required_literal_missing')
        states={(a['style_problem'],a['process_problem']) for a in annotations}
        confirmed_state=list(next(iter(states))) if len(annotations)>=2 and len(states)==1 else None
        no_edit=len(annotations)>=2 and all(a['valid_task'] and a['no_edit_needed'] and a['source_fidelity']=='pass' and a['task_satisfied']=='pass' and not a['style_problem'] and not a['process_problem'] for a in annotations)
        output.append({'id':row['id'],'source_group_id':row['source_group_id'],'route':row['provenance']['route'],
                       'annotation_count':len(annotations),'review_flags':reasons,
                       'task_validity':'insufficient_evidence' if len(annotations)<2 else 'invalid' if all(not a['valid_task'] for a in annotations) else 'disputed' if any(not a['valid_task'] for a in annotations) else 'model_agreement_valid',
                       'agreed_state_style_process':confirmed_state,'model_confirmed_no_edit':no_edit,
                       'designed_boundary':bool(row['provenance'].get('designed_boundary')),
                       'required_literal_count':len(row['constraints'].get('literal_required',[])),
                       'missing_required_literal_count':len(missing)})
    return output

def export(work,destination,release_locked=False,release_locked_families=None):
    if release_locked_families is not None and not release_locked:raise ValueError("Family release list requires explicit locked release")
    approved_locked=None if release_locked_families is None else set(release_locked_families)
    work=Path(work);out=Path(destination)
    if out.exists() and any(out.iterdir()):raise ValueError('Data export output must be empty')
    out.mkdir(parents=True,exist_ok=True)
    schema=json.loads((Path(__file__).resolve().parents[1]/'schemas/sample-0.1.0.json').read_text(encoding='utf-8'))
    allowed=set(schema['properties']);all_rows=[];phase_counts={}
    with sqlite3.connect(work/'requests.sqlite3') as db:
        request_dates={rid:datetime.datetime.fromtimestamp(started,datetime.timezone.utc).isoformat() for rid,started in db.execute('select id,started from requests')}
    def observable(rid):
        p=work/'requests'/(rid+'.request.json')
        if not p.exists():return {'request_date':request_dates.get(rid),'transport':'unknown'}
        setting=json.loads(p.read_text(encoding='utf-8'))
        return {'request_date':request_dates.get(rid),'transport':setting.get('transport','unknown'),'provider_config_hash':setting.get('provider_config_hash','unknown'),'parameters':setting.get('parameters',{}),'endpoint':setting.get('endpoint'),'requested_max_tokens':setting.get('max_tokens'),'effective_max_tokens':setting.get('effective_max_tokens','unknown')}
    for phase,prefix in [('calibration','cal'),('main','main')]:
        directory=work/'data'/phase;rows=[]
        for path in sorted(directory.glob(prefix+'-*.json')):
            family=json.loads(path.read_text(encoding='utf-8'))
            for original in family['records']:
                row={k:v for k,v in original.items() if k in allowed}
                row=json.loads(json.dumps(row))
                rid=row['provenance'].get('request_id')
                row['generation_config'].update(observable(rid))
                row['provenance']['request_id']=reference(rid)
                votes=[]
                for p in sorted((directory/('labels-'+ANNOTATION_VERSION)).glob(row['id']+'--*.json')):
                    vote=json.loads(p.read_text(encoding='utf-8'))
                    vote={k:vote[k] for k in ('provider','requested_model','reported_model','request_id','annotation_version','annotation') if k in vote}
                    vote.update(observable(vote['request_id']))
                    vote['request_id']=reference(vote['request_id']);votes.append(vote)
                row['annotation_records']=votes
                signatures=[tuple(v['annotation'][k] for k in ('valid_task','style_problem','process_problem','source_fidelity','task_satisfied','no_edit_needed')) for v in votes]
                row['disagreement_status']='insufficient_evidence' if len(votes)<2 else 'agreement' if len(set(signatures))==1 else 'disputed'
                row['issues']=votes[0]['annotation']['issues'] if row['disagreement_status']=='agreement' else []
                rows.append(row)
        phase_counts[phase]=dataset_summary(rows);all_rows.extend(rows)
    locked_families={r["source_group_id"] for r in all_rows if r["split"]=="locked_test"}
    if approved_locked is not None and not approved_locked<=locked_families:raise ValueError("Unknown locked family in release list")
    released_locked=locked_families if release_locked and approved_locked is None else (approved_locked or set())
    validation=validate_dataset(all_rows)
    write_json(out/'validation.json',validation)
    suites={}
    for suite in ('StyleBench-ZH','DeliveryBench-ZH'):
        root=out/suite;root.mkdir(exist_ok=True)
        rows=[r for r in all_rows if r['suite']==suite]
        published=[r for r in rows if r['split']!='locked_test' or r['source_group_id'] in released_locked]
        with (root/'samples.jsonl').open('w',encoding='utf-8',newline='\n') as stream:
            for row in published:stream.write(json.dumps(row,ensure_ascii=False)+'\n')
        # Alternate task views share their existing source families; they add zero independent families.
        view_index=[]
        with (root/'task-views.jsonl').open('w',encoding='utf-8',newline='\n') as stream:
            for row in published:
                for track in ('detect','generate','workflow'):
                    view=public_input(row);view.update(id=opaque_id(row['id'],'solver-view-v1')+'-'+track,parent_id=opaque_id(row['id'],'solver-view-v1'),source_group_id=opaque_id(row['source_group_id'],'solver-family-v1'),track=track,view_status='task_view_not_independent_sample')
                    view_index.append({'view_id':view['id'],'parent_id':row['id'],'source_group_id':row['source_group_id'],'split':row['split']})
                    if track=='generate':view.pop('input_text',None)
                    stream.write(json.dumps(view,ensure_ascii=False)+'\n')
        write_json(root/'task-view-index.json',view_index)
        partition={kind:[r['id'] for r in published if r['split']==kind] for kind in ('calibration','development','validation','locked_test')}
        write_json(root/'partitions.json',partition)
        write_json(root/'disputed-index.json',[r['id'] for r in published if r['disagreement_status']=='disputed'])
        family_manifest=[]
        for group in sorted({r['source_group_id'] for r in published}):
            members=[r for r in published if r['source_group_id']==group]
            family_manifest.append({'source_group_id':group,'split':members[0]['split'],'suite':suite,'instance_ids':[r['id'] for r in members],'generator':members[0]['provenance']['generator'],'origin':'synthetic fictional task world'})
        write_json(root/'family-manifest.json',family_manifest)
        quality=quality_index(published)
        write_json(root/'quality-index.json',quality)
        summary=dataset_summary(published)
        summary['quality']={'task_validity':dict(collections.Counter(r['task_validity'] for r in quality)),'review_flags':dict(collections.Counter(flag for r in quality for flag in r['review_flags'])),'confirmed_no_edit_instances':sum(r['model_confirmed_no_edit'] for r in quality),'agreed_four_states':dict(collections.Counter(str(r['agreed_state_style_process']) for r in quality)),'required_literal_missing_instances':sum(bool(r['missing_required_literal_count']) for r in quality),'scope':'automated judgments; flags remain visible, no human validation or forced consensus'}
        summary.update(planned_main_families=250,main_families=len({r['source_group_id'] for r in rows if r['split']!='calibration'}),held_back_instances=len(rows)-len(published),generation_cohorts=dict(collections.Counter(r['provenance']['generator']+'|'+r['generation_config'].get('transport','unknown')+'|'+r['generation_config'].get('provider_config_hash','unknown') for r in published)),designed_boundary_instances=sum(bool(r['provenance'].get('designed_boundary')) for r in published),all_labels_automated=True,human_validation=False,independent_family_caveat='distinct fictional task worlds drawn from seven base templates; lexical deduplication does not prove semantic independence')
        suites[suite]=summary;write_json(root/'summary.json',summary)
    release={'version':'0.1.0','annotation_version':ANNOTATION_VERSION,'phases':phase_counts,'suites':suites,'validation_status':validation['status'],'locked_test_released':release_locked,'locked_test_release':{'scope':'explicit_family_allowlist' if approved_locked is not None else 'all_locked' if release_locked else 'none','family_ids':sorted(released_locked),'held_back_families':len(locked_families-released_locked)},'files':{str(p.relative_to(out)).replace('\\','/'):hashlib.sha256(p.read_bytes()).hexdigest() for p in out.rglob('*') if p.is_file() and p.name!='manifest.json'},'origin':'programmatic fictional facts and recorded model responses','license':'CC-BY-4.0'}
    write_json(out/'manifest.json',release)
    return release

if __name__=='__main__':
    p=argparse.ArgumentParser();p.add_argument('--work-dir',required=True);p.add_argument('--output',required=True);p.add_argument('--release-locked',action='store_true');p.add_argument('--release-locked-family',action='append',help='Only release evaluated locked families; repeat for each source_group_id');a=p.parse_args()
    print(json.dumps(export(a.work_dir,a.output,a.release_locked,a.release_locked_family),ensure_ascii=False,indent=2))