Full SKILL.md
Style Extractor
Learn style preferences from the manual edits you make to a generated deck. Diffs the original generated .pptx against the hand-edited copy, resolving inherited styling against the template master so real changes (not inheritance noise) surface, then merges them into a confidence-weighted ledger and routes recurring fixes back to the template. Trigger on "note the style changes I made", "learn from my edits to this deck", "update the deck style rules", or after the user hand-corrects a generated deck.
Captures revealed style preferences — what you actually changed in an edited
deck — and accumulates them into a ledger. The edited file is ground truth, so
there is no judgement about whether an edit was "good"; the only judgement is
whether a change is general (recurs across decks) or a one-off, resolved by
counting recurrences over time. It is the second half of the loop that begins
with its sibling deck-generator.
Preconditions — refuse without both files
original— the deck exactly as generated, before editing.edited— your manually corrected copy.
If only the edited file exists, STOP: there is nothing to diff against, and deltas cannot be extracted without fabrication. Discipline: generate → save the original untouched → edit a copy.
Both files share the template master. The differ reads the master from
original to resolve inherited styling.
Reference map
Step 1 — run the differ
pip install python-pptx lxml --break-system-packages
python scripts/diff_decks.py <original.pptx> <edited.pptx> --json deltas.json
The differ walks both decks in lockstep (slide → shape → paragraph → run) and,
crucially, resolves each run's EFFECTIVE styling through the master ladder and
theme before comparing. A run that inherits its font/size/colour reports the
resolved baseline (the brand font, body/title sizes, the brand colours), not
None. So re-stating an inherited value produces no delta, while a real change
(e.g. body 14→18pt) surfaces exactly. Geometry, paragraph alignment/level/
spacing, and slide layout are compared directly. Added/removed/reordered slides
or shapes emit a structural count-mismatch — treat the affected slide as
low-confidence rather than feeding its run deltas in.
It never emits text-content deltas (a run's text string is not a tracked property), so styling and content stay separate.
Step 2 — merge into the ledger (accumulate, never rewrite)
Read STYLE_LEDGER.md (format and worked rules: references/style-ledger.md).
For each delta:
- Matches an existing rule (same property +
to) → incrementcount, updatelast_seen. - New → add as
candidate,count: 1. - Contradicts an existing rule (same property, different
to) → setconflicting, record both values; do not overwrite. A conflict means the preference is context-dependent.
Promote a candidate to always at count >= 3 distinct decks. Only always
rules are acted on. The ledger is the artifact that improves; this SKILL.md is
stable.
Step 3 — route each promoted rule to where it belongs
The template carries styling in the master, so most learnings should be FIXED at the source, not re-applied per deck:
- Pure default (a font/size/colour that should be the baseline, e.g. "body
18pt not 14pt") → TEMPLATE DEFECT. Fix once in the
.potxmaster/theme, then rebuildlayout_map.json. Do not encode it as a generator rule. - Layout/structure preference (e.g. "level-0 body heading should be bold brand blue") → either add a heading style to the template, or encode as a generator convention.
- Judgement (e.g. "dense comparison → use '2 text' not '1 text'") → a generator layout-selection heuristic or a content-md convention.
A correction you make every single time is a defect at the source, not a learned preference. The ledger makes these obvious.
Step 4 — report
Summarise: deltas found, rules reinforced, new candidates, conflicts, defects
flagged. Show the STYLE_LEDGER.md diff.
Convergence signal
Log total deltas per iteration in the ledger history. Trending down = working (you correct less because generation/template already does it). Plateau with the same deltas recurring = the learning belongs in the template or generator, not the ledger — fix it at the source rather than feeding the loop forever.
Note
lib/pptx_master.py is duplicated in both skills so each is self-contained. If
you change it here, copy it to deck-generator/lib/ too.