quad/.claude/session/2026-08-28-02-claim-promotion.md
qwreey 253d141096
qa: Claim 갈래 8건 확정 — research/existing-mount-plan → base/claim-plan.md 승격, 루트 .Parent= 밖에서 허용 복원
- 루트 키 센티널(맨 테이블+Claim<<T>> 기각), type <Class>Param 필드 파트 공유, Claim 타입 인자 없음
- 디스크립터 순서 정본 / claim된 부모 안 New 자식 허용(위치는 프로바이더 몫) / 이름 Claim·D.Mapper
- §5-7: Claim은 1회·전체 소유, H-146 루트 .Parent= 예외를 좁혀 복원(H-148 폐기 → 같은 날 복원)
- debug 검사 범위는 research/debug-tooling-plan.md로 이관, nativeFindChild 주입 op 등록
- 감사 8라운드 수렴(2→3→1→3→2→0→4→0) + /code-review high 10건 반영 — 새 메커니즘 넷은
  base/claim-plan.md §10 + question.md "M5 착수 전" 절로(gcconn/gchold 셋업 자리 /
  이중 claim 레지스트리 / PlayerGui own-all vs ResetOnSpawn / <Class>Param 배열 파트)

Co-authored-by: qwreey <me@qwreey.moe>
Claude-Session: https://claude.ai/code/session_01546hjsYNLSMZdHdPyTZaGb
2026-08-28 17:23:30 +09:00

135 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 2026-08-28 (02) — `Claim` 갈래 확정, `research/`에서 `base/claim-plan.md`로 승격
> 이 파일은 **원문 기록**이다(시행착오 포함). 지금 유효한 설계는 `base/claim-plan.md`.
> 앞 세션 `session/2026-08-28-01-handtrace-round10-resolution.md`가 만든 research
> 문서(옛 `existing-mount-plan`) §5 갈래 여덟을 사용자와 대화형으로 닫은 기록.
## 경위
10라운드 후속 2까지 커밋(`f020f3f`)한 뒤 사용자가 *"`research/existing-mount-plan.md`
관해서 다뤄보자. 우선 5. 미결을 보자"*로 이어갔다. 사용자가 항목 1~5를 먼저 적어
보냈고("내가 적어둔걸 볼래?"), 에이전트가 사실 셋을 확인한 뒤 의견과 함께 답이
없던 §5-7·§5-8을 되물었다. 사용자가 둘을 답해 전량 확정.
## 사용자 원문 (1차 메시지)
> 1. 의 권고 b는 문제가 생겨. 루트에 대해서 {} 안의 타입체크와 타입 자동완성이
> 전혀 안 먹음. 내 생각에는 D.Frame 의 함수의 부분들을 type FrameParam = {}
> 형태로 빼서 공유되는 타입 부분으로 D.Mapper.Frame 도 구성되고, 리턴부분만
> 다르게 될것 같아. Claim 자체는 타입을 받는건 말이 안되어보임. New 와는 완전
> 다른 계열이라서: New 는 후행 입력에 대한 타입을 선언시키는 D 계열이지만,
> Claim 은 공유 부분이고 말한것 처럼 엔진 요소를 알 수 없어. a 가 가장 정확한
> 구현으로 보임.
> 2. 나는 처음에 A 를 생각했어. 권고 그대로 가줘.
> 3. 그런데 호출 순서가 달라진다는 문제가 있긴함. D.Mapper 의 프레임이 전부
> 구워지는 도중에 생기고 각각 claim 매핑 되기 전에 New 가 호출됨. 새로 붙임
> 자체는 한 배열에 섞이는게 문제는 없어보여. 그 경우에서도 순차 마운트 Add 는
> 작동할것이거든. 대신 Add 가 위치를 진짜 실어서 보내지 않으면 맨 뒤에
> 놓인다는게 문제일 뿐.
> 4. 는 디버깅 도구 만들 때 고려해야할 점으로 옮겨져야해. 부분 부분 디버깅
> 가능성을 아직 다 논한게 없어서 지금 그림으로 보면 작은 그림을 먼저
> 그리는거라서, 미결상황으로, 위치 이동이 필요함
> 5. 표면 이름은 Claim 이 가장 마음에 들어. D.Mapper 가 이미 있는걸 매핑해서
> 내가 가진다는 의미적으로 가장 맞고.
> 승격은 지금도 가능해보임. 간단한 레이어라서.
## 에이전트가 확인한 사실과 되물은 것
- `D.Frame = New<<Frame>> "Frame" :: (({ ...타입명시 }) -> Frame)` — props 타입이
캐스트 안 인라인이고 `D` 전체가 생성기 산출물(`base/bind-system-plan.md`) →
`type FrameParam` 공유는 생성기 한 줄. `InstanceChildHandler``v.Parent = inst`이고
`H-154` 문단이 이미 "같은 값, 엔진 no-op"을 전제 → §5-8 근거. `nativeInsert`
Roblox가 offset을 무시(`architecture.md`) → §5-3의 위치 문제는 web 프로바이더 요구사항.
- 제안 둘(사용자 거부 없음, 결정은 아님으로 표시): 센티널을 `D.Mapper.Root`
두기 / `Claim<T>(inst: T, desc: MapperDescriptor<T>): T` **추론**(타입 인자 없음은
사용자 결정).
- **§5-7 문항을 다시 세움** — "여러 quad 인스턴스"가 아니라 **한 quad·여러
스크립트**(같은 `quad` 모듈 require)가 흔한 경우라 이중 claim error가 그 사례를
막는 게 진짜 문제. 갈래 (α) `Claim`은 전체 소유만, 루트 `.Parent =`는 밖에서
(`H-146` 복원, 새 메커니즘 0) [권고] / (β) 다중 claim·부분 소유(web에서 offset이
남의 자식을 못 봄) / (γ) 별도 표면(`H-146` 인용문이 반대한 것).
## 사용자 원문 (2차 메시지) — §5-7·§5-8
> 5-8 확인완료. 5-7 에서는 정확히는 두번 Claim 불가하다는 의미. 필요하다면
> Slot 을 안에 만들고 리턴하는 중간 모듈을 만들어야함. 밖에서 .Parent 설정하는건
> 괜찮아. 루트도 quad 소유이긴 한데, .Parent 를 밖에서 설정하는건 괜찮음.
> 정확히는 ScreenGUI 가 이미 존재해도 똑같음.
읽기: (α) 채택. `Claim`은 같은 `inst`에 1회, 소유는 전체. 루트의 `Parent`
**만든 방법과 무관하게**(`New`든 `Claim`한 기존 `ScreenGui`든) 부기 밖이라 밖에서
대입 허용 — `H-146`의 예외가 좁혀서(그리고 `Claim`한 루트까지 넓혀서) 복원됐다.
PlayerGui 직하 Slot을 여러 스크립트가 공유하려면 `Claim` 한 번 + Slot 반환 중간 모듈.
## 반영
`git mv research/existing-mount-plan.md base/claim-plan.md` 후 전면 재작성(§7 결정
기록, §8 안 만들기로 한 것, §9 구현 체크리스트·문서화 대상). 포인터 갱신:
`bind-system-plan.md` `H-146` 배너("폐기" → "좁혀서 복원") / `slot-plan.md` 두 곳 /
`architecture.md` 주입 op 목록에 `nativeFindChild`(조합 폴백 예외) / `ROADMAP.md`
M2 배너·M5 두 체크박스 / `question.md` 최우선 절 비움 + `archive/question-resolved.md`
절 / `debug-tooling-plan.md` "열린 질문"에 검사 범위 이관 / `documentation-content-map.md`
§4 21번 / `README.md` 행 이동 / `CLAUDE.md`·`todos.md`·`project-context.md` /
`-round10-followup.md` 후속 3 절. 코퍼스의 옛 경로는 새 경로로 일괄 치환(히스토리
문서 포함 — 파일 참조가 깨지지 않게).
## 옛 §5 원문 (승격 직전 커밋 `f020f3f`의 `research/existing-mount-plan.md` §5 — 갈래 a/b/c 선택지 전문)
1. **루트 디스크립터의 이름** — 루트는 `Claim``inst`를 직접 받으니 매칭 키가
필요 없다. 사용자: *"최상위는 이름을 뭐로 둬야할지 아직 모르겠음. 비워두는걸
D.Mapper.Frame{} 으로 제공하는건 더 나빠보이는데. 아니면 테이블로써
MapperRoot = {} Mapper.Frame (MapperRoot) {} 모양이 되어도 될것같음."*
갈래: (a) 센티널 `MapperRoot`(`M.Frame(MapperRoot) {…}`) / (b) 루트는
`Claim(inst, { … })`처럼 클래스 없는 맨 테이블(클래스는 `inst`가 이미 안다)
/ (c) 이름을 받되 무시. **권고 (b)** — 루트 클래스를 두 번 말하지 않고,
`M.<Class>`는 "찾아야 하는 자식"에만 쓰여 뜻이 하나가 된다. 단 타입(`D`
생성기가 만든 props 타입)을 잃으므로 `Claim<<"Frame">>(inst, {…})`처럼
타입 인자로 보완 — `New<<X>>`와 같은 관용구.
2. **물리 순서 계약** — 디스크립터 배열 순서와 기존 트리의 실제 순서가 다를 때.
Roblox는 물리 순서가 의미 없어 무관, web은 DOM 순서라 `nativeInsert` 위치가
어긋난다. 갈래: (a) 디스크립터 순서가 정본이고 일치는 사용자 책임(UB,
debug 검사) / (b) claim 시 quad가 `nativeMove`로 실제 순서를 디스크립터에
맞춘다. **권고 (a)** — "이미 있는 걸 그대로"의 취지, Roblox에선 비용 0.
3. **`New`로 만든 자식을 claim된 부모에 넣는 것** — 위 §4 첫 항목. 정적 자식이니
`InstanceChildHandler``Parent =`를 하면 되고 새 결정은 없어 보이나,
"매핑(이미 있음)"과 "생성(새로 붙임)"이 한 배열에 섞이는 것이 계약상
괜찮은지 확인 문항.
4. **debug 검사의 범위** — 이름 중복 / 부재 / 클래스 불일치 / 미매핑 부기
대상 자식 / 같은 quad의 이중 claim 중 어디까지. 권고: 전부(debug에선 싸다).
5. **표면 이름**`Claim`/`Mount`/`Adopt`, `D.Mapper`/`D.Existing`.
`Mount(root, parent)``H-146`에서 기각한 사유("부기 없는 대상에 quad 객체
주입")는 여기 반대로 적용된다 — claim은 부기를 *세우는* 행위. 권고 `Claim`.
6. **마일스톤** — M5 이후(`nativeFindChild`가 프로바이더 표면). `ROADMAP.md`
백로그에 포인터만. **[2026-08-28 `/code-review`, `H-161`]** 단 `H-146` 루트
예외를 폐기한 지금 **M5에 승인된 루트 부착 경로가 없다** — (a) `Claim`을 M5
스코프로 당김 / (b) `Claim` 전까지 M5 한정 임시 예외 / (c) 루트 컨테이너용
얇은 표면. **사용자 확정 (a)**(*"M5 스코프로 올라가도 될것으로 보임"*) — 헤더와
`ROADMAP.md` M5 체크박스에 반영. §5-7(다중 스크립트)은 여전히 미결.
7. **[2026-08-28 `/code-review`, `H-161`] 여러 스크립트/여러 quad가 같은 루트
컨테이너를 쓰는 경우** — 위 "이중 claim error / 다중 quad UB / 부기 대상 자식
전부 매핑"을 그대로 두면 `Shop.client.luau``Inventory.client.luau`가 각각
`Claim(PlayerGui, …)`하는 **가장 흔한 사례가 막힌다**. 이건 "전부 매핑" 계약이
**루트 컨테이너**(부기 대상이 아닌 `PlayerGui`·`CoreGui`류 — 자식 순서가
의미 없고 quad가 그 형제들을 관리하지 않는다)에는 안 맞는다는 신호다. 갈래:
(a) `Claim`은 **부기를 갖는 노드**에만, 루트 컨테이너엔 "quad가 만든 자식
하나를 붙이는" 별개 표면(부기 없음, 여러 스크립트 공존, 이름은 §5-5와 같이) /
(b) `Claim`에 "이 노드의 다른 자식은 관리하지 않는다"(부분 매핑) 모드 — 단
web처럼 물리 순서가 의미 있는 엔진에선 위험 / (c) 다중 claim을 허용하되 각
claim이 자기가 매핑한 자식만 소유(UB 대신 정의) — 부기 충돌 없음이 조건.
**권고 없음** — (a)는 `H-146`에서 기각한 `Mount(root, parent)`의 재개방과
경계가 얇고, (b)(c)는 계약을 약화시킨다. 사용자 판단.
8. **매핑된 정적 자식의 `Parent` 대입** — §2는 "부기만, `.Parent =`는 안 한다"인데
`InstanceChildHandler``v.Parent = inst`가 계약(`dispatch-core-plan.md`
`H-134`). 같은 핸들러를 쓰면 이미 거기 있는 자식에 같은 값을 재대입(엔진
no-op)하는 것뿐이라 별도 핸들러가 필요 없어 보인다 — 확인 문항(권고: 같은
핸들러, 재대입 감수).
## 승격 뒤 `/code-review high` (2026-08-28)
감사 6라운드 수렴 뒤 돌린 리뷰가 10건을 냈다. 서술·라벨·stale 여섯은 반영, **새
메커니즘이 필요한 넷**(gcconn/gchold 셋업 자리 / 이중 claim 레지스트리 / `PlayerGui`
own-all vs `ResetOnSpawn` / 공유 `Param` 배열 파트)은 `base/claim-plan.md` §10과
`question.md`에 문항으로 — 사용자 결정 대기. 리뷰가 제안한 이름(`nativeAdopt`,
`FrameParam<C>`)은 전부 가칭.