OpenHarmony Requirement-Review PPTX Deck Generation

SkillDocs & knowledge

Use when converting an OpenHarmony requirement document, spec, or design proposal into an OpenHarmony review slide deck (需求评审 / 需求变更评审 / 设计评审 PPTX) — produces the fixed OpenHarmony-branded review-deck structure (OH logo on every page) with architecture/flow diagrams and field tables. Triggers on "需求评审PPT", "需求变更评审", "把需求文档转成评审PPT", "spec转评审PPT", "requirement/spec to review deck". NOT for arbitrary or generic slide decks unrelated to OpenHarmony requirement/design review.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the OpenHarmony Requirement-Review PPTX Deck Generation skill

What this skill tells your AI

The instructions your AI receives, as published by openharmonyinsight/openharmony-skills in skills/ohos-req-review-ppt-gen/SKILL.md and read by ahel’s review.

Overview

Build clean, consistent 16:9 PowerPoint decks by calling a ready-made helper library — you supply only content; the library owns all coordinates, colors, fonts, spacing, and arrow-drawing.

Core principle: Never compute slide geometry or restyle shapes by hand. Import deckbuilder.Deck and call its slide methods. Building raw python-pptx shapes from scratch is the #1 cause of broken layouts, overlapping boxes, text-only "diagrams", and wrong imports. Don't do it.

Fastest path — 需求评审 in ONE call (start here)

If the task is an OpenHarmony 需求变更评审 / 需求评审 deck (the common case), do NOT hand-assemble slides and do NOT choose builders yourself. Fill one plain spec dict and make a single call — the library owns the page order, which builder each page uses, and every fixed table shape (5 影响对象 rows, 8 风险 rows, 11 交付 columns). This is the most reliable path and removes the top mistake (picking the wrong builder, e.g. four cards for the 价值 page).

from deckbuilder import Deck
Deck().requirement_review_deck(spec).save("requirement_change_review.pptx")
  • Copy examples/requirement_review_oneshot.py, replace the <placeholders>, keep the structure, run it. That's the whole job.
  • Every field is optional — anything you leave out renders as 待评估 / TBD, never fabricated. List those TBD fields back to the user.
  • spec["design"] may be one dict (one 设计方案 page) or a list of dicts (multiple, auto-paged). spec["delivery"]["items"] is one row per 子需求; the 合计 row is summed for you.
  • The 8 fixed pages, in order: 封面 · 需求价值描述 · 需求设计方案 · 需求变更背景 · 需求变更影响性分析 · 版本交付计划 · 兼容性分析 · 风险评估.

The full spec shape is documented in the requirement_review_deck docstring and in examples/requirement_review_oneshot.py. Everything below is the manual / advanced mode — the individual builders, for non-review decks or one-off custom pages.

Page → builder map (do not deviate)

For 需求评审 pages, each page has exactly ONE correct builder. Never use content_slide / banded_slide for the 价值 or 设计 pages — that produces the "four boxes" / rainbow-bars result. (The library will warnings.warn if you do.)

PageBuilderNever use
需求价值描述value_slide (左文右图)content_slide (四格)
需求设计方案design_slide + diagram= (左文右图+框图)content_slide / bullet list
需求变更背景 / 影响性分析 / 兼容性 / 风险table_slidebanded_slide (彩色横条)
版本交付计划table_slide (11 列)❌ 手写列宽/字号

When to Use

  • Converting an OpenHarmony requirement document / spec / design proposal into a review deck — this is the primary trigger
  • 需求评审 / 需求变更评审 / 设计评审 decks (OH-branded, fixed structure)
  • Feature-proposal decks that follow the OH review flow
  • Such decks needing an architecture / data-flow diagram (real boxes + arrows) or comparison / breakdown tables

When NOT to use: generic or non-OpenHarmony slide decks (this skill always stamps the OpenHarmony logo and imposes the OH review structure — it is not a general-purpose PPT maker); editing an existing .pptx the user already has (open it with python-pptx directly); or when the user wants Markdown/PDF instead.

Setup (do this first)

python3 -c "import pptx" 2>/dev/null || pip install python-pptx

The library file deckbuilder.py lives in this skill's scripts/ directory, alongside oh_logo.png (the OpenHarmony logo). Copy both (keep them together) next to your build script, or add the scripts/ dir to sys.pathdeckbuilder.py auto-finds the logo in its own directory, so the two files must stay side by side. Then write ONE script that imports it and calls slide methods in order, e.g.:

import os, sys
sys.path.insert(0, os.path.join("<skill-dir>", "scripts"))
from deckbuilder import Deck

Visual style (built in — do not re-implement)

The library renders a light theme with a red accent ("red ink"): titles are near-black ink (subdued, not a loud color), a single red accent carries each page's conclusion and primary path, structure is soft neutral grey, blue is used for value-page body text and table headers, and amber is reserved for change points. Every choice below is automatic, you never set colors or coordinates:

  • The conclusion is the highlight, not the title. Each page's 32pt title is calm near-black ink (primary); the eye is drawn instead to the takeaway conclusion line, rendered in red (accent) right under the title. The red accent also draws the title underline and primary data-flow arrows. Everything else — secondary arrows, grid, connector bars, box borders — is soft grey (grey). Do NOT give cards/sections different accent colors — that produces a rainbow ("不纯粹") deck. Leave accent unset (defaults to red).
  • Reserve hue changes for real meaning only: red (a muted brick-red) for an actual risk/blocker; the built-in ★变更 change box (a light-amber fill with an amber badge, drawn for you when you pass "change": True). green (the logo green) exists but is rarely needed — don't sprinkle colors to "add color".
  • Cover & headers. Cover has a thin red spine; each content page is a 32pt Microsoft YaHei ink title on white with a thin red underline and the page number top-right.
  • OpenHarmony logo, bottom-left of every page (cover included) — added automatically from oh_logo.png. If the file is missing it's silently skipped.
  • Diagrams are real drawing boxes — rounded rectangles joined by arrows.
  • Tablesslate-blue header (C6D7EC) with black bold text, white body, and black solid grid lines; fonts follow the value/design page standard (header 15pt bold, body 13.5pt). Light-red total row when highlight_last=True. All drawn for you.

The Only API You Need

from deckbuilder import Deck

deck = Deck()                    # 16:9; font defaults to "Microsoft YaHei"

# ── EASIEST: whole 需求评审 deck in one call (see "Fastest path" above) ──
deck.requirement_review_deck(spec)   # spec = dict; fixed 8-page 需求变更评审

# ── or assemble pages manually (advanced / non-review decks) ──
# NOTE: every content slide below REQUIRES takeaway="结论:…" (the page's one-line
# conclusion) — pass it as a keyword. Omitting it raises ValueError. Only cover()
# takes no takeaway.
deck.cover(title, subtitle=None, meta_lines=[...])
deck.content_slide(title, cards, takeaway="结论:…", subtitle=None)
deck.banded_slide(title, sections, takeaway="结论:…", subtitle=None)
deck.bullets_slide(title, bullets, takeaway="结论:…", subtitle=None)
deck.table_slide(title, headers, rows, takeaway="结论:…", col_widths=None, highlight_last=False)
deck.flow_slide(title, stages, takeaway="结论:…", note=None, lane_label=None)
deck.layered_diagram_slide(title, layers, takeaway="结论:…", connect=None, note=None)
deck.architecture_slide(title, nodes, edges, takeaway="结论:…", note=None)
# Two-column pages (左文右图) — title is 28pt bold YaHei; takeaway is OPTIONAL here:
deck.value_slide(title="需求价值描述", background=[...], features=[...], scope=[...], image=None)
deck.design_slide(title="需求设计方案", design=[...], changes=[...], extra=None, image=None)
deck.save("output.pptx")

Every page leads with its conclusion — takeaway is REQUIRED. Pass takeaway="结论:…" (one short sentence) to every content slide — it renders as a bold red line with a red kicker right under the (subdued ink) title, so the reviewer's eye lands on the point before the detail. The title stays the topic label (五、兼容性分析); the takeaway carries the verdict (不改变公开 API 行为,应用无需适配). Write an assertion, not a restatement of the title. subtitle (small grey) still exists for neutral scope notes; if both are given, takeaway wins the slot. takeaway is mandatory: a content slide built without it raises ValueError and the deck will not save. There is no way to ship a page without its 突出重点 — write the one-line verdict for every slide.

Page numbers auto-increment (cover is excluded). Header band, accent colors, and spacing are automatic. Colors are passed by name string"accent" (red) and "grey" (soft grey) cover almost everything; "red" for a genuine risk; "green", "orange", "primary" exist but are rarely the right call. Default to omitting accent (or using "accent") so the deck stays one coordinated family — don't vary it per card just to add color.

Quick reference — what each method takes

MethodKey argument shape
requirement_review_deckspec={...} — whole 8-page 需求变更评审 in one call. Preferred for review decks. Missing fields → 待评估/TBD. See examples/requirement_review_oneshot.py
coverstrings + meta_lines=["Team", "2026-06-23"]
content_slidecards=[{"title","bullets":[...]}] (1–6 auto-grid). Per-card accent is ignored — all cards render in one family (no rainbow). For 需求变更评审 4–7 use table_slide, not this
banded_slidesame sections=[{"title","bullets"}] shape, rendered as full-width horizontal bars stacked top→bottom. Per-section accent is ignored — all bars are one color. Avoid for 需求变更评审 4–7 (use table_slide); the colored 横条 it used to make were the #1 "不纯粹" complaint
bullets_slidebullets=["text", {"text","level":1,"accent","bold"}]
table_slideheaders=[...], rows=[[...],[...]], highlight_last=True for totals. col_widths are relative weights — auto-scaled to fit, never overflow
flow_slidestages=[{"title","lines":[...],"change":True}] → 1 row, auto arrows
layered_diagram_slidelayers=[{"label","nodes":[{"title","lines","change"}]}] + optional connect
architecture_slidenodes=[{"id","title","lines","row","col","change"}], edges=[{"from","to","label","dir":"f"/"both","accent"}] — labeled directional connectors for high-level module interaction
value_slidebackground=[...], features=[...], scope=[...], image=None. Two-column 需求价值描述 page (see below). takeaway optional
design_slidedesign=[...], changes=[...], extra=[{"heading","lines"}], image=None. Two-column 需求设计方案 page (see below). takeaway optional

需求价值描述 / 需求设计方案 — the two-column pages (左文右图)

Two dedicated builders for the standard 需求评审 value + design pages. Title is Microsoft YaHei, bold, 28pt (auto-shrinks only if absurdly long). Left column = stacked sections; right column = a scene/architecture image (pass image=) or, if omitted, a labeled placeholder card telling the user where to paste one. Typography is fixed and built in — section heading 15pt bold, body 13.5pt, not bold. takeaway= is OPTIONAL on these two pages (they lead with their sections, not a one-line verdict).

value_slide — 需求价值描述 (3 sections)

deck.value_slide(
    title="需求价值描述",
    background=["…"],   # 段一「背景」    — body BLUE 13.5pt
    features=["…"],     # 段二「特性及价值点」— body BLUE 13.5pt
    scope=["…"],        # 段三「需求收益(影响)范围」— body BLUE 13.5pt
    image="scene.png",  # 右侧场景图(可选,缺省显示占位卡)
)
  • 段一「背景」 — 蓝色正文。需求由来 / 现状问题。
  • 段二「特性及价值点」 — 蓝色正文。明确需求价值所在,参考:用户痛点、需求功能点、 范围、用户场景、所带来的价值。toD 内容需明确开发者适用范围、明确开发者完成后达成的 结果;能力提升需求不能脱离业务(除能力目标外,需能力提供后的业务目标能力开放范围); 可量化目标:用户活跃数、好评率、新增用户留存等;产品范围:1+8+N 涉及的产品。
  • 段三「需求收益(影响)范围」 — 蓝色正文。描述特性的使用范围、地区、具体产品重点关注特性通用性,不允许仅为单个产品做特性(硬件依赖除外)。
  • 右半部分贴场景图展示该特性的价值。

design_slide — 需求设计方案 (左文右图,可多页)

deck.design_slide(
    title="需求设计方案",
    design=["…"],    # 1、设计方案:设计重点(交互模块及如何达成需求的规格等)
    changes=["…"],   # 2、变更点及影响(见下)
    extra=[{"heading": "三、UI 示意", "lines": ["…"]},
           {"heading": "四、裁剪说明", "lines": ["…"]}],   # 可选追加段落
    image="arch.png",   # 右侧架构图(可选)
)
  • 1、设计方案 — 输出设计方案设计重点,如交互模块及如何达成需求的规格等。
  • 2、体现变更点及影响 — 包括但不限于:数据结构变更、外部接口变更、外部依赖分析、 性能功耗评估、影响用户体验的关键 KPI 等。
  • 设计方案可以有多种,可多页输出 —— 每个方案各调用一次 design_slide(自动翻页)。
  • 如涉及 UI,需具体示意图 —— 把示意图作为 image= 贴在右侧,或在 extra 里加「UI 示意」段。
  • 如裁剪已上线需求,需需求方意见 —— 在 extra 里加一段说明。
  • 右边可贴架构图补充展示image=)。

Architecture diagrams (the part models get wrong)

A design/system slide MUST be a real diagram — boxes connected by arrows — not a bullet list. Three builders, all auto-layout and auto-draw arrows. Pick by intent:

  • flow_slide — one left-to-right pipeline (data flow through stages).
  • layered_diagram_slide — stacked planes (e.g. control plane over data plane).
  • architecture_slidehigh-level module interaction: how a subsystem touches its peers. Use this for the "系统级架构 / 对 OpenHarmony 整体影响" slide. Labeled, directional connectors say WHAT each link is and WHICH way it flows — far clearer than uniform arrows. See the requirement-review template for the canonical OH-module example.

Simple pipeline — one left-to-right flow. Mark changed components with "change": True (renders a light-amber box with an amber ★变更 badge + border):

deck.flow_slide("System Design — Data Flow", [
    {"title": "HID device",   "lines": ["USB / BT"]},
    {"title": "normalize",    "lines": ["resolve binding"], "change": True},
    {"title": "windows mgr",  "lines": ["hit test, isolate state"], "change": True},
    {"title": "UDS dispatch",  "lines": ["consistent ids"]},
], takeaway="结论:变更集中在 normalize 与窗口命中两处",
   note=["normalize resolves the binding before coordinate calc.",
         "Light-amber ★变更 boxes are the change points."])

Layered diagram — stacked planes (e.g. control plane over data plane). Each layer is a row; connect draws vertical arrows between nodes by [layer, node] index:

deck.layered_diagram_slide("System Design — Framework", [
    {"label": "control", "nodes": [
        {"title": "Service (SA)", "lines": ["bind request"]},
        {"title": "BindHelper",   "lines": ["runtime state", "inner API"], "change": True}]},
    {"label": "data", "nodes": [
        {"title": "device",    "lines": ["event"]},
        {"title": "normalize", "lines": ["resolve"], "change": True},
        {"title": "dispatch",  "lines": ["consistent"]}]},
], connect=[[[0, 1], [1, 1]]],   # BindHelper → normalize (down arrow)
   takeaway="结论:BindHelper 变更下沉到 normalize 阶段",
   note="Helper feeds the normalize stage.")

Requirement-CHANGE-review decks (需求变更评审) — use the fixed template

Prefer the one-call path (deck.requirement_review_deck(spec) — see "Fastest path" at the top). It builds this exact 8-page structure for you, so you can skip the manual builder choices below. The rest of this section documents what each page contains — useful for filling the spec, or for building pages by hand when you need a variation.

When the user asks for a 需求变更评审 / requirement-change-review deck, or gives a page-by-page brief (需求价值 → 需求设计方案 → 需求变更背景 → 需求变更影响性分析 → 版本交付计划 → 兼容性分析 → 风险评估), follow the 8-page structure in requirement-review-template.md instead of inventing an outline. examples/requirement_review_example.py is a complete, generic fill-in deck.

The fixed page order (cover counts as page 1):

  1. 封面cover
  2. 需求价值描述value_slide (左文右图, unchanged)
  3. 需求设计方案design_slide (左文右图 + 右侧框图, unchanged; 可多页)
  4. 需求变更背景table_slide: ① 需裁剪/变更的需求说明(原始需求/编号、特性概述与影响、使用场景,重点 2C/2D 价值与影响);② 原始被接纳时的决策纪要(SIG 评审通过记录)
  5. 需求变更影响性分析table_slide, 5 行: 北向应用开发者/南向开发者/分布式设备/系统开发者(跨子系统依赖)/设备使用者
  6. 版本交付计划table_slide, 11 列横向计划表:承接领域/承接类型(IR/SR)/主要需求内容/落地版本/设计者/代码行数/是否涉及API/端到端工作量(500行≈1人月)/领域PM/管道是否满足/工作量是否由领域PM审核OK。把需求拆解成多个子需求,一行一个、逐行呈现工作量,末行用 highlight_last=True 合计
  7. 兼容性分析table_slide: 是否涉及应用兼容性;兼容性包括(机制/权限/API行为/其它);兼容性方案;应用适配方案和计划
  8. 风险评估table_slide, 固定 2 列 8 行 checklist

What this page reliably gets wrong (the top two are the most-reported):

  • Pages 4–8 must be table_slide, never banded_slide / content_slide. The bar/card builders tempt you to color each section differently → multi-colored 横条 ("不纯粹"). Build them as field tables (页 4/5/7/8 两列 分项|内容;页 6 为 11 列宽表). (The engine also forces those builders to one color now, but tables are the right layout here.)
  • Every table_slide page must pass takeaway="结论:…" — a topic title over a table with no conclusion has no 突出重点. This is enforced: a slide without takeaway raises ValueError, so the deck will not build until every page has its verdict. (value_slide / design_slide take takeaway optionally.)
  • Keep pages 2–3 (价值/设计) as the two-column 左文右图 builders — do NOT convert them to tables. Page 3's right column is a real 框图 (diagram= layers or image=), never a bullet list.
  • Page 5 has exactly 5 影响对象 rows, in order: 北向应用开发者 → 南向开发者 → 分布式设备 → 系统开发者(跨子系统/部件依赖)→ 设备使用者(性能/功耗/功能/体验).
  • Page 6 版本交付计划 is a fixed 11-列 wide table — 把需求拆解成多个子需求,一行一个、 逐行呈现工作量,末行 highlight_last=True 合计;表头/正文字号随列数自动收缩,不要手设字号 或写死列宽英寸;col_widths 传相对权重。
  • Page 8 is a fixed 2×8 checklist — these 8 rows, in order: 对性能/功耗/RAM/ROM 是否有影响;是否存在其他依赖关系;是否有安全风险;是否涉及合法/合规问题;是否涉及外部 承诺;是否开源;是否涉及 AI;隐私风险特性识别. Answer each with 是/否/待评估 + 一句话。
  • Mark absent fields 待评估 / TBD (需求编号、SIG 决策纪要、落地版本、设计者、代码行数、 端到端工作量、领域PM、适用地区/产品、外部承诺、合规/安全结论) and list them back to the user — never fabricate them.

Workflow

  1. Install python-pptx if missing; make scripts/deckbuilder.py importable (add the scripts/ dir to sys.path, keeping oh_logo.png alongside it).
  2. If the source is a spec/doc, read it and pull the real content per slide. Don't invent technical facts; if a number (e.g. effort) isn't given, label it an estimate or use TBD.
  3. Write the build script:
    • 需求评审 deck → copy examples/requirement_review_oneshot.py, fill spec, deck.requirement_review_deck(spec)deck.save(). One call, done.
    • Other decks → Deck() → one method call per slide → deck.save().
  4. Wrap the build in warnings.catch_warnings(record=True) so any table_slide content-overflow warning is captured, not just printed and lost — see Verification below.
  5. Run it. Then verify (next section). Report the output path + slide count.

Verification before claiming done

Always run this after building — it confirms the file opens, no table_slide overflowed its content, and nothing overflows the canvas:

import warnings
with warnings.catch_warnings(record=True) as w:
    warnings.simplefilter("always")
    # ... build the deck here (or re-import/re-run the build script) ...
    table_warnings = [str(x.message) for x in w if "table" in str(x.message)]

from pptx import Presentation
p = Presentation("output.pptx"); W, H = p.slide_width, p.slide_height
bad = 0
for i, s in enumerate(p.slides):
    for sh in s.shapes:
        if sh.left is None: continue
        if sh.left < 0 or sh.top < 0 or sh.left+sh.width > W+2000 or sh.top+sh.height > H+2000:
            bad += 1; print("overflow on slide", i+1)
print("slides:", len(p.slides._sldIdLst), "overflow:", bad,
      "table warnings:", len(table_warnings))
# both overflow == 0 AND table_warnings == [] must hold

No renderer (LibreOffice) is needed; the bounds check is the smoke test. It catches SHAPE-level overflow (a table/box positioned or sized past the canvas edge). table_slide() now sizes each row to the actual measured wrapped-text height of its cells (not a flat row-count average), and leaves the table at its true (taller) height instead of force-compressing it when content doesn't fit — so a table with genuinely too much text pushes its shape past BODY_BOTTOM and IS caught by the check above, rather than silently shrinking rows until text is visually clipped. If table_slide() cannot fit the content even at its minimum font size, it also raises a Python UserWarning naming the table — treat that warning as a build failure and split the rows across multiple table_slide() calls or shorten the cell text.

takeaway is enforced — the build fails without it. A content slide built without takeaway="结论:…" raises ValueError naming the slide, so a deck that saves successfully already has a conclusion on every page. If your script errors with slide '…' was built without takeaway=, add the one-line verdict to that slide and rerun — do not work around it.

Common Mistakes

MistakeFix
Hand-assembling a 需求评审 deck page by page (and picking a wrong builder)Use deck.requirement_review_deck(spec) — one call, fixed 8 pages
价值/设计页做成 content_slide 四格 / bullet 列表value_slide / design_slide(左文右图;设计页右侧传 diagram=)— the library warns if you don't
Building shapes with raw python-pptx and hand-picked inchesUse Deck methods; they place everything for you
from pptx.dgm... / guessing import pathsThe library already imports correctly — just from deckbuilder import Deck
Design slide is a bullet list, not a diagramUse flow_slide or layered_diagram_slide
Passing RGBColor(...) everywherePass color names; default to "accent"/"grey", names map to the palette
Giving every card/section a different accent (rainbow 横条)Don't — per-card/section colors are ignored by design; for 需求变更评审 4–7 use table_slide
Pages 4–8 as colored banded_slide barsUse table_slide (分项|内容 / 计划宽表) — the bars invite the "不纯粹" rainbow
Pages with no point — just a topic title over a tableGive every content slide a takeaway="结论:…" one-liner; it's required — a slide without it raises ValueError
Cramming 8+ cards on one slideMax 6 per content_slide; split across slides
Putting >8 rows in one table at full fontThe library auto-shrinks; still split very long tables
Claiming done without running itRun the script + the overflow check, report path & slide count

Real-World Impact

This skill was distilled from building OpenHarmony 需求变更评审 decks (cover, 需求价值 描述, 需求设计方案, 需求变更背景, 需求变更影响性分析, 兼容性分析, 风险评估). The 两-column 价值/设计 pages carry a real 框图 on the right, and the change-review pages (4–7) are clean 分项|内容 field tables — both reproducible in a few lines via value_slide / design_slide / table_slide.

Signals

GitHub stars
34
Forks
7
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
ohos-req-review-ppt-gen
Source
github.com/openharmonyinsight/openharmony-skills