tooling: 핸드오버 준비 — session-summary.md 색인 공백 + ROADMAP/CLAUDE.md stale 정정

session-summary.md에 오늘 세션 04~08 색인 항목이 통째로 빠져 있던 걸 발견해
신설. 더 크게는 CLAUDE.md/project-context.md/ROADMAP.md가 "구현 아직 시작
전"이라는 낡은 전제를 깔고 있었는데, 실측해보니 M0 스파이크 4개와 M1
스캐폴딩 대부분이 이미 완료돼 있어 전부 정정(ROADMAP 체크박스 갱신 포함,
wally.toml→pesde.toml 표기도 같이 정정). quad-roblox-types 백로그는
todos.md/ROADMAP.md M5에 짧은 포인터 보강.

Co-authored-by: qwreey <me@qwreey.moe>
This commit is contained in:
qwreey-agent-selene 2026-08-19 20:47:31 +09:00
parent 5dfc9b9a43
commit 871c582771
No known key found for this signature in database
7 changed files with 229 additions and 34 deletions

View file

@ -26,7 +26,7 @@
| `research/` | 아직 착수 전, 사용자와 스코프/설계를 더 상의해야 함 | | `research/` | 아직 착수 전, 사용자와 스코프/설계를 더 상의해야 함 |
| `qa-request/` | 원래 용도는 "구현 완료(코드/에이전트 검증까지 끝남) + 사용자 본인의 실기기(Roblox Studio) QA만 남음". **[2026-08-18 확장]** 구현 전에도 **사용자 심사 라운드의 산출물**을 여기 둠 — `pre-implementation-qa-round1.md`(1라운드: `base/` 확정 문서 전체를 문항으로 재확인받아 **"아니오"가 나온 항목만** 모은 결함 목록 + 신규 요구사항(`N-n`) + 부수 오탈자. **같은 날 전부 `base/`에 반영 완료**라 지금은 "무엇이 왜 틀렸었나"의 근거 기록이고, 지금 유효한 설계는 항상 `base/`가 소스. 아직 안 닫힌 것은 `question.md` 3번과 `.claude/todos.md` 00번이 소스), `pre-implementation-qa-round2.md`(2라운드: 확정 의사코드를 실제로 손으로 실행해보는 트레이싱 — **완료**, 발견된 크래시 `RC-1`(`recompute` 트리거 모델)도 같은 날 후속 세션에서 Blocker 게이팅 설계로 해결·반영까지 끝남, `archive/question-resolved.md`에 논의 요지 정리), `pre-implementation-qa-round3.md`(3라운드: `RC-1` 해법(Blocker 게이팅)이 실제로 `attachSlot`/`recompute`에 반영된 걸 손으로 트레이싱 — **완료**, `RC-3`/`RC-4`(`activateList`가 자기 Slot의 Blocker보다 먼저 실행되는 순서 문제)와 `bk.N` 수명주기 미정을 발견했다가 같은 세션에 사용자가 최초 분석 오류를 직접 정정하며 전부 해결·`base/` 반영까지 끝남, `archive/question-resolved.md`에 논의 요지 정리. `ROADMAP.md` M2가 M3의 `Blocker.luau`에 의존하게 된 마일스톤 순서 불일치는 각주로 반영, 마일스톤 재편 여부는 열려 있음). 다음 라운드가 필요해지면 라운드마다 파일을 새로 만들고 이름에 라운드 번호를 넣을 것 | | `qa-request/` | 원래 용도는 "구현 완료(코드/에이전트 검증까지 끝남) + 사용자 본인의 실기기(Roblox Studio) QA만 남음". **[2026-08-18 확장]** 구현 전에도 **사용자 심사 라운드의 산출물**을 여기 둠 — `pre-implementation-qa-round1.md`(1라운드: `base/` 확정 문서 전체를 문항으로 재확인받아 **"아니오"가 나온 항목만** 모은 결함 목록 + 신규 요구사항(`N-n`) + 부수 오탈자. **같은 날 전부 `base/`에 반영 완료**라 지금은 "무엇이 왜 틀렸었나"의 근거 기록이고, 지금 유효한 설계는 항상 `base/`가 소스. 아직 안 닫힌 것은 `question.md` 3번과 `.claude/todos.md` 00번이 소스), `pre-implementation-qa-round2.md`(2라운드: 확정 의사코드를 실제로 손으로 실행해보는 트레이싱 — **완료**, 발견된 크래시 `RC-1`(`recompute` 트리거 모델)도 같은 날 후속 세션에서 Blocker 게이팅 설계로 해결·반영까지 끝남, `archive/question-resolved.md`에 논의 요지 정리), `pre-implementation-qa-round3.md`(3라운드: `RC-1` 해법(Blocker 게이팅)이 실제로 `attachSlot`/`recompute`에 반영된 걸 손으로 트레이싱 — **완료**, `RC-3`/`RC-4`(`activateList`가 자기 Slot의 Blocker보다 먼저 실행되는 순서 문제)와 `bk.N` 수명주기 미정을 발견했다가 같은 세션에 사용자가 최초 분석 오류를 직접 정정하며 전부 해결·`base/` 반영까지 끝남, `archive/question-resolved.md`에 논의 요지 정리. `ROADMAP.md` M2가 M3의 `Blocker.luau`에 의존하게 된 마일스톤 순서 불일치는 각주로 반영, 마일스톤 재편 여부는 열려 있음). 다음 라운드가 필요해지면 라운드마다 파일을 새로 만들고 이름에 라운드 번호를 넣을 것 |
| `archive/` | 완료 + 사용자가 실사용/실기기로 직접 검증까지 마침 (구현 대상). **[2026-08-06 확장]** 완전히 뒤집힌 설계 결정을 원문+역전 이유+diff와 함께 보존하는 용도로도 사용(제목 `[역전됨]` — 한 번 확정했다가 뒤집힌 것) — 더 이상 능동적으로 참고 안 해도 되지만(토큰 낭비 방지 위해 `base/`/`research/`에서 뺌) `quadnomicon` 소재로는 나중에 쓸 수 있음. **[2026-08-07 확장]** 후보였다가 채택 안 된 것(확정한 적 없이 검토 후 기각)도 같은 방식으로 보존, 제목은 구분을 위해 `[기각됨]``[역전됨]`과 의미가 다르므로 혼동하지 말 것. **[2026-08-07 세 번째 확장]** 설계 반전/기각과 별개로, 에이전트가 문서 작성 중 스스로 낸 개념 혼동을 정정한 이력은 `[에이전트 실수]` 태그로 `agent-mistake.md` 하나에 모음(`.claude/session-summary.md`/`session/` 로그와의 중복 방지) | | `archive/` | 완료 + 사용자가 실사용/실기기로 직접 검증까지 마침 (구현 대상). **[2026-08-06 확장]** 완전히 뒤집힌 설계 결정을 원문+역전 이유+diff와 함께 보존하는 용도로도 사용(제목 `[역전됨]` — 한 번 확정했다가 뒤집힌 것) — 더 이상 능동적으로 참고 안 해도 되지만(토큰 낭비 방지 위해 `base/`/`research/`에서 뺌) `quadnomicon` 소재로는 나중에 쓸 수 있음. **[2026-08-07 확장]** 후보였다가 채택 안 된 것(확정한 적 없이 검토 후 기각)도 같은 방식으로 보존, 제목은 구분을 위해 `[기각됨]``[역전됨]`과 의미가 다르므로 혼동하지 말 것. **[2026-08-07 세 번째 확장]** 설계 반전/기각과 별개로, 에이전트가 문서 작성 중 스스로 낸 개념 혼동을 정정한 이력은 `[에이전트 실수]` 태그로 `agent-mistake.md` 하나에 모음(`.claude/session-summary.md`/`session/` 로그와의 중복 방지) |
| `feedback/` | 실사용 피드백을 정리한 긴 로그 — **[2026-08-16 기준] 폴더 자체가 아직 없음**(구현 시작 전, 첫 피드백이 생길 때 만들면 됨). `qa-request/`**[2026-08-18] 더 이상 비어 있지 않음**(구현 전 QA 1라운드 산출물이 들어감) — 여긴 아직 폴더도 없음 | | `feedback/` | 실사용 피드백을 정리한 긴 로그 — **[2026-08-19 기준] 폴더 자체가 아직 없음**(M0/M1 스캐폴딩만으론 안 생기고 실제로 렌더링해보고 쓰는 단계부터, 첫 피드백이 생길 때 만들면 됨). `qa-request/`**[2026-08-18] 더 이상 비어 있지 않음**(구현 전 QA 1라운드 산출물이 들어감) — 여긴 아직 폴더도 없음 |
| `luau-test/` | **[2026-08-09 신설]** `base/` 확정 사항 중 "추론만으로 확정하고 실제 Luau로 부딪혀본 적 없는 것"(M0 스파이크 대상)을 `luau`/`luau-analyze`/`luau-lsp`/Roblox Studio로 사용자가 직접 돌려볼 독립 실행 스크립트 모음. **[2026-08-13 여섯 번째 세션, 첫 실측]** `luau`/`luau-analyze` 바이너리가 생겨 처음으로 실제 실행 — **런타임 12개 전원 통과**, 타입 쪽에서 `:Compute(fn)` lazy 핸들 계약이 Luau 추론과 충돌하는 게 드러남(당시 `question.md` 0-Y). **[2026-08-13 열세 번째 세션]** 그 0-Y가 해소되며 `review-required/`**비었음** — 계약은 유지 확정, 남은 건 Luau 자체 한계라 `base/typing-limits.md`가 담당. **`STATUS.md`가 상태의 소스**(pass / 사람 결정 필요 / 스파이크 깨짐 / 미실행 분류 — 사람이 먼저 볼 것만 위에), `luau-test/README.md`는 각 파일의 검증 의도·배경, 실행 결과 상세는 `audit/luau-test-first-run-2026-08-13.md` | | `luau-test/` | **[2026-08-09 신설]** `base/` 확정 사항 중 "추론만으로 확정하고 실제 Luau로 부딪혀본 적 없는 것"(M0 스파이크 대상)을 `luau`/`luau-analyze`/`luau-lsp`/Roblox Studio로 사용자가 직접 돌려볼 독립 실행 스크립트 모음. **[2026-08-13 여섯 번째 세션, 첫 실측]** `luau`/`luau-analyze` 바이너리가 생겨 처음으로 실제 실행 — **런타임 12개 전원 통과**, 타입 쪽에서 `:Compute(fn)` lazy 핸들 계약이 Luau 추론과 충돌하는 게 드러남(당시 `question.md` 0-Y). **[2026-08-13 열세 번째 세션]** 그 0-Y가 해소되며 `review-required/`**비었음** — 계약은 유지 확정, 남은 건 Luau 자체 한계라 `base/typing-limits.md`가 담당. **`STATUS.md`가 상태의 소스**(pass / 사람 결정 필요 / 스파이크 깨짐 / 미실행 분류 — 사람이 먼저 볼 것만 위에), `luau-test/README.md`는 각 파일의 검증 의도·배경, 실행 결과 상세는 `audit/luau-test-first-run-2026-08-13.md` |
| `audit/` | **[2026-08-13 신설]** `luau-test/` 등 스파이크를 실제로 돌려본 뒤 "무엇이 확인됐고 무엇이 아직 안 됐는지"를 기록하는 곳 — 스크립트/계획 자체가 아니라 **실측 결과**만 다룸. base/luau-test와 달리 부분 확인(일부만 통과)도 있는 그대로 기록, 완전히 해소되면 관련 `base/`/`luau-test/README.md` 캐비엇을 지우고 이 문서는 근거로 남김. **개수는 폴더가 소스**(여기서 세지 않음): `luau-test-first-run-2026-08-13.md`(첫 실측 라운드 전체 — 런타임 12개 통과, 구 `question.md` 0-Y의 1차 근거. **단 이 문서의 "콜백이 raw 값을 받으면 완전 클린" 판정은 아래 `type-recursion-issue/`가 뒤집었음**), `gcconn-trick-verification.md`(사용자가 Studio에서 직접 돌린 gcconn 트릭 부분 확인 — `10`의 A 섹션 앞부분만. **[2026-08-14 다섯 번째 세션, 열한 번째 세션에 `canBound` 재도입 반영해 재갱신]** 실측된 사실 자체는 그대로 유효하고 `value` 단독 1-인자 재정정으로 오히려 더 중요해졌음 — 이중 바인딩 게이트(`canBound`)/emit 게이팅(`canExecute`)/재바인딩 허용/`value` 쪽 복사 gcconn 판정/Instance userdata 동일성/B/C가 미확인), **`type-recursion-issue/`**(**[2026-08-13 열세 번째 세션 신설]** 0-Y 재실측 전체 — `REPORT.md` + `spikes/`(개수는 폴더가 소스). 다른 audit 기록과 달리 **스크립트를 같이 둠**: 이 건의 근거가 "여러 formulation을 서로 대조한 것"이라 개별 파일을 직접 돌려야 판정이 재현되기 때문. 결론은 `base/typing-limits.md`로 승격됨), `fallback-xpcall-verification.md`(**[2026-08-14 신설]** `base/fallback-plan.md``Traceback` 메커니즘 전부 확인 — 클로저 업밸류 배선/중첩 스택 캡처/`err: any`/`error(msg)` 위치 접두 10개 검증 전부 통과. 스크립트 1개뿐이라 재현용으로 같이 둠: `fallback-xpcall-spike.luau`), **`type-recursive-issue-with-typeof/`**(**[2026-08-15 신설]** 사용자가 발견한 `typeof(named fn)` 간접참조가 0-Y(재귀 제네릭 반환 leak)를 실제로 우회하는지 실측 — `REPORT.md` + `spikes/`. 결론: 인라인 대신 이름 붙은 함수 + `typeof`로 선언하면 LHS 명시 없이도 다운스트림이 안전해짐(체이닝 50단·타입 변경·중첩 self 호출까지 확인), `typing-limits.md` §1 ③으로 승격. 부수적으로 `setmetatable` 확장 시도에서 quad와 무관한 Luau 0.733 솔버 버그(모순 진단 두 개 동시 발생) 발견, 채택 안 함. `luau-test/16`(type function으로 `Store<T>` 레코드 필드 합성) 복구도 이 조사 중 완료 — API 버전 드리프트였을 뿐 설계 문제 아니었음, `typing-limits.md` §5 승격), **`type-recursive-issue-try-callback/`**(**[2026-08-15 신설]** 콜백 파라미터 무주석 추론을 뚫을 방법이 정말 없는지 type function/메타테이블/오버로드/제네릭 디폴트 등 전방위로 재시도 — `REPORT.md` + `spikes/`(개수는 폴더가 소스 — 최초 라운드 + `/code-review high`가 이중 꺾쇠 명시적 제네릭 인스턴스화를 안 시도했음을 지적해 추가된 후속 조사 라운드로 구성). 결론: quad의 `state:Compute(fn)` 단일 호출 모양을 유지한 채로는 여전히 안 됨. 발견 셋 — (1) 근본 원인이 재귀 자기참조가 아니라 "제네릭 콜백 인자 전반에 컨텍스트 타입 전파가 안 됨"이라는 게 더 정확함(재귀 없는 최소 사례로도 재현), (2) `T`를 명시 중간 변수로 먼저 고정하거나 재사용 가능한 monomorphize 헬퍼를 거치면 실제로 추론이 살아나지만 둘 다 단일 콜론 호출을 2단계 체인으로 바꿔야만 해서 §0 대전제로 채택 안 함, (3) 이중 꺾쇠 명시 인스턴스화(`Compute<<T,U>>(fn)`)는 leaf 호출에선 sound하게 성립하지만(spurious 진단 원인도 규명 — read-only/read-write 가변성 불일치) 매 호출 T/U 전부 명시 필요 + 중첩 self 호출 여전히 실패라 순손해로 채택 안 함) | | `audit/` | **[2026-08-13 신설]** `luau-test/` 등 스파이크를 실제로 돌려본 뒤 "무엇이 확인됐고 무엇이 아직 안 됐는지"를 기록하는 곳 — 스크립트/계획 자체가 아니라 **실측 결과**만 다룸. base/luau-test와 달리 부분 확인(일부만 통과)도 있는 그대로 기록, 완전히 해소되면 관련 `base/`/`luau-test/README.md` 캐비엇을 지우고 이 문서는 근거로 남김. **개수는 폴더가 소스**(여기서 세지 않음): `luau-test-first-run-2026-08-13.md`(첫 실측 라운드 전체 — 런타임 12개 통과, 구 `question.md` 0-Y의 1차 근거. **단 이 문서의 "콜백이 raw 값을 받으면 완전 클린" 판정은 아래 `type-recursion-issue/`가 뒤집었음**), `gcconn-trick-verification.md`(사용자가 Studio에서 직접 돌린 gcconn 트릭 부분 확인 — `10`의 A 섹션 앞부분만. **[2026-08-14 다섯 번째 세션, 열한 번째 세션에 `canBound` 재도입 반영해 재갱신]** 실측된 사실 자체는 그대로 유효하고 `value` 단독 1-인자 재정정으로 오히려 더 중요해졌음 — 이중 바인딩 게이트(`canBound`)/emit 게이팅(`canExecute`)/재바인딩 허용/`value` 쪽 복사 gcconn 판정/Instance userdata 동일성/B/C가 미확인), **`type-recursion-issue/`**(**[2026-08-13 열세 번째 세션 신설]** 0-Y 재실측 전체 — `REPORT.md` + `spikes/`(개수는 폴더가 소스). 다른 audit 기록과 달리 **스크립트를 같이 둠**: 이 건의 근거가 "여러 formulation을 서로 대조한 것"이라 개별 파일을 직접 돌려야 판정이 재현되기 때문. 결론은 `base/typing-limits.md`로 승격됨), `fallback-xpcall-verification.md`(**[2026-08-14 신설]** `base/fallback-plan.md``Traceback` 메커니즘 전부 확인 — 클로저 업밸류 배선/중첩 스택 캡처/`err: any`/`error(msg)` 위치 접두 10개 검증 전부 통과. 스크립트 1개뿐이라 재현용으로 같이 둠: `fallback-xpcall-spike.luau`), **`type-recursive-issue-with-typeof/`**(**[2026-08-15 신설]** 사용자가 발견한 `typeof(named fn)` 간접참조가 0-Y(재귀 제네릭 반환 leak)를 실제로 우회하는지 실측 — `REPORT.md` + `spikes/`. 결론: 인라인 대신 이름 붙은 함수 + `typeof`로 선언하면 LHS 명시 없이도 다운스트림이 안전해짐(체이닝 50단·타입 변경·중첩 self 호출까지 확인), `typing-limits.md` §1 ③으로 승격. 부수적으로 `setmetatable` 확장 시도에서 quad와 무관한 Luau 0.733 솔버 버그(모순 진단 두 개 동시 발생) 발견, 채택 안 함. `luau-test/16`(type function으로 `Store<T>` 레코드 필드 합성) 복구도 이 조사 중 완료 — API 버전 드리프트였을 뿐 설계 문제 아니었음, `typing-limits.md` §5 승격), **`type-recursive-issue-try-callback/`**(**[2026-08-15 신설]** 콜백 파라미터 무주석 추론을 뚫을 방법이 정말 없는지 type function/메타테이블/오버로드/제네릭 디폴트 등 전방위로 재시도 — `REPORT.md` + `spikes/`(개수는 폴더가 소스 — 최초 라운드 + `/code-review high`가 이중 꺾쇠 명시적 제네릭 인스턴스화를 안 시도했음을 지적해 추가된 후속 조사 라운드로 구성). 결론: quad의 `state:Compute(fn)` 단일 호출 모양을 유지한 채로는 여전히 안 됨. 발견 셋 — (1) 근본 원인이 재귀 자기참조가 아니라 "제네릭 콜백 인자 전반에 컨텍스트 타입 전파가 안 됨"이라는 게 더 정확함(재귀 없는 최소 사례로도 재현), (2) `T`를 명시 중간 변수로 먼저 고정하거나 재사용 가능한 monomorphize 헬퍼를 거치면 실제로 추론이 살아나지만 둘 다 단일 콜론 호출을 2단계 체인으로 바꿔야만 해서 §0 대전제로 채택 안 함, (3) 이중 꺾쇠 명시 인스턴스화(`Compute<<T,U>>(fn)`)는 leaf 호출에선 sound하게 성립하지만(spurious 진단 원인도 규명 — read-only/read-write 가변성 불일치) 매 호출 T/U 전부 명시 필요 + 중첩 self 호출 여전히 실패라 순손해로 채택 안 함) |
| `tools/` | **[2026-08-13 신설, `session/2026-08-13-09-structure-and-guardrails.md`]** 코퍼스 기계 점검 — `doc-check.py`가 깨진 파일/절 참조, README 색인 누락, 날짜 없는 시한부 주장("아직 안 돌려봄" 등), 미반영 ⚠️ 배너를 한 번에 훑음. **[2026-08-16]** 절 참조는 WARN이 아니라 **ERROR** — 판정 규칙은 `conventions.md`의 "절 인용 규약"이 소스. **중대 변경 후 커밋 전에 돌릴 것**(`python3 .claude/tools/doc-check.py`) — 수동 감사에서 나온 발견의 대부분이 이 종류였고, 실제로 문서를 쪼개다 잘못 옮긴 참조를 이게 잡아냄. ERROR는 고치고 WARN은 판단 대상 | | `tools/` | **[2026-08-13 신설, `session/2026-08-13-09-structure-and-guardrails.md`]** 코퍼스 기계 점검 — `doc-check.py`가 깨진 파일/절 참조, README 색인 누락, 날짜 없는 시한부 주장("아직 안 돌려봄" 등), 미반영 ⚠️ 배너를 한 번에 훑음. **[2026-08-16]** 절 참조는 WARN이 아니라 **ERROR** — 판정 규칙은 `conventions.md`의 "절 인용 규약"이 소스. **중대 변경 후 커밋 전에 돌릴 것**(`python3 .claude/tools/doc-check.py`) — 수동 감사에서 나온 발견의 대부분이 이 종류였고, 실제로 문서를 쪼개다 잘못 옮긴 참조를 이게 잡아냄. ERROR는 고치고 WARN은 판단 대상 |

View file

@ -10,10 +10,13 @@ Roblox 엔진에서 동작하는 DOMless UI 렌더러 **quad**를 처음부터
지속 가능성 — 빠른 이터레이션보다 정확성/설계 정합성이 우선. 작업 기간은 지속 가능성 — 빠른 이터레이션보다 정확성/설계 정합성이 우선. 작업 기간은
길게 잡음. 길게 잡음.
**[2026-08-16 기준] 지금은 설계/계획 단계이고 구현은 아직 시작 전**(M0에 **[2026-08-19 기준] M0(스파이크 검증)/M1(스캐폴딩) 완료, M2(디스패치
착수하면 루트 `CLAUDE.md` 머리말도 같이 고칠 것 — 같은 상태를 두 곳이 엔진)부터 착수 예정**(마일스톤이 넘어갈 때 루트 `CLAUDE.md` 머리말도
서술하고 있음) — 저장소 루트에 실제 소스 같이 고칠 것 — 같은 상태를 두 곳이 서술하고 있음) — 저장소 루트에
코드(`src/` 등)가 없음. 핵심 아키텍처(Store 책임 분리, `process`/`retract` `quad-base/src/`(`New()`/`RunInit`/`AddPlugin`/`Relate`/`Debug`)/
`quad-types/src/`/`type-version-check/src/`가 실제로 존재(`quad-roblox/src`는
아직 빈 폴더 — M5에서 채워짐), 자세한 진행 상황은 루트 `ROADMAP.md`
소스. 핵심 아키텍처(Store 책임 분리, `process`/`retract`
디스패치 모델, Store/State/Source 온톨로지, 소스 트리 구조, Modifier 메커니즘, 디스패치 모델, Store/State/Source 온톨로지, 소스 트리 구조, Modifier 메커니즘,
컴포넌트=플레인 함수, 컴포넌트 경계 modifier/Ref 전달)는 전부 `.claude/base/` 컴포넌트=플레인 함수, 컴포넌트 경계 modifier/Ref 전달)는 전부 `.claude/base/`
문서로 확정돼 있음 — 먼저 `.claude/base/architecture.md`를 읽을 것. 사용자가 문서로 확정돼 있음 — 먼저 `.claude/base/architecture.md`를 읽을 것. 사용자가
@ -73,8 +76,9 @@ modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션
담는 폴더였으나, **[2026-08-18]** 구현 전 사용자 심사 라운드의 산출물도 담는 폴더였으나, **[2026-08-18]** 구현 전 사용자 심사 라운드의 산출물도
여기 둠(`pre-implementation-qa-round1.md`/`pre-implementation-qa-round2.md`/ 여기 둠(`pre-implementation-qa-round1.md`/`pre-implementation-qa-round2.md`/
`pre-implementation-qa-round3.md` 전부 **완료** — 라운드마다 새 `pre-implementation-qa-round3.md` 전부 **완료** — 라운드마다 새
파일, 상태의 소스는 각 파일 자신). `.claude/feedback/` — 구현 시작되면 쓰기 시작함, 파일, 상태의 소스는 각 파일 자신). `.claude/feedback/` — **실사용**
**[2026-08-18 기준] 폴더 자체가 아직 없음**. 피드백용(M0/M1 스캐폴딩이 아니라 실제로 렌더링해보고 쓰는 단계부터),
**[2026-08-19 기준] 폴더 자체가 아직 없음** — 첫 피드백이 생길 때 만들면 됨.
`.claude/archive/`는 원래 같은 취급이었으나 `.claude/archive/`는 원래 같은 취급이었으나
2026-08-06 세 번째 세션부터 **완전히 뒤집힌 설계 결정을 원문+역전 2026-08-06 세 번째 세션부터 **완전히 뒤집힌 설계 결정을 원문+역전
이유+diff와 함께 보존하는 용도로도 사용 시작**(구현 완료 대상만이 이유+diff와 함께 보존하는 용도로도 사용 시작**(구현 완료 대상만이

View file

@ -1535,3 +1535,77 @@ ERROR 0.
드러나 **순수 슈가로 재평가**(옛 "실제 기능 갭이라 우선순위 위" 서술 드러나 **순수 슈가로 재평가**(옛 "실제 기능 갭이라 우선순위 위" 서술
철회). `ROADMAP.md`/`question.md`/`todos.md`/`README.md`/ 철회). `ROADMAP.md`/`question.md`/`todos.md`/`README.md`/
`source-state-plan.md`/`blocker-plan.md` 전량 반영. `source-state-plan.md`/`blocker-plan.md` 전량 반영.
## 2026-08-19 — M0/M1 스캐폴딩 첫 시도, wally→pesde 전환, `@self` require 함정
원문: `session/2026-08-19-04-pesde-migration-and-project-setup.md`
`ROADMAP.md` M0(스파이크 3종)/M1(스캐폴딩)을 revert 가능한 상태로 실제로
짜보는 시도 — `quad-base/`/`quad-roblox/` 폴더, `Relate.luau` 전량 구현,
`Debug/init.luau` + 최상위 `init.luau`, mock+스모크 테스트까지 작성. 그
과정에서 크로스파일 require가 전부 깨지는 진짜 버그를 찾았으나 원인
진단은 처음에 틀렸음(CWD 기준설로 오판) — 사용자가 Luau RFC를 근거로
`init.luau``@self/X`가 필요한 특수 케이스라고 직접 정정. 이어서 사용자
결정으로 패키지 매니저를 wally에서 pesde로 전환, tbox 참고 후 실제 설치해
워크스페이스 전체를 검증. 산출물은 `base/project-setup-plan.md`(신설)와
`architecture.md`의 "패키징 방식" 절 정정.
**커밋 후 후속(같은 세션, §5)**: 사용자가 "전부 차근차근"이라고 답해 이어서
4가지 진행 — Rojo를 직접 설치해 `rojo sourcemap`/`rojo build`가 워크스페이스
symlink를 투명하게 따라감을 확인(Luau standalone CLI 전용 문제였음을
재확인, Studio 실물 검증만 계정 분리 대기로 남음), 스파이크 `13`
타입 전용/런타임(`22` 신규) 두 파일로 분리해 `PreRef`/`PostRef` 배타성까지
검증, `luau-lsp`를 직접 설치해 새 Luau 솔버 필요성을 재귀 제네릭 스파이크로
재확인하고 `.vscode/settings.json`에 반영, 스파이크 `05`/`21` STATUS.md
텍스트 갱신.
## 2026-08-19 — rokit→mise 전환, selene 린터 도입, darklua 검토 후 기각
원문: `session/2026-08-19-05-mise-migration-and-selene-linter.md`
사용자가 참고 GitHub 레포 `Word30210/roblox-project-example`
`mise.toml`을 제시("요즘은 rokit보단 mise로 까는듯") → 클론해 구조 전체를
훑고 mise 전환/selene 린터/darklua/Justfile 네 후보를 멀티셀렉트로 제시,
사용자는 mise 전환과 selene만 채택. darklua는 사용자가 직접 반박해 보류
— "Roblox 엔진 자체가 이미 `@self`/`@game` string require를 지원하므로
변환 계층이 불필요"라는 논거. mise 전환은 GitHub artifact attestation +
SLSA provenance 검증까지 거쳐 실제 설치·검증 완료.
## 2026-08-19 — `RunInit` 재설계, darklua 경계 정밀화, 한국어 진행 합의
원문: `session/2026-08-19-06-runinit-redesign-and-darklua-precision.md`
사용자 요청 두 가지: (1) darklua 기각 근거를 실측으로 정밀화 — 직접
설치해 돌려보니 `@self`/`@game`은 안 건드리고 커스텀 `.luaurc` alias만
변환한다는 정확한 경계 확인(지금은 불필요하지만 나중에 축약 alias를 쓰면
필요해질 수 있음을 `project-setup-plan.md`에 반영). (2) `New()`의 멱등
Init 가드를 파일마다 `Relate`+센티널을 두는 대신 **함수 자체를 릴레이션
키로 쓰는 공유 `module:RunInit(initFn)`**로 재설계 — 실제 구현+3개
시나리오 스모크 테스트까지 완료. 이후 대화를 한국어로 진행하기로 합의.
## 2026-08-19 — `quad-types` 패키지 신설, `AddPlugin`/`CheckedQuad` 실측 설계
원문: `session/2026-08-19-07-quad-types-package-addplugin-checkversion.md`
`RunInit` vs backend 유일 슬롯 가드를 `_initializedBy`로 분리 확정한 뒤,
사용자가 "quad-roblox가 quad-base를 런타임 주입으로만 받으면
dev-dependency로도 타입이 못 산다"는 문제를 제기 — 실측으로 확인하고
`quad-types`(구현 없는 타입 계약 전용 워크스페이스 패키지)를 신설,
`AddPlugin<Self,P>` 플러그인 체이닝과 `CheckedQuad<T>` 컴파일 타임
버전 체크를 설계·구현·검증까지 전부 마침. 과정에서 "값이 한 번이라도
`type function`을 거치면 이후 제네릭 self 체이닝이 조용히 깨진다"는 새
Luau 함정을 발견해 `typing-limits.md` §6으로 승격.
## 2026-08-19 — `type-version-check` 패키지 추출, `CheckedQuad<T, Pattern>` 확장
원문: `session/2026-08-19-08-type-version-check-package-extraction.md`
직전 세션의 `CheckedQuad<T>`(정확 버전 일치만)가 `quad-spring`/
`quad-spring-roblox`류 독립 게시 플러그인엔 너무 빡빡하다는 사용자 지적
→ 글롭(`"*"`)/캐럿(`"N^"`) 패턴을 지원하는 `CheckedQuad<T, Pattern>`으로
확장. 버전 매칭 로직 자체는 quad에 종속되지 않은 범용 워크스페이스 멤버
`type-version-check`로 분리(사용자 지시: 지금은 모노레포 안에 두고 독립
저장소 분리는 나중에 직접 — `HUMAN_TODO.md` 9번). 새 Luau 함정 2건 발견
(`type function`은 outer local 참조 불가, cross-package엔 `export type
function` + 이중 꺾쇠 제네릭 인스턴스화 필요). 핸드오버 감사 2라운드로
구 시그니처 잔존/개수 하드코딩 8건 발견·수정 후 커밋.

View file

@ -0,0 +1,78 @@
# 2026-08-19, 아홉 번째 세션 — 핸드오버 준비, `session-summary.md`/`ROADMAP.md` stale 대청소
**요약**: 사용자가 "quad-roblox-types도 base 문서에 짧게 언급해둘까,
핸드오버 준비해줘, 빠진 게 있으면 적절히 적어달라"고 요청. 확인해보니
`quad-roblox-types`는 직전 세션에 이미 `quad-types-plan.md`에 반영돼
있었으나, 감사 과정에서 훨씬 큰 두 가지 실제 공백을 발견 — (1)
`session-summary.md`에 오늘 세션 5개(04~08)의 색인 항목이 통째로 빠져
있었고, (2) `CLAUDE.md`/`project-context.md`/`ROADMAP.md`가 "구현 아직
시작 전"이라는 낡은 전제를 그대로 깔고 있었는데 실제로는 오늘 M0(스파이크
4개)/M1(스캐폴딩) 전부가 이미 완료·커밋된 상태였음. 둘 다 발견 즉시
반영, 감사 라운드로 재검증까지 마침.
## 1. `quad-roblox-types` 확인
`base/quad-types-plan.md`의 "남은 것" 절에 이미 백로그로 적혀 있음을
확인(직전 세션 산출물). 추가로 두 곳에 짧은 포인터만 보강 —
`todos.md` 4번 백로그(다른 미래 패키지 아이디어들과 나란히), `ROADMAP.md`
M5 섹션 상단(구현 관례 각주: quad-roblox 공개 타입은 지금부터 단일 파일에
몰아둘 것). 개수/설명 자체는 `quad-types-plan.md`가 계속 유일한 소스.
## 2. `session-summary.md` 색인 공백 발견·수정
`.claude/session/` 폴더엔 오늘 파일이 01~08까지 있는데
`session-summary.md`엔 01~03만 있었음(04~08 다섯 개 누락). 각 세션 파일
상단 "요약" 단락을 압축해 5개 항목 신설. 그 과정에서 session-04 항목이
그 세션 §5(커밋 후 후속 — Rojo/symlink 검증, 스파이크 13→13/22 분리,
에디터 새 솔버 설정 확정)를 놓치고 있는 것도 감사가 잡아내 보강.
## 3. `ROADMAP.md`/`CLAUDE.md`/`project-context.md` 대규모 stale 발견
감사 라운드가 지적: `CLAUDE.md`/`project-context.md`가 "[2026-08-16
기준] 지금은 설계/계획 단계이고 구현은 아직 시작 전"이라고 서술 중인데,
오늘 커밋 로그(`205af32`~`5dfc9b9`, 총 10개)를 보면 M0 스파이크 4개
전부와 M1 스캐폴딩 대부분이 이미 끝나 있었음 — `quad-base/src/init.luau`
동작하는 `New()`/`RunInit`/`AddPlugin`이 실존, smoke 테스트도 전부 PASS.
`Explore` 서브에이전트로 각 M0/M1 체크박스를 하나하나 실측 대조(과대평가
방지):
- **M0 4개 전부 통과**`luau-test/done/05`(다이아몬드 전파, 현행
모델로 재작성됨)/`08`(Source⊇State 제네릭)/`03`(재귀 재-process
디스패치)/`01`+`02`+`13`+`22`(props 두 패스+PreRef/PostRef)/`06`
(컴포넌트 경계 `or None` 관용구).
- **M1 5개 중 4개 확실히 완료, 1개는 항상 충족돼 있던 조건으로 판명**
폴더+`pesde.toml`(단 체크박스 텍스트가 `wally.toml`로 stale — pesde
전환 반영해 정정), `default.project.json`/`.luaurc`, mock 테스트
하네스, `New()`/`RunInit`. `qa-request/`/`archive/` "실사용 시작"
항목은 실제로 M1 이전부터 이미 계속 쓰이고 있어 조건이 항상 참이었음
(모호했던 문구를 명시적으로 정리).
**반영**: `ROADMAP.md` 상단 배너 갱신(M0/M1 완료, M2 착수 예정), M0/M1
체크박스 전부 `[x]` + 근거 스파이크 파일명 추가, "통과 기준"의 하드코딩된
개수("세 개 다") 제거(개수는 `luau-test/STATUS.md`가 소스), M5 섹션에
`quad-roblox-types` 관례 각주. `CLAUDE.md`/`project-context.md` 머리말을
"M0/M1 완료, M2 착수 예정"으로 갱신. `README.md`/`project-context.md`의
`feedback/` 폴더 부재 설명도 "구현 시작 전이라서"에서 "M0/M1 스캐폴딩만
으론 안 생기고 실사용 단계부터"로 정정(폴더가 없다는 결론 자체는 그대로,
근거만 정확하게).
## 4. 감사 루프
핸드오버 체크리스트대로 라운드를 나눠 진행(전부 `quad-doc-auditor` 단독
호출, 병렬 없음):
1. `type-version-check`/`CheckedQuad<T, Pattern>` 관련 변경 감사 3라운드
(직전 턴에서 이미 완료 — 1라운드 5건, 2라운드 3건 발견·수정, 3라운드
무발견으로 수렴).
2. `session-summary.md`/`todos.md` 신규 변경 감사 1라운드 — 위 3번 항목의
대규모 stale(CLAUDE.md/project-context.md/ROADMAP.md)을 여기서 발견.
3. ROADMAP/CLAUDE.md/project-context.md 수정분 재감사 1라운드 — 무발견,
여기서 종료.
`python3 .claude/tools/doc-check.py`는 전 과정에서 ERROR 0 유지(기존
WARN 8건은 이 세션과 무관한 사전 부채).
## 다음에 확인할 것
없음 — M2(디스패치 엔진) 착수가 다음 마일스톤. M2 진입 전 필독 문서는
`ROADMAP.md` 상단 배너와 `todos.md` 0번이 이미 안내하고 있음(`typing-limits.md`/
`dispatch-core-plan.md`).

View file

@ -200,6 +200,10 @@
참고 구현 `qwreey/spring.lua` 사용 가능성 확인 필요) — 둘 다 설계 논의 참고 구현 `qwreey/spring.lua` 사용 가능성 확인 필요) — 둘 다 설계 논의
전 아이디어 단계이고 사용자가 직접 "아주 나중"으로 후순위 지정, M0/설계 전 아이디어 단계이고 사용자가 직접 "아주 나중"으로 후순위 지정, M0/설계
게이트와 무관. 게이트와 무관.
**[2026-08-19 추가]** `quad-roblox-types`(가칭, `quad-types`와 같은
패턴으로 `quad-roblox` 전체 대신 그 타입만 필요한 모듈을 위한 패키지)도
같은 성격의 백로그로 신설 — 사용자가 지금 만들 필요는 없다고 명시적으로
후순위 지정, 상세는 `base/quad-types-plan.md`의 "남은 것" 절.
5. 자율 작업 루프/스케줄 설정 여부는 사용자 결정 대기 중 5. 자율 작업 루프/스케줄 설정 여부는 사용자 결정 대기 중
(`HUMAN_TODO.md` 2번 항목). (`HUMAN_TODO.md` 2번 항목).
6. **[신규 백로그, 2026-08-14 열네 번째 세션]** 문서 stale 감소용 include 6. **[신규 백로그, 2026-08-14 열네 번째 세션]** 문서 stale 감소용 include

View file

@ -1,9 +1,10 @@
# CLAUDE.md # CLAUDE.md
Roblox 엔진용 DOMless UI 렌더러 **quad**를 처음부터 다시 짜는 프로젝트. Roblox 엔진용 DOMless UI 렌더러 **quad**를 처음부터 다시 짜는 프로젝트.
**[2026-08-16 기준] 지금은 설계/계획 단계이고 구현은 아직 시작 전** — 같은 **[2026-08-19 기준] M0(스파이크 검증)/M1(스캐폴딩)까지 완료, M2(디스패치
상태를 `.claude/project-context.md`도 서술하니 M0에 착수하면 두 곳을 같이 엔진)부터 착수 예정** — 같은 상태를 `.claude/project-context.md`
고칠 것. 서술하니 마일스톤이 넘어갈 때 두 곳을 같이 고칠 것. 진행 상황의 소스는
항상 루트 `ROADMAP.md`.
<!-- [2026-08-16 재구조화] 이 파일은 1537줄까지 불어나 (a) 사람이 검토 불가, <!-- [2026-08-16 재구조화] 이 파일은 1537줄까지 불어나 (a) 사람이 검토 불가,
(b) 공식 권장치(파일당 200줄) 7.7배 초과로 지침 준수도 저하, (c) 에이전트가 (b) 공식 권장치(파일당 200줄) 7.7배 초과로 지침 준수도 저하, (c) 에이전트가

View file

@ -5,8 +5,16 @@ quad-v2 구현 단계 실행 계획. 설계 근거/아키텍처 자체는 여기
체크박스를 세분화해서 늘려도 되고, 끝나면 체크만 하면 됨 — 살아있는 문서. 체크박스를 세분화해서 늘려도 되고, 끝나면 체크만 하면 됨 — 살아있는 문서.
**2026-08-04 세션에 준비만 해둔 상태로 신설, 이후 여러 세션에 걸쳐 설계가 **2026-08-04 세션에 준비만 해둔 상태로 신설, 이후 여러 세션에 걸쳐 설계가
확정될 때마다 각 마일스톤 체크박스가 계속 갱신돼왔음 — 그래도 아직 M0 확정될 때마다 각 마일스톤 체크박스가 계속 갱신돼왔음.**
자체는 시작 안 함.** 다음 세션은 바로 M0부터.
> **✅ [2026-08-19 기준] M0 스파이크 4개 전부 통과, M1 스캐폴딩도 대부분
> 완료(quad-base/quad-roblox 폴더+pesde.toml, 루트 default.project.json/
> .luaurc, mock 테스트 하네스, `New()`/`RunInit`/`AddPlugin` 골격 — 아래
> M0/M1 체크박스 참고). 다음은 M2(디스패치 엔진) 착수.** M1 착수 도중
> wally→pesde 전환이 확정돼(`base/project-setup-plan.md`) M1 체크박스의
> `wally.toml` 표기도 `pesde.toml`로 정정. 부수로 M3가 의존하는
> `quad-types`/`type-version-check` 두 워크스페이스 멤버도 이 과정에서
> 먼저 신설됨(`base/quad-types-plan.md`).
> **✅ [2026-08-13 열네 번째 세션] M0 착수를 막던 결정이 전부 해소됐음.** > **✅ [2026-08-13 열네 번째 세션] M0 착수를 막던 결정이 전부 해소됐음.**
> `0-Y`(13차 세션), `0-Z`(Attribute 이름 소유권)/`0-A`(재디스패치 하강 > `0-Y`(13차 세션), `0-Z`(Attribute 이름 소유권)/`0-A`(재디스패치 하강
@ -29,24 +37,29 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
`architecture.md`/`bind-system-plan.md` 등을 이 시점에 고치는 게 정상 — `architecture.md`/`bind-system-plan.md` 등을 이 시점에 고치는 게 정상 —
실패가 아니라 이 단계의 목적. 실패가 아니라 이 단계의 목적.
- [ ] Store/State push-invalidate → pull-recompute propagation을 실제로 - [x] Store/State push-invalidate → pull-recompute propagation을 실제로
짜보기(다이아몬드 의존성 케이스 포함 — **[2026-08-14 정정]** 확인할 짜보기(다이아몬드 의존성 케이스 포함 — **[2026-08-14 정정]** 확인할
것은 "이미 invalid면 전파 중단되는지"가 **아니라** 그 반대: 것은 "이미 invalid면 전파 중단되는지"가 **아니라** 그 반대:
**emit은 자기 invalid 상태와 무관하게 항상 전파되고**, 중복 재계산은 **emit은 자기 invalid 상태와 무관하게 항상 전파되고**, 중복 재계산은
`:Get()` 시점 캐시로만 막히는지. 특히 `:Get()`을 안 부르는 `:Get()` 시점 캐시로만 막히는지. 특히 `:Get()`을 안 부르는
`Observer`가 매 변경마다 계속 울리는지 — 옛 모델에선 두 번째부터 `Observer`가 매 변경마다 계속 울리는지 — 옛 모델에선 두 번째부터
침묵했음(`archive/invalidate-dedup-propagation-reversed.md`). 침묵했음(`archive/invalidate-dedup-propagation-reversed.md`).
스파이크 `05-store-state-diamond-propagation.luau`는 옛 모델을 스파이크 `05-store-state-diamond-propagation.luau`**[2026-08-19
검증 중이라 `rewrite-required/`에 있음) 재작성 완료, `done/`]** 현행 모델("emit은 항상 전파 + `:Get()`
- [ ] Source가 State를 구조적으로 만족하는 제네릭 타입(`:Compute<U>(self: 시점 캐시로만 dedup")로 재검증 통과)
- [x] Source가 State를 구조적으로 만족하는 제네릭 타입(`:Compute<U>(self:
Source<T>, ...) -> State<U>`류, self 타이핑 + State 참조 혼합)이 Source<T>, ...) -> State<U>`류, self 타이핑 + State 참조 혼합)이
Luau 솔버에서 안전하게 추론되는지 확인(2026-08-06 세 번째 세션, Luau 솔버에서 안전하게 추론되는지 확인(2026-08-06 세 번째 세션,
`base/source-state-plan.md` "Source가 State를 만족함" 절 — `State<T>` `base/source-state-plan.md` "Source가 State를 만족함" 절 — `State<T>`
`Source`를 참조하지 않는 단방향 의존으로 두면 위험한 상호 재귀는 `Source`를 참조하지 않는 단방향 의존으로 두면 위험한 상호 재귀는
피할 수 있어 보이나 실제 검증 전엔 확정 아님) 피할 수 있어 보이나 실제 검증 전엔 확정 아님. **[통과]**
- [ ] `process`(+반환 retractor 클로저) 재귀 재-process 디스패치를 실제로 `luau-test/done/08-type-source-satisfies-state.luau` — 핵심 케이스
짜보기(store-bind 핸들러 하나 + `isHandlable` 우선순위 스캔 포함) 통과, 잔여 자기재귀 케이스는 Luau 한계로 별도 확정
- [ ] props 순회의 "배열 파트 먼저, 해시 파트 나중" 두 패스 계약이 실제 (`base/typing-limits.md`), 설계 영향 없음)
- [x] `process`(+반환 retractor 클로저) 재귀 재-process 디스패치를 실제로
짜보기(store-bind 핸들러 하나 + `isHandlable` 우선순위 스캔 포함 —
`luau-test/done/03-recursive-store-bind-dispatch.luau` 통과)
- [x] props 순회의 "배열 파트 먼저, 해시 파트 나중" 두 패스 계약이 실제
Luau 테이블에서 관찰한 대로 동작하는지 확인, `PreRef` pre-pass + Luau 테이블에서 관찰한 대로 동작하는지 확인, `PreRef` pre-pass +
일반 `Ref`의 위치 기반 순서까지 최소 스파이크로 검증 일반 `Ref`의 위치 기반 순서까지 최소 스파이크로 검증
(2026-08-07 세 번째 세션, `base/ref-plan.md` "`phase` 옵션 (2026-08-07 세 번째 세션, `base/ref-plan.md` "`phase` 옵션
@ -62,7 +75,7 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
(`base/ref-plan.md` "PreRef" 절, `base/dispatch-core-plan.md` (`base/ref-plan.md` "PreRef" 절, `base/dispatch-core-plan.md`
"Length/Offset" 절) — 아래 `PreRef` pre-pass/동적 경로 가드 "Length/Offset" 절) — 아래 `PreRef` pre-pass/동적 경로 가드
체크리스트 항목도 이 값으로 스파이크할 것. 체크리스트 항목도 이 값으로 스파이크할 것.
- [ ] `props.Modifier`/`props.Ref` named-parameter로 받는 컴포넌트 하나 작성, - [x] `props.Modifier`/`props.Ref` named-parameter로 받는 컴포넌트 하나 작성,
`export type Params = {...}`로 타입 체크되는지 확인 `export type Params = {...}`로 타입 체크되는지 확인
(`component-composition-plan.md` 최종 결론 1번) — **`props.Modifier or (`component-composition-plan.md` 최종 결론 1번) — **`props.Modifier or
None`/`props.Ref or None` 관용구(2026-08-07 열 번째 세션 확정, None`/`props.Ref or None` 관용구(2026-08-07 열 번째 세션 확정,
@ -71,25 +84,38 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
`or None`이 항상 non-nil을 보장하므로 `{nil, ref, child}`류 리터럴 `or None`이 항상 non-nil을 보장하므로 `{nil, ref, child}`류 리터럴
구멍 자체가 안 생김(`research/pre-implementation-audit.md` 1-5). 구멍 자체가 안 생김(`research/pre-implementation-audit.md` 1-5).
M0에서 검증할 것은 "어떻게 막을지"가 아니라 이 관용구가 실제로 M0에서 검증할 것은 "어떻게 막을지"가 아니라 이 관용구가 실제로
타입 체크/런타임 양쪽에서 문제없이 동작하는지** 타입 체크/런타임 양쪽에서 문제없이 동작하는지** —
- [ ] 위 과정에서 소스 트리/메커니즘 문서에 고칠 부분이 생기면 그 자리에서 `luau-test/done/06-component-boundary-nil-hole-props.luau` 통과
`.claude/base/` 갱신 - [x] 위 과정에서 소스 트리/메커니즘 문서에 고칠 부분이 생기면 그 자리에서
`.claude/base/` 갱신 — 실제로 여러 차례 발생, 그때마다 반영됨(각
스파이크 항목의 "정정"/"재작성" 표시가 그 기록)
**통과 기준**: 세 개 다 Luau에서 자연스럽게 짜이는 게 확인되면 M1 진행. **통과 기준**: 위 항목들이 Luau에서 자연스럽게 짜이는 게 확인되면 M1
안 되면 여기서 관련 `base/` 문서부터 고치고 재시도. 진행 — **[2026-08-19] 전부 통과, M1 진행 중**(개수는 `luau-test/STATUS.md`
소스, 여기서 세지 않음).
## M1 — 실제 스캐폴딩 ## M1 — 실제 스캐폴딩
- [ ] `quad-base/`, `quad-roblox/` 폴더 + 각 `wally.toml` - [x] `quad-base/`, `quad-roblox/` 폴더 + 각 `pesde.toml`(**[2026-08-19
- [ ] 루트 `default.project.json`, `.luaurc`(`architecture.md` "구현 착수: 정정]** 이 체크박스는 원래 `wally.toml`이라 적혀 있었으나 같은 날
wally→pesde 전환이 확정돼 `pesde.toml`로 정정 —
`base/project-setup-plan.md` 참고. `quad-roblox/src`는 아직 빈
폴더 — 실제 소스는 M5)
- [x] 루트 `default.project.json`, `.luaurc`(`architecture.md` "구현 착수:
소스 트리 구조 확정" 절 그대로) 소스 트리 구조 확정" 절 그대로)
- [ ] quad-base용 최소 mock 테스트 하네스(Vide `test/mock.luau` 선례, 순수 - [x] quad-base용 최소 mock 테스트 하네스(Vide `test/mock.luau` 선례, 순수
`luau` CLI, `architecture.md` "테스트 전략" 절 참고) `luau` CLI, `architecture.md` "테스트 전략" 절 참고) —
- [ ] 최상위 `New()`/`InitXxx(module)` 팩토리 체이닝 골격 — 각 서브시스템 `quad-base/test/mock.luau` + `smoke.*.luau`, 전부 PASS
- [x] 최상위 `New()`/`InitXxx(module)` 팩토리 체이닝 골격 — 각 서브시스템
Init이 `module`을 파라미터로 받아 뮤테이션, `Relate` 기반 인스턴스별 Init이 `module`을 파라미터로 받아 뮤테이션, `Relate` 기반 인스턴스별
멱등 가드(`base/module-lifecycle-plan.md`의 "New()의 내부 구성" 절 멱등 가드(`base/module-lifecycle-plan.md`의 "New()의 내부 구성" 절
그대로, 2026-08-19 확정) 그대로, 2026-08-19 확정) — `quad-base/src/init.luau``New()`/
- [ ] 이 시점부터 `.claude/qa-request/`/`.claude/archive/` 폴더 실사용 시작 `RunInit`/`AddPlugin`으로 구현·smoke 테스트 검증 완료
- [x] 이 시점부터 `.claude/qa-request/`/`.claude/archive/` 폴더 실사용
시작(**[2026-08-19 확인]** 두 폴더 모두 M1 이전인 설계 단계부터
이미 쓰이고 있었고 — QA 라운드/역전 결정 기록 — M1 착수 이후에도
계속 같은 방식으로 쓰이는 중이라 "실사용 시작"이라는 조건은 사실상
항상 충족돼 있었음)
## M2 — 디스패치 엔진 ## M2 — 디스패치 엔진
@ -361,7 +387,15 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
## M5 — quad-roblox 최소 프로바이더 ## M5 — quad-roblox 최소 프로바이더
- [ ] `RobloxFactory.luau`(BaseModule 뮤테이션, 재호출 가드) > **⚠️ 구현 관례**: `quad-roblox`의 공개 타입은 지금부터 단일 파일
> (`src/init.luau` 또는 `types.luau`)에 몰아둘 것 — 나중에 필요해지면
> 백로그 `quad-roblox-types`(가칭, `quad-types`와 같은 패턴)로 쉽게
> 분리할 수 있게 하기 위함. `base/quad-types-plan.md`의 "남은 것" 절이
> 소스.
- [ ] `RobloxFactory.luau`(BaseModule 뮤테이션, 재호출 가드) — 진입점
`QuadRoblox(Quad): QuadRoblox``QuadTypes.CheckedQuad<T, Pattern>`으로
주입받은 quad-base 버전을 확인(`base/quad-types-plan.md` 참고)
- [ ] `D/init.luau`(제네릭 생성자 `New` + 생성기가 찍는 정적 별칭 필드 — **[2026-08-18]** 범위는 "GUI에 쓰이는 모든 인스턴스", 이벤트 필드의 콜백 타입까지 생성, `base/bind-system-plan.md`의 "인스턴스 생성 / 이벤트 네이밍 인체공학" 절) - [ ] `D/init.luau`(제네릭 생성자 `New` + 생성기가 찍는 정적 별칭 필드 — **[2026-08-18]** 범위는 "GUI에 쓰이는 모든 인스턴스", 이벤트 필드의 콜백 타입까지 생성, `base/bind-system-plan.md`의 "인스턴스 생성 / 이벤트 네이밍 인체공학" 절)
- [ ] `Handlers/Property.luau`, `Handlers/InstanceChild.luau` - [ ] `Handlers/Property.luau`, `Handlers/InstanceChild.luau`
- [ ] **Instance 생성 시점의 gcconn/gchold 셋업**(2026-08-14 다섯 번째 세션 - [ ] **Instance 생성 시점의 gcconn/gchold 셋업**(2026-08-14 다섯 번째 세션