Skip to content
Back to skills

deck-pipeline

ASecurity

Production-grade Claude Code system that takes presentation decks from raw Chinese draft to McKinsey-polished English — with full audit trail, layout integrity checks, and a swappable PROFILE block for project-specific defaults. Built on a 4-stage pipeline (Sense Pass → McKinsey Translation → Layout Audit → Handoff). Also runs polish-only on any single-language deck. TRIGGER when the user: • hands over a .pptx containing Chinese and asks for English / translation • asks for "deck pipeline", ...

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 5, 2026
ai-agentspythongorailsgitapi

Works with

  • claude code
  • api

Security analysis

A100/100

Pro scans all 13 files and shows the line behind each finding

Scanned June 5, 2026

npx -y skills add TinaDu-AI/deck-pipeline --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of deck-pipeline?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for deck-pipeline
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tinadu-ai-deck-pipeline/badge)](https://www.skillsdirectory.com/skills/tinadu-ai-deck-pipeline)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: deck-pipeline
description: |
  Production-grade Claude Code system that takes presentation decks from raw
  Chinese draft to McKinsey-polished English — with full audit trail, layout
  integrity checks, and a swappable PROFILE block for project-specific
  defaults. Built on a 4-stage pipeline (Sense Pass → McKinsey Translation →
  Layout Audit → Handoff). Also runs polish-only on any single-language deck.

  TRIGGER when the user:
    • hands over a .pptx containing Chinese and asks for English / translation
    • asks for "deck pipeline", "deck polish", "deck globalizer"
    • asks for layout polish, font cleanup, overflow fixing on any deck
    • asks to update / reverse-sync a bilingual comparison Excel against a deck

  SUPPRESS with "Ignore deck-pipeline".
version: 0.1.0
license: MIT
---

# Deck Pipeline

> **A 4-stage, audit-trailed Chinese→English deck globalization system with a swappable project profile.**

This skill bundles the generic deck-globalization engine (originally upstream
DeckGlobalizer v2.1.1) and an editable PROFILE block (palette, fonts,
glossary, style preferences). The two are **separated** by section so the
profile can be swapped per project / brand without touching the engine.

For a marketing-style overview, see `README.md` in this directory.
For implementation, see `scripts/` and the per-stage runbooks below.

---

## 0. Modes & activation

| Mode | Trigger | Stages |
|---|---|---|
| **Full pipeline** | CN deck (± EN draft) + user wants English output | 1 → 2 → 3 → 4 |
| **Polish-only**   | Single-language deck + "layout / format only / skip translation" | 1 → 3 → 4 |
| **Reverse-sync only** | User hand-edited a PPT after a comparison Excel was generated | 3.5 (sync sub-routine) |

Detect the mode in the first turn. If ambiguous, ask one yes/no question
("This deck is already in EN — should I just polish layout, or also rewrite
McKinsey-style?"). Do not guess silently.

---

## 1. PROFILE block — defaults (swappable)

Edit this block to retarget the skill for your project / brand. Everything
below this block is **profile-agnostic**.

```yaml
PROFILE:
  # ---- L1 Tokens ----
  palette:
    # Replace with your brand colors.
    ink:          "#1A1A1A"
    primary:      "#000000"   # accent / brand primary
    soft:         "#FFFFFF"   # soft fill behind banners
    page_bg:      "#FFFFFF"
  fonts:
    # Choose a serif title face + a sans-serif body face for best contrast.
    title:        "Georgia"
    body:         "Verdana"
    title_bold:   true
  unit_table:
    # Chinese number magnitudes → English. 亿 is 100M, NOT "billion".
    "百万":       "M"
    "千万":       "10M"
    "亿":         "100M"
    "十亿":       "1B"
    "百亿":       "10B"
    "千亿":       "100B"
    "万亿":       "1T"
    # Currency suffix is left to the user — append "$" / "RMB" / "€" as appropriate.

  # ---- L2 Constants ----
  size_ladder:           [22, 14, 10, 8, 6, 4]   # H1, H2, body, caption, footnote, source
  floors:
    body:     7
    caption:  6
    source:   4
  compression_step:      0.1     # discrete -0.1pt iterations only
  line_height_default:   1.25
  line_height_fallback:  1.15    # used before sub-floor compression
  quote_style:           "single"  # 'McKinsey' single quotes
  footer_format:         "Confidential · For Intended Recipients Only · {month} {year}"
  separator_in_footer:   "·"     # middle dot, NOT em-dash

  # ---- L1 Glossary (extensible) ----
  # Replace the example entries below with your project's locked terms.
  # Categories are illustrative; you can rename / add / remove.
  glossary:
    locked:
      people_orgs:
        # "<source term>": "<canonical translation>"
        # e.g. "John Smith": "John Smith"
        # e.g. "Acme Capital": "Acme Capital"
        {}
      business_terms:
        # Common Chinese business-deck idioms with industry-standard
        # English mappings. Edit / extend as needed.
        "流水":     "gross revenue"
        "私域":     "owned audience"
        "出海":     "global expansion"
      domain_specific:
        # Project / industry / domain terms.
        # "<source term>": "<canonical translation>"
        {}
    rejected_rewrites:
      # Entries the user vetoed during prior sessions.
      # Format: { source: "...", proposed: "...", reason: "..." }
      []
    pending: []
    session_added: []

  # ---- Style rules ----
  # McKinsey is the default baseline. Additional style references can be
  # uploaded and distilled via scripts/style_distill.py; their rules layer
  # ON TOP of the McKinsey base.
  style_baseline: "mckinsey"
  mckinsey:
    title_is_takeaway:      true   # title = the so-what, not the topic
    lead_with_so_what:      true
    parallel_structure:     true   # bullets share tense, opening part-of-speech
    strong_action_verbs:    true   # cut "is/has", prefer concrete verb
    cut_filler:
      - "in order to → to"
      - "a number of → many"
      - "due to the fact that → because"
      - "at this point in time → now"
    case:                   "sentence"   # lowercase unless proper noun or locked term
    em_dash_policy:         "use em-dash for parentheticals; use · (middle dot) in lists/footers"
  style_references:
    # Each entry is a PDF / .pptx reference. style_distill.py reads it and
    # emits rules (cadence, signature phrases, paragraph length, tone) that
    # layer on top of the McKinsey base. Conflicts: more recent entry wins;
    # user is asked at first conflict.
    # Example:
    # - path: "/path/to/sample.pdf"
    #   weight: 0.7
    []

  # ---- Structural anchor heuristics ----
  anchor_detection:
    min_pages: 3              # appears on ≥3 slides
    match_on:                 # signature components
      - position_xy
      - fill_color
      - font_size_class
    auto_protect: true

  # ---- Overflow estimator ----
  overflow:
    severity:
      high: 1.5
      med:  1.15
      low:  1.0
    surface_only: "high"      # surface MED/LOW only when explicitly asked
    defer_to_user_threshold: 10   # if HIGH > 10 → ask user to render externally

  # ---- CN ↔ EN slide alignment ----
  # Default is 1:1 (EN slide N maps to CN slide N).
  # Set overrides only when the two decks have been restructured.
  # Pass this config to excel_sync.py via `--cn-offset <yaml>`.
  cn_en_slide_offset:
    default: 0           # offset added to EN slide number (0 = 1:1)
    overrides: {}        # e.g. {"9-26": -1, "20": null}
                         # int = relative offset; null = no CN counterpart
```

> **Profile-agnostic note:** all sections below treat `PROFILE` as an
> opaque dict. Do not hardcode project-specific values anywhere outside the
> PROFILE block.

---

## 2. Pipeline stages

Each stage has: **inputs · what it does · outputs · stop-and-ask conditions.**

### Stage 1 — Sense Pass

**Inputs:** one or two `.pptx` paths (CN, optional EN draft)
**What it does:**
1. Run `scripts/sense_pass.py` to extract:
   - palette (top fill colors)
   - font usage histogram
   - size distribution
   - title-zone shapes (top ≤ 600K EMU)
   - layout heuristics
2. Cross-check sensed values against `PROFILE.palette` / `PROFILE.fonts`.
   If a sensed font is NOT in the whitelist AND NOT in `SKIP_POLLUTION`,
   record it as **font pollution**.
3. Surface **candidate glossary entries**: any CN noun phrase that appears
   ≥2 times and isn't already in `glossary.locked`.

**Outputs:**
- `Style_Manifest.md` (in-memory; not written to disk unless requested)
- `pollution_report` (slide → font → count)
- `candidate_glossary` (term → count → sample context)

**Stop-and-ask:**
- Candidate glossary surfaces a term Claude can't confidently translate →
  ask user, write answer to `glossary.session_added`.
- Sensed primary palette color differs from `PROFILE.palette.primary` →
  ask whether to update profile or keep existing.

---

### Stage 2 — McKinsey Translation (skipped in polish-only mode)

**Inputs:** Stage 1 outputs + the CN deck (and optional EN draft for diff context) + any uploaded `style_references`.

**Style layering**: McKinsey base rules (`PROFILE.mckinsey`) apply first. If
`PROFILE.style_references` is non-empty, run `scripts/style_distill.py` on
each reference before translation begins; the distilled rules (cadence,
signature phrases, paragraph length, tone) layer on top. More recent entry
wins on conflict; ask user at the first conflict.

**Page-by-page execution (hard requirement):**
1. **Overall confirmation first** — after Stage 1, show the user the planned
   per-page edit count + sample of style rules in effect; wait for "go".
2. **Then loop slides 1 → N**, one at a time:
   - Collect paragraph-level CN text on this slide via `scripts/extract.py`.
   - For each paragraph, produce EN per the layered style rules:
     - lowercase by default; title = so-what; parallel bullets; strong verbs;
       filler-word table applied; glossary `locked` inline
     - any unknown term → STOP, ask user, write to `session_added`
   - Build the slide's edit batch as a JSON object.
   - Run `scripts/apply.py` with the slide's batch → writes that slide's
     changes into `<file>-en-polished-<date>.pptx` AND appends rows to
     `<file>-bilingual-diff-<date>.xlsx` immediately.
   - **Checkpoint**: print "P{n} done — N changes applied. Continue?" and
     wait for user OK before moving to P{n+1}.
   - User can interject "back to P{n-1}" or "stop here" between pages.

**Why per-page (not all-at-once):**
- The user can review and steer mid-stream.
- A bad assumption on P3 doesn't propagate to P27 unnoticed.
- Excel grows incrementally — survives any mid-session interruption.
- Token-efficient: only one slide's context in active scratchpad.

---

### Stage 3 — Layout Audit

**Inputs:** the post-translation deck (or, in polish-only mode, the raw deck)
**What it does:**

#### 3a. Font pollution cleanup
Run `scripts/layout_audit.py --fix`:
- For every run whose `font.name` is NOT in the title/body whitelist
  OR ends in a style suffix (`Bold` / `Regular` / `Italic` / `Light`):
  - Strip the suffix
  - Set `font.name` to the pure family
  - Set `font.bold` / `font.italic` attributes accordingly
- Skip any face in the configured `SKIP_POLLUTION` set.

#### 3b. Structural-anchor detection
Run `scripts/anchor_detect.py`:
- For each shape, compute a signature: `(rounded_position, fill_color, font_size_class)`.
- Group across slides. Any signature occurring on ≥ `PROFILE.anchor_detection.min_pages`
  pages becomes an **anchor**.
- Build `per_page_protect[page] = [anchor_shape_ids...]`.
- Surface the anchor list to the user. They can add/remove.

#### 3c. Overflow estimation
Run `scripts/overflow_recheck.py`:
- Honor `auto_size` (skip if SHAPE_TO_FIT_TEXT or TEXT_TO_FIT_SHAPE).
- Read actual `margin_*`.
- Use `PROFILE.line_height_default = 1.25` initially. If a shape is flagged,
  try 1.15 as a what-if before flagging as HIGH.
- Per-character width by class (narrow `iIl`, wide `MW`, digits, upper, space).
- Greedy word-wrap simulation.
- Emit only HIGH (`ratio > PROFILE.overflow.severity.high`) by default.

If HIGH count > `PROFILE.overflow.defer_to_user_threshold`:
- **Do not** dump 30+ rendered PNGs into the session.
- Tell the user: "Render to PDF/PNG via Keynote or PowerPoint, tell me which
  pages look broken, I'll fix those targeted pages."

#### 3d. Compression (when user OKs a fix)
For each shape needing fix:
1. Is it in `per_page_protect[page]`? → SKIP (it's an anchor).
2. Try widening: increase shape `width` until ratio < 1.0 OR shape collides.
3. Still > 1.0? Try line-height 1.25 → 1.15.
4. Still > 1.0? Iterate `font.size -= PROFILE.compression_step` (0.1pt) until
   floor (`PROFILE.floors.<body|caption|source>`) hit.
5. Still > 1.0 at floor? **STOP. Escalate to user.** List the shape, its
   current size, the calculated ratio, and ask whether to break the floor.

#### 3e. Late-stage glossary re-scan
Run `scripts/glossary_audit.py`:
- For each text run in the deck, check against `glossary.locked`:
  - If a CN-side phrase exists locked but a non-canonical EN translation
    appears → flag.
  - If the same source term is translated two different ways in the deck
    (wavering) → flag.
- Surface flagged rows. Auto-fix if all flags point to the same canonical
  translation; ask otherwise.

#### 3f. Reverse sync (sub-routine, also Mode 3.5 entry point)
Run `scripts/excel_sync.py --reverse`:
- Diff current PPT against the Excel's `en_optimized` column.
- For each mismatched row:
  - Try ordinal-position match (slide + paragraph-index).
  - If no match, try `difflib.get_close_matches` against same-slide texts.
  - Update Excel cell on success.
- Report any leftover unmatched rows.

**Outputs:**
- `<file>-final-<date>.pptx` (full pipeline) or `<file>-final-<date>.pptx` (polish-only)
- Updated Excel (if applicable)

---

### Stage 4 — Handoff

**Inputs:** all prior-stage outputs
**What it does:**
1. Write `HANDOFF.md` to the same directory as the deck — see `scripts/handoff.py`.
2. Print a one-paragraph deliverables summary to the user.

**Stop-and-ask:** none.

---

## 3. Operational rules (apply across stages)

### 3.1 File-write discipline

Before writing **any** `.pptx` or `.xlsx`:
1. Check for `~$<filename>` lock file in the same directory.
2. If present → **STOP.** Tell the user: "`<filename>` is open in
   PowerPoint/Excel. Save and close it, then say 'go' to continue."
3. After writing, immediately readback-verify (next rule).

### 3.2 Excel companion three guard-rails

1. **Pre-write check** — load existing Excel (if any), confirm header row is
   `[page, kind, cn, en_original, en_optimized, notes]`. If columns missing
   → rebuild header before writing data.
2. **Post-write readback** — immediately reload the saved file and assert
   `max_column ≥ 7` and header is intact.
3. **Reverse sync** available on demand: see Stage 3f.

### 3.3 Font compression discipline

See Stage 3d. The single rule: **never** bulk-reduce font sizes.
Always discrete `-0.1pt`, always after exhausting widening + line-height
fallback, always with anchor protection.

### 3.4 Glossary discipline

- Ask once per session per unknown term. Then it's in `session_added` for
  the rest of the session.
- At handoff, promote `session_added` to a `glossary_proposed_additions.yaml`
  file next to the deck. The user can copy them into PROFILE for the next run.
- **Never** silently apply a translation Claude is unsure about. Stop and ask.

### 3.5 Magnitude verification

Any number with a CN magnitude word (百万 / 千万 / 亿 / 百亿 / 千亿 / 万亿)
must be re-verified against `PROFILE.unit_table` before being written to EN.
Treat this as a HARD CHECK; do NOT take prior-session translations on faith.

### 3.6 CN-alignment confidence

When auto-aligning the Excel's `cn` column by paragraph ordinal:
- Slides with > 15 changes → auto-tag `notes` column as `needs-review`.
- Always present this as best-effort, never as ground truth.

---

## 4. Scripts (in `scripts/`)

| Script | Role | Stage |
|---|---|---|
| `sense_pass.py` | extract design DNA, font usage, palette | 1 |
| `extract.py`    | paragraph-level text extraction | 1, 2, 3 |
| `apply.py`      | apply EN edits + write Excel with highlight | 2 |
| `layout_audit.py` | font pollution cleanup, suffix audit | 3a |
| `anchor_detect.py` | cross-page anchor signature detection | 3b |
| `overflow_recheck.py` | overflow estimator with severity tiers | 3c |
| `glossary_audit.py` | late-stage glossary re-scan + wavering | 3e |
| `excel_sync.py` | bidirectional PPT ↔ Excel sync (configurable slide offset) | 3f |
| `handoff.py`    | write HANDOFF.md | 4 |
| `style_distill.py` | distill style fingerprint from a reference PDF/.pptx | pre-2 |

Each script is invokable standalone; the skill wires them together.

---

## 5. Deliverables (recap)

**Full pipeline (4 files):**
- `<file>-en-polished-<date>.pptx`
- `<file>-final-<date>.pptx`
- `<file>-bilingual-diff-<date>.xlsx`
- `HANDOFF.md`

**Polish-only (3 files):**
- `<file>-final-<date>.pptx`
- `<file>-layout-changes-<date>.xlsx`
- `HANDOFF.md`

**Mode 3.5 (reverse-sync only):**
- updated `<file>-bilingual-diff-<date>.xlsx`

---

## 6. Known limitations

1. Overflow estimator is a **hint, not a verdict** — final visual check
   requires external rendering (Keynote / PowerPoint export to PDF).
2. `python-pptx` cannot render slides. There is no built-in preview.
3. CN auto-alignment by paragraph ordinal can drift on heavily-restructured
   pages — configure `PROFILE.cn_en_slide_offset.overrides` for known cases.
4. The skill assumes the CN source is semantic ground truth — typos in CN
   propagate to EN unless the user catches them.
5. File-lock collisions silently corrupt output. The pre-write `~$xxx` check
   is the only line of defense.

---

## 7. Changelog

See `CHANGELOG.md`.

---

## 8. Credits

Generic deck-globalization engine derived from upstream **DeckGlobalizer v2.1.1**
by tinadu-ai (<https://clawhub.ai/tinadu-ai/deckglobalizer>). Original
three-phase architecture (Visual Audit / Semantic Alignment /
Page-by-Page Execution) credited and retained.

Files in this skill

  • CHANGELOG.md2.3 KB
  • CONTRIBUTING.md2.1 KB
  • SKILL.md16.9 KB
  • scripts/anchor_detect.py3.5 KB
  • scripts/apply.py5 KB
  • scripts/excel_sync.py9.9 KB
  • scripts/extract.py2 KB
  • scripts/glossary_audit.py4.8 KB
  • scripts/handoff.py2.2 KB
  • scripts/layout_audit.py7.8 KB
  • scripts/overflow_recheck.py5.9 KB
  • scripts/sense_pass.py6.4 KB
  • scripts/style_distill.py6.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.