# 생활 제작·가공 재사용 조사

2026-10-09, 기존 소스를 읽어 별도 복사한 조사 자료다. 이 폴더의 코드는 실행하지 않았다. 원본 수정, 게임 입력, 화면 캡처, 포커스 전환, 인증 생성은 하지 않았다. 원본/사본 해시와 복사 시각은 `manifest.json`, `geometry-manifest.json`, `resource-manifest.json`에 있다. 이전 코드의 완료 표기·관측 표시는 역사 자료이며 dev.2의 현재 검증 완료를 뜻하지 않는다.

현재 CLI 연결 검사는 `../../analysis/live-io/readonly-probe-original-cli.json`에 있다. 설치된 CLI의 status/capabilities는 `pipe=disconnected, reason=game_off`였다. 이는 이 실행 환경에서 읽지 못했다는 근거다. 따라서 아래 필드는 기존 소비 코드의 계약이며 이번에 성공한 실시간 응답 스키마로 표시하면 안 된다.

## 결론과 정확한 진입점

| 능력 | 확인한 재사용 경로 | 현재 한계 |
|---|---|---|
| life.alter | `SourceLife.visit(recipe)` → `select(recipe)` → `tape_target('register')`; `MultiProcessingPort.register/collect/finish_collection` | 현재 시설/레시피/활성 목록 순서/스크롤/레벨/작업 상태가 필요하다. 카탈로그 존재만으로 입력 가능하지 않다. |
| life.craft | `SourceTravelSnack._open_recipe/_set_batch_count/craft_target/result_target`, `TravelSnack.craft` | 확인된 UI 구현은 **여행자 간식** 전용이다. 임의 제작품에 적용할 일반 recipe UI 경로는 이 자료에서 확인하지 못했다. |
| 공식 CLI | 읽기 `get_craftable_items/get_alterable_items/get_altering_works/get_items/get_activity` 소비 코드 | 현재 연결 성공 없음. 기존 유료 쓰기 `execute_crafting/execute_altering`는 이 작업의 실행 경로로 채택하지 않는다. |

`SourceLife`의 정확한 메서드명은 **visit(recipe)**다. `open(group)` 또는 `open(recipe)`가 아니다. `recipe`는 최소 `id/name/group/materials`를 갖는 정확한 카탈로그 항목이며 산출량은 `output_per_batch`다. mini27 카탈로그에는 6시설·91레시피가 있으나 현재 잠금 해제·재료·UI 순서·작업 슬롯을 의미하지 않는다.

## 가공 입력 순서와 효과 경계

1. 현재 소유한 field/facilities/remote/local 상태를 확인한다. local_detail/remote_detail/slot_detail이면 해당 소유 상세만 닫는다. 기존 `SourceLife.visit`는 field에서 K → `processing.tab.Altering` → 시설 선택을 하나의 준비된 순서로 보낸다. 원본의 반복 focus 및 `timeout=600` 같은 정책을 dev.2에 복사할 근거는 아니다.
2. 시설 선택 직후 remote/local 경계에서 관측한다. remote면 `processing.facility.travel`을 선택하고 현장 local 도착을 기다린다. 등록 버튼을 이동 버튼으로 사용하지 않는다. 여행 확인은 정확히 소유한 시설 이동 질문에서만 가능하다.
3. 현재 시설 목록의 정확한 recipe를 선택한 후 `processing.register`를 누른다. 등록 전 durable intent에 recipe/facility/before_works/count를 저장한다. 정상 준비된 배치 중에는 입력마다 OCR/CLI를 추가하지 않는다.
4. `MultiProcessingPort._register_current`는 요청 수, 현재 빈 슬롯, 실제 재료 가능 수 중 최솟값만 등록한다. 가방 재료가 없어 보관함 전송이 필요한 경우 한 번 등록한 뒤 해당 popup만 관측·처리한다. 현 사용자 범위의 보관함 사용·비용 승인은 별도 조건이며 예전 허용 정책을 자동 승계하지 않는다.
5. 배치 후 `get_altering_works` 목록 변화로 등록 효과를 확인한다. 불확실하면 등록을 재전송하지 않는다. 슬롯 등록은 생산 완료가 아니다.
6. 수령은 기본 모든 대상 작업 완료 시 `processing.collect_all` → 원본 규칙 `processing.collect.confirm_interval_seconds`(기본 1.5초, 실제 첫 press 시각 기준) → `processing.result.confirm`이다. 이 간격은 입력 순서의 일부이며 목표 시간초과가 아니다. 중단은 항상 가능해야 한다.
7. 수령 후 works multiset 차이로 제거 작업을 확인한다. durable 수령 기록이 이미 확인된 경우 `finish_collection`은 남은 결과창만 닫고 collect를 반복하지 않는다. 실제 최종 소지품 목표는 inventory의 정확한 수량으로 별도 확인한다.

근거: `mini27/source_life_port.py:283,326,396,404,435`, `multi_processing_port.py:1264,1296,1383,1449`, `automation.py:1039`.

## 순수 좌표 공급 API와 필요한 상태

```python
resolve_life_scene(context: CanvasContext, scene: str, *,
                   state: Mapping, processing_rules=None, result_rules=None)
```

구현: `mini27/source_life_routes.py:732`. 반환값은 role별 `LifeRouteGeometry(rect, ocr_rect, visible, enabled, metadata, visible_rect)`다. 물리 클라이언트 좌표이며 스크린 원점은 최종 IO에서 한 번만 적용한다. `Rect.bounds`는 **left, top, right, bottom**이다. dev.2 `InputCommand.safe_rect`의 **left, top, width, height**와 혼용하지 않는다. `visible/enabled`는 수식상 선언이며 현재 화면의 활성 상태나 입력 권한을 증명하지 않는다.

공통: 현재 CanvasContext(실제 viewport/UI scale/orientation/safe area), 정확한 scene 소유권, window/process/session identity, 관측 출처·시각을 붙인다. 선택적 `parent_rect`, `safe_area`, `content_parent`는 해당 모듈의 `Rect`이며 client 안의 계산된 부모다. 관측 문자열의 OCR box를 입력 좌표로 승격하지 않는다.

| scene → role | 필수 현재 상태 및 분기 |
|---|---|
| `processing.tabs` → `processing.tab.<ID>` | 현재 `ordered_ids`. 기존 호출의 QuickCrafting/Altering/SkillCrafting/Alchemy 순서는 명시된 초기 후보이며 현재 활성 배열의 증거가 아니다. |
| `processing.facilities` → `processing.facility.<ID>` | `ordered_ids`, 물리 `scroll_x`, `scroll_y`; 선택적 resolved `parent_rect`, `safe_area`. 카탈로그 순서 가정은 metadata에 남는다. |
| `processing.recipes` → `processing.recipe.<ID>` | 위 목록 필드 + `facility_id`, bool `subtract_padding`. 부모가 없으면 landscape는 category_bottom(911에서 safe.top+158*scale 유도 가능), portrait는 topinfo_bottom 또는 실제 `queue_count/move_visible/upgrade_visible`와 선택적 `description_height`가 필요하다. |
| 위 목록의 `.scroll` | `focus_id`, `scroll_phase`(reset/seek), `reset_remaining_notches`를 순수 공급기로 전달. 반환 `next_wheel_delta/next_scroll_y/next_scroll_phase`를 사용. wheel 입력은 최대 5개의 개별 notch로 처리하며 wheel delta를 scroll offset으로 해석하지 않는다. |
| `processing.facility.travel` → 같은 role | `facility_id`, `remote=True`, `move_visible=True`, 명시적 bool `upgrade_visible`. 소스 범위 내 안전한 버튼 내부를 계산하며 글꼴 폭을 임의 고정하지 않는다. |
| `processing.travel.confirm` → 같은 role | `facility_id`, `owned_travel_request/question_confirmed/settled=True`, `popup_position=bottom`. center 부모는 미지원. 기본 bottom은 원본에서도 후보 가정이다. |
| `processing.register` → 같은 role | `facility_id`, `recipe_id`, `local_detail/register_enabled/settled=True`, 물리 `scroll_y`. `content_fits` 또는 계산된 `content_bottom`으로 실제 popup content 분기를 공급한다. 누락 시 fitting-content 후보 가정이 생긴다. |
| `processing.storage_confirm` → 같은 role | `facility_id/recipe_id`, `owned_registration/storage_required/popup_visible/settled=True`. 현재 정확한 보관함 재료 전송 질문, 비용 정책을 별도 확인. 일반 확인/구매/취소 버튼으로 사용 불가. |
| `processing.collect` → `processing.collect_all` | 실제 `queue_count`, `facility_ready/full_safe_area/collect_enabled`; portrait 추가 `move_visible=False`, `upgrade_visible`, 선택적 `description_height`. landscape는 Screen left/right/bottom 보존 필수. |
| `processing.result` → `processing.result.confirm` | 현재 `settled` bool; 선택적 `safe_area` 또는 이미 패딩된 `content_parent`(동시 불가). facility result family만 해당. |

`candidate_assumptions`, `anchor_candidate_assumptions`, `order_basis`, `branch_basis`, `runtime_click_approved=False`를 삭제하거나 검증 완료로 바꾸지 않는다. 정확한 현재 분기 없이는 계산 후보의 입력 연결을 주장할 수 없다. 수식 파일만 직접 가져오려면 `ui_layout`, list/menu/result layouts, `ui_rule_engine` 등의 정적 의존을 새 프로젝트 안에 묶고 리소스 경로를 dev.2 안으로 바꿔야 한다. 원본 `paths.py`/install_dir에 런타임 의존하지 않는다. 이 폴더 자체는 실행 패키지가 아니다.

## 시설 슬롯과 관측 스키마

`resources/processing-facility-capacity.json`: metal/wood/leather/cloth/medicine/food 각각 현재 레벨 1..6 → 슬롯 2..7. 원본 FacilityTypeSheet Level/SlotCapacity 출처와 row SHA가 포함된다. `slot_capacity(group, observed_level)`는 정확한 표 값만 반환한다. 알 수 없는 레벨에 기본 7·외삽·반올림을 적용하지 않는다. `queue_count`는 **빈 슬롯까지 포함한 생성 슬롯 수**이며 `len(works)`가 아니다. 현재 레벨은 기존 `facility_capacity`에서 소스 계산 heading ROI를 관측해 얻었다. 신뢰 가능한 현재 level 관측이 필요하다.

기존 작업 응답: `{works: [...], completedCount: int}`. 각 row `DisplayName`, `FacilityName`, `State`(NotStarted/InProgress/Completed), `IsCompleted` bool, `RemainingSeconds` finite >=0. 완료는 State/IsCompleted 일치, 남은 시간 0을 요구한다. API에 없는 안정적 slot ID를 만들지 않는다. 동일 이름 작업 구분은 multiset 수준이며 혼동은 미확인이다. `main/connector_works.py`의 facility_works는 정확한 이름 후보가 여러 시설과 겹치면 거부한다.

기존 품목 응답: `{items:[...]}` 또는 일부 read의 배열. 소비 대상 row는 정확한 `DisplayName`, `Category`, `Location`, `Count`(int>=0), `IsLocked` bool을 요구한다. 같은 이름의 Category가 여러 개면 합산하지 않는다. `MultiProcessingPort._materials`는 inventory/character_storage/account_storage의 잠기지 않은 항목을 다뤘다. dev.2는 사용자 보존수량·위치별 사용 허용을 유지해야 한다. 데이터 없는 품목을 0개로 간주하지 않는다.

제작 읽기: `get_craftable_items`는 `{craftingUnlocked: bool, items:[...]}` 중 정확한 DisplayName의 `Craftable=True`를 기존 간식 코드가 검사한다. 가공 읽기: `get_alterable_items`의 정확한 DisplayName 재료 변형과 `ProducedPerWork`가 recipe output과 일치하는지 기존 본버전 코드가 확인한다. metadata의 가능 flag만으로 현장 재료나 빈 슬롯을 인정하지 않는다.

## 제작 특례와 미지원 영역

`mini27/snack.py:18`의 SNACK은 `여행자 간식`, MATERIALS는 `달걀`, `고기`이며 BATCH=10이다. 기존 순서는 K → snack.tab → snack.food → snack.recipe → count 선택 → 검증된 숫자 입력 → blur → craft → 결과 확인이다. 소비 입력 직전 pending 기록을 저장하고 수량 증가 또는 해당 소유 결과로 효과를 확인한다. 취소나 불명확한 응답으로 pending을 지우지 않는다.

숫자 입력 `snack_text`는 별도의 기존 입력 연산이다. 이를 일반 문자열 입력 API가 이미 구현된 것으로 간주하면 안 된다. 또한 `source_life_routes._MISSING_ROLES`에는 별도 snack.result caller/parent 결합이 명시되어 있다. 소스 결과 수식의 facility family를 임의 제작 결과에 재사용하지 않는다. 임의 퀘스트 제작품의 메뉴 분기·목록 순서·레시피·수량·결과 UI를 지원하려면 해당 클라이언트 정의와 현재 상태를 추가로 연결해야 한다.

본버전 `ConnectorPort.perform`에는 기존 쓰기 스키마 `execute_crafting({displayName, craftCount})`, `execute_altering({displayName})`가 있으며 실행은 유료 행동 설정에 종속한다. 이번 dev.2에는 이 쓰기 경로를 연결하지 않는다. 특히 `execute_altering`의 `result=started`는 등록이며 생산/수령 완료가 아니다.

## 이번 조사 검증

- 3개 manifest에 기록된 원본/복사 해시를 확인하고 각 복사 전후 원본 불변을 확인했다.
- Python 파일은 AST로 함수명/문법만 검사했다. 기존 모듈 import·실행은 하지 않았다.
- IO 모의 검사는 별도 `analysis/live-io/verification.json`, `unit-tests.log`에 있다. 실제 게임 실행 검증과 분리한다.
- 현재 라이브 CLI/화면 의미 관측은 이 조사에서 새로 확보하지 않았다. 기존 성공 보고나 카탈로그 상태값을 현재 효과 증거로 가져오지 않는다.
