[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71B9BC0ZP0RAF5MGP04J6T5":3,"skill-same:01M71B9BC0ZP0RAF5MGP04J6T5":85},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":57,"commitSha":58,"skillDirectory":59,"forksCount":60,"repositoryHtmlUrl":61,"repositoryHomepageUrl":6,"ownerHtmlUrl":62,"ownerBlogUrl":63,"ownerDescription":64,"updatedAt":65,"install":66,"resources":78},"01M71B9BC0ZP0RAF5MGP04J6T5","pptx-template",null,"Interactive PPTX template builder and maintainer. Two modes: CREATE: converts any base .pptx into a semantic placeholder template through a gated process. UPDATE: maintains an existing template after user changes (add\u002Fremove\u002Fmodify slides). Use when preparing a new PPTX template, converting a presentation to a template, or updating an existing template after changes. Also use when user says \"template pptx\", \"prepare template\", \"build pptx template\", \"convert pptx to template\", \"update template\", \"sync template\".","Wizarck\u002Fnexandro","Wizarck","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F23051550?v=4","01M71B3AAVR67GRWFV5ZXXZP31","arturo6ramirez","01M71B3ABYG1BFNXHX4KZ3PPK6",2,"AGPL-3.0","https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fpptx-template\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000003","演示文稿","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000034","行政与办公人员","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"template","pptx template","pptx","modes","slides","modify","path","presentation","opus","add","sync","update","inline","placeholder","create","sync template","when","new","remove","builder","2026-11-10 10:12:30",false,"---\nname: pptx-template\ndescription: >\n  Interactive PPTX template builder and maintainer. Two modes:\n  CREATE: converts any base .pptx into a semantic placeholder template through a gated process.\n  UPDATE: maintains an existing template after user changes (add\u002Fremove\u002Fmodify slides).\n  Use when preparing a new PPTX template, converting a presentation to a template,\n  or updating an existing template after changes.\n  Also use when user says \"template pptx\", \"prepare template\", \"build pptx template\",\n  \"convert pptx to template\", \"update template\", \"sync template\".\nmodel: opus\ncontext: inline\nargument-hint: \"[--update] \u003Cpath-to-template.pptx>\"\ndisable-model-invocation: true\n---\n\n# PPTX Template Builder\n\nYou convert any base .pptx into a semantic placeholder template through a safe, gated process.\nThe core safety invariant: **python-pptx (structure) -> save -> lxml (content) -> never touch again**.\n\nSee [guardrails.md](guardrails.md) for absolute rules that override all other instructions.\n\n## Argument Parsing\n\nThe user provides a path to a base .pptx file:\n- `\u002Fpptx-template path\u002Fto\u002Fdeck.pptx`\n- If no argument, ask: \"Which .pptx file should I convert to a template?\"\n\n---\n\n## STEP 0: Input + Backup\n\n1. Verify the .pptx exists and can be opened by python-pptx\n2. Copy to a working directory (never modify the original)\n3. Save checkpoint: `_int_ai\u002Fcheckpoint_00_original.pptx`\n4. Report slide count\n5. Ask user:\n   - \"This PPTX has X slides. What type? (BC \u002F BS \u002F OS)\"\n   - \"Where is the corresponding markdown file (e.g., LEAN_BUSINESS_CASE.md)?\"\n\n**GATE**: User provides type and markdown path before proceeding.\n\n---\n\n## STEP 1: Content Alignment Audit (PPTX vs Markdown)\n\n1. Read the base .pptx slide titles and content summaries (python-pptx, read-only)\n2. Read the markdown file section structure (H1, H2, H3 headings)\n3. Compare: which sections exist in both? Which are in markdown but not PPTX? Which are in PPTX but not markdown?\n4. Present alignment table:\n\n```\nPPTX Slide              | Markdown Section       | Match\nCanvas (slide 5)        | Executive Summary      | YES\nWave Gates (slide 12)   | S9.2 Wave Gates        | YES\n(missing)               | S6 Key Assumptions     | NO -- PPTX missing\nRoadmap (slide 36)      | (not in markdown)      | NO -- MD missing\n```\n\n5. Ask: \"Here is how the PPTX aligns with the markdown. Should we add\u002Fremove slides to match? Should we reorder to follow the markdown structure?\"\n\n**GATE**: User decides the target structure.\n\n---\n\n## STEP 2: Structural Inventory (read-only)\n\n1. Catalog all slides: number, title, layout name, SmartArt yes\u002Fno\n2. Present list alongside the STEP 1 alignment\n3. Ask: \"Based on the alignment, do you need to add, remove, or reorder slides? Or is the structure final?\"\n\nIf user says structure is final -> skip to STEP 4.\n\n---\n\n## STEP 3: Structural Changes (python-pptx -- ONE save)\n\n1. Collect ALL operations the user wants (add, remove, reorder)\n2. Execute ALL in ONE python-pptx session (add + reorder + save)\n3. Save checkpoint: `_int_ai\u002Fcheckpoint_03_structured.pptx`\n4. Ask: \"Open in PowerPoint. Is the structure correct?\"\n\n**GATE**: User must confirm before proceeding. If not correct, repeat STEP 3.\n\n---\n\n## STEP 4: Deep Audit (lxml -- on the FINAL structure)\n\n1. **Identify protected slides first.** Read the filler skill spec (e.g., `_int_ai\u002F_pptx_pipeline\u002Ffiller_spec_BC.md`) or ask the user which slides are fully static. Protected slides are: branding\u002Fframework visuals, TOC, section separators, thank-you\u002Fclosing. These slides are SKIPPED entirely in STEPs 4-6.\n2. Present the protected list to the user for confirmation:\n   ```\n   PROTECTED (will NOT be audited or tagged):\n     Slide 2: \"Lean Business Case Structure\" (TOC)\n     Slide 3: \"Intelligent Innovation\" (branding)\n     Slide 4: \"GTM Offering Creation Blueprint\" (framework)\n     Slide 9: \"Thank You\" (closing)\n     Slides 10,12,19,23,36,42: Section separators\n   ```\n3. Parse EVERY `\u003Ca:t>` and `\u003Cdgm:t>` element with lxml across all XML files in the PPTX zip, **excluding protected slides**\n4. Record for each element: file path, element index, text content, parent context\n5. Output: `_int_ai\u002Felement_audit.json` (protected slides are absent from this file)\n6. Save the protected list to `semantic_mapping.yaml` under `protected_slides`\n\n**GATE**: User confirms the protected slide list before proceeding.\n\n**IMPORTANT**: After STEP 3 completes, NEVER use python-pptx again on this file. All subsequent operations use lxml only.\n\n---\n\n## STEP 5: Classify Elements (AI + user review)\n\nClassification rules are defined in [guardrails.md](guardrails.md) under \"Classification\". Key principles:\n\n1. **FIXED**: titles, headers, labels, sub-headers, section numbers, decorative symbols, metric labels\n2. **DATA**: financial figures, descriptions, names, dates, year ranges, status indicators\n3. **Series Pattern Rule**: ANY list of items (bullets, costs, partners, risks, segments, etc.) MUST use `{n}` pattern -- never assume a fixed count. The filler skill determines N from the markdown.\n4. **Object-Grouped Tags**: When a slide has N repetitions of a multi-field object (iterations, milestones, risk cards), tags MUST group by object index: `{{OBJECT_{n}_FIELD}}`, NOT `{{OBJECT_FIELD_{n}}}`. The filler writes complete objects, not parallel lists. See [guardrails.md](guardrails.md) \"Placeholder Naming\" for the full rule and examples.\n5. **Shared Metadata Tags**: iteration number, maturity level, offering name appear across multiple slides -- use consistent tag names (`{{ITERATION_NUM}}`, `{{ITERATION_MATURITY}}`, `{{TITLE_OFFERING}}`)\n6. **Mixed Elements**: when a single text element contains both fixed and variable parts (e.g., \"Iteration 1\" where \"Iteration \" is fixed), split at the `\u003Ca:r>` run level if possible, or document the fixed prefix in the mapping\n7. **Split-Run Words**: PowerPoint may split a word across runs (e.g., \"Itera\" + \"tion 1\"). Place `{{TAG}}` in the first run, clear subsequent fragment runs. See [guardrails.md](guardrails.md) \"Split-Run Words\" for details.\n8. **Sub-label + Bullets**: When a panel has bold sub-labels followed by bullet points, encode the sub-label identity into the series prefix: `{{PREFIX_SUBLABEL_{n}}}`. Always use `{n}` series even for single bullets today. See [guardrails.md](guardrails.md) \"Sub-label + Bullets Pattern\" for full rule and edge cases.\n\n9. **Double-Variable Tables**: When a table has variable rows (BUs, {n}) AND variable columns (capabilities, {m}), use double-index tags: headers as `{{PREFIX_CAP_{m}_HEADER}}`, body cells as `{{PREFIX_{n}_CAP_{m}}}`, and fixed final column (Risk) as `{{PREFIX_{n}_RISK}}` (single index only). Applies to PEOPLE, PROCESS, PLATFORM, PARTNER capability slides. See [guardrails.md](guardrails.md) \"Double-Variable Tables\" for full pattern and example.\n\nAssign semantic `{{TAG}}` names following [guardrails.md](guardrails.md) \"Placeholder Naming\":\n- UPPER_SNAKE_CASE with slide context prefix\n- Series: `{{CANVAS_COST_{n}}}`, `{{EXEC_MILESTONE_{n}_DATE}}`\n- Compound series: `{{EXEC_RISK_{category}_{n}}}`\n\nPresent to user in batches of ~3 slides, element by element, using this format:\n\n```\n=== Slide 12 — Customer Problem (32 elements) ===\n\n| # | Text | Class | Tag \u002F Reason |\n|---|------|-------|--------------|\n| 0 | \"Customer Problem & Use-Case Validation\" | FIXED | Slide title |\n| 1 | (auto-field) | SKIP | PowerPoint slide number |\n| 2-8 | \"Remote customers operating...\" | DATA cluster | {{PROBLEM_STATEMENT}} |\n| 9 | \"Key Data Highlights:\" | FIXED | Section label |\n| 10 | \"High Latency Friction:\" | DATA series | {{PROBLEM_PAIN_{n}_TITLE}} — pain point name varies per offering |\n| 11-13 | \"Standard M365 fails... 600-800ms...\" | DATA series | {{PROBLEM_PAIN_{n}_DESC}} — pain point description |\n| 26 | \"Observable Business Impact:\" | FIXED | Section label |\n| 27 | \"End-user productivity is unreliable...\" | DATA cluster | {{PROBLEM_IMPACT}} |\n```\n\nKey distinctions in the table:\n- **FIXED**: titles, labels, decorative — no tag\n- **SKIP**: auto-fields (`\u003Ca:fld>`) — invisible to the pipeline\n- **DATA series**: repeating items with `{n}` — N determined by BC content\n- **DATA cluster**: named fields with fixed structure — always present\n\n### Label Genericization (inline with classification)\n\nFIXED labels must work for ANY offering, not just the current one. When presenting each batch:\n- For every FIXED label that contains offering-specific or overly narrow language, propose a generic alternative inline\n- Use a separate column or note: `Original: \"Into standardized managed pathways:\" -> Proposed: \"Migration targets:\"`\n- Slide titles are EXCLUDED from this review (they are structural and already generic)\n- The user approves or adjusts each label change in the same review pass\n- Approved generic labels are applied during STEP 6 (lxml injection) alongside placeholder insertion\n\nAsk: \"Review the classification and label proposals. Flip any FIXED \u003C-> DATA and adjust labels as needed.\"\n\n**GATE**: User must approve the full classification before proceeding.\nOutput: `_int_ai\u002Fclassification.json`\n\n---\n\n## STEP 6: Insert Placeholders + Generate Mapping (lxml -- SINGLE pass)\n\nSee [guardrails.md](guardrails.md) \"Injection Engine Rules\" for the mandatory mechanisms.\n\n### 6a. Build the injection script\n\nWrite a Python script with per-slide configs. Each slide MUST have:\n- `pre_fields`: positional tag names for the first N DATA elements (before any group delimiter)\n- `groups`: `{label: prefix}` dict using FIXED labels as delimiters for semantic groups\n- `default`: fallback prefix (should only apply to truly positional tables)\n- `table_cols`: column names for table-structured slides (column cycling)\n\nThe FIXED set MUST be a Python list literal (never parsed from free text).\n\n### 6b. Execute: Label genericization + tag injection in one pass\n\n1. Open checkpoint_03 as zip\n2. For each non-protected slide and its associated diagram files:\n   - Apply label genericizations (old text -> new generic text)\n   - Skip auto-fields (`\u003Ca:fld>`)\n   - Skip FIXED elements\n   - Assign semantic `{{TAG}}` to DATA elements using pre_fields -> groups -> table_cols -> default\n3. For SmartArt: process data{N}.xml AND drawing{N}.xml with the same config\n4. Validate XML after each file modification\n5. Save: `_int_ai\u002Fcheckpoint_06_with_placeholders.pptx`\n\n### 6c. Post-injection verification (mandatory, blocks GATE)\n\n1. python-pptx open test\n2. Count all `{{TAG}}` occurrences\n3. **Scan for generic tags**: any `{{PREFIX_N}}` where PREFIX is a bare default (no semantic group) is a BUG -- fix before proceeding\n4. Report: total tags, tags per slide, any generic tag violations\n\n### 6d. Generate semantic_mapping.yaml (mandatory, same step)\n\nThe YAML is generated from the **template tag inventory**, NOT from the classification.\n\n**Procedure**:\n1. **Scan the injected template** (checkpoint_06): grep all `{{TAG}}` patterns across ALL XML files (slides + diagrams\u002Fdata + diagrams\u002Fdrawing)\n2. **Deduplicate**: build the canonical tag list (unique tag patterns found in the template)\n3. **Enrich**: for each tag in the inventory, add classification metadata (description, suggestion, example, max_chars, type) from the STEP 5 classification output\n4. **Discard phantom tags**: tags in classification but NOT in the template = classification artifacts. Do NOT include them in the YAML.\n5. **Report injection gaps**: tags in the template but NOT in classification = injection bugs. Fix before proceeding.\n\n**Invariant**: `meta.total_tags` MUST equal the count of unique tag patterns found in the template PPTX. If these numbers diverge, the YAML is wrong.\n\n**Why**: Classification defines what SHOULD be tagged. The template defines what IS tagged. The YAML must reflect reality (template), enriched with intent (classification). Previous approach generated YAML from classification (453 patterns) for a template with only 217 actual tags -- causing 80.9% orphan ratio and 9 STRUCTURAL failures during generation.\n\n7. Ask: \"Template has X semantic tags. Opens OK? Check in PowerPoint. Mapping saved to semantic_mapping.yaml.\"\n\n**GATE**: User confirms template + mapping are correct.\n\n---\n\n### 6e. Generate PNG sets (mandatory, same step)\n\nRender the template to two PNG sets for use by fill and QA agents:\n\n1. **Template PNGs** (`OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F`): Render checkpoint_06 to PDF via LibreOffice, then to PNG via pymupdf. Shows `{{TAG}}` placeholders in situ.\n2. **Reference PNGs** (`OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Freference\u002F`): If a completed offering exists (e.g., OFFER-001), render its LEAN_BUSINESS_CASE.pptx. If none exists yet, skip -- reference PNGs will be generated after the first successful fill.\n\nBoth PNG sets are stored in `OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002F`. They serve as visual context for the 3-Layer Context rule (guardrails.md).\n\n**PNG validation (mandatory before and after copy)**:\n\nBefore copying new PNGs to either directory, validate existing state:\n```bash\npython 98_Scripts\u002Fvalidate_slide_pngs.py \"OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F\"\n```\n\nIf mixed naming is detected (old `slide_N.png` + new `page_NN.png`), clean up first:\n```bash\ncd \"OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F\" && rm -f slide_*.png\n```\n\nAfter copying PNGs, re-validate with expected count:\n```bash\npython 98_Scripts\u002Fvalidate_slide_pngs.py \"OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F\" --expected-count 65\n```\n\nDo NOT proceed past this step if validation fails. See guardrails.md \"PNG Directory Management\" for full rules.\n\n---\n\n## STEP 7: Filler Spec + Guardrails Debate\nTags are NOT hardcoded counts -- the filler skill determines how many based on the markdown content.\n\n### B) filler_spec_{type}.md\n\nA reference document for the corresponding filler skill (`\u002Fbc-to-pptx`, etc.) that defines:\n\n1. For each slide: what markdown section feeds it, what data type (text, table, list, number)\n2. For iterative elements: how to determine the count from the markdown\n3. For conditional elements: when to include\u002Fexclude\n4. Content rules (no CIT, no SKU codes, max chars per field)\n5. Validation checks: cross-slide consistency (revenue Y1 must match everywhere)\n6. **Filler skill guardrails** (see debate below)\n\n### C) Generate Script Contract (mandatory, same step)\n\nDuring the filler spec debate, also define the `generate_pptx.py` interface contract:\n\n1. **Input format**: flat JSON with static tags + expanded series (TAG_1, TAG_2, ...)\n2. **Series handling**: join-based (all values joined with `\\n`), NEVER paragraph cloning\n3. **Dedup strategy**: seen_tags set per file, first occurrence kept, rest emptied\n4. **SmartArt file list**: slides + data + drawing (triple-file mandatory)\n5. **Pilot test plan**: 3 representative slides (1 SmartArt, 1 table, 1 canvas) before full run\n\nThis contract becomes Section 9 of the filler_spec. It ensures the injection format and the generation consumption format are aligned from the start.\n\n**Why this is mandatory in STEP 7**: designing the script reactively (after first fill attempt) caused 6 broken iterations. The contract must exist before any fill agent runs.\n\n### C) Filler Skill Guardrails Debate\n\nStructured conversation with the user to define the rules the filler skill must follow for THIS specific template. Walk through each category, suggest defaults, and let the user override.\n\n**1. Protected slides** (carried forward from STEP 4):\n- \"These slides are protected and the filler skill will skip them: [list]. Anything to add or remove?\"\n\n**2. Content vocabulary**:\n- \"What terms are forbidden in this template?\" (suggest defaults: CIT→Cloud & IT, SKU codes→service names)\n- \"Are there any product\u002Fbrand names that should NOT appear because they belong to a different offering?\" (DO NOT assume -- ask. e.g., M365 is forbidden in a 1EDGE deck, but perfectly valid in an EUP deck)\n- \"Should the filler skill auto-fix these or just block and report?\"\n\n**3. Structural constraints**:\n- \"The BC has 7 risks. The template risk heat map has 4 slots. Expand to 7 or summarize to 4?\"\n- \"The BC has 6 segments but the template market table has 5 rows. How to handle?\"\n- \"The SKU breakdown has N services. Does this match the template table rows?\"\n- For each mismatch: decide expand template, truncate data, or flag for user.\n\n**4. Field formatting**:\n- \"Max characters per field type?\" (suggest: title=60, body=200, table cell=80, bullet=150)\n- \"Number format?\" (suggest: $X.XM for millions, $X,XXXK for thousands, X.X% for percentages)\n- \"How to handle bullet lists?\" (suggest: `\\n`-separated within a single field)\n\n**5. Cross-slide consistency**:\n- \"Which values must be identical across slides?\" (suggest: Revenue Y1, fleet\u002Fsite count, target margin)\n- \"How strict? Block on mismatch, or warn and continue?\"\n\n**6. Data completeness**:\n- \"If a markdown section is empty, what should the filler skill do?\" (suggest: leave {{TAG}} visible so QA catches it, vs. insert placeholder text like \"TBD\")\n- \"Minimum fill rate before generation proceeds?\" (suggest: 90% of tags must have values)\n\nAll decisions are recorded in `filler_spec_{type}.md` under a \"Guardrails\" section. These become the enforceable rules for the filler skill.\n\n**GATE**: User approves the mapping, filler spec, AND guardrails before proceeding.\n\n---\n\n## STEP 8: Build\u002FUpdate the Filler Skill\n\nBased on the filler spec, update the corresponding skill:\n- BC templates -> update `.claude\u002Fskills\u002Fbc-to-pptx\u002FSKILL.md`\n- BS templates -> create `.claude\u002Fskills\u002Fbs-to-pptx\u002FSKILL.md`\n- OS templates -> create `.claude\u002Fskills\u002Fos-to-pptx\u002FSKILL.md`\n\nThe filler skill MUST reference:\n- The `semantic_mapping.yaml` (what tags exist)\n- The `filler_spec_{type}.md` (how to fill them)\n- The guardrails (what NOT to do)\n\nAsk: \"Here is the filler skill spec. Does this capture how data flows from markdown to PPTX?\"\n\n**GATE**: User approves.\n\n---\n\n## STEP 9: Extract Data (per offering, using the filler skill)\n\nThis step is performed by the filler skill (e.g., `\u002Fbc-to-pptx`), not by `\u002Fpptx-template`.\nThe filler skill:\n1. Reads the BC\u002FBS\u002FOS markdown\n2. For fixed-count tags: extracts directly\n3. For iterative tags: counts rows in markdown tables, expands pattern, extracts each\n4. For conditional tags: checks if markdown section exists\n5. Validates: no CIT, no SKU codes, no M365, cross-slide consistency\n6. Reports: \"X of Y tags filled. Z empty. W iterative patterns expanded.\"\n\n---\n\n## STEP 10: Generate + QA (reuses existing Worker -> QA pattern)\n\nThis step reuses the existing pipeline -- no duplication:\n\n```\n\u002Fbc-to-pptx (worker, already exists)\n    | Extract data (STEP 9) -> validate -> generate_pptx.py\n    | Render slides -> launch QA swarm\n\u002Fqa-pptx (QA, already exists)\n    | Returns: APPROVED \u002F ISSUES FOUND \u002F CLARIFICATION\n    |\nISSUES -> Fix slide_data -> regenerate -> re-QA (max 2 iterations)\nAPPROVED -> Ask user to open in PowerPoint -> GATE -> Done\n```\n\n| Concern | Existing Tool | NOT duplicated |\n|---------|--------------|----------------|\n| Slide visual QA | `\u002Fqa-pptx` | NOT in \u002Fpptx-template |\n| Error recovery | `\u002Fqa-improve Mode 1` | NOT in \u002Fpptx-template |\n| Data extraction | filler skill (STEP 8) | NOT in \u002Fqa-pptx |\n| Data validation | `validate_pptx_data.py` | NOT in filler skill |\n| PPTX generation | `generate_pptx.py` | NOT duplicated anywhere |\n| Template prep | `\u002Fpptx-template` (this skill) | NOT in filler skills |\n\n---\n\n## Checkpoints and Recovery\n\n| Checkpoint | Created At | Purpose |\n|-----------|------------|---------|\n| `_int_ai\u002Fcheckpoint_00_original.pptx` | STEP 0 | Pristine copy of input |\n| `_int_ai\u002Fcheckpoint_03_structured.pptx` | STEP 3 | After structural changes |\n| `_int_ai\u002Fcheckpoint_06_with_placeholders.pptx` | STEP 6 | Final template |\n\nIf any step fails, restore the previous checkpoint and retry.\n\n---\n\n## Contract\n\n**Deliverables**: Semantic PPTX template with {{TAG}} placeholders, semantic_mapping.yaml, filler_spec_{type}.md, template PNGs\n**Validation**: none (interactive gated builder, user approves at each step)\n**Acceptance Criteria**:\n- All tags have description + suggestion + max_chars in semantic_mapping.yaml\n- Template PNGs generated and validated (no mixed naming)\n- SmartArt triple-file rule followed (slide + data + drawing)\n- No orphan tags (tags in YAML but absent from template)\n- meta.total_tags matches unique tag count in template PPTX\n**Escalation Triggers**:\n- PPTX fails python-pptx open test → restore checkpoint, ask user\n- Orphan tag ratio > 10% → stop, reconcile YAML against template\n**Max Rework Cycles**: 2\n\n## Output Files\n\nWhen complete, the skill produces:\n1. **Template PPTX** -- the .pptx with `{{TAG}}` placeholders\n2. **_int_ai\u002Felement_audit.json** -- full element inventory\n3. **_int_ai\u002Fclassification.json** -- FIXED\u002FDATA classification\n4. **semantic_mapping.yaml** -- tag-to-slide contract\n5. **filler_spec_{type}.md** -- how to fill the template\n\n---\n\n## Update Mode: `\u002Fpptx-template --update path\u002Fto\u002Ftemplate.pptx`\n\nFor maintaining an EXISTING template after the user makes changes in PowerPoint.\n\n### Argument Parsing\n\nWhen invoked with `--update`:\n1. Read the template PPTX (the modified version the user just saved)\n2. Read the last checkpoint (`_int_ai\u002Fcheckpoint_06_with_placeholders.pptx`) as the baseline\n3. Read the associated markdown file (from semantic_mapping.yaml or ask user)\n4. Compare: detect added slides, removed slides, modified content\n\n### When User ADDS a Slide\n\n1. Detect new slide(s) by comparing current template vs checkpoint\n2. Check if the new slide matches a protected category (branding, TOC, separator, closing). If so, add it to `protected_slides` in semantic_mapping.yaml and report: \"New slide 'X' classified as protected (reason). No tags will be created. OK?\"\n3. For each new NON-protected slide:\n   - Read its content (titles, text boxes, tables)\n   - Read the associated markdown file (BC.md, BS.md, OS.md)\n   - Search markdown for sections\u002Fdata that could match the new slide content\n   - Present mapping suggestion to user:\n     ```\n     NEW SLIDE: \"Marketing Intelligence\" (pos 15)\n\n     Markdown matches found in LEAN_BUSINESS_CASE.md:\n       §3.2 Key Market Drivers → could map to slide body\n       §3.4 Competitive Landscape → could map to table\n\n     Suggested tags:\n       {{MARKET_DRIVERS}} → §3.2 bullet list\n       {{COMP_LANDSCAPE}} → §3.4 table data\n\n     Accept these? [Y\u002Fn\u002Fedit]\n     ```\n3. User approves\u002Fedits the tag suggestions\n4. Insert approved `{{TAGS}}` into the template with lxml\n5. Add entries to slide_data with extracted values from markdown\n6. Update semantic_mapping.yaml\n7. Save new checkpoint\n\n### When User REMOVES a Slide\n\n1. Detect removed slide(s) by comparing vs checkpoint\n2. Identify ORPHANED tags: tags in slide_data that no longer appear anywhere in the template\n3. Present cleanup report:\n   ```\n   REMOVED SLIDE: \"Marketing Intelligence\" (was pos 15)\n\n   Orphaned tags (in slide_data but no longer in template):\n     {{MARKET_DRIVERS}} → value: \"CAPEX to OPEX shift...\"\n     {{COMP_LANDSCAPE}} → value: \"Speedcast, Navarino...\"\n\n   Remove from slide_data? [Y\u002Fn]\n   ```\n4. User approves → remove orphaned entries from slide_data and semantic_mapping.yaml\n5. Save new checkpoint\n\n### When User MODIFIES a Slide\n\n1. Detect changed text elements by comparing vs checkpoint\n2. If new text was added that needs a tag → suggest it (with markdown lookup)\n3. If existing tags were removed from the slide → identify as orphans\n4. If text around tags changed → no action needed (tags are still in place)\n\n### Core Principle: Tags Are Demand-Driven\n\n- Tags exist ONLY because the template needs them\n- The markdown file is the SOURCE of values, not the source of tags\n- When a slide needs variable data → skill proposes tags by searching the markdown\n- When a slide is removed → skill cleans up orphaned tags\n- NEVER create tags \"just in case\" — only when the template demands it\n- **Protected slides are invisible** — never audit, classify, tag, or suggest tags for them\n- The `protected_slides` list in semantic_mapping.yaml is the authority on which slides are off-limits\n","# PPTX Template Builder\n\nYou convert any base .pptx into a semantic placeholder template through a safe, gated process.\nThe core safety invariant: **python-pptx (structure) -> save -> lxml (content) -> never touch again**.\n\nSee [guardrails.md](guardrails.md) for absolute rules that override all other instructions.\n\n## Argument Parsing\n\nThe user provides a path to a base .pptx file:\n- `\u002Fpptx-template path\u002Fto\u002Fdeck.pptx`\n- If no argument, ask: \"Which .pptx file should I convert to a template?\"\n\n---\n\n## STEP 0: Input + Backup\n\n1. Verify the .pptx exists and can be opened by python-pptx\n2. Copy to a working directory (never modify the original)\n3. Save checkpoint: `_int_ai\u002Fcheckpoint_00_original.pptx`\n4. Report slide count\n5. Ask user:\n   - \"This PPTX has X slides. What type? (BC \u002F BS \u002F OS)\"\n   - \"Where is the corresponding markdown file (e.g., LEAN_BUSINESS_CASE.md)?\"\n\n**GATE**: User provides type and markdown path before proceeding.\n\n---\n\n## STEP 1: Content Alignment Audit (PPTX vs Markdown)\n\n1. Read the base .pptx slide titles and content summaries (python-pptx, read-only)\n2. Read the markdown file section structure (H1, H2, H3 headings)\n3. Compare: which sections exist in both? Which are in markdown but not PPTX? Which are in PPTX but not markdown?\n4. Present alignment table:\n\n```\nPPTX Slide              | Markdown Section       | Match\nCanvas (slide 5)        | Executive Summary      | YES\nWave Gates (slide 12)   | S9.2 Wave Gates        | YES\n(missing)               | S6 Key Assumptions     | NO -- PPTX missing\nRoadmap (slide 36)      | (not in markdown)      | NO -- MD missing\n```\n\n5. Ask: \"Here is how the PPTX aligns with the markdown. Should we add\u002Fremove slides to match? Should we reorder to follow the markdown structure?\"\n\n**GATE**: User decides the target structure.\n\n---\n\n## STEP 2: Structural Inventory (read-only)\n\n1. Catalog all slides: number, title, layout name, SmartArt yes\u002Fno\n2. Present list alongside the STEP 1 alignment\n3. Ask: \"Based on the alignment, do you need to add, remove, or reorder slides? Or is the structure final?\"\n\nIf user says structure is final -> skip to STEP 4.\n\n---\n\n## STEP 3: Structural Changes (python-pptx -- ONE save)\n\n1. Collect ALL operations the user wants (add, remove, reorder)\n2. Execute ALL in ONE python-pptx session (add + reorder + save)\n3. Save checkpoint: `_int_ai\u002Fcheckpoint_03_structured.pptx`\n4. Ask: \"Open in PowerPoint. Is the structure correct?\"\n\n**GATE**: User must confirm before proceeding. If not correct, repeat STEP 3.\n\n---\n\n## STEP 4: Deep Audit (lxml -- on the FINAL structure)\n\n1. **Identify protected slides first.** Read the filler skill spec (e.g., `_int_ai\u002F_pptx_pipeline\u002Ffiller_spec_BC.md`) or ask the user which slides are fully static. Protected slides are: branding\u002Fframework visuals, TOC, section separators, thank-you\u002Fclosing. These slides are SKIPPED entirely in STEPs 4-6.\n2. Present the protected list to the user for confirmation:\n   ```\n   PROTECTED (will NOT be audited or tagged):\n     Slide 2: \"Lean Business Case Structure\" (TOC)\n     Slide 3: \"Intelligent Innovation\" (branding)\n     Slide 4: \"GTM Offering Creation Blueprint\" (framework)\n     Slide 9: \"Thank You\" (closing)\n     Slides 10,12,19,23,36,42: Section separators\n   ```\n3. Parse EVERY `\u003Ca:t>` and `\u003Cdgm:t>` element with lxml across all XML files in the PPTX zip, **excluding protected slides**\n4. Record for each element: file path, element index, text content, parent context\n5. Output: `_int_ai\u002Felement_audit.json` (protected slides are absent from this file)\n6. Save the protected list to `semantic_mapping.yaml` under `protected_slides`\n\n**GATE**: User confirms the protected slide list before proceeding.\n\n**IMPORTANT**: After STEP 3 completes, NEVER use python-pptx again on this file. All subsequent operations use lxml only.\n\n---\n\n## STEP 5: Classify Elements (AI + user review)\n\nClassification rules are defined in [guardrails.md](guardrails.md) under \"Classification\". Key principles:\n\n1. **FIXED**: titles, headers, labels, sub-headers, section numbers, decorative symbols, metric labels\n2. **DATA**: financial figures, descriptions, names, dates, year ranges, status indicators\n3. **Series Pattern Rule**: ANY list of items (bullets, costs, partners, risks, segments, etc.) MUST use `{n}` pattern -- never assume a fixed count. The filler skill determines N from the markdown.\n4. **Object-Grouped Tags**: When a slide has N repetitions of a multi-field object (iterations, milestones, risk cards), tags MUST group by object index: `{{OBJECT_{n}_FIELD}}`, NOT `{{OBJECT_FIELD_{n}}}`. The filler writes complete objects, not parallel lists. See [guardrails.md](guardrails.md) \"Placeholder Naming\" for the full rule and examples.\n5. **Shared Metadata Tags**: iteration number, maturity level, offering name appear across multiple slides -- use consistent tag names (`{{ITERATION_NUM}}`, `{{ITERATION_MATURITY}}`, `{{TITLE_OFFERING}}`)\n6. **Mixed Elements**: when a single text element contains both fixed and variable parts (e.g., \"Iteration 1\" where \"Iteration \" is fixed), split at the `\u003Ca:r>` run level if possible, or document the fixed prefix in the mapping\n7. **Split-Run Words**: PowerPoint may split a word across runs (e.g., \"Itera\" + \"tion 1\"). Place `{{TAG}}` in the first run, clear subsequent fragment runs. See [guardrails.md](guardrails.md) \"Split-Run Words\" for details.\n8. **Sub-label + Bullets**: When a panel has bold sub-labels followed by bullet points, encode the sub-label identity into the series prefix: `{{PREFIX_SUBLABEL_{n}}}`. Always use `{n}` series even for single bullets today. See [guardrails.md](guardrails.md) \"Sub-label + Bullets Pattern\" for full rule and edge cases.\n\n9. **Double-Variable Tables**: When a table has variable rows (BUs, {n}) AND variable columns (capabilities, {m}), use double-index tags: headers as `{{PREFIX_CAP_{m}_HEADER}}`, body cells as `{{PREFIX_{n}_CAP_{m}}}`, and fixed final column (Risk) as `{{PREFIX_{n}_RISK}}` (single index only). Applies to PEOPLE, PROCESS, PLATFORM, PARTNER capability slides. See [guardrails.md](guardrails.md) \"Double-Variable Tables\" for full pattern and example.\n\nAssign semantic `{{TAG}}` names following [guardrails.md](guardrails.md) \"Placeholder Naming\":\n- UPPER_SNAKE_CASE with slide context prefix\n- Series: `{{CANVAS_COST_{n}}}`, `{{EXEC_MILESTONE_{n}_DATE}}`\n- Compound series: `{{EXEC_RISK_{category}_{n}}}`\n\nPresent to user in batches of ~3 slides, element by element, using this format:\n\n```\n=== Slide 12 — Customer Problem (32 elements) ===\n\n| # | Text | Class | Tag \u002F Reason |\n|---|------|-------|--------------|\n| 0 | \"Customer Problem & Use-Case Validation\" | FIXED | Slide title |\n| 1 | (auto-field) | SKIP | PowerPoint slide number |\n| 2-8 | \"Remote customers operating...\" | DATA cluster | {{PROBLEM_STATEMENT}} |\n| 9 | \"Key Data Highlights:\" | FIXED | Section label |\n| 10 | \"High Latency Friction:\" | DATA series | {{PROBLEM_PAIN_{n}_TITLE}} — pain point name varies per offering |\n| 11-13 | \"Standard M365 fails... 600-800ms...\" | DATA series | {{PROBLEM_PAIN_{n}_DESC}} — pain point description |\n| 26 | \"Observable Business Impact:\" | FIXED | Section label |\n| 27 | \"End-user productivity is unreliable...\" | DATA cluster | {{PROBLEM_IMPACT}} |\n```\n\nKey distinctions in the table:\n- **FIXED**: titles, labels, decorative — no tag\n- **SKIP**: auto-fields (`\u003Ca:fld>`) — invisible to the pipeline\n- **DATA series**: repeating items with `{n}` — N determined by BC content\n- **DATA cluster**: named fields with fixed structure — always present\n\n### Label Genericization (inline with classification)\n\nFIXED labels must work for ANY offering, not just the current one. When presenting each batch:\n- For every FIXED label that contains offering-specific or overly narrow language, propose a generic alternative inline\n- Use a separate column or note: `Original: \"Into standardized managed pathways:\" -> Proposed: \"Migration targets:\"`\n- Slide titles are EXCLUDED from this review (they are structural and already generic)\n- The user approves or adjusts each label change in the same review pass\n- Approved generic labels are applied during STEP 6 (lxml injection) alongside placeholder insertion\n\nAsk: \"Review the classification and label proposals. Flip any FIXED \u003C-> DATA and adjust labels as needed.\"\n\n**GATE**: User must approve the full classification before proceeding.\nOutput: `_int_ai\u002Fclassification.json`\n\n---\n\n## STEP 6: Insert Placeholders + Generate Mapping (lxml -- SINGLE pass)\n\nSee [guardrails.md](guardrails.md) \"Injection Engine Rules\" for the mandatory mechanisms.\n\n### 6a. Build the injection script\n\nWrite a Python script with per-slide configs. Each slide MUST have:\n- `pre_fields`: positional tag names for the first N DATA elements (before any group delimiter)\n- `groups`: `{label: prefix}` dict using FIXED labels as delimiters for semantic groups\n- `default`: fallback prefix (should only apply to truly positional tables)\n- `table_cols`: column names for table-structured slides (column cycling)\n\nThe FIXED set MUST be a Python list literal (never parsed from free text).\n\n### 6b. Execute: Label genericization + tag injection in one pass\n\n1. Open checkpoint_03 as zip\n2. For each non-protected slide and its associated diagram files:\n   - Apply label genericizations (old text -> new generic text)\n   - Skip auto-fields (`\u003Ca:fld>`)\n   - Skip FIXED elements\n   - Assign semantic `{{TAG}}` to DATA elements using pre_fields -> groups -> table_cols -> default\n3. For SmartArt: process data{N}.xml AND drawing{N}.xml with the same config\n4. Validate XML after each file modification\n5. Save: `_int_ai\u002Fcheckpoint_06_with_placeholders.pptx`\n\n### 6c. Post-injection verification (mandatory, blocks GATE)\n\n1. python-pptx open test\n2. Count all `{{TAG}}` occurrences\n3. **Scan for generic tags**: any `{{PREFIX_N}}` where PREFIX is a bare default (no semantic group) is a BUG -- fix before proceeding\n4. Report: total tags, tags per slide, any generic tag violations\n\n### 6d. Generate semantic_mapping.yaml (mandatory, same step)\n\nThe YAML is generated from the **template tag inventory**, NOT from the classification.\n\n**Procedure**:\n1. **Scan the injected template** (checkpoint_06): grep all `{{TAG}}` patterns across ALL XML files (slides + diagrams\u002Fdata + diagrams\u002Fdrawing)\n2. **Deduplicate**: build the canonical tag list (unique tag patterns found in the template)\n3. **Enrich**: for each tag in the inventory, add classification metadata (description, suggestion, example, max_chars, type) from the STEP 5 classification output\n4. **Discard phantom tags**: tags in classification but NOT in the template = classification artifacts. Do NOT include them in the YAML.\n5. **Report injection gaps**: tags in the template but NOT in classification = injection bugs. Fix before proceeding.\n\n**Invariant**: `meta.total_tags` MUST equal the count of unique tag patterns found in the template PPTX. If these numbers diverge, the YAML is wrong.\n\n**Why**: Classification defines what SHOULD be tagged. The template defines what IS tagged. The YAML must reflect reality (template), enriched with intent (classification). Previous approach generated YAML from classification (453 patterns) for a template with only 217 actual tags -- causing 80.9% orphan ratio and 9 STRUCTURAL failures during generation.\n\n7. Ask: \"Template has X semantic tags. Opens OK? Check in PowerPoint. Mapping saved to semantic_mapping.yaml.\"\n\n**GATE**: User confirms template + mapping are correct.\n\n---\n\n### 6e. Generate PNG sets (mandatory, same step)\n\nRender the template to two PNG sets for use by fill and QA agents:\n\n1. **Template PNGs** (`OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F`): Render checkpoint_06 to PDF via LibreOffice, then to PNG via pymupdf. Shows `{{TAG}}` placeholders in situ.\n2. **Reference PNGs** (`OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Freference\u002F`): If a completed offering exists (e.g., OFFER-001), render its LEAN_BUSINESS_CASE.pptx. If none exists yet, skip -- reference PNGs will be generated after the first successful fill.\n\nBoth PNG sets are stored in `OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002F`. They serve as visual context for the 3-Layer Context rule (guardrails.md).\n\n**PNG validation (mandatory before and after copy)**:\n\nBefore copying new PNGs to either directory, validate existing state:\n```bash\npython 98_Scripts\u002Fvalidate_slide_pngs.py \"OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F\"\n```\n\nIf mixed naming is detected (old `slide_N.png` + new `page_NN.png`), clean up first:\n```bash\ncd \"OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F\" && rm -f slide_*.png\n```\n\nAfter copying PNGs, re-validate with expected count:\n```bash\npython 98_Scripts\u002Fvalidate_slide_pngs.py \"OFFER-000 (Template)\u002F_int_ai\u002F_int_ai\u002F_pptx_pipeline\u002Fslide_pngs\u002Ftemplate\u002F\" --expected-count 65\n```\n\nDo NOT proceed past this step if validation fails. See guardrails.md \"PNG Directory Management\" for full rules.\n\n---\n\n## STEP 7: Filler Spec + Guardrails Debate\nTags are NOT hardcoded counts -- the filler skill determines how many based on the markdown content.\n\n### B) filler_spec_{type}.md\n\nA reference document for the corresponding filler skill (`\u002Fbc-to-pptx`, etc.) that defines:\n\n1. For each slide: what markdown section feeds it, what data type (text, table, list, number)\n2. For iterative elements: how to determine the count from the markdown\n3. For conditional elements: when to include\u002Fexclude\n4. Content rules (no CIT, no SKU codes, max chars per field)\n5. Validation checks: cross-slide consistency (revenue Y1 must match everywhere)\n6. **Filler skill guardrails** (see debate below)\n\n### C) Generate Script Contract (mandatory, same step)\n\nDuring the filler spec debate, also define the `generate_pptx.py` interface contract:\n\n1. **Input format**: flat JSON with static tags + expanded series (TAG_1, TAG_2, ...)\n2. **Series handling**: join-based (all values joined with `\\n`), NEVER paragraph cloning\n3. **Dedup strategy**: seen_tags set per file, first occurrence kept, rest emptied\n4. **SmartArt file list**: slides + data + drawing (triple-file mandatory)\n5. **Pilot test plan**: 3 representative slides (1 SmartArt, 1 table, 1 canvas) before full run\n\nThis contract becomes Section 9 of the filler_spec. It ensures the injection format and the generation consumption format are aligned from the start.\n\n**Why this is mandatory in STEP 7**: designing the script reactively (after first fill attempt) caused 6 broken iterations. The contract must exist before any fill agent runs.\n\n### C) Filler Skill Guardrails Debate\n\nStructured conversation with the user to define the rules the filler skill must follow for THIS specific template. Walk through each category, suggest defaults, and let the user override.\n\n**1. Protected slides** (carried forward from STEP 4):\n- \"These slides are protected and the filler skill will skip them: [list]. Anything to add or remove?\"\n\n**2. Content vocabulary**:\n- \"What terms are forbidden in this template?\" (suggest defaults: CIT→Cloud & IT, SKU codes→service names)\n- \"Are there any product\u002Fbrand names that should NOT appear because they belong to a different offering?\" (DO NOT assume -- ask. e.g., M365 is forbidden in a 1EDGE deck, but perfectly valid in an EUP deck)\n- \"Should the filler skill auto-fix these or just block and report?\"\n\n**3. Structural constraints**:\n- \"The BC has 7 risks. The template risk heat map has 4 slots. Expand to 7 or summarize to 4?\"\n- \"The BC has 6 segments but the template market table has 5 rows. How to handle?\"\n- \"The SKU breakdown has N services. Does this match the template table rows?\"\n- For each mismatch: decide expand template, truncate data, or flag for user.\n\n**4. Field formatting**:\n- \"Max characters per field type?\" (suggest: title=60, body=200, table cell=80, bullet=150)\n- \"Number format?\" (suggest: $X.XM for millions, $X,XXXK for thousands, X.X% for percentages)\n- \"How to handle bullet lists?\" (suggest: `\\n`-separated within a single field)\n\n**5. Cross-slide consistency**:\n- \"Which values must be identical across slides?\" (suggest: Revenue Y1, fleet\u002Fsite count, target margin)\n- \"How strict? Block on mismatch, or warn and continue?\"\n\n**6. Data completeness**:\n- \"If a markdown section is empty, what should the filler skill do?\" (suggest: leave {{TAG}} visible so QA catches it, vs. insert placeholder text like \"TBD\")\n- \"Minimum fill rate before generation proceeds?\" (suggest: 90% of tags must have values)\n\nAll decisions are recorded in `filler_spec_{type}.md` under a \"Guardrails\" section. These become the enforceable rules for the filler skill.\n\n**GATE**: User approves the mapping, filler spec, AND guardrails before proceeding.\n\n---\n\n## STEP 8: Build\u002FUpdate the Filler Skill\n\nBased on the filler spec, update the corresponding skill:\n- BC templates -> update `.claude\u002Fskills\u002Fbc-to-pptx\u002FSKILL.md`\n- BS templates -> create `.claude\u002Fskills\u002Fbs-to-pptx\u002FSKILL.md`\n- OS templates -> create `.claude\u002Fskills\u002Fos-to-pptx\u002FSKILL.md`\n\nThe filler skill MUST reference:\n- The `semantic_mapping.yaml` (what tags exist)\n- The `filler_spec_{type}.md` (how to fill them)\n- The guardrails (what NOT to do)\n\nAsk: \"Here is the filler skill spec. Does this capture how data flows from markdown to PPTX?\"\n\n**GATE**: User approves.\n\n---\n\n## STEP 9: Extract Data (per offering, using the filler skill)\n\nThis step is performed by the filler skill (e.g., `\u002Fbc-to-pptx`), not by `\u002Fpptx-template`.\nThe filler skill:\n1. Reads the BC\u002FBS\u002FOS markdown\n2. For fixed-count tags: extracts directly\n3. For iterative tags: counts rows in markdown tables, expands pattern, extracts each\n4. For conditional tags: checks if markdown section exists\n5. Validates: no CIT, no SKU codes, no M365, cross-slide consistency\n6. Reports: \"X of Y tags filled. Z empty. W iterative patterns expanded.\"\n\n---\n\n## STEP 10: Generate + QA (reuses existing Worker -> QA pattern)\n\nThis step reuses the existing pipeline -- no duplication:\n\n```\n\u002Fbc-to-pptx (worker, already exists)\n    | Extract data (STEP 9) -> validate -> generate_pptx.py\n    | Render slides -> launch QA swarm\n\u002Fqa-pptx (QA, already exists)\n    | Returns: APPROVED \u002F ISSUES FOUND \u002F CLARIFICATION\n    |\nISSUES -> Fix slide_data -> regenerate -> re-QA (max 2 iterations)\nAPPROVED -> Ask user to open in PowerPoint -> GATE -> Done\n```\n\n| Concern | Existing Tool | NOT duplicated |\n|---------|--------------|----------------|\n| Slide visual QA | `\u002Fqa-pptx` | NOT in \u002Fpptx-template |\n| Error recovery | `\u002Fqa-improve Mode 1` | NOT in \u002Fpptx-template |\n| Data extraction | filler skill (STEP 8) | NOT in \u002Fqa-pptx |\n| Data validation | `validate_pptx_data.py` | NOT in filler skill |\n| PPTX generation | `generate_pptx.py` | NOT duplicated anywhere |\n| Template prep | `\u002Fpptx-template` (this skill) | NOT in filler skills |\n\n---\n\n## Checkpoints and Recovery\n\n| Checkpoint | Created At | Purpose |\n|-----------|------------|---------|\n| `_int_ai\u002Fcheckpoint_00_original.pptx` | STEP 0 | Pristine copy of input |\n| `_int_ai\u002Fcheckpoint_03_structured.pptx` | STEP 3 | After structural changes |\n| `_int_ai\u002Fcheckpoint_06_with_placeholders.pptx` | STEP 6 | Final template |\n\nIf any step fails, restore the previous checkpoint and retry.\n\n---\n\n## Contract\n\n**Deliverables**: Semantic PPTX template with {{TAG}} placeholders, semantic_mapping.yaml, filler_spec_{type}.md, template PNGs\n**Validation**: none (interactive gated builder, user approves at each step)\n**Acceptance Criteria**:\n- All tags have description + suggestion + max_chars in semantic_mapping.yaml\n- Template PNGs generated and validated (no mixed naming)\n- SmartArt triple-file rule followed (slide + data + drawing)\n- No orphan tags (tags in YAML but absent from template)\n- meta.total_tags matches unique tag count in template PPTX\n**Escalation Triggers**:\n- PPTX fails python-pptx open test → restore checkpoint, ask user\n- Orphan tag ratio > 10% → stop, reconcile YAML against template\n**Max Rework Cycles**: 2\n\n## Output Files\n\nWhen complete, the skill produces:\n1. **Template PPTX** -- the .pptx with `{{TAG}}` placeholders\n2. **_int_ai\u002Felement_audit.json** -- full element inventory\n3. **_int_ai\u002Fclassification.json** -- FIXED\u002FDATA classification\n4. **semantic_mapping.yaml** -- tag-to-slide contract\n5. **filler_spec_{type}.md** -- how to fill the template\n\n---\n\n## Update Mode: `\u002Fpptx-template --update path\u002Fto\u002Ftemplate.pptx`\n\nFor maintaining an EXISTING template after the user makes changes in PowerPoint.\n\n### Argument Parsing\n\nWhen invoked with `--update`:\n1. Read the template PPTX (the modified version the user just saved)\n2. Read the last checkpoint (`_int_ai\u002Fcheckpoint_06_with_placeholders.pptx`) as the baseline\n3. Read the associated markdown file (from semantic_mapping.yaml or ask user)\n4. Compare: detect added slides, removed slides, modified content\n\n### When User ADDS a Slide\n\n1. Detect new slide(s) by comparing current template vs checkpoint\n2. Check if the new slide matches a protected category (branding, TOC, separator, closing). If so, add it to `protected_slides` in semantic_mapping.yaml and report: \"New slide 'X' classified as protected (reason). No tags will be created. OK?\"\n3. For each new NON-protected slide:\n   - Read its content (titles, text boxes, tables)\n   - Read the associated markdown file (BC.md, BS.md, OS.md)\n   - Search markdown for sections\u002Fdata that could match the new slide content\n   - Present mapping suggestion to user:\n     ```\n     NEW SLIDE: \"Marketing Intelligence\" (pos 15)\n\n     Markdown matches found in LEAN_BUSINESS_CASE.md:\n       §3.2 Key Market Drivers → could map to slide body\n       §3.4 Competitive Landscape → could map to table\n\n     Suggested tags:\n       {{MARKET_DRIVERS}} → §3.2 bullet list\n       {{COMP_LANDSCAPE}} → §3.4 table data\n\n     Accept these? [Y\u002Fn\u002Fedit]\n     ```\n3. User approves\u002Fedits the tag suggestions\n4. Insert approved `{{TAGS}}` into the template with lxml\n5. Add entries to slide_data with extracted values from markdown\n6. Update semantic_mapping.yaml\n7. Save new checkpoint\n\n### When User REMOVES a Slide\n\n1. Detect removed slide(s) by comparing vs checkpoint\n2. Identify ORPHANED tags: tags in slide_data that no longer appear anywhere in the template\n3. Present cleanup report:\n   ```\n   REMOVED SLIDE: \"Marketing Intelligence\" (was pos 15)\n\n   Orphaned tags (in slide_data but no longer in template):\n     {{MARKET_DRIVERS}} → value: \"CAPEX to OPEX shift...\"\n     {{COMP_LANDSCAPE}} → value: \"Speedcast, Navarino...\"\n\n   Remove from slide_data? [Y\u002Fn]\n   ```\n4. User approves → remove orphaned entries from slide_data and semantic_mapping.yaml\n5. Save new checkpoint\n\n### When User MODIFIES a Slide\n\n1. Detect changed text elements by comparing vs checkpoint\n2. If new text was added that needs a tag → suggest it (with markdown lookup)\n3. If existing tags were removed from the slide → identify as orphans\n4. If text around tags changed → no action needed (tags are still in place)\n\n### Core Principle: Tags Are Demand-Driven\n\n- Tags exist ONLY because the template needs them\n- The markdown file is the SOURCE of values, not the source of tags\n- When a slide needs variable data → skill proposes tags by searching the markdown\n- When a slide is removed → skill cleans up orphaned tags\n- NEVER create tags \"just in case\" — only when the template demands it\n- **Protected slides are invisible** — never audit, classify, tag, or suggest tags for them\n- The `protected_slides` list in semantic_mapping.yaml is the authority on which slides are off-limits\n",{"name":5,"model":37,"context":41,"description":54,"argument-hint":55,"disable-model-invocation":56},"Interactive PPTX template builder and maintainer. Two modes: CREATE: converts any base .pptx into a semantic placeholder template through a gated process. UPDATE: maintains an existing template after user changes (add\u002Fremove\u002Fmodify slides). Use when preparing a new PPTX template, converting a presentation to a template, or updating an existing template after changes. Also use when user says \"template pptx\", \"prepare template\", \"build pptx template\", \"convert pptx to template\", \"update template\", \"sync template\".\n","[--update] \u003Cpath-to-template.pptx>",true,"master","f57cddf3a79f076c1bb1ba9c187850fba797c0c9","skills\u002Fpptx-template",1,"https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro","https:\u002F\u002Fgithub.com\u002FWizarck","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Framirezarturo\u002F","Geek by birth, with not much to say but plenty to talk about.","2026-09-25 20:04:26",{"source":8,"skillName":5,"commands":67,"prompt":77,"zipAvailable":56},[68,71,74],{"tool":69,"command":70},"npx","npx skills add Wizarck\u002Fnexandro --skill pptx-template",{"tool":72,"command":73},"bunx","bunx skills add Wizarck\u002Fnexandro --skill pptx-template",{"tool":75,"command":76},"pnpm","pnpm dlx skills add Wizarck\u002Fnexandro --skill pptx-template","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fpptx-template\u002FSKILL.md",[79],{"path":80,"resourceType":81,"resourceTypeDesc":82,"sizeBytes":83,"sourceHtmlUrl":84},"guardrails.md","REFERENCE","参考文档",41560,"https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fpptx-template\u002Fguardrails.md",[86,114,142,164,178,204],{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":96,"publishedAt":49},"01M71BBM78XJY2YXFXJ2YNCEGY","xlsx","Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file; create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files into proper spreadsheets.","https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fxlsx\u002FSKILL.md",[92,95],{"categoryNo":93,"categoryName":94,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000004","电子表格",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[88,97,98,99,100,101,102,103,104,105,106,46,107,108,109,45,110,111,112,113],"sources","tsv","by name","for","spreadsheet","time","trigger","fix","scratch","open","files","use","Existing","done","convert","file","tabular",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":126,"publishedAt":49},"01M71BBGZJG2FKCPJZWR32SCZ5","use-case-research","Creates JTBD-aligned Use Cases CSVs through structured user interviews, parallel vendor\u002Findustry research, and Jobs-to-be-Done synthesis. Generates 17-column CSV (OFFER-001 format) and validates with \u002Fqa-use-cases. Use when creating or updating use case research for an offering.","https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fuse-case-research\u002FSKILL.md",[120,123],{"categoryNo":121,"categoryName":122,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",{"categoryNo":124,"categoryName":125,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[127,108,128,129,130,131,132,133,45,110,134,135,136,137,138,139,37,140,100,141],"use case research","case","research","industry research","user interviews","qa","jtbd","Bash","websearch","read","write","edit","interviews","parallel","true",{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":149,"publishedAt":49},"01M71BBCCGXCBJZSYK72CT7MJW","sync-jira","Two-way sync between PROGRESS.md pipeline status and JIRA CIT tasks. Use when syncing offering progress with JIRA, checking JIRA status, bootstrapping JIRA tasks for new offerings, or pushing\u002Fpulling status updates. Also use when the user mentions JIRA, CIT tasks, or pipeline sync.","https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fsync-jira\u002FSKILL.md",[148],{"categoryNo":124,"categoryName":125,"taxonomyType":21,"taxonomyTypeDesc":22},[150,151,39,152,153,100,154,155,46,156,108,45,157,134,158,159,160,161,162,163],"sync jira","jira","pull","push","pipeline","status updates","MCP","updates","tasks","bootstrap","dry","two","with","id",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":168,"categories":169,"keywords":171,"publishedAt":49},"01M71BBAV2F4ABBVAM9FMZ692C","strategy","Tunes business strategy and aligns with corporate ABC Goals. Use when working on 01_BS\u002F business strategy files.","https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fstrategy\u002FSKILL.md",[170],{"categoryNo":124,"categoryName":125,"taxonomyType":21,"taxonomyTypeDesc":22},[166,141,107,108,172,45,162,163,173,174,136,137,138,175,176,177],"business","goals","business strategy","corporate","grep","sonnet",{"skillNo":179,"name":180,"nameZh":6,"description":181,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":182,"categories":183,"keywords":188,"publishedAt":49},"01M71BB6N1EJDAMAWAF0FSGFRR","start","Starts the full MCP stack: LiteLLM proxy + Docker services (Hindsight, Atlassian, Google Workspace) + skills-manager + notebooklm. All services connect directly — no proxy. Use \u002Fstart at the beginning of any session where MCP tools are needed, or when any service is stopped. LiteLLM must start before Docker — Hindsight depends on it at startup.","https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fstart\u002FSKILL.md",[184,187],{"categoryNo":185,"categoryName":186,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":124,"categoryName":125,"taxonomyType":21,"taxonomyTypeDesc":22},[180,189,190,191,192,193,194,156,108,195,45,134,196,197,198,199,200,201,202,203],"hindsight","google workspace","proxy","docker","session","litellm","connect","stack","haiku","services","workspace","at","notebooklm","google","startup",{"skillNo":205,"name":206,"nameZh":6,"description":207,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":208,"categories":209,"keywords":211,"publishedAt":49},"01M71BB50307CW202PCTECJ3BB","start-palafito","Úsalo cuando el usuario quiere arrancar el stack palafito-prod (Paperclip) y, si hace falta, levantar Docker Desktop antes.","https:\u002F\u002Fgithub.com\u002FWizarck\u002Fnexandro\u002Fblob\u002Fmaster\u002Fskills\u002Fstart-palafito\u002FSKILL.md",[210],{"categoryNo":185,"categoryName":186,"taxonomyType":21,"taxonomyTypeDesc":22},[180,212,196,213,214,215,134,192,177],"start palafito","desktop","fork","paperclip"]