## 2026-08-11 여섯 번째 세션 — `Slot:Single` 확정, Slot-in-Slot 중첩 확정, Length/Offset `recompute` off-by-one 버그 발견·수정 `Slot():Single(state, updateFn?)` 백로그(2026-08-09 여섯 번째 세션, "`State`가 offset을 못 받아서 위쪽 Slot의 offset/length를 써야 했다"는 동기)를 실제로 설계하다가, 더 큰 질문(Slot을 다른 Slot 안에 넣을 수 있는가)까지 라이브로 풀어낸 긴 세션. 다섯 갈래로 정리: **1. `Slot:Single(state, updateFn)` — `:List` 위의 순수 sugar로 확정.** `state`를 0/1개짜리 배열로 감싸(`:Compute`) `:List`에 위임, 고정 key(`true`)로 `prev` 재사용을 보장, `index`는 상수라 안 넘김. 원래 동기(offset 접근)를 이걸로 완전히 해결 — "offset을 얻으려고 컴포넌트가 Slot을 리턴하는" 우회가 필요 없어짐. `base/slot-plan.md` "`Slot:Single(...)`" 절. **2. Slot-in-Slot 중첩 확정 — 동기는 카테고리 헤더가 아니라 컴포넌트 결합의 균일성.** 사용자가 직접 짚은 진짜 이유: `SomeComponent(props)`가 `Instance`를 리턴하든 `Slot`(멀티루트 워크어라운드)을 리턴하든 `outerSlot:Add(result)`가 분기 없이 동작해야 함 — 지금까지 "요소 타입 제약"이 `Slot`을 암묵적으로 배제하고 있어서 정확히 이 케이스가 막혀 있었음. **핵심 발견 — 메커니즘은 그대로 재사용, 새 프리미티브 불필요:** `Dispatch.setLength`/`setOffsetSource`의 첫 인자(`inst`)가 물리 Instance일 필요가 없다는 것(`Relate`가 아무 테이블이나 weak 키로 받음)을 재사용해, **Slot 자신을 owner 키로 같은 두 함수를 한 번 더 부르면 최상위 마운트와 중첩 마운트가 완전히 같은 함수 호출**이 됨 — 재귀 `attachSlot(slot, physicalTarget, ownerKey, position)` 하나로 통합. `Slot.Length`는 raw 개수에서 "요소별 기여도의 합"(plain=1, nested Slot=그 `.Length`)으로 의미 변경. - **타입 레벨로 확장하려던 "모든 instance 처리를 Slot에 위임"은 기각** — 리터럴 배열(`Dispatch.drive`)의 요소 타입 규칙(Ref/PreRef/Observer 허용)이 Slot의 요소 타입 규칙(같은 값들 금지)과 정반대라, 타입을 진짜로 통합하면 "만들어진 방식에 따라 행동이 다른 Slot"이라는 숨은 분기가 생김 — **메커니즘(setLength/setOffsetSource/recompute)만 공유하고 타입/CRUD 표면은 분리 유지**로 스케일 확정(사용자 확인: "그게 더 엔지니어링 비용이 싸고 좋은 구현"). - **파괴는 재귀적 `Clear()`가 아니라 flat `destroySlotTree`** — 사용자가 직접 비용 문제 지적("clear된 다음 length 바뀌고 위치변경 전파되는 구조는 안 됨"): 재귀 `Clear()`(요소별 Remove 반복)는 죽는 서브트리 내부에서 불필요한 shift+recompute가 요소 수만큼 반복됨 — 대신 순수 파괴 walk(`.Destroy()`만)+`unbindLifetime` walk로 바꾸고, outer 쪽 recompute는 자기 위치 하나에 대해서만 1회. `unbindLifetime`이 왜 꼭 필요한지도 새로 드러남 — `bindLifetime`은 물리 target 생명주기에 걸려있어 target이 살아있는 채로 논리 서브트리만 죽는 경우(카테고리 삭제 등) GC가 자동으로 안 치워줌, 명시적 호출 필요(물리 target 자체가 죽는 경우는 기존처럼 GC가 전부 처리). - **`Slot(initial?: {T})` 생성자로 확장** — "인자 없는 빈 생성자로 확정"을 뒤집음(2026-08-09 세 번째 세션 결정 정정), 단 새 마운트 로직이 아니라 `:Add` 반복 호출 sugar(`ipairs`의 "첫 nil에서 멈춤" 동작이 "중간 nil UB, 그 뒤 무시"를 공짜로 구현). **`initial ~= nil`이면 빈 테이블이어도 즉시 `_crudUsed = true`**(사용자 지적: `Slot({})`은 상태상 `add():remove(1)`과 동일이라 결과가 비어있어도 "CRUD를 썼다"는 의도는 이미 커밋됨) — `Slot()`(진짜 `nil`)만 나중에 `:List`/`:Single` 설치 가능. **`_crudUsed` ↔ `_listed` 상호 배타 가드도 신설** — 기존엔 `:List` 설치 후 수동 CRUD만 막았지 반대(수동 CRUD 후 `:List` 설치)는 안 막아서, `:List`의 reconcile이 기존 요소를 모른 채 충돌하는 gap이 있었음(사용자 발견). - **DOM 백엔드가 nested Slot을 실제 `