2026-08-06 11:29:00 +09:00

163 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: ubisam-ppt-make
description: >-
Ubisam SW 설계서 디자인 시스템으로 .pptx 덱을 만든다. 모든 페이지에 UbiSam 로고,
고정 폰트(한글=굴림 / 영문=Arial), 파란 accent 컬러. JSON spec을 받아 python-pptx로 렌더링한다.
"Ubisam 설계서 PPT 만들어줘", "유비삼 스타일 덱", "이 양식으로 발표자료", "/ubisam-ppt-make"
요청 시 사용. `ubisam-deliverables`·`ubisam-deliverable-rebuild`가 PPTX 렌더링을 위임할 때도
반드시 이 스킬을 쓴다 — 다른 곳에서 python-pptx로 **덱을 새로 만들지** 않는다.
(예외: `ui_layout_image`가 **기존 pptx에 이미지를 삽입·교체**하는 것은 렌더링이 아니므로 허용.)
구분 — 기획·조사부터 필요한 일반 발표자료는 `ppt_Agent`, 이 스킬은 **Ubisam 브랜드 spec→pptx 렌더링 전용**.
맨손 "업데이트"·"다시 실행"만으로는 이 스킬을 고르지 않는다 — 무엇을 만들지 먼저 확인한다.
---
# ubisam-ppt-make — Ubisam SW 설계서 deck builder
Deterministic PPT builder following the design system extracted from
`P-PRJ_BFHB_UBISAM_Ver1.4.pptx` and the user's edited layout showcase
(UbiSam logo placed on every page). Takes a JSON spec and emits a `.pptx`
via python-pptx.
## When to use
- The user types `/ubisam-ppt-make`
- Requests like "Ubisam 설계서 PPT 만들어줘" / "유비삼 스타일 덱" / "this format으로"
- New design-document presentations that must keep Ubisam branding
- **`ubisam-deliverables` 스킬이 PPTX 생성을 위임할 때** — deliverables는 spec JSON만 준비하고 렌더링은 반드시 이 스킬의 `build_deck.py`로 위임한다
> **역할 경계**: `ubisam-ppt-make`는 PPTX 렌더링 엔진. JSON spec → `.pptx` 변환만 담당.
> 산출물 구조·MD·xlsx 관리는 `ubisam-deliverables` 스킬이 담당.
## Design system (fixed)
- Slide: 16:9 (13.333 × 7.5 in)
- **슬라이드 마스터 배경** (모든 pptx 자동 적용):
- 캔버스: **`WHITE`** — `_apply_master_background()`가 마스터와 전 레이아웃에 흰색을 적용한다
(`build_deck.py:55-73`). `BG_SOFT`(#F4F7FA)는 **패널·표 짝수행 fill 전용**이지 배경색이 아니다
- 하단 accent 바: `#4A8DCB` h=0.15in @ y=7.35in (마스터 공통)
- cover·divider·closing은 자체 full rect로 덮음
- 캔버스 배경은 `_apply_master_background()`가 `WHITE`로 고정한다. spec JSON으로 재정의할 수 없다
- Accent: `#4A8DCB` (blue), dark `#2F5E8C`; warn `#E53E3E`
- Ink `#262A2E`, sub-gray `#6B7278`, soft panel `#F4F7FA`
- **Font rule (do not change): 한글=굴림, 영문=Arial** — applied to every run
- **UbiSam logo on every page**: cover = bottom-right, all others = top-right
- Header pattern: `0X.` badge + title + KO subtitle + split accent bar
- Footer: `Ubisam | <doc_title>` + page number (content pages only)
## 12 layout types (`slide.type`)
Document layouts:
| type | purpose | key fields |
|------|---------|-----------|
| `cover` | 표지 | `tag, title, subtitles[], team, contacts[]` |
| `history` | 변경 이력 표 | `rows[] = [No,Version,날짜,변경자,내용]` |
| `agenda` | 목차 그리드(≤6) | `items[] = {no,title,sub}` |
| `divider` | 섹션 간지(큰 숫자) | `no, title, subtitle` |
| `content` | 4분할 패널 | `no, title, subtitle, panels[] = {title,body}` |
| `flow` | 시퀀스 플로우차트 | `no, title, subtitle, steps[]={title,code,kind}, branch{title,sub}` |
| `table` | 스펙/IO 표 | `no, title, headers[], widths[], center_cols[], rows[][]` |
| `closing` | 마무리 | `title, message, team, contacts[]` |
Manual layouts (HMI Manual / 27번):
| type | purpose | key fields |
|------|---------|-----------|
| `screen_guide` | 화면 설명(캡처+번호 콜아웃) | `no, title, caption, image(PNG경로), items[]={title,desc,pos:[x,y]}` |
| `procedure` | 조작 절차(번호 단계) | `no, title, steps[]={title,desc}` |
| `icon_ref` | 버튼/아이콘 설명(3열 카드, ≤6) | `no, title, items[]={icon,name,func}` |
| `alarm` | 알람·조치(주의 배너+표) | `no, title, notice, rows[]=[코드,알람명,원인,조치]` |
`kind` for flow steps: `"proc"` (process box) or `"dec"` (decision, blue outline).
`pos` in `screen_guide` items = callout marker offset (inch) inside the capture box.
Page numbers auto-increment over content/manual pages; cover/divider/closing excluded.
`divider`/`closing` use a white background with a `#0070C0` / `#2F5E8C` block.
## Choosing a layout for each piece of data
Match every chunk of source/analysis data to the layout whose intent fits it —
do not force everything into `table`. Full rules + disambiguation in
[`reference/layout_selection.md`](reference/layout_selection.md). Cheat sheet:
- ordered **human** steps → `procedure` · machine sequence **with branches** → `flow`
- 2–4 facets, one line each → `content` · repeating rows/cols → `table`
- annotate ONE screenshot → `screen_guide` · button/icon legend → `icon_ref`
- fault → cause → action (+safety) → `alarm` · revision log → `history`
## Workflow
1. **Gather info** — topic, doc title, sections, slide contents, contacts.
내용이 없으면 **무엇을 만들지 되묻는다.** 샘플 showcase는 사용자가 **명시적으로 샘플/레이아웃
예시를 요청했을 때만** 만든다 — 그냥 만들면 원하지 않은 13장 덱이 나온다.
2. **Classify each data chunk → layout** using the guide above, then
**write the spec JSON** — see `examples/showcase.json` and the type tables.
Reuse the original BFHB sample text only when the user wants the showcase.
3. **Run the builder**:
저장소 루트에서 한 줄로 실행한다 (`cd` 하지 않는다 — 출력이 스킬 폴더로 새는 것을 막기 위함):
```bash
PYTHONUTF8=1 py .claude/skills/ubisam-ppt-make/build_deck.py --input <spec.json> --output <출력 .pptx 절대·상대 경로>
```
`PYTHONUTF8=1`은 반드시 **같은 줄** 접두로 둔다. 별도 줄에 두면 적용되지 않아 한글이 깨진다.
4. **Verify** — render to PNG and eyeball every slide (see Verification).
5. **Report** — output path + slide summary.
## Spec schema (minimal)
```json
{
"doc_title": "{문서 제목}",
"slides": [
{ "type": "cover", "title": "...", "subtitles": ["..."],
"team": "{조직명}", "contacts": ["{이름} {직급} {email}"] },
{ "type": "divider", "no": "01", "title": "...", "subtitle": "..." },
{ "type": "content", "no": "02.", "title": "...", "subtitle": "...",
"panels": [ {"title": "...", "body": "..."} ] }
]
}
```
A full working spec is in [`examples/showcase.json`](examples/showcase.json).
## Verification
**가용성을 먼저 확인한다.** PNG 렌더 검증은 PowerPoint COM이 있어야 한다 —
`powershell -c "New-Object -ComObject PowerPoint.Application"` 이 실패하면 렌더 검증을 생략하고
보고에 **`PNG 검증 미수행 — PowerPoint 부재`** 로 명시한다(검증했다고 하지 않는다).
이 경우 아래 **폰트 감사**만 수행한다 — 그건 zipfile만으로 되므로 항상 가능하다.
PowerPoint가 있으면: Export every slide to PNG and inspect; check no overflow/overlap, logo on
every page, and 한글=굴림 / 영문=Arial on all runs.
```powershell
# PowerPoint COM export (Windows, PowerPoint installed)
$ppt = New-Object -ComObject PowerPoint.Application
$pres = $ppt.Presentations.Open($pptx, $true, $false, $false)
$i=1; foreach ($s in $pres.Slides) { $s.Export("$dir/slide$i.png","PNG",1280,720); $i++ }
$pres.Close(); $ppt.Quit()
```
Font audit (every `rPr` must show `ea=굴림`, `latin=Arial`):
```bash
PYTHONUTF8=1 py -c "import zipfile,re,sys;from collections import Counter;z=zipfile.ZipFile(sys.argv[1]);\
[print(Counter(re.findall(r'<a:ea typeface=\"([^\"]*)\"',z.read(n).decode('utf-8','ignore')))) \
for n in z.namelist() if re.match(r'ppt/slides/slide\\d+',n)]"
```
## Notes
- python-pptx sets only the latin font via `run.font.name`; `_set_font()` also
writes `<a:ea>`/`<a:cs>` so Korean renders in 굴림. Always go through it.
- Logo asset: `assets/Ubisam_logo_transparent.png`. On dark divider/closing the
colored logo has lower contrast but matches the user's original placement.
- Keep `.md` files under 200 lines (`rules.md` #4); split if it grows.
- **생성·덮어쓸 `.pptx` 경로를 먼저 제시하고 승인받는다** (`rules.md` #2). 같은 이름이 이미 있으면
덮어쓰기 전에 무엇이 사라지는지 한 줄로 알린다 — 렌더링은 되돌릴 수 없다.
- ⚠ **`build_deck.py` 의 `__main__` 데모와 `examples/showcase.json` 은 타 프로젝트(P-PRJ BFHB) 실데이터다.**
조직명·담당자·이력 행을 **그대로 복사하지 않는다.** 값은 `_meta/project.yaml` 또는 사용자 입력에서 온다.
- **`table` 높이 상한**: 표는 `_TABLE_MAX_H = 5.3"` (y 1.7" ~ 7.0")로 자동 제한.
행이 많아도 푸터(`Ubisam | <doc_title>`, y=7.05")를 절대 침범하지 않는다.
행 높이는 `min(0.5×rows, 5.3) / rows`로 균등 압축된다.
> 보고는 `rules.md` #11~13 출력 형식을 따르고(수정 줄=초록 화살표, 단어=주황, 미변경=기본색),
> 단계 전환마다 진행을 한 줄로 알리며(#10), 끝에 관련 `.md` 갱신 필요 여부를 묻는다(#6).