decide(tween): confirm natural-completion bookkeeping is left as-is, promote to base/

Completed 시 per-instance 북키핑 정리는 불필요 — 자연완료는 유저가 원한
목표값에 도달한 상태라 남은 참조가 부작용 없고, Value가 lerp 가능한
프리미티브라 메모리 문제도 없어 별도 정리 장치는 오버엔지니어링. 이걸로
tween-plan.md에 남은 열린 질문이 없어져 research/에서 base/로 승격,
라이브 크로스레퍼런스 전부 갱신.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
qwreey 2026-08-12 12:19:49 +09:00
parent 3e37d9bc36
commit e6880e518c
Signed by: qwreey
GPG key ID: D28DB79297A214BD
13 changed files with 119 additions and 30 deletions

View file

@ -43,6 +43,7 @@
| `attribute-plan.md` | **[2026-08-07 여덟 번째 세션 신설]** 단일 키 `[AttributeKey<T> "Name"]`(구 `Attribute<T>`) — `SetAttribute(name, nil)`이 네이티브 지우기라 `None` 센티널과 가장 깔끔하게 맞아떨어짐, `retract` 불필요. **[2026-08-11 아홉 번째 세션]** 여러 Store를 한 번에 attribute로 묶는 그룹 `Attribute(...)` 프리미티브 신설(`Tag`와 동형 array-part 값 객체, `Merged`로 헤테로지니어스 Store 합성), 이름 충돌 방지로 단일 키를 `AttributeKey`로 리네임(잠정). **[같은 세션 후속]** `AttributeKey(name)`이 이름별 weak 캐시로 동등성 보장하도록 확정되며, 그룹 Handler는 자기 완결형 재구현 대신 메모이즈된 키로 기존 단일 키 경로에 재귀 위임하는 걸로 개정(중복 구현 제거) | | `attribute-plan.md` | **[2026-08-07 여덟 번째 세션 신설]** 단일 키 `[AttributeKey<T> "Name"]`(구 `Attribute<T>`) — `SetAttribute(name, nil)`이 네이티브 지우기라 `None` 센티널과 가장 깔끔하게 맞아떨어짐, `retract` 불필요. **[2026-08-11 아홉 번째 세션]** 여러 Store를 한 번에 attribute로 묶는 그룹 `Attribute(...)` 프리미티브 신설(`Tag`와 동형 array-part 값 객체, `Merged`로 헤테로지니어스 Store 합성), 이름 충돌 방지로 단일 키를 `AttributeKey`로 리네임(잠정). **[같은 세션 후속]** `AttributeKey(name)`이 이름별 weak 캐시로 동등성 보장하도록 확정되며, 그룹 Handler는 자기 완결형 재구현 대신 메모이즈된 키로 기존 단일 키 경로에 재귀 위임하는 걸로 개정(중복 구현 제거) |
| `onchange-plan.md` | **[2026-08-10 세션 신설]** `OnChange(name)``GetPropertyChangedSignal` 바인딩 전용 DI 키, `Attribute`와 달리 제네릭 타입 파라미터 없음(콜백 타입은 인라인 명시, 이벤트 바인딩과 같은 급 트레이드오프). 전부 quad-roblox(`Handlers/OnChange.luau`), `State<function>`은 기존 이벤트 store-bind 메커니즘 재사용. **[2026-08-11 아홉 번째 세션 후속]** `AttributeKey`와 동일한 이름별 weak 캐시로 `OnChange(a) == OnChange(a)` 동등성 보장 | | `onchange-plan.md` | **[2026-08-10 세션 신설]** `OnChange(name)``GetPropertyChangedSignal` 바인딩 전용 DI 키, `Attribute`와 달리 제네릭 타입 파라미터 없음(콜백 타입은 인라인 명시, 이벤트 바인딩과 같은 급 트레이드오프). 전부 quad-roblox(`Handlers/OnChange.luau`), `State<function>`은 기존 이벤트 store-bind 메커니즘 재사용. **[2026-08-11 아홉 번째 세션 후속]** `AttributeKey`와 동일한 이름별 weak 캐시로 `OnChange(a) == OnChange(a)` 동등성 보장 |
| `relate-plan.md` | **[2026-08-08 신설]** `Relate``inst`를 weak 키로 하는 범용 릴레이션 프리미티브(`SetWeak`/`GetWeak`/`SetStrong`/`GetStrong`, 비싱글톤 생성자). 구 `base.perInstanceState(inst)` placeholder를 대체·정식 승격, `lifecycle-pattern.md``bindLifetime`/`canExecute`가 그 위에 얹힘 | | `relate-plan.md` | **[2026-08-08 신설]** `Relate``inst`를 weak 키로 하는 범용 릴레이션 프리미티브(`SetWeak`/`GetWeak`/`SetStrong`/`GetStrong`, 비싱글톤 생성자). 구 `base.perInstanceState(inst)` placeholder를 대체·정식 승격, `lifecycle-pattern.md``bindLifetime`/`canExecute`가 그 위에 얹힘 |
| `tween-plan.md` | **[2026-08-12 세션, `research/`에서 승격]** 값-레벨 `Tween<T>` 래퍼(PropertyHandler가 소비, 구 특수 bind key 모델은 `archive/tween-special-bind-key-reversed.md`). 3-상태 릴레이션 슬롯(`{Tween,Value}\|true\|nil`), `T'=T\|Tween<T>` 타입 치환. 옵션 값 모양은 `Info: TweenInfo?` 우선+편의 필드 폴백, override는 `Tween.Cancel`(기본)/`Tween.Finish` 2값. `Animate(info)``Tween` opts를 `T\|State<T>`로 받아 `:Apply`로 꽂는 sugar. 자연완료 시 per-instance 북키핑은 정리 안 해도 됨으로 확정(목표값 도달 상태라 부작용 없음, Completed 이벤트 구독 장치는 오버엔지니어링으로 판단). `initValue`는 사용자가 직접 처리(에이전트 범위 제외) |
## `reference/` — 온디맨드 참고 자료 (2026-08-07 신설) ## `reference/` — 온디맨드 참고 자료 (2026-08-07 신설)
@ -56,7 +57,6 @@
| 문서 | 내용 | 우선순위 | | 문서 | 내용 | 우선순위 |
|---|---|---| |---|---|---|
| `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>`로 받아 `factory(self)->State`를 반환하는 sugar로 확정(구 `useTween` 스케치 대체), 호출 경로는 같은 세션 후속 논의로 `:Compute`→`:Apply` 정정(재사용 가능한 콤비네이터 정합성 문제, `operator-sugar-plan.md`와 같은 근거). `initValue`는 사용자가 직접 처리(에이전트 범위 제외), 남은 건 자연완료 북키핑 하나뿐 | 하 — 사실상 다 닫힘 |
| `existing-instance-bind-plan.md` | 이미 생성된 인스턴스 재바인드 — 착수 안 하되 "미지원" 확정도 안 함, 열린 가능성 유지 | 하 — v2 초기 스코프 제외 | | `existing-instance-bind-plan.md` | 이미 생성된 인스턴스 재바인드 — 착수 안 하되 "미지원" 확정도 안 함, 열린 가능성 유지 | 하 — v2 초기 스코프 제외 |
| `debug-tooling-plan.md` | 실물 Instance→코드 위치 역추적 Studio 플러그인(`quad-debug`) — 채널 실현 가능성(BindableEvent/Function 크로스 컨텍스트)까지 실측 검증 완료, 세부 API 이름·구현만 남음 | 하 — 사용자가 "quad 개발 완료 전엔 착수 못 함"으로 직접 후순위 지정, base 설계 시 훅 확장 지점만 고려 | | `debug-tooling-plan.md` | 실물 Instance→코드 위치 역추적 Studio 플러그인(`quad-debug`) — 채널 실현 가능성(BindableEvent/Function 크로스 컨텍스트)까지 실측 검증 완료, 세부 API 이름·구현만 남음 | 하 — 사용자가 "quad 개발 완료 전엔 착수 못 함"으로 직접 후순위 지정, base 설계 시 훅 확장 지점만 고려 |
| `documentation-plan.md` | 문서 사이트 구조(초심자/api/심화/`quadnomicon` 4축, 백엔드별 트랙 분리) + UI 네이밍 컨벤션·Store 부작용 패턴·권장 이벤트 핸들링 3개 세부 문서 뼈대 | 하 — 착수 시점 미정, 구조/스코프만 합의된 상태 | | `documentation-plan.md` | 문서 사이트 구조(초심자/api/심화/`quadnomicon` 4축, 백엔드별 트랙 분리) + UI 네이밍 컨벤션·Store 부작용 패턴·권장 이벤트 핸들링 3개 세부 문서 뼈대 | 하 — 착수 시점 미정, 구조/스코프만 합의된 상태 |
@ -83,7 +83,7 @@
| `observer-cleanup-contract-rejected.md` | **[기각됨, 2026-08-09 코퍼스 정리 신설]** `Observer` 자체에 React `useEffect`식 cleanup 반환 계약을 추가하는 안 — 클로저로 이미 충분해 기각, `Effect`가 opt-in 상위 계층으로 이 패턴을 제공 | | `observer-cleanup-contract-rejected.md` | **[기각됨, 2026-08-09 코퍼스 정리 신설]** `Observer` 자체에 React `useEffect`식 cleanup 반환 계약을 추가하는 안 — 클로저로 이미 충분해 기각, `Effect`가 opt-in 상위 계층으로 이 패턴을 제공 |
| `keyed-collection-state-method-rejected.md` | **[기각됨, 2026-08-09 코퍼스 정리 신설]** 키 기반 동적 컬렉션 재조정 프리미티브를 `state:Keyed(...)` State 메소드로 두려던 초안 — Source 미사용 컴포넌트가 접근 못 한다는 반례로 철회, 현재는 자유 함수로 확정 | | `keyed-collection-state-method-rejected.md` | **[기각됨, 2026-08-09 코퍼스 정리 신설]** 키 기반 동적 컬렉션 재조정 프리미티브를 `state:Keyed(...)` State 메소드로 두려던 초안 — Source 미사용 컴포넌트가 접근 못 한다는 반례로 철회, 현재는 자유 함수로 확정 |
| `debug-channel-replicatedstorage-rejected.md` | **[기각됨, 2026-08-09 코퍼스 정리 신설]** quad-debug 채널을 `ReplicatedStorage`에 자동 생성하던 초안 — 게임 트리 오염 부작용으로 기각, quad 모듈 자신의 트리+`CollectionService` 태그로 대체 | | `debug-channel-replicatedstorage-rejected.md` | **[기각됨, 2026-08-09 코퍼스 정리 신설]** quad-debug 채널을 `ReplicatedStorage`에 자동 생성하던 초안 — 게임 트리 오염 부작용으로 기각, quad 모듈 자신의 트리+`CollectionService` 태그로 대체 |
| `tween-special-bind-key-reversed.md` | **[역전됨, 2026-08-10 신설]** 구 Tween 모델(`[Tween(key,tweenData...)] = storeValue` 특수 bind key, 우선순위 최상위 Dispatch 핸들러) — 값-레벨 `Tween<T>` 래퍼 모델로 완전히 대체됨(`research/tween-plan.md`) | | `tween-special-bind-key-reversed.md` | **[역전됨, 2026-08-10 신설]** 구 Tween 모델(`[Tween(key,tweenData...)] = storeValue` 특수 bind key, 우선순위 최상위 Dispatch 핸들러) — 값-레벨 `Tween<T>` 래퍼 모델로 완전히 대체됨(`base/tween-plan.md`) |
| `onchange-per-property-codegen-rejected.md` | **[기각됨, 2026-08-10 신설]** `OnChange.PropertyName` 프로퍼티별 정적 코드 생성 — Attribute의 정적 지름길과 달리 (클래스 수 × 프로퍼티 수) 규모로 폭발해 기각, `OnChange(name)` 단일 팩토리로 대체 | | `onchange-per-property-codegen-rejected.md` | **[기각됨, 2026-08-10 신설]** `OnChange.PropertyName` 프로퍼티별 정적 코드 생성 — Attribute의 정적 지름길과 달리 (클래스 수 × 프로퍼티 수) 규모로 폭발해 기각, `OnChange(name)` 단일 팩토리로 대체 |
## 참고 ## 참고

View file

@ -2,7 +2,7 @@
**역전 일시**: 2026-08-10. **원 확정 일시**: 2026-08-04(로드맵 인수인계 **역전 일시**: 2026-08-10. **원 확정 일시**: 2026-08-04(로드맵 인수인계
라운드 전후, "확정된 방향: 트윈을 Store/반응 그래프 밖에 둔다" 최초 작성). 라운드 전후, "확정된 방향: 트윈을 Store/반응 그래프 밖에 둔다" 최초 작성).
**현재 유효한 설계**: `research/tween-plan.md`(전면 재작성됨)가 최종 소스. **현재 유효한 설계**: `base/tween-plan.md`(전면 재작성됨)가 최종 소스.
이 파일은 능동적으로 참고할 필요 없음(구현에 안 씀) — 왜 "Tween이 곧 이 파일은 능동적으로 참고할 필요 없음(구현에 안 씀) — 왜 "Tween이 곧
범용 store-bind 핸들러"였던 모델에서 "Tween은 PropertyHandler가 소비하는 범용 store-bind 핸들러"였던 모델에서 "Tween은 PropertyHandler가 소비하는
값-레벨 래퍼"로 넘어갔는지가 `quadnomicon` 소재로 가치 있어서 사유·원문을 값-레벨 래퍼"로 넘어갔는지가 `quadnomicon` 소재로 가치 있어서 사유·원문을

View file

@ -143,7 +143,7 @@ quad/
│ ├── Modifier.luau # flatten-before-dispatch, immutable 체이닝, 제네릭 `__index` 필드 setter 합성 + `:Apply`/`:Peek`/`Overridden`(`base/modifier-plan.md`) │ ├── Modifier.luau # flatten-before-dispatch, immutable 체이닝, 제네릭 `__index` 필드 setter 합성 + `:Apply`/`:Peek`/`Overridden`(`base/modifier-plan.md`)
│ ├── Tag.luau # 값 타입+immutable clone 체이닝(`Tag(...)`/`:Added`/`:Removed`/`:Contains`/`:Apply`/`Merged`), CollectionService 글루는 quad-roblox Handlers/Tag.luau(`base/tag-plan.md`, 2026-08-08 세 번째 세션) │ ├── Tag.luau # 값 타입+immutable clone 체이닝(`Tag(...)`/`:Added`/`:Removed`/`:Contains`/`:Apply`/`Merged`), CollectionService 글루는 quad-roblox Handlers/Tag.luau(`base/tag-plan.md`, 2026-08-08 세 번째 세션)
│ ├── Attribute.luau # 그룹 값 타입+API(`Attribute(store1, store2, ...)`/`Merged`, `Tag`와 동형) — `SetAttribute` 글루는 quad-roblox Handlers/Attribute.luau(`base/attribute-plan.md`, 2026-08-11 아홉 번째 세션). 단일 키(`AttributeKey<<T>>`)는 값 타입 레이어 없이 quad-roblox 단독 소속(아래) │ ├── Attribute.luau # 그룹 값 타입+API(`Attribute(store1, store2, ...)`/`Merged`, `Tag`와 동형) — `SetAttribute` 글루는 quad-roblox Handlers/Attribute.luau(`base/attribute-plan.md`, 2026-08-11 아홉 번째 세션). 단일 키(`AttributeKey<<T>>`)는 값 타입 레이어 없이 quad-roblox 단독 소속(아래)
│ ├── Tween.luau # 값 타입만(`Tween(opts)` 팩토리, `isTween`/`TweenTag`) — 엔진 무관, 독립 Dispatch 핸들러 아님. 실제 애니메이션 처리는 quad-roblox Handlers/Property.luau 내부 분기(`research/tween-plan.md`, 2026-08-10 세션 재설계) │ ├── Tween.luau # 값 타입만(`Tween(opts)` 팩토리, `isTween`/`TweenTag`) — 엔진 무관, 독립 Dispatch 핸들러 아님. 실제 애니메이션 처리는 quad-roblox Handlers/Property.luau 내부 분기(`base/tween-plan.md`, 2026-08-10 세션 재설계)
│ ├── Effect.luau # `Effect(fn, state?)` — state 없으면 설치1회+leaf사망시 정리, 있으면 State.Observer를 조합해 재실행(`base/effect-plan.md`) │ ├── Effect.luau # `Effect(fn, state?)` — state 없으면 설치1회+leaf사망시 정리, 있으면 State.Observer를 조합해 재실행(`base/effect-plan.md`)
│ ├── Dispatch/ │ ├── Dispatch/
│ │ ├── init.luau # process/retract 엔진, isHandlable 우선순위 스캔, `chains`(inst,k별 핸들러 체인)+`retractUnder`(`bind-system-plan.md` "Dispatch 체인" 절, 2026-08-08 세 번째 세션) │ │ ├── init.luau # process/retract 엔진, isHandlable 우선순위 스캔, `chains`(inst,k별 핸들러 체인)+`retractUnder`(`bind-system-plan.md` "Dispatch 체인" 절, 2026-08-08 세 번째 세션)
@ -170,7 +170,7 @@ quad/
│ ├── Tag.luau # CollectionService 글루만(process/retract) — 값 타입/API는 quad-base Tag.luau(`base/tag-plan.md`) │ ├── Tag.luau # CollectionService 글루만(process/retract) — 값 타입/API는 quad-base Tag.luau(`base/tag-plan.md`)
│ ├── Slot.luau # base Slot 재조정 로직의 실제 적용/해제(Instance Parent 조작) │ ├── Slot.luau # base Slot 재조정 로직의 실제 적용/해제(Instance Parent 조작)
│ └── InstanceChild.luau # k:number, v:Instance — 중첩 인스턴스 자식(예: Frame { Frame {} }) │ └── InstanceChild.luau # k:number, v:Instance — 중첩 인스턴스 자식(예: Frame { Frame {} })
├── Animate.luau # `Animate(info)` 편의 콤비네이터 — `factory(self)->State`, `:Apply`로 붙임(내부는 `:Compute`/`Tween{...}` 조합), base 프리미티브 아님(`research/tween-plan.md`) ├── Animate.luau # `Animate(info)` 편의 콤비네이터 — `factory(self)->State`, `:Apply`로 붙임(내부는 `:Compute`/`Tween{...}` 조합), base 프리미티브 아님(`base/tween-plan.md`)
├── DI/ ├── DI/
│ └── init.luau # 제네릭 생성자 + ~25개 정적 필드(UIInstances) │ └── init.luau # 제네릭 생성자 + ~25개 정적 필드(UIInstances)
└── init.luau └── init.luau

View file

@ -114,7 +114,7 @@ end
같은 `AttributeKeyHandler`가 이 키를 계속 담당(핸들러 *타입*이 안 바뀜). 같은 `AttributeKeyHandler`가 이 키를 계속 담당(핸들러 *타입*이 안 바뀜).
`retract`가 의미 있는 유일한 패턴("매치되는 핸들러 타입 자체가 바뀜", `retract`가 의미 있는 유일한 패턴("매치되는 핸들러 타입 자체가 바뀜",
`Tag(...)`↔`nil`이 실사례 — 2026-08-10 세션부터 Tween은 더 이상 이 `Tag(...)`↔`nil`이 실사례 — 2026-08-10 세션부터 Tween은 더 이상 이
패턴의 예시가 아님, `research/tween-plan.md`)에 해당 안 함 — 패턴의 예시가 아님, `base/tween-plan.md`)에 해당 안 함 —
`bind-system-plan.md` "확정된 디스패치 모델" 절이 한때 Attribute도 `bind-system-plan.md` "확정된 디스패치 모델" 절이 한때 Attribute도
retract 필요 예시로 들었던 걸 여기서 바로잡음. retract 필요 예시로 들었던 걸 여기서 바로잡음.
- store-bind 가능(일반 프로퍼티와 동일하게 취급, `Store<T>`/`State<T>` - store-bind 가능(일반 프로퍼티와 동일하게 취급, `Store<T>`/`State<T>`

View file

@ -132,7 +132,7 @@ src/schema/union.luau:48-68`) — 에러 메시지는 즉시 문자열로 만들
PropertyHandler가 소비하는 값-레벨 래퍼(`Tween<T>`)로 재설계되며 PropertyHandler가 소비하는 값-레벨 래퍼(`Tween<T>`)로 재설계되며
매치되는 핸들러가 항상 PropertyHandler 하나뿐이 되어 이 케이스 매치되는 핸들러가 항상 PropertyHandler 하나뿐이 되어 이 케이스
자체가 사라짐 — 트윈 취소/전환은 이제 PropertyHandler 내부의 자체가 사라짐 — 트윈 취소/전환은 이제 PropertyHandler 내부의
3-상태 릴레이션 슬롯으로 처리(`research/tween-plan.md`, `archive/ 3-상태 릴레이션 슬롯으로 처리(`base/tween-plan.md`, `archive/
tween-special-bind-key-reversed.md`). tween-special-bind-key-reversed.md`).
- store bind가 새 값으로 넘어갈 때 이전 핸들러의 `retract`를 호출해주면 - store bind가 새 값으로 넘어갈 때 이전 핸들러의 `retract`를 호출해주면
됨 — **정확한 전파 메커니즘은 아래 "Dispatch 체인" 절 참고**(재귀 됨 — **정확한 전파 메커니즘은 아래 "Dispatch 체인" 절 참고**(재귀
@ -324,7 +324,7 @@ NoneHandler.process(inst, k, v) = process(inst, k, nil) -- 재귀 재호출
등록됨 — base 기본 핸들러와 backend 핸들러가 별도 경로로 안 갈리고 등록됨 — base 기본 핸들러와 backend 핸들러가 별도 경로로 안 갈리고
전부 하나의 우선순위 스캔을 공유. **[정정, 2026-08-10 세션]** Tween은 전부 하나의 우선순위 스캔을 공유. **[정정, 2026-08-10 세션]** Tween은
더 이상 별도로 등록되는 핸들러가 아님 — Property 핸들러 내부에서 더 이상 별도로 등록되는 핸들러가 아님 — Property 핸들러 내부에서
소비되는 값-레벨 래퍼로 재설계됨(`research/tween-plan.md`). 소비되는 값-레벨 래퍼로 재설계됨(`base/tween-plan.md`).
- **모듈 재생성(`New()`)과의 관계 — 새 설계 불필요, 이미 있는 선례로 자연히 - **모듈 재생성(`New()`)과의 관계 — 새 설계 불필요, 이미 있는 선례로 자연히
풀림.** v1처럼 `require`를 감싸 `Init(QuadId?)`로 격리 인스턴스를 만드는 풀림.** v1처럼 `require`를 감싸 `Init(QuadId?)`로 격리 인스턴스를 만드는
방식은 안 씀(위 "확정된 것" 절 — id 기반 조회 자체가 Ref로 대체되며 방식은 안 씀(위 "확정된 것" 절 — id 기반 조회 자체가 Ref로 대체되며
@ -2008,7 +2008,7 @@ Modifier처럼 플래튼하지 않는가"는 설계 근거를 알고 싶은 사
**[2026-08-12 세션 감사에서 확인] `:Compute` 콜백 인자에 `:Get()`을 빠뜨리는 **[2026-08-12 세션 감사에서 확인] `:Compute` 콜백 인자에 `:Get()`을 빠뜨리는
실수가 반복되기 쉬움 — 실제로 `.claude/` 문서 예시 코드 4곳(`tag-plan.md`, 실수가 반복되기 쉬움 — 실제로 `.claude/` 문서 예시 코드 4곳(`tag-plan.md`,
`slot-plan.md` 2곳, `research/tween-plan.md`)에서 발견·수정됨.** `fn(self, `slot-plan.md` 2곳, `base/tween-plan.md`)에서 발견·수정됨.** `fn(self,
...)`의 모든 인자가 raw 값이 아니라 lazy State 핸들이라는 원칙(바로 위 절)을 ...)`의 모든 인자가 raw 값이 아니라 lazy State 핸들이라는 원칙(바로 위 절)을
사람도 에이전트도 코드 작성 중에 잊기 쉬운 지점 — `:Compute`/`:With` 콜백 사람도 에이전트도 코드 작성 중에 잊기 쉬운 지점 — `:Compute`/`:With` 콜백
안에서 인자를 비교(`==`)/연산(`+`)/테이블에 담기 전에 항상 `:Get()`부터 안에서 인자를 비교(`==`)/연산(`+`)/테이블에 담기 전에 항상 `:Get()`부터
@ -2272,7 +2272,7 @@ T|State<T>|nil`가 돌려주는 raw union을 사용자 코드가 분기하려면
`Source`/`Slot`/`None`까지, Handler 구현(`isHandlable`에서 "이 값이 `Source`/`Slot`/`None`까지, Handler 구현(`isHandlable`에서 "이 값이
Store인가/Tag인가" 판별, 또는 PropertyHandler의 `process` 내부에서 Store인가/Tag인가" 판별, 또는 PropertyHandler의 `process` 내부에서
"이 값이 Tween인가" 판별 — 2026-08-10 세션부터 `isTween``isHandlable` "이 값이 Tween인가" 판별 — 2026-08-10 세션부터 `isTween``isHandlable`
아니라 값-레벨 분기에서만 쓰임, `research/tween-plan.md` 참고)과 사용자 아니라 값-레벨 분기에서만 쓰임, `base/tween-plan.md` 참고)과 사용자
코드 양쪽에서 반복적으로 필요해질 수단이라 `isState` 하나만 만들고 코드 양쪽에서 반복적으로 필요해질 수단이라 `isState` 하나만 만들고
끝내지 않고 전체를 일관된 메커니즘으로 끝내지 않고 전체를 일관된 메커니즘으로
통합(component-composition-plan.md 4번 절이 이미 "`isSource`류 판별자로 통합(component-composition-plan.md 4번 절이 이미 "`isSource`류 판별자로

View file

@ -322,7 +322,7 @@ predicate(`Brand` 절)를 State/Source 쪽에도 적용해 **런타임에 직접
왜 Modifier만 막고 나머지는 다 허용하는지의 핵심 근거. **[정정, 왜 Modifier만 막고 나머지는 다 허용하는지의 핵심 근거. **[정정,
2026-08-10 세션] `Tween`은 이 그룹에서 빠짐** — Tween이 독립 Dispatch 2026-08-10 세션] `Tween`은 이 그룹에서 빠짐** — Tween이 독립 Dispatch
핸들러(`process`/`retract`를 가진 dispatch 참가자)에서 PropertyHandler가 핸들러(`process`/`retract`를 가진 dispatch 참가자)에서 PropertyHandler가
소비하는 값-레벨 래퍼로 재설계되며(`research/tween-plan.md`), `Tween<T>` 소비하는 값-레벨 래퍼로 재설계되며(`base/tween-plan.md`), `Tween<T>`
이제 `process`/`retract`가 없는 순수 raw 데이터 값 — `None`과 같은 이제 `process`/`retract`가 없는 순수 raw 데이터 값 — `None`과 같은
분류. State/Source에 `Tween<T>`가 담기는 것 자체는 여전히 문제없이 분류. State/Source에 `Tween<T>`가 담기는 것 자체는 여전히 문제없이
허용되지만(위 타입 대수 절 참고), 그 이유는 "재귀 dispatch 참가자라서"가 허용되지만(위 타입 대수 절 참고), 그 이유는 "재귀 dispatch 참가자라서"가
@ -550,7 +550,7 @@ Source도 같이 잡아줌 — **[2026-08-07 여덟 번째 세션 정정] `isSou
### 10. `Tween<T>`와의 타입 합성 — `T' = T | Tween<T>` 치환만으로 해결 (2026-08-10 세션) ### 10. `Tween<T>`와의 타입 합성 — `T' = T | Tween<T>` 치환만으로 해결 (2026-08-10 세션)
`research/tween-plan.md`가 값-레벨 `Tween<T>` 래퍼로 재설계되며, 프로퍼티류 `base/tween-plan.md`가 값-레벨 `Tween<T>` 래퍼로 재설계되며, 프로퍼티류
Modifier 필드 setter가 트윈 값도 받을 수 있어야 하는지가 자연히 따라오는 Modifier 필드 setter가 트윈 값도 받을 수 있어야 하는지가 자연히 따라오는
질문이었음 — **답은 "이미 있는 `T | State<T>` 필드 타입 모양에 새 케이스를 질문이었음 — **답은 "이미 있는 `T | State<T>` 필드 타입 모양에 새 케이스를
추가할 필요가 없다"** — 위 4번 절이 확정한 필드 타입 모양(리터럴 `T` 또는 추가할 필요가 없다"** — 위 4번 절이 확정한 필드 타입 모양(리터럴 `T` 또는

View file

@ -1,4 +1,4 @@
# Tween / 애니메이션 플러깅 (구조+옵션 값 모양+`Animate` 확정 — 자연완료 북키핑만 남음) # Tween / 애니메이션 플러깅 (전부 확정 — `base/`로 승격)
**상태**: research — **2026-08-10 세션에서 구조 전체가 재설계됨.** 기존 **상태**: research — **2026-08-10 세션에서 구조 전체가 재설계됨.** 기존
"`v`가 Store인 아무 `k`나 잡는 우선순위 최상위 Dispatch 핸들러" 모델은 "`v`가 Store인 아무 `k`나 잡는 우선순위 최상위 Dispatch 핸들러" 모델은
@ -14,8 +14,10 @@ tweenData...)] = storeValue`)은 `archive/tween-special-bind-key-reversed.md`로
시그니처까지 전부 확정됨**(아래 "확정: `Tween{...}` 최종 모양"/"`Animate` 시그니처까지 전부 확정됨**(아래 "확정: `Tween{...}` 최종 모양"/"`Animate`
콤비네이터" 절), **같은 날 후속 논의에서 `Animate`의 호출 경로가 콤비네이터" 절), **같은 날 후속 논의에서 `Animate`의 호출 경로가
`:Compute` 직결 → `:Apply`로 정정됨**(아래 "왜 `:Apply`로 정정됐는가" 절, `:Compute` 직결 → `:Apply`로 정정됨**(아래 "왜 `:Apply`로 정정됐는가" 절,
`research/operator-sugar-plan.md`와 같은 근거) — 남은 건 자연 완료 `research/operator-sugar-plan.md`와 같은 근거). **같은 날 다섯 번째 후속
(Completed) 시 북키핑 정리 여부뿐. 논의에서 마지막 남은 질문(자연완료 시 북키핑 정리 여부)도 "정리 안 해도
됨"으로 확정**(아래 "열린 질문" 절) — 이걸로 열린 설계 질문이 없어져
`research/`에서 `base/`로 승격.
`initValue`는 사용자가 필요해지면 직접 처리하기로 확정(에이전트 작업 `initValue`는 사용자가 필요해지면 직접 처리하기로 확정(에이전트 작업
범위에서 제외, 아래 해당 절 참고). 원본: 범위에서 제외, 아래 해당 절 참고). 원본:
`.claude/initreq/raw-userinput.md` "트윈은 어떻게 할 것이냐" / "스토어 값은 `.claude/initreq/raw-userinput.md` "트윈은 어떻게 할 것이냐" / "스토어 값은
@ -444,14 +446,32 @@ Tween(opts: {
받으므로(다른 모든 핸들러와 동일) 이 문제 자체가 성립하지 않음. 절 자체는 받으므로(다른 모든 핸들러와 동일) 이 문제 자체가 성립하지 않음. 절 자체는
과거 기록으로만 남김, 실행할 내용 없음. 과거 기록으로만 남김, 실행할 내용 없음.
## 열린 질문 (`.claude/question.md`에도 취합) ## 열린 질문 — 전부 해소됨
**2026-08-12 세션에서 옵션 값 모양/override 정책 이름/릴레이션 슬롯 저장 **2026-08-12 세션에서 옵션 값 모양/override 정책 이름/릴레이션 슬롯 저장
모양/`Animate` 콤비네이터 시그니처까지 전부 확정됨** — 아래 하나만 남음: 모양/`Animate` 콤비네이터 시그니처까지 전부 확정됨**, 마지막 남았던 아래
질문도 같은 날 다섯 번째 후속 논의로 확정됨 — 이제 열린 설계 질문 없음.
- 자연 완료(Completed) 시 per-instance 북키핑 정리 여부(3-상태 슬롯을 ### 자연 완료(Completed) 시 per-instance 북키핑 — 정리 안 해도 됨 (확정)
`true`로 되돌리는 시점) — `research/pre-implementation-audit.md` 2-10번
참고, M11 착수 시 확정. `research/pre-implementation-audit.md` 2-10번이 제기했던 질문. **결론:
Completed 이벤트를 구독해 3-상태 릴레이션 슬롯을 `true`로 되돌리는 등의
정리 로직은 만들지 않는다.**
**근거**: 이 정리를 하고 싶어지는 동기는 "인스턴스 초기 생성 시 프로퍼티가
유저가 원치 않는 값(예: `Position`이 기본 `UDim2.new(0,0,0,0)`)일 수 있어,
거기서 트윈이 시작되면 툭 튀어 보인다"는 문제인데 — 이건 이미 **"첫 세팅"
분기**(위 "3-상태 저장" 절의 `prev == nil` 케이스, 애니메이션 없이 즉시
세팅)가 처리하는 문제지, 자연완료와는 무관하다. 자연완료 상태는 반대로
**유저가 원한 목표값에 정확히 도달한 상태**이므로, 그 상태를 나타내는
북키핑(`{Tween, Value}`)을 안 지우고 남겨둬도 다음에 이 `(inst,k)`가 다시
process될 때 위 "3-상태 저장"의 `prev``{Tween, Value}` 테이블 분기를
타는 것뿐 — override 정책(`Cancel`/`Finish`)이 정확히 이 케이스를 위해
이미 정의돼 있어 별다른 부작용이 없다. 게다가 `Value`는 항상 lerp 가능한
프리미티브(number/UDim/Vector 등, 테이블 aliasing 걱정이 있는 타입이
아님)라 참조를 계속 들고 있어도 메모리/정합성 문제가 없다. 이 상태에서
굳이 Completed 이벤트를 구독해 슬롯을 되돌리는 별도 장치를 추가하는 건
실질적 이득 없이 복잡도만 늘리는 오버엔지니어링으로 판단.
`initValue`(진입 애니메이션)는 별도 취급 — 위 해당 절 참고, **에이전트 `initValue`(진입 애니메이션)는 별도 취급 — 위 해당 절 참고, **에이전트
작업 범위에서 제외, 필요해지면 사용자가 직접 처리**하기로 확정(질문 작업 범위에서 제외, 필요해지면 사용자가 직접 처리**하기로 확정(질문

View file

@ -293,7 +293,7 @@ context-rejected.md`. 아래는 그중 **아직 실제로 열려있는 것만**
| Batch(lexical) 기각, Context(+레이어드 Store) 기각 | `archive/batch-rejected.md`, `archive/context-rejected.md` | | Batch(lexical) 기각, Context(+레이어드 Store) 기각 | `archive/batch-rejected.md`, `archive/context-rejected.md` |
| Fusion/Vide 비교 리서치(주의: 일부 서술은 이후 라운드에서 뒤집힘, 문서 내 정정 표시 참고) | `reference/comparison-fusion-vide.md` | | Fusion/Vide 비교 리서치(주의: 일부 서술은 이후 라운드에서 뒤집힘, 문서 내 정정 표시 참고) | `reference/comparison-fusion-vide.md` |
| v1 내부 동작 스냅샷 | `reference/quad-v1-architecture.md` | | v1 내부 동작 스냅샷 | `reference/quad-v1-architecture.md` |
| 트윈 — 값-레벨 `Tween<T>` 래퍼(2026-08-10)+옵션 값 모양·override 정책·`Animate` 콤비네이터(2026-08-12) 전부 확정, 자연완료 북키핑 하나만 남음 | `research/tween-plan.md` | | 트윈 — 값-레벨 `Tween<T>` 래퍼(2026-08-10)+옵션 값 모양·override 정책·`Animate` 콤비네이터·자연완료 북키핑(2026-08-12) 전부 확정, `base/`로 승격 | `base/tween-plan.md` |
| quad2-try(폐기된 이전 시도) 리서치 — OOP 상속/커스텀 파서/Slot 스텁/`Pipe` COW 전부 죽은 접근으로 확인, 반복 조사 금지 | `base/bind-system-plan.md` | | quad2-try(폐기된 이전 시도) 리서치 — OOP 상속/커스텀 파서/Slot 스텁/`Pipe` COW 전부 죽은 접근으로 확인, 반복 조사 금지 | `base/bind-system-plan.md` |
--- ---

View file

@ -36,7 +36,7 @@
10. **생명주기** — GC 위임(수동 정리 불필요), Destroy 이후 대상 재사용 금지 (`lifecycle-pattern.md`) 10. **생명주기** — GC 위임(수동 정리 불필요), Destroy 이후 대상 재사용 금지 (`lifecycle-pattern.md`)
11. **Ref 기초** — 외부 관리 Instance 참조/마이그레이션용, `Ref(default):Callback(fn)`을 children 배열 숫자 슬롯에 직접 놓기 + 배열 위치로 자식 전/후 표현, "프로퍼티보다도 먼저" 필요할 때만 `PreRef`(2026-08-07 세 번째 세션, `phase` 옵션 폐기) (`architecture.md`, `bind-system-plan.md`) 11. **Ref 기초** — 외부 관리 Instance 참조/마이그레이션용, `Ref(default):Callback(fn)`을 children 배열 숫자 슬롯에 직접 놓기 + 배열 위치로 자식 전/후 표현, "프로퍼티보다도 먼저" 필요할 때만 `PreRef`(2026-08-07 세 번째 세션, `phase` 옵션 폐기) (`architecture.md`, `bind-system-plan.md`)
12. **파생값 최소 예시**`:With(...)` + `:Compute(fn)` 기본형 (`bind-system-plan.md`, `store-semantics.md`) 12. **파생값 최소 예시**`:With(...)` + `:Compute(fn)` 기본형 (`bind-system-plan.md`, `store-semantics.md`)
13. **Tween 기초**`[Tween(key, ...)] = storeValue`, 취소 시 현재 보간값에서 자연스럽게 이어짐 (`research/tween-plan.md`) 13. **Tween 기초**`[Tween(key, ...)] = storeValue`, 취소 시 현재 보간값에서 자연스럽게 이어짐 (`base/tween-plan.md`)
14. **UI 숏핸드(quad-roblox 한정)**`UICorner`/`UIPadding`/`UIPaddingOffset`/`UIScale` 인라인 키 (`base/ui-shorthand-plan.md`) 14. **UI 숏핸드(quad-roblox 한정)**`UICorner`/`UIPadding`/`UIPaddingOffset`/`UIScale` 인라인 키 (`base/ui-shorthand-plan.md`)
--- ---
@ -132,7 +132,7 @@ v1 폐기 API/버그/구조 결함 전부 v2 설계를 정당화하는 내부
7. 왜 컴포넌트 경계는 named parameter인가(Compose/Fusion/Vide/v1 수렴) — `component-composition-plan.md` 7. 왜 컴포넌트 경계는 named parameter인가(Compose/Fusion/Vide/v1 수렴) — `component-composition-plan.md`
8. 왜 "다중 루트 반환" 개념을 없앴는가 — `component-composition-plan.md` 8. 왜 "다중 루트 반환" 개념을 없앴는가 — `component-composition-plan.md`
9. 왜 Slot은 단일 마운트 소유권을 강제하는가(v1/Fusion/Vide 대비) — `slot-plan.md`, `comparison-fusion-vide.md` 9. 왜 Slot은 단일 마운트 소유권을 강제하는가(v1/Fusion/Vide 대비) — `slot-plan.md`, `comparison-fusion-vide.md`
10. 왜 Tween은 반응 그래프 밖에 있는가 — `research/tween-plan.md` 10. 왜 Tween은 반응 그래프 밖에 있는가 — `base/tween-plan.md`
11. 왜 `:Emit()`은 Source 전용이고 파생 State엔 없는가(호출부는 `source:Emit()`, 2026-08-06 후속 세션에서 `Store:Emit(key)`→이 형태로 정리) — `store-semantics.md` 11. 왜 `:Emit()`은 Source 전용이고 파생 State엔 없는가(호출부는 `source:Emit()`, 2026-08-06 후속 세션에서 `Store:Emit(key)`→이 형태로 정리) — `store-semantics.md`
12. 독립 프리미티브 vs 파생 데이터 — 생성자 모양을 결정하는 원칙 — `store-semantics.md` 12. 독립 프리미티브 vs 파생 데이터 — 생성자 모양을 결정하는 원칙 — `store-semantics.md`
14. 왜 컴포넌트는 전역 store를 직접 참조하면 안 되는가(이식성) — `purity-and-effects-plan.md` 14. 왜 컴포넌트는 전역 store를 직접 참조하면 안 되는가(이식성) — `purity-and-effects-plan.md`
@ -248,7 +248,7 @@ additional-primitives-plan.md`의 "문서화 백로그" 절이 원자료)**:
`setOffsetSource`(Length/Offset)로 2026-08-09 여섯 번째 세션에 확정, `setOffsetSource`(Length/Offset)로 2026-08-09 여섯 번째 세션에 확정,
`bind-system-plan.md` "Length/Offset" 절 참고. `bind-system-plan.md` "Length/Offset" 절 참고.
- Tween 오버라이드/삭제후재시작/끝점이동 세부 옵션 키 이름, 트윈 옵션 값 - Tween 오버라이드/삭제후재시작/끝점이동 세부 옵션 키 이름, 트윈 옵션 값
모양(TweenInfo vs 편의 필드) (`research/tween-plan.md`) — 아직 열림. 모양(TweenInfo vs 편의 필드) (`base/tween-plan.md`) — 아직 열림.
- **[해소됨]** `Attribute<T>` 제네릭 vs 타입별 정적 생성자 — 2026-08-09 - **[해소됨]** `Attribute<T>` 제네릭 vs 타입별 정적 생성자 — 2026-08-09
열한 번째 세션에 "둘 다 채택"으로 확정, `base/attribute-plan.md` 참고. 열한 번째 세션에 "둘 다 채택"으로 확정, `base/attribute-plan.md` 참고.
- provider/processor 네이밍 — **[해소됨]** `Handler`로 이미 오래전 확정 - provider/processor 네이밍 — **[해소됨]** `Handler`로 이미 오래전 확정

View file

@ -149,7 +149,7 @@ introspection 로직을 추가하는 거라 라이브러리 복잡도가 늘어
`quad-base` — Store/State 계층 위에서만 동작하는 순수 함수라 엔진 종속 `quad-base` — Store/State 계층 위에서만 동작하는 순수 함수라 엔진 종속
없음(`quad-roblox` 아님). `Animate``Tween`과 함께 어디에 배치됐는지와 없음(`quad-roblox` 아님). `Animate``Tween`과 함께 어디에 배치됐는지와
같은 결로 맞추면 됨(`research/tween-plan.md` 참고, 단 `Animate` 자체는 같은 결로 맞추면 됨(`base/tween-plan.md` 참고, 단 `Animate` 자체는
`Tween`이 quad-roblox 개념(`PropertyHandler`)에 연결되므로 quad-roblox `Tween`이 quad-roblox 개념(`PropertyHandler`)에 연결되므로 quad-roblox
배치 — Operator 슈가는 그런 엔진 종속이 없다는 점이 다름). 배치 — Operator 슈가는 그런 엔진 종속이 없다는 점이 다름).

View file

@ -44,7 +44,7 @@ M0 착수 전에 확인**. 우선순위 2는 지금 결정해두면 싼데 안
바뀌어, "일반 store-bind와 Tween-store-bind가 같은 핸들러인지"라는 바뀌어, "일반 store-bind와 Tween-store-bind가 같은 핸들러인지"라는
질문 자체가 성립하지 않게 됨 — 범용 State/Source 언랩은 `Dispatch/ 질문 자체가 성립하지 않게 됨 — 범용 State/Source 언랩은 `Dispatch/
StoreBind.luau` 하나뿐이고 Tween은 그 아래에서 나온 `realv` StoreBind.luau` 하나뿐이고 Tween은 그 아래에서 나온 `realv`
PropertyHandler가 직접 판별. 상세는 `research/tween-plan.md`(전면 PropertyHandler가 직접 판별. 상세는 `base/tween-plan.md`(전면
재작성), 구 모델은 `archive/tween-special-bind-key-reversed.md`. 아래는 재작성), 구 모델은 `archive/tween-special-bind-key-reversed.md`. 아래는
원래 발견 당시 기록. 원래 발견 당시 기록.
@ -488,7 +488,14 @@ Modifier를 합친다"는 시나리오가 `Overridden`의 가장 그럴듯한
### 2-10. Tween 자연완료(Completed) 시 per-instance 북키핑 정리 여부가 명세 안 됨 ### 2-10. Tween 자연완료(Completed) 시 per-instance 북키핑 정리 여부가 명세 안 됨
**위치**: `research/tween-plan.md` "`retract`(구 cleanup)로 확정된 **[해소됨, 2026-08-12 세션]** 결론은 "정리 안 해도 됨" — 자연완료 상태는
유저가 원한 목표값에 도달한 상태라 남은 북키핑이 부작용을 안 일으키고
(`Value`가 항상 lerp 가능한 프리미티브), Completed 이벤트 구독 같은 별도
정리 장치는 오버엔지니어링으로 판단해 안 만들기로 확정. 상세 근거는
`base/tween-plan.md`(승격됨) "자연 완료(Completed) 시 per-instance
북키핑 — 정리 안 해도 됨" 절. 아래는 원래 발견 당시 기록.
**위치**: `base/tween-plan.md` "`retract`(구 cleanup)로 확정된
오버라이드 시맨틱" 절. 오버라이드 시맨틱" 절.
**문제**: "새 값이 들어와 갈아치울 때"의 `retract` 동작(4가지 옵션, 기본값 **문제**: "새 값이 들어와 갈아치울 때"의 `retract` 동작(4가지 옵션, 기본값

View file

@ -0,0 +1,52 @@
# 2026-08-12 세션 — Tween 자연완료 북키핑 확정, `tween-plan.md``base/`로 승격
`research/tween-plan.md`에 마지막으로 남아있던 열린 질문 — 자연 완료
(Completed) 시 per-instance weak-keyed 저장소(3-상태 릴레이션 슬롯)에
남은 이전 Tween 참조를 정리해야 하는가(`research/pre-implementation-audit.md`
2-10번) — 를 사용자가 직접 결론냄.
## 결론: 정리 안 해도 됨
사용자 설명 그대로 요약:
- 이 정리를 하고 싶어지는 동기는 "인스턴스 초기 생성 시 프로퍼티가 유저가
원치 않는 값(예: `Position`이 기본 `UDim2.new(0,0,0,0)`)일 수 있어, 거기서
트윈이 시작되면 툭 튀어 오른다"는 문제다.
- 그런데 이건 이미 "3-상태 저장"의 **첫 세팅 분기**(`prev == nil` →
애니메이션 없이 즉시 세팅)가 처리하는 문제고, 자연완료와는 무관하다.
- **자연완료 상태는 반대로 유저가 원한 목표값에 정확히 도달한 상태**
그 상태를 나타내는 북키핑을 안 지우고 남겨둬도, 다음 process 때 기존
override 정책(`Cancel`/`Finish`)이 정확히 이 케이스를 위해 이미 정의돼
있어 부작용이 없다.
- `Value`는 항상 lerp 가능한 프리미티브(number/UDim/Vector 등, 테이블
aliasing 걱정이 있는 타입이 아님)라 참조를 계속 들고 있어도 메모리/정합성
문제가 없다.
- 이 상태에서 Completed 이벤트를 구독해 슬롯을 되돌리는 별도 장치를
추가하는 건 실질적 이득 없이 복잡도만 늘리는 오버엔지니어링.
## `base/`로 승격
이걸로 `research/tween-plan.md`에 남은 열린 설계 질문이 없어짐 — 사용자
제안대로 `base/tween-plan.md`로 승격(`git mv`).
**반영된 파일**:
- `base/tween-plan.md`(구 `research/tween-plan.md`) — 헤더/열린 질문
절 갱신, "자연 완료(Completed) 시 per-instance 북키핑 — 정리 안 해도
됨 (확정)" 절 신설.
- `research/pre-implementation-audit.md` 2-10번 — `[해소됨]` 표시 추가.
- `.claude/README.md``research/` 표에서 `tween-plan.md` 행 제거,
`base/` 표에 추가. `archive/tween-special-bind-key-reversed.md` 행의
경로도 `base/tween-plan.md`로 갱신.
- `.claude/question.md` — 트윈 요약 줄 경로를 `base/tween-plan.md`로 갱신.
- `CLAUDE.md` — "지금 할 일"/`research/` 목록에서 `tween-plan.md` 제거.
- 라이브 크로스레퍼런스(`research/tween-plan.md` → `base/tween-plan.md`)
일괄 갱신: `base/architecture.md`(2곳), `base/attribute-plan.md`,
`base/modifier-plan.md`(2곳), `base/bind-system-plan.md`(4곳),
`research/pre-implementation-audit.md`, `research/operator-sugar-plan.md`,
`research/documentation-content-map.md`,
`archive/tween-special-bind-key-reversed.md`. **`session/` 안의 과거
기록은 의도적으로 안 건드림** — 그 시점엔 실제로 `research/`였으므로
원문 그대로 정확함.
이걸로 Tween 관련 설계는 전부 확정 — `ROADMAP.md` M11 착수 시 `base/
tween-plan.md`가 유일한 소스.

View file

@ -42,13 +42,13 @@ modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션
base 문서가 근거로 인용하는 온디맨드 참고 자료(v1 내부 동작 스냅샷, base 문서가 근거로 인용하는 온디맨드 참고 자료(v1 내부 동작 스냅샷,
Fusion/Vide 비교 리서치) — 항상 읽을 필요는 없고 인용될 때만 열어볼 것. Fusion/Vide 비교 리서치) — 항상 읽을 필요는 없고 인용될 때만 열어볼 것.
- `.claude/research/` — 아직 착수 전, 사용자와 상의 필요한 설계 논의. - `.claude/research/` — 아직 착수 전, 사용자와 상의 필요한 설계 논의.
`tween-plan.md`/`existing-instance-bind-plan.md`/`debug-tooling-plan.md`/ `existing-instance-bind-plan.md`/`debug-tooling-plan.md`/
`documentation-plan.md`/`documentation-content-map.md`/ `documentation-plan.md`/`documentation-content-map.md`/
`framework-comparison-findings.md`/`additional-primitives-plan.md`(2026-08-09 `framework-comparison-findings.md`/`additional-primitives-plan.md`(2026-08-09
세 번째 세션에 마지막 열린 항목까지 전부 해소, 이제 배경 자료용)/ 세 번째 세션에 마지막 열린 항목까지 전부 해소, 이제 배경 자료용)/
`pre-implementation-audit.md`/`v1-compat-plan.md` `pre-implementation-audit.md`/`v1-compat-plan.md`
— 전부 후순위(`tween-plan.md`는 2026-08-12 세션에서 사실상 다 닫힘, 남은 — 전부 후순위(`tween-plan.md`는 2026-08-12 세션에 마지막 열린 항목까지
건 자연완료 북키핑 정도로 더 이상 급하지 않음). 최신 목록·우선순위는 전부 해소돼 `base/`로 승격, 더 이상 여기 없음). 최신 목록·우선순위는
`.claude/README.md`가 소스, 여기서 개수 반복 안 함(과거에 "두 개뿐"이라 `.claude/README.md`가 소스, 여기서 개수 반복 안 함(과거에 "두 개뿐"이라
적어놨다가 새 문서 추가될 때마다 안 갱신되는 패턴이 반복돼서 아예 안 적어놨다가 새 문서 추가될 때마다 안 갱신되는 패턴이 반복돼서 아예 안
세기로 함). 세기로 함).
@ -489,3 +489,13 @@ bind-system-plan.md`) `local addTax = Sum(a,b)`처럼 만든 값을 `:Compute`
`Relate`로 클로저의 operand 목록 추적) 아이디어도 나왔으나 실사용 `Relate`로 클로저의 operand 목록 추적) 아이디어도 나왔으나 실사용
사례 나오면 재검토로 보류. `base/architecture.md`의 stale `Animate` 사례 나오면 재검토로 보류. `base/architecture.md`의 stale `Animate`
2-인자 시그니처 코멘트도 이 김에 수정. 2-인자 시그니처 코멘트도 이 김에 수정.
**2026-08-12 여섯 번째 세션 — Tween 자연완료 북키핑 확정, `tween-plan.md`
`base/`로 승격** (`session/2026-08-12-06-tween-completed-bookkeeping-promoted.md`)
`tween-plan.md`의 마지막 열린 질문(자연완료 시 per-instance 북키핑 정리
여부)을 사용자가 확정 — 정리 안 해도 됨(자연완료는 유저가 원한 목표값에
도달한 상태라 남은 참조가 부작용 없음, `Value`가 항상 lerp 가능한
프리미티브라 메모리 문제도 없음, 별도 Completed 이벤트 정리 장치는
오버엔지니어링). 이걸로 열린 설계 질문이 없어져 `research/tween-plan.md`
`base/tween-plan.md`로 승격, 라이브 크로스레퍼런스 전부 갱신(session/
과거 기록은 원문 보존을 위해 그대로 둠).