"""Run after apply_audit.py and continue_audit.py: python SCRIPT DATA OUT."""
import csv,json,sys
from pathlib import Path
out=Path(sys.argv[2])
def read(name):
 with (out/name).open(newline='') as f:return list(csv.DictReader(f))
def write(name,rows):
 with (out/name).open('w',newline='') as f:
  w=csv.DictWriter(f,fieldnames=list(rows[0]));w.writeheader();w.writerows(rows)
rows=read('measurement_audit_pass2.csv'); decisions=[]
# Evidence notes distinguish source statements from arithmetic reconstruction.
updates={
'H2025_279':dict(statistic_type='possible_test_bracket_midpoint',numeric_source_status='midpoint_matches_bracket_not_verified_point_estimate',screening_status='hold_exact_threshold_bracket_only',evidence_level='primary_abstract',tested_lower_Hz='45.61',tested_upper_Hz='65.09',source_check_url='https://pubmed.ncbi.nlm.nih.gov/19089401/',source_check_note='Seventeen tuatara discriminated flicker through 45.61 Hz but not 65.09 Hz. Their midpoint equals 55.35 Hz (audit arithmetic inference); the abstract does not establish that point estimate or its derivation. Retain the tested bracket, not a statistical confidence interval.'),
'H2025_061':dict(statistic_type='unverified_point_with_reported_range',numeric_source_status='range_supported_point_statistic_unverified',screening_status='hold_statistic_and_full_text',evidence_level='primary_abstract',tested_lower_Hz='70',tested_upper_Hz='80',source_check_url='https://www.journals.uchicago.edu/doi/abs/10.1086/705124',source_check_note='Temporal operant-conditioning result is reported as 70–80 Hz. Compiled 75 equals the range midpoint, but this does not prove its derivation or that it is a mean. Range fields record the reported range, not individual censoring bounds.'),
'H2025_066':dict(statistic_type='reconstructed_arithmetic_mean_individual_observed_highs',numeric_source_status='verified_reconstruction_124.5',screening_status='measurement_supported_estimand_and_other_gates_pending',evidence_level='primary_full_text',maximum_capacity_status='not_established_for_all_individuals',source_check_url='https://journals.biologists.com/jeb/article/223/1/jeb209031/224571/How-fast-can-raptors-see',source_check_note='Individual observed highs of 120 and 129 Hz average 124.5. A measured FFF at a tested luminance is distinct from a demonstrated peak over luminance. Do not encode unobserved luminance peaks as apparatus-frequency censoring.'),
'H2025_078':dict(statistic_type='reconstructed_arithmetic_mean_individual_observed_highs',numeric_source_status='verified_reconstruction_77.7_rounded',screening_status='measurement_supported_estimand_and_other_gates_pending',evidence_level='primary_full_text',maximum_capacity_status='not_established_for_all_individuals',source_check_url='https://journals.biologists.com/jeb/article/223/1/jeb209031/224571/How-fast-can-raptors-see',source_check_note='Individual observed highs 81, 77 and 75 Hz average 77.6667, rounding to 77.7. These support the compilation statistic, not a fully observed species maximum. Conditions and peak coverage differ among individuals.'),
'H2025_075':dict(statistic_type='unverified_compilation_summary',screening_status='hold_numeric_extraction_and_estimand',evidence_level='primary_full_text',maximum_capacity_status='not_established_for_all_individuals',source_check_url='https://link.springer.com/article/10.1007/s00359-016-1130-z',source_check_note='Full text supports behavioural FFF, but compiled 85 Hz still requires figure/data extraction. Four birds completed the luminance series; only one showed a peak within it. Methods give highest luminance 7200 cd/m2, abstract 7500; retain this discrepancy. Do not replace 85 with the highest individual 93.'),
'H2025_069':dict(statistic_type='reported_observed_maximum',numeric_source_status='verified_reported_maximum_105',screening_status='hold_incompatible_statistic_for_mean_pooling',evidence_level='primary_abstract',maximum_capacity_status='observed_maximum_under_test_conditions',source_check_url='https://pubmed.ncbi.nlm.nih.gov/1571796/',source_check_note='Two Leghorn hens were tested; 105 Hz is reported as the maximum recorded. This supports the number as an observed maximum, not a species mean. Light intensity and behavioural noise limited measurements.'),
'H2025_032':dict(method_audited='Behavioural motion task',endpoint_audited='rotating_stripe_motion_detection',statistic_type='reported_mean_SD',numeric_source_status='verified_mean_37.2_SD_1.6',screening_status='exclude_from_uniform_flicker_primary_separate_motion_stratum',evidence_level='primary_author_abstract',source_check_url='https://pubs.usgs.gov/publication/70024117',source_check_note='Young adults: 37.2 ± 1.6 cycles/s under photopic log I=1.96, using rotating stripes and optomotor/optokinetic responses. The abstract identifies mean and SD. Keep motion detection separate from uniform flicker; do not infer cd/m2 from log I.')}
for r in rows:
 r.update(statistic_type='not_yet_classified',evidence_level='see_prior_source_note',tested_lower_Hz='',tested_upper_Hz='',maximum_capacity_status='not_yet_classified')
 if r['record_id'] in updates:
  r.update(updates[r['record_id']]);decisions.append(r.copy())
write('measurement_audit_pass3.csv',rows);write('source_decisions_pass3.csv',decisions)
queue=[r for r in rows if r['longevity_years_audited'] and r['anage_quality_audited'] in ['acceptable','high'] and not r['screening_status'].startswith('exclude')]
write('candidate_source_check_queue_pass3.csv',sorted(queue,key=lambda r:(r['method_audited']!='Behavioural',r['Species_phylo'],r['record_id'])))
summary=dict(audit_pass=3,pass3_records_adjudicated=len(decisions),total_measurement_records=len(rows),pass3_CFF_numeric_changes=0,candidate_queue_measurements=len(queue),candidate_queue_taxon_labels=len({r['Species_phylo'] for r in queue}),final_analysis_sample_frozen=False)
(out/'audit_summary_pass3.json').write_text(json.dumps(summary,indent=2)+'\n')
assert len(rows)==280 and len(decisions)==7
print(json.dumps(summary,indent=2))
