# 현재 생활 관측 공급기

`masukja2/life_observer.py`는 입력이나 화면 캡처를 수행하지 않는다. 기본 `allow_process_read=False`이며 이 작업에서 실제 프로세스 접근·게임 입력·CLI 호출은 하지 않았다. 단위 검사는 합성 화면·가짜 읽기 세션·가짜 입력 영수증만 사용한다.

구현한 흐름은 다음과 같다.

1. 현재 캡처의 HUD 메뉴와 M 및 UI 비율 결과를 받는다. 아이템 공급 후보가 유일하거나 호출자가 명시적으로 고른 원본 후보에 대해서만 기존 생활 선택 tape를 준비한다. 이 단계에서 활동 조회·OCR·서버 잠금 확인을 추가하지 않는다.
2. 엔진이 보존한 전체 `sent_unconfirmed` 선택 tape 영수증을 확인한다. 각 입력의 종류·키·좌표·역할·창 영역을 원래 tape와 대조한다. 준비 상태·부분 전송·dry-run은 카드 소유권이 아니다.
3. 공통 `CurrentUILayoutSession`을 확장하여 현재 `UIInstanceService.handleTable`의 활성 `DetailCardUIInstance` 하나만 찾는다. `cardInfo`의 정확한 선언, 열림/닫힘/초기화/동작 상태, 읽기 중 변경을 확인한다. 메타데이터 해시는 기존 읽기 계획과 같아야 한다.
4. 기존 `prepared_requirement_locked`의 붉은 픽셀 비율 `.008`, RGB 조건 및 썸네일 제외 영역을 같은 제공 화면에 적용한다. 통상 입력에 OCR을 추가하지 않는다. 상세 부모는 기존 측정 보정값이라는 출처를 유지한다.
5. 소유한 가까운 위치 입력 영수증 이후에만 제공된 공식 `get_activity` 읽기를 사용한다. 누락한 불리언은 idle이 아니며, 입력 이후 서로 다른 시각의 두 idle 관측을 보존한다. 활동 중간에 busy가 보이면 연속 idle 근거를 지운다. 이 모듈은 중단 입력을 보내지 않는다.

연결 API:

```python
life = LifeObservationProvider(
    allow_process_read=False,
    pending_provider=lambda: engine.data.get("pending"),
    activity_reader=lambda: cli.query("get_activity"),
    cancelled=input_adapter.cancelled.is_set,
)
# 같은 run에서 인스턴스를 유지한다. GameObserver.life_provider=life.
# stop/foreign input/resume에서는 life.invalidate().
# 이미 열린 공통 세션은 __call__(..., session=current_life_session)로 주입 가능.
```

현재 원시 ID의 단일 `Int32` 값 형식은 정확한 런타임 형식 식별자가 일치할 때만 해석한다. 런타임 형식 표현이 다르면 정확한 읽기 공백을 보존한다. 앱의 `daily-001`과 클라이언트 `GatherableSheetId`의 정적 조인은 아직 없다. 따라서 경로 소유권은 미니27의 성공 계약인 **자신이 보낸 선택 tape·같은 창/캐릭터·중단되지 않은 관측기 수명**에 근거하며, 독립적인 원시 ID 일치를 꾸미지 않는다. 링크의 현재 enabled 필드도 직접 복원된 것이 아니라 그 계약을 따른다. 이러한 구분은 각 결과의 `detail.identity_binding`, `detail.link_binding`에 남는다.

미지원은 제작/가공 관측, 새 화면 비율의 완전한 선택 tape, 정적 원시 ID 조인, 독립적인 현재 링크 enabled/caption 연결, 무료 stop 실행 경로, 현재 `life.gather` 목표에서 원본 생활 route로 연결할 typed 바인딩이다. `inventory.hold`의 아이템 증가를 실제 채집 횟수로 바꾸지 않는다. 이 결과는 게임 성공이나 실검증 완료를 뜻하지 않는다.

`declarations.json`에는 현재 메타데이터의 6개 정확한 형식 선언과 원본/사본 해시가 있다. 기존 게임 원본을 다시 분석하지 않고 이미 확보한 메타데이터 사본을 읽었다. `snapshot_sources.py`는 오프라인 추출 도구이며 제품 실행 중 실행하지 않는다.
