From f14ba09cd62578d6723c88fcfd2fb7be4274dc2c Mon Sep 17 00:00:00 2001 From: qwreey-agent-selene Date: Mon, 31 Aug 2026 14:59:23 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20M3=20=EC=9E=90=EC=9C=A8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EA=B7=9C=EC=95=BD=20=ED=99=95=EC=A0=95=20=E2=80=94?= =?UTF-8?q?=20round12=20=C2=A70=20=EC=A0=84=EB=9F=89=20(a)=C2=B7=C2=A76=20?= =?UTF-8?q?=EC=B2=AB=20=EB=8B=A8=EC=9C=84=20=EA=B3=84=ED=9A=8D=20=EC=8A=B9?= =?UTF-8?q?=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - §0 회신 기록: Q1(M2 골격 + Handler 체크리스트 게이트)/Q2(단위 넷)/ Q3(M2 하자는 규모로 가름) 전부 권고 (a) 사용자 채택 - §6 신설·승인: Dispatch/Handler.luau(타입 전용 잎) + Dispatch/init.luau (InitDispatch(module), chains는 인스턴스별 Relate, HANDLER_PRIORITY_* 상수 정의+재노출) + quad-types Dispatch 필드(H-25) / drive는 단위 1에서 (b) 본체 루프만 — 배치 게이팅은 단위 2, pre-pass·postRefList는 M8 / 스파이크 01 재작성은 spec.drive.luau 상시 회귀로 대체 - round12.md 스텁을 실 스켈레톤(요약 표/§4/§5/§6)으로 교체, H-212부터 - 인덱스 3층 갱신: README qa-request 행, CLAUDE.md·project-context 머리말, todos.md 00번 — "M3 진행 중" Co-authored-by: qwreey Claude-Session: https://claude.ai/code/session_01LF78pXeFGD1ZSVD3ifteYG --- .claude/README.md | 2 +- .claude/project-context.md | 6 ++- .../m3-implementation-round12-brief.md | 54 ++++++++++++++----- .../qa-request/m3-implementation-round12.md | 39 ++++++++++++-- .claude/todos.md | 13 +++-- CLAUDE.md | 8 +-- 6 files changed, 94 insertions(+), 28 deletions(-) diff --git a/.claude/README.md b/.claude/README.md index d2dc136..8e443a4 100644 --- a/.claude/README.md +++ b/.claude/README.md @@ -24,7 +24,7 @@ | `base/` | 결정 완료 + 프로젝트 전체에 걸치는 컨텍스트 — plan/done 개념 없음, 계속 참조되는 배경지식. **항상 읽어야 하는** 배경지식만 여기 둠(다른 문서를 이해하는 데 전제되는 것) | | `reference/` | **[2026-08-07 신설]** 결정 자체가 아니라 다른 문서가 근거로 인용하는 온디맨드 참고 자료(v1 스냅샷, 프레임워크 비교 리서치) — "완료" 개념 없는 건 `base/`와 같지만, 항상 읽을 필요는 없고 해당 문서가 인용될 때만 열어보면 됨. `quadnomicon` 소재 후보가 많음. **[2026-08-21 확장] 확정된 결정의 "왜 그렇게 정했나" 근거 기록도 여기 둔다** — `research/`(아직 상의 필요)도 `archive/`(뒤집혔거나 기각됨)도 아니고, `base/`가 근거로 인용하는 온디맨드 자료라는 이 폴더의 기준에 정확히 맞기 때문(`slot-attach-decomposition.md`/`epoch-brand-composition.md`가 그렇게 들어옴) | | `research/` | 아직 착수 전, 사용자와 스코프/설계를 더 상의해야 함 | -| `qa-request/` | 원래 용도는 "구현 완료(코드/에이전트 검증까지 끝남) + 사용자 본인의 실기기(Roblox Studio) QA만 남음". **[2026-08-18 확장]** 구현 전에도 **사용자 심사 라운드의 산출물**을 여기 둠 — `pre-implementation-qa-round1.md`(1라운드: `base/` 확정 문서 전체를 문항으로 재확인받아 **"아니오"가 나온 항목만** 모은 결함 목록 + 신규 요구사항(`N-n`) + 부수 오탈자. **같은 날 전부 `base/`에 반영 완료**라 지금은 "무엇이 왜 틀렸었나"의 근거 기록이고, 지금 유효한 설계는 항상 `base/`가 소스. 아직 안 닫힌 것은 `question.md` 최우선 절과 `.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` M3가 M2의 `Blocker.luau`에 의존하게 된 마일스톤 순서 불일치는 각주로 반영 — **[2026-08-24]** 그때 열어뒀던 마일스톤 재편은 M2/M3 순서 교체로 닫혔다). `pre-implementation-qa-round4.md`(4라운드: 사용자 요청으로 **`base/` 확정 전체를 "예가 나와야 정상인 문항"으로 다시 뽑은 전수 문항지** — **[2026-08-21] 완료·종결**. 1~3라운드와 달리 이 파일은 **문항지 원본 그대로 남긴다** — 처리 결과 전량이 `-followup.md`에 쌓였으므로 "아니오만 남기는 재편"은 안 하기로 함(같은 정보가 두 곳에 갈라지는 걸 피함). 문항 수/문서별 분포는 그 파일 자신이 소스). `pre-implementation-qa-round4-response.md`(사용자 회신 원문 — 이 라운드는 회신을 **별도 파일**로 받았다, 1~3라운드와 다른 점), `pre-implementation-qa-round4-followup.md`(**[2026-08-20 시작, 2026-08-21 종결]** 그 회신 처리 결과 — A~H 8개 절이 4차에 걸쳐 시간순으로 쌓였고 **마지막 H절이 최신이자 소스**. B·C절의 재질문/판단 대기 항목은 F·G절을 거쳐 **H절에서 전량 닫혔다**(`Detach` 보존 주체, `KeyGone`, `Owned`, `attachSlot` 분해). **열린 질문 없음**. **[2026-08-21 정정]** 여기 적혀 있던 "5라운드 문항지는 만들지 않는다"는 뒤집혔다 — 같은 날 사용자 요청으로 5라운드를 만들었다), `pre-implementation-qa-round5.md`(**[2026-08-21 신설·처리 완료]** 5라운드: 4라운드에서 "예"로 넘어간 자리는 건너뛰고 **(1) 4라운드에 문항이 아예 없던 영역**(`project-setup-plan.md`/`quad-types-plan.md`, 그리고 **문서가 아니라 실제 커밋된 M1 코드**), **(2) 4라운드 회신 이후 새로 확정된 것**(`Detach`/`_detached`/`KeyGone`/`Owned`/`attachSlot` 분해 등), **(3) 큰 문서의 심화**(예: `debounce-throttle-plan.md`)만 묻는다. 문항 수는 그 문서 자신이 소스), `pre-implementation-qa-round5-response.md`(사용자 회신 원문 — 4라운드와 같이 별도 파일), `pre-implementation-qa-round5-followup.md`(**[2026-08-21]** 그 회신 처리 결과 — 즉시 반영분 / 재질문 / 사용자 판단 필요 / 새로 만든 문서 둘(`gate-plan.md`·`state-epoch-plan.md` — 같은 날 확정되며 `base/`로 승격)까지. **처리 결과의 소스는 이 파일**). `pre-implementation-handtrace-round6.md`(**[2026-08-22 신설]** 6라운드: 문항지가 아니라 **손 트레이싱**이다(2·3라운드와 같은 성격) — 사용자가 지목한 최근 확정 5개 영역(`Effect(fn, ...deps)`/`Gate`·`Blocker`/State 전파(`rawInvalid`·emit 지연)/Slot의 `native*`·offset·length·mount/`Brand`·`Epoch`·`EpochMap`)을 실제 값으로 돌려본 결과. 발견 번호는 `H-n`. **[2026-08-23] 2차 패스** — 1차가 안 본 영역(디스패치 코어 전체/라이프타임 유틸/Ref·Tag·Attribute·UI 숏핸드 핸들러/Slot의 `raw*` 계층). **[2026-08-23] 3차 패스** — 1·2차가 한 번도 안 연 문서 전체(Store/State/Source 코어, Modifier·컴포넌트 합성, 이벤트·라이프사이클·에러 격리, Tween·시간 게이트, 타입 계약과 실제 커밋된 M1 코드) + 통합 시나리오. **[2026-08-24] 4차 패스** — 문서 단위가 아니라 **축을 바꿔서**(핸들러 레지스트리 전수/두 대형 핸들러 문서 심층/`luau-test` 스파이크 실제 재실행/프리미티브 조합 매트릭스/`reference`·`archive`·로드맵 M2~M9/엔진·언어 사실 주장 전수 검증). 3·4차는 추론으로 끝내지 않고 로컬 `luau`/`luau-analyze`와 공식 문서로 **직접 재현·교차검증**했고, 그 부수로 기존 `H-2`의 크래시 주장이 틀렸음도 드러났다(3차 패스 머리의 정정 절). 발견 번호는 패스를 가로질러 이어서 매긴다. 발견 수/심각도 분포는 그 문서 자신이 소스. 각 패스의 "확인만 하고 문제 없었던 것" 절은 다시 트레이싱할 필요 없는 자리를 적어둔 것. **⭐ [2026-08-24] 전량 처리·반영 완료** — 그 문서는 이제 **발견 당시의 기록**이라 각 항목의 "갈래"는 선택 전 목록이니 그대로 믿지 말 것), `pre-implementation-handtrace-round6-followup.md`(**[2026-08-24 신설] 6라운드의 결정과 근거가 여기 소스다** — `H-1`~`H-54`를 사용자와 대화형으로 하나씩 결정한 기록이고, 반영 후 `/code-review high`가 잡은 7건(그중 셋이 이번 반영이 만든 회귀)도 D절에 있다. 진행 경위와 사용자 발언 원문은 `session/2026-08-24-01-handtrace-round6-resolution.md`). `pre-implementation-handtrace-round7.md`(**[2026-08-25 신설, 회신 대기]** 7라운드: 6라운드와 같은 손 트레이싱이되 범위가 **M2(반응형 코어)와 M2→M3 경계**다. 패스 6개가 각기 다른 각도를 쓴다 — 1차는 프리미티브 사이의 *호출 순서*를 시간축으로 겹쳐 보기, 2차는 문서가 "확인했다"고 적은 런타임/타입 주장을 실제로 `luau`/`luau-analyze`에 걸어보기, 3차는 **커밋된 M1 코드·툴체인을 이 저장소에서 그대로 돌려보기** + 1·2차가 뺐던 "M2를 *소비하는* 문서", 4차는 **M2 코어를 문서 그대로 옮긴 참조 구현을 돌려보기** + 아무 문서도 안 정한 **예외 경로**, 5차는 **확정된 M2 표면을 실제 Luau 타입으로 선언해 `luau-analyze`에 걸어보기**(확정 시그니처가 확정 관용구를 통과시키는가), 6차는 **그 참조 구현을 M2→M3 경계(Length/Offset 부기·Dispatch 체인)까지 이어 붙여 돌려보기** + **quad 자신이 던지기로 확정한 error 42곳의 계약 감사**. 발견 번호는 6라운드에서 이어서 `H-55`부터, 패스를 가로질러 연속으로 매긴다. 발견 수/심각도 분포는 그 문서 자신이 소스. 각 패스의 "문제가 없던 것" 부록은 다시 파지 않아도 되는 자리를 적어둔 것. **아직 아무것도 `base/`에 반영하지 않았다** — 판정은 사용자가 하고, 결정이 나면 6라운드처럼 `-followup.md`를 새로 만든다), `pre-implementation-handtrace-round7-verification.md`(**[2026-08-25 신설]** 그 52건이 **정말 유효한지만** 판정한 검증 패스 — 새 발견은 없다. ⚠️ **재실행이 아니라 대조로 판정했다**: 4·5·6차 패스가 쓴 전사물(`audit/handtrace-round7-reference-impl/spikes/`), `pre-implementation-handtrace-round7-followup.md`(**[2026-08-25 신설] 그 52건에 대한 사용자 결정과 `base/` 반영 결과 — 결정 단위 12묶음(🅐~🅜) 순서로 대화형 처리. **이 파일이 결정의 소스**이고 발견 원문은 앞의 두 파일. 무효/기각 7건(`H-73`~`H-77` 계열: `<>`가 값 호출부에서 동작함이 실측으로 드러나 Store 재설계로 이어짐, `RunInit` 누수는 성립 안 하는 사용법), 나머지는 전량 반영. **부수로 `question.md` 최우선 두 항목이 같이 닫혀 M2 착수 게이트가 0이 됐다**)과 `base/` 확정 의사코드를 줄 단위로 맞춰봤고(전사 오류로 생긴 발견은 **없었다**, 미신고 차이 3개는 전부 발견을 만들지 않는 방향), Luau 언어 동작·저장소 상태를 주장하는 것만 직접 재실행했다. 판정 분포와 항목별 근거는 그 문서 자신이 소스 — 여기서 세지 않는다. **결정 전에 반드시 읽을 것**: 부정 주장·개수 주장 몇 건이 정정됐고, 특히 **이미 사용자가 판단한 항목을 다시 묻게 되는 자리**가 하나 있다. 마지막 절의 **batch용 요약**이 유효 항목을 "한 결정으로 닫히는 묶음"으로 재편성해뒀으니 회신은 번호순이 아니라 그 묶음 단위로 하는 게 싸다), `pre-implementation-handtrace-round8.md`(**[2026-08-26 신설, 회신 대기]** 8라운드: 7라운드 반영으로 새로 쓰인 `base/` 서술을 **서로 겹쳐서** 재트레이싱한 것 — 개별 함수가 아니라 "반영된 결정들이 조합될 때 성립하는가"가 주제. 3패스에 걸쳐 `base/` 전 문서를 완독했고, 발견 번호는 `H-107`부터 이어 매김(발견 수·심각도 분포는 그 문서 자신이 소스), 실측 스파이크는 발견 항목에 인라인 전사. 사용자 결정 문항 Q1~Q10이 §4에 배치 회신용으로 정리돼 있다. 커밋 전 `/code-review`가 이 문서 자체의 결함 7건을 잡아 반영됐다(각 항목의 `[code-review 정정/추가]` 표시). **⭐ [2026-08-26] 전량 처리·반영 완료** — 그 문서는 이제 **발견 당시의 기록**이라 각 항목의 "갈래"는 선택 전 목록이니 그대로 믿지 말 것), `pre-implementation-handtrace-round8-followup.md`(**[2026-08-26 신설] 8라운드의 결정과 근거가 여기 소스다** — Q1~Q10을 사용자와 대화형으로 처리한 기록. **역전은 없고** 전부 "7라운드 확정이 `base/`에 내려앉을 때 생긴 누락·충돌"을 닫은 것. ⭐ 사용자가 **문항의 전제 자체를 정정한 것이 둘** 있다(Ref 콜백 ↔ Observer 콜백은 애초에 통합 대상이 아니다 / `H-118`은 소유권 문제가 아니라 문장이 틀린 것) — 결정만 읽지 말고 그 두 절을 볼 것), `pre-implementation-handtrace-round9-brief.md`(**[2026-08-26 신설]** 9라운드를 돌릴 감사자에게 주는 **지시서** — 발견 보고가 아니라 그 앞단이다. 이런 지시서를 저장하는 건 이번이 처음으로, 7·8라운드 것은 대화에만 있었고 저장되지 않았다(8라운드 본문이 인용하는 "감사 지시서 §2"가 코퍼스 어디에도 없는 이유). 스코프를 **커밋 `9dd8213` 하나의 델타**로 정의한 게 핵심 — 8라운드 결정 반영과 그 뒤 `/code-review high` 7패스 수정이 전부 그 커밋에 들어 있고 아무도 트레이싱한 적이 없다. 레인 셋(A: 그 델타의 상호 간섭 / C: `audit/handtrace-round7-reference-impl/`을 지금 계약으로 갱신해 실행 / B: 8라운드 §6이 남긴 M5+ 값 단위 트레이싱)과 우선순위 근거, `-round8-followup.md`가 적어둔 **반복 실패 모드 7개**를 사냥 목록으로 옮겨 실었다. 각도 문자(A~H)는 8라운드와 같은 걸 유지해 상호참조가 되게 했다), `pre-implementation-handtrace-round9.md`(**[2026-08-26]** 9라운드 발견 보고 — 레인 A(`9dd8213` 델타 상호 간섭)·C(참조 구현을 현재 계약으로 재전사해 `luau` 실행)·G(Luau 사실 재확인)·D(ROADMAP M2 시뮬레이션)·B(M5+ 값 단위, 첫 시도) — 발견 `H-124`~`H-141`, 🔴 둘(`recompute`의 `lengthList[i]` nil 읽기 / 재마운트 시 `_baseObserver` 미바인드 캐시 stale) 다 실측 재현. §4 배치 문항 Q1~Q10 + §5 이상 없음(⭐ `keyof<{}>` 빈 Store 실측으로 클린) + §6), `pre-implementation-handtrace-round9-followup.md`(**[2026-08-27] 9라운드 결정의 소스 — 전량 처리 완료** — Q1(`recompute` 되감기 판정을 읽기 앞으로) / Q2(`Offset`·`_baseObserver`를 Slot 생성자로, `materializeSlotTree` 순서, `_destroyed` 플래그) / Q3(`element → index`는 `bk.indexOfElement` 하나 — 사용자가 정한 적 없는 `token` 폐기, `H-137` 소멸, `H-141` 신설) / Q4(`EffectHandle` 네 진입점 의사코드) / Q5(M2에 `Ref` 최소형) / Q6(`WeakUnsubscribe` 관대) / Q7(폐기 블록 `archive/`) / Q8(`InstanceChildHandler` 부기) / **Q9(문항 전제가 틀림 — Tween 절 스케치 한 줄 복사 오류)** / Q10(`reconcile` 배치 Blocker) + `H-138`(숏핸드 우선순위) / `H-139`(`New`/`drive` 파이프라인 의사코드) / **`H-142`(props에 `Parent` 금지 — 순서 문제 소멸)** / **`H-143`~`H-146`**(`/code-review`가 낸 새 메커니즘 넷 — 전부 권고 (a), `H-144`는 사용자 요청으로 재구독 뒤 epoch·Blocker 상호작용을 재트레이싱한 기록 포함). 진행 표가 상태의 소스, 사용자 회신 원문 셋 인용; **[2026-08-28]** `H-143`~`H-146` 반영분의 감사 8라운드 표와 `/code-review high` 기록도 여기), `pre-implementation-handtrace-round10-brief.md`(**[2026-08-28 신설]** 10라운드 지시서 — 델타가 아니라 **광범위** 스코프(M2~M8, 레인 A 반응형 코어 전체 / C 참조 구현 갱신·실행 / B 디스패치·Slot / D 타입·M1 코드), 신선한 탐사자가 한 번에 문항지를 만들어 사용자가 배치로 결정하게 하는 것이 목적), `pre-implementation-handtrace-round10.md`(**[2026-08-28 신설, 회신 대기]** 10라운드 발견 보고 + §4 배치 문항지 — 씨앗은 `/code-review`가 낸 `H-147`~`H-149`(죽은 핸들에서 `Rerun` / `Parent` 거부 전용 문구는 새 메커니즘 / Observer `Subscribe` 위임과 `level 2`), 탐사자 발견은 `H-150`부터. 레인 C 실행 기록은 `audit/handtrace-round10-reference-impl/`. **[2026-08-28 탐사 완료]** 🔴 0 / 🟡 5 / 🟢 3, §4 문항 7건(기존 3 + `H-150` `Effect._blocker` 죽은 부품 / `H-151` 게이트 우회 계약 / `H-153` Store 예약 이름 런타임 가드 / `H-154` `InstanceChildHandler` dedup) — 전부 권고 (a). 레인 A·C 완료, B 부분, D `./scripts/test.sh` ALL PASS), `pre-implementation-handtrace-round10-followup.md`(**[2026-08-28] 10라운드 결정의 소스 — 전량 처리 완료.** 사용자가 *"하나하나 같이 보자"*라 대화형으로 처리. **문항의 전제를 뒤집은 것 둘**: `H-147`은 "죽은 핸들에서 `Rerun`"이 아니라 **`fn`/cleanup이 자기 구독을 바꿀 수 있다는 허용 자체가 모순**(→ (A) 금지, `H-143` 소멸, `rawRerun(force)`/`Rerun` 분리), `H-148`은 "문구"가 아니라 **루트 마운트 표면의 부재**(→ `Claim` + `D.Mapper`, `base/claim-plan.md`). 나머지: `H-149` Observer 진입점 인라인 / `H-150` `_blocker` 제거 / `H-151` `Refresh` 캐치업 폐기 — 게이트는 emit 경로만 미룬다 / `H-153` Store 예약 이름 가드 / `H-154` dedup. 새로 생긴 `H-158`(`:Block` 슈가)도 같은 날 확정 — 폐기, `state:Apply(blocker)`. **[2026-08-28 후속 3]** `Claim` 갈래 여덟 전량 확정 → `base/claim-plan.md`로 승격, 그 경위도 이 파일 끝 절). `m2-implementation-round11-brief.md`(**[2026-08-28 신설]** **M2 자율 구현 규약**이자 단위 끝마다 띄우는 탐사자 지시서 — 세 갈래 분류(자율 수정 / §4 배치 / 즉시 중단), 단위 넷, 두 층 커밋 게이트, 첫 단위 계획은 §6), `m2-implementation-round11.md`(**[2026-08-28 신설]** M2 구현 중 발견 원문 + §4 배치 문항지, 번호는 `H-165`부터 — 종이 트레이싱이 아니라 실제 코드를 옮기고 돌리다 나온 것. **[2026-08-31 개명]** 원래 `pre-implementation-handtrace-round11*`이었으나 구현 **중** 문서라 이름이 틀려 사용자 지시로 개명 — brief도 같이). **⭐ [2026-08-31 명명 규약, 사용자 확정]** 구현 라운드 파일은 **`mN-implementation-roundNN`** — 라운드 번호는 마일스톤을 가로질러 **단순 증가**하고(다음 라운드는 어느 마일스톤이든 round12), 마일스톤 접두가 어느 마일스톤의 라운드인지 담는다. 근거: *"m3 을 진행하다 m2 에 하자가 있음을 확인하면 다시 m2 로 올라가 round 가 진행되다 돌아오는 경우도 있을것 … 접두가 둘 다 있는게 정보를 온전히 담아줘"* — 번호만으로는 순서가, 접두만으로는 소속이 안 담긴다. 지시서도 같이 남길 것(`-roundNN-brief.md`). round1~10의 옛 이름(`pre-implementation-*`)은 그대로 둔다 — 실제로 구현 전 라운드였으니 이름이 맞다. `m3-implementation-round12-brief.md`(**[2026-08-31 신설, §0 회신 대기]** M3 자율 구현 규약 초안 + 착수 문항지 — §0 표(Q1 규약 재사용/Q2 단위 넷/Q3 M2 하자 혼입 규칙)가 사용자가 읽을 자리, 회신되면 M2 brief와 같은 지위가 된다. 발견 문서 `m3-implementation-round12.md`는 착수 시 신설, 번호 `H-212`부터) | +| `qa-request/` | 원래 용도는 "구현 완료(코드/에이전트 검증까지 끝남) + 사용자 본인의 실기기(Roblox Studio) QA만 남음". **[2026-08-18 확장]** 구현 전에도 **사용자 심사 라운드의 산출물**을 여기 둠 — `pre-implementation-qa-round1.md`(1라운드: `base/` 확정 문서 전체를 문항으로 재확인받아 **"아니오"가 나온 항목만** 모은 결함 목록 + 신규 요구사항(`N-n`) + 부수 오탈자. **같은 날 전부 `base/`에 반영 완료**라 지금은 "무엇이 왜 틀렸었나"의 근거 기록이고, 지금 유효한 설계는 항상 `base/`가 소스. 아직 안 닫힌 것은 `question.md` 최우선 절과 `.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` M3가 M2의 `Blocker.luau`에 의존하게 된 마일스톤 순서 불일치는 각주로 반영 — **[2026-08-24]** 그때 열어뒀던 마일스톤 재편은 M2/M3 순서 교체로 닫혔다). `pre-implementation-qa-round4.md`(4라운드: 사용자 요청으로 **`base/` 확정 전체를 "예가 나와야 정상인 문항"으로 다시 뽑은 전수 문항지** — **[2026-08-21] 완료·종결**. 1~3라운드와 달리 이 파일은 **문항지 원본 그대로 남긴다** — 처리 결과 전량이 `-followup.md`에 쌓였으므로 "아니오만 남기는 재편"은 안 하기로 함(같은 정보가 두 곳에 갈라지는 걸 피함). 문항 수/문서별 분포는 그 파일 자신이 소스). `pre-implementation-qa-round4-response.md`(사용자 회신 원문 — 이 라운드는 회신을 **별도 파일**로 받았다, 1~3라운드와 다른 점), `pre-implementation-qa-round4-followup.md`(**[2026-08-20 시작, 2026-08-21 종결]** 그 회신 처리 결과 — A~H 8개 절이 4차에 걸쳐 시간순으로 쌓였고 **마지막 H절이 최신이자 소스**. B·C절의 재질문/판단 대기 항목은 F·G절을 거쳐 **H절에서 전량 닫혔다**(`Detach` 보존 주체, `KeyGone`, `Owned`, `attachSlot` 분해). **열린 질문 없음**. **[2026-08-21 정정]** 여기 적혀 있던 "5라운드 문항지는 만들지 않는다"는 뒤집혔다 — 같은 날 사용자 요청으로 5라운드를 만들었다), `pre-implementation-qa-round5.md`(**[2026-08-21 신설·처리 완료]** 5라운드: 4라운드에서 "예"로 넘어간 자리는 건너뛰고 **(1) 4라운드에 문항이 아예 없던 영역**(`project-setup-plan.md`/`quad-types-plan.md`, 그리고 **문서가 아니라 실제 커밋된 M1 코드**), **(2) 4라운드 회신 이후 새로 확정된 것**(`Detach`/`_detached`/`KeyGone`/`Owned`/`attachSlot` 분해 등), **(3) 큰 문서의 심화**(예: `debounce-throttle-plan.md`)만 묻는다. 문항 수는 그 문서 자신이 소스), `pre-implementation-qa-round5-response.md`(사용자 회신 원문 — 4라운드와 같이 별도 파일), `pre-implementation-qa-round5-followup.md`(**[2026-08-21]** 그 회신 처리 결과 — 즉시 반영분 / 재질문 / 사용자 판단 필요 / 새로 만든 문서 둘(`gate-plan.md`·`state-epoch-plan.md` — 같은 날 확정되며 `base/`로 승격)까지. **처리 결과의 소스는 이 파일**). `pre-implementation-handtrace-round6.md`(**[2026-08-22 신설]** 6라운드: 문항지가 아니라 **손 트레이싱**이다(2·3라운드와 같은 성격) — 사용자가 지목한 최근 확정 5개 영역(`Effect(fn, ...deps)`/`Gate`·`Blocker`/State 전파(`rawInvalid`·emit 지연)/Slot의 `native*`·offset·length·mount/`Brand`·`Epoch`·`EpochMap`)을 실제 값으로 돌려본 결과. 발견 번호는 `H-n`. **[2026-08-23] 2차 패스** — 1차가 안 본 영역(디스패치 코어 전체/라이프타임 유틸/Ref·Tag·Attribute·UI 숏핸드 핸들러/Slot의 `raw*` 계층). **[2026-08-23] 3차 패스** — 1·2차가 한 번도 안 연 문서 전체(Store/State/Source 코어, Modifier·컴포넌트 합성, 이벤트·라이프사이클·에러 격리, Tween·시간 게이트, 타입 계약과 실제 커밋된 M1 코드) + 통합 시나리오. **[2026-08-24] 4차 패스** — 문서 단위가 아니라 **축을 바꿔서**(핸들러 레지스트리 전수/두 대형 핸들러 문서 심층/`luau-test` 스파이크 실제 재실행/프리미티브 조합 매트릭스/`reference`·`archive`·로드맵 M2~M9/엔진·언어 사실 주장 전수 검증). 3·4차는 추론으로 끝내지 않고 로컬 `luau`/`luau-analyze`와 공식 문서로 **직접 재현·교차검증**했고, 그 부수로 기존 `H-2`의 크래시 주장이 틀렸음도 드러났다(3차 패스 머리의 정정 절). 발견 번호는 패스를 가로질러 이어서 매긴다. 발견 수/심각도 분포는 그 문서 자신이 소스. 각 패스의 "확인만 하고 문제 없었던 것" 절은 다시 트레이싱할 필요 없는 자리를 적어둔 것. **⭐ [2026-08-24] 전량 처리·반영 완료** — 그 문서는 이제 **발견 당시의 기록**이라 각 항목의 "갈래"는 선택 전 목록이니 그대로 믿지 말 것), `pre-implementation-handtrace-round6-followup.md`(**[2026-08-24 신설] 6라운드의 결정과 근거가 여기 소스다** — `H-1`~`H-54`를 사용자와 대화형으로 하나씩 결정한 기록이고, 반영 후 `/code-review high`가 잡은 7건(그중 셋이 이번 반영이 만든 회귀)도 D절에 있다. 진행 경위와 사용자 발언 원문은 `session/2026-08-24-01-handtrace-round6-resolution.md`). `pre-implementation-handtrace-round7.md`(**[2026-08-25 신설, 회신 대기]** 7라운드: 6라운드와 같은 손 트레이싱이되 범위가 **M2(반응형 코어)와 M2→M3 경계**다. 패스 6개가 각기 다른 각도를 쓴다 — 1차는 프리미티브 사이의 *호출 순서*를 시간축으로 겹쳐 보기, 2차는 문서가 "확인했다"고 적은 런타임/타입 주장을 실제로 `luau`/`luau-analyze`에 걸어보기, 3차는 **커밋된 M1 코드·툴체인을 이 저장소에서 그대로 돌려보기** + 1·2차가 뺐던 "M2를 *소비하는* 문서", 4차는 **M2 코어를 문서 그대로 옮긴 참조 구현을 돌려보기** + 아무 문서도 안 정한 **예외 경로**, 5차는 **확정된 M2 표면을 실제 Luau 타입으로 선언해 `luau-analyze`에 걸어보기**(확정 시그니처가 확정 관용구를 통과시키는가), 6차는 **그 참조 구현을 M2→M3 경계(Length/Offset 부기·Dispatch 체인)까지 이어 붙여 돌려보기** + **quad 자신이 던지기로 확정한 error 42곳의 계약 감사**. 발견 번호는 6라운드에서 이어서 `H-55`부터, 패스를 가로질러 연속으로 매긴다. 발견 수/심각도 분포는 그 문서 자신이 소스. 각 패스의 "문제가 없던 것" 부록은 다시 파지 않아도 되는 자리를 적어둔 것. **아직 아무것도 `base/`에 반영하지 않았다** — 판정은 사용자가 하고, 결정이 나면 6라운드처럼 `-followup.md`를 새로 만든다), `pre-implementation-handtrace-round7-verification.md`(**[2026-08-25 신설]** 그 52건이 **정말 유효한지만** 판정한 검증 패스 — 새 발견은 없다. ⚠️ **재실행이 아니라 대조로 판정했다**: 4·5·6차 패스가 쓴 전사물(`audit/handtrace-round7-reference-impl/spikes/`), `pre-implementation-handtrace-round7-followup.md`(**[2026-08-25 신설] 그 52건에 대한 사용자 결정과 `base/` 반영 결과 — 결정 단위 12묶음(🅐~🅜) 순서로 대화형 처리. **이 파일이 결정의 소스**이고 발견 원문은 앞의 두 파일. 무효/기각 7건(`H-73`~`H-77` 계열: `<>`가 값 호출부에서 동작함이 실측으로 드러나 Store 재설계로 이어짐, `RunInit` 누수는 성립 안 하는 사용법), 나머지는 전량 반영. **부수로 `question.md` 최우선 두 항목이 같이 닫혀 M2 착수 게이트가 0이 됐다**)과 `base/` 확정 의사코드를 줄 단위로 맞춰봤고(전사 오류로 생긴 발견은 **없었다**, 미신고 차이 3개는 전부 발견을 만들지 않는 방향), Luau 언어 동작·저장소 상태를 주장하는 것만 직접 재실행했다. 판정 분포와 항목별 근거는 그 문서 자신이 소스 — 여기서 세지 않는다. **결정 전에 반드시 읽을 것**: 부정 주장·개수 주장 몇 건이 정정됐고, 특히 **이미 사용자가 판단한 항목을 다시 묻게 되는 자리**가 하나 있다. 마지막 절의 **batch용 요약**이 유효 항목을 "한 결정으로 닫히는 묶음"으로 재편성해뒀으니 회신은 번호순이 아니라 그 묶음 단위로 하는 게 싸다), `pre-implementation-handtrace-round8.md`(**[2026-08-26 신설, 회신 대기]** 8라운드: 7라운드 반영으로 새로 쓰인 `base/` 서술을 **서로 겹쳐서** 재트레이싱한 것 — 개별 함수가 아니라 "반영된 결정들이 조합될 때 성립하는가"가 주제. 3패스에 걸쳐 `base/` 전 문서를 완독했고, 발견 번호는 `H-107`부터 이어 매김(발견 수·심각도 분포는 그 문서 자신이 소스), 실측 스파이크는 발견 항목에 인라인 전사. 사용자 결정 문항 Q1~Q10이 §4에 배치 회신용으로 정리돼 있다. 커밋 전 `/code-review`가 이 문서 자체의 결함 7건을 잡아 반영됐다(각 항목의 `[code-review 정정/추가]` 표시). **⭐ [2026-08-26] 전량 처리·반영 완료** — 그 문서는 이제 **발견 당시의 기록**이라 각 항목의 "갈래"는 선택 전 목록이니 그대로 믿지 말 것), `pre-implementation-handtrace-round8-followup.md`(**[2026-08-26 신설] 8라운드의 결정과 근거가 여기 소스다** — Q1~Q10을 사용자와 대화형으로 처리한 기록. **역전은 없고** 전부 "7라운드 확정이 `base/`에 내려앉을 때 생긴 누락·충돌"을 닫은 것. ⭐ 사용자가 **문항의 전제 자체를 정정한 것이 둘** 있다(Ref 콜백 ↔ Observer 콜백은 애초에 통합 대상이 아니다 / `H-118`은 소유권 문제가 아니라 문장이 틀린 것) — 결정만 읽지 말고 그 두 절을 볼 것), `pre-implementation-handtrace-round9-brief.md`(**[2026-08-26 신설]** 9라운드를 돌릴 감사자에게 주는 **지시서** — 발견 보고가 아니라 그 앞단이다. 이런 지시서를 저장하는 건 이번이 처음으로, 7·8라운드 것은 대화에만 있었고 저장되지 않았다(8라운드 본문이 인용하는 "감사 지시서 §2"가 코퍼스 어디에도 없는 이유). 스코프를 **커밋 `9dd8213` 하나의 델타**로 정의한 게 핵심 — 8라운드 결정 반영과 그 뒤 `/code-review high` 7패스 수정이 전부 그 커밋에 들어 있고 아무도 트레이싱한 적이 없다. 레인 셋(A: 그 델타의 상호 간섭 / C: `audit/handtrace-round7-reference-impl/`을 지금 계약으로 갱신해 실행 / B: 8라운드 §6이 남긴 M5+ 값 단위 트레이싱)과 우선순위 근거, `-round8-followup.md`가 적어둔 **반복 실패 모드 7개**를 사냥 목록으로 옮겨 실었다. 각도 문자(A~H)는 8라운드와 같은 걸 유지해 상호참조가 되게 했다), `pre-implementation-handtrace-round9.md`(**[2026-08-26]** 9라운드 발견 보고 — 레인 A(`9dd8213` 델타 상호 간섭)·C(참조 구현을 현재 계약으로 재전사해 `luau` 실행)·G(Luau 사실 재확인)·D(ROADMAP M2 시뮬레이션)·B(M5+ 값 단위, 첫 시도) — 발견 `H-124`~`H-141`, 🔴 둘(`recompute`의 `lengthList[i]` nil 읽기 / 재마운트 시 `_baseObserver` 미바인드 캐시 stale) 다 실측 재현. §4 배치 문항 Q1~Q10 + §5 이상 없음(⭐ `keyof<{}>` 빈 Store 실측으로 클린) + §6), `pre-implementation-handtrace-round9-followup.md`(**[2026-08-27] 9라운드 결정의 소스 — 전량 처리 완료** — Q1(`recompute` 되감기 판정을 읽기 앞으로) / Q2(`Offset`·`_baseObserver`를 Slot 생성자로, `materializeSlotTree` 순서, `_destroyed` 플래그) / Q3(`element → index`는 `bk.indexOfElement` 하나 — 사용자가 정한 적 없는 `token` 폐기, `H-137` 소멸, `H-141` 신설) / Q4(`EffectHandle` 네 진입점 의사코드) / Q5(M2에 `Ref` 최소형) / Q6(`WeakUnsubscribe` 관대) / Q7(폐기 블록 `archive/`) / Q8(`InstanceChildHandler` 부기) / **Q9(문항 전제가 틀림 — Tween 절 스케치 한 줄 복사 오류)** / Q10(`reconcile` 배치 Blocker) + `H-138`(숏핸드 우선순위) / `H-139`(`New`/`drive` 파이프라인 의사코드) / **`H-142`(props에 `Parent` 금지 — 순서 문제 소멸)** / **`H-143`~`H-146`**(`/code-review`가 낸 새 메커니즘 넷 — 전부 권고 (a), `H-144`는 사용자 요청으로 재구독 뒤 epoch·Blocker 상호작용을 재트레이싱한 기록 포함). 진행 표가 상태의 소스, 사용자 회신 원문 셋 인용; **[2026-08-28]** `H-143`~`H-146` 반영분의 감사 8라운드 표와 `/code-review high` 기록도 여기), `pre-implementation-handtrace-round10-brief.md`(**[2026-08-28 신설]** 10라운드 지시서 — 델타가 아니라 **광범위** 스코프(M2~M8, 레인 A 반응형 코어 전체 / C 참조 구현 갱신·실행 / B 디스패치·Slot / D 타입·M1 코드), 신선한 탐사자가 한 번에 문항지를 만들어 사용자가 배치로 결정하게 하는 것이 목적), `pre-implementation-handtrace-round10.md`(**[2026-08-28 신설, 회신 대기]** 10라운드 발견 보고 + §4 배치 문항지 — 씨앗은 `/code-review`가 낸 `H-147`~`H-149`(죽은 핸들에서 `Rerun` / `Parent` 거부 전용 문구는 새 메커니즘 / Observer `Subscribe` 위임과 `level 2`), 탐사자 발견은 `H-150`부터. 레인 C 실행 기록은 `audit/handtrace-round10-reference-impl/`. **[2026-08-28 탐사 완료]** 🔴 0 / 🟡 5 / 🟢 3, §4 문항 7건(기존 3 + `H-150` `Effect._blocker` 죽은 부품 / `H-151` 게이트 우회 계약 / `H-153` Store 예약 이름 런타임 가드 / `H-154` `InstanceChildHandler` dedup) — 전부 권고 (a). 레인 A·C 완료, B 부분, D `./scripts/test.sh` ALL PASS), `pre-implementation-handtrace-round10-followup.md`(**[2026-08-28] 10라운드 결정의 소스 — 전량 처리 완료.** 사용자가 *"하나하나 같이 보자"*라 대화형으로 처리. **문항의 전제를 뒤집은 것 둘**: `H-147`은 "죽은 핸들에서 `Rerun`"이 아니라 **`fn`/cleanup이 자기 구독을 바꿀 수 있다는 허용 자체가 모순**(→ (A) 금지, `H-143` 소멸, `rawRerun(force)`/`Rerun` 분리), `H-148`은 "문구"가 아니라 **루트 마운트 표면의 부재**(→ `Claim` + `D.Mapper`, `base/claim-plan.md`). 나머지: `H-149` Observer 진입점 인라인 / `H-150` `_blocker` 제거 / `H-151` `Refresh` 캐치업 폐기 — 게이트는 emit 경로만 미룬다 / `H-153` Store 예약 이름 가드 / `H-154` dedup. 새로 생긴 `H-158`(`:Block` 슈가)도 같은 날 확정 — 폐기, `state:Apply(blocker)`. **[2026-08-28 후속 3]** `Claim` 갈래 여덟 전량 확정 → `base/claim-plan.md`로 승격, 그 경위도 이 파일 끝 절). `m2-implementation-round11-brief.md`(**[2026-08-28 신설]** **M2 자율 구현 규약**이자 단위 끝마다 띄우는 탐사자 지시서 — 세 갈래 분류(자율 수정 / §4 배치 / 즉시 중단), 단위 넷, 두 층 커밋 게이트, 첫 단위 계획은 §6), `m2-implementation-round11.md`(**[2026-08-28 신설]** M2 구현 중 발견 원문 + §4 배치 문항지, 번호는 `H-165`부터 — 종이 트레이싱이 아니라 실제 코드를 옮기고 돌리다 나온 것. **[2026-08-31 개명]** 원래 `pre-implementation-handtrace-round11*`이었으나 구현 **중** 문서라 이름이 틀려 사용자 지시로 개명 — brief도 같이). **⭐ [2026-08-31 명명 규약, 사용자 확정]** 구현 라운드 파일은 **`mN-implementation-roundNN`** — 라운드 번호는 마일스톤을 가로질러 **단순 증가**하고(다음 라운드는 어느 마일스톤이든 round12), 마일스톤 접두가 어느 마일스톤의 라운드인지 담는다. 근거: *"m3 을 진행하다 m2 에 하자가 있음을 확인하면 다시 m2 로 올라가 round 가 진행되다 돌아오는 경우도 있을것 … 접두가 둘 다 있는게 정보를 온전히 담아줘"* — 번호만으로는 순서가, 접두만으로는 소속이 안 담긴다. 지시서도 같이 남길 것(`-roundNN-brief.md`). round1~10의 옛 이름(`pre-implementation-*`)은 그대로 둔다 — 실제로 구현 전 라운드였으니 이름이 맞다. `m3-implementation-round12-brief.md`(**[2026-08-31 신설, 같은 날 §0·§6 확정]** **M3 자율 구현 규약**이자 단위 끝 탐사자 지시서 — §0 세 문항(Q1 규약 재사용/Q2 단위 넷/Q3 M2 하자 혼입 규칙) 전부 권고 (a) 채택, §6 첫 단위(코어) 계획도 승인. M2 brief와 같은 지위), `m3-implementation-round12.md`(**[2026-08-31 신설]** M3 구현 중 발견 원문 + §4 배치 문항지, 번호는 `H-212`부터 — 상태의 소스는 그 파일 자신) | | `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-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` | diff --git a/.claude/project-context.md b/.claude/project-context.md index 3f1c400..105cb83 100644 --- a/.claude/project-context.md +++ b/.claude/project-context.md @@ -11,10 +11,12 @@ Roblox 엔진에서 동작하는 DOMless UI 렌더러 **quad**를 처음부터 길게 잡음. **⭐ [2026-08-31 기준] M0(스파이크 검증)/M1(스캐폴딩)/M2(반응형 코어 — -Source/State/Store) 완료, 다음은 M3(디스패치 엔진)** — M2는 자율 구현 +Source/State/Store) 완료, M3(디스패치 엔진) 진행 중** — M2는 자율 구현 구간(규약 `qa-request/m2-implementation-round11-brief.md`, 발견 `-round11.md`) 으로 2026-08-28 착수~08-31 종결(단위 넷 구현·감사·리뷰·탐사 완료, §4 문항· -코드 마커 0). **M3 착수 전 새 자율 규약 문항은 사용자와 정할 것** — +코드 마커 0). **M3도 같은 방식의 자율 구간으로 2026-08-31 착수** — 규약은 +`qa-request/m3-implementation-round12-brief.md`(같은 날 §0 세 문항·§6 첫 단위 +계획 사용자 확정), 발견은 `-round12.md`(`H-212`부터). 진행 상태는 `.claude/todos.md` 00번이 소스(마일스톤이 넘어갈 때 루트 `CLAUDE.md` 머리말도 같이 고칠 것 — 같은 상태를 두 곳이 서술하고 있음). **⚠️ [2026-08-24] M2와 M3의 번호·순서가 맞바뀌었다** — 열려 있던 마일스톤 순서 문제가 (a) 순서 diff --git a/.claude/qa-request/m3-implementation-round12-brief.md b/.claude/qa-request/m3-implementation-round12-brief.md index e1c475d..a60cf18 100644 --- a/.claude/qa-request/m3-implementation-round12-brief.md +++ b/.claude/qa-request/m3-implementation-round12-brief.md @@ -1,10 +1,10 @@ -# M3 자율 구현 규약(안) — 12라운드 지시서 + 착수 문항지 +# M3 자율 구현 규약 — 12라운드 지시서 + 착수 문항지 -> **이 파일이 무엇인가**: **[2026-08-31 신설, §0 회신 대기]** M3(디스패치 엔진) -> 구현 구간의 규약 초안이자 착수 문항지다. **§0 표가 사용자가 읽을 유일한 -> 자리** — 회신이 §0에 기록되면 이 파일이 M2의 `m2-implementation-round11-brief.md`와 -> 같은 지위(규약 소스 + 단위 끝 탐사자 지시서)가 된다. 산출물(발견 문서)은 -> 착수 시 `m3-implementation-round12.md`로 신설. +> **이 파일이 무엇인가**: **[2026-08-31 신설, 같은 날 §0·§6 회신 완료 — 규약 +> 확정]** M3(디스패치 엔진) 구현 구간의 규약이자 착수 문항지다. §0 세 문항과 +> §6 첫 단위 계획이 전부 확정돼(회신 기록은 §0 바로 아래), 이 파일은 M2의 +> `m2-implementation-round11-brief.md`와 같은 지위(규약 소스 + 단위 끝 탐사자 +> 지시서)다. 산출물(발견 문서)은 `m3-implementation-round12.md`. > > **명명**: `mN-implementation-roundNN` 규약(2026-08-31 사용자 확정, > `.claude/README.md` `qa-request/` 행이 소스) — 라운드 번호는 마일스톤을 @@ -24,6 +24,12 @@ | **Q2** | 단위 절단 | (a) **넷** — §1의 제안(코어 → 부기 → `None`/`Nil` 핸들러 → Leaf·가드·종합) / (b) 셋(코어+부기 합침 — 단위당 비용 커짐) / (c) 다른 절단 | **(a)** | 의존이 단방향(코어 → 부기(NilHandler가 부기 API를 등록) → 핸들러 → 가드·종합)이고, M2와 단위당 규모가 비슷해 비용 감각이 검증된 눈금 그대로다. 단위 2가 M2 소비의 첫 실전(Observer 콜백·Blocker·접두합 캐시)이라 M2 결함이 있다면 일찍 드러난다 | | **Q3** | M3 진행 중 **M2 하자**가 나올 때 | (a) 경미한 것(문서 stale·주석·기존 계약 **안**의 코드 오류)은 M3 라운드 파일(`m3-implementation-round12.md`)에 `H-nnn`으로 기록하고 ① 갈래로 자율 수정, **M2 설계 결정이 필요한 규모**(새 메커니즘·확정 역전)면 그때 `m2-implementation-round13`(그 시점의 다음 번호)을 새로 열어 §4 배치 문항으로 / (b) 규모 무관 전부 M3 파일에 / (c) 규모 무관 전부 M2 파일 신설 | **(a)** | 명명 규약의 취지(*"m3 을 진행하다 m2 에 하자가 있음을 확인하면 다시 m2 로 올라가 round 가 진행되다 돌아오는 경우"*) 그대로 — 접두가 소속을 담으려면 **결정이 필요한 것만** M2 라운드로 승격하고, 잔손질까지 파일을 쪼개면 발견 흐름이 갈라진다 | +**⭐ [2026-08-31 회신 — 전량 확정]** 사용자가 대화형 선택지로 **Q1·Q2·Q3 전부 +권고 (a)를 채택**했고, **§6 첫 단위(코어) 계획도 그대로 승인**했다("승인 — +이대로 착수" 선택; 세션은 사용자 지시 *"M3 를 작업 시작하자. +m3-implementation-round12 문서를 보면 돼"*로 열렸다). 이로써 이 파일이 M3 +규약 소스다 — 발견 번호 `H-212`부터, M2 하자는 Q3 (a) 규칙. + **통보(문항 아님 — 규약·코드 배치라 여기 명시만)**: 발견 문서는 착수 시 `m3-implementation-round12.md` 신설, 번호 `H-212`부터. **mock 확장은 불필요** — M3 핸들러가 부르는 건 quad-base 자기 부기 API(`setLength` 등)뿐이고 엔진 @@ -98,11 +104,33 @@ M2 §5를 그대로 쓰되 치환 셋: 대상 라운드 파일은 무효화 표)·`bind-system-plan.md`가 중심. `git stash` 금지·실행 우선·한 줄 대조·`grep -rn "TODO(H-"` 전수 확인은 동일. -## §6 첫 단위(코어) 작업 계획 — §0 회신 후 확정 +## §6 첫 단위(코어) 작업 계획 — **[2026-08-31 사용자 확정]** ("승인 — 이대로 착수") -Q1·Q2가 (a)로 닫히면 여기 M2 §6과 같은 급의 파일·spec 표를 채워 사용자 -확정을 받는다(코드 배치는 그 계획이 소스). 초안 요지만: `Handler.luau`는 -계약 타입만 담는 잎 / `Dispatch/init.luau`가 `InitDispatch(module)` 팩토리 -(`module-lifecycle-plan.md`의 예시 그대로 — `H-174` (a)의 원형) / -`chains`는 `Relate` 인스턴스 / spec은 `spec.dispatch.luau` + spec-로컬 -테스트 핸들러. +여기 적힌 것은 `base/`가 정하지 않은 **코드 배치·범위 절단**이라 이 계획이 +소스다(M2 §6과 같은 지위) — 설계 결정이 아니다. + +**소스 (`quad-base/src/`, 배치는 `architecture.md` 소스 트리 그대로)** + +| 파일 | 내용 | 옮겨 적는 절 | +|---|---|---| +| `Dispatch/Handler.luau` | 계약 **타입만** 담는 잎 — `Handler` 타입(`isHandlable(inst,k,v): boolean` / `priority: number` / `process(inst,k,v,index) -> (any?) -> ()`). Dispatch를 되참조하지 않는다 | `dispatch-core-plan.md` "핸들러 계약" 절, "Dispatch는 프리미티브가 아니다" 절의 단방향 의존 | +| `Dispatch/init.luau` | `InitDispatch(module)` 팩토리(`module-lifecycle-plan.md` "New()의 내부 구성" 예시 그대로 — `H-174` (a)) — `module.Dispatch`에: `getHandler`(우선순위 스캔·첫 매치, 매치 실패는 `Brand`+`typeof(v)` 출력 + provider 안내 즉시 error, 실패 메시지는 클로저 지연 생성) / `process`(하강 diff (A)/(B) 의사코드 그대로 — retractor `nil` 반환 즉시 error 양쪽, (B) 점유 마커 선행, `chains:SetStrong`이 `h.process` **전**, (A) 소비 직후 `NOOP` 교체) / 3-인자 `retractFrom`(꼬리 역순, 구멍이면 error) / `addHandler`(등록 시점 정렬, 동률 감지 print는 `module.debug`가 참일 때만) / `listHandlers`(항상 호출 가능, 반환만 하는 순수 조회) / `drive`(범위는 아래 행). `chains`는 별도 파일이 아니라 `InitDispatch`가 만드는 `Relate` **인스턴스별** 값. `HANDLER_PRIORITY_HIGH`/`_NORMAL`/`_LOW`/`_FALLBACK` 상수는 이 파일 정의 + `module.Dispatch`에 재노출(Handler.luau를 타입 전용 잎으로 유지) | "Dispatch 체인" 절 의사코드(`H-103` 주석 포함), "우선순위 동률/매치 실패 처리", `H-162`(NOOP = `Void`) | +| (범위 절단) `drive` | 이 단위에선 파이프라인 (b) **본체 단일 일반화 `for`만**(각 `(k,v)`에 `process(inst,k,v,1)`). ⓪/⓪' 배치 Blocker 게이팅은 **단위 2**(`getBlocker`/`getBookkeeping`/`recompute`가 생기는 자리)에서 배선, (a) pre-pass/(c) `postRefList`는 **M8**(`PreRef`/`PostRef` 본체·소진 센티널이 생기는 자리). 정본과의 차이는 코드 헤더 주석에 명시 | `bind-system-plan.md` "`New(name)(props)` 파이프라인 의사코드" 절 | +| `quad-types/src/init.luau` | `Quad` 타입에 `Dispatch` 필드 + `Handler` 타입 재수출(`H-25` — 마일스톤마다 갱신 규칙의 M3 몫) | `quad-types-plan.md` "`Quad` 타입 — 확정된 표면" 절 | +| `init.luau`(최상위) | `module:RunInit(InitDispatch)` 추가 | `module-lifecycle-plan.md` | + +**테스트 (`quad-base/test/`)** — 테스트 핸들러는 §0 통보대로 spec 파일 로컬 +(실핸들러가 아직 없음). `inst`는 평범한 테이블(base 계약상 `inst`는 백엔드 +재량이라 mock 확장 불필요). + +| 파일 | 검증하는 계약 | +|---|---| +| `spec.dispatch.luau` | `getHandler` 우선순위 스캔·첫 매치 · 매치 실패 error 메시지(Brand/typeof/provider 안내) · (A) 분기: retractor가 **새 값**을 받고 아래 체인은 안 건드림, 같은 자리 클로저 교체 · (B) 분기: 그 자리부터 꼬리 역순 철거 후 재설치 · retractor 반환 생략 즉시 error((A)/(B) 모두) · `retractFrom` 꼬리 역순·항상 소비(`list[i]=nil`)·구멍 error · 재귀 위임 `index+1`/다른 키 위임 항상 `1` · 래핑 핸들러 2단 체인(같은 핸들러가 인덱스 N·N+1 — `State>` 유사 구조를 spec 핸들러로) · `SetStrong` 선행(재귀 위임 시 하위 retractor 유실 없음 — 2026-08-13 감사 버그의 음성 대조) · 조건부 재위임 핸들러의 `retractFrom(index+1)` 직접 호출 경로(체크리스트 8) · `addHandler` 정렬·동률 경고가 `module.debug` 게이팅 · `listHandlers` 반환만 · `New()` 인스턴스 간 레지스트리/체인 격리 | +| `spec.drive.luau` | 단일 일반화 `for` 한 번으로 배열 파트 **전체**가 해시 파트보다 먼저 + 배열 안에서는 index 순서(`F-4-1` — 재작성 대기 스파이크 `01`이 물어야 했던 언어 동작 질문을 여기서 실측) · 모든 진입이 index 1 | + +- 스파이크 `01` 재작성(`luau-test/rewrite-required/01-*`)은 **따로 안 한다** — + `spec.drive.luau`가 같은 질문을 상시 회귀로 실측하므로. `STATUS.md`에 그 + 취지를 기록하고 재작성 대기 목록에서 정리(이 처분도 §0 회신에 묶임). + +**커밋 단위**: M2와 같게 모듈마다 하나(구현 + spec + `base/` 정정이 있으면 +같은 커밋), 단위 끝 절차는 §4. diff --git a/.claude/qa-request/m3-implementation-round12.md b/.claude/qa-request/m3-implementation-round12.md index 1ab8078..b4ad708 100644 --- a/.claude/qa-request/m3-implementation-round12.md +++ b/.claude/qa-request/m3-implementation-round12.md @@ -1,6 +1,35 @@ -# M3 구현 **12라운드** — 발견 원문 + 배치 문항지 (스텁) +# M3 구현 **12라운드** — 발견 원문 + 배치 문항지 -> **[2026-08-31 스텁]** 규약 문항지(`m3-implementation-round12-brief.md`)의 -> §0 회신이 아직이라 **비어 있다** — M3 착수와 함께 round11 파일과 같은 -> 구조(요약 표 / 상세 / §4 배치 문항 / §5 이상 없음 / §6 남은 의심)로 -> 채워진다. 발견 번호는 **`H-212`부터**(round11이 `H-211`까지 썼다). +> **이 파일이 무엇인가**: **[2026-08-31 신설]** M3 자율 구현 구간 +> (`m3-implementation-round12-brief.md`가 규약, 같은 날 §0·§6 확정)에서 나온 +> 발견 전부. 실제 코드를 옮기고 돌리다 나온 것이다. 번호는 **`H-212`부터** +> (11라운드가 `H-211`까지 썼다). +> +> **갈래 표기**(규약 §2): **①** 자율로 고침(같은 커밋에서 `base/`+코드) / +> **②** §4 표에 쌓아 배치 회신 대기 / **③** 즉시 중단·보고. M2 하자는 +> 규약 §0 Q3 (a) — 경미하면 여기 ①, 설계 결정 규모면 그때 +> `m2-implementation-round13`을 새로 연다. +> +> **상태의 소스는 이 파일 자신** — 요약 표의 상태 열이 최신. + +## 요약 표 + +| 번호 | 갈래 | 단위 | 심각도 | 한 줄 | 상태 | +|---|---|---|---|---|---| +| (아직 없음) | | | | | | + +## §4 배치 문항지 (사용자가 읽을 유일한 자리) + +**[2026-08-31 기준] 열린 문항 없음.** + +| 번호 | 무엇 | 선택지 | 권고 | 권고 근거 | +|---|---|---|---|---| +| (아직 없음) | | | | | + +## §5 이상 없음 확인 (탐사자·구현이 확인만 하고 문제 없었던 자리) + +(아직 없음) + +## §6 남은 의심 (발견은 아니지만 다음 라운드가 파볼 자리) + +(아직 없음) diff --git a/.claude/todos.md b/.claude/todos.md index 81790ff..cd78201 100644 --- a/.claude/todos.md +++ b/.claude/todos.md @@ -23,10 +23,15 @@ 개명(구현 중 문서라 옛 이름이 안 맞았음; 명명 규약 `mN-implementation-roundNN`은 `.claude/README.md` `qa-request/` 행이 소스 — 라운드 번호는 마일스톤을 가로질러 단순 증가). M2 종료 보고도 전달 — **M2 종결.** - **다음 액션: M3(디스패치 엔진) 착수 — [2026-08-31] 규약 문항지 - `qa-request/m3-implementation-round12-brief.md` 작성 완료, §0 표(문항 셋) - 사용자 회신 대기.** 회신되면 그 파일이 M3 규약 소스가 되고 §6(첫 단위 - 계획) 확정 후 착수(2026-08-29 체크포인트의 "M3은 새 규약 문항" 이행). + **다음 액션 이행됨 — ⭐⭐⭐ [2026-08-31] M3(디스패치 엔진) 자율 구현 구간 + 착수.** 규약 문항지 `qa-request/m3-implementation-round12-brief.md`의 §0 + 세 문항(규약 재사용/단위 넷/M2 하자 혼입 규칙)이 **전부 권고 (a)로 사용자 + 확정**됐고 §6 첫 단위(코어) 계획도 승인됨("승인 — 이대로 착수") — 그 + 파일이 M3 규약 소스다(2026-08-29 체크포인트의 "M3은 새 규약 문항" 이행). + 발견·배치 문항은 `-round12.md`(`H-212`부터), **진행 상태의 소스는 + `ROADMAP.md` M3 체크박스** — 여기서 세지 않는다. 단위 넷: ① Handler + 계약+디스패치 코어 → ② Length/Offset 부기 → ③ `None`+`NoneHandler`/ + `NilHandler` → ④ Leaf+가드 등록+종합 테스트(brief §1이 소스). 아래는 착수 전(2026-08-26) 서술: **[2026-08-26] 8라운드까지 전부 처리 완료 — M2 착수 게이트가 0이다.** diff --git a/CLAUDE.md b/CLAUDE.md index 8f4df19..e093503 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,12 +2,14 @@ Roblox 엔진용 DOMless UI 렌더러 **quad**를 처음부터 다시 짜는 프로젝트. **⭐ [2026-08-31 기준] M0(스파이크 검증)/M1(스캐폴딩)/M2(반응형 코어 — -Source/State/Store)까지 완료, 다음은 M3(디스패치 엔진)** — M2는 자율 구현 +Source/State/Store)까지 완료, **M3(디스패치 엔진) 진행 중**** — M2는 자율 구현 구간(규약 `.claude/qa-request/m2-implementation-round11-brief.md`, 발견·배치 문항 `-round11.md`)으로 돌아 2026-08-28 착수~08-31 종결: 단위 넷 구현·감사· 리뷰·탐사 완료, `ROADMAP.md` M2 체크박스 전부 `[x]`, §4 문항·코드 마커 0. -**M3 착수 전에 새 자율 규약 문항을 사용자와 정할 것**(`.claude/todos.md` -00번이 소스). **⚠️ [2026-08-24] M2와 M3의 +**M3도 같은 방식의 자율 구간** — 규약은 +`.claude/qa-request/m3-implementation-round12-brief.md`(2026-08-31 §0·§6 +사용자 확정, 단위 넷·발견 `H-212`부터 `-round12.md`), 진행 상태는 +`.claude/todos.md` 00번이 소스. **⚠️ [2026-08-24] M2와 M3의 번호·순서가 맞바뀌었다** — 예전엔 M2=디스패치, M3=반응형이었는데 의존이 한 방향(디스패치 → 반응형)이라 반응형을 먼저 짓기로 확정했다. 그래서 **2026-08-24 이전에 쓰인 `session/`·`archive/`·`qa-request/` 문서의