Full-text manual diff R1.03 -> R1.05 (catch unlisted R1.04 edits)

tools/manual_diff.py: word-level diff of one manual between two doc folders.
version-differences.md: the 20 manuals whose revision tables list only
contact information were diffed; E10 and E30 have real content changes,
the rest wording only. CLAUDE.md: re-checks use the full diff.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Clio Liu 2026-10-08 18:35:39 +11:00
parent e90ad790a2
commit af9a1bbe29
3 changed files with 97 additions and 4 deletions

View file

@ -60,3 +60,7 @@ The R1.05 test server is shared with other projects. Never disturb their work th
read-only checks unless the user approves a change, never restart CI Server, never write to other read-only checks unless the user approves a change, never restart CI Server, never write to other
projects' records or to live plant values, and remove anything you put on the server. projects' records or to live plant values, and remove anything you put on the server.
Fixes that also apply to R1.03 can be cherry-picked onto branch `r1.03`. Fixes that also apply to R1.03 can be cherry-picked onto branch `r1.03`.
When re-checking a manual for R1.05, compare its full text with the R1.03 edition
(`tools/manual_diff.py`), not just the revision table or release notes: R1.04 changes are
often not listed there.

View file

@ -67,10 +67,28 @@ the R1.04 and R1.05 revision tables.
| IM 36K10G10 Tutorial | R1.04 §9.2, ch. 14 new. R1.05 ch. 14 extended, ch. 15 new | `knowledge/manuals/IM36K10G10-01EN.md` | | IM 36K10G10 Tutorial | R1.04 §9.2, ch. 14 new. R1.05 ch. 14 extended, ch. 15 new | `knowledge/manuals/IM36K10G10-01EN.md` |
| IM 36K10L55 Exchange Tool Engineering | R1.04: upgrade scenario for CI Exchange for CENTUM VP. R1.05 §2.7: HIS-TSE connection options | `knowledge/manuals/IM36K10L55-01EN.md` | | IM 36K10L55 Exchange Tool Engineering | R1.04: upgrade scenario for CI Exchange for CENTUM VP. R1.05 §2.7: HIS-TSE connection options | `knowledge/manuals/IM36K10L55-01EN.md` |
**No content change** (only contact information or wording): C20, C30, E10, E30, J20, J40, **Revision table lists only contact information:** C20, C30, E10, E30, J20, J40, L10, L15,
L10, L15, L20, L25, L30, L35, L36, L40, P10, P11, P20, P30, R20, R40. Skills based only on L20, L25, L30, L35, L36, L40, P10, P11, P20, P30, R20, R40. The revision tables do not list
these manuals still need a quick re-test on R1.05 (installed files may differ), but their every R1.04 edit, so each of these was also compared word by word with its R1.03 edition
content is expected to hold. (`tools/manual_diff.py`, 2026-10-08). Result:
| Manual | Unlisted changes found by the text diff |
|---|---|
| E10 Excel Add-in | Item search: new description of the *Item Filter* / *Description Filter* boxes and wildcards (`*` default; both filters combine with AND); a CI Portal SSL note moved |
| E30 Alarm System Performance Analysis | KPI grid: the KPI charts now have labels (*In Time*, *Too Late*, *Not Ackn*, *Nuisance*) |
| L30 BUS Service | `durwfp` return value reworded (1 = process attached/running, 0 = otherwise); same meaning |
| P11 Java class language | §10.2 methods reworded; same meaning |
| P20 RQL | Footer `<position>` sentence split in two; same meaning |
| L40, R20, R40, C30, L35, J40 | Spacing, punctuation, titles only |
| C20, J20, L10, L15, L20, L25, L36, P10, P30 | None |
Skills based only on these manuals still need a quick re-test on R1.05 (installed files may
differ), but their content is expected to hold. The E10 and E30 changes go into the
`reporting` and `alarm-management` re-checks.
**Method for every manual re-check:** do not rely on the revision table or the release notes.
Run `python tools/manual_diff.py <R1.03 doc\EN> <R1.05 doc\EN> <IM>` and review every change,
including those made in R1.04.
## 3. Re-check plan ## 3. Re-check plan

71
tools/manual_diff.py Normal file
View file

@ -0,0 +1,71 @@
"""Word-level diff of one CI Server manual between two releases (e.g. R1.03 and R1.05).
Catches changes the revision table does not mention (for example R1.04 edits listed only as
"Added contact information"). Needs `pdftotext` (Poppler / Git for Windows) on PATH.
Usage:
python tools/manual_diff.py <old_pdf_dir> <new_pdf_dir> IM36K10L40-01EN [more IMs] [-o out_dir]
Prints one block per change: [replace]/[insert]/[delete] with old (-) and new (+) words.
Page footers, edition lines and dates are removed first, so only text changes remain.
Writes nothing into the repo; with -o it saves <IM>.diff.txt files in out_dir.
"""
import difflib
import os
import re
import subprocess
import sys
import tempfile
NOISE = re.compile(
r'IM ?36K\w+-01EN( \d+\w\w Edition)?( : [A-Za-z]+\.? ?\d+, ?\d+-00)?'
r'|\d+(st|nd|rd|th) Edition|Toc-\d+|Rev-\d+|App\.\d+-\d+|\b\d+-\d+\b')
def words(pdf):
with tempfile.TemporaryDirectory() as d:
out = os.path.join(d, 'm.txt')
subprocess.run(['pdftotext', pdf, out], check=True)
text = open(out, encoding='utf-8', errors='replace').read()
return NOISE.sub(' ', text).split()
def diff(old_pdf, new_pdf):
a, b = words(old_pdf), words(new_pdf)
sm = difflib.SequenceMatcher(None, a, b, autojunk=False)
lines = []
for op, a1, a2, b1, b2 in sm.get_opcodes():
if op == 'equal':
continue
lines.append('[%s] at word %d\n - %s\n + %s' % (
op, a1, ' '.join(a[a1:a2]), ' '.join(b[b1:b2])))
return lines
def main(argv):
out_dir = None
if '-o' in argv:
i = argv.index('-o')
out_dir = argv[i + 1]
del argv[i:i + 2]
if len(argv) < 3:
sys.exit(__doc__)
old_dir, new_dir, ims = argv[0], argv[1], argv[2:]
for im in ims:
old_pdf = os.path.join(old_dir, im + '.pdf')
new_pdf = os.path.join(new_dir, im + '.pdf')
if not os.path.exists(old_pdf):
print('=====', im, ': new manual (no old edition)')
continue
lines = diff(old_pdf, new_pdf)
report = '\n'.join(lines)
print('=====', im, ':', len(lines), 'changes')
if out_dir:
os.makedirs(out_dir, exist_ok=True)
open(os.path.join(out_dir, im + '.diff.txt'), 'w', encoding='utf-8').write(report)
else:
print(report)
if __name__ == '__main__':
main(sys.argv[1:])