Form Field Association (Multi-Direction) + Checkbox State

ocr/structure recognises a label only if its text ends in : and pairs it with the immediately next cell — it cannot handle a label sitting above its value, a two-column key/value layout, right-aligned values, or any widget that isn’t a text cell, and it has no notion of checkbox / radio state at all. form_fields generalises this: it pairs each label with the nearest aligned value in any of several directions (right, below), matches free-standing widgets (checkboxes, radios, inputs) to their nearest label, and reads a checkbox’s checked state from its fill ratio.

The association is pure-stdlib over plain box dicts (fully unit-testable, no image); only checkbox_state touches pixels, isolated behind the shared visual_match gray loader so tests can pass a synthetic array. Reuses table_grid_fill’s box-bounds reader. Imports no PySide6.

Headless API

from je_auto_control import (associate_fields, match_labels_to_widgets,
                             checkbox_state)

fields = associate_fields(ocr_boxes, directions=("right", "below"))
# [{"label": "Name", "value": "Ann", "direction": "right", "gap": 20, ...}]

pairs = match_labels_to_widgets(label_boxes, checkbox_boxes)
# [{"widget": {...}, "label": "Accept terms", "distance": 22}]

state = checkbox_state(screenshot, checkbox_box)   # "checked" | "unchecked"

associate_fields treats boxes whose text ends in : as labels and pairs each with the nearest value box in the requested directions (within max_gap), returning {label, value, direction, gap, label_box, value_box}. match_labels_to_widgets assigns each widget to its nearest label by centre distance. checkbox_state returns "checked" / "unchecked" from the dark-pixel fill ratio of the box (image is injectable — path / ndarray / PIL).

Executor commands

AC_associate_fields (text_boxes / directions / max_gap{count, fields}) and AC_match_labels_to_widgets (labels / widgets{count, pairs}). They are exposed as the MCP tools ac_associate_fields / ac_match_labels_to_widgets (read-only) and as the Script Builder commands Associate Form Fields / Match Labels To Widgets under OCR.