skills/ohos-req-review-ppt-gen/SKILL.md
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.
npx skillsauth add openharmonyinsight/openharmony-skills ohos-req-review-ppt-genInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
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")
examples/requirement_review_oneshot.py, replace the <placeholders>,
keep the structure, run it. That's the whole job.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 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.
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.)
| Page | Builder | Never use |
|------|---------|-----------|
| 需求价值描述 | value_slide (左文右图) | ❌ content_slide (四格) |
| 需求设计方案 | design_slide + diagram= (左文右图+框图) | ❌ content_slide / bullet list |
| 需求变更背景 / 影响性分析 / 兼容性 / 风险 | table_slide | ❌ banded_slide (彩色横条) |
| 版本交付计划 | table_slide (11 列) | ❌ 手写列宽/字号 |
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.
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.path —
deckbuilder.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
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:
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).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".oh_logo.png. If the file is missing it's silently skipped.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.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.
| Method | Key argument shape |
|--------|--------------------|
| requirement_review_deck | spec={...} — whole 8-page 需求变更评审 in one call. Preferred for review decks. Missing fields → 待评估/TBD. See examples/requirement_review_oneshot.py |
| cover | strings + meta_lines=["Team", "2026-06-23"] |
| content_slide | cards=[{"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_slide | same 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_slide | bullets=["text", {"text","level":1,"accent","bold"}] |
| table_slide | headers=[...], rows=[[...],[...]], highlight_last=True for totals. col_widths are relative weights — auto-scaled to fit, never overflow |
| flow_slide | stages=[{"title","lines":[...],"change":True}] → 1 row, auto arrows |
| layered_diagram_slide | layers=[{"label","nodes":[{"title","lines","change"}]}] + optional connect |
| architecture_slide | nodes=[{"id","title","lines","row","col","change"}], edges=[{"from","to","label","dir":"f"/"both","accent"}] — labeled directional connectors for high-level module interaction |
| value_slide | background=[...], features=[...], scope=[...], image=None. Two-column 需求价值描述 page (see below). takeaway optional |
| design_slide | design=[...], changes=[...], extra=[{"heading","lines"}], image=None. Two-column 需求设计方案 page (see below). takeaway optional |
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", # 右侧场景图(可选,缺省显示占位卡)
)
design_slide — 需求设计方案 (左文右图,可多页)deck.design_slide(
title="需求设计方案",
design=["…"], # 1、设计方案:设计重点(交互模块及如何达成需求的规格等)
changes=["…"], # 2、变更点及影响(见下)
extra=[{"heading": "三、UI 示意", "lines": ["…"]},
{"heading": "四、裁剪说明", "lines": ["…"]}], # 可选追加段落
image="arch.png", # 右侧架构图(可选)
)
design_slide(自动翻页)。image= 贴在右侧,或在 extra 里加「UI 示意」段。extra 里加一段说明。image=)。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_slide — high-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.")
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):
covervalue_slide (左文右图, unchanged)design_slide (左文右图 + 右侧框图, unchanged; 可多页)table_slide: ① 需裁剪/变更的需求说明(原始需求/编号、特性概述与影响、使用场景,重点 2C/2D 价值与影响);② 原始被接纳时的决策纪要(SIG 评审通过记录)table_slide, 5 行: 北向应用开发者/南向开发者/分布式设备/系统开发者(跨子系统依赖)/设备使用者table_slide, 11 列横向计划表:承接领域/承接类型(IR/SR)/主要需求内容/落地版本/设计者/代码行数/是否涉及API/端到端工作量(500行≈1人月)/领域PM/管道是否满足/工作量是否由领域PM审核OK。把需求拆解成多个子需求,一行一个、逐行呈现工作量,末行用 highlight_last=True 合计table_slide: 是否涉及应用兼容性;兼容性包括(机制/权限/API行为/其它);兼容性方案;应用适配方案和计划table_slide, 固定 2 列 8 行 checklistWhat this page reliably gets wrong (the top two are the most-reported):
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.)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.)diagram= layers or
image=), never a bullet list.highlight_last=True 合计;表头/正文字号随列数自动收缩,不要手设字号
或写死列宽英寸;col_widths 传相对权重。待评估 / TBD (需求编号、SIG 决策纪要、落地版本、设计者、代码行数、
端到端工作量、领域PM、适用地区/产品、外部承诺、合规/安全结论) and list them back to the
user — never fabricate them.scripts/deckbuilder.py importable (add the
scripts/ dir to sys.path, keeping oh_logo.png alongside it).TBD.examples/requirement_review_oneshot.py, fill spec,
deck.requirement_review_deck(spec) → deck.save(). One call, done.Deck() → one method call per slide → deck.save().warnings.catch_warnings(record=True) so any
table_slide content-overflow warning is captured, not just printed and
lost — see Verification below.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.
| Mistake | Fix |
|---------|-----|
| 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 inches | Use Deck methods; they place everything for you |
| from pptx.dgm... / guessing import paths | The library already imports correctly — just from deckbuilder import Deck |
| Design slide is a bullet list, not a diagram | Use flow_slide or layered_diagram_slide |
| Passing RGBColor(...) everywhere | Pass 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 bars | Use table_slide (分项|内容 / 计划宽表) — the bars invite the "不纯粹" rainbow |
| Pages with no point — just a topic title over a table | Give every content slide a takeaway="结论:…" one-liner; it's required — a slide without it raises ValueError |
| Cramming 8+ cards on one slide | Max 6 per content_slide; split across slides |
| Putting >8 rows in one table at full font | The library auto-shrinks; still split very long tables |
| Claiming done without running it | Run the script + the overflow check, report path & slide count |
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.
testing
--- name: ohos-req-value-decision description: Use after review meeting to record decision and route to next step. Triggers: 评审决策纪要, 评审结论回流, value decision, 评审接纳, 评审不接纳, 评审退回, 下次重新上会. Do NOT use for feature baseline (ohos-req-feature-baseline), review gate checks (ohos-req-review-gate), or IR generation (ohos-req-feature-to-ir). metadata: author: openharmony scope: common stage: requirements capability: value-decision version: 0.3.0 status: draft tags: - sdd - requirements
testing
Use when performing the Phase 0 Step 0.5 Review Ready Gate on a 04-feature.md, especially when the user says "evaluate gate", "review readiness", "feature ready?", "should we generate IR", or when the ohos-req-intake-orchestration main session needs a structured Ready / Conditional Ready / Not Ready judgment instead of doing the check inline. Reads 01-04, runs seven fixed checks plus a conditional-items check, and returns a machine-readable JSON summary plus a human-readable table that the main session can route on. Do NOT use for feature baseline generation (ohos-req-feature-baseline), value decision recording (ohos-req-value-decision), or IR generation (ohos-req-feature-to-ir).
testing
--- name: ohos-req-requirement-intake description: Use when importing an OHOS requirement into Phase 0.1, especially for 01-requirement.md, requirement intake, background, user value, scenarios, scope, FR/NFR, affected modules, or priority. Triggers: 需求导入, 01-requirement, 需求基线, RR单号. Do NOT use for feasibility analysis (ohos-req-feasibility-analysis), architecture decision (ohos-req-arch-decision), or feature baseline (ohos-req-feature-baseline). metadata: author: openharmony scope: common
testing
--- name: ohos-req-proposal-to-sr description: Use when every proposal associated with an OHOS IR has passed GATE A and a System Requirement baseline is needed before spec and design work begins. Triggers: 生成SR, proposal转SR, SR基线, 系统需求基线, GATE A通过, 05-proposal to SR. Do NOT use for IR generation (ohos-req-feature-to-ir), feature baseline (ohos-req-feature-baseline), or feasibility analysis (ohos-req-feasibility-analysis). metadata: author: openharmony scope: common stage: requirements ca