# WB自加手动编号与前序自动编号撞号 — 诊断与修复

实战来源：端午节福利品采购合同（2026-06-16）。Maggie："转包责任应该是7，上一个编号是6。手动修复上传。"

## 场景识别
- 我们(WB)用 `w:ins` 新增了若干尾部条款（转包/违约/争议…），编号是**手动文字**写在 run 文本开头（"6、转包限制…"）。
- 紧邻的前一条是**原文自带的自动编号**条款（pPr 有 `<w:numPr>`，编号由 numbering.xml 的 `<w:start>` 生成，文字里**没有**编号）。
- 二者渲染数字撞号：自动编号末值=6，我方手动也从6起 → 接受修订后出现两个6。

## 诊断步骤（顺序不可颠倒，OnlyOffice为准）
1. 取交付版(任务交付/【修】…docx)+原文(待审查/…doc)，各用 `scripts/onlyoffice-render.sh` 渲染 PDF。
2. `pdftotext -layout x.pdf - | grep -E "^\s*\f?[0-9]+、"` 数出**完整可见编号链**（注意"5、结算"可能挤在第4条段内、自动编号条款文字里无编号——肉眼易漏）。
3. 读 numbering.xml 确认前序自动条款的 numId→abstractNumId→lvl0 的 `start` 值，得知它渲染成几（端午节：numId=3, start=6 →"6"）。
4. 读 document.xml，确认我方各条是 `w:ins author=WB`，编号"6、""7、""8、"在 ins 首个 w:r 的 w:t 开头。

## 判定
前序自动编号末值 = N → 我方手动编号应从 **N+1** 起顺延。端午节：售后=6 → 转包=7、违约=8、争议=9。
**有Maggie明确指示 + 完整核对 → 执行。** 不要因"擅改编号"的旧教训而拒绝正确修复（区别在：当初错在没核对没确认，不在方向）。

## 修复（纯 zipfile+lxml，最干净）
只改 ins 首个 w:t 的编号前缀，不拆 run、不碰 rPr、不转 numbering：

```python
import zipfile, os
from lxml import etree
W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
src='deliver.docx'; out='deliver_FIXED.docx'
root = etree.fromstring(zipfile.ZipFile(src).read('word/document.xml'))
paras = root.find(f'{W}body').findall(f'{W}p')
changes = {19:('6、','7、','转包'), 20:('7、','8、','违约'), 21:('8、','9、','争议')}  # 段索引→(旧号,新号,关键词)
for idx,(old,new,kw) in changes.items():
    ins = paras[idx].find(f'{W}ins')
    assert ins is not None and ins.get(f'{W}author')=='WB', f"段{idx}非WB的ins!"   # 铁律：绝不改他人ins
    t = ins.find(f'{W}r').find(f'{W}t')
    assert t.text.startswith(old) and kw in t.text[:6]
    t.text = new + t.text[len(old):]
new_doc = etree.tostring(root, xml_declaration=True, encoding='UTF-8', standalone=True)
tmp=out+'.tmp'
with zipfile.ZipFile(src) as zin, zipfile.ZipFile(tmp,'w',zipfile.ZIP_DEFLATED) as zout:
    for it in zin.infolist():
        zout.writestr(it, new_doc if it.filename=='word/document.xml' else zin.read(it.filename))
os.replace(tmp,out)
```

## 交付前四查（vision不可用时的强制验证，缺一不可）
1. **逐段markup diff vs交付源**：提取两版每个 w:p 的 markup 文本（含 delText），断言**只有目标N段不同**、其余全部零改动（端午节33段只动3段）。
2. **OnlyOffice渲染PDF编号链**：pdftotext 数出 1,2,3,4,(5),6,7,8,9 连续无双号。
3. **INS run rPr 改前==改后**：`etree.tostring(rpr)` 逐段比对，确认字体/字号一字未动。
4. **python-docx 能打开** + 接受修订后（去 del、解包 ins）编号链连续，证明 XML 合法、WB 修订标记完整保留。

## 交付（Editor到此为止则交deliverer；本例Maggie直接要"上传"故一并做）
- 文件名**一字不动**：覆盖 `Doro合同审查任务/任务交付/【修】<原名>.docx`。
- `docker cp` 进 nextcloud-nextcloud-1 → `chown www-data` → `occ files:scan --path=...`。
- 落盘 md5 == 修复版 md5 才算成功。
- 清 OnlyOffice 缓存：`docker exec nextcloud-onlyoffice-1 rm -rf .../App_Data/cache/files/*`。
- 已 pass 登记过的合同仅编号订正：tracker/xlsx 记录不变动。
