Version: 2.3.3-harness-v2 · Engine: MckEngine (python-pptx) · Author: likaku
Required tools: Read, Write, Bash · Requires:
pip install python-pptx lxml
Common failure modes (must read before each generation, before HARD RULES)
Telling the AI what effect you want is usually not enough; telling it where previous people are most likely to break down works better. The following three anti-patterns have all been verified in real execution and must be actively guarded against every time.
Anti-pattern 1: Verbally declaring "gate passed" (most common)
Wrong approach:
"S4 QA has 7 errors in total, all judged to be engine design behavior, gate passed, entering S5"
What the problem is:passed is judged verbally by the AI, not derived by a program. No matter how sufficient the reason is, this sentence is the AI writing a completion certificate for itself.
Correct approach:
- Execute
python references/scripts/gate_check.py <pptx路径> <项目目录> - Read
<项目目录>/gate_result.json - Only
gate_result.jsonin"passed": truewhen, can enter S5 - If
"passed": false, fixuser_code_errorsthe issues in the list, re-render, and execute gate_check again
Anti-pattern 2: S3 gate "running through it in your head" counts as passed
Wrong approach:
"S3 content gate pre-check: API format is correct, word count is within the limit, passed, entering S4" (no code was executed)
What the problem is: the 3 API format errors that actually occurred today (four_column/matrix_2x2/executive_summary parameter format), cannot be caught by running through it in your head; they must be caught by code checks.
Correct approach:
- Execute
python references/scripts/gate_check_s3.py <content.json路径> <项目目录> - Read
<项目目录>/gate_s3.json - Only
"passed": truewhen, can enter S4 - If there are
failitems, correctcontent.json, and execute gate_check_s3 again
Anti-pattern 3: engine_bug classification as a soft escape hatch
Wrong approach:
"peer_font_inconsistency is engine internal design behavior, not a user code issue, can be let through"
What the problem is: this classification itself is correct, but when made verbally by the AI in the conversation, it is equivalent to handing the exemption right to the AI itself - and the AI has an incentive to let itself pass.
Correct approach:
gate_check.py has a hard-coded ENGINE_BUG_WHITELIST enumeration. Only error categories in the whitelist will be exempted. The whitelist is code, not the AI's judgment. If you think a certain type of error should be added to the whitelist, modify gate_check.py the enumeration in, rather than verbally declaring an exemption.
HARD RULES (must be followed, cannot be bypassed)
- Each generation must follow the five-stage process, "one-sentence direct generation" is not allowed to skip the preceding stages
- TaskCreate drives progress: create 5 tasks before starting, and immediately TaskUpdate completed after each stage is completed
- Load context on demand: each stage only reads the corresponding file, do not load all the content from the old SKILL.md at once
- Gates must be machine-readable: S3 and S4 gates must execute the corresponding gate_check script and read the JSON result; verbal judgment is not allowed
- Self-Refinement is mandatory: after each correction of a pattern-level issue, write to
experiences/the corresponding file - Engine path is fixed:
sys.path.insert(0, os.path.expanduser('~/.workbuddy/skills/mck-ppt-design'))
Knowledge routing (context loading index)
At the start of each stage, read the corresponding file. Do not read everything all at once.
| Stage | Must read | Description |
|---|---|---|
| S1 Requirements | references/team/brand-guide.md |
Understand design constraints |
| S2 Structure | references/framework/engine-api.md + references/layout-matrix.yaml |
Layout selection and capability boundaries |
| S3 Content | references/framework/guard-rails.md + experiences/*.md(when present) |
Overflow prevention rules + historical pitfalls |
| S4 Rendering | Used references/layouts/*.md(read-only layouts actually used) |
Layout implementation details |
| S5 Delivery | None | — |
Full routing table:references/INDEX.md
Five-stage generation process
┌─────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ ┌──────────┐
│ S1 需求 │──▶│ S2 结构 ⭐ │──▶│ S3 内容 ⭐ │──▶│ S4 渲染+QA ⭐⭐│──▶│ S5 交付 │
│ brief.md│ │ outline.json│ │content.json │ │ .pptx │ │ + 沉淀 │
└─────────┘ └─────────────┘ └─────────────┘ └──────────────┘ └──────────┘
⭐ = 门禁(FAIL 则在本阶段修正,不得跳过)
S3/S4 门禁必须运行 gate_check 脚本,读 JSON 结果 — 不得口头宣布通过
Stage 1: Requirements Definition
Read files:references/team/brand-guide.md
Collect information:
- Audience (job title/decision-making role)
- Goal (decision/reporting/persuasion)
- Duration (minutes → approx. 1 minute/page)
- Key messages (at most 5 core messages)
- Data sources (what data is available)
Output: Create in the working directory ppt-project-{slug}/brief.md
Gate:audience + goal + key_messages The three items are non-empty (AI self-assessment is sufficient)
Stage 2: Structure Design
Read files:references/framework/engine-api.md, references/layout-matrix.yaml
Tasks:
- Determine the number of pages based on duration (1 minute/page)
- Select for each slide
layout(check the engine-api.md quick reference table) - Write one core statement per page
key_point(a complete sentence, not a label) - Confirm the layout is within capability boundaries (check layout-matrix.yaml)
Output:ppt-project-{slug}/outline.json
{
"brief": {"audience": "董事会", "goal": "战略汇报", "duration_minutes": 15},
"slides": [
{"idx": 1, "layout": "cover", "title": "Q1 2026 战略回顾", "key_point": ""},
{"idx": 2, "layout": "toc", "title": "目录", "key_point": ""},
{"idx": 3, "layout": "table_insight", "title": "市场格局三大转变驱动战略重构", "key_point": ""}
]
}
⭐ Gate S2(AI self-assessment):
-
coverSlides exist - The number of slides is within the duration constraint (
count <= duration_minutes * 1.2) - All layouts are in
layout-matrix.yamldefined in - Action Titles are all complete sentences (len > 10, contains a verb)
-
two_column_textQuantity ≤ 1
Stage 3: Content Population
Read files:references/framework/guard-rails.md, experiences/*.md(all existing files)
Tasks:
- Populate each slide with specific copy, numbers, and chart data
- Ensure each page has
sourcesource - According to
layout-matrix.yamlofchar_budgetcontrol the amount of text
Output:ppt-project-{slug}/content.json
⭐ Gate S3(must be machine-readable, AI self-assessment is not allowed):
python ~/.workbuddy/skills/mck-ppt-design/references/scripts/gate_check_s3.py \
<项目目录>/content.json <项目目录>
Read <项目目录>/gate_s3.json:
"passed": true→ proceed to S4"passed": false→ correctcontent.jsoninfail_itemsthe listed issues, and re-execute
Stage 4: Rendering + QA
Read files: the references/layouts/*.md
Tasks:
- Based on
content.jsongenerate the Python rendering script - Execute the script to generate
.pptx - Run the QA gate script
⭐⭐ Gate S4(must be machine-readable, cannot be verbally declared as passed):
python ~/.workbuddy/skills/mck-ppt-design/references/scripts/gate_check.py \
<pptx路径> <项目目录>
Read <项目目录>/gate_result.json:
"passed": true→ proceed to S5"passed": false→ viewuser_code_errors, fix the rendering code, re-render, and execute again
Note:engine_bug category errors (peer_font_inconsistency whitelist entries such as these) are automatically exempted by the script and do not require verbal AI judgment.
Output:<项目目录>/gate_result.json + .pptx
Stage 5: Delivery + Self-Refinement
Tasks:
- Read
gate_result.jsonconfirmpassed: true(Must not claim passing when this file is absent) - Deliver
.pptxfile - Self-Refinement: determine whether there is a pattern-level correction this time
⭐ Self-Refinement Protocol:
修正后判断:
ONE-TIME(单次特定调整)→ 不需要沉淀
PATTERN(跨 deck 可重现的问题)→ 必须写入 experiences/
- 溢出类 → experiences/overflow.md
- 图表限制 → experiences/chart-limits.md
- 版式踩坑 → experiences/layout-pitfalls.md
- 中文渲染 → experiences/cjk-issues.md
格式:
## Experience NNN: {title}
**Date**: YYYY-MM-DD
**Problem**: ...
**Root Cause**: ...
**Fix**: ...
**Rule**: ...(门禁层面如何预防)
Fast Track (skip S2/S3 gates for simple requirements)
Whenallconditions are met, the AI may skip the S2 structural review and S3 content review:
- Total pages ≤ 5
- No data charts (donut/bar/table types)
- The user explicitly expresses "quick"/"need it right away"/"simple"
Still mandatory: S1 requirements gathering + S4 QA gate (gate_check.py script execution) + S5 delivery
Checkpoint / breakpoint recovery
When the user says "continue working on that PPT":
import os, json, glob
projects = glob.glob('ppt-project-*/')
for proj in projects:
brief = os.path.exists(f'{proj}brief.md')
outline = os.path.exists(f'{proj}outline.json')
content = os.path.exists(f'{proj}content.json')
gate_s3 = os.path.exists(f'{proj}gate_s3.json')
gate_s4 = os.path.exists(f'{proj}gate_result.json')
pptx = bool(glob.glob(f'{proj}*.pptx'))
if not brief: stage = 1
elif not outline: stage = 2
elif not content: stage = 3
elif not gate_s3: stage = '3-gate' # content 有了但 gate 还没跑
elif not pptx: stage = 4
elif not gate_s4: stage = '4-gate' # pptx 有了但 gate 还没跑
else: stage = 5
print(f"项目 {proj}: 当前处于 Stage {stage}")
MckEngine quick template
import sys, os
sys.path.insert(0, os.path.expanduser('~/.workbuddy/skills/mck-ppt-design'))
from mck_ppt import MckEngine
from mck_ppt.constants import *
eng = MckEngine(total_slides=12)
eng.cover(title='标题', subtitle='副标题', author='作者', date='2026年')
eng.toc(items=[('1', '章节一', '一句话描述'), ('2', '章节二', '一句话描述')])
# ... 内容页 ...
eng.closing(title='谢谢', message='期待进一步交流')
eng.save('output/deck.pptx') # 自动 full_cleanup
Detailed API:references/framework/engine-api.md
Layout specifications:references/layouts/
10 guardrails:references/framework/guard-rails.md
Layout capability boundaries:references/layout-matrix.yaml
Historical pitfalls:experiences/
S3 gate script:references/scripts/gate_check_s3.py
S4 gate script:references/scripts/gate_check.py