docs: PostRef 반영 후 코퍼스 정합성 감사 — 모순 5건 정정
- CLAUDE.md 아홉 번째 세션 항목 제목이 "미보장으로 역전"으로 남아 본문
(철회·보장 유지)과 정면 모순 → 정정
- CLAUDE.md 여섯 번째 세션 항목이 "OnRendered는 지금 의도적으로 구현 안 함"을
현재형 확정으로 서술 중 → 아홉 번째 세션 역전 포인터 추가
- research/documentation-content-map.md:
(1) "PreRef는 retract 체인에 아예 안 올라감" — 2026-08-14 두 번째 세션의
ProcessedPreRef 정정이 미반영된 옛 근거였음(이번 변경과 무관한 기존
stale) → 정정, PostRef도 동일하다고 명시
(2) hook/pre-hook 프레이밍에 PostRef(post-hook) 3항 확장 + 순서 보장
왕복을 에세이 소재로 메모
(3) 서베이가 2026-08-06 파일 구성 기준이라 bind-system-plan.md 포인터가
전부 분할 전 것 → 파일 상단에 읽는 법 배너
- luau-test/README.md: 13번 재작성 시 PostRef까지 커버할 것
- base/lifecycle-hooks-plan.md: 시그니처의 `Instance`는 가독성용 표기이고
실제로는 백엔드 타입을 모르는 자리라는 주석(quad-base 소속과의 정합)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
f9f0babc87
commit
2c575d91f0
4 changed files with 50 additions and 15 deletions
|
|
@ -64,6 +64,11 @@ local function OnDestroyed(fn: () -> ()): EffectHandle
|
|||
end
|
||||
```
|
||||
|
||||
*(위 시그니처의 `Instance`는 읽기 편하라고 quad-roblox 기준으로 적은
|
||||
것 — 이 셋은 quad-base 소속이므로 실제 선언은 `Ref<T>`가 그렇듯 백엔드
|
||||
Instance 타입을 모르는 제네릭/불투명 타입 자리로 남음. `bindLifetime(inst,
|
||||
value)`류 base 유틸을 문서가 `inst`라고만 부르는 것과 같은 관례.)*
|
||||
|
||||
호출 즉시 `PreRef():Callback(fn)`/`PostRef():Callback(fn)`/`Effect(...)`가
|
||||
실행되고, children 배열에 실제로 놓이는 건 **그 결과인 `PreRef`/`PostRef`/
|
||||
`EffectHandle` 인스턴스 자체**임 — `OnCreated`라는 이름이나 개념은 이
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ ROADMAP 항목 근거인지, 어떻게 실행하는지, 실행 후 뭘 확인해
|
|||
| `10-roblox-studio-checks.server.luau` (Studio 전용) | **[⚠️ 2026-08-14 다섯 번째 세션: A 섹션이 폐기된 모델을 검증 중 → `rewrite-required/`]** (A) `bindLifetime`/`unbindLifetime`/`canExecute`의 gcconn 트릭 + 이중 바인딩 게이트(Destroy 시 Connected 전환 포함), (B) Attribute의 Instance 참조 타입 지원, (C) CollectionService 태그/GetTagged 왕복. **A는 재작성 대상** — 파일 속 `canBound`, `bindLifetime`의 `value.Subscribed = true` 세팅, 2-인자 `canExecute(inst, value)`는 전부 폐기됨(게이트는 `if canExecute(v) then error(...) end` 하나, `canExecute`는 `value` 단독 1-인자, gcconn/gchold는 **Instance 생성 시점**에 생성). **[2026-08-13]** A 섹션 앞부분(ClassName 신호 미발화, Destroy 시 Connected 즉시 전환)은 사용자 자작 스크립트로 부분 확인됐고 **새 모델에서도 그대로 유효**(오히려 더 중요 — `canExecute`가 `.Connected`를 직접 읽는 게 leaf 경로 판정의 전부), `audit/gcconn-trick-verification.md` 참고. 이중 바인딩 게이트/재바인딩 허용/B/C는 이 공식 파일로 아직 확인 안 됨 | `lifecycle-pattern.md` "`bindLifetime`/`canExecute`/`unbindLifetime` — 확정", `archive/canexecute-inst-arg-reversed.md`, `source-state-plan.md` "이중 바인딩 금지", CLAUDE.md 2026-08-06 세션, `debug-tooling-plan.md` |
|
||||
| `11-modifier-illegal-value-error.luau` | Modifier 필드에 Ref/PreRef/Observer/Effect/Slot/Modifier가 들어오면 즉시 error, State/Source가 확정하는 값이 Modifier면 즉시 error(2026-08-09 세션에 "UB"에서 전환된 규칙) | `modifier-plan.md` "핸들러 계층 값 즉시 error" 절 + 7번 절 |
|
||||
| `12-type-attribute-generic-key-narrowing.luau` (타입체크 전용) | `[AttributeKey<<T>> "name"] = value`(구 `Attribute<<T>>`)처럼 제네릭 DI 키를 쓸 때 `value`의 타입이 실제로 `T`로 좁혀지는지 — base 문서 자신이 "미검증"이라 명시한 항목 | `attribute-plan.md` "[실측 필요, M0/M10]" (2026-08-09 열한 번째 세션 신설) |
|
||||
| `13-type-ref-preref-subtype.luau` | (A, 타입) `PreRef<T>`가 `Ref<T>`를 구조적으로 만족하는지, (B, 런타임) `isRef`/`isPreRef` 합성이 재정정대로 동작하는지(`isRef(preRefInstance)`가 이제 `true`) + Leaf 핸들러가 `isRef(v) and not isPreRef(v)`로 명시적으로 좁혀야 하는 이유 | `brand-plan.md`의 `Brand` 절(2026-08-09 열한 번째 세션 재정정) |
|
||||
| `13-type-ref-preref-subtype.luau` | (A, 타입) `PreRef<T>`가 `Ref<T>`를 구조적으로 만족하는지, (B, 런타임) `isRef`/`isPreRef` 합성이 재정정대로 동작하는지(`isRef(preRefInstance)`가 이제 `true`) + Leaf 핸들러가 `isRef(v) and not isPreRef(v)`로 명시적으로 좁혀야 하는 이유. **[2026-08-14 아홉 번째 세션] 재작성 시 `PostRef`도 같이 커버할 것** — 같은 `Ref` 런타임 재사용 + 브랜드 태그만 다른 형제라 A/B 둘 다 그대로 확장되고, Leaf predicate도 `isRef(v) and not isPreRef(v) and not isPostRef(v)`로 늘어남 | `brand-plan.md`의 `Brand` 절(2026-08-09 열한 번째 세션 재정정) |
|
||||
| `14-type-nilable-default-overload.luau` (타입체크 전용) | `Source(default)`/`Ref(default)`의 `default` 생략이 `T`가 nilable일 때만 안전하다는 캐비엇을, 함수 오버로드(교차 타입)로 실제로 타입 레벨에서 막을 수 있는지 | `source-state-plan.md` "State는 쓰기 대상이 아님" 절의 `default` 생략 캐비엇 |
|
||||
| `15-type-compute-trailing-deps-typepack.luau` (타입체크 전용) | `:Compute(fn, ...)`의 trailing deps를 `fn`에 위치 인자(lazy State 핸들)로도 노출하는 확장, 최종 시그니처 `fn(self, previous?, ...deps)` — 이형(heterogeneous) 다중 deps를 제네릭 타입 팩(`U...`)으로 표현 가능한지, `previous?`가 팩 앞(정정된 순서)에서만 통과하고 팩 뒤(옛 순서)에서는 막히는지 | `source-state-plan.md` "trailing deps를 fn에 lazy positional 인자로도 노출" 절(2026-08-11 후속 세션, 순서는 같은 날 세 번째 세션에 정정) |
|
||||
| `16-type-store-key-typefunction.luau` (타입체크 전용) | `Store<T>`가 `T`의 각 필드를 `Source`로 감싼 타입을 Luau `type function`(`types.newtable`/`:setproperty`/`ty:properties()`)으로 실제 합성 가능한지, 결과가 구조적으로 `Source<T>` 필드를 만족하는지 | `typing-limits.md` "`store.key` 레코드 필드 타이핑" 절(2026-08-12 열일곱 번째 세션), `pre-implementation-audit.md` 1-10 |
|
||||
|
|
|
|||
|
|
@ -7,6 +7,17 @@
|
|||
시점은 여전히 구현 우선(`CLAUDE.md` "지금 할 일" 1번). 나중에 실제 문서화를
|
||||
시작할 때 이 맵을 목차/우선순위표로 쓰면 됨.
|
||||
|
||||
> **⚠️ [2026-08-14 아홉 번째 세션 감사] 이 서베이는 2026-08-06 시점의
|
||||
> `base/` 파일 구성을 기준으로 작성됐음.** 그 뒤 `bind-system-plan.md`가
|
||||
> 세 번(2026-08-13 아홉 번째 / 2026-08-13 열네 번째 / 2026-08-14 일곱 번째
|
||||
> 세션) 쪼개져 지금은 203줄짜리 분할 색인만 남았으므로, **아래에서
|
||||
> `bind-system-plan.md`를 가리키는 포인터는 대부분 실제로는
|
||||
> `source-state-plan.md`/`store-plan.md`/`ref-plan.md`/`event-plan.md`/
|
||||
> `brand-plan.md`/`dispatch-core-plan.md` 중 하나를 뜻함**(그 문서 맨 위의
|
||||
> 분할 표에서 어디로 갔는지 바로 찾을 수 있음). 콘텐츠 분류 자체는 여전히
|
||||
> 유효해서 경로만 이 규칙으로 읽으면 되고, 실제 문서화 착수 시점에 한
|
||||
> 번에 정규화할 것.
|
||||
|
||||
**api↔심화 연결 원칙(사용자 확정)**: api 문서는 항목마다 설명을 간략하게
|
||||
유지하고, 근거·내부 동작까지 파고드는 내용은 심화 섹션으로 링크("더 알아보기
|
||||
→ 심화")하는 방식으로 연결. 아래 [api] 항목 중 "→심화"가 붙은 것들이 이
|
||||
|
|
@ -205,17 +216,28 @@ additional-primitives-plan.md`의 "문서화 백로그" 절이 원자료)**:
|
|||
`(v=Ref)` 매치 핸들러로 처리돼 다른 핸들러들과
|
||||
같은 우선순위 스캔에 참여한다는 의미에서 "hook"(순서 등록 가능, 다른
|
||||
값으로 교체되면 `retract`로 취소됨)에 가깝고, `PreRef`는 그 스캔 밖의
|
||||
고정 pre-pass라는 의미에서 "pre-hook"(항상 최우선 고정, 순서/취소
|
||||
개념 자체가 다름)에 가깝다는 구분 — quadnomicon 에세이로 쓸 때 이
|
||||
고정 pre-pass에서 fire된다는 의미에서 "pre-hook"(항상 최우선 고정,
|
||||
취소 개념 자체가 다름)에 가깝다는 구분 — quadnomicon 에세이로 쓸 때 이
|
||||
"hook"/"pre-hook" 용어 자체를 채택할지만 아직 열려있음(복수 `PreRef`
|
||||
간 순서는 2026-08-07 아홉 번째 세션에서 해소됨 — 배열 index 순서
|
||||
그대로, 별도 규칙 없음, `ref-plan.md` "PreRef" 절 참고).
|
||||
그대로 **보장**, 별도 규칙 없음, `ref-plan.md` "PreRef" 절 참고.
|
||||
2026-08-14 아홉 번째 세션에 이 보장을 잠깐 미보장으로 뒤집었다가
|
||||
철회한 왕복이 있음 — `archive/preref-order-unguaranteed-withdrawn.md`,
|
||||
이것도 에세이 소재).
|
||||
**[2026-08-14 아홉 번째 세션] `PostRef`가 생겨 이 프레이밍은 3항이 됨**
|
||||
— "pre-hook / hook / post-hook"으로 자연히 확장되고, 특히
|
||||
`PostRef`("두 패스가 전부 끝난 뒤")가 **자기 서브트리 완성은 보장하되
|
||||
자기가 부모에 붙기 전**이라는 점은 React `componentDidMount`와의 대조
|
||||
소재로 좋음(`ref-plan.md`의 "`PostRef`" 절, `base/lifecycle-hooks-plan.md`).
|
||||
**[해소됨, 2026-08-12 여섯 번째 세션]** 취소 가능 여부 — PreRef는
|
||||
구조적으로 `retract` 체인에 아예 안 올라가므로 취소 개념 자체가 없고,
|
||||
대신 이미 fire된 PreRef를 재사용하면(두 번째 construction에 다시
|
||||
놓으면) 즉시 `error` — "1회용, 재할당 불가"로 확정. `ref-plan.md`
|
||||
"동적 경로로 도착한 PreRef는 런타임에도 명시적으로 에러" 절 바로 아래
|
||||
"PreRef는 '취소'라는 개념이 없다" 항목 참고.
|
||||
취소 개념 자체가 없고(**[정정, 2026-08-14 두 번째 세션]** 근거가
|
||||
"`retract` 체인에 아예 안 올라가서"에서 **"그 자리의 retract가 하드코딩된
|
||||
no-op이라 되돌릴 상태 자체가 없어서"**로 바뀜 — `ProcessedPreRef` 신설로
|
||||
소진된 슬롯도 이제 정상 `Dispatch.process` 경로를 타 체인에 올라감,
|
||||
`PostRef`도 동일), 대신 이미 fire된 PreRef를 재사용하면(두 번째
|
||||
construction에 다시 놓으면) 즉시 `error` — "1회용, 재할당 불가"로 확정.
|
||||
`ref-plan.md` "동적 경로로 도착한 PreRef는 런타임에도 명시적으로 에러"
|
||||
절 바로 아래 "PreRef는 '취소'라는 개념이 없다" 항목 참고.
|
||||
|
||||
7. **왜 `Compute(fn, ...)`는 여러 의존성을 편하게 받고 `Effect`/`Observer`는
|
||||
안 받는가** (2026-08-11 세션 원자료, `source-state-plan.md` "`:Compute(fn,
|
||||
|
|
@ -272,13 +294,16 @@ additional-primitives-plan.md`의 "문서화 백로그" 절이 원자료)**:
|
|||
완전히 확정(2026-08-09 열한 번째 세션엔 `Extract(index, newElement?)`로
|
||||
더 확장). `research/additional-primitives-plan.md`는 더 이상 열린
|
||||
항목 없음, 배경 자료로만 유지.
|
||||
- **"hook"/"pre-hook" 용어 채택 여부** (2026-08-07, 위 심화 후보 6번 참고)
|
||||
— `bind-system-plan.md`는 `PreRef`가 위치 무관 호이스팅이라는 것과 일반
|
||||
- **"hook"/"pre-hook"(+`PostRef` 이후로는 "post-hook") 용어 채택 여부**
|
||||
(2026-08-07, 위 심화 후보 6번 참고)
|
||||
— `ref-plan.md`(**[2026-08-13 아홉 번째 세션]** `bind-system-plan.md`에서
|
||||
분리됨, 옛 경로로 적혀 있던 것을 2026-08-14 감사에서 정정)는 `PreRef`가
|
||||
위치 무관 호이스팅이라는 것과 일반
|
||||
`Ref`가 우선순위 스캔에 참여한다는 것까지는 확정해뒀고(복수 `PreRef`
|
||||
간 순서=배열 index 순서, 동적 경로로 도착한 PreRef는 전용 Handler가
|
||||
즉시 error — 둘 다 아홉 번째 세션에서 추가 확정), **`PreRef`의 취소
|
||||
간 순서=배열 index 순서 보장, 동적 경로로 도착한 PreRef는 전용 Handler가
|
||||
즉시 error — 둘 다 2026-08-07 아홉 번째 세션에서 추가 확정), **`PreRef`의 취소
|
||||
가능성은 2026-08-12 여섯 번째 세션에 "취소 개념 없음, 재사용은 error"로
|
||||
해소됨**(위 심화 후보 6번, `bind-system-plan.md` 참고) — "hook 대
|
||||
해소됨**(위 심화 후보 6번) — "hook 대
|
||||
pre-hook"이라는 용어 자체를 문서화 시 채택할지만 아직 미정.
|
||||
|
||||
`PreRef` 취소 가능성 항목은 실제로는 `.claude/question.md`에 별도로
|
||||
|
|
|
|||
|
|
@ -1240,6 +1240,10 @@ PreRef pre-pass 한 스윕에서 `isPostRef`도 같이 소진해 `postRefList`
|
|||
될 것 같다는 구체 스케치를 남겨 백로그 후보로 보존 — 네 번째 세션이
|
||||
이 스케치를 이어받아 `ProcessedPreRef` 기반으로 갱신함(위 참고).
|
||||
`question.md`엔 안 올림(이미 "지금 안 함"으로 답이 나온 질문이라).
|
||||
**[역전, 같은 날 아홉 번째 세션]** 이 "지금은 구현 안 함" 결정은 뒤집혔음
|
||||
— `PostRef`/`OnRendered` 둘 다 채택 확정되어 `base/ref-plan.md`/
|
||||
`base/lifecycle-hooks-plan.md`로 승격됨(아래 아홉 번째 세션 항목).
|
||||
"공짜가 아니다"라는 판단 자체는 그대로 맞고, 그 비용을 지불하기로 한 것.
|
||||
`research/lifecycle-hooks-plan.md` 신설, README 인덱스 반영, 별도
|
||||
워크트리에서 작업 후 메인에 수동 반영(다른 세션이 동시에 메인에서
|
||||
작업 중이라 병합 타이밍을 사용자와 직접 조율) — 커밋 `9f9a68f`. 같은
|
||||
|
|
@ -1315,7 +1319,8 @@ pull-recompute+캐시가 막고 중복 **통지**는 안 접음(접으려면 `Bl
|
|||
`doc-check.py`는 참조 존재는 봐도 서술 간 모순은 못 봄.
|
||||
|
||||
**2026-08-14 아홉 번째 세션 — `PostRef` 확정·`OnRendered` 채택, 계열 안
|
||||
fire 순서 미보장으로 역전, `lifecycle-hooks-plan.md` base 승격**
|
||||
fire 순서는 미보장으로 갔다가 철회(보장 유지), `lifecycle-hooks-plan.md`
|
||||
base 승격**
|
||||
(`session/2026-08-14-09-postref-confirmed.md`)
|
||||
사용자가 백로그 후보로만 남아 있던 `PostRef`를 확정(선택지 (a) — pre-pass
|
||||
공동 수집 + 두 패스 뒤 `postRefList` 소비, "Pre-Post 둘을 지원 안 할 이유가
|
||||
|
|
|
|||
Loading…
Reference in a new issue