genetics-mcp 2.9.0 → 2.9.2

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.
@@ -1,473 +1,31 @@
1
- # 문서 일러스트 만들기 (Higgsfield)
1
+ # 일러스트 — 폐기됨 (2026-08-24 관보 전환)
2
2
 
3
- LIM 서식(`template: "lim-report"`)의 hero·챕터 일러스트를 만드는 절차다.
4
- 계약 7.1절이 **Higgsfield 를 기본 생성 공급자**로 못박았고, hero·챕터의 `provider` 가
5
- `higgsfield` 가 아니면 **발행이 거절**된다.
3
+ > 이 문서는 관보 전환으로 폐기됐다.
4
+ > 관보 서식에는 **비트맵이 한 장도 안 실린다.**
6
5
 
7
- 도구 사용법 자체는 `higgsfield-generate` 스킬이 정본이다. 이 문서는 **절차와 규격**만 적는다.
6
+ ## ⚠ 먼저 읽을 것 — `brief` 를 주지 마라
8
7
 
9
- ---
8
+ `assets[].brief` 를 넣으면 **서버가 진짜로 그린다.**
9
+ `asset_jobs_plan()`(`www/portal/lib/asset_jobs.php:167`)은 `brief` 가 있고 `data` 가 없으면
10
+ **role 을 안 가리고** 작업을 만들고, `api.php:2414` 가 발행 때 큐에 건다.
10
11
 
11
- ## 0. 어느 길로 가는가 — **포털 발행이면 그리지 말고 맡긴다** (2026-08-19)
12
+ 그리고 `gazette.py:878-887` 이 그 결과를 **세고 버린다.**
12
13
 
13
- | 산출 | 그림을 누가 만드나 | 무엇을 하나 |
14
- |---|---|---|
15
- | **Lim 포털 발행** | **서버** | `assets[].brief` 에 **장면만** 적어 `publish_report` 를 부른다. 끝 |
16
- | 단일 HTML | 이 기계 | 아래 §1~§4 대로 직접 만든다(서버가 없으니 대신 해 줄 쪽이 없다) |
14
+ 즉 크레딧은 타고 문서에는 안 나온다.
15
+ 문서를 지우는 것만으로는 이 행동이 안 막히므로 이 묘비를 남긴다.
17
16
 
18
- 포털로 나가는 문서라면 **그림을 기다리지 않는다.** 어느 절에 어느 그림이 앉는지는
19
- 발행 전에 이미 정해져 있으므로(`chapters[].asset`), 문서는 자리만 잡고 즉시 나간다.
20
- 그 뒤 서버가 hero → 관문 → 참조 업로드 → 챕터 순으로 그려 넣고 발행물을 다시 굽는다.
21
- 독자에게는 그동안 **「그리는 중」 자리**가 보이고, 다 되면 화면이 스스로 갱신된다.
17
+ ## 쓸 수 있는 것은 하나뿐이다
22
18
 
23
- ```jsonc
24
- // publish_report 의 data.assets — 바이트도 주소도 없다. 장면만 있다.
25
- { "id": "hero", "role": "hero", "provider": "higgsfield",
26
- "alt": "…", "brief": "(그 문서의 결론을 한 장면으로)" },
27
- { "id": "chapter-01", "role": "chapter", "provider": "higgsfield",
28
- "alt": "…", "brief": "(그 장이 주장하는 것)" }
29
- ```
19
+ `assets[].role` 중 관보가 싣는 것은 **`logo`** 하나다 — 표지 우상단 고객사 마크.
20
+ `data:image/` 로 시작하는 값이어야 읽는다(`gazette.py:142`).
21
+ 로고를 못 받았으면 `assets` 를 비우고 `client` 에 이름만 적는다 — 렌더러가 활자로 세운다.
30
22
 
31
- **왜 이렇게 바뀌었나.** 예전에는 이 기계에서 8장을 순차로 만든 뒤에야 발행했다 —
32
- 대화가 10~15분 멈췄고, 그 사이 기계가 잠들면 거기서 끝났다. 서버는 안 잠든다.
23
+ `hero` · `chapter` · `figure` · `eof` 는 전부 세어서 버려진다.
24
+ `REPORT_EOF_TEMPLATES = []`(`report_publish.php:1249`)라 꼬리 카드도 안 붙는다.
33
25
 
34
- **무엇이 옮겨 갔고 무엇이 남았나.**
26
+ ## 그 자리를 무엇이 채우는가
35
27
 
36
- | | 어디에 있나 |
37
- |---|---|
38
- | **장면**(무엇을 그릴지) | **여전히 이쪽.** 그 문서의 챕터 데이터에서 나온다 — §1b 가 그대로 유효하다 |
39
- | 스타일 계약·모델·비율 | 서버(`www/portal/lib/asset_jobs.php` 의 `ASSET_STYLE`) |
40
- | 참조 체인(hero → 챕터) | 서버 |
41
- | 재시도·한도 백오프 | 서버 |
42
- | 시각 관문 | 서버(`lib/report_visual.php`, 발행 때 쓰는 것과 **같은 자**). hero 는 떨어지면 다시 만들고(2회), 챕터는 경고만 남는다 |
28
+ 표지 가운데의 **빈 마당**과 문서를 닫는 **판권지**가 그 자리의 문법이다.
29
+ 관보는 괘선과 여백과 활자로 만든다 — 그림으로 만들지 않는다.
43
30
 
44
- **브리프에 스타일을 적지 말 것.** 선 굵기·라임 hex·금지 목록은 서버가 얹는다.
45
- 두 벌이 되면 갈라지고, 갈라지면 어느 쪽이 이겼는지 아무도 모른다.
46
-
47
- ⚠ **진행을 되풀이해 두드리지 말 것.** `report_assets(id)` 가 진행을 말해 주지만
48
- 한 장에 60~120초다. 7장짜리면 처음 물어보기까지 5분쯤 두는 편이 낫다.
49
- 그리고 **다시 발행하지 말 것** — 교체(PUT)는 옛 슬롯을 지우고 새로 걸어서,
50
- 방금 시작한 생성이 통째로 버려진다.
51
-
52
- 아래 §1~§4 는 **단일 HTML 산출**과 **서버가 낸 결과를 사람이 검수할 때**의 정본이다.
53
- 브리프 표(§1c)는 두 길 모두에서 먼저 쓴다 — 그것이 계약 §7.1 의 첫 산출물이다.
54
-
55
- > **이 문서에 나오는 참조 세트 경로(`_template/…`)와 아이콘 예시는 한 프로젝트의 표본이다.**
56
- > 다른 고객사·다른 업종은 **자기 참조 세트와 자기 팔레트**로 같은 절차를 밟는다.
57
- > 스킬은 *어떻게* 할지만 정하고, *무엇을* 그릴지는 그 문서의 데이터가 정한다(SKILL.md 9항).
58
-
59
- ---
60
-
61
- ## 0. 순서를 지킨다
62
-
63
- 계약 7.1절: *"자산 생성은 **문서 내용과 디자인 계약이 확정된 뒤에만** 시작한다."*
64
- 브리프 없이 만들면 장마다 다른 세트가 나온다 — 실제로 그렇게 한 번 만들어 전량 재생성했다.
65
-
66
- 1. 내용 확정(건·요약·챕터 문안) → 2. 슬롯별 브리프 → 3. 생성 → 4. **전수 시각 검수** → 5. 발행
67
-
68
- ---
69
-
70
- ## 1. 모델과 호출 — 실측으로 정해진 것
71
-
72
- | 항목 | 값 | 근거 |
73
- |---|---|---|
74
- | 모델 | **GPT Image 2** (`gpt_image_2`) | 사용자 지정. 선이 균일하고 여백이 깨끗하다 |
75
- | 호출 | `higgsfield generate create … --wait` (**CLI**) | MCP 이미지 도구가 아니라 CLI 를 쓴다 |
76
- | 비율 | hero `16:9` · 챕터 `4:3` | |
77
- | 해상도 | `2k` | 긴 변 1400 으로 줄일 것이므로 축소가 확대보다 낫다 |
78
- | 산출 | PNG (약 1.8–3.9MB) | 발행물엔 안 들어간다. MCP 가 WebP q78 로 굳힌다 |
79
-
80
- ```bash
81
- higgsfield generate create gpt_image_2 --wait \
82
- --aspect_ratio 16:9 --resolution 2k --prompt "…"
83
- ```
84
-
85
- ### 세트 일관성은 **참조 이미지**로 잡는다
86
-
87
- hero 를 먼저 만들고, 그것을 `--image` 로 넘겨 챕터를 잇는다. 프롬프트만으로는 장마다
88
- 인물이 달라진다(얼굴 있음/없음·정면/측면이 뒤섞였다).
89
-
90
- ```bash
91
- # 한 번만 올리고 UUID 를 재사용한다 — 매번 파일을 주면 업로드가 작업 수를 배로 늘려
92
- # 동시 실행 한도(8)에 걸린다.
93
- REF=$(higgsfield upload create hero.png --json | jq -r .id)
94
- higgsfield generate create gpt_image_2 --wait --aspect_ratio 4:3 --resolution 2k \
95
- --image "$REF" --prompt "Keep the same flat line-art style, same character design… Scene: …"
96
- ```
97
-
98
- 참조를 줄 때 프롬프트는 **바뀌는 것만** 적는다(입력을 다시 묘사하지 않는다).
99
-
100
- ⚠ 동시 제출이 잦으면 `rate_limit_reached` 가 난다. 순차로 돌리고, 실패하면 45초 뒤 재시도한다.
101
-
102
- ---
103
-
104
- ## 1b. 장면은 **그 문서에서 나온다** — 고정 목록을 두지 않는다
105
-
106
- **이 파일에 장면 예시를 적어 두고 그것을 돌려 쓰면 안 된다.** 보고서마다 다룰 내용이 다르므로
107
- 일러스트도 달라야 하고, 그 판단은 **읽는 쪽(LLM)이 매번** 한다. 스크립트에 장면 문자열을
108
- 박아 넣는 순간 문서가 바뀌어도 같은 그림이 나온다(2026-08-16 실제로 그렇게 짰다가 반려됨).
109
-
110
- 장면을 정하는 재료는 **그 챕터의 데이터**다:
111
-
112
- | 재료 | 쓰임 |
113
- |---|---|
114
- | `chapters[].title` / `title_lines` | 그 장이 주장하는 **한 문장** — 장면의 뼈대 |
115
- | `chapters[].lead` | 왜 읽어야 하는지 — 무엇을 대비시킬지 |
116
- | `chapters[].topics` | 그 장이 다루는 항목 — 화면에 놓을 **오브젝트** |
117
- | 그 장에 속한 `cases[].title` | 실제로 무슨 일이 있었는지 — 행동의 근거 |
118
-
119
- 그리고 **장마다 달라야 하는 것**을 의식적으로 갈라 준다. 안 그러면 참조 이미지 때문에
120
- 전 장이 같은 포즈로 수렴한다(1차 실측: 7장 중 5장이 「남자가 왼팔 들고 여자는 팔짱」).
121
-
122
- | 축 | 예 |
123
- |---|---|
124
- | 시점 | 전신 / 손 클로즈업 / 뒤에서 / 사람 없이 도식만 |
125
- | 주체 | 두 사람 / 한 사람 / **인물 없음** |
126
- | 오브젝트 | 눈금자 · 카드판 · 막대 · 경로 · 화면과 표 |
127
- | 동작 | 옮긴다 · 맞춘다 · 모인다 · 짚는다 · 정렬된다 |
128
-
129
- 참조 이미지에 `same character design` 은 넘기되 **`figures on the right third` 처럼 구도를
130
- 고정하는 문구는 넘기지 않는다** — 그것이 1차에서 전 장을 같은 그림으로 만든 원인이다.
131
-
132
- ---
133
-
134
- ## 1c. 그리기 전에 **브리프 표**를 쓴다
135
-
136
- 정본은 그림을 바로 만들지 않았다 — `image-briefs.md` 라는 **표를 먼저 썼다**. 그 형식을 따른다.
137
- 계약 §7.1 의 첫 단계(「자산 브리프」)가 요구하는 산출물이 바로 이것이다.
138
-
139
- 문서 작업 폴더에 `image-briefs.md` 를 만들고 두 부분을 채운다:
140
-
141
- 1. **공통 스타일 계약** — §2.1 의 정본 문단을 **그대로 복사**한다. 문서마다 다시 쓰지 않는다.
142
- 2. **자산 표** — 아래 네 칸. 장면은 §1b 의 재료(그 문서의 챕터 데이터)에서 나온다.
143
-
144
- ```markdown
145
- | 자산 | 비율·구도 | 주제와 장면 | 텍스트 안전 영역 |
146
- | --- | --- | --- | --- |
147
- | Hero | 16:9, 2K급 | (그 문서의 결론을 한 장면으로) | **왼쪽** — 선은 지나가되 연하고 고르게, 채운 형태·얼굴 없음 |
148
- | Chapter 01 | 4:3 | (그 장이 주장하는 것) | **왼쪽** — 인물·채운 형태는 오른쪽에 모으고, 왼쪽은 얇은 선만 |
149
- | Chapter 02 | 4:3 | … | **오른쪽** — 인물·채운 형태는 왼쪽에 모으고, 오른쪽은 얇은 선만 |
150
- ```
151
-
152
- 네 번째 칸은 **그 장의 배치**(글이 어느 쪽에 서는가)를 적는다. 홀수 장은 왼쪽,
153
- 짝수 장은 오른쪽으로 교차한다(정본 `is-reverse`, 렌더러의 `data-side`).
154
-
155
- ⚠ 이 칸은 **그림에 지시를 주지 않는다.** 글과 그림은 하나의 테두리 안에서 **좌우로 따로**
156
- 서고(계약 4.2절 v1.4), 그림 위에는 아무것도 앉지 않는다. 그래서 그림은 **자기 칸을 꽉
157
- 채우면 된다** — 한쪽을 비우지 말 것. 이 칸은 사람이 장 순서를 바꿀 때 대조하는 용도다.
158
-
159
- 2026-08-17~18 에 이 칸을 「글이 앉을 쪽을 연하게 그려라」로 읽고 프롬프트에 넣었다가
160
- 반려됐다. 글을 그림 위에 얹는다는 전제 자체가 오독이었다.
161
-
162
- ### 장면은 **오브젝트를 이름으로** 적는다
163
-
164
- 「원형 노드 다섯 개」처럼 **개수만 적으면 모델이 빈칸을 스톡 아이콘으로 채운다.**
165
- 2026-08-17 실측: 판단 항목 아홉 개를 그리라고 했더니 **우산·돼지저금통·집·하트비트**가 나왔다 —
166
- 보험 상품 도상이고 문서와 아무 상관이 없다. 관문(색 면적)은 이것을 **못 잡는다.**
167
-
168
- 노드 안에 무엇이 드는지 **그 장의 `topics` 에서 뽑아 이름으로** 적는다:
169
-
170
- | 나쁨 | 좋음 |
171
- |---|---|
172
- | 「원형 노드 다섯 개」 | 다섯 노드에 들어갈 사물을 **그 장의 `topics` 하나씩에 대응시켜 이름으로** 적는다 |
173
- | 「선택 노드 아홉 개」 | 사물이 아닌 개념(결정·판단·선택)이면 **속이 빈 동그라미**라고 못박고 「아이콘을 넣지 않는다」를 덧붙인다 |
174
- | 「라임 원 하나」 | 노드 안에 무엇이 드는지 함께 적는다 — 안 적으면 **속이 빈 색 동그라미**가 나온다 |
175
-
176
- **주제 낱말은 브리프에만 있고 스킬에는 없어야 한다.** 이 파일에 특정 업종의 아이콘 목록을 적어
177
- 두면 다음 고객사에서 그 목록이 그대로 나온다 — 스킬은 **어떻게 적을지**만 정하고, **무엇을 적을지**는
178
- 그 문서의 `topics` 가 정한다.
179
-
180
- 큰 노드를 「라임 원」이라고만 적으면 **속이 빈 라임 동그라미**가 나온다. 정본은 노드 안에
181
- 반드시 무언가 든다 — 안에 들 것을 같이 적는다.
182
-
183
- **생성기는 이 파일만 읽는다.** 스크립트 안에 장면 문자열이 있으면 안 된다 — 문서가 바뀌어도
184
- 같은 그림이 나온다(2026-08-16 반려 사유). 브리프가 곧 입력이고, 브리프가 없으면 생성하지 않는다.
185
-
186
- ---
187
-
188
- ## 2. 프롬프트 규격
189
-
190
- > **2026-08-17 — 이 절은 통째로 다시 썼다.** 앞선 판의 고정 블록은 **정본 그림을 한 번도 안 보고**
191
- > 계약 7절의 요약 한 문장 + 하루치 픽셀 튜닝 로그로 만든 것이었고, 세 곳이 정본과 **정반대**였다:
192
- > `large filled areas`(정본은 「넓은 면에 칠하지 않는다」) · `All surfaces stay blank`(계약에 없는
193
- > 발명, 아이콘까지 금지시킴) · `wide calm margins`(정본은 프레임을 채운다). 그 결과 정본의
194
- > 「아이콘 든 원형 노드 + 점선 연결선 + 작은 라임 배지 다수」가 「막대 하나 + 인물 둘」로 붕괴했다.
195
-
196
- ### 2.0 정본은 실물이다
197
-
198
- | 무엇 | 어디 |
199
- |---|---|
200
- | 그림 원본 8장 | `_template/lim-report-assets/*.png` |
201
- | **제작 브리프** | `_template/lim-report-final-handoff.zip` 안 `documents/image-briefs.md` |
202
- | 렌더 결과 | `_template/lim-report-static/lim-weight-guidance-audit.static.html` |
203
-
204
- **프롬프트를 쓰기 전에 실물을 연다.** 이 파일은 사용법이지 정본이 아니다.
205
-
206
- ### 2.1 공통 스타일 계약 — 정본 원문 그대로
207
-
208
- `image-briefs.md` 의 첫 문단이다. **요약하지 말고 이 문장을 근거로 쓴다**(요약이 사고의 시작이었다).
209
-
210
- > 모든 생성 자산은 한 세트처럼 보여야 한다. `Ink #191A23`의 깨끗하고 일정한 라인 아트,
211
- > `White #FFFFFF`와 `Mist #F3F3F3` 면, **`Lime #B9FF66` 한두 지점만** 사용한다. 선 굵기, 인물 비율,
212
- > 손·얼굴 단순화, 옷의 채색 면적을 통일한다. **텍스트, 숫자, 로고, 워터마크, 사진풍, 3D,
213
- > 그라데이션, 네온, 복잡한 의료 장비, 가짜 UI는 금지**한다.
214
-
215
- ### 2.2 실물에서 읽은 조형 문법 (계약 문장에는 없다)
216
-
217
- 계약에는 조형 어휘가 0개다(`점선`·`원형`·`노드` 각 0회). 그림을 보고 세어야 나온다:
218
-
219
- | 장치 | 실물에서 |
220
- |---|---|
221
- | 원형 노드 | **그 문서가 다루는 사물**을 단순 선 아이콘으로 담은 동그라미. 무엇이 들어갈지는 문서마다 다르다 — 정본 표본(체중 관련 문서)에서는 저울·클립보드+돋보기·노트북·스마트폰·문서·장바구니·별·말풍선이 쓰였다 |
222
- | 연결 | **점선**과 실선 곡선을 섞어 노드를 잇는다 |
223
- | 배지 | 검은 원 안 ✕ · 라임 원 안 ✓ · 라임 원 안 ! |
224
- | 라임 | **여러 곳에 작게** — 옷 이너, ✓ 배지, 인물 실루엣 채움, 발밑 그림자, 작은 마름모 |
225
- | 인물 | 검은 머리(포니테일·단발·짧은머리), 흰 셔츠 + 라임 이너, **이목구비 있는 얼굴**, 반신 크롭 |
226
- | 구도 | 인물이 한쪽, 도식이 반대쪽. **프레임을 채운다** |
227
-
228
- ### 2.3 프롬프트 고정 블록
229
-
230
- ```
231
- Flat line illustration in one consistent set. Clean uniform thin dark outlines (#191A23)
232
- on pure white, with light gray (#F3F3F3) fills. People have black hair, white shirts with
233
- a small lime accent garment, and simple drawn faces; keep figure proportions identical
234
- across the set.
235
- Build the scene as a small diagram: icons inside outlined circles, connected by dotted and
236
- solid curved lines, with small badges — a dark circle holding an X, a lime circle holding
237
- a check.
238
- The one accent colour is lime, exactly the hex #B9FF66 — a bright yellow-green highlighter
239
- tone, much lighter and more yellow than grass green. Never use a darker or duller green.
240
- Place the lime in several small spots — a garment accent, a filled badge, a small figure,
241
- a ground shadow — never as one large filled area.
242
- Draw the people large: cropped at the waist, each figure about one third of the frame
243
- height, with visible hands and facial features. Small distant figures are wrong for this set.
244
- Fill the frame densely: keep the outlined circles large and close together, add a few small
245
- loose accents around them — tiny dots, thin arcs, small diamonds — so the drawing reaches
246
- near the edges of the frame.
247
- Composition: the drawing fills its frame edge to edge as one balanced scene.
248
- Do not leave one half of the frame empty - there is no text on top of this picture.
249
- No text, no numbers, no logos, no watermarks, no photographic or 3D style, no gradients,
250
- no neon, no fake UI.
251
- ```
252
-
253
- - **hex 를 박지 않으면 잔디 초록이 나온다.** 서술만으로는 `#B4D92A` 가 나왔다(2026-08-16 실측).
254
- `exactly the hex #B9FF66` + `Never use a darker or duller green` 이라야 잡힌다.
255
- - **라임은 「여러 곳에 작게」다.** 「큰 면으로」 지시하면 정본의 배지 문법이 통째로 사라진다.
256
- 정본 실측이 0.75–1.91% 뿐이라는 사실이 이 지시를 뒷받침한다(§3).
257
- - **숫자는 `Wordless` 만으로 안 막힌다.** 1차에서 `42`·`27`·`43`·`31` 이 합성됐다.
258
- 막을 대상은 **글자**이지 표면이 아니다 — `All surfaces stay blank` 로 일반화하면 아이콘·표지·라벨
259
- 같은 정본의 디테일까지 함께 죽는다. 브리프 원문의 금지 목록(§2.1)을 그대로 쓴다.
260
- - **모델은 `gpt_image_2`.** 6종 비교(2026-08-17, 같은 프롬프트·16:9)에서 유일하게 정본 선화 품질에
261
- 도달했다 — `openai_hazel` 은 16:9 자체가 불가하고 색 오차 최악(43), `z_image` 는 선화가 아니며,
262
- `flux_2`(3.60%)·`seedream_v5_pro`(3.19%)는 라임이 계약 §1 을 넘는다. `nano_banana_2` 는 값은
263
- 좋으나(2 크레딧·44초) 얼굴 없는 실루엣이라 정본과 계열이 다르다. 값은 7 크레딧/장.
264
- - **밀도는 「채워라」가 아니라 「어디에 모아라」로 준다.** 세 라운드 실측(2026-08-17):
265
-
266
- | 지시 | 결과 | 판정 |
267
- |---|---|---|
268
- | 밀도 언급 없음 | 인물이 작고 여백이 넓다 (Ink 밴드 **미달**) | 성김 |
269
- | `fill the frame densely … reaches near the edges` | 인물이 프레임의 75~85%, **양쪽 끝에 벌어짐** (Ink·Surface **초과**) | 빽빽함 |
270
- | `each figure about half the frame height` + `keep every figure on the SAME side` + `group the drawing into about two thirds of the frame` + 위의 `light and even` 문단 | 정본과 같은 구도 | ← 쓸 것 |
271
-
272
- 「채워라」와 「글자리」는 **싸우지 않게** 써야 한다. 둘 다 같은 프롬프트 안에 있으므로,
273
- 뒤엣것을 「비워라」로 쓰면 앞엣것과 정면충돌해 모델이 한쪽을 버린다. 그래서 글자리 지시는
274
- **금지가 아니라 성질**로 준다 — `may continue across it, but only as thin outlines`.
275
-
276
- - **밀도를 말하지 않으면 성기게 나온다.** 문법(원형 노드·점선·배지)을 다 지켜도 인물이 작고
277
- 여백이 넓으면 정본과 다르다 — 관문의 **Ink**(선 밀도)가 그것을 잡는다. 2026-08-17 실측:
278
- 문법을 고친 4장이 Ink **0.66~1.66%** 로 밴드(1.67–4.07%) 미달이었다. 두 문장을 더 준다 —
279
- `people large: cropped at the waist, each figure about one third of the frame height` 와
280
- `fill the frame densely … reaches near the edges of the frame`(뒤에 글자리 문단이 붙는다).
281
- - **생성기는 스킬이 갖고 있다** — `assets/generate-illustrations.py`.
282
- 스크래치패드에 두면 다음 세션이 못 쓰고, 그때마다 다시 쓰다가 규칙이 빠진다.
283
-
284
- ```bash
285
- python3 ~/.claude/skills/genetics-report/assets/generate-illustrations.py \
286
- --brief <문서>/image-briefs.md --out <폴더>
287
- # 한두 장만 다시: --only ch02,ch05 --ref <세트참조UUID>
288
- ```
289
-
290
- 장면·비율·글자리 쪽은 **전부 브리프에서** 온다. 스크립트가 가진 것은 스타일 계약뿐이고,
291
- 브리프가 쪽을 안 말하면 **그 장을 만들지 않는다**(기본값을 넣으면 어긋남이 숨는다).
292
-
293
- - **색·밀도 미달은 레버 셋으로 잡는다.** 2026-08-18 hero 한 장(7크레딧)으로 **먼저 증명하고**
294
- 나머지를 돌렸다 — 세트를 통째로 돌린 뒤 재는 것보다 42크레딧 싸다.
295
-
296
- | 레버 | 문장 | 움직인 값 |
297
- |---|---|---|
298
- | 채도 유지 | `never wash it out toward pale mint, sage or pastel yellow-green: it must stay vivid and fully saturated` | 강조색 거리 **55.8 → 12.8** (정본 22.4) |
299
- | 선 굵기 | `Draw the outlines confidently thick and solid - the line weight of a printed editorial illustration, not a faint hairline sketch` | Ink 0.987 → 1.025% · 강조 면적 0.283 → **0.543%** |
300
- | 회색 절제 | `only inside a few small shapes … Never fill a background, a panel, a board, a large circle or a garment with gray` | Surface 5.936 → **4.x%** (밴드 상한 5.04) |
301
-
302
- 회색은 **한 번에 안 들었다.** 「sparingly, only inside small shapes」로는 5.239% 로 여전히
303
- 초과했고, 채우면 안 되는 것을 **이름으로 열거**(background·panel·board·large circle·garment)
304
- 하고서야 들어왔다. 「적게 써라」가 아니라 **「이것들엔 쓰지 마라」**로 준다.
305
-
306
- - **참조 UUID 는 첫 장의 결함까지 나른다.** 6차에서 hero 의 흐린 라임(#C8E997, 거리 55.8)이
307
- 참조로 올라가 뒤 6장이 전부 그 색을 물려받았다(50.7·57.4 …). **hero 를 관문에 통과시킨 뒤**
308
- 참조로 올릴 것.
309
-
310
- - **`rate_limit_reached` 는 재시도로 넘는다.** 동시 작업 한도가 8이라 순차로 돌려도 걸린다.
311
- 재시도가 없으면 **그 장이 통째로 빈다**(2026-08-17 3장 유실). 45·90·135초로 물러서며 4회.
312
- - **글자리는 「비우는」 것이 아니라 「연하게 그리는」 것이다.** ⚠ 2026-08-17 반려 —
313
- `The entire left 40 percent stays clean empty white` 로 지시하면 그림이 반쪽이 되고,
314
- 겹침의 뜻(그림이 글의 짝)이 사라진다. 사용자 판정: *「애초에 그림 생성 자체부터가
315
- 여백으로 만들어져서는 안 된다」*.
316
-
317
- 정본 실측이 이를 뒷받침한다 — 챕터 6장 중 **4장이 좌 40% 에 잉크를 갖는다**(최대 14.94%).
318
- 정본이 지킨 것은 공백이 아니라 **밝기**다:
319
-
320
- | 자산 | 글자리 밝은 쪽 평균 | 반대쪽 |
321
- |---|---|---|
322
- | chapter-01 | 251.8 | — |
323
- | chapter-02 | 248.7 | 237.7 |
324
- | chapter-04~06 | 249~252 | 238~239 |
325
-
326
- 8장 전부 **한쪽이 248 이상**이다. 그래서 지시는 「비워라」가 아니라 위 프롬프트의
327
- `light and even … not an empty one` 이다.
328
-
329
- ⚠ **이 두 축은 2026-08-18 에 관문에서 뺐다.** 글이 그림 위에 얹힐 때만 뜻이 있는
330
- 지표인데 배치가 좌우 분리로 정정됐다 — 그림 위에 아무것도 앉지 않으므로 잴 것이 없다.
331
- 측정 자체(`text_bg_l`·`text_bg_r`·`text_side`)는 남겨 두되 판정에는 쓰지 않는다.
332
- 안 재는 것을 재는 척하는 관문은 없는 관문보다 나쁘다: 그 초록불이 근거로 인용된다.
333
-
334
- - **생성기는 스킬이 갖고 있다** — `assets/generate-illustrations.py`.
335
- 스크래치패드에 두면 다음 세션이 못 쓰고, 그때마다 다시 쓰다가 규칙이 빠진다.
336
-
337
- ```bash
338
- python3 ~/.claude/skills/genetics-report/assets/generate-illustrations.py \
339
- --brief <문서>/image-briefs.md --out <폴더>
340
- # 한두 장만 다시: --only ch02,ch05 --ref <세트참조UUID>
341
- ```
342
-
343
- 장면·비율·글자리 쪽은 **전부 브리프에서** 온다. 스크립트가 가진 것은 스타일 계약뿐이고,
344
- 브리프가 쪽을 안 말하면 **그 장을 만들지 않는다**(기본값을 넣으면 어긋남이 숨는다).
345
-
346
- - **색·밀도 미달은 레버 셋으로 잡는다.** 2026-08-18 hero 한 장(7크레딧)으로 **먼저 증명하고**
347
- 나머지를 돌렸다 — 세트를 통째로 돌린 뒤 재는 것보다 42크레딧 싸다.
348
-
349
- | 레버 | 문장 | 움직인 값 |
350
- |---|---|---|
351
- | 채도 유지 | `never wash it out toward pale mint, sage or pastel yellow-green: it must stay vivid and fully saturated` | 강조색 거리 **55.8 → 12.8** (정본 22.4) |
352
- | 선 굵기 | `Draw the outlines confidently thick and solid - the line weight of a printed editorial illustration, not a faint hairline sketch` | Ink 0.987 → 1.025% · 강조 면적 0.283 → **0.543%** |
353
- | 회색 절제 | `only inside a few small shapes … Never fill a background, a panel, a board, a large circle or a garment with gray` | Surface 5.936 → **4.x%** (밴드 상한 5.04) |
354
-
355
- 회색은 **한 번에 안 들었다.** 「sparingly, only inside small shapes」로는 5.239% 로 여전히
356
- 초과했고, 채우면 안 되는 것을 **이름으로 열거**(background·panel·board·large circle·garment)
357
- 하고서야 들어왔다. 「적게 써라」가 아니라 **「이것들엔 쓰지 마라」**로 준다.
358
-
359
- - **참조 UUID 는 첫 장의 결함까지 나른다.** 6차에서 hero 의 흐린 라임(#C8E997, 거리 55.8)이
360
- 참조로 올라가 뒤 6장이 전부 그 색을 물려받았다(50.7·57.4 …). **hero 를 관문에 통과시킨 뒤**
361
- 참조로 올릴 것.
362
-
363
- - **`rate_limit_reached` 는 재시도로 넘는다.** 동시 작업 한도가 8이라 순차로 돌려도 걸린다.
364
- 재시도가 없으면 **그 장이 통째로 빈다**(2026-08-17 3장 유실). 45·90·135초로 물러서며 4회.
365
- - **글자리는 「비우는」 것이 아니라 「연하게 그리는」 것이다.** ⚠ 2026-08-17 반려 —
366
- `The entire left 40 percent stays clean empty white` 로 지시하면 그림이 반쪽이 되고,
367
- 겹침의 뜻(그림이 글의 짝)이 사라진다. 사용자 판정: *「애초에 그림 생성 자체부터가
368
- 여백으로 만들어져서는 안 된다」*.
369
-
370
- 정본 실측이 이를 뒷받침한다 — 챕터 6장 중 **4장이 좌 40% 에 잉크를 갖는다**(최대 14.94%).
371
- 정본이 지킨 것은 공백이 아니라 **밝기**다:
372
-
373
- | 자산 | 글자리 밝은 쪽 평균 | 반대쪽 |
374
- |---|---|---|
375
- | chapter-01 | 251.8 | — |
376
- | chapter-02 | 248.7 | 237.7 |
377
- | chapter-04~06 | 249~252 | 238~239 |
378
-
379
- 8장 전부 **한쪽이 248 이상**이다. 그래서 지시는 「비워라」가 아니라 위 프롬프트의
380
- `light and even … not an empty one` 이다.
381
-
382
- **관문은 두 축으로 잰다** — 하나로 하면 정본이 자기 기준에 떨어진다:
383
-
384
- | 축 | 하한 | 뜬 곳 | 정본 |
385
- |---|---|---|---|
386
- | 밝은 쪽이 있는가 | **247.7** | 8장의 `max(좌,우)` 최솟값 | 7/7 |
387
- | 앉히는 쪽이 밝은가 | **237.9** | 정본이 **실제로 글을 앉힌 쪽**의 최솟값 | 7/7 |
388
-
389
- 둘째 축을 첫째와 같은 값으로 두면 **정본 chapter-05 가 떨어진다**(글은 왼쪽인데
390
- 그 왼쪽이 238.9). 계약 §7 「Lime 2–8%」가 정본 0/7 이었던 것과 같은 함정이다.
391
-
392
- 쪽이 어긋나면(앉히는 쪽 ≠ 밝은 쪽) **경고**만 낸다. 실패로 못 만든다 — 정본 6장 중
393
- 1장이 그 모양이기 때문이다. 정본의 좌우는 추정이 아니라 정본 HTML 실측이다:
394
- `chapter-opener` 에 `is-reverse` 가 붙은 2·4·6장이 글 오른쪽, 1·3·5장이 왼쪽.
395
-
396
- ```bash
397
- # 브리프가 정한 쪽을 파일 뒤에 붙여 준다
398
- python3 tools/visual-baseline.py check out/hero.png:l out/ch01.png:l out/ch02.png:r …
399
- ```
400
- - **인물 자리를 고정하지 않는다.** 정본은 챕터마다 좌우를 교차한다(`is-reverse`). 장면마다 다른
401
- 행동·오브젝트·시점을 준다.
402
-
403
- ---
404
-
405
- ## 3. 시각 검수 — 전수, 눈으로
406
-
407
- 계약 7.1절이 요구하는 단계다. **표본이 아니라 전수**를 본다.
408
-
409
- | 검사 | 방법 | 기준 |
410
- |---|---|---|
411
- | **정본과 나란히** | 눈 | `_template/lim-report-assets/*.png` 8장 옆에 놓고 본다. 조형 문법(§2.2)이 살아 있나 |
412
- | 개념이 원문과 맞나 | 눈 | 그 문서 브리프의 원문 근거와 대조 |
413
- | 글자·로고 합성 | 눈 (벡터면 `<text>` 개수) | 0 |
414
- | 글자리 | 도구 | 글 앉는 쪽 46% 평균 밝기 **≥ 247.7** · 밝은 쪽이 브리프가 지정한 쪽과 일치 |
415
- | 세트 일관성 | 눈 | 인물 디자인·선 굵기·채색량이 같은가 |
416
- | 색 면적 | `assets/visual-baseline.py check` | **기준선 파일이 정한다.** 수치를 여기 적지 않는다 — 참조 세트와 팔레트마다 다르다 |
417
-
418
- > **다른 고객사·다른 서식이면 자기 기준선을 뜬다.** 밴드는 참조 세트에서 나오고 색 판정은
419
- > 그 문서의 **팔레트**로 한다 — `lim` 은 강조색이 `#B9FF66` 이지만 `korean-navy` 는 금색
420
- > `#C9A961` 이라, 색을 상수로 박으면 그 서식에서 전량 오판정한다(실측으로 확인).
421
- >
422
- > 도구는 이 스킬이 갖고 있다 — `assets/visual-baseline.py`. 저장소에 복사해 두지 말 것
423
- > (복사본은 갈라지고, 갈라진 순간 색을 상수로 박는 유혹이 생긴다).
424
- >
425
- > ```bash
426
- > T=~/.claude/skills/genetics-report/assets/visual-baseline.py
427
- >
428
- > # ① 팔레트 이름으로 — 그 프로젝트의 palette.py 를 가리킨다
429
- > python3 "$T" freeze --ref <원본 폴더> --palette-module <프로젝트>/palette.py \
430
- > --palette <이름> --base <기준선>.json
431
- >
432
- > # ② 팔레트 모듈이 없으면 색을 직접
433
- > python3 "$T" freeze --ref <원본 폴더> --accent '#RRGGBB' --ink '#RRGGBB' \
434
- > --surface '#RRGGBB' --base <기준선>.json
435
- >
436
- > python3 "$T" check --base <기준선>.json <png>... # 기준선이 색을 지고 다닌다
437
- > python3 "$T" selftest --ref <원본 폴더> --base <기준선>.json
438
- > ```
439
- >
440
- > 프로젝트마다 기본값을 얹고 싶으면 **얇은 호출기**를 두면 된다 — 본체를 복사하지 않는다.
441
- > (예: 포털 저장소의 `tools/visual-baseline.py` 는 `--ref/--palette/--base` 만 얹어 이 파일을 부른다.)
442
- >
443
- > **기준선 없이 판정하지 않는다.** 그리고 `selftest` 로 그 기준선 자체를 먼저 증명한다 —
444
- > 참조 세트를 넣으면 전부 통과하고(항등), 흐트러뜨린 것은 떨어져야 한다(뮤테이션).
445
-
446
- > **이 저장소 표본의 밴드 출처.** 정본 7장 실측(2026-08-17, 400px 축소 계수)은 Lime **0.75–1.91%**(평균 1.22%)이다.
447
- > 계약 §7 의 옛 「2–8%」는 **한 장도 만족하지 않았고**, §1 의 「Mist 약 25%」는 웹 화면 규칙이지
448
- > 그림 규칙이 아니다(정본 실측 1.0–2.7%). 그림에는 위 밴드만 적용한다.
449
-
450
- 여러 장을 한 번에 보려면 대지로 붙인다 — 한 장씩 여는 것보다 훨씬 빠르다.
451
-
452
- ```bash
453
- magick montage ch0*.png -tile 2x3 -geometry 900x900+8+8 -background '#DDD' contact.png
454
- ```
455
-
456
- 색 면적은 눈으로 못 잰다. 픽셀을 센다(400px 로 줄여서 세면 충분하다).
457
-
458
- ---
459
-
460
- ## 4. 매니페스트로 넘기기
461
-
462
- 검수를 통과하면 `assets[]` 에 **주소와 출처만** 적는다. 바이트·크기·형식은 MCP 가 채운다.
463
-
464
- ```json
465
- { "id": "chapter-01", "role": "chapter", "provider": "higgsfield",
466
- "alt": "…", "origin": "higgsfield:gpt_image_2:<job-id>", "source": "<결과 URL>" }
467
- ```
468
-
469
- `alt` 에 **수를 주장하지 말 것.** "아홉 개 노드 가운데 네 개" 라고 썼는데 그림은 10개 중 2개였다.
470
- 계약 7.3절이 「정확한 수치를 이미지에 그리지 않는다」이므로, 세는 문장은 alt 에도 두지 않는다.
471
-
472
- 원본 주소는 `IMAGE_HOST_ALLOW`(`mcp/genetics.mjs`)에 있는 호스트여야 받아온다.
473
- 목록 밖 주소면 MCP 가 거절한다 — 그때는 사람이 실물을 확인하고 목록을 고친다.
31
+ 조판 원전은 `gazette-report` 스킬에 있다.