diff --git a/scripts/meta_optimize_distributed.sh b/scripts/meta_optimize_distributed.sh index 00389b4e..d05afce2 100755 --- a/scripts/meta_optimize_distributed.sh +++ b/scripts/meta_optimize_distributed.sh @@ -108,16 +108,16 @@ if [[ "$LINES" -ne "$N" ]]; then fi # Lex-sort matching CorpusReport's compare_reports: -# tier-1: fail_coverage, fail_bg, fail_single_stroke, fail_two_stroke, fail_length_budget +# tier-1: fail_coverage, fail_single_stroke, fail_two_stroke, fail_length_budget, fail_bg # tier-2: total_bg, total_strokes, total_unpainted_density, total_repaint, total_length echo "" >&2 echo "[orch] top 5 by lex order:" >&2 jq -s 'sort_by([ .report.fail_coverage, - .report.fail_bg, .report.fail_single_stroke, .report.fail_two_stroke, .report.fail_length_budget, + .report.fail_bg, .report.total_bg, .report.total_strokes, .report.total_unpainted_density, @@ -129,10 +129,10 @@ echo "" >&2 echo "[orch] best (full JSON on stdout):" >&2 jq -s 'sort_by([ .report.fail_coverage, - .report.fail_bg, .report.fail_single_stroke, .report.fail_two_stroke, .report.fail_length_budget, + .report.fail_bg, .report.total_bg, .report.total_strokes, .report.total_unpainted_density, diff --git a/src/brush_paint_opt.rs b/src/brush_paint_opt.rs index 777fbebb..7a808de4 100644 --- a/src/brush_paint_opt.rs +++ b/src/brush_paint_opt.rs @@ -253,15 +253,21 @@ pub fn run_one_start(start_idx: usize, base: &PaintParams, max_passes: u32) -> R // // Tier 1 — count of letters violating each hard criterion: // 1. max unpainted cluster > 0.5 × brush_area (a feature is missing) -// 2. bg_painted / total_swept > 5 % -// 3. SINGLE_STROKE_LETTERS with strokes ≠ 1 -// 4. TWO_STROKE_LETTERS with strokes ≠ 2 -// 5. total_length > 2 × skeleton_length +// 2. SINGLE_STROKE_LETTERS with strokes ≠ 1 (wrong topology) +// 3. TWO_STROKE_LETTERS with strokes ≠ 2 (wrong topology) +// 4. total_length > 2 × skeleton_length (wandering path) +// 5. bg_painted / total_swept > 5 % (off-glyph paint) +// +// Order rationale: structural correctness (cluster coverage, stroke +// topology, path budget) ranks above aesthetic cleanliness (off-glyph +// paint). A previous run found the comparator was preferring +// tiny-brush configs that minimised bg paint at the cost of doubling +// stroke counts and 5×ing path length — bg sat at the wrong tier. // // Tier 2 — corpus aggregates (smaller is better, in this order): // 6. total bg pixels // 7. total stroke count -// 8. total density-weighted unpainted (Σ size^1.5) +// 8. total density-weighted unpainted (exponential per-cluster) // 9. total repaint // 10. total length @@ -350,11 +356,12 @@ pub fn compare_reports(a: &CorpusReport, b: &CorpusReport) -> Ordering { } }; } // Tier 1: count of letters failing each hard criterion. + // Structural fails first; bg-rate last (a soft aesthetic). cmp_field!(fail_coverage); - cmp_field!(fail_bg); cmp_field!(fail_single_stroke); cmp_field!(fail_two_stroke); cmp_field!(fail_length_budget); + cmp_field!(fail_bg); // Tier 2: aggregates. cmp_field!(total_bg); cmp_field!(total_strokes);