# 구조 골격 · 표면 이식 · 장소 표시면 재작화 — production 편입 설계

2026-07-31. 대상 = 야외 구조물 씨드 계보(`outdoor_structure_*`).
사용자 결정 3건 + Codex 설계 의논 반영본.

## 0. 무엇을 편입하는가

하네스로만 검증한 셋을 메인 파이프라인 계약으로 올린다.

1. **구조 골격 선행** — 참조 없이 선 스케치로 형태를 먼저 확정한다.
2. **표면 이식** — 스케치를 형태 권위로, 검색 사진을 표면 권위로 분리한다.
3. **장소 표시면 재작화** — 장소를 알리는 활자·표시가 들어가는 면을 검색
   참조로 다시 그린다. **그 면에 들어갈 이름도 검색으로 회수한 그 지역의
   이름 관례를 따른다**(§3.1.1 — 2026-07-31 추가). 면을 아무리 잘 그려도
   거기 적힌 이름이 그 나라 사람에게 어색하면 장소가 가짜가 된다.

### 0.1 절대 제약 — 하드코딩 · 하드프롬프팅 금지

사용자가 이번에 다시 강조했다. 금지 범위가 넓다.

- **작품 고유명사** — 인물·장소·상호.
- **업종 이름** — 특정 업종을 가리키는 낱말이 코드·프롬프트에 들어가면
  안 된다. 업종은 데이터에서 나오고, 저작이 런타임에 원본어로 쓴다.
- **개념 자체** — 장소를 알리는 표시물의 통칭도 박지 않는다. 코드가 아는
  것은 *"장소를 알리는 활자나 표시가 들어가는 면"* 까지이고, 그런 면이
  사진에 있는지·읽힐 크기인지·고칠 값어치가 있는지는 **전부 VLM 이 정한다**.
- **대상 그룹 목록** — 상수 배열로 들지 않는다. 실험 하네스의 `GROUPS`
  상수와 `SIGN_*` 계열 상수는 편입 대상이 아니라 제거 대상이다.

### 0.2 사용자 결정 (2026-07-31)

| 결정 | 채택 |
|---|---|
| 편입 구조 | **정식 3스텝 분리** (계약 경계·수명 분리) |
| 어휘 이행 범위 | **활성 경로 전부** — legacy 는 읽기 전용 어댑터로 격리 |
| 표면 참조 확보 | **기존 후보 풀 재판정** — 재검색은 필요성이 실측될 때 |

`repo 전체 grep 0` 은 채택하지 않았다. 발행된 구 팩을 사후 개정하게 되어
"프롬프트 파일 덮어쓰기 금지" 규칙과 충돌한다.

## 1. 왜 지금 이 모양인가 — 실측 근거

### 1.1 참조의 관할 계약이 생성에 도달하지 않는다 (코드 결함)

`multiroll_select.py:755-756`:

```python
def _roll_prompt(lab: str) -> str:
    return roll_prompts[lab] if roll_prompts else prompt
```

`outdoor_structure_seed_step.py:744-750` 은 `build_form_only_clause()` 를
`_gen_prompt` 에만 붙인다. variants 모드(= 현행 production, 팩 v13)에서는
`roll_prompts` 가 주어지므로 **생성 모델은 그 관할절을 받지 않는다.**
관할절은 judge/critique 로만 간다.

즉 지금 검색 사진은 `FORM REFERENCE` 라벨만 달린 채 아무 계약 없이
들어가고 있다. "나쁜 참조가 구조를 그대로 전이시킨다"는 육안 실측
(계단 하부 사선 슬래브)의 **직접 결함이자 강한 원인 근거**다. 단독 원인
으로 확정한 것은 아니다 — 계약을 붙인 뒤 같은 그룹으로 대조해야 한다.

Codex 가 같은 결론을 독립적으로 냈다.

**★카나리 실측 (2026-07-31, `bg_police_station` 2롤 × 2팔).** 같은
프롬프트·같은 사진에 관할절만 각 롤에 더했더니 산출이 달라졌다:

| 항목 | A (오늘) | B (관할절 주입) |
|---|---|---|
| 주 표시면의 기관 표장 | **2/2 없음** | **2/2 있음** |
| 층수 | 3층 ✓ | 3층 ✓ |
| 시점 | 눈높이 1 · 부감 1 | 부감 2 |

★표장 차이는 **관할절 본문에 귀속된다** — 그 절에
`the same signage conventions and lettering style of that region` 이
들어 있다. **즉 "표시면에 글자만 덜렁 남는다"는 결함의 일부는 이 배선
결함이 만든 것이다.** 그 요구가 생성에 닿은 적이 없었다.

★시점은 **관할절 탓이라 말할 수 없다** — A 에서도 부감이 나온다. 첫
판독에서 B 만 부감으로 갔다고 봤으나 나머지 롤을 열어 보고 정정했다.
표본이 2롤 × 1그룹이라 여기까지가 말할 수 있는 전부다. 최종 육안 판정은
사용자에게 있다. 갤러리 = `artifact/20260731_편입전_카나리_4팔/_갤러리/`.

### 1.2 선 스케치에서는 구조가 또렷하다

같은 브리프로 실사를 뽑으면 4층 요구가 3층으로 뭉개지는데, 선만 남기면
3롤 모두 4층·계단 도착점이 한눈에 읽혔다. 재질·조명·생활감이 형태를 덮고
있었다.

### 1.3 형태 권위를 그림으로 주면 판정도 검증 가능해진다

4그룹 확대 실측에서 critique 가 스케치를 자로 삼았다 — "스케치(3칸)와
달리 2칸", "스케치의 일자형과 다르게 지그재그". 형태 권위가 텍스트일 때는
없던 검증 축이다.

### 1.4 표면 이식은 나쁜 참조의 구조 전이를 끊는다

룩 참조로 어제 구조를 망친 바로 그 사진을 그대로 썼는데 구조가 전이되지
않았고, 그 사진의 벽돌·기단·철문·젖은 골목만 왔다.

### 1.5 표시면은 글자만 지정돼 있다

현행 절은 `main signage reads exactly "{text}"` 뿐이다. 표시면은 글자가
아니라 묶음이다 — 표장, 다른 문자 병기, 색 분할, 서체 굵기, 파사드에서의
위치, 조명 방식. 그 묶음을 아무도 주지 않으니 상호만 덜렁 남는다.

★부수 실측: `add no other readable text anywhere` 가 **배경 표시물을 뭉갠
획으로 만든다.** 모델이 형태는 그리되 글자를 못 쓰니 낙서를 채운다.
뭉개짐은 사고가 아니라 지금 계약이 시킨 결과다.

### 1.6 아직 해소되지 않은 것

- **표시면 판정의 회차 변동성** — 같은 이미지인데 승자가 B→C 로 바뀌고
  크기 판정이 medium→small 로 흔들린다. 크기 판정이 흔들리면 "작아서 고칠
  가치 없음" 기준 자체가 불안정하다. **§7 선행 과제, 해소 전 편입 금지.**
- **시점을 아무도 소유하지 않는다** — 부지가 넓은 시설이 드론 부감으로
  나온다. 프롬프트에 카메라 높이 계약이 없다는 것이 남는 설명이나 미검증.
- **검색 후보 파일명이 고정**이라 재검색이 이전 라운드를 파괴한다.
  갤러리 manifest 344건이 `overwritten` 으로 확인됐다. **§7 선행 과제.**

## 2. 스텝 구성

```
outdoor_structure_form_reference   21.915   후보 풀 · form_ref · look_ref(신규)
  → outdoor_structure_seed_plan    21.916   저작 · render_strategy · evidence
  → outdoor_structure_skeleton     21.917   선 스케치 (전략이 요구하는 그룹만)
  → outdoor_structure_seed         21.92    2권위 합성
  → outdoor_structure_place_mark   21.925   표시면 재작화 · effective asset map
```

소비자는 `background_render`(24.72) · `shot_conti_light`(24.73) 이므로
슬롯 여유가 충분하다.

### 2.1 왜 3스텝으로 쪼개는가

내부 전처리는 구현량이 작지만 저작 sidecar 가 하류의 공식 SOT 가 아니고,
스케치·표면 이식·씨드의 비용·재시도·팩 수명이 다른데 CP 하나에 묶인다.
표면 계약 변경이나 씨드 `force` 가 정상 스케치까지 재생성하고, 부분
resume 과 lineage 감사도 복잡해진다.

`outdoor_structure_form_reference` 를 독립 스텝으로 뺀 것과 같은 논거다
— "검색은 네트워크·비결정·비용 수명이 seed 생성과 다르다".

저작을 스텝으로 빼는 것은 부작용이 아니라 **올바른 계약 경계**다. 스케치
스텝이 존재하려면 저작본이 durable CP 여야 하고, 저작은 비결정 LLM 호출
이라 재파생할 수 없기 때문이다.

## 3. 계약표

### 3.1 `outdoor_structure_form_reference` (개정)

| 항목 | 내용 |
|---|---|
| 변경 | 같은 후보 풀에 **표면 기준 pick 계약**을 추가로 적용해 `look_ref` 를 따로 고른다 |
| 산출 추가 | `look_ref_path` · `look_ref_sha256` · `look_ref_asset_id` · `look_pick`(심판별 원본 포함) · **`naming_convention`**(§3.1.1) |
| 기존 산출 | `form_ref_*` 불변 — `direct` 전략 그룹이 계속 쓴다 |
| 후보 경로 | `structure_form_refs/<gid>/<round_key>/cand_NN.png` 로 **라운드 분리** (선행 과제) |
| asset role | `structure_form_reference` / `structure_look_reference` 두 role 분리 |
| config_hash 추가 | `look_pick_pack` · `look_pick_judges` · `naming_lookup_pack` |
| 실패 | 세 산출이 서로를 죽이지 않는다 — 아래 §3.1.0 |

#### 3.1.0 지문 3분리 — 획득과 선택의 수명은 다르다

★**단일 `_group_fingerprint` 에 선택 계약을 얹으면 안 된다.** 표면 pick
계약을 한 줄 고쳤을 뿐인데 그룹 전체가 stale 이 되어 **재검색이 돌고, 고정
파일명 때문에 후보 풀이 파괴된다.** "재검색 없이 재판정"이라는 결정과
라운드 보존 계약을 동시에 깨는 경로다. (Codex 지적, 수용)

지문을 셋으로 나눈다:

| 지문 | 지배하는 것 | 바뀌면 |
|---|---|---|
| `candidate_pool_fp` | 구조 서술 · 세계 사실 · 원문 sha · 검색 계약 · 다운로드 정책 | 새 라운드로 재검색 |
| `form_pick_fp` | 형태 pick 계약 · 심판 구성 | **후보 재판정만** (frozen round bytes 읽기 전용) |
| `look_pick_fp` | 표면 pick 계약 · 심판 구성 | **후보 재판정만** |
| `naming_fp` | 이름 관례 조회 계약 | 관례 조회만 |

- 선택 전용 재실행은 **frozen round 디렉토리를 읽기만 한다.** 쓰지 않는다.
- 세 산출(`form_ref` · `look_ref` · `naming_convention`)의 status · UUID ·
  lineage · 실패가 **전부 독립**이다. 표면 pick 실패가 형태 산출을 훼손하지
  않는다.
- 표면 pick 실패 = 그 그룹 `look_ref` 결손. `skeleton_then_look` 전략
  그룹이면 seed 에서 fail-closed.
- **이름 관례 실패는 그룹을 죽이지 않는다** (§3.1.1).
- **라운드별 경로 도입이 어떤 재판정보다 먼저다.** manifest·cleanup 계약에
  전제로 넣는다.

**두 선택은 독립 영속한다** — 판정 기록·UUID·lineage 를 각각 남긴다.
하나가 다른 하나의 별칭이 되면 두-권위 설계가 반쪽이 된다.

표면 pick 계약이 보는 것: 벽 재료와 쌓기 · 색과 풍화·얼룩 · 트림·난간·문·
계량기·배관의 마감 · 노면 마감 · 연식과 관리 상태. **형태 유사성은 판정
축이 아니다.**

★**조명은 판정의 품질 조건일 뿐 권위가 아니다.** "표면을 판독할 만큼
밝은가"는 후보를 고를 때 볼 수 있지만, 그 사진의 시간대·날씨·그림자가
씨드로 전이되면 안 된다(§3.4 관할 계약).

#### 3.1.1 사전조사 (신규 — 사용자 지시 2026-07-31)

> "작명 관련해서 검색해야 한다고 분명 말했는데 … 경찰서 이름 같은 경우
> 99퍼센트 지역명이라고. 그리고 **시골 마을 경찰서가 저렇게 클 수가 없어
> 예산 때문에.** 즉 **조사를 안 한 거지 — 작명 + 규모나 사전조사**가."

**하나의 결손이다.** 이름도 규모도 시나리오가 침묵하는 항목이고, 침묵한
자리를 저작이 **자기 통념으로 메우고 있다.** 조사 단계가 파이프라인에
없다.

##### 실측 — `bg_police_station` (2026-07-31)

| 층 | 무엇을 말하나 |
|---|---|
| 시나리오 | `경찰서 주차장` · `경찰서 형사과` — **고유명 없음 · 규모 언급 0 · 입지 성격 언급 0** |
| 저작 evidence | 씬 헤딩 2건 + 모니터 화면 서술 1건 — **규모 근거 0건** |
| 저작 산출 | `30 by 18 metre` **3층** · `in an inhabited urban neighborhood` · 표시 문안 `새봄경찰서` |

`새봄` 은 원문에 **0회** 등장한다. `urban` 도 원문 근거가 없다. 실내
증거는 방 **1개**이고 브리프가 그것을 적고 있다 —
`footprint and massing MUST plausibly hold all 1 of them`.

★**세 구멍이 겹쳐 있다.**

1. **입지 성격을 저작이 지어낸다.** `location_line_en` 이 `urban` 을
   확정하고, 유형이 정해지면 규모가 따라온다. **이 구멍을 먼저 막지
   않으면 사전조사가 틀린 유형을 조사해서 도장을 찍는다.**
2. **규모의 유도 출처가 실내 증거뿐이다.** `author_sys` 가 "규모를
   비워 두지 말라"고 강제하는데(`:58`) 출처는 INTERIOR NOTES 와
   시나리오뿐이다(`:80-89`). 근거가 바닥나면 통념이 메운다.
3. **이름 관례가 문항 범위 밖이다.** 결손 문항 저작이 *"이 구조물의
   외관을 그린다"* 를 전제해 형태만 본다. 이름은 형태가 아니다.

★이것은 팩 v11 결함의 **거울상**이다. 그때는 침묵을 **부재로 확정**했고
(`no canopy`), 지금은 침묵을 **지어내서 확정**한다. 같은 빈자리다.

##### 설계 — 사전조사를 1급 입력으로

`typology_prior` 모듈이 정확히 이 자리를 위해 만들어졌으나 **production
배선이 0** 이다(`backend/` 에 없고 scratchpad 하네스로만 존재). 편입한다.

- **권위 순서 = 시나리오 > place spec > 사전조사.** 침묵한 항목에서만
  쓰고 충돌하면 앞의 것이 이긴다.
- **문항·질의는 유형 일반으로 환원한다.** 작품 고유명사·인물·사건·배치를
  넣지 않는다. 질의 언어는 원본어.
- **이중 검색 후 일치만 채택**하고, 한쪽만 찾은 것은 `[single source]`
  로 표시해 *경향*으로만 쓴다(확정·개수·부정으로 쓰지 않는다).
- 미발견·불일치는 폐기 — 오늘 상태로 돌아갈 뿐이라 손해가 없다.

##### 문항 범위를 넓힌다 (실측이 요구한 3축)

기존은 형태 결손만 물었다. 아래를 더한다. **어떤 답이 맞는지는 코드가
알지 못한다** — 코드는 묻기만 하고 답은 전부 검색에서 온다.

| 축 | 무엇을 묻나 |
|---|---|
| `siting` | 이 종류의 시설이 **어떤 성격의 정주지**에 놓이는가. 그 성격이 규모·구성을 어떻게 가르는가 |
| `scale` | 그 성격의 정주지에서 이 종류 시설이 실제로 갖는 **연면적·층수·부지** |
| `composition` | 그 격의 시설이 통상 갖추는 구성 (그리고 갖추지 않는 것) |
| `naming` | 이 종류의 장소가 그 지역에서 **어떻게 이름 지어지는가** (§3.1.1a) |

★**`siting` 이 먼저다.** 나머지 셋이 그 답에 매달린다. 그래서 저작이
입지를 확정하기 **전에** 조사가 돌아야 한다.

##### 저작 계약 개정 (새 팩)

- `location_line_en` 을 **evidence-bound** 로 만든다. 입지 성격을
  단정하려면 원문 인용이나 사전조사 사실이 있어야 하고, 둘 다 없으면
  **입지 성격을 쓰지 않는다**(비워 두는 것이 지어내는 것보다 낫다).
- 규모의 유도 출처에 **사전조사를 세 번째로** 넣는다. "비워 두지 말라"는
  유지하되, 근거가 셋 다 침묵하면 **그 사실을 적게** 한다 — 조용히
  통념으로 메우지 않는다.
- 규모·이름마다 **무엇에 근거했는지**를 산출에 남긴다
  (`from_source_text` / `from_prior` / `no_basis`).

#### 3.1.1a 이름 관례 회수

> "간판이나 이름 명소 등이 들어가는 곳에서는 LLM 이 검색을 통해서 기초
> 자료 수집 시에 꼭 기존과 비슷한 이름을 사용해야 해."

**무엇이 문제인가.** 저작이 장소 이름을 지을 때 관례를 모른 채 짓는다.
실측에서 나온 이름들이 실제로 그런 종류의 장소가 그 지역에서 불리는
방식과 어긋났다 — 사용자 육안 판정. 표시면을 아무리 잘 그려도 거기 적힌
이름 자체가 그 나라 사람에게 어색하면 장소가 가짜가 된다.

**어디서 메우는가.** §3.1.1 사전조사의 `naming` 축이다. 검색은 이미 이
스텝에서 원본어로 돌고 있고 이름을 저작하는 `seed_plan` 보다 앞선다.
묻는 것은 그 종류의 장소가 그 지역에서 **실제로 어떻게 이름 지어지는가**.

산출:

```
naming_convention = {
  applicable: bool,                  # 그 종류의 장소가 고유 이름을 갖는가
  pattern_native: str,               # 이름이 어떤 성분으로 조립되는가 (원본어)
  observed_examples_native: [str],   # 검색에서 실제로 관측된 이름 (근거 전용)
  source_urls: [str],
  reason_ko: str,
}
```

**★ `observed_examples_native` 는 근거일 뿐 베낄 대상이 아니다.** 실재하는
장소의 이름을 작품에 그대로 쓰면 안 된다. 관례에서 가져오는 것은 **조립
방식**이고, 그 자리에 들어갈 성분은 작품 자신의 것이다.

**하드코딩 금지가 여기서 특히 엄하다.** 코드도 프롬프트도 어떤 관례가
있는지 말하지 않는다. 특정 나라의 특정 업종이 무엇을 이름에 넣는지를 한
줄이라도 적는 순간 그 규칙은 다른 작품·다른 나라에서 조용히 틀린다. 코드가
아는 것은 *"이 종류의 장소는 이 지역에서 어떻게 이름 지어지는가를 찾아
와라"* 까지이고, 답은 전부 검색과 판정에서 온다.

`applicable=false`(고유 이름을 갖지 않는 종류)면 저작은 오늘과 같이 동작
한다. 검색·판정 실패도 마찬가지 — **이름 관례 결손이 그룹을 죽이지
않는다.** 관례가 없으면 이름이 덜 그럴듯해질 뿐이고, 그것은 오늘의 상태다.

### 3.2 `outdoor_structure_seed_plan` (신규)

| 항목 | 내용 |
|---|---|
| 입력 | `outdoor_lane_plan` · `outdoor_place_spec` · `scene_save` · `background_classify` · `entity_merge` · `scene_director` · `shot_ref_classify` · `visual_world_rules` · **`outdoor_structure_form_reference`(이름 관례)** |
| 하는 일 | 저작을 이관하고 **전략 판정 · 이름 관례 준수 · 구조 검사축을 추가**. 계약 2개로 나눈다 |
| 산출 | `groups[gid] = {status, author, author_fp, strategy, strategy_fp, conformance_brief_en, roll_prompts}` |
| 대상 | seed 대상과 **exact parity** (`collect_lane2_groups(..., all_groups=<같은 플래그>)`) |
| 실패 | 각 계약의 검증 재시도 소진 = 그룹 실패 격리 |
| config_hash | resolved policy · 저작 팩 · 전략 팩 · 저작 모델(alias+물리) · 변형 수 |

#### 3.2.0 계약 2분리 — 그리고 구 CP 승계는 성립하지 않는다

원안은 "구 seed CP 의 저작본을 `author_fp` 재계산이 일치하면 승계한다"
였다. **성립하지 않는다.** (Codex BLOCKING-1, 수용)

- `author_fp` 는 CP entry 가 아니라 sidecar `seed_variant_records.json`
  에만 있다. CP 만 보고는 재계산 대조를 할 수 없다.
- 지문에 저작 schema 전문이 들어간다. 그런데 이번에 **어휘 이행(§4)으로
  저작 schema 자체가 바뀐다** — `signage_*` → 중립 명칭. 그러므로 구 v13
  지문과 원칙적으로 일치할 수 없다.

Codex 는 base 저작과 전략을 분리해 base 만 frozen v13 로 승계하는 안을
냈으나, **그 경로는 `signage_*` 를 활성 경로에 남긴다** — 사용자가 결정한
"활성 경로 전부 이행"과 충돌한다.

**그래서 승계를 버린다.** `seed_plan` 은 새 중립 schema 로 다시 저작한다.
비싼 것은 이미지이지 저작이 아니다 — 그룹당 텍스트 호출 몇 번이다. 구 CP
의 저작본은 **legacy 어댑터로 읽기만** 한다(감사·대조용, 활성 경로 분기
없음).

다만 Codex 의 **계약 분리 논거 자체는 채택한다** — 앞으로 전략 계약만
고쳤을 때 브리프 전체를 다시 저작하면 안 되기 때문이다.

| 계약 | 산출 | 지문 |
|---|---|---|
| **A. 구조 브리프 저작** | 변형 3 + `conformance_brief_en` + `place_mark_surface_*` + `structure_checks[]` | `author_fp` |
| **B. 렌더 전략 판정** | `render_strategy` + evidence | `strategy_fp` (A 의 산출을 입력으로 받는다) |

각각 sidecar 캐시 슬롯을 따로 갖는다. sidecar 결손·불일치는 **재호출**
이지 승계가 아니다.

#### 전략 판정 — tri-state · 근거 결속

```
strategy = {
  raw: skeleton_then_look | direct | uncertain,   # 판정이 말한 것
  effective: skeleton_then_look | direct,         # 코드가 적용하는 것
  evidence: [{ scene_index: int, quote: str }],   # 공급 씬 원문 verbatim
  reason_ko: str,
}
```

★**`raw` 와 `effective` 를 둘 다 남긴다.** 승격만 기록하면 감사에서
불확실성이 사라져, 나중에 "이 그룹은 확신해서 스케치를 탄 것"처럼 보인다
(Codex NARROW, 수용).

- **`uncertain` 은 코드가 `skeleton_then_look` 로 보수 승격한다.**
- **`direct` 는 비어 있지 않은 원문 provenance + 명시적 확신이 있을 때만**
  허용한다. validator 가 인용의 `scene_index` 가 공급 씬 집합 안에 있고
  인용문이 whitespace-normalized 로 원문에 실재하는지 대조한다
  (`room_inventory` 와 같은 방식).
- **호출 실패·검증 실패는 재시도 소진 후 fail-closed.** `direct` 로
  내려가지 않는다.
- 모든 seed 대상에 entry 가 있어야 한다 (exact parity).

##### 왜 판정을 다시 얹는가 — 과거 실패와 무엇이 다른가

`outdoor_structure_form_reference` 는 v1(프록시)·v2(LLM scope 판정)로 두 번
실패하고 v3 에서 판정을 없앴다. 그 실패의 본질은 **판정이 검색 모집단을
줄였다**는 것이다 — 판정이 틀리면 그 배경은 검색을 아예 못 타고, 사용자가
지적한 "배경이 이상해"를 아무도 모르게 재생산한다.

여기서는 다르다. **모집단을 줄이지 않고 렌더 전략만 고른다.** 모든 그룹이
저작을 타고, 모든 그룹이 씨드를 뽑는다. 판정은 "스케치를 앞에 세울지"만
정한다.

다만 `direct` 오판이 무해하지는 않다 — 스케치 없이 사진을 붙이면 §1.1 의
구조 전이 경로로 되돌아간다. 그래서 tri-state 이고 `uncertain` 이 스케치로
승격된다.

`built_structure` boolean 단독 추가는 기각한다(복잡도를 표현하지 못한다).
저작 산출의 숫자·개구부에서 코드가 결정론 파생하는 방식도 기각한다(의미를
과도하게 축약한다).

#### 장소 이름 저작 — 관례 준수 (신규)

`place_mark_surface_text`(표시면에 들어갈 문안)를 지을 때 §3.1.1 이 회수한
`naming_convention` 을 따른다.

권위 순서:

1. **시나리오 원문이 그 장소의 이름을 말하면 그것이 이긴다.** 지어내지
   않는다. (기존 원문 우선 규칙)
2. 원문이 침묵하면 **관례의 조립 방식**으로 짓는다 — 성분은 작품의 것
   (작품 자신의 지명·소유자·특징 등, 근거는 씬 원문)에서 가져온다.
3. 관례가 `applicable=false` 이거나 결손이면 오늘과 같이 짓는다.

산출에 준수 기록을 남긴다:

```
place_mark_surface_text: str
place_mark_naming_basis ∈ { from_source_text, from_convention, no_convention }
place_mark_naming_evidence: [{ scene_index, quote }]   # from_source_text 일 때
place_mark_naming_reason_ko: str
```

validator 가 잠그는 것:

- `from_source_text` 면 인용이 실재해야 한다(다른 evidence 필드와 같은 대조).
- `from_convention` 이면 `naming_convention.applicable` 이 참이어야 한다.
- **저작된 문안이 `observed_examples_native` 의 항목과 같으면 위반이다** —
  실재 장소의 이름을 베낀 것이다. 재시도에 그 위반을 교정 블록으로 병기한다.

★이 validator 는 **문자열 동일성만** 본다. 글자 패턴으로 의미를 판정하지
않는다(관례를 만족하는지, 이름이 그럴듯한지는 코드가 판단하지 않는다).

#### 구조 검사축 저작 — `structure_checks[]` (신규)

스케치 게이트(§3.3)가 쓸 축을 **같은 SOT 에서 저작해 내려보낸다.** 코드가
검사 항목을 지어내면 그 순간 유형별 규칙이 코드에 박힌다.

```
structure_checks: [{
  axis ∈ { mass, storey_count, access, openings, ground_connection, view_coverage },
  requirement_en: str,          # 이 구조물에서 무엇이 참이어야 하는가
  evidence: [{ scene_index, quote }],
}]
```

축 이름은 **구조의 보편 성질**이지 유형 이름이 아니다. 무엇이 참이어야
하는지는 그룹마다 저작이 근거와 함께 쓴다.

### 3.3 `outdoor_structure_skeleton` (신규)

| 항목 | 내용 |
|---|---|
| 입력 | `outdoor_structure_seed_plan` 만 |
| 대상 | `render_strategy == skeleton_then_look` 인 그룹. 나머지는 명시적 `not_applicable` entry |
| 참조 | **없음.** 웹 사진을 절대 붙이지 않는다 |
| 프롬프트 | 스케치 변환절 + `conformance_brief_en` **원문 그대로** |
| 산출 | `groups[gid] = {status, skeleton_png_path, skeleton_sha256, skeleton_asset_id, skeleton_prompt, gate_rounds}` |
| asset role | `structure_skeleton` |
| 판정 | **구조 전용 conformance gate + bounded 재생성** — 아래 |
| 실패 | 그룹 단위 격리. 대상 그룹의 스케치 결손은 seed 에서 fail-closed |
| config_hash | resolved policy · 스케치 팩 · 게이트 팩 · 생성 모델 · 게이트 심판 모델 · 최대 회차 |

#### 구조 전용 게이트 — 1롤 무판정을 버린다

원안은 판정 없이 1롤이었다. **나쁜 한 장이 하류에서 절대 권위가 된다.**
(Codex HIGH-5, 수용)

미감 3롤 경쟁은 필요 없다 — 스케치에 미감은 없다. 대신:

```
round N 생성 → 전체 계약 재판정 → PASS 면 즉시 채택·정지
                              → FAIL 이면 그 회차를 불변 보존하고
                                 full base prompt + 그 회차 위반으로 round N+1
              (상한 소진) → eligible(PASS) 없음 = fail-closed
```

**★카나리 실측이 이 형태를 강제했다.** 개정 변환절로 다시 그리자 한 그룹은
**더 나빠졌다** — 1차는 순수 선화·눈높이·계단 1개가 정확히 2층 도착이었는데
2차는 색·부감·계단 2개였다. 즉 "위반 목록만 보고 통과할 때까지 재생성"은
**다른 축에서 새로 깨진 회차를 통과로 확정**한다.

세 가지를 못박는다 (Codex 카나리 피드백, 수용):

1. **매 회차 전체 계약을 처음부터 다시 판정한다.** 이전 위반 목록은 다음
   *생성*의 교정 힌트일 뿐 다음 *판정*의 범위를 줄이지 않는다. 입력은
   ①변환 hard rule 전부(무문자·무색·무재질·무인물) ②`structure_checks[]`
   전 항목 ③시점 계약 전체. 위 multifamily 2차는 이 규칙에서 **FAIL** 이다.
2. **후보 비교는 PASS 한 후보끼리만.** `eligible = 모든 hard invariant
   PASS`. eligible 0 = **fail-closed**("가장 덜 나쁜 후보" 채택 금지 —
   그러면 fail-closed 가 상대평가로 바뀐다). eligible 1 = 즉시 채택.
   2 이상일 때만 구조 가독성·시점 커버리지 같은 soft 축으로 비교하고,
   **동점은 가장 이른 PASS 회차**로 고정한다.
3. **회차를 지우지 않는다.** `round_01.png` · `round_02.png` … 불변 파일 +
   회차마다 프롬프트 SHA · 산출 SHA · 판정 원문 · 축별 정규화 판정 · 위반
   목록을 durable persist. 이미지 생성 뒤 판정 전에 죽으면 **이미지를 다시
   만들지 않고 판정만 재개**한다. `winner` 는 선정 회차와 후보 SHA 를 적는다.

게이트 팩 · 물리 모델 · 변환 계약 · 최대 회차 · winner 정책을 **스텝
`config_hash` 와 그룹 지문 양쪽**에 넣는다.

★`multiroll_select._critique_and_fix` 를 그대로 재사용하지 않는다 —
그쪽은 원본 대 수정 2후보 계약이고 동점이 수정본 우선이며 `_clear_outputs`
수명이 불변 회차와 맞지 않는다. **스케치 전용 bounded-attempt helper** 를
따로 둔다.

게이트가 보는 축은 `seed_plan` 이 저작한 `structure_checks[]` 와 변환
hard rule · 시점 계약이다 — 매스 · 층수 · 접근 동선 · 개구부 · 지면 접합 ·
구조 가시성. **재질·색·미감·분위기는 soft 비교 축이 아니라 hard 금지
항목이다.** 코드가 검사 항목을 지어내지 않고 같은 SOT 에서 파생하므로,
유형별 규칙이 코드에 박히지 않는다.

브리프를 **손대지 않고 앞에 변환절만 붙인다.** 브리프를 고치면 무엇이
스케치 덕인지 구분할 수 없다.

#### 관할 분리 — 변환절과 브리프가 충돌할 때

★**카나리 실측: 변환절의 "글자 금지"가 브리프에 진다.** 3장 중 2장에
상호가 그려졌고 2장에 색이 들어갔다. 브리프 안에 표시 문안 절이 있어
서로 요구가 어긋나는데 해소 규칙이 없었기 때문이다.

"변환절이 브리프보다 항상 우선"으로 뭉뚱그리면 **브리프의 구조 사실까지
지워진다**(Codex 지적, 수용). 관할로 나눈다:

| 권위 | 소유 |
|---|---|
| 변환 계약 | 표현 매체·추상화 수준·**금지 내용**(색·질감·활자 자체) |
| 브리프 · `structure_checks[]` | 구조·위상·개구부·동선, 그리고 **표시가 놓일 면의 존재와 형상** |

즉 **면은 보존하되 글자는 비운다** — 브리프가 문안을 요구해도 그 면을
빈 윤곽으로 그리고 문자를 넣지 않는다. 문안은 뒤 단계에서 복원된다.
실측: 이 문안을 넣자 두 그룹의 위반이 해소됐다.

변환절이 지우는 것: 색·회색조·음영·해칭·질감·재질 렌더·풍화·그림자·하늘·
빛·분위기·인물·차량·식생·잡동사니·모든 활자.
변환절이 남기는 것: 매스 윤곽과 접합 · **모든 층 높이의 수평선**(반지하·
기단층·필로티도 각각 한 층) · 개구부의 위치·크기·개수 · 계단/램프의 전
주행·상승 방향·계단참·**도착 개구부** · 지붕선·파라펫·옥상 설치물 · 지면
접합선. 이웃 건물은 윤곽만.

#### 시점 — 무조건 눈높이는 아직 계약이 아니다

부지가 넓은 시설이 부감으로 올라가는 실측(§8) 때문에 눈높이 강제를
검토했으나, **production 계약으로 박기에는 이르다**(Codex HIGH-6, 수용).
넓은 부지·지붕·연결 위상을 가려 스케치의 정보량을 줄이고, 원문이 높은
데서 내려다보는 관찰을 요구할 때 충돌한다.

- 기본 문안은 **구조 가시성을 우선**한다 — *"구조 사실을 전부 보이려면
  필요한 경우를 제외하고는 지상에서 접근 가능한 시점"*.
- 무조건 눈높이는 채택하지 않는다.
- ★**시점은 프롬프트만이 아니라 게이트 축이다**(Codex 수용). 실측에서
  이 문안이 1/3 에서 무시됐으므로, 매 회차 판정에서 시점을 검사한다.
- 게이트를 넣고도 계속 흔들리면 evidence-bound `survey_view` 저작을
  **후속이 아니라 구현 전 선행 계약으로 승격**한다.

### 3.4 `outdoor_structure_seed` (개정)

| 항목 | 내용 |
|---|---|
| 제거 | 저작(`_author_seed_variants`)을 `seed_plan` 으로 이관 |
| 입력 추가 | `outdoor_structure_seed_plan` · `outdoor_structure_skeleton` |
| 참조 | 전략에 따라 고정 |
| 관할절 | **모든 roll prompt · judge · critique 에 주입** (§1.1 봉합) |
| config_hash | plan/skeleton 계약 sha + 관할절 팩 + 전용 critique 플래그 |

#### 참조 구성

| 전략 | labeled_refs |
|---|---|
| `skeleton_then_look` | `[("STRUCTURE SKELETON", skeleton), ("SURFACE LOOK REFERENCE", look_ref)]` |
| `direct` | `[("FORM REFERENCE", form_ref)]` — 오늘과 동일 |

#### 관할 계약 — `skeleton_then_look`

- **STRUCTURE SKELETON = 형상·매스·개구부·수직 동선·지붕·지면 접합·
  시점의 유일 권위.** 층을 더하거나 빼지 말고, 개구부를 옮기거나 늘리지
  말고, 계단을 다시 놓지 말 것.
- **SURFACE LOOK REFERENCE = 재료·색·마감·풍화·관리 상태·노면 마감만.**
  형태 권위 없음 — 충돌하면 스케치가 이긴다.

★**룩 참조에서 전이가 금지되는 것을 명시한다** — 카메라 위치와 화각 ·
조명 · 시간대 · 날씨 · 그림자 · 하늘 · 그 사진에 있던 사람·차량·물건.
(Codex HIGH-7, 수용. 원안의 "빛의 질"을 뺐다 — 넣으면 무작위 사진의
정오 그림자가 씨드에 고착된다.)

#### 관할 계약 — `direct`

`direct` 경로의 형태 전용 관할절도 **똑같이 명시하고 똑같이 주입한다.**
§1.1 결함이 여기서 재발할 수 있다(Codex HIGH-8, 수용). 오늘 이 경로에는
관할절이 생성에 도달하지 않고 있으므로, `direct` 는 "오늘과 동일"이
아니라 **"오늘 + 관할절이 실제로 도달"** 이다.

#### 주입 지점 — 두 경로 공통

우선순위 절은 **`roll_prompts` 의 각 항목에 조립 시점에 들어간다.**
judge·critique 브리프에도 같은 우선순위가 들어간다. base prompt 에만
붙이면 §1.1 결함을 그대로 반복한다.

#### critique

Stage 2 의 critique 활성 여부를 전역 `still_recipe_critique_enabled` 에
맡기지 않는다. `seed_critique_mode`(§5.1) 가 소유한다.

**계약 팩 버전 · 계약 본문 해시 · 물리 모델을 `config_hash` 와 per-group
`extra_fingerprint` 양쪽에 넣는다.** 한쪽만 넣으면 sidecar 재사용이 바뀐
계약을 뚫는다(Codex HIGH-8).

#### lineage

`ImageAsset.input_image_ids` 에 **스케치와 표면 참조 두 UUID 를 분리
기록**한다. 실제 첨부된 참조와 정확히 일치해야 한다.

### 3.5 `outdoor_structure_place_mark` (신규)

| 항목 | 내용 |
|---|---|
| 입력 | `outdoor_structure_seed` · `outdoor_structure_seed_plan`(목표 문안) · `visual_world_rules` |
| 대상 | 목표 문안이 비어 있지 않은 그룹 **중** 필요성 판정이 통과한 그룹 |
| 산출 | `groups[gid] = {status, source_seed_asset_id, corrected_png_path, corrected_asset_id, assess, pick, verdict}` + `data.effective_seed` (**seed 대상 전 그룹 exact parity**) |
| **base seed 미덮어쓰기** | 파생 자산을 따로 만들고 map 으로 소비하게 한다 |
| 실패 | **typed no-op** — seed 실패로 번지지 않되 조용히 내려가지도 않는다 |
| config_hash | resolved policy · 필요성 판정 팩 · 검색·선택 팩 · i2i 팩 · 심판 구성 |

#### 3.5.0 typed no-op — "감사 가능"과 "결손 시 fallback"은 양립하지 않는다

원안은 전 그룹 map 을 약속하면서 동시에 **map 결손 시 base seed fallback**
을 허용했다. 모순이다 — 그러면 producer 버그·부분 실행·stale CP 와 정상
no-op 를 구분할 수 없다(Codex BLOCKING-3, 수용).

```
effective_seed[gid] = {
  asset_id: <uuid>,          # 하류가 실제로 쓸 자산 (no-op 이면 base seed UUID)
  basis ∈ {
    applied,                  # 수정본 채택
    unchanged_not_required,   # 고칠 면이 없거나 고칠 값어치가 없다
    unchanged_uncertain,      # 필요성 판정이 확신하지 못했다
    unchanged_disagreement,   # 심판이 갈렸다 / 원본이 이겼다
    unchanged_failed,         # 검색·생성·판정이 실패했다
  },
  reason_ko: str,
}
```

- **seed 대상 전 그룹에 entry 가 있어야 한다** (exact parity).
- no-op 도 **base seed UUID 를 명시적으로 적는다.**
- 소비자는 **map 결손 · 모르는 `basis` · 존재하지 않는 UUID 를
  fail-closed** 한다. producer 가 기록한 typed no-op 일 때만 base 를 쓴다.
- 스텝 자체가 꺼져 CP 가 없는 경우는 다르다 — 그때는 §5.1 resolved policy
  가 `place_mark_mode=off` 임을 보증하므로 소비자가 base 를 쓴다.

이것이 place_mark 실패를 seed 실패로 전파하지 않으면서 조용한 하강도
막는 경계다.

#### 4단

1. **필요성 판정 (VLM, 선정 씨드 사진 위에서)**
   코드는 표시물의 존재를 전제하지 않는다. 찾는 것은 *"이 장소를 알리는
   활자나 표시가 들어가는 면"* 이고, 사진에 그런 면이 있는지·화면에서
   얼마나 큰지·읽히는지·고칠 값어치가 있는지를 전부 여기서 정한다.

   ```
   place_mark_fix_needed ∈ { required, not_required, uncertain }
   ```

   `uncertain` 과 **심판 불일치는 원본 유지**(건드리지 않는다).

2. **원본어 검색 지시문 저작** — 대상이 건물이 아니라 표시면이므로
   구조물용 `brief_system` 과 별개 계약이다. 업종 이름은 코드가 아니라
   저작이 데이터에서 읽어 런타임에 원본어로 쓴다.

3. **검색 → 후보 다운로드 → VLM 이중 선택.** 판정 기준은 *면이 어떻게
   만들어졌는가가 읽히는가*. **후보에 적힌 문구는 판정과 무관하다** —
   다른 상호가 적혀 있다는 것은 탈락 사유가 아니다.

4. **i2i 재작화 → 원본 포함 비교 판정.**
   - 원본은 반드시 후보에 포함한다. 원본이 이기면 수정을 버린다.
   - **구조 보존 hard gate 를 먼저 통과해야 한다** — 표시면 밖이 바뀌었
     거나 없던 면을 새로 만들었거나 키웠으면 그 후보는 그 자리에서 탈락.
   - 게이트 통과 후 **두 심판이 개선에 동의할 때만** 수정본 채택.
     **동점·불일치 = 원본.**

#### 다중 표시면 일관성 (3겹)

① 모든 표시면이 같은 문자·색·서체·표장을 쓰고, 면의 비례에 따라 배치만
다르다 ② 한 면만 고치고 다른 면을 남기면 실패다 ③ 없던 표시면을 새로
만들거나 키우지 않는다. 최종 판정·재판정 프롬프트에도 같은 조항.

#### 소비

`background_render` · `shot_conti_light` 이 `effective_seed` map 을 통해
명시적으로 소비한다. **결손·미지 `basis`·존재하지 않는 UUID 는
fail-closed**(§3.5.0). 스텝이 꺼져 CP 자체가 없을 때만 base seed.

## 4. 어휘 이행

### 4.1 활성 경로

| 구 | 신 |
|---|---|
| `signage_required` | `place_mark_surface_applicable` |
| `signage_reason_ko` | `place_mark_surface_reason_ko` |
| `signage_text` | `place_mark_surface_text` |
| `signage_clause` | `place_mark_surface_clause` |
| — (신규) | `place_mark_naming_basis` · `place_mark_naming_evidence` · `place_mark_naming_reason_ko` |

**필드의 내용은 살린다.** 목표 문안(`..._text`)은 재작화 스텝이 "그 면이
무슨 글자를 달아야 하는가"의 입력으로 계속 쓴다. 바뀌는 것은 명칭과,
**"고칠 것인가"를 정하는 게이트가 저작에서 VLM 으로 옮겨간다**는 것이다.
저작 시점 판정은 이미지가 없어 면의 존재·가독 크기를 알 수 없다.

### 4.2 legacy

발행된 구 팩(`seed_prompt_variants/9~13` 등)은 **개정하지 않는다**. 구 CP
를 읽는 legacy 어댑터에만 구 필드명을 남기고 활성 경로는 분기하지 않는다.

### 4.3 금지 어휘 검사

활성 모듈·팩을 대상으로 금지 어휘 inventory test 를 둔다. legacy 어댑터
경로만 명시 allowlist. 금지 목록은 작품 고유명사·업종 이름·표시물 통칭.

## 5. 기존 계약의 보존

- 레거시 경로(`structure_seed_recipe=legacy`)는 동작이 바뀌지 않는다.
- **구 CP 저작본 승계는 하지 않는다** (§3.2.0). 어휘 이행으로 저작 schema
  가 바뀌므로 지문이 원칙적으로 달라진다. 구 CP 는 legacy 어댑터로 읽기만
  한다(감사·대조). 재저작 비용은 그룹당 텍스트 호출 몇 번이다.
- 구 `signage_*` → 중립 필드 어댑터는 **읽기 방향만** 존재한다. 활성 경로가
  이 어댑터로 분기하지 않는다.

### 5.1 조합 유효성 — 중앙 resolved policy SOT

플래그 4개를 그대로 두면 16가지 조합이 생기고, `config_hash` 나 manifest
applicability 하나가 유효성까지 떠맡게 된다. **hash 는 무효화·감사 장치이지
validity gate 가 아니다**(Codex BLOCKING-4, 수용).

중앙 policy 를 SOT 로 둔다:

```
structure_seed_recipe ∈ { legacy, skeleton_look_v1 }
place_mark_mode       ∈ { off, v1 }
seed_critique_mode    ∈ { off, structure_preserving_v1 }
```

- **실행·claim 이전에 중앙 validator 가 불가능한 조합을 거부한다**
  (fail-fast). 예: 변형 저작이 꺼졌는데 `skeleton_look_v1` / 선행 산출이
  결손인데 `place_mark_mode=v1` / 신규 스텝 일부만 활성.
- manifest applicability 는 **이 resolved policy 에서 파생**한다.
- 각 스텝 `config_hash` 는 resolved policy 를 **기록**만 한다.
- boolean 플래그를 유지해야 한다면 16 조합 truth table 을 잠그고
  producer·consumer 양쪽에서 방어한다.

## 6. 검증

### 6.1 결정론 (유닛)

- **관할절이 실제 생성 프롬프트에 있는가** — `gen_fn` 이 받은 **전 롤**의
  프롬프트를 포착해 검사한다. base prompt 만 보는 테스트는 §1.1 결함을
  다시 놓친다.
- judge/critique 브리프에도 같은 우선순위가 있는가.
- 계약 변경이 `roll_prompts` 지문을 흔드는가.
- **`direct` 경로에도 형태 전용 관할절이 전 롤에 도달하는가** — 같은 결함이
  이쪽에서 재발한다.
- 전략 tri-state — `uncertain` 승격 / `direct` 의 provenance 강제 /
  실패 시 fail-closed / seed 대상 exact parity / **`raw`·`effective` 둘 다
  영속**.
- **지문 3분리** — 표면 pick 계약만 바꿨을 때 `candidate_pool_fp` 가
  불변이고 재검색이 돌지 않는가. 선택 전용 재실행이 라운드 디렉토리에
  쓰지 않는가. 세 산출의 실패가 서로 독립인가.
- **룩 참조 전이 금지 목록** — 카메라·조명·시간·날씨·그림자·일시 객체가
  관할절에 금지로 들어가는가.
- 스케치 게이트 — 축이 `structure_checks[]` 에서만 파생되는가 / 재생성
  상한 / 소진 시 fail-closed / `gate_rounds` 기록.
- **조합 유효성** — 중앙 validator 가 불가능한 조합을 실행 전에 거부하는가.
  manifest applicability 가 resolved policy 에서 파생하는가.
- 이름 관례 — 회수본이 저작 입력에 실제로 실리는가 / `from_source_text` 의
  인용 대조 / `from_convention` 이 `applicable=true` 를 요구하는가 /
  **저작 문안이 관측 예시와 같으면 위반으로 잡히는가** / 관례 결손이
  그룹을 죽이지 않는가.
- 참조 구성이 전략과 일치하는가, lineage 두 UUID 가 실제 첨부와 일치하는가.
- `place_mark` — 원본 포함 / 동점·불일치 = 원본 / **typed no-op 전 그룹
  parity** / 소비자가 map 결손·미지 basis·없는 UUID 를 fail-closed 하는가.
- 각 스텝의 독립 config_hash · schema_version · resume 계약.
- 금지 어휘 inventory (활성 경로 0, legacy allowlist).
- 레거시 경로 무변 · 구 CP legacy 어댑터가 **읽기 방향만** 인가.

### 6.2 LLM · 이미지 (육안)

TDD 로 판정하지 않는다. 갤러리 육안 + 대조 실행.

- **shadow audit 먼저** — 이미지 0, 저작만 돌려 25그룹의 전략 분포와 근거
  인용을 표로 본다. 전략이 납득되지 않으면 그 앞에서 멈춘다.
- **이름 표를 같이 본다** — 그룹마다 회수된 관례 · 관측 예시 · 저작된 문안 ·
  근거(`place_mark_naming_basis`)를 한 표에 놓는다. 이름이 그 지역 사람에게
  자연스러운지는 **사용자 육안이 최종 권한**이다. 코드도 나도 판정하지
  않는다.
- **대조 실행** — 같은 그룹을 `direct`(오늘) vs `skeleton_then_look` 로
  뽑아 나란히 놓는다. §1.1 봉합의 효과가 여기서 드러난다.
- 산출은 `artifact/<YYYYMMDD_설명>/` 아래, 갤러리 URL 은 LAN IP.

## 7. 선행 과제 — 편입 전에 끝내야 하는 것

1. **표시면 판정의 회차 변동성** — 같은 이미지인데 회차마다 승자와 크기
   판정이 바뀐다. 크기 판정이 흔들리면 필요성 게이트 자체가 불안정하다.
   **해소 전 `place_mark` 편입 금지.**
2. **검색 후보 라운드 분리** — 고정 파일명이 이전 라운드를 파괴한다.
   표면 재판정이 후보 풀에 의존하기 시작하므로 그 전에 고친다.
3. **미커밋 42건 Codex 코드 리뷰 + 커밋** — 편입 베이스라인을 깨끗하게.
4. **검색 실행 system 언어 A/B 육안 판정** — 원어 팔이 3/3 점수 우세이나
   점수는 판정이 고른 것이라 단독 근거가 아니다. 회수 사진 육안이 남았다.

## 8. 미해결 · 이 설계가 답하지 않는 것

- **시점을 아무도 소유하지 않는다.** 부지가 넓은 시설이 드론 부감으로
  나온다. 이번에는 "구조 가시성 우선" 문안 + canary 변수까지만 하고
  (§3.3), evidence-bound `survey_view` 저작은 넣지 않았다.
- **표면 이식의 세기가 그룹마다 다르다.** 벽돌·젖은 골목까지 오는 그룹이
  있는가 하면 참조가 배너로 가득한데 산출이 빈 그룹이 있다.
- **스케치 게이트의 상한이 적절한가.** 총 2~3회로 잡았으나 근거가 없다.
  실측으로 조정할 값이다. 상한 소진이 잦으면 게이트가 너무 엄하거나
  `structure_checks[]` 가 과하게 요구하는 것이다.
- **`interior_note` 에 `excluded_transient_elements` 필터가 걸리지 않는다**
  (실외 spec 만 걸러진다). 장소 서술이 사건 직후 상태로 굳는 원인.
- **`add no other readable text anywhere` 를 어떻게 할 것인가.** 이 절이
  배경 표시물을 뭉갠 획으로 만든다는 것은 실측됐으나, 빼면 모델이 엉뚱한
  글자를 채울 위험이 있다. 이번 범위에 넣지 않는다.

## 9. 시나리오 종속 없음

- 대상 선정에 그룹 이름 목록·업종 이름이 없다. 전략은 데이터(저작 근거
  인용)에서 나오고, 표시면 적용 여부는 이미지에서 VLM 이 정한다.
- **이름 관례를 코드·프롬프트에 적지 않는다.** 어떤 나라의 어떤 종류
  장소가 무엇을 이름에 넣는지는 한 줄도 쓰지 않는다 — 그런 규칙은 다른
  작품·다른 나라에서 조용히 틀린다. 코드가 아는 것은 "찾아와라"까지이고
  답은 검색에서 온다. validator 도 **문자열 동일성만** 본다(관례 만족
  여부를 글자로 판정하지 않는다).
- 코드·프롬프트에 작품 고유명사·업종 이름·표시물 통칭이 없다. §4.3 검사가
  이를 잠근다.
- 실험 하네스의 `GROUPS` 상수와 `SIGN_*` 계열 상수는 편입 대상이 아니라
  제거 대상이다.

## 10. 관련

- 선행 설계 `2026-07-28-search-grounded-seed-and-conti-entity-chain-design.md`
- 선행 설계 `2026-07-31-sketch-skeleton-look-transfer-design.md`
