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

  1. original — the deck exactly as generated, before editing.
  2. 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) → increment count, update last_seen.
  • New → add as candidate, count: 1.
  • Contradicts an existing rule (same property, different to) → set conflicting, 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 .potx master/theme, then rebuild layout_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.