"repository 를 여는 게 아냐. 거기서 나온 걸 여는 거지. 나오는 게 있다면."
멤버랑 surface 는 다른 물건이야
'가족이란 repo 목록이고, 실행이란 repo 를 여는 것' 이렇게 생각하기 쉬워. Firelink 는 그 지름길을 안 써. FamilyMember 는 repository 나 제품 정체성이야. 얘가 LaunchSurface 를 0개 이상 갖는데, surface 는 그 멤버가 실제로 내놓는 사용자용 물건이야. WebUI 나 네이티브 앱 같은 거. 런처는 그 surface 를 열지 repository 속을 열지 않아. 이름만 봐도 읽히지. Pippa 의 WebUI surface, Firekeeper 의 메뉴바 앱 surface, Ember 의 engine UI surface. repo 가 멤버고, 열리는 건 surface 야.
surface 가 아예 없는 멤버도 있어
이 구분은 가장자리에서 값을 해. 같이 쓰는 kit 이나 workshop repo 는 열 게 아무것도 없을 수 있거든. 다른 형제가 갖다 쓰는 라이브러리거나, 서버 없이 도는 배치 도구니까. 그래도 Firelink 는 그 멤버를 Web Hub 에 보여줘. 존재하고, Git 상태가 있고, 중요하니까. 대신 없는 실행 대상을 지어내진 않아. 눌러도 아무 일 없는 유령 'Open' 버튼은 안 만들어. surface 가 없으면 런처는 내놓을 게 없는 거고, 그게 정직한 답이야.
'열기'는 지금 어디 있는지를 본다
surface 가 URL 문자열이 아니라 진짜 물건이라서, 여는 방식도 상황을 봐. 같은 web surface 라도 사무실 loopback 에선 localhost 로, 같은 랜에선 LAN 주소로, tailnet 에선 Tailscale HTTPS 로 풀려. 어디서든 통한다고 우기는 'primary' URL 은 일부러 안 뒀어. 카드에 박힌 링크도 메인 Open 버튼이랑 똑같은 방식으로 주소를 골라. surface 는 주소 하나로 버티는 척하는 대신, 네가 어디 있든 거기서 어떻게 닿는지를 알고 있어.