Commit graph

13 commits

Author SHA1 Message Date
e35905ceca
docs: 코퍼스 전체 감사 + canBound/canExecute 재분리, Ref 0-W 해소
전체 .claude/ 코퍼스를 doc-check.py + 6개 병렬 서브에이전트로 감사해
stale 세션 번호, 잘못된 인용, 자기모순 배너 등 15개 파일의 실제 사실
오류를 발견·수정. 이어서 question.md 0-W(같은 Ref 객체가 두 자리에
동시에 놓이는 문제)를 선택지 (a)로 확정 — RefLeafHandler가 새 Relate
없이 bindLifetime/unbindLifetime을 재사용해 이중 배치를 방지.

이 과정에서 bindLifetime의 이중 바인딩 가드(bound 문맥)와 State emit
전파 게이팅(execute 문맥)이 서로 다른 질문인데 canExecute 하나로
뭉쳐 있던 걸 발견 — canBound를 별도 진입점으로 재도입(판정 로직은
비공개 헬퍼 하나를 공유, 코드 중복 없음). Tag/Attribute의 미지원
백엔드 처리 모델도 여러 라운드 논의 끝에 확정: TagHandler 등은
quad-base가 스스로 등록하고, addTag/removeTag/setAttribute만 백엔드
팩토리가 채우는 타입 계약 — 안 채운 슬롯은 명시적으로 에러내는 스텁.

/code-review high가 추가로 3건(gcconn-trick-verification.md 배너,
README.md 인덱스 4곳, luau-test/STATUS.md의 재작성 지침) 발견해 정정.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXqrGrh83Sh61C3tUCMdmY
2026-08-14 11:03:24 +09:00
623c9316fe
docs: Debounce/Throttle 백로그 신설 + "emit은 항상 전파" base 역전 정정
워크트리(worktree-debounce-throttle-plan)에서 네 라운드로 다듬은 결과를
메인의 3단계 분할 구조에 맞춰 필요한 변경만 이식.

## 신설: research/debounce-throttle-plan.md

- Blocker가 이미 쓰는 게이티드 노드의 릴리스 트리거만 타이머로 바꾼 것.
  공개 Blocker API엔 "상류 신호 도착" 통지가 없어 그 위엔 못 얹음 →
  M3에서 게이트를 공용 Gate로 뺄 것.
- 두 도구의 차이는 "신호가 창 타이머를 리셋하는가" 한 비트뿐.
  공개 생성자 2개 + 내부 구현 1개(초안이 옮겨온 lodash식 maxWait 공식엔
  trailing 통과 직후 이중 발화 버그가 있었음).
- quad-base + 주입 op 2개: setTimeout(func, delay) -> Timeout /
  clearTimeout. Roblox는 task.delay/task.cancel로 배선(인자 순서 반대).
  os.clock()은 Luau 표준 라이브러리라 주입 대상 아님(diff 전용).
  Timeout = { __type_timeout: true, _native: any }.

## 역전: emit은 자기 invalid 상태와 무관하게 항상 전파된다

source-state-plan.md의 "이미 invalid였다면 그 아래로 더 전파하지 않는다"가
확정된 Observer 계약(fn이 :Get()을 안 불러도 됨)과 정면 충돌 — 액면대로면
:Get() 안 하는 Observer는 한 번 울고 영구 침묵. architecture.md가 같은
다이아몬드 문제를 pull-recompute로 설명하는 것과도 어긋나 있었음.

정정 모델: invalid는 캐시 낡음 표시일 뿐, 중복 재계산은 pull-recompute+
캐시가 막고 중복 통지는 안 접음(접으려면 Blocker 같은 명시적 게이트).

- source-state-plan.md: 전파 규칙 재작성, "다이아몬드 의존성은 무엇이
  푸는가" 절 신설, Observer 절 상호 참조. 플래튼 기각/:With 빌더 기각
  근거를 캐시 공유로 재작성(두 결론 유지, 근거 강도는 상승)
- architecture.md, blocker-plan.md(전파를 지연시키는 유일한 요소로 위치
  명문화), comparison-fusion-vide.md, framework-comparison-findings.md
- ROADMAP M0 체크리스트: 확인할 것이 정반대가 됨
- luau-test 05 → rewrite-required/(옛 모델을 통과 상태로 검증 중이었음),
  STATUS.md 개수 동기화(rewrite 6→7, done 14→13)
- audit: 05 행 정정 + "12개 전원 통과"를 액면대로 읽지 말라는 경고
- archive/invalidate-dedup-propagation-reversed.md 신설

doc-check: ERROR 0 / WARN 84(작업 전 85).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 05:22:06 +09:00
91fd7b88a8
docs(audit): 코퍼스 5차 감사 — 0-Y/0-Z 포인터 4곳 + 파괴 용어 잔존 5곳 전수 정리
4차 감사(반복되던 두 패턴을 grep으로 전수 스윕)에서 발견한 것 정리:

- architecture.md: 모든 세션이 "먼저 읽으라"는 진입점 파일인데 소스
  트리의 chains/retractFrom 서술에 0-Z 포인터가 전혀 없었음 — 최상단
  배너 추가(가장 중요한 gap, question.md 0-A가 경고하던 바로 그 함정)
- tween-plan.md/operator-sugar-plan.md/effect-plan.md: self-lazy-핸들
  계약(0-Y)에 의존하는 실행 예시/메커니즘 서술에 포인터가 전혀 없었음
  — 3곳 추가
- CLAUDE.md: "지금 할 일" 0번(0-Y/0-Z가 최우선 게이트)과 1번("M0 착수
  전 남은 유일한 게이트는 luau-test뿐")이 정면 모순 — 0-Y/0-Z 발견
  이전에 쓰인 문장이 안 갱신된 stale, 정정
- slot-plan.md 3곳/additional-primitives-plan.md/
  dispatch-redispatch-diff-plan.md: reconcile/Slot:List/재귀 재emit
  가드 설명이 여전히 "파괴"를 현재형으로 서술 — 2026-08-13 여섯 번째
  세션의 언마운트 전환 반영해 정정(지난 세 라운드가 놓친 인스턴스들,
  전수 grep으로 확인)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 17:20:45 +09:00
baa004ad42
decide(base): Slot CRUD(Add/Remove/Extract/Clear/Move/Swap)·요소 타입 제약 확정, Slot:List 신설
- Slot CRUD를 Add/Remove/Extract/Clear/Move/Swap 6종으로 확정, get/set 드롭
- "원시 연산 최소화" 원칙 뒤집고 Move/Swap 추가 — Extract+Add 기반 리오더가
  Parent 조작 두 번(detach+reattach)이라 무겁고, :List 없이 수동 구성한
  Slot엔 리오더 수단 자체가 없었음. Swap은 element 아닌 index 기준(element면
  위치 조회에 2n 들어 O(1) 약속이 깨짐)
- isMounted 이중 추적 분리(Slot 컨테이너 self._mounted vs 개별 element
  전역 weak-set), pre-implementation-audit.md 1-7/1-8 해소
- 요소 타입 제약 신설 — nil/None 둘 다 raw 요소로 금지, 핸들러 계층 값
  (Ref/PreRef/Observer/Effect/Modifier)은 self-ref 컨텍스트가 없어 의미
  불성립이라 즉시 error(Modifier 필드와 같은 판별 메커니즘 재사용).
  Slot<T>() 제네릭화
- Slot:List(data, updateFn, keyFn?) 신설 — 키 기반 동적 컬렉션 재조정,
  research/additional-primitives-plan.md에서 승격·통합. keyFn 생략 시
  index를 key로 사용(80% 케이스 커버, 캐스케이드 갱신 트레이드오프 명시)
- updateFn<UD>(item, index, userdata, prev)이 매 reconcile 사이클마다
  호출 — filter/toggle이 Visible 토글이 아니라 실제 파괴/재생성이 되도록
  재설계(200+ 항목에서 lazy하지 않은 문제 회피), prev 재사용이 저비용 경로
- :List가 Source를 더 이상 안 만들고 userdata로 그 권한을 updateFn에 위임 —
  result/userdata 반환값 커플링 제거, 정리 루프는 mounted가 아니라 직전
  keyIndex 전체를 순회해야 함(userdata만 살아남는 케이스 커버)
- userdata는 GC-native 값만 허용, 명시적 cleanup 필요한 값은 UB로 명문화 —
  item=nil 정리 훅 추가안은 부모 Destroy 경로에서 안 불려 절반만 동작하므로
  기각(retract가 Destroy 시 안 불리는 것과 같은 이유)
- question.md/ROADMAP.md/README.md 동기화, slot-plan.md 자체 정합성 재감사
  (stale 백로그 섹션 제거 등)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYfAz3BsaTrmMM8hnzn6mj
2026-08-09 19:21:22 +09:00
911ab559ea
fix(base): 코퍼스 전체 stale 마커/모순 감사 및 무효화된 인라인 서사 archive 이전
이미 해소된 결정이 미해결로 표시되거나 문서 간 모순되던 항목 7개 파일
수정, 뒤집힌/무효화된 설계 서술이 정정 표시만 붙은 채 본문에 남아있던
곳을 기존 archive 컨벤션대로 이전(quad2-try 리서치, Observer cleanup
계약, keyed collection state method, debug channel ReplicatedStorage).
CLAUDE.md에 세션 로그 반영.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYfAz3BsaTrmMM8hnzn6mj
2026-08-09 16:36:59 +09:00
8fc6dd3b8c
decide(base): Observer 즉시실행 확정, Effect가 Observer를 조합하도록 확정
- state:Observer(fn)는 등록 즉시 1회 실행되는 것으로 확정 — 초기화 순서
  디버깅 문제를 피하고, store-bind 프로퍼티 핸들러가 "초기값 적용"과
  "이후 변경 반영"을 같은 코드 경로로 통일할 수 있게 됨.
- Effect(fn, state?)로 확정 — state 생략 시 기존 스펙(설치 1회 + 확정
  정리) 유지, state 지정 시 내부적으로 state:Observer(...)를 조합해
  재실행 + 자동 cleanup 배선(React useEffect와 동형). 다수 의존성은
  :With(...)로 묶어서 넘김. 여전히 자유 함수(메소드 아님) — leaf 생명주기
  바인딩을 state가 소유하지 않아서.
- fn 커링 스타일을 Effect/Observer 공통 모듈화 관용구로 권장, state:Apply
  커링 조합기 아이디어는 백로그로만 기록.
- question.md 0번의 Effect/Observer 열린 질문 해소.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 16:20:54 +09:00
226490153e
docs: Blocker/Effect를 base/additional-primitives.md에서 별개 파일로 재분리
State 작업 시 Effect까지 같이 볼 필요는 없다는 지적(둘은 무관한 프리미티브)과
기존 프리미티브당 1파일 컨벤션(modifier-plan.md, slot-plan.md류)에 맞춰
base/blocker-plan.md, base/effect-plan.md로 재분리. Blocker는 store-semantics.md
교차 참조를 유지, Effect는 독립 파일로 완전히 분리. 전체 상호참조 경로 갱신.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 14:45:57 +09:00
5c9d10df66
docs: .claude/ 코퍼스 정리 — reference/ 신설, 승격/기각 분리, 역전 이력 트리밍
base 밖으로 늘 읽을 필요 없는 참고자료(quad-v1-architecture, comparison-fusion-vide)를
새 reference/ 폴더로 분리하고, ui-shorthand-plan을 base로 승격(RoundSize 드롭+
UICorner/UIPadding/UIScale 리네임), additional-primitives-plan을 Blocker/Effect(base
승격)·Batch/Context(archive 기각)·키 기반 컬렉션 재조정(research 잔류)으로 4분할했다.
component-composition-plan의 중복 역전 서사는 기존 archive 포인터로 압축하고, archive
제목 컨벤션을 [역전됨]/[기각됨]로 분화했다. tween-plan에는 retract/canExecute 구분
메모와 트윈 옵션 값 모양 논의를 추가했다. Effect가 Observer 변형인지는 임의로
결론내지 않고 question.md에 열린 질문으로 남겼다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 14:39:20 +09:00
ccde1cb31c
research: Blocker 프리미티브 채택 확정 — Batch(lexical) 대안, 문서 마무리
세션 마무리 라운드. Batch를 부활시킨 게 아니라 완전히 별개인 새 primitive
Blocker를 채택한 것으로 명확히 분리:
- Batch(함수/코루틴 스코프 lexical block)는 그대로 기각 유지, 반면교사 기록.
- Blocker: 콜스택/코루틴이 아니라 값(On/Off)으로 지연 구간을 표현해 코루틴
  yield 위험을 구조적으로 우회. state:Block(blocker)->state가 호출 즉시
  onunblock 핸들을 등록(지연 등록 아님, 사용자 정정 반영). 이름 확정
  (Blocker/On/Off/IsBlocked/HasBlockedEmit). 재진입(네스팅)은 의도적으로
  미지원 — Rust poisoned-mutex류 위험 회피, 문서화 강조 필수로 기록. 사용
  가이드: 파이프라인 최종 연산 지점에 배치.

documentation-content-map.md에 새 심화/quadnomicon 콘텐츠 후보 반영:
State 파생 체인 동작 원리, :Compute의 조건부 의존값 사용 팁, Blocker 사용
가이드(네스팅 금지 최우선 강조), "왜 Batch 대신 Blocker인가" 비교 에세이,
push-invalidate/pull-recompute의 laziness 설계 철학 심층 에세이.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 00:05:18 +09:00
4358fa71d7
research: 키 재조정 자유함수+Extract로 정정, Effect 단순화, Batch/Context 최종 기각
사용자 라이브 피드백 반영:
- 키 기반 컬렉션 재조정: State 메소드 프레이밍 철회(Source 안 쓰는 컴포넌트가
  못 씀), 자유 함수 + plain-or-State 폴리모픽 시그니처로 정정. Slot에 파괴
  없이 빼내는 Extract 연산 필요(리오더용, 기존 "portal 없음" 결정과는 다른
  층위라 안 부딪힘). 이름 후보(Render/Draw/List) 추가, Keyed는 탈락.
- Effect: Observer에 cleanup 반환 계약 추가하는 안 기각(클로저 업밸류로 이미
  충분 — pre-implementation-audit.md 3-1과 같은 논리). 대신 leaf 죽음에
  확정 정리하는 별도 단순 primitive로 수렴, 시그니처만 남음.
- Batch: 코루틴 yield 시나리오 분석 결과 lexical transaction 모델 자체가
  구조적으로 위험 — 프리미티브로 안 만들기로 결정, 심화 최적화 팁 +
  quadnomicon 에세이로 대체.
- Context: 기각 확정. 대안이던 레이어드 Store도 사용자 반박으로 철회(이미
  있는 타입 강제 명시적 Store 전달 + 오버라이드 지점 명시적 병합으로 충분).

documentation-content-map.md에 quadnomicon 에세이 후보 2개(왜 Batch가/
Context가 없는가) + 심화 최적화 팁 1개 추가.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 23:36:36 +09:00
67438a172e
research: Context 난이도 판정 완료 — 기각 권고, 레이어드 Store 대안 확정
서브에이전트 조사: 동기 콜스택 한정 버전은 구현 난이도 낮지만(Fusion
Contextual 이식 가능), quad가 정상 패턴으로 확정한 Slot 비동기 추가에서
조용히 defaultValue로 폴백하는 함정 있음 + quad-debug의 "모든 연결은
선언된 그래프" 철학과 충돌. Roblox Luau는 thread-local이 없어 완전 자동
버전은 플랫폼 한계로 사실상 불가(Node AsyncLocalStorage/Python contextvars와
동일 문제). 대안 비교 결과 레이어드 Store(__index 델리게이션, Modifier/
Source가 이미 쓰는 패턴과 동일 계열)가 서브트리 오버라이드 가치를 명시적
전달 철학·비동기 안전성 유지하며 대부분 재현 — 최종 권고안으로 채택.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 22:04:54 +09:00
ec5fb8184b
research: 키 기반 컬렉션 재조정 설계 스케치, Context 난이도 판정 진행중 기록
사용자와 라이브 논의 반영 — state:Keyed(keyFn, renderFn) -> Slot 스케치(독립
프리미티브 vs 파생 데이터 원칙 적용해 메소드 프레이밍 채택), Context는
서브에이전트에게 구현 난이도 평가 위임 중.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 21:59:23 +09:00
3af792e33a
research: 추가 프리미티브 필요성 조사 (키 기반 컬렉션 재조정 등)
웹 프레임워크(React/Vue/Solid/Svelte/MobX) + Fusion/Vide/quad v1 소스 근거로
현재 확정된 프리미티브(Source/State/Store/Ref/Observer/Modifier/Slot/DI)만으로
충분한지 조사. 가장 명확한 빈 자리는 키 기반 동적 컬렉션 재조정(Fusion
ForPairs/Vide indexes()류) — Slot은 CRUD 껍데기일 뿐 diff 엔진이 아님.
Effect/cleanup 공개 API, Batch, Context는 부차적 후보로 확인.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 21:26:58 +09:00