decide(tween): finalize Animate combinator, fix and/or falsy-value bug
Animate(info) resolves T|State<T> option fields into a plain Tween{...},
matching :Compute's self-as-lazy-handle contract directly. Also audited
.claude/base for and/or ternary idioms per Luau if-then-else guidance;
fixed a real falsy-value leak in Dispatch.retractUnder.
This commit is contained in:
parent
eac66d0173
commit
8fdb9f1bb2
6 changed files with 186 additions and 55 deletions
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
| 문서 | 내용 | 우선순위 |
|
||||
|---|---|---|
|
||||
| `tween-plan.md` | **[2026-08-12 세션에서 구조+옵션 값 모양+override 정책까지 전부 확정]** 값-레벨 `Tween<T>` 래퍼(PropertyHandler가 소비), 구 특수 bind key 모델은 `archive/tween-special-bind-key-reversed.md`로 이전. 3-상태 릴레이션 슬롯(`{Tween,Value}\|true\|nil`), `T'=T\|Tween<T>` 타입 치환, `useTween`은 `:Apply`/`:Compute`로 해소. 옵션 값 모양은 `Info: TweenInfo?` 우선+편의 필드(`Time`/`Style`/...) 폴백, override는 `Tween.Cancel`(기본)/`Tween.Finish` 2값으로 확정. `initValue`는 사용자가 직접 처리(에이전트 범위 제외), 남은 건 `Animate` 시그니처+자연완료 북키핑뿐 | 하 — 거의 다 닫힘, 두 세부 항목만 남음 |
|
||||
| `tween-plan.md` | **[2026-08-12 세션에서 구조+옵션 값 모양+override 정책+`Animate` 콤비네이터까지 전부 확정]** 값-레벨 `Tween<T>` 래퍼(PropertyHandler가 소비), 구 특수 bind key 모델은 `archive/tween-special-bind-key-reversed.md`로 이전. 3-상태 릴레이션 슬롯(`{Tween,Value}\|true\|nil`), `T'=T\|Tween<T>` 타입 치환. 옵션 값 모양은 `Info: TweenInfo?` 우선+편의 필드(`Time`/`Style`/...) 폴백, override는 `Tween.Cancel`(기본)/`Tween.Finish` 2값. `Animate(info)`는 `Tween` opts(`Value` 제외)를 `T\|State<T>`로 받아 `:Compute`에 바로 넘기는 sugar로 확정(구 `useTween` 스케치 대체). `initValue`는 사용자가 직접 처리(에이전트 범위 제외), 남은 건 자연완료 북키핑 하나뿐 | 하 — 사실상 다 닫힘 |
|
||||
| `existing-instance-bind-plan.md` | 이미 생성된 인스턴스 재바인드 — 착수 안 하되 "미지원" 확정도 안 함, 열린 가능성 유지 | 하 — v2 초기 스코프 제외 |
|
||||
| `debug-tooling-plan.md` | 실물 Instance→코드 위치 역추적 Studio 플러그인(`quad-debug`) — 채널 실현 가능성(BindableEvent/Function 크로스 컨텍스트)까지 실측 검증 완료, 세부 API 이름·구현만 남음 | 하 — 사용자가 "quad 개발 완료 전엔 착수 못 함"으로 직접 후순위 지정, base 설계 시 훅 확장 지점만 고려 |
|
||||
| `documentation-plan.md` | 문서 사이트 구조(초심자/api/심화/`quadnomicon` 4축, 백엔드별 트랙 분리) + UI 네이밍 컨벤션·Store 부작용 패턴·권장 이벤트 핸들링 3개 세부 문서 뼈대 | 하 — 착수 시점 미정, 구조/스코프만 합의된 상태 |
|
||||
|
|
|
|||
|
|
@ -377,12 +377,22 @@ function Dispatch.retractUnder(inst, k, keep, v)
|
|||
for i, h in list do if h == keep then cutoff = i break end end
|
||||
end
|
||||
for i = #list, cutoff + 1, -1 do
|
||||
list[i].retract(inst, k, i == cutoff + 1 and v or nil)
|
||||
list[i].retract(inst, k, if i == cutoff + 1 then v else nil)
|
||||
list[i] = nil
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**[2026-08-12 세션에서 정정]** `list[i].retract(...)`의 세 번째 인자가
|
||||
원래 `i == cutoff + 1 and v or nil`(and/or 삼항 관용구)이었으나, `v`가
|
||||
`false`일 때(정당한 boolean 프로퍼티 값) `and`의 결과가 falsy가 되어
|
||||
`i == cutoff + 1`이 참이어도 `or nil`로 새는 조용한 버그였음 — Luau의
|
||||
`if-then-else` 표현식(2021년 도입)으로 교체. **일반 규칙**: `cond and
|
||||
truthyOnly or fallback` 관용구는 가운데 값이 테이블/항상-truthy 값일
|
||||
때만 안전(예: `Tag(...)`/`Length:Get()`처럼 절대 `nil`/`false`가 될 수
|
||||
없는 값) — 임의 `T`(boolean 포함) 값이 가운데 올 수 있으면 반드시
|
||||
`if cond then a else b`를 쓸 것.
|
||||
|
||||
- **`handler.process(inst,k,v)`를 `Dispatch.process`를 거치지 않고 직접
|
||||
호출하는 것은 UB — 반드시 `Dispatch.process`를 통해서만 진입할 것.**
|
||||
이유: `chains` 배열에 push하는 bookkeeping이 `Dispatch.process` 내부에만
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ context-rejected.md`. 아래는 그중 **아직 실제로 열려있는 것만**
|
|||
| Batch(lexical) 기각, Context(+레이어드 Store) 기각 | `archive/batch-rejected.md`, `archive/context-rejected.md` |
|
||||
| Fusion/Vide 비교 리서치(주의: 일부 서술은 이후 라운드에서 뒤집힘, 문서 내 정정 표시 참고) | `reference/comparison-fusion-vide.md` |
|
||||
| v1 내부 동작 스냅샷 | `reference/quad-v1-architecture.md` |
|
||||
| 트윈 — 값-레벨 `Tween<T>` 래퍼(2026-08-10)+옵션 값 모양·override 정책(2026-08-12) 전부 확정, `Animate` 시그니처·자연완료 북키핑만 남음 | `research/tween-plan.md` |
|
||||
| 트윈 — 값-레벨 `Tween<T>` 래퍼(2026-08-10)+옵션 값 모양·override 정책·`Animate` 콤비네이터(2026-08-12) 전부 확정, 자연완료 북키핑 하나만 남음 | `research/tween-plan.md` |
|
||||
| quad2-try(폐기된 이전 시도) 리서치 — OOP 상속/커스텀 파서/Slot 스텁/`Pipe` COW 전부 죽은 접근으로 확인, 반복 조사 금지 | `base/bind-system-plan.md` |
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Tween / 애니메이션 플러깅 (구조+옵션 값 모양 확정 — `Animate` 시그니처/자연완료 북키핑만 남음)
|
||||
# Tween / 애니메이션 플러깅 (구조+옵션 값 모양+`Animate` 확정 — 자연완료 북키핑만 남음)
|
||||
|
||||
**상태**: research — **2026-08-10 세션에서 구조 전체가 재설계됨.** 기존
|
||||
"`v`가 Store인 아무 `k`나 잡는 우선순위 최상위 Dispatch 핸들러" 모델은
|
||||
|
|
@ -10,11 +10,11 @@
|
|||
tweenData...)] = storeValue`)은 `archive/tween-special-bind-key-reversed.md`로
|
||||
이전됨** — 원문/역전 사유는 거기 보존, 이 문서는 새 모델만 서술.
|
||||
|
||||
**2026-08-12 세션에서 옵션 값 모양+override 정책 이름까지 전부 확정됨**
|
||||
(아래 "확정: `Tween{...}` 최종 모양" 절) — 남은 건 `Animate` 콤비네이터의
|
||||
정확한 시그니처와 자연 완료(Completed) 시 북키핑 정리 여부뿐, 둘 다 다음
|
||||
세션으로 미룸. `initValue`는 사용자가 필요해지면 직접 처리하기로 확정
|
||||
(에이전트 작업 범위에서 제외, 아래 해당 절 참고). 원본:
|
||||
**2026-08-12 세션에서 옵션 값 모양+override 정책 이름+`Animate` 콤비네이터
|
||||
시그니처까지 전부 확정됨**(아래 "확정: `Tween{...}` 최종 모양"/"`Animate`
|
||||
콤비네이터" 절) — 남은 건 자연 완료(Completed) 시 북키핑 정리 여부뿐.
|
||||
`initValue`는 사용자가 필요해지면 직접 처리하기로 확정(에이전트 작업
|
||||
범위에서 제외, 아래 해당 절 참고). 원본:
|
||||
`.claude/initreq/raw-userinput.md` "트윈은 어떻게 할 것이냐" / "스토어 값은
|
||||
항상 먼저 캐치한다" / "네임스페이스드 객체" 절. Fusion의 Tween/Spring이
|
||||
반응 그래프 안에 있는 설계는 명시적 반면교사 — `reference/
|
||||
|
|
@ -179,38 +179,96 @@ State<T | Tween<T>>`가 나옴 — Modifier/State/Source/StoreBind 코드엔
|
|||
참가자" 그룹으로 분류해뒀던 건 부정확했던 것으로 이번에 정정(아래
|
||||
"패키지 경계" 절 참고).
|
||||
|
||||
## `useTween`(트윈 우회) — 해소됨, 새 옵션 필드 불필요
|
||||
## `Animate` 콤비네이터 — 확정 (2026-08-12 세션)
|
||||
|
||||
이전엔 `Tween{useTween=state<boolean>}`처럼 `Tween` 생성자 안에 별도
|
||||
옵션 필드를 두는 방향으로 열려 있었으나, 값-레벨 래퍼 모델에선 **이미
|
||||
있는 `state:Apply(factory)`/`:Compute`만으로 공짜로 풀림** — 새 필드
|
||||
불필요:
|
||||
**동기**: `Tween{Value=..., Style=..., ...}`을 매번 손으로 `:Compute` 안에서
|
||||
조립하는 건, 값(`Value`)만 바뀔 뿐 옵션(`Style`/`Time`/`Override`...)은
|
||||
거의 고정인 흔한 케이스에서 번거로움. `Animate`는 이 흔한 케이스만 감싸는
|
||||
얇은 sugar — 다시 보니 매우 단순해서(사용자 표현: "생각해보니 엄청
|
||||
간단하다") 다음 세션으로 미룰 이유가 없어 이번 세션에 바로 확정.
|
||||
|
||||
**모양**: `Tween`의 옵션(`Value` 제외 전부)을 그대로 받되, **각 필드가
|
||||
`T | State<T>`를 받을 수 있음** — `Tween{...}` 자신의 필드는 plain만
|
||||
받는 것과 대조적(위 "`Tween{...}`의 모든 필드는 plain 값만 받음" 절).
|
||||
모순이 아님: `Animate`가 반환하는 함수 안에서 각 필드를 **`:Get()`으로
|
||||
한 번 풀어 plain 값으로 만든 뒤에만** `Tween{...}`에 넘기므로, `Tween`
|
||||
쪽 불변식(plain-only)은 그대로 유지됨.
|
||||
|
||||
```lua
|
||||
-- reduceMotion: State<boolean>
|
||||
Position = mySource:Apply(Animate(reduceMotion, {Time = 0.3}))
|
||||
```
|
||||
local function resolve(v)
|
||||
if isState(v) then
|
||||
return v:Get()
|
||||
else
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
`Animate(reduceMotion, opts)`는 커링 팩토리로, 개념상 다음과 같은 모양:
|
||||
|
||||
```lua
|
||||
return function(state)
|
||||
return state:Compute(function(v)
|
||||
if reduceMotion:Get() then
|
||||
return v
|
||||
else
|
||||
return Tween{Value = v, Time = opts.Time}
|
||||
end
|
||||
end)
|
||||
local function Animate(info)
|
||||
return function(self)
|
||||
return Tween{
|
||||
Value = self:Get(),
|
||||
Info = resolve(info.Info),
|
||||
Time = resolve(info.Time),
|
||||
Style = resolve(info.Style),
|
||||
Direction = resolve(info.Direction),
|
||||
RepeatCount = resolve(info.RepeatCount),
|
||||
Reverses = resolve(info.Reverses),
|
||||
DelayTime = resolve(info.DelayTime),
|
||||
Override = resolve(info.Override),
|
||||
}
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
`reduceMotion`이 바뀌면 `:Compute`가 재계산되어 StoreBind가 자연히 새
|
||||
`realv`(plain 또는 Tween-wrapped)로 재-dispatch — PropertyHandler는 평소처럼
|
||||
그 값만 보고 처리하면 됨, 우회 로직을 따로 알 필요 없음. **`Animate`는
|
||||
base 프리미티브가 아니라 quad-roblox가 제공하는 자유 함수 조합기**(아래
|
||||
"패키지 경계" 절) — `Modifier:Apply(Boldify(10))` 커링 패턴과 완전히
|
||||
같은 모양이라 base에 새로 추가할 게 없음.
|
||||
`resolve`가 `and`/`or` 삼항 관용구가 아니라 `if-then-else`인 이유는
|
||||
`base/bind-system-plan.md`의 2026-08-12 정정 노트와 같음 — `Override`
|
||||
등 필드가 `false`일 수 있는 값이면 `isState(v) and v:Get() or v` 식은
|
||||
`v:Get()`이 falsy일 때 조용히 `v`(State 객체 자신)로 새는 버그가 됨.
|
||||
|
||||
**왜 `:Compute`에 직접 넘길 수 있는가**: `Animate(info)`가 반환하는
|
||||
`function(self) ... end`는 `:Compute(fn)`의 콜백 시그니처(`fn(self,
|
||||
previous?, ...deps)`, `self`는 raw 값이 아니라 lazy State 핸들 —
|
||||
`bind-system-plan.md` "self/with 값 둘 다 lazy State 핸들로 통일" 절)와
|
||||
정확히 일치 — 그래서 `state:Compute(Animate{Style=...})`처럼 **바로**
|
||||
넘기면 됨, 예전 `useTween` 스케치가 필요로 했던 `:Apply` 경유가 불필요:
|
||||
|
||||
```lua
|
||||
-- 슈거로 충분한 흔한 케이스
|
||||
Position = mySource:Compute(Animate{Style = Enum.EasingStyle.Bounce, Time = 0.3})
|
||||
```
|
||||
|
||||
**`Style`/`Override` 등이 State여도 값 변경 자체가 재애니메이션을
|
||||
트리거하지 않음 — 의도된 동작.** `Animate{...}`가 반환한 `fn`은
|
||||
`self`(= `mySource`, `Value`가 될 State)가 바뀔 때만 `:Compute`에
|
||||
의해 다시 불림 — `info.Style`이 State여도 `:Compute`의 구독 목록에
|
||||
안 걸림(`resolve`가 그냥 `fn` 본문 안에서 클로저로 읽을 뿐, `:With`/
|
||||
trailing-deps로 선언 안 됨). 그래서 `Style`이 바뀌어도 그 자체로는
|
||||
아무 일도 안 일어나고, 다음에 `Value`가 실제로 바뀔 때 그 시점의
|
||||
최신 `Style`이 자연히 반영됨. 사용자가 직접 짚은 근거: "style 같은
|
||||
게 바뀐다고 다시 애니메이션을 수행하는 경우는 없다" — 실사용 요구와
|
||||
정확히 일치하는 동작이라 별도 트리거 배선이 오히려 불필요한
|
||||
복잡도였을 것.
|
||||
|
||||
**구 `useTween`(reduceMotion 우회) 스케치는 이 설계로 대체됨** — 이전엔
|
||||
`Animate(cond, opts)`처럼 조건 인자를 받아 내부에서 plain/Tween 분기하는
|
||||
전용 2-인자 시그니처를 검토했으나, 새 `Animate(info)`는 그 조건 분기를
|
||||
아예 안 가짐(단일 책임 유지). 우회가 필요하면 `Animate`를 감싸는 평범한
|
||||
`:Compute` 클로저로 여전히 표현 가능 — 새 프리미티브 불필요:
|
||||
|
||||
```lua
|
||||
-- reduceMotion: State<boolean>
|
||||
Position = mySource:Compute(function(self)
|
||||
if reduceMotion:Get() then
|
||||
return self:Get()
|
||||
end
|
||||
return Animate{Style = Enum.EasingStyle.Bounce}(self)
|
||||
end)
|
||||
```
|
||||
|
||||
**base 프리미티브 아님 — 여전히 quad-roblox 유틸**(아래 "패키지 경계"
|
||||
절) — `Tween<T>` 값 타입/`isTween`만 base(`quad-base/Tween.luau`)에
|
||||
있고, `Animate`는 이미 있는 `:Compute`/`Tween{...}`/`isState`를 조합한
|
||||
quad-roblox 레벨 편의 함수라 base 계약에 영향 없음.
|
||||
|
||||
## 초기 진입 애니메이션(`initValue`) — **에이전트 작업 범위 제외로 확정, 사용자가 직접 처리**
|
||||
|
||||
|
|
@ -229,20 +287,6 @@ base 프리미티브가 아니라 quad-roblox가 제공하는 자유 함수 조
|
|||
한 파일 + 릴레이션 슬롯) 사용자가 직접 처리하는 데 범위상 문제가 없음.
|
||||
에이전트는 이 항목을 임의로 착수하지 말 것.
|
||||
|
||||
## `Animate` 콤비네이터 — quad-roblox 유틸(base 아님), 다음 세션으로 미룸
|
||||
|
||||
`Animate(condOrOpts, opts?)`류 팩토리를 quad-roblox가 제공, `:Apply`로
|
||||
체이닝해서 쓰는 용도. 상세 시그니처는 미확정(예: `Animate({ease=...,
|
||||
useAnimate=state<boolean>})`처럼 조건과 옵션을 하나의 테이블로 합치는
|
||||
안도 검토 가치 있음 — **2026-08-12 세션에서 다음 세션으로 명시적으로
|
||||
미룸**(단순히 `Tween{...}`/`:Apply`/`:Compute`를 감싸는 슈거라
|
||||
`Slot:List`류와 성격이 비슷함, 별도 세션에서 다루기로 함). 핵심은 **base
|
||||
프리미티브가 아니라는 것** — `Tween<T>` 값 타입/`isTween`만
|
||||
base(`quad-base/Tween.luau`)에 있고, `Animate`는 이미 있는 `:Apply`/
|
||||
`:Compute`/`Tween{...}`를 조합한 quad-roblox 레벨 편의 함수라 나중에
|
||||
이름/모양을 자유롭게 바꿔도 base 계약에 영향이 없음 — 저비용
|
||||
고효율(사용자 표현) 엔지니어링으로 판단.
|
||||
|
||||
## 패키지 경계 — `Tag`가 이미 밟은 것과 같은 분리 (2026-08-10 세션 확정)
|
||||
|
||||
- **quad-base**: `Tween.luau` — 값 타입(`Tween(opts)` 팩토리, `isTween`
|
||||
|
|
@ -332,12 +376,8 @@ Tween(opts: {
|
|||
## 열린 질문 (`.claude/question.md`에도 취합)
|
||||
|
||||
**2026-08-12 세션에서 옵션 값 모양/override 정책 이름/릴레이션 슬롯 저장
|
||||
모양까지 전부 확정됨** — 아래 두 개만 남음, 둘 다 다음 세션 이후로 명시적
|
||||
연기(급하지 않음):
|
||||
모양/`Animate` 콤비네이터 시그니처까지 전부 확정됨** — 아래 하나만 남음:
|
||||
|
||||
- `Animate` 콤비네이터의 정확한 시그니처(조건/옵션 분리 vs 통합) — 단순
|
||||
`Tween{...}`/`:Apply`/`:Compute` 슈거라 `Slot:List`류와 성격이 비슷함,
|
||||
다음 세션에서 다룸.
|
||||
- 자연 완료(Completed) 시 per-instance 북키핑 정리 여부(3-상태 슬롯을
|
||||
`true`로 되돌리는 시점) — `research/pre-implementation-audit.md` 2-10번
|
||||
참고, M11 착수 시 확정.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
<!-- quad-v2 세션 로그 원문 — CLAUDE.md에서 이전됨(2026-08-11 정리 세션에서 확립된 관례를 따름). -->
|
||||
<!-- 이 파일은 quadnomicon 개발로그 소재용 원자료로, 당시 시행착오(정정 전 서술 포함)를 그대로 보존함. -->
|
||||
<!-- 현재 유효한 설계는 이 파일이 아니라 base//research//archive/가 최종 소스 — 이 파일 안의 판단이 이후 세션에서 뒤집혔을 수 있음. -->
|
||||
|
||||
## 2026-08-12 두 번째 세션 — `Animate` 콤비네이터 확정(다음 세션 연기 철회), `.claude/` 전체 and/or 삼항 관용구 감사
|
||||
|
||||
앞선 세션(`session/2026-08-12-01-tween-shape-finalized.md`)에서 `Animate`
|
||||
시그니처를 "단순 슈거라 다음 세션에서" 미뤘으나, 사용자가 곧바로 "생각해보니
|
||||
엄청 간단하다"며 구체안을 들고 와서 같은 세션 안에 바로 확정.
|
||||
|
||||
**`Animate` 최종 확정**: `Tween`의 옵션(`Value` 제외 전부)을 그대로 받되
|
||||
각 필드가 `T | State<T>`를 받을 수 있는 `Animate(info)`. 반환하는
|
||||
`function(self) return Tween{Value = self:Get(), ...(각 필드 resolve)} end`가
|
||||
`:Compute(fn)`의 콜백 시그니처(`fn(self, ...)`, `self`는 lazy State 핸들 —
|
||||
`bind-system-plan.md`가 이미 확정해둔 계약)와 정확히 일치한다는 걸 사용자가
|
||||
직접 확인해서, `state:Compute(Animate{Style=...})`처럼 **바로** 넘길 수
|
||||
있음(예전 `useTween` 스케치가 필요로 했던 `:Apply` 경유 불필요 —
|
||||
`Animate`가 스스로 `state:Compute(...)`를 감싸던 이전 모양에서, `:Compute`가
|
||||
직접 받는 `fn` 그 자체가 되는 모양으로 바뀜). `Style`/`Override` 등이
|
||||
State여도 값 변경 자체가 재애니메이션을 트리거하지 않는다는 것도 사용자가
|
||||
의도적으로 확정 — `resolve`가 `fn` 본문 안에서 클로저로만 읽고 `:With`/
|
||||
trailing-deps로 구독 등록을 안 하므로, `Value`가 실제로 바뀌는 다음
|
||||
재계산 때만 그 시점의 최신 옵션이 자연히 반영됨. 근거(사용자 표현):
|
||||
"style 같은 게 바뀐다고 다시 애니메이션을 수행하는 경우는 없다."
|
||||
|
||||
구 `useTween`(reduceMotion 조건부 우회) 2-인자 스케치(`Animate(cond,
|
||||
opts)`)는 폐기 — 새 `Animate(info)`는 조건 분기를 안 가지므로, 우회가
|
||||
필요하면 `Animate{...}(self)`를 감싸는 평범한 `:Compute` 클로저로 여전히
|
||||
표현 가능(새 프리미티브 불필요, 코드 예시로 문서화).
|
||||
|
||||
**and/or 삼항 관용구 감사(사용자 요청)** — 사용자가 Luau의 `if-then-else`
|
||||
표현식(2021년 정식 도입, 링크 제공)을 언급하며 `.claude/` 전체에서
|
||||
`cond and truthyOnly or fallback` 패턴이 falsy-값 함정(가운데 값이
|
||||
`nil`/`false`일 수 있으면 `cond`가 참이어도 `fallback`으로 새는 버그)에
|
||||
해당하는 곳이 있는지 확인 요청. `grep -rn " and .* or "`로 `.claude/base`
|
||||
전역 스캔, 히트 8곳 검토:
|
||||
|
||||
- `tag-plan.md`(`cond and Tag("a") or nil/None`), `slot-plan.md`
|
||||
(`isSlot(result) and result.Length:Get() or 1`, `v == nil and {} or
|
||||
{v}`) — 전부 가운데 값이 테이블이거나 숫자(Lua에서 0도 truthy)라 안전,
|
||||
수정 불필요.
|
||||
- **`bind-system-plan.md:380`(`Dispatch.retractUnder`) — 실제 버그로
|
||||
확인.** `list[i].retract(inst, k, i == cutoff + 1 and v or nil)`에서
|
||||
`v`가 `false`(정당한 boolean 프로퍼티 값)일 때 `i == cutoff+1`이 참이어도
|
||||
`and`가 falsy가 되어 `or nil`로 새서 `v` 대신 `nil`이 전달되는 조용한
|
||||
버그. `if i == cutoff + 1 then v else nil`로 교체, 문서에 일반 규칙("가운데
|
||||
값이 임의 `T`(boolean 포함)일 수 있으면 반드시 if-then-else, 테이블/숫자처럼
|
||||
항상-truthy로 보장되는 값일 때만 and/or 안전")까지 정정 노트로 남김.
|
||||
- `.claude/research`/`.claude/archive`/`.claude/reference`/`ROADMAP.md`/
|
||||
`CLAUDE.md`/`HUMAN_TODO.md`에는 해당 패턴 자체가 없음(전부 `.claude/base`에만
|
||||
존재).
|
||||
|
||||
새 `Animate` 예시 코드(`resolve` 헬퍼)도 이 원칙을 바로 실천 — `and`/`or`
|
||||
대신 `if isState(v) then v:Get() else v`로 작성, 같은 세션의 정정 노트를
|
||||
직접 참조.
|
||||
|
||||
**반영된 파일**: `research/tween-plan.md`(`Animate` 콤비네이터 절 전면
|
||||
확정, `useTween` 절 삭제·흡수, 헤더/열린질문 갱신), `base/bind-system-plan.md`
|
||||
(`Dispatch.retractUnder` 버그 수정+일반 규칙 정정 노트), `.claude/README.md`/
|
||||
`.claude/question.md`(트윈 요약 행 갱신).
|
||||
|
||||
**여전히 열려있는 것**: 자연 완료(Completed) 시 per-instance 북키핑 정리
|
||||
여부 하나뿐(`research/pre-implementation-audit.md` 2-10번, M11 착수 시).
|
||||
`research/tween-plan.md`는 이걸로 사실상 마감 상태.
|
||||
|
||||
**다음 세션이 할 일**: 안 바뀜(`ROADMAP.md` M0부터, `.claude/luau-test/`
|
||||
결과 확인 우선).
|
||||
18
CLAUDE.md
18
CLAUDE.md
|
|
@ -47,8 +47,8 @@ modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션
|
|||
`framework-comparison-findings.md`/`additional-primitives-plan.md`(2026-08-09
|
||||
세 번째 세션에 마지막 열린 항목까지 전부 해소, 이제 배경 자료용)/
|
||||
`pre-implementation-audit.md`/`v1-compat-plan.md`
|
||||
— 전부 후순위(`tween-plan.md`는 2026-08-12 세션에서 거의 다 닫힘, 남은 건
|
||||
`Animate` 시그니처 정도로 더 이상 급하지 않음). 최신 목록·우선순위는
|
||||
— 전부 후순위(`tween-plan.md`는 2026-08-12 세션에서 사실상 다 닫힘, 남은
|
||||
건 자연완료 북키핑 정도로 더 이상 급하지 않음). 최신 목록·우선순위는
|
||||
`.claude/README.md`가 소스, 여기서 개수 반복 안 함(과거에 "두 개뿐"이라
|
||||
적어놨다가 새 문서 추가될 때마다 안 갱신되는 패턴이 반복돼서 아예 안
|
||||
세기로 함).
|
||||
|
|
@ -435,3 +435,17 @@ retract는 Tag처럼 확실히 청소). 이름 충돌 방지로 기존 단일
|
|||
`TweenBase` API 현실상 나머지 옵션들이 관찰상 Cancel과 동일했음), `initValue`는
|
||||
에이전트 범위 제외하고 사용자가 직접 처리하기로 확정. `Animate` 시그니처와
|
||||
자연완료 북키핑만 다음 세션으로 연기.
|
||||
|
||||
**2026-08-12 두 번째 세션 — `Animate` 콤비네이터 확정, `.claude/` and/or 삼항 관용구 감사**
|
||||
(`session/2026-08-12-02-animate-confirmed-and-or-audit.md`)
|
||||
"다음 세션"으로 미뤘던 `Animate`를 사용자가 곧바로 간단한 구체안으로
|
||||
확정: `Tween` opts(`Value` 제외)를 `T|State<T>`로 받아 각 필드를 resolve한
|
||||
뒤 `Tween{...}`을 반환하는 `function(self)...end` — `:Compute(fn)`의
|
||||
`self`-lazy-핸들 계약과 정확히 일치해 `state:Compute(Animate{...})`로
|
||||
바로 연결(구 `useTween` 2-인자 스케치 대체). 옵션이 State여도 값 변경이
|
||||
재애니메이션을 트리거하지 않는 게 의도된 동작임을 확정. 별도로 사용자가
|
||||
Luau `if-then-else` 표현식을 언급하며 `.claude/base` 전역 and/or 삼항
|
||||
관용구를 감사 — `bind-system-plan.md`의 `Dispatch.retractUnder`에서 실제
|
||||
falsy-값 버그(`v`가 `false`일 때 `nil`로 새는 문제) 발견·수정, 나머지
|
||||
히트는 가운데 값이 테이블/숫자라 안전 확인. `research/tween-plan.md`는
|
||||
이걸로 자연완료 북키핑 하나만 남기고 사실상 마감.
|
||||
|
|
|
|||
Loading…
Reference in a new issue