From f1c8be83901f34ea9fbafef51ff5f91250b80c91 Mon Sep 17 00:00:00 2001 From: qwreey-agent-selene Date: Sat, 29 Aug 2026 03:10:00 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=A0=84=20=EC=BD=94=ED=8D=BC=EC=8A=A4?= =?UTF-8?q?=20=EC=8A=A4=EC=9C=95=20=EB=B0=98=EC=98=81=20=E2=80=94=20deboun?= =?UTF-8?q?ce-throttle=EC=9D=98=20HasBlockedEmit=20=EA=B0=9C=EB=85=90=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=ED=91=9C=EA=B8=B0=20=EB=91=98(H-86),=20ef?= =?UTF-8?q?fect-plan=EC=9D=98=20'LifetimeHandle=20=ED=83=91=EB=A0=88?= =?UTF-8?q?=EB=B2=A8=20=ED=95=A8=EC=88=98'=20=E2=86=92=20=EC=9D=B8?= =?UTF-8?q?=EC=8A=A4=ED=84=B4=EC=8A=A4=20=ED=95=84=EB=93=9C(H-174)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: qwreey --- .claude/base/debounce-throttle-plan.md | 12 ++++++++---- .claude/base/effect-plan.md | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.claude/base/debounce-throttle-plan.md b/.claude/base/debounce-throttle-plan.md index e364df2..31d042c 100644 --- a/.claude/base/debounce-throttle-plan.md +++ b/.claude/base/debounce-throttle-plan.md @@ -100,11 +100,14 @@ ## 1. 왜 `Blocker`로는 안 되는가 (그리고 왜 그 옆자리인가) `base/blocker-plan.md`의 "메커니즘 (확정)"이 정의하는 게이티드 State는 -정확히 이렇게 동작함: +정확히 이렇게 동작함(**[2026-08-29 표기 정정]** 아래 `HasBlockedEmit`은 개념 +이름이다 — 실제 구현은 게이트 노드의 흡수 집합 `_withheld`이고 "쌓인 게 있나"는 +`next(_withheld) ~= nil` = 정책이 쥔 `emit(commit)`의 반환값, `H-86`·`blocker-plan.md` +"이름 확정" 절의 각주; 이 절의 나머지 서술은 그 이름을 개념으로 읽으면 그대로 맞다): - 상류가 emit(무효화)하면 게이티드 노드로 전파를 시도 -- 블록 중이면 전파 안 하고 `HasBlockedEmit = true`만 세팅 -- 열릴 때 `HasBlockedEmit`이 true면 **정확히 1회** 전파하고 플래그 리셋 +- 블록 중이면 전파 안 하고 출처를 흡수 집합에 쌓아둔다(개념상 `HasBlockedEmit = true`) +- 열릴 때 쌓인 게 있으면 **정확히 1회** 전파하고 집합을 스왑(개념상 플래그 리셋) 이건 debounce/throttle이 필요로 하는 것과 **글자 그대로 같음**. 차이는 딱 하나 — 여는 주체: @@ -287,7 +290,8 @@ quad의 전파 모델은 `base/source-state-plan.md`의 "전파 모델 확정" 문서가 정당한 사용법으로 허용한 것이 문서의 다른 문장 때문에 조용히 깨지는 것이므로, 취향 문제가 아니라 **base 내부의 실제 모순**임. -사용자의 "저건 `Blocker`가 하는 것" 지적도 정확함 — `HasBlockedEmit`이 +사용자의 "저건 `Blocker`가 하는 것" 지적도 정확함 — `HasBlockedEmit`(개념 +이름 — 실체는 게이트의 `_withheld`, 위 1절 정정)이 바로 "블록 중엔 여러 emit을 하나로 접어뒀다가 열릴 때 1회"이고, `Blocker`는 그걸 **명시적으로 켜고 끄는 opt-in 게이트**로 제공함. 같은 동작을 모든 State 노드에 암묵적으로 심어두면 `Blocker`의 존재 의의가 diff --git a/.claude/base/effect-plan.md b/.claude/base/effect-plan.md index 5ff8192..bd814d9 100644 --- a/.claude/base/effect-plan.md +++ b/.claude/base/effect-plan.md @@ -614,8 +614,9 @@ Observer 쪽 의사코드는 가드가 첫 줄이라 이 문제가 없었다. -- ⭐⭐ [2026-08-27 확정 (b), 9라운드 `H-144` 후속 — 감사 4라운드] **`EffectHandle`은 -- 네 진입점을 자기 것으로 가진다 — Observer의 함수 본문을 배정하지 않는다.** -- 공유하는 건 **레지스트리 두 개**(`Subscribed`/`WeakSubscribed`, 소유 모듈은 --- `Observer.luau` — `H-99`)와 **`canBound` 게이트**(`LifetimeHandle.luau`의 --- 탑레벨 함수)뿐이고, `.Subscribed` 플래그의 뜻도 같다. 여기 한때(Q4/`H-127`) +-- `Observer.luau` — `H-99`)와 **`canBound` 게이트**(quad 인스턴스의 필드 — +-- `module.canBound`, `H-174`; 한때 "`LifetimeHandle.luau`의 탑레벨 함수"라 적었다)뿐이고, +-- `.Subscribed` 플래그의 뜻도 같다. 여기 한때(Q4/`H-127`) -- `EffectHandle.Subscribe = Observer.Subscribe`처럼 **함수 객체를 그대로 배정**해 -- 뒀는데, `Observer:Subscribe`의 본문이 `self:WeakSubscribe()`로 **콜론 위임**하는 -- 탓에 `self`가 `EffectHandle`이면 그 조회가 `EffectHandle`의 오버라이드로 가서