genetics-mcp 2.16.7 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,76 @@
1
+ # 가독성 기본 틀 — 도판·표·문단이 같이 지키는 측정 가능한 규칙 (2026-09-10)
2
+
3
+ > 근거 사례 둘. ① 2026-09-08 앳플리 4차 「글씨 작아서 문제」 — 880px 합성 그림이 본문 단에서 9.5~12.5px 로 떠 반려.
4
+ > 처방은 figure.mjs 의 14px 게이트였다. ② 2026-09-09 앳플리 #173 그림 1-2 「가독성에 하자 있는 상태로 만드는 짓을
5
+ > 왜 계속 하느냐, 가독성이 무엇인지 모르나」 — 그 게이트를 **통과한** 그림이 반려됐다. 라벨 15px · 행간 1.3 · 라벨 간격 2px ·
6
+ > 표식 간 7px · 띠 대비 1.2:1 · 뜻 색 5 · 그림 안 문단 150자 · 1x 손실 인코딩. 재던 것은 글자 크기 하나였고 나머지는
7
+ > 재지 않았다. **가독성은 글자 크기가 아니라 열 가지 잣대의 합이다.** 이 문서가 그 잣대의 값을 정한다.
8
+
9
+ ## 0. 원칙 한 줄
10
+
11
+ **독자가 읽으려 애쓰지 않아도 읽히는가.** 사용자의 틀(디자인 상식)로 풀면 넷이다 — 단락과 요소 사이에 **여백**을 두어 덩어리가
12
+ 갈리게, **헤더는 본문의 1.5배 이상 굵게** 해 위계가 보이게, **글자·줄 간격**이 빽빽하지 않게, **배경과 글자의 대비**를 높게.
13
+ 글 층에서는 넷이 이렇게 나타난다 — **문장은 한 줄(60자)**, **표 칸은 두 줄(20자)**, **부연은 문장당 하나**, **숫자 나열은 표**. 여기에 도판 고유의 넷을 더한다 — 관련 요소는 **가깝게**(근접성), 뜻을 나르는 **색은 셋 안**, 그림 안에 **문장을 넣지 않고**,
14
+ **선명하게**(밀도·무손실). 가독성이 높은 문서는 메시지가 명확하게 전달되고, 그것이 신뢰와 전문성의 인상을 만든다.
15
+
16
+ ## 1. 규칙표 — 값의 정본
17
+
18
+ 「표시 px」는 열람 화면의 CSS px 다. 기준 창 1440×900, 본문 단 **760px**, 전폭 **1030px**, 본문 활자 **17px / 1.75**.
19
+ `figure.mjs` 기본값 · `gazette.py` 상수 · `visual-first.md` §4 · `lim-portal-format.md` §11-1 은 **이 표를 가리키고 값을 되풀이하지 않는다**
20
+ (같은 값이 세 곳에 있으면 갈린다 — 고칠 때는 여기와 코드 상수를 함께 고친다).
21
+
22
+ | # | 규칙 | 값 | 재는 곳 | 어기면 |
23
+ |---|---|---|---|---|
24
+ | R1 글자 | 도판 **주 글자**(글자 수 가중 최빈 크기)의 표시 크기 ≥ 본문 **17px**. 어떤 글자도 ≥ **15px** | figure.mjs | ✗ |
25
+ | R2 위계 | 그림 안 **제목(h1~h3) 금지** — 캡션이 제목이다. 강조 값은 주 글자 ×1.3 이상. 크기 단계 ≤ 3 | figure.mjs | 제목 ✗ · 나머지 ⚠ |
26
+ | R3 행간 | 2줄 이상으로 접히는 요소의 line-height ≥ **1.4** (본문 문단은 1.75 로 서식이 고정) | figure.mjs | ✗ |
27
+ | R4 정보량 | 그림 안 **문장 0** — 요소 하나의 글자 > 60자 또는 2줄 이상의 서술문 금지. 설명은 캡션 한 문장과 본문으로 | figure.mjs | ✗ |
28
+ | R5 근접성 | 텍스트 상자 겹침 **0** · 텍스트 상자 사이 ≥ **1em** · 라벨 중심↔자기 표식 가로 오프셋 ≤ 1em · 표식 사이 ≥ 0.5em | figure.mjs | 겹침·표식 ✗ · 간격·오프셋 ⚠ |
29
+ | R6 대비 | 글자/배경 ≥ **4.5:1**(24px 이상 굵은 글자 3:1). 표시 19px 미만 회색 글자는 7:1 미만이면 ⚠. **뜻을 나르는 도형**(띠·막대·핀)/배경 ≥ **3:1**. 배경은 포털 도판 바탕 `#f5f6f7` 까지 합성 | figure.mjs | ✗ |
30
+ | R7 색 수 | 채도 있는 색(뜻 색) ≤ **3** + 검정·회색·흰. HSL 색상 30° 버킷으로 센다. 같은 뜻엔 같은 색 | figure.mjs | ✗ |
31
+ | R8 선명도 | 출력 픽셀 폭 ≥ 표시 폭 × **1.8**(서버 긴 변 상한 1400 에서 최대 1.84). 평면 그림(HTML 개념도·도표)은 `provider: deterministic`(무손실). 화면 캡처만 `user-provided`(손실 사다리) | figure.mjs · genetics.mjs 힌트 | ⚠ (늘려 그려지면 ✗) |
32
+ | R9 세로 | 표시 높이 ≤ **702px**(0.78 × 900) — 포털은 `max-height: 78vh` 로 세로 긴 그림의 **폭을 깎는다**. 넘으면 위아래 두 장으로 | figure.mjs · gazette.py(로컬 render.py — 운영 dry_run 은 렌더러 배포 뒤) | ⚠ |
33
+ | R10 중복·용어 | 제목·캡션·본문이 같은 말을 세 번 하지 않음. 통계 기호(SD·σ·p)는 부록에만 — `--forbid` 정규식 | figure.mjs 옵션 · 사람 눈 | ✗(forbid) |
34
+ | R11 본문·표 | 문단 사이 ≥ 1.5em · 한 줄 한글 14~45자 · 헤더 ≥ 본문 ×1.5 굵게 · 문단 ≤ 220자 · 산문 참조 번호 ≤ 3 | gazette.css 토큰 · gazette-report `read.mjs` · §10-1 | ⚠ |
35
+ | R11a 문장 | **한 문장 ≤ 60자**(공백 제외). 관보는 한 문장을 한 줄로 세우므로 문장 길이가 곧 줄 길이 — 본문 단은 한 줄에 45자, 60자면 1.4줄. 판단 항목·건처럼 가장 많이 읽는 자리는 **45자 안**으로 써 한 줄에 세운다. 접히는 문장은 마침표에서 둘로 끊는다(실측: #173 4판에서 45~57자 문장 20개가 한 번씩 접혔음) | gazette.py `text_scan` | ⚠ |
36
+ | R11b 표 칸 | 칸 ≤ **20자**(4열 이하) · ≤ **12자**(5열 이상) — 열 폭 130~180px 에서 두 줄. 설명은 ※ 주석·본문으로. 흐름도 칸 ≤ 20자·note ≤ 12자(칸 폭 200px), 조건은 note. 칸에 넣던 숫자 나열은 **행으로 푼다**(「0~6세 995 · 7~12세 5,368 …」 한 칸 → 네 행) | gazette.py `text_scan` | ⚠ |
37
+ | R11c 도판 글 | 캡션 ≤ **60자** 한 문장(「무엇을 보라」만) · 출처 줄 ≤ 80자 | gazette.py `text_scan` | ⚠ |
38
+ | R11d 요약면 | 현황 줄 ≤ **80자** 한두 문장 · 수치 칸 라벨 ≤ **16자**(이름표) · 요약 문단 본문 ≤ 160자 세 문장 | gazette.py `text_scan` | ⚠ |
39
+ | R11e 절 머리 | 도입문 ≤ 90자 두 문장 · 여백 주석 why 30 · key 45 · advice 40자(19자/줄 단) | gazette.py `text_scan` | ⚠ |
40
+ | R11f 판단 항목 | 본문 ≤ 220자 네 문장 — 첫 문장은 기한, 상세는 건으로 | gazette.py `text_scan` | ⚠ |
41
+ | R11g 부연 | 한 문장에 괄호 부연 ≤ 1, 괄호 안 ≤ 20자. 숫자 나열은 문장이 아니라 표 | gazette.py `text_scan` | ⚠ |
42
+ | R11h 과정 어휘 | 본문에 **진행 상태 어휘 0** — 「정해짐 · 회신 대기 · 남은 물음 · 정해진 것 · N판」, 개수로 상태를 세는 표 제목(「정해진 것 셋과 남은 것 하나」). 독자는 앞 회차·회신·판을 모른다. 정해진 것은 **사실**로 배경(요지)에, 결정 요청에는 **지금 열린 것만**, 회차는 `history` 에만. 원고는 직전 판의 차분이 아니라 독자의 0 상태에서 다시 쓴다(2026-09-11 「뒷 내용을 나는 알고 너는 알아도 독자는 모름」) | gazette.py `text_scan` | ⚠ |
43
+ | R12 덩어리 층 | 글 층(R11)이 문장·칸 하나의 길이를 재면 이 층은 **덩어리**(※ 주석 · 판단 항목 · 표·흐름도 · 요청 장치 · 도판 출처 · 같은 항의 되풀이)의 **문장 수와 자릿수**를 잰다. 값은 R12a~f. 전부 ⚠ 이고 거절이 아니다(실사례 2026-09-11, 고객사 결정 브리핑 — 문장은 짧아졌는데 같은 항이 여러 자리에 되풀이돼 반려) | a·b·e gazette.py `text_scan` · c·d·f 없음 — 사람 눈 | ⚠ · — |
44
+ | R12a 표 주석 | `tables[].note`(※ 주석) ≤ **2문장** — 문장은 렌더러가 문장 블록을 세우는 판별(`boundary.py`)로 센다 — 날짜 마침표(「2026. 9. 30.」·「9. 8.」)는 경계가 아니다. R11a 의 문장 길이도 같은 분할이다. 셋째 문장부터 ⚠ | gazette.py `text_scan` | ⚠ |
45
+ | R12b 판단 항목 문장 | `open_items[].body` ≤ **4문장**(R11f 의 「네 문장」과 같은 값 — 자수 220 은 R11f, 문장 수는 여기서 센다). 다섯째 문장부터 ⚠ | gazette.py `text_scan` | ⚠ |
46
+ | R12c 표 하나 | 한 절에 **같은 행 키**(같은 항·같은 선택지를 행으로 세운) 표·흐름도 ≤ **1** | 없음 — 사람 눈 | — |
47
+ | R12d 요청 장치 | `cta` 기본 **[]** — 결론 한 줄은 `notice.text` 의 몫(lim-portal-format §12.3b) | 없음 — 사람 눈 | — |
48
+ | R12e 도판 출처 | 출처 줄(`assets[].source_text`)에 **원본 이름 + 쪽/행 + (주소 또는 건 §)** — 보이는 출처 줄인 `source_text` 에 쪽·행·주소·건 § 가운데 하나는 있어야 한다(R11c 의 80자 안에서). `source_url` 은 도판에 그려지지 않으므로 대신하지 못한다. 기계는 고객·제3자 자료에서 낸 도판(`provider:"user-provided"`)만 센다 — 그린 도판(`deterministic`)·서버가 그린 삽화(`higgsfield`)는 세지 않는다. 파일로 싣는 합성은 `user-provided` 라 출처 줄에 바탕 도안의 자리를 적는다 | gazette.py `text_scan`(W2) | ⚠ |
49
+ | R12f 되풀이 | **같은 항의 이름·기한**이 문서 전체에서 서는 자리 ≤ **3** — 네 자리부터는 되풀이 | 없음 — 사람 눈 | — |
50
+
51
+ ## 2. 사람 눈이 보는 것 (기계가 못 잰다)
52
+
53
+ - 색이 **뜻**에 맞는가 — 초록=정상·노랑=주의·빨강=위험처럼 독자가 이미 아는 뜻을 거스르지 않는가.
54
+ - 색이 **선택지의 옳고 그름**을 판정하지 않는가 — 한 길만 빨강, 다른 길만 초록이면 그림이 답을 먼저 말한다. 빨강·초록은 이용자 상태를 나르는 그림에만.
55
+ - 캡션이 「무엇을 보라」인가 — 그림이 이미 보여 주는 것을 되풀이하면 장식이다.
56
+ - 라벨이 **자기 표식**을 가리키는가 — 기계는 거리만 잰다.
57
+ - 한 그림에 **한 생각**인가 — 패널 둘까지.
58
+ - 열람 화면을 **실제로 열어** 본다 — 반려는 늘 화면에서 났다(process.md 7단계 눈 검수).
59
+
60
+ ## 3. 도판을 그리는 순서 (figure.mjs 와 짝)
61
+
62
+ 1. **폭은 표시 폭 그대로**(760, 전폭이면 1030) 로 HTML 을 쓴다 — 소스 px = 표시 px 라 셈이 1:1 이 된다. 높이는 폭의 0.4~0.9배.
63
+ 2. 글자는 라벨 17px 이상, 값(강조) 22px 굵게, 보조 15px. 행간 1.45~1.5. 회색은 `#595959`(7:1) 이하로 내려가지 않는다.
64
+ 3. 뜻 색 셋을 먼저 정한다. 띠·막대는 **불투명**하게 칠하고 그 안 글자는 흰색 굵게(각 ≥ 4.5:1). 표식은 검정.
65
+ 4. 문장은 쓰지 않는다. 라벨은 12자 안. 설명하고 싶은 것은 캡션 한 문장으로, 여러 값은 표로.
66
+ 5. `node figure.mjs in.html out.png` — 기본값(scale auto → 1400px 출력)으로 돌려 ✗ 0 을 확인한다. 결과의 「provider 권고」대로 `assets[]` 에 적는다.
67
+ 6. 발행 뒤 열람 화면을 캡처해 라벨 크기와 선명도를 눈으로 본다.
68
+
69
+ ## 4. 출처
70
+
71
+ - 사용자 제시 틀(2026-09-10 카드 4장): 단락 사이 여백 = 본문 1.5배 · 헤더 = 본문 1.5배 이상 굵게 · 글자·줄 간격이 빽빽하지 않게 · 배경과 글자의 높은 대비 → 메시지 명확 전달·신뢰성.
72
+ - 「모바일 UI 디자인 기본 요소 — 타이포그래피 가독성」(brunch @chulhochoiucj0/34): 본문 16~19px(이상 17) · 행간 150~160% · 대비 4.5:1 · 문단 간격 본문의 75% · 왼끝맞춤.
73
+ - 「읽기 쉬운 웹을 위한 타이포그래피」(parksb.github.io/article/37): 행간 최소 1.5 · 위계는 크기와 굵기의 격차 · 어간 < 행간 · word-break: keep-all.
74
+ - 「좋아보이는 디자인의 비밀」(brunch @sarayun/31): 제목·본문 크기 대비 극대화 · 행간 150~200%.
75
+ - WCAG 2.1 — 1.4.3 텍스트 대비 4.5:1(큰 글자 3:1) · 1.4.11 비텍스트 대비 3:1 · 1.4.12 텍스트 간격(행간 1.5).
76
+ - 이 스킬의 `visual-first.md` §4 「글은 장치 옆 3줄」 · `lim-portal-format.md` §11-1 「도형과 실촬 화면은 인코딩이 갈린다」.
@@ -0,0 +1,44 @@
1
+ // 독자 검토 워크플로 — 발행 전에 원고를 네 관점으로 읽힌다(visual-first.md §7).
2
+ // 실행: Workflow 도구에 이 파일을 scriptPath 로 주고 args 를 넘긴다.
3
+ // args = { file: "<report.json 절대경로>", reader: "<독자 한 줄: 누구이며 무엇을 결정하나>",
4
+ // example: "<예시 한 명 한 줄: 번호·측정일·실제 값>", bitmapBudget: 3 }
5
+ // 돌아오는 것: merged.findings[](where·problem·severity·rewrite·visual) 상위 10 + overall(작성자가 할 일 5줄).
6
+ // 2026-09-08 앳플리 4차에서 이 검토가 용어 충돌(한 낱말 두 값)·수치 불일치·참조 오류·반올림 설명 오류를 잡았다.
7
+ // 2026-09-11 실사례(고객사 결정 브리핑) 반려 둘에서 더한 것 — decider 관점에 「권고가 제목·열·색·요약에 배어 동의만 받는 틀인지」,
8
+ // 새 관점 source(원본 대조: 링크를 실제로 열어 인용·쪽·값을 대조, 「흐리다」는 원본 해상도로 재측정). 원고에 확인 없이 「원본이 흐림」이 실렸었다.
9
+ // 집행자: 이 워크플로의 agent 읽기(스크립트). 렌더러 ⚠ 는 없음 — 링크를 못 여는 환경이면 source 관점은 「미확인」으로 적고 사람의 눈으로 넘긴다.
10
+ export const meta = {
11
+ name: 'report-reader-review',
12
+ description: '보고서 원고(JSON)를 처음 읽는 사람·결정권자·정보 디자이너·원본 대조 네 관점으로 읽고 막히는 곳과 시각화할 곳을 합친다',
13
+ phases: [{ title: 'Read', detail: '독자 4관점 병렬' }, { title: 'Merge', detail: '중복 제거·우선순위' }],
14
+ }
15
+ const FILE = args.file
16
+ const READER = args.reader || '고객사 기획 담당(비개발자). 판단 요청에 회신해야 한다'
17
+ const EXAMPLE = args.example || '(예시 한 명 미지정 — 원고에서 찾아 쓰라)'
18
+ const BUDGET = Number(args.bitmapBudget ?? 3)
19
+ const CTX = `[읽기 전용. 파일을 수정하지 말 것. 한글로 답할 것.]
20
+ 원고: ${FILE} (Lim 포털 관보 서식 보고서의 발행 JSON. sections[] 절, cases[] 건, open_items[] 판단 요청, summary, appendix, assets 도판)
21
+ 독자: ${READER}
22
+ 예시 한 명: ${EXAMPLE}
23
+ 도판 예산: 새 비트맵 그림은 ${BUDGET}장까지. 표·flow(4열 흐름도)·charts(막대)는 예산 밖이라 자유롭게.
24
+ 작성자 기준: 「글은 직관적이고 흐름을 이해하기 쉽게, 보충 설명은 글이 아니라 그림 같은 시각 자료로. 핵심은 굵게, 상태는 칩, 색은 뜻으로」. 단 인라인 표기(굵게·칩·[글자](주소))는 운영 렌더러에 오르기 전에는 권하지 않는다(lim-portal-format §11-6 머리) — 그 전에는 tone·표·차트로.
25
+ 표기: **굵게** · ==강조== · {{ok|칩}}(톤 ok·wait·bad·info·muted) · 차트 rows[].tone.`
26
+ const FIND = { type: 'object', properties: { findings: { type: 'array', items: { type: 'object', properties: {
27
+ where: { type: 'string', description: '절·건·항목 번호와 자리' },
28
+ problem: { type: 'string', description: '독자가 왜 막히는가 — 한 문장' },
29
+ severity: { type: 'integer', minimum: 1, maximum: 5 },
30
+ rewrite: { type: 'string', description: '글로 고친다면(개조식 2~4문장). 필요 없으면 빈 문자열' },
31
+ visual: { type: 'string', description: '그림/표/flow/chart 로 바꾼다면 — 종류(bitmap|flow|table|chart|none) + 축·칸·숫자·라벨. 예시 한 명의 숫자로' } },
32
+ required: ['where', 'problem', 'severity', 'rewrite', 'visual'] } }, overall: { type: 'string' } }, required: ['findings', 'overall'] }
33
+ const LENSES = [
34
+ ['first-time', '처음 읽는 사람 — 배경을 모른다. 정의 없이 나오는 용어, 앞 절을 안 읽으면 못 따라가는 곳, 한 낱말이 두 값을 가리키는 곳, 문단이 길어 요지가 묻히는 곳, 산문 속 참조 번호 때문에 앞뒤로 오가야 하는 곳.'],
35
+ ['decider', '결정권자 — 회신해야 한다. 판단 요청 각 항에서 「무엇을 고르는지(물음) / 두 길이 각각 무엇을 바꾸는지(그대로 두면 · 바꾸면) / 기한」이 3초 안에 읽히는지. 안 읽히는 항의 재구성안과, 항들을 한눈에 묶는 표·관문 흐름도. 수치·링크·건수가 절마다 어긋나는 곳(신뢰를 깨는 것). 권고가 제목·표 열·색(칩·톤)·요약면에 배어 독자가 동의만 하게 되는 틀(답정너)인지 — 배인 자리마다 짚고, 물음과 두 길 대칭으로 되돌린 재구성안.'],
36
+ ['visual', '정보 디자이너 — 글로 설명하는데 그림이면 한 번에 보일 곳. 원리·갈림·타임라인·분포·자리별 상태. 각 그림의 축·칸·숫자·라벨을 구체로. 표의 숫자를 문장으로 되풀이하는 문단, 굵게·칩·톤을 둘 자리.'],
37
+ ['source', '원본 대조 — 원고가 가리키는 원본을 실제로 연다: 건 cases[].source_url, 도판 출처 줄 assets[].source_text 안의 주소·쪽, 부록 출처 목록과 본문 글자 안의 맨 주소·[글자](주소). assets[].origin 은 렌더되지 않는 제공자 기록이라 대조 대상이 아니다. 인용 문구·쪽(행)·값을 원문과 대조한다. 어긋나는 인용, 원문에 없는 문장, 쪽·절 번호 오기, 고객이 눌러도 안 열리는 링크를 발견으로. 「흐리다」「못 연다」는 주장은 원본 해상도로 재측정해(PDF 는 pdfimages -list 전체, 웹은 실제로 열어) 잰 값을 problem 에 적고, 못 열었으면 「미확인」이라 적는다 — 짐작으로 판정하지 않는다. rewrite 에는 원문 문구 그대로 + 원본 이름·쪽(행)·주소로 고친 출처 줄.'],
38
+ ]
39
+ phase('Read')
40
+ const reads = (await parallel(LENSES.map(([k, inst]) => () => agent(`${CTX}\n[관점: ${k}] ${inst}\n원고 전체를 읽고 findings 를 8~14개, severity 로 정직하게 매겨라. overall 에 이 원고의 흐름이 어디서 끊기는지 3문장.`, { label: `read:${k}`, phase: 'Read', schema: FIND })))).filter(Boolean)
41
+ log(`독자 관점 ${reads.length}/${LENSES.length} · 발견 ${reads.reduce((n, r) => n + r.findings.length, 0)}`)
42
+ phase('Merge')
43
+ const merged = await agent(`${CTX}\n[합치기] 아래 네 관점의 발견을 같은 자리끼리 합치고(중복 제거), severity 합산으로 정렬해 상위 10개만 남겨라. 각 항목에 가장 구체적인 rewrite 와 visual 을 고르되, 비트맵은 ${BUDGET}장까지만 'bitmap' 으로 두고 나머지는 flow/table/chart 로 바꿔 적어라. overall 에는 「작성자가 지금 바로 할 일 순서」를 5줄로 — 용어 잠금과 수치·참조·원본 대조 오류가 그림보다 먼저다.\n${JSON.stringify(reads)}`, { label: 'merge', phase: 'Merge', schema: FIND })
44
+ return { merged, raw: reads }
@@ -0,0 +1,127 @@
1
+ # 시각 우선 집필 공식 — 글보다 먼저 정한다
2
+
3
+ > 근거 사례(2026-09-08, 앳플리 체중 조절 권장량 검수 보고 4차): 같은 날 세 번 반려됨.
4
+ > ① 「글만 적어서는 이해가 어려움. 사진이나 그림 자료가 함께 있으면 좋겠음. 내가 이해를 하고 있어도
5
+ > 네가 쓴 글은 내 이해를 혼란스럽게 하고 있음」 → 개념도 2장 + 실제 화면 캡처 1장을 붙이자 「잘했어.
6
+ > 이렇게 보고서가 되어야 해. 글은 직관적이고 흐름을 이해하기 쉽게, 보충 설명은 그림 같은 시각 자료로」
7
+ > ② 「신입은 읽다가 자겠는걸? Y/N」 → 실측: 본문 23,152자(46분), 문단 38개 평균 135자, 교차 참조 189회
8
+ > ③ 「읽기가 아직도 어려움. 색상 다변화, 핵심은 굵은 글씨, 배지 디자인과 그래프 보강」 → 인라인 표기 신설
9
+ > 그리고 「이런 식으로 genetics report 근본 로직부터 개선해 놔야 돼. 지금 일회성 교정만 해 둔 거잖아」.
10
+ > 이 문서와 렌더러 관문(§10-1)이 그 처방이다.
11
+
12
+ ## 0. 원칙 하나
13
+
14
+ **독자가 글을 읽어 머릿속에 그림을 그리게 하지 않는다. 그림을 먼저 주고 글은 그 옆에 3줄.**
15
+ 에이전트는 「글이면 충분하다」고 판단하는 쪽으로 기운다 — 글이 자기 산출물이기 때문이다. 그래서
16
+ 판단을 에이전트에게 두지 않고 렌더러가 센다(`lim-portal-format.md` §10-1 — ⛔ 운영 dry_run 은 렌더러 배포 뒤, 지금은 로컬 `render.py`). 여기는 그 앞, 원고를
17
+ 쓰기 전에 정할 것의 순서다.
18
+
19
+ ## 1. 한 장 이야기 — 요약면 다섯 칸의 순서
20
+
21
+ 문제 → 원인 → 해법 → 지금 상태 → 정할 것. `summary[]` 다섯 항목을 이 순서로 쓰고, 1절에
22
+ 「사건 경과」 표(날짜 · 일어난 일 · 상태 칩) 한 장을 둔다 — 다루는 일의 경과이지 이 문서의 판 이력이 아니다(판 이력은 `history`, SKILL 3b). 신입은 여기서 멈춰도 문서를 안 것이다.
23
+
24
+ ```json
25
+ {"label":"Decide","lead":"정식 배포 전에 정할 것은 5항, 나머지는 차기임.",
26
+ "body":"…==5항 중 「바꾼다」가 하나라도 있으면 2차 시험판을 거침==(제2절 흐름도).","refs":["6.6"]}
27
+ ```
28
+
29
+ ## 2. 예시 한 명 — 문서 전체를 한 사람의 숫자로 관통
30
+
31
+ 실존 이용자 하나(번호·측정일·실제 값)를 골라 그림·표·흐름도·건·판단 항목이 **같은 숫자**를 되풀이하게
32
+ 한다. 독자는 숫자 하나를 기억하고 그 숫자가 어디로 흘러가는지 따라간다. 앳플리 4차의 1388741(여 159cm ·
33
+ 9월 4일 63.3kg · 체지방 14.4 · 기준 체중 57.3 · 적정 체중 62.0 · 조절 −1.3)이 그 예다.
34
+ 이름은 가린다(캡처의 닉네임 칸은 `shot.mjs --mask`).
35
+
36
+ ## 3. 용어 잠금 표 — 같은 낱말이 두 값을 가리키면 거기서 죽는다
37
+
38
+ 검토 워크플로가 첫째로 잡은 것이 이것이었다: 「적정 체중」이 한 절에서는 키 기준 57.3, 다른 절에서는
39
+ 결과지 칸 62.0 을 가리켰다. 뜻이 갈리는 낱말은 **판단 요청 절에** 표 한 장으로 박는다 —
40
+ 열: 이름 · 값(예시 한 명) · 어떻게 정해지나 · 어디에 보이나. 산식 안의 값과 화면 칸 이름은 다른 낱말을 쓴다.
41
+
42
+ ## 4. 절마다 시각 장치를 먼저 정한다
43
+
44
+ | 말하려는 것 | 장치 | 만드는 법 |
45
+ |---|---|---|
46
+ | 개념·원리(왜 갈리나) | 개념도(비트맵) | HTML 한 장을 **표시 폭 그대로(760px, 전폭 1030px)** 쓰고 `assets/figure.mjs` 로 굽는다(배율 auto → 1400px 출력). 라벨 17px 이상·값 23px 굵게·행간 1.5·뜻 색 3·그림 안 문장 0 — 규칙표는 `references/readability.md` |
47
+ | 실제 화면의 확인 자리 | 번호 표식 캡처 | `assets/shot.mjs` — 페이지 안에 ①②③ 배지를 얹은 채 요소를 찍는다. 이름은 `--mask` |
48
+ | 여러 항목을 축으로 견주기 | 표(`tables`) | 칸은 짧게(20자·5열 이상 12자), 수는 `align:"r"`. 상태 칩 `{{ok|보통}}`(문법 lim-portal-format §11-6 — ⛔ 운영 반영 전에는 쓰지 않는다, 같은 절 머리) |
49
+ | 「A 가 되면 B 가 되고 C 가 된다」 | 흐름도(`flow`) | 4열 고정. 판단 절에는 「정하면 어느 길로」 관문 흐름도 |
50
+ | 분포·비중 | 막대 차트(`charts`) | 행마다 `tone` 으로 뜻 색. 두 축 비교는 `toggle` |
51
+ | 사건 경과·타임라인 | 표 | 날짜 · 일어난 일 · 상태(칩은 운영 반영 뒤 — lim-portal-format §11-6 머리) |
52
+ | **화면이 바뀌는 선택지**(비표시·제거·추가·이동) | 「그대로 두면 · 지금」 / 「바꾸면 · 재현」 두 컷 한 쌍 | 실제 화면 캡처에 바뀔 자리를 **검정** 테두리로, 뒤 컷은 그 자리를 실제로 빼고(아래 내용이 올라온 채) 빈 자리를 **회색 점선**으로 찍는다. 두 컷의 이름표는 **같은 모양**(앞 「그대로 두면 · 지금」, 뒤 「바꾸면 · 재현」), 문구는 「예시」라 적는다. **빨강·초록은 이용자 상태를 나르는 그림에만** — 선택지 두 컷에 칠하면 색이 두 길의 옳고 그름을 먼저 판정한다(실사례 2026-09-11, 고객사 결정 브리핑 「답정너 틀」 반려). 여러 항이 같은 자리를 가리키면 라벨을 「세 항 공통」으로 — 항 번호를 패널에 나눠 붙이면 독자는 항마다 자리가 다르다고 읽는다(2026-09-08 「비표시하면 어떤 게 비표시된다는 건지 UI 도 없다」 반려, 독자 시험 3/3 오독). 집행자: 없음 — 사람의 눈(readability.md §2) |
53
+
54
+ 글은 장치 옆 **3줄(220자) 안**. 표의 숫자를 문장으로 되풀이하지 않는다 — 검토가 잡은 둘째 결함이었다
55
+ (제8절 문단 8개가 표 3개를 문장으로 반복). 산문에 참조 번호(6.6 · 2.12a)를 넣지 않는다 — 번호는 표·건·항목의 몫이다.
56
+
57
+ ### 판독 — 도판은 열람 화면(본문 단 760px)에서 재고, 잣대는 글자 크기 하나가 아니다 (2026-09-08 · 09-09 반려)
58
+
59
+ 880px 로 그린 합성 그림이 9.5~12.5px 로 떠 반려됐고(9/8), 14px 게이트를 통과한 그림이 「가독성에 하자」로 다시 반려됐다(9/9 —
60
+ 라벨 15px·행간 1.3·라벨 간격 2px·띠 대비 1.2:1·뜻 색 5·그림 안 문단 150자·1x 손실 인코딩). **값의 정본은 `references/readability.md` §1
61
+ 규칙표(R1~R11)** 이고 `figure.mjs` 가 그 표를 그대로 센다 — 여기서는 되풀이하지 않는다. 그리는 순서는 그 문서 §3.
62
+
63
+ ### 도판 예산
64
+
65
+ 장당 80,000B · 합계 400,000B(WebP q78, 긴 변 1400px). 개념도는 1000~1200px 폭·색 3개면 40~55KB.
66
+ 실제 화면 캡처는 필요한 요소만(전체 페이지 금지). 넘치면 **중복 증거 도판을 빼고 부록 자료 목록에 사유를 적는다**
67
+ — 앳플리 4차에서 InBody 570 p.23(같은 주장을 970 p.12 가 담음)과 Lancet Figure 2(본문 근거 표에는 남김)를 그렇게 뺐다.
68
+ 접수 화면 캡처는 1000px 로 줄여도 읽힌다.
69
+
70
+ ## 5. 판단 요청 — 6항 이상이면 산문으로 못 고른다
71
+
72
+ - **한눈표**: 항 · 지금 · 그대로 두면 · 바꾸면 — 두 길의 결과(이용자에게 보이는 변화)를 **대칭**으로 같은 칸 모양에.
73
+ 「FCG 권고」 열은 두지 않는다 — 한 길의 결과만 있는 열도 같다(실사례 2026-09-11, 고객사 결정 브리핑 「답정너 틀」 반려).
74
+ - **관문 흐름도**: 단계 · 정할 것 · 지금 상태 · 정하면 — 「바꾼다」가 하나라도 있으면 어느 길로 가는지.
75
+ - 제목은 물음. 본문은 네 문장 안: 첫 문장은 기한과 두 길 이름 → 길마다 달라지는 것 → 근거 절(readability R12b). FCG 의견은 **한 절 한 자리**에만(낼지는 따로 묻는다) — 항마다 「권고안은 …」을 되풀이하지 않는다. 요청 문장은 완전한 높임(SKILL 5a).
76
+ - 기한은 날짜로 적는다(「2026년 10월까지」) — 「배포 전」·「차기」만 적으면 기한 ⚠ 가 뜬다.
77
+ - 항이 이용자 화면을 바꾸면(팝업·안내·칸의 유무) 글과 표만으로 묻지 않는다 — 아래 「화면 도안」 절의 도안까지 붙인다.
78
+ - 집행자: 한눈표·흐름도의 유무는 렌더러 ⚠(lim-portal-format §10-1 「판단 요청 N항이 산문으로만 섭니다」) · 권고 낱말은 `gazette.py` ⚠ W1 · 열 구성(대칭인가)은 없음 — 사람의 눈(SKILL 「카피 게이트」).
79
+
80
+ ### 화면 도안 — 결정 요청이 이용자 화면의 변화를 낳으면 도안까지 (2026-09-11)
81
+
82
+ > 반려 원문(2026-09-11, 고객사 결정 브리핑): 「앱 켜면 공지 팝업을 띄울지 — 고객 디자인 시스템에 일치하게 도안 잡고, 보고서에 결재까지
83
+ > 받으면 보고서가 제 할 일을 하는 것. 스킬도 그 정도가 base 가 되기를.」 팝업·안내·칸의 유무처럼 **화면이 바뀌는
84
+ > 결정**을 글과 표로만 물으면 결재할 물건이 없다. 개념도(§4)·캡처(shot.mjs)와 다른 세 번째 도판 — **고객 디자인
85
+ > 시스템 규격의 도안**을 붙인다.
86
+
87
+ | 순서 | 무엇 | 어떻게 |
88
+ |---|---|---|
89
+ | 1 | 규격 실측 | 고객 앱 소스에서 옮긴다 — 색 토큰 SSOT(예 `styles/global.ts` colors) · 표준 모달·안내 카드·CTA·시트의 수치 · 문구 목록의 낱말과 맺음 빈도(「닉네임」인가 「이름」인가, 「~해 주세요」인가). 추정하지 않는다 |
90
+ | 2 | 도안 HTML | 화면 폭(휴대폰 375 CSS px)으로 그린다. 값·이름은 예시라고 주석에 적고, 배경이 자리 표시면 그렇게 적는다 |
91
+ | 3 | 2배 PNG | `assets/mockshot.mjs <도안.html> <out.png>` — 요소를 2배 밀도로 찍는다(figure.mjs 와 같은 playwright-core·크롬) |
92
+ | 4 | 관보 도판 | 도판 HTML 에 `<img>` 로 앉힌다. **전폭**(`assets[].wide: true`, 1030px) 두 칸 485px 이면 앱 12px 글자가 15.5px 로 R1 을 넘는다. 760 단 1장이면 배율 1.42 이상(12 → 17px). 표시 높이 702px 안 — 긴 화면은 위·아래 크롭 두 칸 |
93
+ | 5 | 관문 | `figure.mjs --wide --img-text <화면의 가장 작은 글자 px> --img-dpr 2` ✗ 0. 전폭의 ⚠ R8 밀도 1.36 은 서버 긴 변 1400px 상한 때문이라 고정값이다 |
94
+ | 6 | 원고 | 도안 표(도안 · 모양 · 누르면 · 앱의 선례 · 바꿀 것) · 문구 출처 표 · 뜨는 조건 표 · 기존 화면 흐름(번호 표식) · 「안내를 띄울 자리」 조사 건. 권고는 FCG 의견 절 한 곳에만(§5) |
95
+ | 7 | 합성(선택) | Higgsfield `gpt_image_2` 에 도안 PNG 를 참조 그림(role image)으로 주면 한글 UI 글자를 보존한 채 손·기기 합성이 된다(2k·high 2 credits). 크기 감 그림 1장만, `provider: user-provided`, origin 에 「합성」 명시, 출처 줄 `source_text` 에 바탕 도안의 자리(「도안은 그림 1-2 · 규격은 건 §4.8」처럼 그림 번호·건 §)를 적는다 — W2 가 원본 위치를 센다. 크롭으로 `--img-text` 를 넘긴다 |
96
+ | 8 | 반출 | Figma 는 MCP 인증이 있을 때만. 없으면 HTML 원본 경로를 문서 origin 과 핸드오프에 적고 반출은 사람 몫으로 남긴다 |
97
+
98
+ 집행자: 없음 — 사람의 눈(process.md 7단계 표 「결정 요청에 화면 변화가 있는데 도안이 없다」). 실행 사례와 도판 넷의 실물 경로는
99
+ genetics(lim) 사례 「결정 요청에 화면 변화가 따르면 고객 디자인 시스템 도안까지」에 있다.
100
+
101
+ ## 6. 표기 — 색은 뜻으로
102
+
103
+ 차트 `rows[].tone` · 절·PART `tone` · `notice.state` · 건 `source_url`. 인라인 표기(`**굵게**` · `==강조==` · `{{톤|글자}}` · `[글자](주소)`, 문법 lim-portal-format §11-6)는 ⛔ 운영 반영 전에는 쓰지 않는다(같은 절 머리).
104
+ 톤 다섯: ok(끝났거나 정상) · wait(사람 판단 대기) · bad(이용자에게 나쁜 상태·오류) · info(참고) · muted(범위 밖·처리 완료).
105
+ 문단 절반이 굵으면 굵기가 위계를 못 나른다 — 절마다 한둘. 문법과 렌더는 `lim-portal-format.md` §11-6.
106
+
107
+ ## 7. 독자 검토 — 발행 전에 네 관점으로 읽힌다
108
+
109
+ `references/reader-review.workflow.js` 를 Workflow 도구로 돌린다(`args: {file: <report.json 절대경로>, reader: "<독자 한 줄>", example: "<예시 한 명 한 줄>"}`).
110
+ 처음 읽는 사람 · 결정권자 · 정보 디자이너 · 원본 대조 네 에이전트가 원고를 읽고 「어디서 막히나 / 글로 고치면 / 그림으로 바꾸면」을
111
+ severity 로 내고, 합치기 에이전트가 상위 10개로 줄인다. 앳플리 4차에서 이 검토가 용어 충돌·수치 불일치·
112
+ 참조 오류(6.6 링크의 이용자 번호)·반올림 설명 오류를 잡았다 — 작성자는 못 본 것들이다.
113
+
114
+ ## 8. 실물 확인 — dry_run 경고 0 이 목표, 그 다음은 눈
115
+
116
+ 1. 로컬 `render.py` 와 `update_report(dry_run: true)` — §10-1 경고가 0 이 될 때까지 원고를 고친다(요청 자리의 경어체 경고는 의도). ⛔ 운영 dry_run 은 렌더러 배포 뒤부터 §10-1 을 센다(lim-portal-format §11-6 머리).
117
+ 2. 발행 뒤 **열람 주소를 실제로 연다**(Cursor 인앱 브라우저 `iab` 나 헤드리스 크롬). 그림 수·이미지 로드 수·표·흐름도·차트 수를 세고
118
+ 판단 절과 그림 절을 캡처로 본다. 「구조 확인 outline」은 블록이 섰는지만 말하지 보이는지는 말하지 않는다.
119
+ 3. 큰 원고(70KB 이상)는 채팅에 붙여넣지 말고 MCP 서버를 자식으로 띄워 파일 인자로 보낸다
120
+ (`node mcp/genetics.mjs` 를 stdio JSON-RPC 로 — 스크래치 `mcp-call.mjs` 30줄).
121
+
122
+ ## 9. 하지 않는 것
123
+
124
+ - 렌더러 밖에서 색·굵기를 손으로 조판하지 않는다(단일 HTML 경로 제외). 렌더러가 없는 장치는 렌더러에 넣고 배포한다.
125
+ - 그림을 넣었으니 글을 안 줄이지 않는다 — 그림은 글을 **대체**한다.
126
+ - 「회차에 추가함」류 회차 서술을 본문 절에 쓰지 않는다(발행 이력에만).
127
+ - 예쁘라고 칠하지 않는다 — 색은 뜻이다.
@@ -1,24 +0,0 @@
1
- {
2
- "name": "scripts",
3
- "lockfileVersion": 3,
4
- "requires": true,
5
- "packages": {
6
- "": {
7
- "dependencies": {
8
- "playwright-core": "^1.62.1"
9
- }
10
- },
11
- "node_modules/playwright-core": {
12
- "version": "1.62.1",
13
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz",
14
- "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==",
15
- "license": "Apache-2.0",
16
- "bin": {
17
- "playwright-core": "cli.js"
18
- },
19
- "engines": {
20
- "node": ">=20"
21
- }
22
- }
23
- }
24
- }