# 배경 씨드 · 배경 생성 — 테스팅 플랜 (2026-08-01)

**대상:** 2026-07-28 ~ 08-01 에 손댄 배경 씨드·배경 생성 계보.
검색 그라운딩 형태 참조 v3 + 이중 판정 · 씨드 팩 v11~v13 · 사전조사 4축 ·
배경/도면/포즈 계보 정리 · 키 failover · 실험 3종(스케치+룩 · 표시면 재작화 ·
검색어 언어 A/B).

**왜 지금 쓰나.** 이 구간의 변경이 대부분 **이미지 산출로만 확인되는 영역**이라
"돌려 보고 좋아 보인다"로 넘어가기 쉽다. 그런데 지난 며칠의 실측이 그 방식의
실패를 세 번 보여 줬다 — ①층수 병목의 진범은 생성이 아니라 **judge** 였고
②같은 개정절로 다시 그리자 한 그룹이 **더 나빠졌고** ③"글자만 덜렁" 결함의
일부는 프롬프트가 아니라 **배선 결함**이 만든 것이었다. 셋 다 육안만으로는
원인을 못 짚는다.

---

## 0. 원칙 — 무엇을 자동화하고 무엇을 하지 않는가

| | 자동 테스트 | 근거 |
|---|---|---|
| 배선·계약·지문·경로 | **한다** | 결정론이다. 깨지면 항상 깨진다. |
| judge·critique 의 판단 | **부분적으로** | 같은 입력에 같은 답이 나오는지(재현성)는 잴 수 있다. "옳은 답인지"는 못 잰다. |
| 이미지 품질 | **하지 않는다** | 실험 반복 + 육안. 사용자가 최종 판정자다. |

**금지**: PASS 카운트를 품질 근거로 제시하는 것. "유닛 N건 통과 = 동작 검증"
이라는 서술. 이미지 산출에 대해 "고쳤다"를 항목별 확인 없이 쓰는 것.

---

## 1. 현재 상태 실측 (2026-08-01)

배경·씨드 영역 테스트 **95파일 · 1439건 · 22 실패**.

| 실패 | 건수 | 성격 | 처리 |
|---|---|---|---|
| `test_experiment_background_pipeline_slice.py` | 10 | 옛 실험 슬라이스 | **분류 필요** — 실험 잔재면 격리, 계약이면 수정 |
| `test_outdoor_structure_seed_step.py` | 6 | **실제 결함**(BLOCKING 3과 동일 뿌리) | A1 에서 함께 고친다 |
| `test_seed_prompt_variants.py` | 1 | v11~v13 미반영 stale assertion | 즉시 수정 |
| `background_image_smoke_*` | 2 | 실험 스모크 | 분류 필요 |
| `test_c8_area7_residual_hygiene` / `test_d6_master_plan_determinism` / `test_background_prompt_step_v7` | 3 | 미분류 | 분류 필요 |

★22건 중 **실제 결함으로 확인된 것은 6건뿐**이고 나머지는 아직 성격을 모른다.
"전부 기존 실패"로 뭉뚱그리지 않고 하나씩 분류하는 것이 이 플랜의 첫 작업이다.

---

## 2. A층 — 결정론 계약 (자동 · 비용 0)

Codex 리뷰가 지목한 BLOCKING·HIGH 가 **전부 이 층**이다. 지금 아무 테스트도
이것들을 잡지 못한다는 사실 자체가 커버리지 구멍이다.

### A1. producer → consumer 계약 잠금 (BLOCKING 3 · 실패 6건)

- 매니페스트 `outdoor_structure_seed.depends_on` 에 `outdoor_structure_form_reference` 가 있다
- 소비 직전 CP 검증: status `completed` · schema 일치 · `mandatory_group_ids` 와
  현재 target 집합의 **exact parity**
- **`[] or 폴백` 제거** — 지금은 "선행 미실행"과 "필수 대상 0건"을 구분하지
  못해, 정상 판정을 뒤집어 spec 결손 그룹까지 세운다. 반대로 구 CP 가 남아
  있으면 15그룹을 조용히 순수 T2I 로 내린다. **양방향 결함이다.**
- 테스트: fixture 에 form_reference CP 를 넣은 정상 경로 / CP 없음 / CP 있으나
  target 불일치 / mandatory 0건 — 네 갈래 각각의 기대 동작

### A2. 관할절이 실제 롤 프롬프트에 실린다 (BLOCKING 2)

- `roll_prompts[label]` 각각에 form-only 절이 들어간다(base 프롬프트만이 아니라)
- judge·critique 가 보는 유효 계약에도 같은 절이 실린다
- `prompt_used` 에 절이 포함된 프롬프트가 기록된다
- ★근거: 카나리 A/B 에서 절을 각 롤에 주입하니 주 표시면의 기관 표장이
  **A 2/2 없음 → B 2/2 있음** 으로 바뀌었다

### A3. 씨드 자산 계보 (BLOCKING 2)

- seed asset 의 `input_image_ids` 에 `form_ref_asset_id` 가 들어간다(지금은 `[]`)
- CP 에 resolved pack · ref id · ref sha 가 남고 소비 시 재검증된다

### A4. 후보 풀 라운드 불변 (BLOCKING 4 · 계획 1 Task 3)

- 재실행이 기존 `cand_NN.png` 를 덮지 않는다 — 지문별 불변 디렉토리
- 선택 성공 시에만 current 포인터를 원자적으로 갱신
- 테스트: 같은 그룹 2회 실행 후 1회차 파일 bytes 와 audit sha 가 그대로다

### A5. 키 failover 동시성 (BLOCKING 5)

- 전환 기준이 "예외 시점의 전역 active index" 가 아니라 **그 호출이 쓴 슬롯**
- 다른 스레드가 이미 전환했으면 현재 슬롯으로 재시도
- 테스트: 두 호출을 barrier 로 동시에 quota 실패시켜 **둘 다** 살아남는다
  (지금은 하나가 "남은 키 없음" 으로 죽는다 — Codex 실측)

### A6. 이중 판정 parity (HIGH 6)

- 심판별 후보 인덱스가 `1..N` 의 **정확한 순열**인지 검증
- 누락·중복·범위 밖이면 그 심판 전체를 실패로 격리(무시 금지)
- ★현재 테스트(`test_search_grounded_ref_v3.py:105-132`)는 오히려 **malformed
  무시를 정상 계약으로 잠그고 있다** — 이 테스트부터 고쳐야 한다

### A7~A8. 완료분

- 어휘 ratchet (`test_banned_vocabulary_inventory.py`, 5건) — 부채 13건 고정
- 정책 SOT (`test_structure_pipeline_policy.py`, 9건) — 불가능한 조합 거부

---

## 3. B층 — 판정 신뢰도 (생성 비용 0 · LLM 비용만)

**생성은 하지 않고 판정만 다시 돌린다.** 이미 만든 이미지가 재료라 비용이
싸고, 판정 층의 결함을 생성 층과 분리해 볼 수 있다. 도구 =
`harness_rejudge_only.py` (백업본 `artifact/20260801_실험_하네스/`).

### B1. 재판정 재현성 — 회차 변동성 측정

- 같은 이미지 세트에 judge 를 **N=5회** 돌려 승자 일치율을 센다
- 대상: 씨드 3롤 판정 / 표시면 필요성·최종 판정
- ★표시면 판정은 회차마다 답이 달랐다(승자 B→C, 크기 medium→small).
  **크기 판정이 흔들리면 "작아서 고칠 가치 없음" 기준 자체가 불안정하다** —
  이것이 place_mark 편입의 차단 조건이다
- 합격 기준: 승자 일치율이 낮으면 편입 보류. 수치는 측정 후 사용자와 합의

### B2. 계수 절차가 실제로 작동하는가

- 팩 v13 이 넣은 "본 층수 vs 브리프 층수" 계수 절차의 효과를 재판정으로 확인
- 방법: 층수가 어긋난 것으로 알려진 이미지 쌍에 구/신 팩 판정을 각각 돌려
  **층수가 맞는 후보가 이기는지** 본다(이미 2회 역전 확인, 표본을 늘린다)

### B3. 탈락 후보 감사 — 선정본만 보지 않는다

- 3롤 전체를 갤러리에 나란히 걸고 판정 사유와 함께 육안 대조
- ★"판정을 거친 산출은 생성이 만든 것이 아니라 **판정이 고른 것**"이다.
  선정본만 열어 보고 "모델이 못 그린다"고 두 번 오진했다

---

## 4. C층 — 산출 품질 (생성 비용 · 육안이 최종)

### C1. 카나리 1그룹 (승인 불필요 · 소액)

편입 항목마다 **한 그룹 먼저**. 지난 며칠의 실측이 전부 1그룹 카나리에서
나왔다. 통과 못 하면 확대하지 않는다.

### C2. 소규모 배치 4그룹

유형이 다른 것으로 고른다(주거 / 상업 / 시설 / 자연물). 한 유형에서 통한
방법이 다른 유형에서 뒤집히는 것을 이미 봤다 — 룩 이식의 세기가 그룹마다
달랐고, 시점 드리프트는 부지가 넓은 시설에서만 나왔다.

### C3. 전량 재생성은 마지막

★**재생성이 개선을 보장하지 않는다.** 같은 개정절로 다시 그리자 한 그룹이
더 나빠졌다(색·부감·계단 2개). 그래서 게이트를 "통과할 때까지 재생성"이
아니라 **PASS 자격 2단계**로 둔다 — eligible 0 이면 fail-closed 이고,
"가장 덜 나쁜 후보" 채택은 금지, 동점이면 가장 이른 PASS.

---

## 5. 실행 순서

```
① 실패 22건 분류 (16건 미분류)          — 비용 0, 반나절
② A층 A1~A6 구현 + BLOCKING 이행        — 비용 0, TDD
   └ A1 이 실패 6건을 함께 해소한다
③ B층 재판정 측정 (B1 회차 변동성 먼저)  — LLM 소액
   └ 여기서 place_mark 편입 가부가 갈린다
④ C1 카나리 1그룹 → 사용자 육안          — 이미지 소액
⑤ C2 4그룹 → 사용자 육안                 — 이미지 중간
⑥ C3 전량                                 — 사용자 승인 후
```

각 단계는 **앞 단계가 통과해야** 다음으로 간다. ②를 건너뛰고 ④부터 하면,
이미지가 나빠도 원인이 배선인지 프롬프트인지 판정인지 구분할 수 없다 —
지난 며칠에 실제로 겪은 순서 실패다.

---

## 6. 이 플랜이 하지 않는 것

- 이미지 품질을 자동 판정으로 대체하지 않는다
- 통과 건수를 품질 근거로 제시하지 않는다
- 전량 재생성을 개선의 수단으로 쓰지 않는다
- 실험 하네스를 production 테스트로 승격하지 않는다(절차만 옮긴다)
