You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The hoist-assignment step now finds the globally optimal row→property assignment (bitmask DP) with a uniqueness check, replacing greedy best-pair-first. Greedy's local ambiguity test refused whenever the chosen row scored equally on another property — even when a different captioned row's hard constraint forced the choice. Production case: SubCrewMaterial's DocumentType/DocumentType_2 collision family, where a row captioned DocumentType ties at 100 on both properties, but the sibling captioned DocumentType_2 can only take _2, forcing the first onto the bare name — greedy refused this no matter what the operator captioned. A genuinely tied optimum (two equal-total assignments) still refuses. Verified: zero mapping or status changes across the 112-GI production feed; the change only accepts previously-refused constraint-forced cases. Ported to align_columns.mjs (kept in sync) and unit-tested (147 tests).
Documented (and rejected) exact-caption preference. Ranking an exact caption→property match above a suffix-stripped one looks like it should pin X when both X and X_2 exist — but collision suffixes are POSITIONAL (the earlier grid row takes the bare name), so a captioned row sitting after an uncaptioned same-name row correctly owns X_2. Verified counterexample on a production forecast GI, where exact-preference stole CostCode from the stored costCodeID row. The scoring keeps exact and stripped matches equal on purpose; the comment in columnScore() records why.