# Split-Run Numbering in docx XML

## Problem
Contract numbering like `（5）` is often split across multiple `<w:r>` runs in the XML:
```xml
<w:r><w:t>（</w:t></w:r>
<w:r><w:t>5</w:t></w:r>
<w:r><w:t>）委托方</w:t></w:r>
```

A naive `tracked_replace("（5）", "（6）")` searching for the complete string in a single `<w:t>` will **silently fail** — no match, no error, no renumbering.

## Solution: Multi-run concatenation + split

### Algorithm
```python
def tracked_replace_split_number(p, old_num, new_num):
    """Handle （old_num） spread across multiple runs."""
    target = f'（{old_num}）'
    new_target = f'（{new_num}）'
    
    # 1. Collect all plain runs (not inside w:ins or w:del)
    plain_runs = [(index, run, text) for each child of p]
    
    # 2. Slide a window: concatenate adjacent run texts until target is found
    for start in range(len(plain_runs)):
        concat = ""
        for end in range(start, start+4):  # max 4 runs for a number
            concat += plain_runs[end].text
            if target in concat:
                # Found! Extract before/after text around the number
                runs_to_wrap = plain_runs[start:end+1]
                # ...proceed to replace
    
    # 3. Remove original runs, insert:
    #    - [before_run if text before number]
    #    - DEL element with delText=target
    #    - INS element with t=new_target  
    #    - [after_run if text after number, e.g. "委托方"]
    
    # 4. Set rsid attributes: rsidDel on DEL runs, rsidR on INS runs
```

### Critical: Process order
**Always renumber from bottom to top** (last paragraph first) to avoid index shifting:
```python
# CORRECT
renumber = [(P113, '10', '11'), (P112, '9', '10'), (P111, '7', '8')]

# WRONG - P112 was already renumbered when we get to it
renumber = [(P111, '7', '8'), (P112, '9', '10'), (P113, '10', '11')]
```

### Edge cases encountered (2026-06-08)
- `（` + `10）` (two runs, not three) — the closing `）` merged with the digit
- `（` + `5` + `）委托方` — closing `）` merged with following text, must split run to preserve "委托方"
- Copy `w:rPr` from original runs to all new DEL/INS runs to preserve font/size

## Lesson
This was the root cause of a terminal review failure where 3 new clauses were inserted without numbering, and subsequent numbering was not renumbered. The `tracked_replace` function matched nothing because it expected `（5）` as a single text node.
