야외 구조물 이미지 파이프라인 — 개발자 상세도

2026-07-31 기준. 시나리오 텍스트 한 편에서 야외 구조물의 확정 실사(씨드)가 나오기까지 어떤 스텝이 무엇을 근거로 무엇을 만드는지, 그리고 어디가 아직 비어 있는지를 적는다. 각 블록에 상태 표를 달았다 — 문서와 코드가 어긋나면 코드가 맞다.

구현·배선됨 모듈만 있음 (미배선) 설계만 (코드 없음) 실측 결함

0. 전체 조감 — 83스텝 중 어디를 다루는가

파이프라인은 step_manifest.pyorder 로 정렬된 83스텝이다. 이 문서가 자세히 다루는 것은 21.7 ~ 21.93 구간(야외 구조물 계보)과 그 소비처다.

flowchart LR subgraph A["분석 0~19 · 텍스트만"] direction TB A1["text_cleanup 1
scene_segmentation 2
visual_world_rules 4"] A2["beat_extract 7.1
shot_extract 7.2
shot_validator 7.25"] A3["entity_* 8~13.7
entity_merge 13.5"] A4["scene_director 16
shot_selection 15.5
outlook 19~19.3"] A1-->A2-->A3-->A4 end subgraph B["공간 계획 19.5~21.6"] direction TB B1["shot_staging 19.5
background_classify 19.51"] B2["location_floor_plan 21.5
floor_plan_render 21.55"] B3["background_prompt 21.6"] B1-->B2-->B3 end subgraph C["야외 구조물 21.76~21.92
★이 문서의 주제"] direction TB C1["outdoor_site_layout 21.76"] C2["outdoor_place_spec 21.77"] C3["outdoor_lane_plan 21.775"] C4["outdoor_place_canon 21.78"] C5["form_reference 21.915"] C6["structure_seed 21.92"] C1-->C2-->C3-->C4-->C5-->C6 end subgraph D["이미지 생성 22~25"] direction TB D1["space_set_bg 22.5"] D2["background_chain_render 24.7
background_render 24.72"] D3["shot_conti_light 24.73"] D4["scene_image_pipeline 25"] D1-->D2-->D3-->D4 end A-->B-->C-->D style C fill:#fff3d6,stroke:#c8922a,stroke-width:2px
모델 분업 — 확정·감독 계열은 gemini-pro(gemini-3.1-pro-preview), 분석 주력은 gpt(gpt-5.6-sol), 이미지 생성은 gemini-3.1-flash-image-preview(nb2), 웹 검색 오케스트레이터는 gpt-5.6.

1. 야외 구조물 계보 — 현행 배선 구현·배선됨

flowchart TB SS["scene_save 6
시나리오 원문 전문
(절대 무절단)
"] VWR["visual_world_rules 4
지역·시대 확정 사실"] BC["background_classify 19.51
building_groups"] EM["entity_merge 13.5
locations"] SPEC["outdoor_place_spec 21.77
그룹별 persistent_site 검증 서술
+ excluded_transient_elements"] LANE["outdoor_lane_plan 21.775
place_segment 분할
+ 선택 샷 레인 바인딩"] CANON["outdoor_place_canon 21.78
캐논 자산"] FR["outdoor_structure_form_reference 21.915
원본어 검색 → 후보 → VLM 이중 선택"] SEED["outdoor_structure_seed 21.92
저작 3변형 → 3롤 → 판정 → critique → fix"] BR["background_render 24.72"] CL["shot_conti_light 24.73"] SS --> SPEC BC --> SPEC EM --> SPEC SPEC --> LANE --> CANON SPEC --> FR LANE --> FR VWR --> FR SS -.->|"언어 판정 전용
(의미 기여 금지)"| FR FR -->|"form_ref_path
+ sha256 + asset_id"| SEED SPEC --> SEED LANE --> SEED SS --> SEED SEED -->|seed_png_path| BR SEED -->|seed_png_path| CL style FR fill:#d6ecff,stroke:#2a6fc8,stroke-width:2px style SEED fill:#d6ecff,stroke:#2a6fc8,stroke-width:2px

1.1 대상 집합이 정해지는 곳 — 두 번 틀린 자리

“어떤 배경이 검색·씨드를 타는가”는 두 번 잘못 설계됐고, 두 번 다 자격을 판정하려 한 것이 원인이었다.

버전대상 규칙무엇이 깨졌나
v1structure_plate 레인 바인딩 그건 구조물의 성질이 아니라 샷의 필요성이다. 25그룹 중 10만 검색을 탔고 편의점·파출소·주유소·도축장 등 15그룹이 순수 T2I 로 남았다
v2바인딩 ∪ LLM scope 판정 ①판정 입력에 작품 고유명사가 실려 이름으로 의미를 판정하는 경로가 열렸다 ②validator 가 근거 없는 NO 를 통과시켜 “애매하면 yes” 가 강제되지 않았다
v3 (현행)판정을 없앤다. 소비자(seed)와 exact parity 유일한 제외는 place spec 결손이고 data.target.no_spec_group_ids 에 명시 기록된다. 조용히 빠지는 경로가 존재하지 않는다
검색 대상 = collect_lane2_groups(lane, all_groups=<seed 와 동일 플래그>)
           - (place spec 결손 그룹)

1.2 outdoor_structure_form_reference — 검색·다운로드·이중 판정

flowchart TB IN["structure_desc (place spec 파생)
world_facts_block (지역·시대)
source_text (씬 원문 전문)"] BRIEF["① 검색 지시문 저작
model=gpt · schema=structure_form_ref_brief
산출은 원본어
search_directive_native + search_terms_native"] SEARCH["② 웹 이미지 검색
orchestrator=gpt-5.6
tools=[web_search]
search_content_types=[image,text]
SEARCH_IMAGE_RESULTS=6"] DL["③ 후보 다운로드
MAX_PICK_CANDIDATES=12
SAFE_DOWNLOAD_POLICY
→ structure_form_refs/<gid>/cand_NN.png"] J1["④-a 심판 gemini-pro
0~100 척도"] J2["④-b 심판 gpt
0~100 척도"] COMB["combine_pick_verdicts
후보별 평균 최고"] OK{"선택됨?"} NARROW["⑤ 주 구조물 하나로 좁혀
1회 재검색 (narrow hint)"] FAIL["fail-closed
(순수 T2I 자동 하강 금지)"] ASSET["ImageAsset UPSERT
asset_type=structure_form_ref
variant_type=form_ref"] IN --> BRIEF --> SEARCH --> DL --> J1 & J2 --> COMB --> OK OK -- yes --> ASSET OK -- no --> NARROW --> FAIL REUSE["그룹 재사용 판정
_group_fingerprint 일치
+ 파일 존재 + sha 재검증"] REUSE -.->|"일치 시 검색 생략"| ASSET style BRIEF fill:#e8f5e9,stroke:#2e7d32 style COMB fill:#fff3d6,stroke:#c8922a style FAIL fill:#ffe0e0,stroke:#c62828

왜 이 모양인가 (감독 말판 실험 6~13회차 + 금월도 2고 실측)

금월도 2고 실측 (2026-07-31) — 25/25 성공, 실패 0. 검색어 116개가 전부 한국어. 후보 회수 239장(그룹당 평균 9.6, 최소 5). VLM 탈락 61건이며 사유가 실질적이다 — “실내에서 외부를 내다본 구도라 외관 구조 판단 불가”, “표지판이 주 피사체라 형태 파악 불가”.
실측 결함 미해결 — 후보 파일명이 그룹당 고정 (cand_01.png…)이라 재검색이 이전 라운드 후보를 파괴한다. 갤러리 manifest 에서 344건이 overwritten 으로 확인됐다(R1 106·R2 100·R3 69·R4 69).

1.3 outdoor_structure_seed — 저작·3변형·판정·수정

flowchart TB GATE{"structure_seed_variants_enabled?"} LEG["레거시 경로
build_structure_seed_prompt
동일 프롬프트 N롤"] AUTH["① 변형 저작 (LLM 위임)
model=gpt(gpt-5.6-sol)
schema=seed_variant_author
SEED_VARIANT_COUNT=3"] AUTHOUT["location_line_en
conformance_brief_en
room_inventory[] + applicable
signage_required/reason/text
variants[3]{approach,evidence,prompt_en}"] VAL["validate_variant_output
· 변형 수·id enum
· 인용 provenance(scene_index +
whitespace-normalized 원문 대조)
· required↔text 정합"] RETRY{"위반?"} SIDE[("sidecar
seed_variant_records.json
author_fp 로 캐시")] ASSEM["② assemble_variant_roll_prompts
롤별 프롬프트 3개
+ 규모 계약(interior_note 상시)"] CONF["build_conformance_prompt
= judge/critique 공용 브리프"] FREF["③ 형태 참조 결정
_resolve_form_ref
파일 존재 + sha 재검증
필수 대상 결손 = AppError"] MR["④ run_multiroll_select
(§1.4)"] UP["⑤ ImageAsset UPSERT
asset_type=structure_seed
variant_type=seed"] GATE -- OFF --> LEG --> MR GATE -- ON --> AUTH --> AUTHOUT --> VAL --> RETRY RETRY -- "예 (최대 2회, 이전 위반 병기)" --> AUTH RETRY -- 아니오 --> SIDE --> ASSEM --> MR AUTHOUT --> CONF --> MR FREF --> MR MR --> UP style AUTH fill:#e8f5e9,stroke:#2e7d32 style MR fill:#d6ecff,stroke:#2a6fc8,stroke-width:2px
★실측 결함 미해결 — 관할절이 생성에 도달하지 않는다
outdoor_structure_seed_step.py:744-750build_form_only_clause()_gen_prompt(= conformance brief)에만 붙이는데, multiroll_select.py:755-756 은 생성 시 roll_prompts[label] 을 쓴다. variants 모드(현행 production)에서 관할절은 judge/critique 로만 가고 생성에는 닿지 않는다. 즉 검색 사진이 라벨만 달고 계약 없이 들어간다.
def _roll_prompt(lab: str) -> str:
    return roll_prompts[lab] if roll_prompts else prompt
카나리 A/B 실측(같은 프롬프트·같은 사진에 관할절만 각 롤에 주입): 주 표시면의 기관 표장이 A 는 2/2 없음, B 는 2/2 있음. 관할절 본문에 the same signage conventions and lettering style of that region 이 들어 있으므로 귀속 가능하다 — “표시면에 글자만 덜렁 남는다”는 결함의 일부는 이 배선 결함이 만든 것이다.

1.4 run_multiroll_select 내부

flowchart TB FP["input_fingerprint 계산
prompt/refs/roll_prompts/extra_fp
→ 불일치 시 산출 무효화"] ROLLS["N롤 생성 (기본 3)
gen_fn(tag, _roll_prompt(L), _gen_refs(L), path)
· roll_prompts 있으면 롤마다 다른 프롬프트
· parallel_rolls 시 budget·generation_context 명시 전파
· 롤 파일 존재 = skip (resume)"] JF["judge_fn 정순
gemini-pro · 후보 블라인드"] JR["judge_fn 역순
(순서 편향 상쇄)"] SEL["합산 → selected"] CR{"critique_enabled?"} CRIT["critique_fn
결함 목록 + needs_regeneration 표시"] BR{"결함 유형"} FIX["fix_gen_fn
i2i 국소 수정"] REGEN["regen_gen_fn
원 브리프로 재생성
(거부 산출만 참조에서 제외)"] RJ["fix_rejudge_fn
원본 vs 수정본 블라인드
정순·역순"] OUT["최종 선정 PNG + record"] FP --> ROLLS --> JF & JR --> SEL --> CR CR -- 아니오 --> OUT CR -- 예 --> CRIT --> BR BR -- "국소 결함" --> FIX --> RJ BR -- "구조 결함
(층수·매스·footprint)" --> REGEN --> RJ RJ --> OUT style REGEN fill:#fff3d6,stroke:#c8922a style RJ fill:#e8f5e9,stroke:#2e7d32
왜 구조 결함은 재생성인가 — i2i 국소 편집으로는 안 고쳐진다. 실측에서 "Add a third full storey" 지시가 그대로 실패했다. 단 거부된 산출만 참조에서 빼고 원래 참조는 유지한다 — 참조를 통째로 비우면 형태 권위까지 사라진다. 재생성은 “이 브리프와 이 참조로 다시 찍기”이지 “맨손으로 다시 그리기”가 아니다.
★층수 병목의 진범은 judge 였다 (원인이 세 번 옮겨갔다)
가설판정근거
저작이 규모를 작게 쓴다아니다v11 에 이미 축소 형용사 금지가 있었고 브리프는 실제로 요구대로 썼다
T2I 가 층수를 못 그린다아니다3롤 중 두 장이 요구대로였다 — 선정본만 보고 단정한 것이 오진
judge 가 맞는 후보를 떨어뜨린다맞다A(3층)=10점 / B(4층)=6점. 같은 산출을 critique 는 정확히 셌다
원인 둘 — ①층수를 “세라”는 절차가 없어 인상으로 판단 ②상위 축(현실감)이 정도 비교로 쓰여 밤에 불 켜진 후보가 대낮의 깔끔한 후보를 이겨 층수 축까지 가지 않았다. 팩 v13 에서 현실감을 PASS/FAIL 로 못박고 계수 절차를 넣어 층수가 맞는 후보가 무조건 이기게 했다. 검증 = 같은 이미지 재판정 2회 모두 순위 역전.

2. 사전조사 (typology prior) 모듈만 있음 · 미배선

씨드 저작은 시나리오 원문 + place spec 두 가지만 근거로 쓴다. 그래서 둘 다 침묵한 항목은 모델의 통념이 메운다.

실측 (bg_police_station, 2026-07-31)
무엇을 말하나
시나리오경찰서 주차장·경찰서 형사과고유명 없음 · 규모 언급 0 · 입지 성격 언급 0
저작 evidence씬 헤딩 2건 + 모니터 화면 서술 1건 — 규모 근거 0건
저작 산출30 by 18 metre 3층 · in an inhabited urban neighborhood · 표시 문안 조어
전수: 표시 문안이 있는 12그룹 중 11건이 원문에 없는 조어. 유일하게 원문에 실재하는 문안도 상호가 아니라 작품 인물 이름이다 — 원문에서 온 상호는 0건.
★팩 v11 결함의 거울상이다. 그때는 침묵을 부재로 확정했고(no canopy), 지금은 침묵을 지어내서 확정한다.
flowchart TB SRC["structure_desc + layout + interior/exterior notes
+ 씬 원문 전문"] GAP["① 결손 문항 저작
model=gpt · GAP_SYSTEM
MAX_GAP_QUESTIONS=8
질의는 원본어 · 유형 일반으로 환원"] AX{"축 검증
validate_gap_output"} AXES["siting / scale / composition / naming
★siting 문항은 반드시 첫 번째"] S1["②-a 검색 gpt-5.6
tools=[web_search]"] S2["②-b 검색 gpt-5.6-sol
독립 실행"] AG["③ 일치 판정
model=gemini-pro
AGREE_SYSTEM"] D1{"양쪽 발견 + 일치"} STRONG["[corroborated] 채택"] WEAK["[single source] 약하게 채택
= 경향이지 단정 아님"] DROP["폐기 (모순 · 양쪽 미발견)"] BLK["④ build_typology_facts_block
권위 서열을 헤더에 박는다:
시나리오 > place spec > 사전조사"] AUTH["씨드 저작 입력"] SRC --> GAP --> AX --> AXES --> S1 & S2 --> AG --> D1 D1 -- 예 --> STRONG --> BLK D1 -- "한쪽만 발견" --> WEAK --> BLK D1 -- "양쪽 발견·불일치 / 양쪽 미발견" --> DROP BLK -.->|"★아직 배선되지 않음"| AUTH style AXES fill:#fff3d6,stroke:#c8922a style AUTH stroke-dasharray: 6 4,fill:#eee,stroke:#999

siting 이 먼저인가

나머지 셋이 그 답에 매달린다. 같은 종류의 시설도 어떤 성격의 정주지에 서느냐로 예산이 갈리고 그래서 규모·구성이 갈린다. 입지를 가정한 채 규모를 물으면 틀린 유형을 조사해서 그 가정에 인용을 붙여 주는 꼴이 된다. validate_gap_output 이 “siting 문항은 첫 번째”를 강제한다.

실행 확인 (2026-07-31, bg_police_station) — 문항 7개 (siting 1 · scale 1 · composition 4 · naming 1), 1번이 siting. 채택 5 / 폐기 2. ★어떤 답이 맞는지는 코드가 알지 못한다. 코드가 가진 것은 축 이름 넷과 “찾아와라”까지이고 답은 전부 원본어 검색에서 온다. 소스에 유형·업종 어휘가 없음을 유닛이 잠근다.

naming 축의 별도 계약

검색 지시  : 이름의 조립 방식을 보고하라. 관측된 실재 이름은 예시로만 표시하라.
주입 블록  : "패턴이지 쓸 이름이 아니다" 경고를 naming 줄이 있을 때만 붙인다.
저작 권위  : ① 원문이 이름을 말하면 그것이 이긴다
             ② 침묵하면 관례의 조립 방식으로 짓되 성분은 작품 것에서
             ③ 관례가 없으면 오늘과 같이
validator : 저작 문안이 관측 예시와 문자열 동일하면 위반 (베낀 것)
            ★문자열 동일성만 본다 — 글자 패턴으로 의미를 판정하지 않는다

3. 편입 예정 설계만

3.1 전체 목표 계보 (5스텝)

flowchart TB FR["outdoor_structure_form_reference 21.915
후보 풀 · form_ref · look_ref(신규) · naming_convention(신규)"] PLAN["outdoor_structure_seed_plan 21.916 (신규)
저작 A + 전략 판정 B (계약 2분리)"] SK["outdoor_structure_skeleton 21.917 (신규)
선 스케치 + 구조 게이트"] SEED["outdoor_structure_seed 21.92 (개정)
두 권위 합성"] PM["outdoor_structure_place_mark 21.925 (신규)
표시면 재작화"] CONS["background_render 24.72
shot_conti_light 24.73"] FR --> PLAN --> SK --> SEED --> PM --> CONS PLAN -.->|"render_strategy = direct 인 그룹은 스케치 없음"| SEED PM -.->|"effective_seed map"| CONS style PLAN fill:#efe3ff,stroke:#7b4fbd style SK fill:#efe3ff,stroke:#7b4fbd style PM fill:#efe3ff,stroke:#7b4fbd

전략 판정 — tri-state

strategy = {
  raw:       skeleton_then_look | direct | uncertain,   # 판정이 말한 것
  effective: skeleton_then_look | direct,               # 코드가 적용하는 것
  evidence:  [{scene_index, quote}],                    # 공급 씬 원문 verbatim
  reason_ko: str,
}
과거 실패와 무엇이 다른가form_reference 의 v1·v2 실패는 판정이 검색 모집단을 줄인 것이었다. 여기서는 모집단을 줄이지 않고 렌더 전략만 고른다. 모든 그룹이 저작을 타고 씨드를 뽑는다.

3.2 skeleton — 구조 게이트와 회차 보존

flowchart TB BRIEF["conformance_brief_en (손대지 않음)
+ 스케치 변환절 (앞에만 붙임)"] GEN["round N 생성
★참조 없음 — 웹 사진 절대 미첨부"] GATE["전체 계약 재판정
① 변환 hard rule 전부
② structure_checks[] 전 항목
③ 시점 계약
★이전 위반 목록은 생성 힌트일 뿐
판정 범위를 줄이지 않는다"] PASS{"PASS?"} KEEP[("round_NN.png 불변 보존
+ prompt SHA · output SHA
+ 판정 원문 · 축별 정규화 · 위반")] MORE{"상한 미만?"} ELIG{"eligible(PASS) 개수"} ADOPT["즉시 채택 · 정지"] CMP["soft 축으로 비교
동점 = 가장 이른 PASS 회차"] FC["fail-closed
★'가장 덜 나쁜 후보' 채택 금지"] BRIEF --> GEN --> GATE --> PASS PASS -- 예 --> ADOPT PASS -- 아니오 --> KEEP --> MORE MORE -- 예 --> GEN MORE -- 아니오 --> ELIG ELIG -- "0" --> FC ELIG -- "1" --> ADOPT ELIG -- "2+" --> CMP style FC fill:#ffe0e0,stroke:#c62828 style GATE fill:#fff3d6,stroke:#c8922a
★카나리 실측이 이 형태를 강제했다 (2026-07-31)
스케치 3장 중 2장이 변환절을 어겼다 — 브리프의 표시 문안 절이 “글자 금지”를 이겨 상호가 그려지고(2/3), 색이 들어가고(2/3), “지상 접근 가능한 시점”을 넣었는데 부감(1/3).

우선순위를 명시해 다시 그리자 한 그룹은 오히려 나빠졌다 — 1차는 순수 선화·눈높이·계단 1개가 정확히 2층 도착이었는데 2차는 색·부감·계단 2개. 즉 “위반 목록만 보고 통과할 때까지 재생성”은 다른 축에서 새로 깨진 회차를 통과로 확정한다.

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

“변환절이 브리프보다 항상 우선”으로 뭉뚱그리면 브리프의 구조 사실까지 지워진다. 관할로 나눈다.

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

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

게이트 축 — structure_checks[]

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

축 이름은 구조의 보편 성질이지 유형 이름이 아니다. 무엇이 참이어야 하는지는 그룹마다 저작이 근거와 함께 쓴다 — 코드가 검사 항목을 지어내면 그 순간 유형별 규칙이 코드에 박힌다.

3.3 두 권위 합성

flowchart LR SK["STRUCTURE SKELETON
(선 스케치)"] LK["SURFACE LOOK REFERENCE
(검색 사진)"] GEN["씨드 생성
roll_prompts 각 항목에
우선순위 절 주입"] SK -->|"형상 · 매스 · 개구부 위치와 수
수직 동선 시작·도착 · 지붕
지면 접합 · 시점"| GEN LK -->|"재료 · 색 · 마감 · 풍화
관리 상태 · 노면 마감"| GEN LK -.->|"★전이 금지
카메라 · 조명 · 시간대 · 날씨
그림자 · 하늘 · 사람 · 차량 · 물건"| GEN style SK fill:#e8f5e9,stroke:#2e7d32 style LK fill:#d6ecff,stroke:#2a6fc8
전략labeled_refs
skeleton_then_look[("STRUCTURE SKELETON", skeleton), ("SURFACE LOOK REFERENCE", look_ref)]
direct[("FORM REFERENCE", form_ref)] — 단, 관할절이 실제로 도달하는 상태
조명을 룩 권위에서 뺀 이유 — 초안은 “빛의 질”을 룩 권위에 넣었는데, 그러면 무작위 사진의 정오 그림자가 씨드에 고착된다. 사진 선택 시 “표면을 판독할 만큼 밝은가”는 품질 조건일 수 있으나 전이 권위는 아니다.

표면 참조는 어떻게 고르나

현재 25장은 “형태가 잘 읽히는가” 기준으로 고른 것이라 표면 권위로 쓰기엔 선택 기준이 어긋난다. 그렇다고 이름만 바꾸면 선택 목적이 여전히 form 이라 반쪽이다. 채택안 = 같은 후보 풀에 표면 기준 pick 계약을 새로 적용(검색 비용 0).

flowchart LR POOL[("후보 풀
structure_form_refs/<gid>/<pool_fp>/")] FP["form pick 계약"] LP["표면 pick 계약 (신규)"] FR2["form_ref → direct 그룹용"] LR2["look_ref → skeleton 그룹용"] POOL --> FP --> FR2 POOL --> LP --> LR2

3.4 장소 표시면 재작화

코드는 표시물의 존재를 전제하지 않는다. 코드가 아는 것은 “이 장소를 알리는 활자나 표시가 들어가는 면” 까지이고, 그런 면이 사진에 있는지·읽힐 크기인지·고칠 값어치가 있는지는 전부 VLM 이 정한다.

flowchart TB SEEDPNG["선정된 씨드 PNG"] ASSESS["① 필요성 판정 (VLM)
사진에서 표시면을 전부 찾고
화면 점유·가독 여부를 보고
required | not_required | uncertain"] D1{"required?"} NOOP1["typed no-op
unchanged_not_required
unchanged_uncertain"] BRIEF2["② 원본어 검색 지시문 저작
★구조물용 brief_system 과 별개 계약
(묻는 대상이 건물이 아니라 그 면이다)"] SEARCH2["③ 검색 → 후보 → VLM 이중 선택
판정 기준 = 면이 어떻게 만들어졌는가가 읽히는가
★후보에 적힌 문구는 판정과 무관"] FIX2["④ i2i 재작화 (3롤)
IMAGE1=고칠 사진(그 외 전부 불변)
IMAGE2=표시면 참조(조립 방식만, 문구 권위 없음)"] HG{"구조 보존 hard gate
표시면 밖 변경 · 없던 면 신설·확대 = 즉시 탈락"} CMP2["⑤ 원본 포함 비교 판정
두 심판이 개선에 동의할 때만 채택
동점·불일치 = 원본"] APPLIED["applied"] NOOP2["unchanged_disagreement
unchanged_failed"] MAP[("effective_seed map
seed 대상 전 그룹 exact parity
{asset_id, basis, reason_ko}")] SEEDPNG --> ASSESS --> D1 D1 -- 아니오 --> NOOP1 --> MAP D1 -- 예 --> BRIEF2 --> SEARCH2 --> FIX2 --> HG HG -- 탈락 --> NOOP2 --> MAP HG -- 통과 --> CMP2 --> APPLIED --> MAP CMP2 -.->|원본 승| NOOP2 style HG fill:#fff3d6,stroke:#c8922a style MAP fill:#e8f5e9,stroke:#2e7d32

다중 표시면 일관성 3겹

  1. 모든 표시면이 같은 문자·색·서체·표장을 쓰고, 면의 비례에 따라 배치만 다르다
  2. 한 면만 고치고 다른 면을 남기면 실패다
  3. 없던 표시면을 새로 만들거나 키우지 않는다

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

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,
}

소비자는 map 결손 · 모르는 basis · 존재하지 않는 UUID 를 fail-closed 한다. producer 가 기록한 typed no-op 일 때만 base 를 쓴다. 이것이 place_mark 실패를 seed 실패로 전파하지 않으면서 조용한 하강도 막는 경계다.

편입 차단 조건 미해결 — 표시면 판정의 회차 변동성. 같은 이미지인데 회차마다 승자가 바뀌고(B→C) 크기 판정이 흔들린다(medium→small). 크기 판정이 흔들리면 “작아서 고칠 가치 없음” 기준 자체가 불안정하다. 해소 전 편입 금지.

4. 계약 · 지문 · 재사용

지문 3분리 (설계) — 획득과 선택의 수명은 다르다

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

★단일 지문에 선택 계약을 얹으면, 판정 문구 한 줄을 고쳤을 뿐인데 그룹 전체가 stale 이 되어 재검색이 돌고 후보 풀이 파괴된다. “재검색 없이 재판정”과 라운드 보존을 동시에 깨는 경로다.

정책 SOT (설계) — hash 는 validity gate 가 아니다

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

어휘 이행 (설계)

signage_requiredplace_mark_surface_applicable
signage_reason_koplace_mark_surface_reason_ko
signage_textplace_mark_surface_text
signage_clauseplace_mark_surface_clause
— (신규)place_mark_naming_basis · ..._evidence · ..._reason_ko

필드의 내용은 살린다 — 목표 문안은 재작화 스텝이 계속 쓴다. 바뀌는 것은 명칭과, “고칠 것인가”를 정하는 게이트가 저작에서 VLM 으로 옮겨간다는 것이다. 저작 시점 판정은 이미지가 없어 면의 존재·가독 크기를 알 수 없다.
현재 부채 13건이고 씨드 경로 밖으로도 번져 있다 — background_render · location_aerial · prompt_service · indoor_shared_pose_provider · visual_continuity_anchor_provider + 활성 팩 6개.

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

5. 실측 결함 대장

#결함상태
1관할절이 생성 프롬프트에 미도달(roll_prompts 경로)배선미해결 · 편입에 흡수 예정
2검색 후보 고정 파일명 → 재검색이 이전 라운드 파괴(344건 overwritten)영속미해결 · 계획 1 Task 3
3사전조사 부재 → 저작이 입지·규모·이름을 근거 없이 확정계약모듈 구현 · 미배선
4스케치 변환절이 브리프의 표시 문안 절에 진다프롬프트관할 분리 설계됨 · 미구현
5재생성이 개선을 보장하지 않는다(다른 축에서 새 위반)절차PASS 자격 2단계로 설계 개정
6표시면 판정의 회차 변동성(승자·크기 판정이 흔들림)판정미해결 · 편입 차단 조건
7시점을 아무도 소유하지 않는다(부지 넓은 시설이 부감)계약게이트 축으로 승격 설계
8interior_noteexcluded_transient_elements 필터 미적용계약미해결 · 범위 밖
9add no other readable text anywhere 가 배경 표시물을 뭉갠 획으로 만든다프롬프트미해결 · 범위 밖
10test_outdoor_structure_seed_step.py 6건 — fixture 가 fail-closed 계약 미반영테스트미해결

6. 구현 상태 매트릭스

구성요소모듈배선유닛실측
검색 그라운딩 형태 참조 (v3 + 이중 판정)✅ 25/25
씨드 3변형 저작 · 판정 · critique · fix✅ 25/25
팩 v13 (층수 계수 절차)✅ 재판정 2회 역전
OpenAI 키 2슬롯 failover✅ 29건✅ 실전 발동
사전조사 4축✅ 20건✅ 1그룹
정책 SOT · 조합 validator
후보 라운드 분리 · 지문 3분리
표면 pick (look_ref)
이름 관례 회수 · 저작 준수부분(축만)부분✅ 조사 결과 확인
seed_plan 스텝 (저작 이관 · 전략 tri-state)
skeleton 스텝 · 구조 게이트✅ 카나리(하네스)
두 권위 합성 · 관할절 전 롤 주입✅ 카나리 A/B
place_mark 스텝✅ 하네스 3그룹
어휘 이행 (활성 경로 13건)
요약 — 현행 production 은 검색 그라운딩 형태 참조 + 3변형 씨드까지가 실제로 돈다. 스케치 선행 · 표면 이식 · 표시면 재작화 · 사전조사 배선은 설계와 실험까지 와 있고 production 코드는 아직 없다. 사전조사만 모듈이 서 있으나 아무 스텝도 부르지 않는다.

설계 SOT = docs/superpowers/specs/2026-07-31-structure-skeleton-look-and-place-mark-production-merge-design.md
구현 계획 = docs/superpowers/plans/2026-07-31-structure-pipeline-foundation.md (계획 1/5)
이 문서는 코드보다 뒤처질 수 있다 — 어긋나면 코드가 맞다.