Redlining polskich umow i pism w .docx z natywnymi Word Track Changes - bez niszczenia formatowania OOXML...
Wrapper nad adeu (MIT, Dealfluence Oy) - dwukierunkowy konwerter miedzy .docx
a Markdown (CriticMarkup), z aplikacja zmian z powrotem do .docx. Robi to,
czego python-docx NIE potrafi: wstrzykuje natywne Word Track Changes
(w:ins/w:del) i komentarze, zachowujac formatowanie, fonty i marginesy.
Cala praca lokalnie (uvx, brak chmury). Silnik testowany na polskim .docx 2026-05-22 (extract/apply/sanitize - patrz THIRD_PARTY_INSPIRATIONS.md).
uv (jezeli brak: pip install uv). adeu pobiera sie samo przy pierwszym uzyciu.
🔴 WERSJA PRZYPIETA:
adeu==1.30.0(zmierzone 2026-08-24). Wszystkie komendy nizej wolajauvx --from adeu==1.30.0 adeu, nie goleuvx adeu. Powod nie jest kosmetyczny: adeu 1.31.0 (2026-08-03) przypiela sie twardo dofastmcp[apps]==4.0.0b1
- bety frameworka pod nowy spec MCP 2026-07-28 - i kazde wydanie od tamtej pory (do 3.0.0 z 2026-08-22) jest nieosiagalne dla
uvxbez--prerelease=allow. Goleuvx adeunie wybuchalo: cicho rozwiazywalo do 1.30.0 i konczylo exit 0, a SKILL.md deklarowal 1.7.5 - trzy rozne wersje w jednym skillu, zero sygnalu. To klasa cichej awarii - narzedzie konczy sie sukcesem, a uruchamia co innego, niz deklaruje dokumentacja. Ta sama regula pinu obowiazuje przy@firecrawl/anydoc.Podniesienie pinu = swiadoma decyzja, nie efekt uboczny - i dzis oznacza wejscie na bete FastMCP 4. Nie robimy tego przed freezem PATRON 2.0.0. Powierzchnia CLI 1.30.0 (zweryfikowana):
extract,init,diff,apply,accept-all,markup,sanitize,help.
Przed wykonaniem każdej operacji ustal tier i zastosuj regułę:
| Tier | Operacje | Reguła |
|---|---|---|
| R - Read-only | extract (czytanie .docx), skan_placeholder.py, memo_negocjacyjne.py (pisza tylko nowe pliki raportu/memo) |
Bez potwierdzenia. Wykonaj od razu. |
| M - Mutating | apply, diff, apply --live |
Pokaż użytkownikowi proponowane zmiany. Czekaj na potwierdzenie słowne. |
| D - Destructive | sanitize --accept-all (akceptuje wszystkie zmiany nieodwracalnie) |
Użytkownik musi wpisać dosłownie: "potwierdzam" zanim wykonasz. |
Redline pokazuje roznice miedzy baza a wersja docelowa. Baza musi byc plikiem edytowalnym od kontrahenta. Rekonstrukcja z PDF (pdftotext -> pandoc -> docx) wstrzykuje artefakty konwersji - podwojne spacje, inne lamanie akapitow, zgubione pogrubienia - ktore w Wordzie wygladaja identycznie jak nasze propozycje merytoryczne. Kontrahent nie odrozni jednych od drugich, a "akceptuj wszystkie" wciaga nasze artefakty do tresci umowy.
Masz tylko PDF? Popros o wersje edytowalna. Jesli naprawde nie da sie jej
zdobyc - dostarcz liste zmian jako osobne pismo z odeslaniami § ust. lit.,
NIE jako track changes na podrobionej bazie.
.odt / .doc -> .docx (adeu czyta tylko .docx):
soffice --headless --convert-to docx --outdir KATALOG PLIK.odt
Windows: "/c/Program Files/LibreOffice/program/soffice.exe". Pandoc do tej
konwersji nie nadaje sie - gubi formatowanie oryginalu, czyli wprowadza ten
sam szum co rekonstrukcja. Bramka routingu doc-intel-contract-pl kieruje .odt
na szczebel 1.5/anydoc, ale anydoc daje markdown - do redline ta sciezka nie
prowadzi.
Lekcja z praktyki: redline na bazie zrekonstruowanej z PDF daje w Wordzie szum konwersji nieodroznialny od propozycji merytorycznych.
uvx --from adeu==1.30.0 adeu extract umowa.docx -o umowa.md
Zwraca czysty Markdown (+ opcjonalny Semantic Appendix: defined terms, cross-references, typos). LLM pracuje na semantyce, nie na surowym OOXML - kilkukrotnie mniej tokenow niz wrzucenie pliku w postaci binarnej.
Format to lista obiektow modify (search-and-replace na tekscie, NIE na pozycji):
[
{
"type": "modify",
"target_text": "sad wlasciwy dla siedziby Zleceniodawcy",
"new_text": "Sad Arbitrazowy przy KIG w Warszawie",
"comment": "Proponuje arbitraz zamiast sadu powszechnego."
}
]
target_text musi byc jednoznaczny - adeu blokuje niejednoznaczne dopasowania
ZANIM dotkna pliku (bramka walidacji). Jezeli fragment wystepuje kilka razy,
doprecyzuj kontekst.
Kazdy obiekt modify moze dostac cztery dodatkowe pola. Sluza one memo
negocjacyjnemu (krok 2a), NIE trafiaja do adeu ani do drugiej strony:
[
{
"type": "modify",
"target_text": "kara umowna w wysokosci 20% wartosci umowy",
"new_text": "kara umowna w wysokosci 5% wartosci umowy, lacznie nie wiecej niz 10%",
"comment": "Proponujemy ograniczenie kary umownej.",
"tier": 1,
"rationale": "20% bez limitu lacznego to ekspozycja nieproporcjonalna do wartosci kontraktu.",
"walkaway": "Maksymalnie 10% z limitem lacznym 15%. Powyzej tego nie podpisujemy.",
"precedent": "Umowa z kontrahentem X (2025): 5% z limitem 10% przeszlo bez sporu."
}
]
| Pole | Znaczenie |
|---|---|
tier |
Priorytet 1-3 (framework nizej). |
rationale |
Uzasadnienie zmiany - argument do rozmowy, nie do dokumentu. |
walkaway |
Granica ustepstwa: co akceptujemy najdalej i kiedy odchodzimy od stolu. |
precedent |
Odwolanie do porownywalnej umowy lub wczesniejszej negocjacji. |
Rozdzial widocznosci jest twardy: comment widzi druga strona (komentarz w
track changes), rationale/walkaway/precedent zostaja w memo wewnetrznym.
| Tier | Kategoria | Regula negocjacyjna |
|---|---|---|
| 1 | Warunki brzegowe (non-starter) | Bez tej zmiany umowy nie podpisujemy. Pozycja walkaway obowiazkowa - memo bez niej nie przejdzie walidacji. |
| 2 | Istotne | Realne ryzyko prawne lub finansowe. Negocjuj, ustepstwo tylko za cos. |
| 3 | Pozadane | Poprawia nasza pozycje, ale mozna odpuscic bez straty. Waluta wymienna za tier 2. |
Brak tier = pozycja nieskategoryzowana; memo wypisze ja osobno jako zaleglosc
do klasyfikacji przez prawnika.
# sciezka scripts/ wzgledem katalogu tego skilla; z katalogu sprawy podaj pelna
python scripts/memo_negocjacyjne.py edits.json -o memo.md --tytul "Umowa serwisowa - kontrahent X"
python scripts/memo_negocjacyjne.py edits.json --adeu edits_adeu.json # kopia bez pol memo, do kroku 3
Generuje memo w Markdown: zmiany pogrupowane wg tierow, naglowek poufnosci,
licznik zmian per tier, przy kazdej pozycji rationale / walkaway / precedent.
Skrypt zero-dep (Python stdlib). Walidacja: tier spoza 1-3 lub tier 1 bez
walkaway = exit 1.
Granica governance: memo to draft do rozmowy, nie automat. Negocjacje
prowadzi czlowiek - skrypt przygotowuje mu mape pozycji, niczego nie wysyla
i nie rozstrzyga. Memo NIGDY nie idzie do drugiej strony (naglowek poufnosci
jest w szablonie na stale). Do adeu apply podawaj kopie z --adeu - pola
negocjacyjne nie moga trafic do pliku wymienianego z kontrahentem.
uvx --from adeu==1.30.0 adeu apply umowa.docx edits.json -o umowa_redline.docx --author "Kancelaria"
Daje umowa_redline.docx ze sledzonymi zmianami i komentarzami. Bez --author
adeu wpisuje nazwe konta systemowego biezacego uzytkownika - zawsze podawaj
--author jawnie, zeby nie wyciekla nazwa konta do dokumentu.
Zweryfikuj strukture niezaleznie od komunikatu narzedzia - exit 0 i "applied" przy kazdej pozycji nie dowodza, ze Word pokaze zmiany jako sledzone:
python -c "
import zipfile,re
x=zipfile.ZipFile('umowa_redline.docx').read('word/document.xml').decode('utf-8')
print('w:ins',len(re.findall(r'<w:ins ',x)),'| w:del',len(re.findall(r'<w:del ',x)),'| w:delText',len(re.findall(r'<w:delText',x)))
"
Usuniety tekst musi siedziec w w:delText, nie w w:t. Zero w:ins przy
"applied" w logu = zmiany poszly poza mechanizm track changes (tak zachowywal sie
drugi silnik, patrz sekcja o genoffice nizej).
# sciezka scripts/ wzgledem katalogu tego skilla, jak w kroku 2a
python scripts/skan_placeholder.py umowa_redline.docx # tez .md / .txt, wiele plikow naraz
python scripts/skan_placeholder.py umowa_redline.docx --json # raport maszynowy
Wykrywa niedokonczone pola: [...], [ ], [wstaw ...], [insert ...],
TBD, DO UZUPELNIENIA, $X / $___, ciagi podkreslen ___, placeholder
sygnatury NN/RR, puste pola dat (dnia __, [data]) i kwot ([kwota] oraz
kazde 0,00 zl - czesty artefakt niewypelnionego pola; jezeli kwota zerowa
jest zamierzona, odnotuj to przy przekazaniu). Raport plik:pozycja (paragraf w .docx,
linia w tekscie) + fragment kontekstu.
Zero zaleznosci (Python stdlib, .docx czytany przez zipfile). Exit 0 = czysto,
exit 1 = znaleziska. Kazde znalezisko blokuje wysylke - najpierw uzupelnij
pole albo swiadomie zostaw (np. kwota do wpisania przez klienta) i odnotuj to
przy przekazaniu draftu czlowiekowi.
uvx --from adeu==1.30.0 adeu sanitize umowa_redline.docx -o umowa_clean.docx --keep-markup --author "Kancelaria" --report
Usuwa: creator, last modified by, template, rsid, custom XML parts;
normalizuje timestampy; podmienia autorow track-changes/komentarzy na jedna nazwe.
--keep-markup zachowuje sledzone zmiany (do negocjacji); bez tego (--accept-all)
akceptuje wszystko i zwraca czysty dokument. Konczy werdyktem Result: CLEAN.
Zawsze rob sanitize przed wyslaniem pisma na zewnatrz. Word zostawia w metadanych nazwiska autorow, sciezki szablonow i historie edycji - to wyciek danych.
uvx --from adeu==1.30.0 adeu diff v1.docx v2.docx # wizualny diff dwoch wersji
uvx --from adeu==1.30.0 adeu apply --live edits.json # edycja zywego dokumentu w Word (Windows + MS Word)
sanitize czysci metadane Worda, ale NIE tresc. Do anonimizacji tresci (PESEL,
NIP, nazwiska w fleksji) najpierw przepusc tekst przez let-it-be, potem redline:
let-it-be -> pseudonimizuj tresc pisma (PII -> tokeny)adeu sanitize -> domkniecie metadanych przed wyslaniemlet-it-be = tresc (RODO art. 4 dane osobowe w tekscie); adeu sanitize = metadane pliku. Dwie rozne warstwy wycieku, obie trzeba domknac.
target_text na dopasowaniu tekstu - przy duplikatach trzeba kontekstu.vendor/docx-engine/ lezy DRUGI silnik (GenOffice, Apache-2.0), zweryfikowany
pomiarowo, ale NIE wpiety w zaden krok workflow. Workflow stoi w calosci na adeu.
Nie wolaj go z tego skilla, dopoki nie zapadnie decyzja opisana nizej.Silnik: adeu (c) 2026 Dealfluence Oy, licencja MIT.
Wzorce memo negocjacyjnego (pola tier/rationale/walkaway/precedent, grupowanie
wg tierow) i skanera placeholderow: evolsb/legal-redline-tools
(MIT). PATTERN, nie kod - oba skrypty napisane od zera pod polskie realia
(wzorce PL: DO UZUPELNIENIA, NN/RR, dnia __, kwoty w zl) i pod format
edits.json adeu zamiast ich wlasnego formatu redlines.
Silnik wendorowany (NIEAKTYWNY): vendor/docx-engine/ - packages/docx-engine
z genspark-ai/genoffice (Apache-2.0, commit 8f52328),
redystrybuowany razem z LICENSE i NOTICE zgodnie z sekcjami 4(b) i 4(d) tej licencji.
Szczegoly i snapshoty licencji: THIRD_PARTY_INSPIRATIONS.md.
W vendor/docx-engine/ lezy silnik round-tripu po bajtach z GenOffice (Apache-2.0),
zmierzony 2026-08-05 na pismach z maszyny WM. Nie zastepuje adeu i nie wolno
go wolac z tego workflow.
Pomiar sledzonych zmian (2026-08-05 wieczor, 71 pism) rozstrzygnal, ze pole
SaveBlock.revision NIE produkuje Word Track Changes: w:ins/w:del laduja na
poziomie w:body, tekst usuniety zostaje w w:t zamiast w:delText, a niezalezny
czytnik (adeu extract) nie widzi zmiany w zadnym z 71 plikow. Druga sciezka silnika
(Run.ins/Run.del) jest poprawna, ale nie daje przewagi nad adeu. Osobno zmierzono
patchTableCellTexts - odbudowuje komorke zamiast ja patchowac, wiec do edycji tabel
takze sie nie nadaje bez wlasnej warstwy ochronnej.
Komplet liczb i rekomendacja: THIRD_PARTY_INSPIRATIONS.md (sekcja o genoffice) oraz vendor/docx-engine/README.md. Decyzja o jakimkolwiek wpieciu nalezy do WM.
Te reguły obowiązują w każdym skillu tej wtyczki, także gdy sam skill milczy. Są skopiowane do każdego skilla, więc działają zarówno po instalacji całej wtyczki, jak i pojedynczego skilla.
Plugin obsługuje dokumenty: konwersję do Markdown, redlining .docx i anonimizację danych osobowych. Część operacji dotyka danych wrażliwych, więc reguła ochrony danych jest tu pierwsza.
let-it-be), zanim treść trafi do modelu. Dane osobowe nie powinny wychodzić do API. To zasada minimalizacji (RODO).Niektóre operacje są nieodwracalne (anonimizacja w trybie nieodwracalnym, zaakceptowanie wszystkich zmian w .docx). Skille oznaczają je jawnie - wykonuj je dopiero po potwierdzeniu przez człowieka.
Wynik to projekt. Nic nie zostaje wysłane ani złożone, zanim sprawdzi to uprawniony człowiek. Plugin przygotowuje plik, nie wykonuje aktu wysyłki.
Plugin daje narzędzia na dokumentach (konwersja, redline, anonimizacja, akta i chronologia). Nie ocenia treści prawnej. Weryfikację cytatu wobec źródła prawa daje plugin „fundament weryfikacyjny”; chronologia-stanowiska-pl sprawdza tylko, czy cytat stoi na wskazanej stronie akt.