Files
hermes-skills/skills/legal/contract-reviewer/references/pre-modified-file-detection.md
T

3.5 KiB

Pre-Modified File Detection (v1.x with Existing Tracked Changes)

Problem

Files arriving as "v1.x" or similar versions may already contain tracked changes from other parties (e.g., the counterparty's legal team). The review-rules state: "已有他人的修订模式保持原样不动,不接受也不拒绝,只叠加我们自己的审查修改."

Technical Impact

  1. python-docx paragraph.text only shows non-tracked-change text (skips content inside w:ins elements), so it does NOT reflect the "accepted state" of the document
  2. ContractEditor.tracked_replace searches through ALL text including w:ins content — search strings must match the accepted state
  3. ContractEditor.tracked_replace may fail when the target text spans across or is inside an existing w:ins from another author (lxml parent-child mismatch)

Detection Procedure

from lxml import etree
ns = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}

# 1. Detect existing tracked changes and identify authors
ins_els = editor.body.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}ins')
authors = set()
for ins in ins_els:
    author = ins.get('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}author', '')
    if author:
        authors.add(author)
# If authors contains names other than 'WB', the file is pre-modified

Reading the Accepted State

def get_para_accepted_text(p):
    """Get paragraph text as it would appear with all changes accepted."""
    text = ''
    W = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
    for t in p.iter(f'{{{W}}}t'):
        if t.text:
            parent = t.getparent()
            in_del = False
            while parent is not None:
                if parent.tag == f'{{{W}}}del':
                    in_del = True
                    break
                parent = parent.getparent()
            if not in_del:
                text += t.text
    return text

Workflow When Pre-Modified File Detected

  1. First pass: Read accepted state of all key paragraphs to understand current document content
  2. Compare accepted state vs what python-docx .paragraphs[].text shows to identify what's been changed
  3. Assess which of our review issues have already been addressed by the existing modifications
  4. Only add our own changes for issues NOT already covered
  5. If tracked_replace fails on text inside another author's w:ins: the text is already part of someone else's tracked change. Options:
    • Skip if the existing change already addresses our concern
    • Use direct XML manipulation to add our w:del + w:ins around the problematic text (complex, error-prone)
    • Note it as "already addressed by [author]" in review notes

2026-07-06 Case Study (健康云服务费-赵巷v1.2)

  • File arrived with tracked changes from authors: 祺帆, 社区, 俊玮 吴
  • python-docx showed P59 as "2026年1月20日" but accepted state was "2026年11月20日" (already fixed by 祺帆)
  • P26 (1.4 侵权条款) already had robust language added by 祺帆
  • P109 (7.4) already had comprehensive损失赔偿 language added by existing changes
  • P115 (8.2) had double period due to 祺帆's ins adding "向甲方所在地法院提起诉讼。" after original "则。" — required manual XML w:del to fix the trailing original period
  • P118 (9.1) already had 转包连带责任 language added

Key lesson: Without reading accepted state first, we would have duplicated 5+ modifications already made by other parties.