
    Oj)                    H   U d Z ddlmZ ddlZddlmZmZmZ ddlm	Z	 dZ
dZdZd	Z e       Zd
ed<    ee
eeeh      Zd
ed<   eez  rJ eez  Zd
ed<    eeh      Zd
ed<   eek  sJ e
Z eeh      Zd
ed<   eek  sJ dZ	 d	 	 	 ddZddZddZddZddZddZddZy)u  GROUNDING-V2 — 모드 enum SOT.

설계: docs/design/2026-08-29-grounding-v2-contract.md §12.

★**boolean 두 개로 두지 않는다.** 둘 다 켜지면 같은 대상을 두 번 사는 상태가
존재한다. enum 이면 그 상태가 **구조적으로 불가능**하다.

    legacy       현재 scene_image_pipeline 만 호출한다
    shadow_plan  새 분류·질의계획만 만들고 **검색도 이미지 생성도 0**
    v2           통합 경계에서 처리한다
    v2_chunk     v2 인데 **구간당 단일 판독**(C(c))으로 산다 — ★아직 아무도 안 쓴다

★``shadow_plan`` 은 **production 지문을 절대 stale 시키지 않는다.** 검색도
산출도 안 바꾸는 무료 관찰을 켠 것만으로 detail/t2i/reference/scene 이 다시
구워지면, 관찰하는 값이 관찰 대상을 바꾸는 것이다. 그래서 지문은 **shadow
체크포인트에만** 접는다.
    )annotationsN)AnyMappingOptional)AppErrorlegacyshadow_planv2v2_chunkzfrozenset[str]PLANNED_MODESGROUNDING_MODESKNOWN_MODESCHUNK_PRODUCER_MODESNO_RESEARCH_AT_ALL_MODESGROUNDING_MODEc           	     *   d}| r| j                  d      }|#t        j                  j                  t              }|t        S t        |      j                         j                         }|t        vr!t        dd|dt        t               d      |S )u*  모드를 정한다 — project_config 우선, 없으면 ENV, 없으면 legacy.

    Raises:
        AppError: enum 밖 값. ★조용히 legacy 로 떨어뜨리지 않는다 — 오타 하나로
            v2 주행이 legacy 로 돌면 「켰는데 안 바뀐다」를 며칠 쫓게 된다.
    Ngrounding_modegrounding.mode_invalidgrounding_mode=u+    는 없는 값이다. 쓸 수 있는 것:   codemessagestatus_code)getosenviron_ENV_KEYDEFAULT_GROUNDING_MODEstrstriplowerr   r   sorted)project_configrawvalues      M/Users/manta/Documents/Projects/TheRoad-I1/backend/app/core/grounding_mode.pyresolve_grounding_moder(   X   s     C  !12
{jjnnX&
{%%HNN""$EO#)!# )''-o'>&?A 
 	
 L    c                H    | t         vrt        dd| dd      | t        k(  S )u   이 모드가 **v2 고증 조사를 사는가.** ★shadow_plan 은 안 산다.

    ★이름을 좁혔다. 예전 ``buys_research`` 는 「legacy 는 아무것도 안 산다」로
    읽혔는데 **사실이 아니다** — legacy 는 자기 몫의 장소 시대 조사를 산다.
    r   r       는 없는 값이다r   r   )r   r   GROUNDING_MODE_V2modes    r'   buys_v2_researchr/   u   s:     ?")%dX-BC
 	

 $$$r)   c                F    | t         vrt        dd| dd      | t        v S )u  C(c) **구간당 단일 판독**으로 사는가. ★`v2_chunk` 만 True.

    이 술어가 **활성화 경계**다 —

        True  → 새 producer ON · 옛 `grounding_a0`/`entity_all_*`/
                `entity_extract_*` provider 경로 **OFF** · screen/filter 는
                결정적 투영 · `entity_merge` 는 read-only adapter
        False → 지금 그대로

    ★한 술어로 묶는 까닭: 이것을 여러 flag 로 나누면 **반만 켠 판**이 존재한다.

    ★D 전에는 `resolve_grounding_mode` 가 `v2_chunk` 를 **안 받으므로** 실제
    주행에서 이 함수가 True 를 낼 길이 없다. 계획된 값에도 답할 수 있게
    `KNOWN_MODES` 로 본다 — 「모르는 값」과 「아직 안 받는 값」은 다르다.
    r   r   r+   r   r   )r   r   r   r-   s    r'   uses_chunk_producerr1      s:      ;)%dX-BC
 	

 '''r)   c                2    t        |       xs t        |       S )u  이 판이 **참조 사진을 사는가** — 어느 producer 든. ★한 자리(SOT).

    ★★같은 규칙이 두 곳에 있었다 (2026-09-03 실측): manifest 술어
    `_if_grounding_reference` 는 「v2 or v2_chunk」로 묻는데, 야외 스텝의 소유권 문
    `acquisition_owner` 는 `buys_v2_research`(= v2 만)를 봐서 **v2_chunk 에선 중앙
    CP 가 있어도 야외가 다시 샀다**. 두 자리가 이 함수 하나를 부른다 — 여기를 고치면
    양쪽이 같이 움직인다. `buys_v2_research` 와 `uses_chunk_producer` 는 서로
    배타적이라 합은 곧 「중앙 조사 스텝이 도는 판인가」다.
    )r/   r1   r-   s    r'   buys_referencer3      s     D!>%8%>>r)   c                    | yt        |       j                         j                         }|t        vrt	        dd| dd      t        |      r|S dS )u)  지문에 접을 **값**. 안 접을 때는 ``None``.

    ★key 째로 빼면 안 된다 (Codex BLOCK). ``v2`` 는
    ``touches_production_fingerprint`` 가 True 인데 key 를 빼면 v2 도 숨겨져
    **legacy 완료 CP 가 v2 진입에서 그대로 재사용된다.**

    ★「revision/content hash 가 대신 stale 을 잡는다」는 전제는 **아직 구현이 없다** —
    저장소 전체에 그 값을 만드는 production 코드가 0건이다. 구현되고 모든 하류
    step-local 지문이 그것을 소비하는 끝점 시험이 생긴 **뒤에야** 이 값을 뺄지
    다시 본다.

    ```
    없음 == legacy == shadow_plan   → None (안 접는다)
    v2                              → "v2"       (접는다)
    v2_chunk                        → "v2_chunk" (접는다)
    ```

    ★`v2` 와 `v2_chunk` 는 **다른 값**이어야 한다. 같은 값으로 접으면 모드를
    바꿔도 지문이 안 움직여 **하류가 옛 산출을 그대로 재사용한다** — 켰는데
    아무것도 안 바뀐다.
    Nr   r   r+   r   r   )r    r!   r"   r   r   touches_production_fingerprint)r.   r&   s     r'   fingerprint_valuer6      sc    , |IOO##%EK )%dX-BC
 	

 3595CtCr)   c                F    | t         vrt        dd| dd      | t        v S )uO   이 모드가 **아무 조사도 안 사는가.** ``shadow_plan`` 만 True 다.r   r   r+   r   r   )r   r   r   r-   s    r'   buys_no_research_at_allr8      s8    ?")%dX-BC
 	

 +++r)   c                R    | t         vrt        dd| dd      | t        t        fv S )u   이 모드가 **production 지문을 움직이는가.**

    ★``shadow_plan`` 은 False 다. 무료 관찰이 하류를 stale 시키면 안 된다.
    ★``v2_chunk`` 도 True 지만 **D 전에는 받는 값이 아니라** 실제로 못 온다.
    r   r   r+   r   r   )r   r   r,   GROUNDING_MODE_V2_CHUNKr-   s    r'   r5   r5      s@     ;)%dX-BC
 	

 %'>???r)   )N)r$   zOptional[Mapping[str, Any]]returnr    )r.   r    r;   bool)r.   Optional[str]r;   r=   )__doc__
__future__r   r   typingr   r   r   app.core.errorsr   GROUNDING_MODE_LEGACYGROUNDING_MODE_SHADOW_PLANr,   r:   	frozensetr   __annotations__r   r   r   r   r   r   r(   r/   r1   r3   r6   r8   r5    r)   r'   <module>rG      s  " # 	 ) ) $  *   % " !*~ +"+57H 	- #  O+ ,, .=^ = (12I1J'K n K{* **.  ,56P5Q+R . R/1 11 37/:%(2
?"DJ,@r)   