104 added, 7 removed. Audit A to A.
---
name: b3os-report
description: b3rys 팀 표준 보고서 스킬. 모든 보고서는 MD를 소스로 먼저 쓰고 → 아이폰에서 읽기 좋은 자체완결 반응형 HTML+SVG로 렌더한다. 사용 시점 — "보고서 써줘", "report", "팀 보고서", "결과 정리해서 보고", "테스트/리뷰/분석 보고서", MD를 HTML로 렌더. owner=maintainer.
trigger: publish to `/reports`
entry: scripts/publish.sh
---
# b3os-report — 팀 표준 보고서
## 언제 작동? (트리거 규율 — the team lead)
- **"보고해 / 현황 알려줘 / 어떻게 됐어"** = 그냥 **메신저로 답변**한다. 스킬 작동 X (단순 질의응답).
- **"보고서 작성해 / 리포트 만들어 / 문서로 정리해"** = 이 스킬 작동.
## /reports 대상 = "지식화되는 컨텐츠"만 (the team lead 2026-06-07)
- ✅ 대상: ①**외부지식 정리**(교육자료·해설·리서치 결과물) ②**내부 플젝하며 얻은 지식·경험**(노하우·교훈을 지식으로 정리한 것)
- ❌ 제외: 단순 논의결과·로그성·운영성(진행보고·리뷰메모·개발로그·툴평가) → **하던 대로 docs/작업카드에**. 포털엔 안 올림.
## 실행 전 확인 (confirm 게이트)
- **렌더 범위**: "①MD만? ②HTML까지? ③/reports 게시까지?" 물어보고 그 범위만.
- **/reports 게시는 컨펌 없이 진행한다** (the team lead 2026-08-01 — 2026-06-07 의 "컨펌 필수"를 뒤집음). `/reports` 는 팀 내부 포털이라 approval gate 대상이 아니다. **팀 밖으로 나가는 것(공개 포스팅·외부 이메일/DM·서드파티 API)은 그대로 승인 대상이다.**
## 문체 원칙 — humanize-korean 최종 패스 (the team lead 2026-06-10)
- 보고서는 **무조건 한글화하지 않는다**. 업계 표준 용어, 제품명, 모델명, API 이름, 검색/평가 용어처럼 영어가 더 정확한 표현은 살린다.
- - 대신 한국어 독자가 자연스럽게 읽을 수 있게 아래 기준으로 최종 검수한다. (`humanize-korean` 스킬을 이미 설치해 둔 사람은 그걸 써도 된다 — ★이 저장소에 포함되어 있지 않고 `install.sh`가 설치하지도 않는 외부 스킬★이다.)
+ - 대신 한국어 독자가 자연스럽게 읽을 수 있게 아래 기준으로 최종 검수한다. (`humanize-korean` 스킬이 그 팀원의 런타임에 설치돼 있으면 그걸로 돌려도 된다 — ★이 저장소에 포함되어 있지 않고 `install.sh`가 설치하지도 않는 외부 스킬★이다.)
- 첫 등장 용어는 `영어 용어(한국어 뜻)`으로 설명한다. 이후에는 문맥상 자연스러운 쪽을 쓴다.
- 장 제목·실행 계획·판단 문장은 한국어 흐름을 기본으로 한다. `Result`, `Decision`, `Step`, `Default criteria` 같은 기계적 영어 라벨은 그대로 남기지 말고 필요한 경우 한국어로 풀어쓴다.
- 영어를 억지로 한국어로 바꾸지 않는다. 목표는 "영어 제거"가 아니라 **의미 보존 + 자연스러운 한국어 리듬**이다.
- 수치·날짜·고유명사·직접 인용은 바꾸지 않는다.
+ ## 어떤 스킬을 언제 쓰나
+
+ 세 스킬이 보고서 작업에 붙는다. **셋 다 이 저장소에 없는 외부 스킬**이고 `install.sh` 가 설치하지도 않는다. 설치돼 있으면 아래 자리에서 쓰고, **없으면 보고서를 쓰는 팀원이 그 자리에서 같은 일을 직접 한다** — 스킬은 절차를 묶어 둔 것이지 그 스킬만 할 수 있는 일이 아니다. 아래 "무엇을 한다" 칸이 그 절차다.
+
+ | 스킬 | 언제 | 무엇을 한다 | 무엇을 안 한다 |
+ |---|---|---|---|
+ | `gd-el10` | **쓰기 전** — 어떻게 설명할지 정할 때 | 되물음이 날 만한 설명(새 이름·원인·동작)을 한 번에 전달되게 하는 규칙 다섯 | 문장을 다듬지 않는다. 사실 확인도 안 한다 |
+ | `gd-explain-like-5` | **남이 준 원문을 해설할 때** | 구절마다 원문 인용 → 용어 설명 → 원문 해석 → 의견·검토 포인트 4단으로 편다 | 내가 쓰는 보고서 본문에는 안 쓴다. 요약 스킬도 아니다 |
+ | `humanize-korean` | **렌더 직전** — 마지막 패스 | 번역투·기계적 병렬·AI 티 나는 리듬만 다듬는다 | **내용을 바꾸지 않는다.** 숫자·용어·인용은 그대로 |
+
+ 셋이 겹치지 않는다 — `gd-el10` 은 **내가 쓰는 글을 어떤 순서로 말할지**, `gd-explain-like-5` 는 **남의 원문을 구절별로 해설할 때**, `humanize-korean` 은 **다 쓴 뒤 문체**다. 대상이 다르다.
+
+ **보고서 본문에는 `gd-el10` 과 `humanize-korean` 둘이 붙는다.** `gd-explain-like-5` 는 원문 해설물(논문·계약서·사양서를 풀어 주는 보고서)일 때만 해당한다. 그런 보고서가 아니면 안 쓴다 — 문단 하나가 어려운 것은 그 문단을 다시 쓰는 문제이지 해설 포맷을 붙일 자리가 아니다.
+
+ **`humanize-korean` 을 돌릴 때 잠글 것** — 숫자, 영어 기술 용어, 백틱 안 코드, 마크다운 강조, 절·그림 번호 참조, 예문. 이것들이 바뀌면 내용이 바뀐 것이다. 돌린 뒤 원문과 **숫자·백틱 전수 대조**를 하고, 바뀐 게 있으면 되돌린다. 입력이 길면 나눠서 돌리되 **줄 수와 줄 순서를 유지**하게 지시해야 나중에 합칠 수 있다.
+
+ **`gd-el10` 을 쓰는 자리** — 보고서 본문 전체가 아니라 **독자가 되물을 만한 곳**이다. 새 용어를 처음 꺼내는 문단, 원인을 설명하는 문단, "왜 이렇게 했나" 를 적는 문단. 단순 현황·수치 나열에는 안 쓴다.
+
## 단계
1. **MD 소스 먼저** — Markdown 작성(`reports/<주제>-<YYYYMMDD>/<name>.md`). 재편집·버전관리·재렌더 원본.
- 2. **최종 윤문** — 렌더 전에 위 “문체 원칙” 기준으로 번역투·기계적 병렬·영어 라벨 남발을 줄인다. 내용 추가/삭제가 아니라 문체·리듬·표현만 다듬는다. (외부 `humanize-korean` 스킬이 설치돼 있으면 그걸로 돌려도 된다.)
- 3. **HTML 렌더** — `scripts/render.sh <md> [out.html] [제목]` → 아이폰 반응형 HTML+SVG(자체완결, **다크/라이트 테마 토글**).
- 4. **포털 게시** — ★원본 md/html 은 `reports/` 밖(작업 폴더·임시 폴더)에 두고 publish.sh 가 복사하게 한다.★
+ 2. **최종 윤문** — 렌더 전에 위 “문체 원칙”과 “어떤 스킬을 언제 쓰나” 기준으로 번역투·기계적 병렬·영어 라벨 남발을 줄인다. 내용 추가/삭제가 아니라 문체·리듬·표현만 다듬는다. (외부 `humanize-korean` 스킬이 설치돼 있으면 그걸로 돌려도 된다.)
+ 3. **팀원 리뷰 — 내용과 표현 둘 다** (the team lead 2026-09-02, ★건너뛰지 않는다★)
+ 렌더 전에 **다른 팀원 한 명**이 읽는다.
+ - **내용** — 사실이 맞나, 근거가 붙어 있나, 빠진 것이 있나
+ - **표현** — ★문장 하나를 앞뒤 가리고 읽었을 때 무엇에 대한 말인지 알 수 있나★
+
+ ★표현 리뷰를 글쓴이가 대신할 수 없다.★ 몇 시간 한 주제를 들여다본 뒤에는 자기가 지어낸 말이
+ 자기에게는 분명하게 읽힌다. 그래서 "이건 나만 아는 말인가" 를 글쓴이가 판정하면 그 시점의 글쓴이는 통과시킨다.
+ 읽는 팀원은 그 맥락이 없으므로 같은 문장에서 걸린다.
+
+ **걸러야 하는 문장 다섯 갈래** — 어느 것도 특정 단어로 걸러지지 않는다. 다섯 갈래에 겹치는 단어가 없다.
+
+ | 갈래 | 예 | 무엇이 빠졌나 |
+ |---|---|---|
+ | 글쓴이가 지어낸 말 | `화면이 6,180px 떨어진 곳에 선다` | 화면은 서지 않는다. 표준 용어나 화면에 보이는 이름을 쓴다 |
+ | 가리키는 것을 안 밝힘 | `코드가 있으면 제자리입니다` | 어디가 제자리인지 글 어디에도 없다 |
+ | 성분이 빠진 토막 | `여섯 다 잡혔습니다` | 무엇이 무엇을 잡았는지 없다 |
+ | 문장이 아닌 명사 나열 | `탭 클릭 시 탭 줄이 화면 위` | 서술어가 없다 |
+ | 사물을 사람처럼 | `이 검사는 그 단어가 있는지만 봅니다` | 검사는 보지 않는다. 무엇이 무엇을 하는지로 쓴다 |
+
+ 여기에 **지시관형사 반복**을 같이 센다 — `그 코드`·`그 값`·`그 장` 이 한 문단에 여러 번 나오면
+ 가리키는 것을 이름으로 바꾼다. 468자 보고 하나에서 8회가 나온 실측이 있다.
+
+ 걸리는 문장이 있으면 **그 문장을 그대로 인용해서 돌려준다.** 글쓴이는 왜 그렇게 썼는지 답하고 고친다.
+ ★"짧게 줄여라" 를 처방으로 쓰지 않는다★ — 줄이면 주어와 목적어부터 지워져 같은 결함이 다시 난다.
+ 줄이는 것은 문장이 아니라 항목 수에서 한다.
+
+ **자동 검사는 이 다섯 갈래를 못 잡는다.** `humanize-korean` 의 71개 패턴에 대응하는 것은 `E-4 단문 일변도` 하나뿐이고,
+ 지시관형사 축·지어낸 표현 축은 목록에 없다. 정량 점수에 위 예문들을 넣으면 **위험도 낮음(2점)** 이 나온다(실측 2026-09-02).
+ 자동 검사는 번역투·쉼표 비율·한자어 밀도를 재므로 **사람이 읽는 단계를 대신하지 못한다.**
+
+ 4. **HTML 렌더** — `scripts/render.sh <md> [out.html] [제목]` → 아이폰 반응형 HTML+SVG(자체완결, **다크/라이트 테마 토글**).
+ 5. **포털 게시** — ★원본 md/html 은 `reports/` 밖(작업 폴더·임시 폴더)에 두고 publish.sh 가 복사하게 한다.★
이미 `reports/<id>/` 안에 써 두면 자기 자신을 복사하다 `SameFileError` 로 죽는다(lui 실측 2026-08-01).
`scripts/publish.sh --title "T" --author maintainer --summary "S" --md a.md --html a.html` → team-collab `reports/`에 복사 + 등록 → **<dashboard-url>/reports** 목록에 바로 뜬다. HTML이 있으면 포털 기본 form은 HTML이고, MD는 정본·다운로드용 보조 form으로 남는다.
두 스크립트는 **이 저장소 안에** 있다. clone 루트에서 실행한다(`install.sh`는 `~/.claude/skills/b3os`만 연결하므로 `~/.claude/skills/b3os-report/…` 경로는 없다).
```bash
skills/b3os-report/scripts/render.sh report.md report.html "제목"
skills/b3os-report/scripts/publish.sh --title "제목" --author maintainer --summary "한줄요약" --md report.md --html report.html
```
→ Telegram `.html` 첨부(아이폰 Safari) + /reports 포털 둘 다 가능.
## 왜
the team lead는 주로 아이폰에서 읽는다. 표·차트가 모바일에서 깨지지 않게 **SVG**로, 매 보고서 CSS 재발명 없이 **한 테마**로 통일. MD 소스를 남겨 추적·재렌더 가능. (메모리 규칙: 보고서=MD→HTML+SVG iPhone.)
## 기본 작동 방식 — 팀원들이 따라야 할 기준
- 사용자가 “보고서/리포트/문서로 정리”를 요청하면 기본은 **MD 원본 작성 → HTML 렌더 → /reports 등록**까지다. 단순 현황 답변은 메신저 답변으로 끝낸다.
+ - **보고서는 설명그림을 적극적으로 쓴다.** 글로만 된 보고서는 기본값이 아니다 — 구조·비교·상태변화가 나오면 그림을 먼저 생각한다. 다만 **장식은 넣지 않는다**: 판별은 "이 그림만 보고 개념을 남에게 설명할 수 있나" 한 줄이고, 못 하면 뺀다. 그리는 법은 `references/diagrams.md`.
- 보고서 첫 화면은 항상 `# 제목` + 메타줄 + 첫 `>` 인용의 **한 줄 결론**으로 시작한다. 독자가 iPhone에서 열었을 때 5초 안에 “무슨 문서인지/결론이 뭔지” 알아야 한다.
- 영어 약어·전문 용어가 처음 나오면 별도 풀이 섹션을 만들기보다 **원래 표현과 짧은 설명을 괄호로 바로 붙인다**. 예: `API(Application Programming Interface, 프로그램끼리 요청을 주고받는 접점)`, `ARR(Annual Recurring Revenue, 연간 반복 매출)`. 모든 용어를 다 풀지 말고 독자가 막힐 가능성이 높은 약어·전문어만 고른다.
- 수식·개발·경제·투자처럼 문장 안 괄호만으로 부족한 복잡한 개념은, 해당 문단 바로 아래에 **5줄 이내의 작은 풀이 박스**를 붙인다. 이때만 `gd-explain-like-5` 흐름을 축약 적용한다: 원래 표현 → 쉬운 해석 → 왜 중요한지.
- 팀원이 디자인 기준을 모르겠으면 먼저 `/reports/file/differential-privacy/html`을 reference로 본다. 그 보고서의 장점은 **다크 editorial 톤, 짧은 섹션, 카드형 설명, 복잡한 개념을 바로 아래에서 짧게 풀어주는 방식**이다.
- 단, `differential-privacy`의 KaTeX/수식 전용 HTML을 그대로 복사하지 않는다. 일반 보고서는 이 스킬의 renderer와 `assets/theme.css`를 source of truth로 쓴다.
## 디자인 기준
- 기본 톤은 `differential-privacy` 보고서처럼 **다크 editorial 페이지**다: 큰 종이 카드가 아니라 어두운 캔버스 위 900~960px 본문, 초록 accent, 넉넉한 섹션 여백, 카드형 표/인용/코드 블록.
- 폭 규격: 표준은 **960px 상한**이다. 표·코드가 많은 보고서는 960px이 적당하고, 더 넓히면 line length가 길어져 읽기가 흐트러진다. 차분 프라이버시 같은 순수 해설형은 820~880px이 더 좋을 수 있지만, 기본 스킬은 표준 960px을 쓴다.
- 색 규칙: **초록/세이지를 primary accent**, amber/orange를 보조 강조로 쓴다. 하늘색/파랑은 다크 그린 배경에서 튀므로 링크·코드 같은 보조 정보에만 muted sage 톤으로 제한한다.
- 배경은 아주 연한 grid texture를 기본으로 쓴다. 라이트 모드는 종이 느낌이 나도록 은은하게 보이게 하고, 다크 모드는 같은 grid를 낮은 대비로 유지하되 눈을 집중하면 인지되는 수준이어야 한다. 본문 가독성을 해치면 안 된다.
- 다크 모드 표·인용·코드·figure·요약 카드는 검정 drop shadow만 쓰지 않는다. `--surface-shadow`/`--surface-shadow-soft`로 아래 방향 그림자, 위쪽 1px inset highlight, 분명한 외곽선을 함께 써서 라이트 모드와 같은 깊이 구조를 만든다.
- - 탭이 필요하면 큰 pill 버튼을 쓰지 않는다. `report-tabs/report-tab`의 **작은 segmented navigation**을 써서 탭임은 인지되지만 본문보다 튀지 않게 한다. 세부 컴포넌트 예시는 `references/ui-components.md`를 따른다.
+ - 탭이 필요하면 큰 pill 버튼을 쓰지 않는다. `report-tabs/report-tab`의 **작은 segmented navigation**을 써서 탭임은 인지되지만 본문보다 튀지 않게 한다. 세부 컴포넌트 예시는 `references/ui-components.md`, 다이어그램은 `references/diagrams.md`를 따른다. 긴 보고서를 탭으로 나누는 것은 렌더러가 해 준다 — 아래 「긴 보고서는 탭으로 나눈다」.
- **라이트 모드는 유지**한다. 다만 라이트도 같은 구조와 여백을 쓰고 색만 밝은 토큰으로 바꾼다.
- - 보고서가 특수 구조를 가진 경우(예: CSS-only 탭 보고서)는 표준 render로 덮어쓰지 말고, 기존 구조를 유지한 채 공통 테마 CSS만 교체한다.
+ - 손으로 짠 특수 구조 보고서(예: 예전 CSS-only 탭 보고서)는 표준 render로 덮어쓰지 말고, 기존 구조를 유지한 채 공통 테마 CSS만 교체한다. 새로 쓰는 보고서는 손으로 짜지 말고 `data-tab` 표식을 쓴다.
- 인포그래픽·다이어그램은 보고서 테마와 같은 팔레트를 써야 한다. `svg.diagram-flow` kit와 `diagram-node*`, `diagram-line*` class를 기본으로 쓰고, blue/violet SaaS slide palette(`#eff6ff`, `#2563eb`, `#faf5ff`, `#7c3aed` 등)는 기본 도식 색으로 쓰지 않는다.
+ - 그림은 장식이 아니라 **설명그림**이다 — 그림만 보고 개념을 남에게 설명할 수 있어야 한다. 판별 기준·여섯 가지 틀·검사 목록은 `references/diagrams.md`.
## 렌더러가 지원하는 MD
- `#`~`####` 헤딩 · `**굵게**` `*기울임*` `` `코드` `` · 표(`| |`) · `-`/`*`/`1.` 목록 · `>` 인용(=강조 박스) · `---` 구분선 · `[텍스트](url)` · 코드펜스 ```` ``` ```` · **`<svg>…</svg>` 원문 통과**(차트는 SVG로 직접 그려 넣으면 그대로 렌더).
+ `#`~`####` 헤딩 · `**굵게**` `*기울임*` `` `코드` `` · 표(`| |`) · `-`/`*`/`1.` 목록 · `>` 인용(=강조 박스) · `---` 구분선 · `[텍스트](url)` · 코드펜스 ```` ``` ```` · **`<svg>…</svg>` 원문 통과**(차트는 SVG로 직접 그려 넣으면 그대로 렌더) · **`<div id="x" data-tab="라벨"></div>` 탭 구분**(아래 절).
+ ## 긴 보고서는 탭으로 나눈다
+
+ **언제** — 본문이 15,000자를 넘거나 그림이 20장을 넘으면 나눈다. 짧은 보고서는 나누지 않는다. 탭이 둘뿐인 보고서는 스크롤보다 불편하다.
+
+ **왜** — 한 장이 길어지면 **목차 링크를 눌러도 엉뚱한 자리에 선다.** 브라우저가 앵커로 스크롤한 뒤에 아래쪽 SVG 들이 뒤늦게 자리를 잡으면서 내용이 통째로 밀리기 때문이다. 실측 — `llm-book` 은 264KB 한 장에 SVG 50장이었고, `#p1-3` 으로 열면 3장이 아니라 다른 자리에 섰다. 여섯 탭으로 나눈 뒤 오차 0.
+
+ **쓰는 법** — MD 에 표식 한 줄을 넣는다. 이 줄부터 다음 표식 전까지가 한 탭이다.
+
+ ```markdown
+ <div id="p0" data-tab="0부 구조"></div>
+
+ ## 0부 — LLM 이 문장을 처리하는 순서
+ ...
+ <div id="p1" data-tab="1부 학습"></div>
+
+ ## 1부 — 값을 어떻게 정하는가
+ ```
+
+ - `id` = 탭 주소. `#p0` 으로도, 탭이 만드는 `#panel-p0` 으로도 열린다.
+ - `data-tab` = 탭에 찍히는 글자. **한 줄에 다 들어가게 짧게** — `0부 구조` 는 되고 `0부 구조 — LLM 이 문장을 처리하는 순서` 는 안 된다.
+ - 첫 표식보다 **위에 있는 내용은 탭 밖에 남는다.** 제목·리드 문단·전체 요약을 거기 둔다.
+ - 표식은 **한 줄로 닫는다.** 여러 줄로 쓰거나, `id`·`data-tab` 중 하나가 빠지거나, id 가 겹치거나, 표식이 1개뿐이면 **렌더가 멈춘다** — 탭이 반만 생긴 보고서가 배포되는 것보다 낫다.
+
+ **전환은 CSS `:target` 이다.** `/reports` 뷰어는 보고서를 `sandbox` iframe 으로 띄워 **스크립트를 막는다**(`Reports.ts`). 자바스크립트로 탭을 만들면 거기서 탭이 죽는다. 생김새는 `theme.css` 의 `.report-tabs`/`.report-tab` 을 그대로 쓴다 — 렌더러가 다시 정의하지 않는다(`references/ui-components.md` 2절).
+
+ **스크립트가 하나 붙는데, 화면 이동만 거든다.** 목적지가 **닫혀 있던 탭 안**이면 브라우저는 첫 스크롤 시점에 그 요소의 위치를 모른다 — 화면에 없어서다. CSS 가 탭을 편 뒤에도 브라우저는 다시 시도하지 않는다. 스크롤 코드를 뺀 보고서에서 `#p3-5` 를 열면 화면이 문서 맨 위에 그대로 있고, 찾아가려던 장은 **6,180px** 아래에 있어 보이지 않는다. 코드를 넣으면 그 장의 제목이 화면 맨 위로 올라온다.
+
+ ★탭은 이동이지 효과가 아니다★ — 렌더러가 탭 보고서에 `html{scroll-behavior:auto}` 를 넣어 `theme.css` 의 부드러운 스크롤을 끈다. 켜 두면 탭을 눌렀을 때 브라우저 애니메이션과 보정 이동이 다투어 **화면이 앞뒤로 흔들린다**(실측 2026-09-02). 탭 클릭도 스크립트가 옮긴다 — **누르는 순간 그 패널은 아직 `display:none` 이라 브라우저가 위치를 모른다.** 그대로 두면 화면이 문서 맨 위로 가고 탭 줄이 화면 가운데에 놓인다(실측 2026-09-02). 어느 경우든 **한 번만** 옮긴다. 깊은 앵커일 때만 400ms 뒤에 어긋난 폭이 4px 를 넘는지 확인해 그때만 한 번 더 옮긴다.
+
+ ★탭마다 읽던 자리를 기억한다★ — 다른 탭에 갔다가 돌아오면 그 자리로 돌려놓는다. 처음 여는 탭은 그 부의 첫머리로 간다. 지금 켜진 탭을 다시 누르면 첫머리로 간다. 자리를 적어 두는 시점은 **클릭**이지 `hashchange` 가 아니다 — `hashchange` 때는 브라우저가 이미 화면을 옮긴 뒤라 늦다. 복원 직전에는 `getBoundingClientRect()` 를 한 번 읽어 방금 열린 패널의 높이를 계산시킨다.
+
+ > ★`requestAnimationFrame` 을 쓰지 마라.★ 배경 탭(`document.hidden === true`)에서는 **콜백이 아예 실행되지 않는다**(실측 2026-09-02: 같은 탭에서 `setTimeout` 은 돌고 rAF 는 안 돈다). rAF 안에 이 로직을 넣으면 그 탭에서는 코드가 한 줄도 실행되지 않는데, 브라우저의 앵커 이동이 비슷한 자리로 옮겨 주기 때문에 **동작하는 것처럼 보인다.** `getBoundingClientRect()` 를 읽으면 `:target` 으로 바뀐 표시 상태가 그 자리에서 계산되므로 프레임을 기다릴 이유가 없다.
+
+ > ★`window.scrollTo(x, y)` 2인자 형태를 쓰지 마라.★ `scroll-behavior:smooth` 가 켜져 있으면 이 형태는 **화면을 못 움직인다**(실측: 목표 5,270 지정, 결과 제자리). `window.scrollTo({top, behavior:'instant'})` 를 쓴다. 에러가 안 나므로, 코드를 넣은 것이 고쳤다는 증거로 잘못 읽히기 쉽다.
+
+ > ★`window.scrollTo(x, y)` 2인자 형태를 쓰지 마라.★ `theme.css` 가 `scroll-behavior:smooth` 를 켜 놓아서 이 형태는 **화면을 못 움직인다**(실측: 목표 5,270 지정, 결과 제자리). `window.scrollTo({top, behavior:'instant'})` 를 쓴다. 이걸 모르고 넣으면 코드가 돌긴 하는데 아무 일도 안 일어나고, "스크립트를 붙였다" 는 사실이 고쳤다는 증거로 잘못 읽힌다.
+
+ **검사** — 배포 전에 브라우저에서 이 넷을 잰다. `render.test.mjs` 는 구조만 본다.
+ 1. 깊은 주소로 바로 열기(`...#p3-5`) — 그 탭이 켜지고 그 절이 화면 위에 오나
+ 2. 탭 클릭 — 탭 줄이 화면 위에 오나 (부가 바뀌면 문서 높이가 달라져 이전 기준 위치는 뜻이 없다)
+ 3. 목차 링크 전부 — 가리키는 id 가 실제로 있나 (`href="#x"` 대 `id="x"` 대조)
+ 4. 첫 진입(해시 없음) — 첫 탭이 켜지나
+
## 차트·인포그래픽·다이어그램은 SVG로 (passthrough)
+ > **다이어그램을 넣는 보고서는 `references/diagrams.md` 를 먼저 읽는다.** 여섯 가지 표준 틀, 예 하나로 여러 그림을 잇는 방법, 실제 값을 넣는 규칙, class 표, 글자 폭 계산, 브라우저 검사 목록이 거기 있다. 아래는 통과(passthrough) 문법만 다룬다.
+
바차트·흐름도·관계도는 MD 안에 인라인 SVG로 직접 작성한다(렌더러가 통과시킴). 단, 새 보고서의 기본 도식은 하드코딩한 파랑/보라 팔레트가 아니라 `diagram-flow` kit를 쓴다.
간단한 바 차트 예시:
```html
<svg class="diagram-flow" viewBox="0 0 420 92" role="img" aria-label="리뷰 방식별 시간 비교">
<text x="18" y="24" class="diagram-title">시간 비교</text>
<text x="18" y="52" class="diagram-muted">솔로</text>
<rect x="86" y="40" width="74" height="14" rx="7" class="diagram-accent"/>
<text x="170" y="52" class="diagram-text">58s</text>
<text x="18" y="76" class="diagram-muted">harness</text>
<rect x="86" y="64" width="190" height="14" rx="7" class="diagram-accent-warm"/>
<text x="286" y="76" class="diagram-text">92s</text>
</svg>
```
SVG는 라이트/다크 모두에서 읽혀야 한다. 텍스트가 긴 도식은 SVG 내부에서 줄바꿈이 자동으로 되지 않으므로 `<text>` 한 줄에 긴 문장을 넣지 말고, 짧은 label·caption·본문 설명으로 분리한다. 도식 안은 “구조”, 도식 아래 문단은 “해석”을 맡긴다.
복잡한 가로 SVG는 iPhone에서 그대로 축소하지 않는다. 같은 `<figure>` 안에 모바일 세로 카드와 데스크톱 SVG를 함께 두면 표준 테마가 640px에서 자동 전환한다.
```html
<figure>
<figcaption>한눈에 보기 · 모바일은 세로 카드, 데스크톱은 전체 다이어그램</figcaption>
<div class="mobile-infographic" role="group" aria-label="모바일 요약">
<div class="mi-card mi-green"><h4>단계 1</h4><p>핵심 설명</p></div>
<div class="mi-card mi-amber"><h4>단계 2</h4><p>주의할 점</p></div>
</div>
<svg class="desktop-infographic diagram-flow" viewBox="0 0 760 220" role="img" aria-label="전체 다이어그램">…</svg>
</figure>
```
사용 가능한 모바일 카드 class는 `mi-green`, `mi-amber`, `mi-orange`, `mi-red`를 기본으로 한다. `mi-blue`, `mi-cyan`, `mi-violet`은 legacy 호환용이며 새 도식의 primary 색으로 쓰지 않는다.
## 컨벤션
- 맨 위 `# 제목` + 메타줄(일시·owner). 첫 `>` 인용 = "한 줄 결론"(노랑 박스로 강조됨).
- 수치 비교는 표 + SVG 바차트 둘 다.
- 끝에 소스 MD 경로 한 줄.
- 최종 보고 전에는 "필요한 영어 용어는 살렸는가 / 장 제목과 실행 계획은 자연스러운 한국어인가 / 용어 첫 등장은 설명했는가"를 확인한다.
## 예제
`examples/harness-pilot-report.md` (소스) → `examples/harness-pilot-report.html` (렌더 결과). 실제 harness 파일럿 보고서.
+
+ 다이어그램 중심 보고서는 `/reports/file/llm-book/html` 이다. 0부에 그림 13장이 예문 하나로 이어지고, `references/diagrams.md` 의 여섯 틀이 전부 한 번씩 나온다. 부별 탭도 이 보고서에서 쓴다.
## 살아있는 스킬
더 나은 차트(자동 바차트 생성기)·레이아웃·호스팅 자동링크는 계속 업뎃(§11 팀 스킬). 테마=`assets/theme.css`(단일 출처, 렌더 시 인라인됨).