| name | python-docx-editor |
|---|---|
| description | Arbeiten mit Word-Dokumenten (.docx) über die Python-Bibliothek python-docx: Text extrahieren, Dokumente erstellen/ändern, Tabellen lesen, einfache Ersetzungen und Struktur-Checks. Use when ein Agent DOCX-Dateien automatisiert verarbeiten soll oder reproduzierbare DOCX-Operationen per Script braucht. |
Nutze diesen Skill für wiederholbare DOCX-Aufgaben mit python-docx.
- Stelle sicher, dass
python-docxverfügbar ist.- Standard-Installation:
py -3 -m pip install python-docx
- Optional für Entwicklung gegen lokalen Clone:
py -3 -m pip install -e vendor/python-docx
- Standard-Installation:
- Prüfe, ob das Dokument Projektbezug hat (Titel, Projektnamen, Akronyme, Partnerlisten, WP-Struktur).
- Wenn Projektbezug vorliegt: lade vor Text-Transformationen die passende Projektreferenz aus
memory/references/projects/<project>/...(falls vorhanden)- und nutze sie als Stil-/Terminologie-Quelle (Begriffe, Rollen, formale Benennungen, Tonalität).
- Nutze für Standardaufgaben
scripts/docx_ops.py. - Für generische Tabellenbefüllung auf Zellebene nutze
scripts/fill_docx_table_from_json.py(layout: "cell-map"). - Für Spezialfälle lade
references/python-docx-quickref.mdund implementiere gezielt.
- Text extrahieren:
py -3 scripts/docx_ops.py text --in <datei.docx>
- Statistik (JSON):
py -3 scripts/docx_ops.py stats --in <datei.docx>
- Einfache Ersetzung in Absätzen + Tabellen:
py -3 scripts/docx_ops.py replace --in <in.docx> --out <out.docx> --find "Alt" --replace "Neu"
- LLM-freundliche Extraktion (v2, hierarchisch nach Sections/Content):
py -3 scripts/extract_docx_for_llm.py --in <in.docx> --out <structure.v2.json>
- Optionaler RAG-Output (v1, flat blocks+chunks):
py -3 scripts/extract_docx_for_llm.py --in <in.docx> --out <structure.v2.json> --rag-output <rag.v1.json>
- Gezieltes Minimal-Writeback via Patch:
py -3 scripts/apply_docx_patch.py --in <in.docx> --out <out.docx> --patch <patch.json>
- Generische Tabellenbefüllung aus JSON-Spec (cell-map, zellgenau):
py -3 scripts/fill_docx_table_from_json.py --in <in.docx> --out <out.docx> --spec <cell-map.json>
- Section-/DOCX-Preview für Review:
py -3 scripts/docx_preview.py v2-section --json <structure.v2.json> --title "<Section Title>"py -3 scripts/docx_preview.py docx-around --in <out.docx> --contains "<Heading Text>" --lines 25
Nutze für Überarbeitungen standardmäßig diesen Ablauf (kein manuelles Range-Basteln im Normalfall):
- Extrahieren (v2)
py -3 scripts/extract_docx_for_llm.py --in <in.docx> --out <structure.v2.json>
- Kontext laden
- Bei Projektbezug zusätzlich relevante Infos aus
memory/references/projects/<project>/...laden (Terminologie, Rollen, Zielgruppen, Ton).
- Bei Projektbezug zusätzlich relevante Infos aus
- Edit-Plan erzeugen (LLM)
- LLM erstellt einen Patch-Plan mit
ops[]fürapply_docx_patch.py. - Für größere Umformungen immer
replace_paragraph_rangeverwenden. replace_textnur für kleine, lokale Korrekturen.
- LLM erstellt einen Patch-Plan mit
- Semantik-Check vor Apply
- Bei Listen/Abschnitts-Rewrites: Original-Claims erfassen und im Zieltext wiederfinden.
- Keine inhaltstragenden Punkte stillschweigend entfernen.
- Apply + Review
py -3 scripts/apply_docx_patch.py --in <in.docx> --out <out.docx> --patch <patch.json>results[].removed_previewprüfen (bei Range-Edits).
- Feinschliff
- Bei Bedarf zweiten, kleinen Patchlauf für Stil-/Rhythmuskorrektur.
Der Workflow gilt nicht nur für Listen, sondern allgemein für:
- Abschnittsverdichtung (zu lang/zu redundant)
- Abschnittsausbau (zu knapp)
- Umstrukturierung (Listen ↔ Fließtext)
- Terminologie-/Stilkonsistenz über das Dokument
Bei Abschnittsverbesserungen:
- Identifiziere den Zielabschnitt in v2 (
Heading+ zugehöriger Content-Bereich). - Entscheide Modus explizit:
narrative(Fließtext)hybrid(Fließtext + wenige kompakte Punkte)preserve-list(Liste bleibt, sprachlich verbessert)
- Erzeuge einen zusammenhängenden Patch pro semantischem Block (Range-basiert statt atomisiert).
- Dokumentkontext-Regel (verbindlich): Vor jedem Kapitel-/Teilpatch kurz den Kontext des Gesamtdokuments prüfen (Ziel, Terminologie, wiederkehrende Struktur, Nachbarkapitel), damit lokale Edits global konsistent bleiben.
- Kapitelregel (verbindlich): Bei Patches auf Teilbereiche immer den gesamten Kapitelkontext (
Heading+ alle zugehörigen Content-Absätze bis vor das nächste gleichrangige Heading) prüfen, bevorstart_block_id/end_block_idfestgelegt werden. - Lead-in-Regel (verbindlich): Bei Listen→Fließtext den unmittelbar davorstehenden Lead-in-Absatz (oft kurzer Satz mit
:) mitprüfen und in die Range aufnehmen, wenn er semantisch im neuen Fließtext aufgeht; keine doppelten Einleitungen stehenlassen. - Halte Claim-Abdeckung hoch: Kerninhalte bleiben erhalten, nur Redundanz wird reduziert.
Pflichtparameter:
--in(Pfad zu bestehender.docx)--out(Zielpfad)
Optionale Parameter:
--table-row-batch(Integer, Default:25; bei<= 0wird die ganze Tabelle als ein Block/Part behandelt)--rag-output(Pfad für optionalen v1-RAG-Output)--max-chars(Integer, Default:4000, nur für--rag-output, intern mindestens500)--overlap-blocks(Integer, Default:1, nur für--rag-output, intern mindestens0)
Validierung:
--inmuss existieren--inmuss.docx-Endung haben- Zielordner von
--outwird bei Bedarf erstellt
Formales JSON-Schema (CLI-Äquivalent):
{
"type": "object",
"required": ["in", "out"],
"properties": {
"in": {
"type": "string",
"description": "Pfad zu bestehender .docx-Datei"
},
"out": {
"type": "string",
"description": "Ausgabepfad für v2-JSON"
},
"rag_output": {
"type": "string",
"description": "Optionaler Ausgabepfad für v1 (RAG blocks+chunks)"
},
"max_chars": {
"type": "integer",
"default": 4000,
"minimum": 500,
"description": "Script erzwingt intern mindestens 500"
},
"overlap_blocks": {
"type": "integer",
"default": 1,
"minimum": 0,
"description": "Script erzwingt intern mindestens 0"
},
"table_row_batch": {
"type": "integer",
"default": 25,
"description": "<=0 bedeutet ganze Tabelle als ein Block"
}
},
"additionalProperties": false
}Der Standard-Output ist hierarchisch und gruppiert Inhalte nach Sections (Heading-basiert).
{
"type": "object",
"required": ["schema", "source", "stats", "document"],
"properties": {
"schema": { "const": "docx-structure.v2" },
"source": { "type": "string" },
"stats": {
"type": "object",
"required": ["sections", "content", "headers", "footers", "pre_heading_nodes"],
"properties": {
"sections": { "type": "integer", "minimum": 0 },
"content": {
"type": "object",
"required": ["paragraph", "list_item", "table"],
"properties": {
"paragraph": { "type": "integer", "minimum": 0 },
"list_item": { "type": "integer", "minimum": 0 },
"table": { "type": "integer", "minimum": 0 }
}
},
"headers": { "type": "integer", "minimum": 0 },
"footers": { "type": "integer", "minimum": 0 },
"pre_heading_nodes": { "type": "integer", "minimum": 0 }
}
},
"document": {
"type": "object",
"required": ["pre_heading", "sections", "headers", "footers"],
"properties": {
"pre_heading": { "type": "array" },
"sections": { "type": "array" },
"headers": { "type": "array" },
"footers": { "type": "array" }
}
}
}
}document.sections[] Knotenstruktur:
level,title,block_id,stylecontent[]mit typisierten Nodes:paragraphlist_item(optional mitlist: {num_id, level})table(mitparts[], je Part eigeneblock_id)
children[]für Unter-Sections
Hinweise zu IDs:
- Absätze/Headings:
p_<n> - Tabellenbereiche:
t_<tableIndex>_r<start>_<end> - Header:
h_<n> - Footer:
f_<n>
Wenn --rag-output <pfad> gesetzt ist, wird zusätzlich ein v1-JSON mit blocks[] und chunks[] erzeugt (kompatibel für Retrieval-Pipelines).
Pflichtparameter:
--in(Pfad zu bestehender.docx)--out(Zielpfad für neue.docx)--spec(Pfad zu JSON-Spec)
Spec-JSON (formal, generischer Modus cell-map):
{
"type": "object",
"required": ["table_index", "cells"],
"properties": {
"table_index": { "type": "integer", "minimum": 1 },
"layout": { "type": "string", "enum": ["cell-map"], "default": "cell-map" },
"cells": {
"type": "array",
"items": {
"type": "object",
"required": ["row", "col"],
"properties": {
"row": { "type": "integer", "minimum": 1 },
"col": { "type": "integer", "minimum": 1 },
"text": { "type": "string", "default": "" },
"clear_first": { "type": "boolean", "default": false },
"mode": { "type": "string", "enum": ["replace", "append"], "default": "replace" }
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}Semantik:
table_index,row,colsind 1-basiert.mode: "replace"setzt den Zellinhalt direkt auftext.mode: "append"hängttextan den bestehenden Zellinhalt an.clear_first: trueleert die Zielzelle vorreplace/append.- Bei ungültigen Zellkoordinaten, fehlender Tabelle oder falschem Schema bricht das Script mit klarer Fehlermeldung ab.
Pflichtparameter:
--in(Pfad zu bestehender.docx)--out(Zielpfad für neue.docx)--patch(Pfad zu Patch-JSON)
Aktuell unterstützte Operationen:
replace_textset_paragraphdelete_paragraphreplace_paragraph_rangereplace_paragraph_range_markdown
Patch-Datei-Schema:
{
"type": "object",
"required": ["ops"],
"properties": {
"ops": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"required": ["op", "block_id", "find", "replace"],
"properties": {
"op": { "const": "replace_text" },
"block_id": { "type": "string" },
"find": { "type": "string", "minLength": 1 },
"replace": { "type": "string" },
"expected_matches": { "type": "integer", "minimum": 0, "default": 1 }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["op", "block_id"],
"properties": {
"op": { "const": "set_paragraph" },
"block_id": { "type": "string" },
"text": { "type": "string" },
"runs": {
"type": "array",
"items": {
"type": "object",
"required": ["text"],
"properties": {
"text": { "type": "string" },
"bold": { "type": "boolean" },
"italic": { "type": "boolean" },
"code": { "type": "boolean" },
"link": { "type": "string" }
}
}
},
"markdown": { "type": "boolean", "default": false },
"style": { "type": "string" },
"expected_contains": { "type": "string" },
"clear_list_format": { "type": "boolean", "default": true }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["op", "block_id"],
"properties": {
"op": { "const": "delete_paragraph" },
"block_id": { "type": "string" },
"expected_contains": { "type": "string" }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["op", "start_block_id", "end_block_id", "new_paragraphs"],
"properties": {
"op": { "const": "replace_paragraph_range" },
"start_block_id": { "type": "string", "pattern": "^p_[0-9]+$" },
"end_block_id": { "type": "string", "pattern": "^p_[0-9]+$" },
"expected_start_contains": { "type": "string" },
"expected_end_contains": { "type": "string" },
"allow_headings": { "type": "boolean", "default": false },
"new_paragraphs": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"text": { "type": "string" },
"runs": {
"type": "array",
"items": {
"type": "object",
"required": ["text"],
"properties": {
"text": { "type": "string" },
"bold": { "type": "boolean" },
"italic": { "type": "boolean" },
"code": { "type": "boolean" },
"link": { "type": "string" }
}
}
},
"markdown": { "type": "boolean", "default": false },
"style": { "type": "string" }
},
"additionalProperties": false
}
}
},
"additionalProperties": false
},
{
"type": "object",
"required": ["op", "start_block_id", "end_block_id", "markdown"],
"properties": {
"op": { "const": "replace_paragraph_range_markdown" },
"start_block_id": { "type": "string", "pattern": "^p_[0-9]+$" },
"end_block_id": { "type": "string", "pattern": "^p_[0-9]+$" },
"expected_start_contains": { "type": "string" },
"expected_end_contains": { "type": "string" },
"allow_headings": { "type": "boolean", "default": false },
"markdown": { "type": "string" }
},
"additionalProperties": false
}
]
}
}
},
"additionalProperties": false
}Zusatzschema für Listen→Fließtext-Refactoring (replace_paragraph_range):
{
"op": "replace_paragraph_range",
"start_block_id": "p_27",
"end_block_id": "p_30",
"expected_start_contains": "Develops and maintains",
"expected_end_contains": "Define QM-Indicators",
"new_paragraphs": [
{ "text": "Neuer Fließtext ...", "style": "Normal" },
{ "text": "Optionaler kompakter Punkt ...", "style": "Compact" }
]
}Regeln für replace_paragraph_range:
- Ersetzt den gesamten Absatzbereich (
p_*von start bis end, inkl.) atomar. - Fügt
new_paragraphsein und entfernt den alten Bereich vollständig (keine leeren Rest-Bullets). - Schützt Headings standardmäßig: wenn der Bereich Heading-Absätze enthält, bricht die Operation ab (nur mit
allow_headings: trueüberschreibbar). - Bei mehreren Range-Operationen im selben Patch von unten nach oben (höhere
p_*zuerst) arbeiten, damit IDs stabil bleiben.
Markdown→Word Support:
- Inline (
markdown:true):*kursiv*,**fett**,***fett+kursiv***,`code`,[Text](https://...) - Block-Level (
replace_paragraph_range_markdown): Headings (#), Listen (-/1.), Zitate (>), Trennlinien (---), Tabellen (|...|)
Qualitätsregeln für Listen→Fließtext:
- Behandle zusammenhängende Listen als eine semantische Einheit (nicht Punkt-für-Punkt umformulieren).
- Führe vor dem Patch eine Claim-Liste der Originalpunkte (1 Claim je Bullet).
- Stelle sicher, dass jeder Claim im neuen Text wieder auftaucht (Inhaltserhalt statt freier Verdichtung).
- Vermeide „Lonely bullet remnants": wenn nur 1 Punkt übrig bleibt, in Fließtext integrieren.
- Bevorzuge bei operativen Abschnitten aktive Verben und konkrete Zuständigkeiten; keine unnötige Abstraktion.
- Nutze
removed_previewim Patch-Resultat als Pflicht-Review vor finaler Freigabe.
apply_docx_patch.py bricht hart mit Fehler ab, wenn:
block_idnicht gefunden wirdfindleer istexpected_matchesnicht der tatsächlichen Trefferanzahl entspricht- ein Treffer über Run-Grenzen geht (kein stilles Full-Rewrite)
- eine unbekannte
opverwendet wird
Erfolgsoutput (stdout) ist JSON:
in,out,ops,results[]- pro Operation:
op,block_id,matches,changes,status
Wenn der User „Abschnitt verbessern/überarbeiten“ sagt, soll der Agent intern diesen Plan erzwingen:
target_section: exakter Heading-Titelmode:narrative | hybrid | preserve-listintent:shorten | expand | clarify | harmonize-stylemust_keep: Liste nicht verlierbarer Kernpunkte/Claimsproject_context_used: welche Datei ausmemory/references/projects/...verwendet wurde (falls vorhanden)style_profile: gewünschter Stil (explizit vom User oder aus Kontext abgeleitet)
Stil-Klärung (verbindlich):
- Wenn Stil/Tonalität aus Prompt + Dokumentkontext nicht klar ableitbar ist, vor dem Patch den User kurz nach dem gewünschten Stil fragen.
- Erst nach Stil-Klärung den finalen Patch erzeugen.
Default-Style (wenn User keinen eigenen Stil vorgibt und Kontext konsistent ist):
- Write in a natural, fluent, and precise style.
- Prefer active voice, clear structure, and concise phrasing.
- Vary sentence length and rhythm without sacrificing coherence.
- Use less common words only when they add technical or conceptual precision, not decorative flair.
- Maintain grammatical accuracy, logical clarity, and stylistic consistency.
- Increase linguistic diversity (“perplexity” and “burstiness”) only insofar as it improves readability and nuance.
Ausgabeformat vor Patch-Anwendung (kurz):
- Claims alt (stichwortartig)
- Claims neu (Mapping alt→neu)
- Style profile (1-2 Zeilen)
- Ops-Plan (
replace_paragraph_rangebevorzugt)
Patch nur anwenden, wenn kein Kernclaim ungemappt bleibt.
- Umgebung prüfen:
py -3 -m pip install python-docx
- Syntax prüfen:
py -3 -m py_compile scripts/extract_docx_for_llm.py scripts/apply_docx_patch.py scripts/fill_docx_table_from_json.py scripts/selftest.py
- End-to-End-Selbsttest (ohne Repo-Artefakte):
py -3 scripts/selftest.py
Vor Veröffentlichung sicherstellen:
-
scripts/selftest.pyläuft lokal grün - v2-Output (
docx-structure.v2) bleibt default - Optionaler v1-RAG-Output funktioniert via
--rag-output -
apply_docx_patch.pyvalidiertexpected_matchesund blockiert Run-Grenzkonflikte -
SKILL.md-Schemas entsprechen dem tatsächlichen CLI-Verhalten - Keine Testartefakte versehentlich versioniert (lokale Dateien bleiben in
Tests/)
- v2 default:
extract_docx_for_llm.py --out ...erzeugtdocx-structure.v2. - v1 optional: Nur bei gesetztem
--rag-outputwird zusätzlichdocx-llm-chunks.v1erzeugt. - Patch-Kompatibilität:
apply_docx_patch.pynutzt die gleiche Paragraph-ID-Logik wie der Extractor (nur nicht-leere Body-Paragraphen erhaltenp_<n>).
replaceindocx_ops.pyist bewusst einfach und kann Formatierung beeinflussen.apply_docx_patch.pyist minimal-sicher: bei Run-Grenzkonflikten wird verweigert statt riskant umgeschrieben.- Für formatkritische Änderungen auf Run-Ebene arbeiten statt
paragraph.textkomplett neu zu setzen.