refactor(luau-test): 상태별 폴더로 재편 — done/review-required/rewrite-required/not-run
사용자 지적: 파일 21개가 평평하게 쌓여 있어 사람이 "지금 내가 볼 게 뭔지" 못 고름. 이전 세션에 README/STATUS 문서만 바뀌고 폴더 구조는 그대로였음. - review-required/ (1) — 설계가 걸려 **사람 결정 필요**: 08 - rewrite-required/ (3) — 스파이크 코드가 깨짐(설계 문제 아님): 13/15/16 - not-run/ (1+헬퍼) — Studio 전용이라 이 환경에서 못 돌림: 10 + gc-trigger-helper - done/ (15) — 통과 or 판정 끝 **폴더를 옮기는 게 곧 상태 갱신**이라는 규칙을 README/STATUS 양쪽에 명시. STATUS.md는 폴더 구조를 그대로 반영해 재작성(맨 위 요약표 → 사람이 볼 review-required부터). 폴더가 상태라 파일이 옮겨 다니므로, 다른 문서의 참조를 경로 대신 파일명 기준으로 정규화(ROADMAP/pre-implementation-audit/bind-system-plan 6곳) — 안 그러면 파일을 옮길 때마다 링크가 깨져 stale이 또 쌓임. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6hzeUi5QdLPEk69B6cXFa
This commit is contained in:
parent
3ca2696208
commit
a30fb43d49
26 changed files with 80 additions and 50 deletions
|
|
@ -1883,7 +1883,7 @@ deps만 받고 싶어도 `previous`가 2번째 자리를 차지하므로, 그
|
|||
비워둬야 함 — deps만 쓰는 흔한 케이스가 약간 불편해지지만, Luau 문법
|
||||
제약상 다른 선택지가 없음(대안은 애초에 이 확장 자체를 안 하는 것뿐).
|
||||
|
||||
**실측 필요 — `.claude/luau-test/15-type-compute-trailing-deps-typepack.luau`
|
||||
**실측 필요 — `luau-test`의 `15-type-compute-trailing-deps-typepack.luau`
|
||||
신규(ROADMAP.md M3 반영).** 순서 문제 자체는 위 정정으로 구조적으로
|
||||
풀렸으므로, 스파이크가 실제로 확인할 진짜 불확실성은 (B) 하나로 좁혀짐 —
|
||||
나머지는 그 결론을 뒷받침하는 대조군: (A) 균일 타입 dep 1개를 고정
|
||||
|
|
@ -2486,7 +2486,7 @@ Modifier처럼 플래튼하지 않는가"는 설계 근거를 알고 싶은 사
|
|||
> 계약이 Luau 양방향 추론과 충돌함이 확인됨.** 가장 흔한 관용구
|
||||
> (`state:Compute(function(s) return s:Get() * 2 end)`)가 타입 에러를
|
||||
> 낸다 — 콜백이 raw 값을 받는 형태면 완전히 클린하다는 것까지 최소
|
||||
> 재현으로 확인됨(`.claude/luau-test/15-type-compute-trailing-deps-typepack.luau`,
|
||||
> 재현으로 확인됨(`luau-test`의 `15-type-compute-trailing-deps-typepack.luau`,
|
||||
> `audit/luau-test-first-run-2026-08-13.md`). `Effect`/`Observer`/`Animate`/
|
||||
> `Operator` 등 같은 계약을 공유하는 API 전부에 걸림 — 아래 서술은 M0
|
||||
> 착수 전 사용자가 확정해야 할 미해결 사안이지 확정된 계약이 아님.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,23 @@
|
|||
# .claude/luau-test — M0 착수 전 실 Luau 기술검증 스파이크 모음
|
||||
|
||||
> **⚡ 지금 뭘 봐야 하는지부터 보려면 [`STATUS.md`](STATUS.md)** — 파일별
|
||||
> pass / 사람 결정 필요 / 스파이크 깨짐 / 미실행 분류. 이 README는 각 파일이
|
||||
> **무엇을 왜 검증하는지**(의도·배경)를 담고, 상태는 STATUS.md가 소스.
|
||||
> **⚡ 지금 뭘 봐야 하는지부터 보려면 [`STATUS.md`](STATUS.md)** — 이
|
||||
> README는 각 파일이 **무엇을 왜 검증하는지**(의도·배경)만 담고, 상태는
|
||||
> **폴더 구조 + STATUS.md**가 소스.
|
||||
|
||||
**[2026-08-13 여덟 번째 세션] 폴더가 곧 상태** — 파일이 평평하게 21개
|
||||
쌓여 있어 사람이 "지금 내가 볼 게 뭔지" 못 고르겠다는 사용자 지적으로
|
||||
재편:
|
||||
|
||||
| 폴더 | 뜻 | 누가 처리 |
|
||||
|---|---|---|
|
||||
| `review-required/` | **설계가 걸림 — 사람 결정 필요**(현재 `08` 하나) | ⭐ 사용자 |
|
||||
| `rewrite-required/` | 스파이크 코드가 깨짐(설계 문제 아님, `13`/`15`/`16`) | 에이전트 |
|
||||
| `not-run/` | 이 환경에서 못 돌림(Studio 전용 `10` + GC 헬퍼) | 사용자 or MCP 연결 후 |
|
||||
| `done/` | 통과 or 판정 끝, 더 할 일 없음(15개) | — |
|
||||
|
||||
**스파이크를 고치거나 돌렸으면 파일을 해당 폴더로 `git mv`하고 STATUS.md의
|
||||
줄도 같이 옮길 것** — 그게 곧 상태 갱신이다. 아래 파일 목록의 경로는
|
||||
폴더 접두어를 생략하고 파일명만 적음(옮겨 다니므로).
|
||||
|
||||
|
||||
**[2026-08-09 이동]** 처음엔 레포 루트 `luau-ignoreme/`(git 자동 제외
|
||||
|
|
|
|||
|
|
@ -1,37 +1,56 @@
|
|||
# 스파이크 상태판 — **사람이 먼저 볼 것만 위에**
|
||||
# 스파이크 상태판 — **폴더가 곧 상태**
|
||||
|
||||
> 마지막 갱신: 2026-08-13 여섯 번째 세션(첫 실측 라운드).
|
||||
> 상세 결과는 `.claude/audit/luau-test-first-run-2026-08-13.md`.
|
||||
> 마지막 갱신: 2026-08-13 여덟 번째 세션(폴더 재편).
|
||||
> 첫 실측은 여섯 번째 세션 — 상세 결과는 `.claude/audit/luau-test-first-run-2026-08-13.md`.
|
||||
> 실행법: `luau <파일>` (런타임) / `luau-analyze <파일>` (타입 전용).
|
||||
|
||||
## 🔴 사람 결정 필요 — 설계가 걸린 것 (1건)
|
||||
**사람이 볼 게 있는 건 `review-required/` 하나뿐입니다.** 나머지는
|
||||
에이전트가 처리할 일(`rewrite-required/`)이거나, Studio가 필요한 일
|
||||
(`not-run/`)이거나, 끝난 일(`done/`)입니다.
|
||||
|
||||
| 파일 | 무엇이 걸렸나 | 어디로 |
|
||||
|---|---|---|
|
||||
| `08-type-source-satisfies-state.luau` | 핵심 질문(Source⊇State)은 통과. 다만 `State<T>`가 **자기 자신**을 다른 타입 인자로 재귀 참조하면 `Recursive type being used with different parameters` — 사용자 방향은 "구울 때 인라이닝" | `question.md` **0-Y** 하단 |
|
||||
| 폴더 | 뜻 | 개수 | 누가 처리 |
|
||||
|---|---|---|---|
|
||||
| `review-required/` | **설계가 걸림 — 사람 결정 필요** | 1 | ⭐ 사용자 |
|
||||
| `rewrite-required/` | 스파이크 코드가 깨짐(설계 문제 **아님**) | 3 | 에이전트 |
|
||||
| `not-run/` | 이 환경에서 못 돌림(Studio 전용) | 1(+헬퍼 1) | 사용자 or MCP 연결 후 에이전트 |
|
||||
| `done/` | 통과 or 판정 끝, 더 할 일 없음 | 15 | — |
|
||||
|
||||
`15`의 `:Compute(fn)` lazy 핸들 계약 충돌(**`question.md` 0-Y** 본 항목)도
|
||||
같은 종류의 사람 결정 필요 사안이지만, 스파이크 자체가 파싱 실패라 아직
|
||||
그 결과를 신뢰할 수 없는 상태 — 아래 🟠 표에서 재작성 대기 중, 재작성 후
|
||||
다시 여기로 승격할 것.
|
||||
|
||||
## 🟠 스파이크 자체가 깨져 있음 — 재작성 필요 (3건, 설계 문제 아님)
|
||||
|
||||
| 파일 | 상태 | 무엇을 고쳐야 하나 |
|
||||
|---|---|---|
|
||||
| `13-type-ref-preref-subtype.luau` | 타입 A섹션은 ✅ 통과 / **런타임 B섹션 실행 불가** | B가 A의 더미 스텁(`fakePreRef = nil`)에 막혀 도달 못 함 — 두 섹션 분리 |
|
||||
| `15-type-compute-trailing-deps-typepack.luau` | **파싱 실패**(SyntaxError) | 음성 대조군의 타입 표기가 `TypeError`가 아니라 `SyntaxError`로 걸려 **파일 전체가 아무것도 검증 못 함** — 대조군을 별도 파일/블록으로 격리. 재작성 후에도 `:Compute` 계약 충돌 자체는 이미 다른 최소 재현으로 확인됐으므로(`question.md` 0-Y) 재작성은 확인 사살일 뿐 0-Y 판단을 바꾸지 않음 |
|
||||
| `16-type-store-key-typefunction.luau` | ❌ 실패 | `types.newfunction` 시그니처가 설치된 버전의 실제 API와 안 맞음 — 실제 API 재확인 후 재시도 |
|
||||
|
||||
## ⚪ 아직 안 돌림
|
||||
|
||||
| 파일 | 이유 |
|
||||
|---|---|
|
||||
| `10-roblox-studio-checks.server.luau` | **Studio 전용**(`luau` CLI로 못 돌림). A 섹션 일부만 사용자가 자작 스크립트로 실측 — `audit/gcconn-trick-verification.md`. A-1/A-2/B/C는 여전히 미확인 |
|
||||
**폴더를 옮기는 게 곧 상태 갱신** — 스파이크를 고치거나 돌렸으면 파일을
|
||||
해당 폴더로 `git mv`하고 아래 표의 줄도 같이 옮길 것. 파일별 "무엇을 왜
|
||||
검증하는가"는 `README.md`가 담당(이 파일은 상태만).
|
||||
|
||||
---
|
||||
|
||||
## ✅ 통과 — 설계 성립 확인됨 (런타임 12개)
|
||||
## ⭐ `review-required/` — 사람 결정 필요 (1건)
|
||||
|
||||
| 파일 | 무엇이 걸렸나 | 어디로 |
|
||||
|---|---|---|
|
||||
| `08-type-source-satisfies-state.luau` | 핵심 질문(Source⊇State)은 **통과**. 다만 `State<T>`가 **자기 자신**을 다른 타입 인자로 재귀 참조하면 `Recursive type being used with different parameters` — 사용자 방향은 "구울 때 인라이닝" | `question.md` **0-Y** 하단 |
|
||||
|
||||
`15`의 `:Compute(fn)` lazy 핸들 계약 충돌(**`question.md` 0-Y** 본 항목)도
|
||||
같은 종류의 사람 결정 사안이지만, **스파이크 자체가 파싱 실패라 그 결과를
|
||||
신뢰할 수 없어** `rewrite-required/`에 둠. 재작성해서 돌아가면 이 폴더로
|
||||
승격할 것. 단 **0-Y 판단 자체는 그걸 기다릴 필요 없음** — 계약 충돌은 이미
|
||||
별도 최소 재현으로 확인됨(`audit/luau-test-first-run-2026-08-13.md`).
|
||||
|
||||
## 🟠 `rewrite-required/` — 스파이크가 깨짐, 설계 문제 아님 (3건)
|
||||
|
||||
| 파일 | 상태 | 무엇을 고쳐야 하나 |
|
||||
|---|---|---|
|
||||
| `13-type-ref-preref-subtype.luau` | 타입 A섹션 ✅ 통과 / **런타임 B섹션 실행 불가** | B가 A의 더미 스텁(`fakePreRef = nil`)에 막혀 도달 못 함 — 두 섹션을 파일로 분리 |
|
||||
| `15-type-compute-trailing-deps-typepack.luau` | **파싱 실패**(SyntaxError) | 음성 대조군의 타입 표기가 `TypeError`가 아니라 `SyntaxError`로 걸려 **파일 전체가 아무것도 검증 못 함** — 대조군을 별도 파일/블록으로 격리 |
|
||||
| `16-type-store-key-typefunction.luau` | ❌ 실패 | `types.newfunction` 시그니처가 설치된 버전의 실제 API와 안 맞음 — 실제 API 재확인 후 재시도 |
|
||||
|
||||
## ⚪ `not-run/` — 이 환경에서 못 돌림
|
||||
|
||||
| 파일 | 이유 |
|
||||
|---|---|
|
||||
| `10-roblox-studio-checks.server.luau` | **Studio 전용**(`luau` CLI로 못 돌림). A 섹션 앞부분만 사용자 자작 스크립트로 실측 — `audit/gcconn-trick-verification.md`. **A-1/A-2(`canBound` 게이트)/B/C는 여전히 미확인** |
|
||||
| `gc-trigger-helper.server.luau` | 스파이크가 아니라 **헬퍼** — Studio에 `collectgarbage()`가 없어서 GC를 강제 트리거하는 기법. `10`을 돌릴 때 같이 씀 |
|
||||
|
||||
## ✅ `done/` — 통과 or 판정 끝 (15건)
|
||||
|
||||
**런타임 12개 전원 통과**(crash 0 / FAIL 0):
|
||||
|
||||
| 파일 | 확인된 것 |
|
||||
|---|---|
|
||||
|
|
@ -42,14 +61,19 @@
|
|||
| `05-store-state-diamond-propagation` | 다이아몬드에서 재계산 정확히 1회, invalidate 2번째는 즉시 중단 |
|
||||
| `06-component-boundary-nil-hole-props` | `or None` 없으면 앞쪽 nil-hole로 슬롯 소실, 관용구 쓰면 항상 보존 |
|
||||
| `07-relate-weak-table-gc` | **연쇄 GC 확정**(아래 별도 절) — GC-native 아키텍처의 핵심 전제 |
|
||||
| `09-type-modifier-overridden-subtype` | 문서가 우려한 `FrameModifier`↔`GuiObjectModifier` 서브타입 깨짐이 그대로 재현, fallback(`any`)은 정상 |
|
||||
| `11-modifier-illegal-value-error` | Modifier 필드/Source에 핸들러 계층 값 넣으면 즉시 error — 16개 케이스 전원 |
|
||||
| `17-modifier-index-tableclone-chaining` | 제네릭 `__index` + `table.clone` 체이닝, 메타테이블 참조 공유, 형제 분기 무오염 |
|
||||
| `18-relate-mutual-cycle-gc` | **두 `Relate` 상호 순환은 실제로 GC 안 됨**(아래 별도 절) |
|
||||
| `19-ownership-refcount-relate-patterns` | Tag 참조 카운트 / Attribute 점유 체크 / Slot `claimOwner` vs `claimOwnerAt` — **음성 대조군 포함** 전원 통과 |
|
||||
| `19-ownership-refcount-relate-patterns` | Tag 참조 카운트 / Attribute 점유 체크 / Slot `claimOwner` vs `claimOwnerAt` — **음성 대조군 포함** 전원 통과. ⚠️ **B 섹션은 `question.md` 0-Z가 정해지면 다시 손봐야 함**(하강 diff 모델에선 그룹↔그룹을 점유 체크만으론 못 잡음) |
|
||||
| `20-slot-splice-index-arithmetic` | `Splice` 산술 11개 경계 케이스 전부 참조 구현과 일치 |
|
||||
|
||||
**타입 스파이크 중 판정이 끝나 더 할 일 없는 것**:
|
||||
|
||||
| 파일 | 판정 |
|
||||
|---|---|
|
||||
| `09-type-modifier-overridden-subtype` | ✅ 통과 — 문서가 우려한 `FrameModifier`↔`GuiObjectModifier` 서브타입 깨짐이 그대로 재현, fallback(`any`)은 정상 |
|
||||
| `12-type-attribute-generic-key-narrowing` | ❌지만 **설계 영향 없음** — 제네릭 키 narrowing이 안 되는 건 `attribute-plan.md`가 이미 fallback으로 예비해둔 결과(타입 패밀리가 유일하게 믿을 경로) |
|
||||
| `14-type-nilable-default-overload` | ⚠️ 부분 — 의도한 오용은 막지만 정상 nilable 사용례까지 막아 현 스케치로는 채택 불가. 설계 결정은 아직 필요 없음(대안이 이미 UB 경고로 존재) |
|
||||
| `14-type-nilable-default-overload` | ⚠️ 부분 — 의도한 오용은 막지만 정상 nilable 사용례까지 막아 현 스케치로는 채택 불가. **설계 결정은 아직 필요 없음**(대안이 이미 UB 경고로 존재)이라 `review-required`가 아님 |
|
||||
|
||||
### 특별히 중요한 통과 3건
|
||||
|
||||
|
|
@ -80,12 +104,3 @@ inst 5개만 살린 상태 → 살아남은 payload 5 / 엔트리 5 (기대치
|
|||
```
|
||||
추측이 아니라 **실제로 GC가 안 됨** — `Slot`의 두-`Relate` 수정이 필수
|
||||
조치였음이 입증.
|
||||
|
||||
---
|
||||
|
||||
## 이 표를 갱신하는 방법
|
||||
|
||||
스파이크를 돌리거나 고칠 때마다 **여기 분류부터 옮기고**, 상세 서술은
|
||||
`audit/`의 실행 결과 문서에 쓸 것. 이 파일은 "지금 뭘 봐야 하는가"만
|
||||
빠르게 답하는 용도라 길어지면 안 됨(파일별 검증 의도/배경은
|
||||
`luau-test/README.md`가 이미 담당).
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ base 인터페이스가 그보다 늦은 M8에서 만들어지는 순서 역전.
|
|||
없어졌으니 M0/M3 어느 시점에 검증해도 무방 — `ROADMAP.md` 배치를 억지로
|
||||
안 옮겨도 됨. 상세는 `base/bind-system-plan.md` "`store.key` 레코드 필드
|
||||
타이핑" 절, 실제 문법 실측은
|
||||
`.claude/luau-test/16-type-store-key-typefunction.luau`(신규). 아래는
|
||||
`luau-test`의 `16-type-store-key-typefunction.luau`(신규). 아래는
|
||||
원래 발견 당시 기록.
|
||||
|
||||
**위치**: `ROADMAP.md` M0 vs M3 `"store.key dot-access 타입 추론 확인"`.
|
||||
|
|
@ -331,7 +331,7 @@ M7의 전제가 Luau 공식 동작대로 성립함. 별도로, 프로퍼티에 A
|
|||
불가능 — Property가 소유권 추적 대신 Modifier의 override 우선순위를 쓰는
|
||||
이유). 상세는 `base/modifier-plan.md` "`table.clone`의 정확한 동작" 절과
|
||||
"Property에 Attribute식 소유권 레지스트리 기각" 절, 실제 실행 확인은
|
||||
`.claude/luau-test/17-modifier-index-tableclone-chaining.luau`(신규).
|
||||
`luau-test`의 `17-modifier-index-tableclone-chaining.luau`(신규).
|
||||
아래는 원래 발견 당시 기록.
|
||||
|
||||
**위치**: `base/modifier-plan.md` "런타임은 클래스별 코드 없이 base에 딱
|
||||
|
|
@ -715,8 +715,8 @@ Handler"라고만 서술해, 사실상 3개의 거의 동일한 형태(리터럴
|
|||
항목 참고).
|
||||
- **M0 스파이크**: 1-10(`store.key` type function)과 1-11(`table.clone`
|
||||
메타테이블 공유)은 메커니즘 자체는 이제 확실하지만, 실제 Luau 코드로
|
||||
돌려보는 것 자체는 여전히 스파이크 대상 — `.claude/luau-test/16-type-
|
||||
store-key-typefunction.luau`/`17-modifier-index-tableclone-chaining.luau`로
|
||||
돌려보는 것 자체는 여전히 스파이크 대상 — `luau-test`의
|
||||
`16-type-store-key-typefunction.luau`/`17-modifier-index-tableclone-chaining.luau`로
|
||||
신규 추가됨(2026-08-12 열일곱 번째 세션 핸드오버 점검 중 발견된 갭,
|
||||
이전까진 이 두 항목을 커버하는 스파이크 파일 자체가 없었음).
|
||||
**[2026-08-13 첫 실측 라운드 결과]** `17`은 **통과**(제네릭 `__index` +
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
|
|||
`Source`로 감싼 레코드 타입을 합성 가능함을 확인(2026-08-12 열일곱
|
||||
번째 세션, `base/bind-system-plan.md` "`store.key` 레코드 필드
|
||||
타이핑" 절) — 실제 문법이 통과하는지는
|
||||
`.claude/luau-test/16-type-store-key-typefunction.luau`로 실측 필요
|
||||
`luau-test`의 `16-type-store-key-typefunction.luau`로 실측 필요
|
||||
- [ ] `:Compute(fn, ...)` — trailing args로 추가 의존성 직접 받는 sugar
|
||||
(2026-08-11 세션, `base/bind-system-plan.md` "`:Compute(fn, ...)`"
|
||||
절) — `:With(...):Compute(fn)` 체인과 달리 노드 1개(Compute 노드
|
||||
|
|
@ -209,7 +209,7 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
|
|||
**앞**에 와야 함, 2026-08-11 후속 세션 제안 → 같은 날 세 번째
|
||||
세션에 순서 정정, `base/bind-system-plan.md` "trailing deps를 fn에
|
||||
lazy positional 인자로도 노출" 절) — 방향/순서는 확정,
|
||||
`.claude/luau-test/15-type-compute-trailing-deps-typepack.luau`로
|
||||
`luau-test`의 `15-type-compute-trailing-deps-typepack.luau`로
|
||||
이형 다중 deps를 제네릭 타입 팩으로 표현 가능한지만 실측 필요(안
|
||||
되면 동종 타입 dep 1개로 한정)
|
||||
- [ ] `Blocker.luau`(`base/blocker-plan.md` 참고 — 여러 Source를
|
||||
|
|
@ -467,7 +467,7 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
|
|||
`table.clone`이 메타테이블을 복사 아닌 참조로 공유해 제네릭 `__index`
|
||||
기반 체이닝이 안 끊긴다는 메커니즘은 확인됨(2026-08-12 열일곱 번째
|
||||
세션, `modifier-plan.md` "`table.clone`의 정확한 동작" 절) — 실제
|
||||
Luau 실행 확인은 `.claude/luau-test/17-modifier-index-tableclone-chaining.luau`
|
||||
Luau 실행 확인은 `luau-test`의 `17-modifier-index-tableclone-chaining.luau`
|
||||
- [ ] `Modifier.Overridden(mod1, mod2, ...)`(이름 확정, 구 `Merge`→`Override`,
|
||||
2026-08-08 세션) — 필드별 raw 덮어쓰기, 특별한 State/함수 분기
|
||||
불필요(`modifier-plan.md` 9번)
|
||||
|
|
|
|||
Loading…
Reference in a new issue