h2. The Ask When docling merges two tables printed side by side into one grid and fusion splits them back apart, the second table keeps the last column of the first. The split boundary is right, the column assignment is not: the cells of the first table's rightmost column land in both tables. h3. Reproduce Document: KREF Q1 2026 Form 10-Q (doc_key {{998c8ed06c0be22d}}, local playground document 293, ingested 2026-09-10 on main at ce13cfe, docling 2.126.0). Page 23 prints the Concentration of Credit Risk note as two tables side by side: Geography on the left, Collateral Property Type on the right. {{998c8ed06c0be22d.fusion.json}} match 14: {{"page": 23, "kind": "docling_undercount", "som_indices": [14, 15], "docling_table_refs": ["#/tables/66", "#/tables/67"], "overlap": 0.7988, "detail": "SoM found 2 tables, docling 1: docling dropped/merged a complex table"}}. Fusion split docling's one grid into two. h3. Actual {{#/tables/66}} (Geography) is 23 rows by 3 columns, bbox l=44 r=317, and is correct. {{#/tables/67}} (Collateral Property Type) is 9 rows by 4 columns, bbox l=276 r=568. Its first column is the Geography table's "December 31, 2025" column for the first eight geography rows: {noformat} [', 2025', 'Collateral Property Type(A)', 'March 31, 2026', 'December 31, 2025'] ['16.6 %', 'Multifamily', '40.6 %', '40.3 %'] ['11.9', 'Industrial', '22.1', '17.9'] ['10.9', 'Office', '17.8', '22.8'] ['12.0', 'Life Science', '13.9', '13.7'] ['6.4', 'Hospitality', '2.9', '2.8'] ['2.9', 'Student Housing', '2.2', '2.1'] ['5.2', 'Mixed Use', '0.5', '0.4'] ['4.7', 'Total', '100.0 %', '100.0 %'] {noformat} The two bboxes overlap by 41 points (276 to 317), which is exactly the width of the stray column. The stray cells are grounded and every one of them is {{reconciled}}: the values are printed on the page, just not in this table. Nothing flags the defect. In the store, each property-type line item leads with the stray value. {{t15-line-3}} reads: ", 2025 Collateral Property Type(A) March 31, 2026 December 31, 2025 10.9 Office 17.8 22.8". The answers in the 2026-09-10 concentration batch (docs/development/Playground_Output_Comp_Concentration_KREF.xlsx) were all correct, so the bleed did not cost an answer here. A question about "the first column" or a row whose label sits in column 0 would read the wrong figure. h3. Expected Each split table holds only the cells under its own column spans. {{#/tables/67}} is 9 rows by 3 columns, first row "Collateral Property Type(A) | March 31, 2026 | December 31, 2025", and its bbox starts at the property-type label column, not inside the geography table's last column. h3. Severity Medium. Financial document, values correct but misplaced into a table they do not belong to, with no flag raised. The same side-by-side layout appears in every KREF 10-Q and 10-K note on concentration. h2. Why now / What's open The declash reads the locator's column spans to split the grid. Not yet known: whether the stray column comes from the docling cell whose bbox straddles the boundary being assigned to both sides, or from the span of the second table being drawn one column too wide. The fix has to decide the tie rule for a cell that overlaps both tables' spans. h2. Acceptance Criteria Sharpened 2026-09-11 once the cause was found. The bleed is one symptom of two side-by-side tables sharing a seam: the grid locator has no rule for tables printed beside each other and merges them into one region on most runs (QUE-371, folded in here), and when it does report two, their tightened boxes overlap by the width of a stub column and Camelot reads that column into both. The fix is on the locator: one prompt rule so the pair is reported as two, and a vertical seam pass so the two boxes tile at the blank column between them, the counterpart of the existing stacked-pair seam. h3. AC1: Side-by-side pages come out as two tables with disjoint columns * *Verify by:* {{quber extract}} over {{998c8ed06c0be22d}} on the fix branch. * *Expected:* page 23 holds Geography 23x3 and Collateral Property Type 9x3; page 33 holds Geography 18x3 and Collateral Property Type 10x3; the two regions on each page tile at one x with no overlap; no grid carries a neighbour's column. * *Show:* the four grids' first rows and regions, and the annotated pages. h3. AC2: The store no longer carries the stray column * *Verify by:* reingest locally and read the {{t15-line-*}} chunks. * *Expected:* each line item leads with the property-type label; no chunk on page 23 carries a geography figure under the property-type table. * *Show:* the nine line-item chunks. h3. AC3: No other page changes * *Verify by:* the same full-document extraction against a baseline run on the current code. * *Expected:* no page other than 23 and 33 gains or loses a table or changes its column count beyond the correction agent's run-to-run variance. * *Show:* per-page table counts and grid shapes, baseline vs fix. h3. AC4: Unit tests pin the seam * *Verify by:* {{pytest tests/test_grid_locator.py}}. * *Expected:* the side-by-side prompt rule sits between the stacked rule and the "prefer ONE region" line; the seam search finds the blank column despite a prose row crossing it and finds none inside one table; the seam pass snaps an overlapping pair to that column and leaves stacked and already-separated pairs alone. * *Show:* the test run. h2. Current State In Progress on branch {{bugfix/QUE-370-side-by-side-tables}}. Fix implemented 2026-09-11 in {{src/quber/agents/grid_locator.py}}: # One bullet added to the locator prompt under "Counting tables": two tables printed side by side, each with its own column-header block and row-label column and a band of empty grid columns between them, are separate tables reported with their own column spans. # {{declash_side_by_side}}, run after {{declash_stacked}}: for a pair whose regions overlap vertically and whose grid column spans share less than the stacked threshold, search the two boxes' overlap for the widest blank column, tolerating a quarter of text rows crossing it (the running header and the intro sentence do), and snap the left box's right edge and the right box's left edge to its midpoint. A pair with no blank column in its overlap passes through untouched. *Validated* (full-document {{quber extract --review}} on the branch, baseline = same command on current main, same day): * Table count 67 to 69; the only pages whose count changed are 23 and 33, one to two each. * Page 23: Geography 23x3 at x 0.071 to 0.491 and Collateral Property Type 9x3 at 0.503 to 0.928, titled "Concentration of Credit Risk" and "Collateral Property Type". Page 33: Geography 18x3 and Collateral Property Type 10x3 tiling at x 0.495, both titled "Concentration of Credit Risk". No grid carries a neighbour's column. Every box starts below the running header. * Locator variance measured before the fix: current prompt merged page 23 in 4 of 4 single-page runs and 4 of 5 full-document runs; with the bullet, 4 of 4 split on both pages. * One other page differs from the baseline: page 76's grid is 6x5 instead of 6x3 with the same region. The same 6x5 appeared in a control run that changed only an unrelated prompt sentence, so it is the correction agent's run-to-run variance, not this change. * Unit tests: 24 in the locator module, 712 in the suite, pre-commit clean. *Superseded:* the first seam search anchored on the model's coarse column boundary and, on page 33, cut one column too far left; it was replaced by searching the boxes' overlap, which by construction holds one table's last column, the blank column and the other's first column. *Still open:* this is measured on one document. The stacked-pair and section-subheading cases the existing prompt wording protects have not been re-run on the review corpus. h2. Links Epic QUE-1 (Document Processing). QUE-371 (locator merge) folded into this ticket. Related: QUE-336 (declash reads locator column spans). Standards: see docs/ENGINEERING_STANDARDS.md