From 31c55c625ede8738a1ece3906ead1b8bc8065fe6 Mon Sep 17 00:00:00 2001 From: qwreey Date: Fri, 28 Aug 2026 19:29:07 +0900 Subject: [PATCH] =?UTF-8?q?qa:=2011=EB=9D=BC=EC=9A=B4=EB=93=9C=20=ED=83=90?= =?UTF-8?q?=EC=82=AC=EC=9E=90=20=EA=B2=B0=EA=B3=BC=20=E2=80=94=20H-174(?= =?UTF-8?q?=F0=9F=94=B4=20=E2=91=A1=20=EC=83=9D=EB=AA=85=EC=A3=BC=EA=B8=B0?= =?UTF-8?q?=20=ED=95=84=EB=93=9C=20=EC=A1=B0=EB=A6=BD=20=ED=98=95=ED=83=9C?= =?UTF-8?q?=20=EB=AF=B8=EC=A0=95,=20=C2=A74)=20=EA=B8=B0=EB=A1=9D,=20H-175?= =?UTF-8?q?=20=ED=81=B4=EB=A1=9C=EC=A0=80=20=EC=BA=90=EC=8B=9C=20=EA=B7=9C?= =?UTF-8?q?=EC=B9=99=20=EB=B2=94=EC=9C=84=20=EC=A2=81=ED=9E=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: qwreey --- .../pre-implementation-handtrace-round11.md | 116 +++++++++++++++++- quad-base/test/spec.ref.luau | 7 +- 2 files changed, 117 insertions(+), 6 deletions(-) diff --git a/.claude/qa-request/pre-implementation-handtrace-round11.md b/.claude/qa-request/pre-implementation-handtrace-round11.md index b4a7cce..42582bc 100644 --- a/.claude/qa-request/pre-implementation-handtrace-round11.md +++ b/.claude/qa-request/pre-implementation-handtrace-round11.md @@ -23,6 +23,8 @@ | `H-171` | โ‘  | 1 | ๐ŸŸก | mock lazy claim: Destroy๋œ inst์— ๋‹ค์‹œ bindํ•˜๋ฉด GC ์ „์—” ์ฃฝ์€ gcconn ์žฌ์‚ฌ์šฉ, GC ๋’ค์—” ์ƒˆ Connected gcconn โ€” ๊ฒฐ๊ณผ๊ฐ€ GC ํƒ€์ด๋ฐ์— ๋”ฐ๋ผ ๊ฐˆ๋ฆผ | โœ… mock: ์ฃฝ์€ inst์˜ ์ƒˆ gcconn์€ ์ฆ‰์‹œ Disconnect(`spec.lifetime` 6b) | | `H-172` | โ‘  | 1 | ๐ŸŸก | mock `Destroy`๊ฐ€ ์ž์†์„ ์•ˆ ์ฃฝ์ด๊ณ (์กฐ์ƒ ํŒŒ๊ดด ๊ณ„์•ฝ ๊ฒ€์ฆ ๋ถˆ๊ฐ€), `Parent` ๋ณ€๊ฒฝ ์‹œ๊ทธ๋„์ด ์—ฐ๊ฒฐ ํ•ด์ œ ๋’ค๋ผ ๊ด€์ธก ๋ถˆ๊ฐ€, ์žฌ๊ท€ Destroy ๋ฌดํ•œ ๋ฃจํ”„ | โœ… mock: Destroying โ†’ Parent nil โ†’ ์ž์† Destroy โ†’ ์—ฐ๊ฒฐ ํ•ด์ œ, ์ด์ค‘ Destroy no-op(`spec.lifetime` 6c) | | `H-173` | โ‘  | 1 | ๐ŸŸข | `ROADMAP.md` M7 ์ฒดํฌ๋ฐ•์Šคยท`tween-plan.md` 352๊ฐ€ `isTween`/`TweenBrand`๋ฅผ `Tween.luau`์— ๋‘”๋‹ค๊ณ  ์•„์ง ์„œ์ˆ (๊ฐ์‚ฌ 3๋ผ์šด๋“œ๊ฐ€ ๋‘ ๊ณณ๋งŒ ๊ณ ์นจ) | โœ… ๋ฐ˜์˜ | +| `H-174` | **โ‘ก** | 1โ†’2 | ๐Ÿ”ด | ์ƒ๋ช…์ฃผ๊ธฐ 4์ข…์€ **`New()` ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ๋‹ค๋ฅธ ํ•„๋“œ**(์ด ๋‹จ์œ„๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ๋งŒ๋“ค์—ˆ๊ณ  `spec.lifetime` 8์ด ๊ณ ์ •)์ธ๋ฐ, ๋‹จ์œ„ 2ยท3์˜ `base/` ์˜์‚ฌ์ฝ”๋“œ(`Observer:_receive`์˜ `canExecute(self)`, `Subscribe` ๋„ท์˜ `canBound(self)`, `EffectHandle.rawRerun`)๋Š” **์ž์œ  ํ•จ์ˆ˜**๋กœ ๋ถ€๋ฅธ๋‹ค โ€” `Observer.luau`/`Source.luau`๊ฐ€ ์ž๊ธฐ ์ธ์Šคํ„ด์Šค์˜ ํ•„๋“œ์— ์–ด๋–ป๊ฒŒ ๋‹ฟ๋Š”์ง€ ์–ด๋А ๋ฌธ์„œ๋„ ์•ˆ ์ •ํ–ˆ๋‹ค. ๊ฒฐ์ • ์—†์ด๋Š” ๋‹จ์œ„ 2์˜ `_receive`๋ฅผ ์“ธ ์ˆ˜ ์—†๋‹ค | ยง4 ๋Œ€๊ธฐ | +| `H-175` | โ‘  | 1 | ๐ŸŸข | ยง5 "๋ถˆ๋ณ€ ์—…๋ฐธ๋ฅ˜๋งŒ ์žก๋Š” ํด๋กœ์ €๋Š” ํ”„๋กœํ† ์— ์บ์‹œ"๋Š” ๋ฒ”์œ„๊ฐ€ ๋„“๋‹ค โ€” ์‹ค์ œ ๊ทœ์น™์€ **์—…๋ฐธ๋ฅ˜๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ „๋ถ€ ํ†ฑ๋ ˆ๋ฒจ(ํ•จ์ˆ˜ ๊นŠ์ด 0) ๋ถˆ๋ณ€ ๋กœ์ปฌ**์ผ ๋•Œ๋งŒ(์ปดํŒŒ์ผ๋Ÿฌ `shouldShareClosure`). ํ•จ์ˆ˜ ์ธ์žยท์ง€์—ญ์„ ์žก๋Š” ํด๋กœ์ €(๋‹จ์œ„ 3 `Effect`์˜ ์ฝœ๋ฐฑ ๋ชจ์–‘)๋Š” ์ •์ƒ GC๋จ์„ ์‹ค์ธก | โœ… ยง5ยท`spec.ref` ์ฃผ์„ ์ขํž˜ | ## ์ƒ์„ธ @@ -106,6 +108,52 @@ - **์ฒ˜๋ฆฌ**: `ROADMAP.md` M7 ์ฒดํฌ๋ฐ•์Šค, `tween-plan.md` "base ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ ์•„๋‹˜" ๋ฌธ๋‹จ. +### ๋‹จ์œ„ 1 โ€” ํƒ์‚ฌ์ž (2026-08-28, ์ปค๋ฐ‹ `d9898d6`..`325f3f0`) + +### `H-174` ๐Ÿ”ด โ€” `canExecute`/`canBound`๋Š” ์ธ์Šคํ„ด์Šค ํ•„๋“œ์ธ๋ฐ ๋ฐ˜์‘ํ˜• ์˜์‚ฌ์ฝ”๋“œ๋Š” ์ž์œ  ํ•จ์ˆ˜๋กœ ๋ถ€๋ฅธ๋‹ค (โ‘ก) + +- **์–ด๋””์„œ**: `quad-base/src/LifetimeHandle.luau`(`Init(module)`์ด `module.bindLifetime = โ€ฆ` + ๋„ค ์Šฌ๋กฏ์„ **์ธ์Šคํ„ด์Šค๋งˆ๋‹ค** ์‹ฌ์Œ) + `quad-base/test/mock.luau` `installLifetime(quad)`(๊ทธ + `quad` ํ•˜๋‚˜๋งŒ ๋ฎ์–ด์”€) + `spec.lifetime.luau` 8("๋‹ค๋ฅธ `New()`์—” ์•ˆ ํผ์ง"์„ ๊ณ ์ •) โ€” + vs `base/source-state-plan.md` "์ „ํŒŒ ๋ฃจํ”„ โ€” ํ™•์ • ์˜์‚ฌ์ฝ”๋“œ"์˜ `Observer:_receive` + (`if canExecute(self) then`), `base/lifecycle-pattern.md` (2)์˜ `Observer:WeakSubscribe` + (`if not canBound(self) then`), `base/effect-plan.md`์˜ `rawRerun`(`canExecute(self)`)๊ณผ + `EffectHandle` ๋„ค ์ง„์ž…์ . +- **๋ฌด์—‡์ด**: ์ด ๋‹จ์œ„๊ฐ€ ํ™•์ •๋Œ€๋กœ ์˜ฎ๊ธด ๊ฒฐ๊ณผ ๋„ค ํ•จ์ˆ˜๋Š” **์ž์œ  ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ `quad` ์ธ์Šคํ„ด์Šค์˜ + ํ•„๋“œ**๋‹ค(`lifecycle-pattern.md` 186ํ–‰ *"ํ‰ํ‰ํ•œ์€ ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค์˜ ํ•„๋“œ๋ผ๋Š” ๋œป"*, `architecture.md` + 13๋ฒˆ *"๋ชจ๋“ˆ์ด ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค(โ€ฆ canExecute ๋“ฑ ๊ณ„์•ฝ ํ•„๋“œ ํ•˜๋‚˜)"*). ๊ทธ๋Ÿฐ๋ฐ ๋‹ค์Œ ๋‹จ์œ„๊ฐ€ + ์˜ฎ๊ธธ ์˜์‚ฌ์ฝ”๋“œ๋Š” ์ „๋ถ€ `canExecute(self)`์ฒ˜๋Ÿผ **์–ด๋А ์ธ์Šคํ„ด์Šค์ธ์ง€ ๋งํ•˜์ง€ ์•Š๊ณ ** ๋ถ€๋ฅธ๋‹ค. + `Ref.luau`์ฒ˜๋Ÿผ `Source.luau`/`State.luau`/`Observer.luau`๋ฅผ ์ธ์Šคํ„ด์Šค ๊ฐ„ ๊ณต์œ ๋˜๋Š” ์žŽ + ๋ชจ๋“ˆ๋กœ ์“ฐ๋ฉด(`spec.init` 27ํ–‰์ด `Ref`/`Void`/`Relate`์— ๋Œ€ํ•ด ๊ณ ์ •ํ•œ ๋ชจ์–‘) ๋ฐœํ™” ์‹œ **์–ด๋А + `quad`์˜ `canExecute`๋ฅผ ๋ถ€๋ฅผ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค** โ€” ๋ฐฑ์—”๋“œ๊ฐ€ ๋‘˜์ด๋ฉด(mock + roblox, `New()`์˜ + ์กด์žฌ ์ด์œ ) ์ž˜๋ชป๋œ ์ธ์Šคํ„ด์Šค์˜ ๊ฒŒ์ดํŠธ๋ฅผ ํƒ€๊ฑฐ๋‚˜, ์•„์ง ์Šคํ…์ธ ์ธ์Šคํ„ด์Šค์—์„œ `error`๊ฐ€ ๋‚œ๋‹ค. + ์ฝ”ํผ์Šค๋ฅผ grepํ•ด๋„(`InitSource`/`InitState`/`InitObserver`/`_quad`/`_module`) ๋ฐ˜์‘ํ˜• ๋ชจ๋“ˆ์˜ + ์กฐ๋ฆฝ ํ˜•ํƒœ๋ฅผ ์ •ํ•œ ๋ฌธ์žฅ์ด ์—†๋‹ค โ€” `module-lifecycle-plan.md` "New()์˜ ๋‚ด๋ถ€ ๊ตฌ์„ฑ"์ด ์ •ํ•œ ๊ฑด + `InitDispatch(module)` ํ•˜๋‚˜์˜ ์˜ˆ์‹œ๋ฟ์ด๊ณ , `ROADMAP.md` "๋ฐ˜์‘ํ˜• ๋ณธ์ฒด" ์ฒดํฌ๋ฐ•์Šค๋„ ์นจ๋ฌตํ•œ๋‹ค. +- **๊ฐ™์ด ๊ฑธ๋ฆฌ๋Š” ํ•˜์œ„ ํ•จ์ •(๊ฒฐ์ •๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ฐธ)**: ๋ฐฑ์—”๋“œ๋Š” `New()`๊ฐ€ **๋๋‚œ ๋’ค** ํ•„๋“œ๋ฅผ + ๋ฎ์–ด์“ด๋‹ค(mock๋„ ๊ฐ™์€ ์ˆœ์„œ). ๊ทธ๋ž˜์„œ ๋ฐ˜์‘ํ˜• ๋ชจ๋“ˆ์ด `Init` ์‹œ์ ์— `local canExecute = + module.canExecute`๋กœ **์Šคํ…์„ ์บก์ฒ˜ํ•˜๋ฉด ์˜์›ํžˆ ์Šคํ…**์ด๋‹ค โ€” ๋ฐœํ™” ์‹œ์ ๋งˆ๋‹ค + `module.canExecute(self)`๋กœ **๋Šฆ๊ฒŒ ์ฝ์–ด์•ผ** ํ•œ๋‹ค. `spec.lifetime` 8์€ `quad.bindLifetime == + before`(์žฌ์„ค์น˜ ๋ฌด์‹œ)๋งŒ ๋ณด๊ณ  ์ด ์ˆœ์„œ๋Š” ์•ˆ ๋ณธ๋‹ค. +- **๋ฌธ์„œ๊ฐ€ ๋‹ต์„ ๊ฐ–๊ณ  ์žˆ๋‚˜**: ์•„๋‹ˆ๋‹ค. `architecture.md` 13๋ฒˆ์˜ *"module-level state๋ฅผ + ์ฐธ์กฐํ•˜๋Š” ์ฝ”๋“œ๋“ค์ด ๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋„๋ก ์†์„ ๋Œ€์•ผ ํ•œ๋‹ค โ€” `InitModule(module)` + ๋“ฑ"*์ด ๋ฐฉํ–ฅ๋งŒ ์ค€๋‹ค. ์–ด๋А ๋ชจ์–‘์ด๋“  **์ƒˆ ์กฐ๋ฆฝ ๋ฉ”์ปค๋‹ˆ์ฆ˜**์ด๋ผ ยง4. +- **๊ฐˆ๋ž˜**: ยง4. ๋‹จ์œ„ 1 ์ฝ”๋“œ๋Š” ์–ด๋А ์„ ํƒ์ง€์—์„œ๋„ ๊ทธ๋Œ€๋กœ๋‹ค(โ‘ข ์•„๋‹˜). + +### `H-175` ๐ŸŸข โ€” ํด๋กœ์ € ์บ์‹œ ๊ทœ์น™์˜ ๋ฒ”์œ„ (โ‘ ) + +- **์–ด๋””์„œ**: ์ด ํŒŒ์ผ ยง5 "ํˆด๋ง ์‚ฌ์‹ค ๋‘˜"์˜ ๋‘˜์งธ ํ•ญ, `spec.ref.luau` 7๋ฒˆ ์ฃผ์„. +- **๋ฌด์—‡์ด**: *"๋ถˆ๋ณ€ ์—…๋ฐธ๋ฅ˜๋งŒ ์žก๋Š” ํด๋กœ์ €๋Š” ํ”„๋กœํ† ์— ์บ์‹œ๋ผ ์˜์˜ GC๋˜์ง€ ์•Š๋Š”๋‹ค"*๋Š” ๋ฒ”์œ„๊ฐ€ + ๋„“๋‹ค. Luau ์ปดํŒŒ์ผ๋Ÿฌ `shouldShareClosure`์˜ ์‹ค์ œ ์กฐ๊ฑด์€ **์—…๋ฐธ๋ฅ˜๊ฐ€ ์—†๊ฑฐ๋‚˜, ์ „๋ถ€ + `functionDepth == 0`(ํ†ฑ๋ ˆ๋ฒจ) ๋ถˆ๋ณ€ ๋กœ์ปฌ**์ผ ๋•Œ๋ฟ์ด๋‹ค โ€” ํ•จ์ˆ˜ ์•ˆ์˜ ์ง€์—ญ/์ธ์ž๋ฅผ ์žก๋Š” ํด๋กœ์ €๋Š” + ๋ถˆ๋ณ€์ด์–ด๋„ ๊ณต์œ ๋˜์ง€ ์•Š๋Š”๋‹ค(์ปดํŒŒ์ผ๋Ÿฌ ์ฃผ์„: ๊ณต์œ ํ•˜๋ฉด *"์ž„์‹œ ๊ฐ์ฒด๊ฐ€ ์˜๊ตฌ๊ฐ€ ๋œ๋‹ค"*๋ผ + ํœด๋ฆฌ์Šคํ‹ฑ์œผ๋กœ ์ขํ˜€๋‘ ). ์‹ค์ธก(์Šคํฌ๋ž˜์น˜, `luau`): `mk(handle)`๊ฐ€ ๋Œ๋ ค์ค€ ํด๋กœ์ €๋Š” GC๋จ, + ์—…๋ฐธ๋ฅ˜ ์—†๋Š” ํด๋กœ์ €๋Š” GC ๋’ค์—๋„ ์‚ด์•„๋‚จ์Œ(์ƒ์กด 1/2). ๋‹จ์œ„ 3 `Effect`๊ฐ€ `handle`์„ ์žก๊ณ  + `ref:WeakCallback(cb)`๋กœ ๊ฑฐ๋Š” ๋ชจ์–‘์„ ๊ทธ๋Œ€๋กœ ํ‰๋‚ด๋‚ด๋ฉด `WeakCallbacks` ํ•ญ๋ชฉ์ด 0์œผ๋กœ + ์‚ฌ๋ผ์ง„๋‹ค โ€” ์ฆ‰ ์ง€๊ธˆ ๋ฌธ์žฅ๋Œ€๋กœ๋ฉด ๋‹จ์œ„ 3 GC ํ…Œ์ŠคํŠธ๊ฐ€ ์ž˜๋ชป ๊ฒฝ๋ณด๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค. +- **์ฒ˜๋ฆฌ**: ๋ฏธ๋ฐ˜์˜(ํƒ์‚ฌ์ž๋Š” ๊ณ ์น˜์ง€ ์•Š์Œ). ยง5 ๋ฌธ์žฅ์„ *"์—…๋ฐธ๋ฅ˜๊ฐ€ ์—†๊ฑฐ๋‚˜ ํ†ฑ๋ ˆ๋ฒจ ๋ถˆ๋ณ€ ์—…๋ฐธ๋ฅ˜๋งŒ + ์žก๋Š” ํด๋กœ์ €"*๋กœ ์ขํžˆ๋ฉด ๋œ๋‹ค. + ## ยง4 โญ ์‚ฌ์šฉ์ž ๊ฒฐ์ •์ด ํ•„์š”ํ•œ ๊ฒƒ (๋ฐฐ์น˜ ํšŒ์‹ ์šฉ) | ๋ฌธํ•ญ | ๋ฌด์—‡ | ์„ ํƒ์ง€ | ๊ถŒ๊ณ  | ๊ถŒ๊ณ  ๊ทผ๊ฑฐ | ์˜› ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋ณต์›? | @@ -113,6 +161,7 @@ | **`H-168`** | `Ref(T)` vs ๋ฌด์ธ์ž `Ref()` ๊ด€์šฉ๊ตฌ | (a) ์‹œ๊ทธ๋‹ˆ์ฒ˜ ์œ ์ง€, ๋ฌธ์„œ์˜ ๋นˆ ํ˜ธ์ถœ ๊ด€์šฉ๊ตฌ๋ฅผ ์ „๋ถ€ `Ref<>()`(nil-able ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ƒ๋žต ๊ฐ€๋Šฅ)๋กœ ๊ณ ์ณ ์”€ / (b) `default: T?`, `.Value: T?`(H-167 ์ด์ „ ๋ชจ์–‘ โ€” `Ref(5).Value`๊นŒ์ง€ nil ๊ฒ€์‚ฌ ๊ฐ•์š”) / (c) ๋‘ ์˜ค๋ฒ„๋กœ๋“œ `Ref(T)` โˆช `Ref() -> Ref` | **(a)** | "์ œ๋„ค๋ฆญ ์‹œ๊ทธ๋‹ˆ์ฒ˜" ํ™•์ •(๋‹จ์ผ ํŒŒ๋ผ๋ฏธํ„ฐ, ๋ช…์‹œ ํ™•์žฅ์œผ๋กœ ๋„“ํž˜)์„ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ๊ด€์šฉ๊ตฌ๋งŒ ๊ทธ ๊ทœ์น™์— ๋งž์ถ”๋Š” ๊ฒƒ โ€” (b)๋Š” ๋ฌธ์„œ๊ฐ€ ๊ธฐ๊ฐํ•œ ๋ชจ์–‘, (c)๋Š” ๊ทธ ์ ˆ์ด ๊ธฐ๊ฐํ•œ 2-ํŒŒ๋ผ๋ฏธํ„ฐ ์†”๋ฒ„ ๋ฌธ์ œ์˜ ์žฌ๊ฐœ๋ฐฉ | (b)๊ฐ€ ๊ทธ๋ ‡๋‹ค | | **`H-169`** | ์žฌ์ง„์ž… `:Set` ๋’ค ๋‚จ์€ ์ฝœ๋ฐฑ์˜ ์ธ์ž | (a) ๋ธ”๋ก์„ `k(self.Value, self)`๋กœ(ํ•ญ์ƒ ์ตœ์‹  ๊ฐ’, ๋ฌธ์„œ ๋ถˆ๋ณ€์‹ ๊ทธ๋Œ€๋กœ) / (b) ๋ฌธ์„œ์— "์žฌ์ง„์ž… ์‹œ ๋ฐ”๊นฅ ํŒŒ๋™์˜ ๋‚จ์€ ์ฝœ๋ฐฑ์€ ์ž๊ธฐ ํŒŒ๋™์˜ ๊ฐ’์„ ๋ฐ›๋Š”๋‹ค"๋กœ ๊ณ„์•ฝํ™”(์ฝ”๋“œ ์œ ์ง€) / (c) ์žฌ์ง„์ž… ์ž์ฒด๋ฅผ ๊ธˆ์ง€(error) | **(a)** | ๋ฌธ์„œ ๋ถˆ๋ณ€์‹(*"์˜› ๊ฐ’์ด ๋ณด์ด๋Š” ์ฐฝ์ด ์—†๋‹ค"*)์ด ์ด๋ฏธ (a)๋ฅผ ๋งํ•˜๊ณ  ์žˆ๊ณ  ํ•œ ํ† ํฐ ์ฐจ์ด โ€” (b)๋Š” ์ธ์ž์™€ `.Value`๊ฐ€ ๋‹ค๋ฅธ ์ฐฝ์„ ๊ณ„์•ฝ์œผ๋กœ ์—ด๊ณ , (c)๋Š” ์ƒˆ ๊ฐ€๋“œ | ์•„๋‹ˆ์˜ค | | **`H-170`** | resume์ด ์‚ผํ‚ค๋Š” ์—๋Ÿฌ | (a) `local ok, err = coroutine.resume(k, self); if not ok then error(err, 0) end` โ€” ๋Œ€๊ธฐ์ž ์—๋Ÿฌ๋ฅผ `:Set` ํ˜ธ์ถœ๋ถ€๋กœ ๋‹ค์‹œ ์˜ฌ๋ฆผ / (b) UB๋กœ ๋ฌธ์„œํ™”(๋Œ€๊ธฐ์ž ์—๋Ÿฌ๋Š” ์‚ฌ๋ผ์ง„๋‹ค) / (c) ๋Œ€๊ธฐ์ž ์†Œ์ง„์„ `task.spawn`๋ฅ˜ ์ฃผ์ž… op๋กœ(Roblox `task.spawn`์€ ์—๋Ÿฌ๋ฅผ ์ฝ˜์†”๋กœ ๋ณด๋ƒ„) | **(a)** | `architecture.md` "์˜ˆ์™ธ ์•ˆ์ „์„ฑ ๊ณ„์•ฝ"(๊ฐ์‹ธ์ง€ ์•Š๋Š”๋‹ค = ์—๋Ÿฌ๋Š” ์ „ํŒŒ)๊ณผ ๊ฐ™์€ ๊ฒฐ. ๋‹ค๋งŒ **์ƒˆ ์ฝ”๋“œ ๋‘ ์ค„(re-raise)** ์ด๋ผ ์‚ฌ์šฉ์ž ๊ฒฐ์ • ์ž๋ฆฌ. (c)๋Š” ์ƒˆ ์ฃผ์ž… op | ์•„๋‹ˆ์˜ค | +| **`H-174`** (ํƒ์‚ฌ์ž, **๋‹จ์œ„ 2 ์ฐฉ์ˆ˜ ์ „ ํ•„์š”**) | ๋ฐ˜์‘ํ˜• ๋ชจ๋“ˆ์ด ์ž๊ธฐ `quad` ์ธ์Šคํ„ด์Šค์˜ `canExecute`/`canBound`์— ๋‹ฟ๋Š” ๋ฒ• | (a) `Source.luau`/`State.luau`/`Observer.luau`/`Effect.luau`๋ฅผ `InitSource(module)`๋ฅ˜ **ํŒฉํ† ๋ฆฌ**๋กœ โ€” ํด๋ž˜์Šค์™€ `Subscribed`/`WeakSubscribed` ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ `module`์„ ๋‹ซ์€ ํด๋กœ์ € ์•ˆ์—์„œ ๋งŒ๋“ค๊ณ  `module.Source = โ€ฆ`๋กœ ์‹ฌ์Œ(`InitDispatch`์™€ ๊ฐ™์€ ๋ชจ์–‘, `EpochMap`/`Brand`/`Ref`๋Š” ๊ทธ๋Œ€๋กœ ์žŽ). ๊ณต๊ฐœ ํ•„๋“œ๊ฐ€ ์—†๋Š” `State`/`Observer` ํด๋ž˜์Šค๋Š” `Init`์˜ ๋ฐ˜ํ™˜๊ฐ’์ด๋‚˜ `module.RunInit` ๋’ค์˜ ๋น„๊ณต๊ฐœ ํ•„๋“œ๋กœ ํ˜•์ œ `Init`์— ๋„˜๊น€ / (b) ์žŽ ๋ชจ๋“ˆ ์œ ์ง€ + ๊ฐ’๋งˆ๋‹ค ์—ญ์ฐธ์กฐ ํ•„๋“œ(`observer._quad`)๋ฅผ ๋‘๊ณ  `self._quad.canExecute(self)` / (c) ์žŽ ๋ชจ๋“ˆ ์œ ์ง€ + ๋ชจ๋“ˆ ๋กœ์ปฌ ์Šฌ๋กฏ ํ•˜๋‚˜๋ฅผ ๋ฐฑ์—”๋“œ๊ฐ€ ์ฑ„์›€(์ธ์Šคํ„ด์Šค ๊ฒฉ๋ฆฌ ํฌ๊ธฐ) | **(a)** | `architecture.md` 13๋ฒˆ(*"๋ชจ๋“ˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋„๋ก"*)๊ณผ `module-lifecycle-plan.md` "New()์˜ ๋‚ด๋ถ€ ๊ตฌ์„ฑ"์ด ์ด๋ฏธ ์ด ๋ชจ์–‘์ด๊ณ , `Observer`์˜ ๋‘ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๊ฐ€ ์ธ์Šคํ„ด์Šค๋ณ„์ด ๋˜์–ด *"์™„์ „ํžˆ ๋ณ„๋„์˜ ์ƒˆ Quad ๋„ค์ž„์ŠคํŽ˜์ด์Šค"*์™€ ๋งž์Œ. (b)๋Š” ์ƒˆ ํ•„๋“œ + ๊ฐ’์ด ์ž๊ธฐ ๋ชจ๋“ˆ์„ ๊ฐ•์ฐธ์กฐ(`Relate` ๋˜์ฐธ์กฐ ๊ณ„์—ด ์œ„ํ—˜), (c)๋Š” `spec.lifetime` 8ยท`New()`์˜ ์กด์žฌ ์ด์œ ์™€ ์ถฉ๋Œ. ์–ด๋А ์ชฝ์ด๋“  **ํ•„๋“œ๋Š” ๋ฐœํ™” ์‹œ์ ์— ๋Šฆ๊ฒŒ ์ฝ๋Š”๋‹ค**(์ƒ์„ธ ์ ˆ์˜ ํ•˜์œ„ ํ•จ์ •) | ์•„๋‹ˆ์˜ค | ์ฝ”๋“œ ์ชฝ ์ž”์—ฌ ๋งˆ์ปค: `grep -rn "TODO(H-" quad-base/src` โ€” ์ด ํ‘œ์˜ ๋ฌธํ•ญ๊ณผ 1:1์ด์–ด์•ผ ํ•œ๋‹ค. **[2026-08-28 ๊ธฐ์ค€] ๋งˆ์ปค 0๊ฐœ** โ€” ์œ„ ์…‹์€ ๋‹จ์œ„ 1 ๋ชจ๋“ˆ์„ ๋ง‰์ง€ ์•Š์•„ ์ฝ”๋“œ๋Š” ๋ฌธ์„œ @@ -138,9 +187,53 @@ - `require("@self/X")`๋Š” **`init.luau`์—์„œ๋งŒ** ํ†ตํ•œ๋‹ค โ€” ์ผ๋ฐ˜ ํŒŒ์ผ์—์„œ `@self`๋Š” ๊ทธ ํŒŒ์ผ ์ž์‹ ์ด๋ผ `could not resolve child component`. ํ˜•์ œ ๋ชจ๋“ˆ์€ `./X`, ํŒจํ‚ค์ง€๋Š” `../roblox_packages/...`. - GC ํ…Œ์ŠคํŠธ ํ•จ์ • ๋‘˜: ๊ฐ™์€ ํ”„๋ ˆ์ž„์˜ ์ฃฝ์€ ๋ ˆ์ง€์Šคํ„ฐ๊ฐ€ ์ž„์‹œ๊ฐ’์„ ๋ถ™์žก๋Š”๋‹ค(๋ณ„๋„ ํ•จ์ˆ˜ ์•ˆ์—์„œ - ๋งŒ๋“ค ๊ฒƒ) / **๋ถˆ๋ณ€ ์—…๋ฐธ๋ฅ˜๋งŒ ์žก๋Š” ํด๋กœ์ €๋Š” Luau๊ฐ€ ํ”„๋กœํ† ์— ์บ์‹œํ•ด ์˜์˜ GC๋˜์ง€ ์•Š๋Š”๋‹ค** - (ํ…Œ์ŠคํŠธ ํด๋กœ์ €๊ฐ€ ์—…๋ฐธ๋ฅ˜๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๊ฒŒ ํ•  ๊ฒƒ โ€” `lifecycle-pattern.md` (0)์˜ - `false or` ํŠธ๋ฆญ์ด ๋ง‰๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ตœ์ ํ™”). + ๋งŒ๋“ค ๊ฒƒ) / **์—…๋ฐธ๋ฅ˜๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ „๋ถ€ ํ†ฑ๋ ˆ๋ฒจ(ํ•จ์ˆ˜ ๊นŠ์ด 0) ๋ถˆ๋ณ€ ๋กœ์ปฌ์ธ ํด๋กœ์ €๋Š” Luau๊ฐ€ + ํ”„๋กœํ† ์— ์บ์‹œํ•ด ์˜์˜ GC๋˜์ง€ ์•Š๋Š”๋‹ค**(**[`H-175` ์ •์ •]** ํ•จ์ˆ˜ ์ธ์žยท์ง€์—ญ์„ ์žก๋Š” ํด๋กœ์ €๋Š” + ์ •์ƒ GC๋จ โ€” ํ…Œ์ŠคํŠธ์˜ ํƒ‘๋ ˆ๋ฒจ ํด๋กœ์ €๋Š” ์—…๋ฐธ๋ฅ˜๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๊ฒŒ ํ•  ๊ฒƒ, + `lifecycle-pattern.md` (0)์˜ `false or` ํŠธ๋ฆญ์ด ๋ง‰๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ตœ์ ํ™”). + +**๋‹จ์œ„ 1 (ํƒ์‚ฌ์ž, 2026-08-28)** โ€” ์ปค๋ฐ‹ `d9898d6`..`325f3f0`, ์‹ ์„ ํ•œ ์ปจํ…์ŠคํŠธ, `git stash` ์•ˆ ์”€: +- **์‹คํ–‰**: `./scripts/test.sh` ์ „์ฒด โ€” relink 30 ๊ฐฑ์‹ , `luau-analyze quad-base/src + spec.* + + mock.luau` ์ง„๋‹จ 0, 9ํŒŒ์ผ ์ „๋ถ€ `ALL PASS`. `grep -rn "TODO(H-" quad-base/src` 0๊ฑด(ยง4 ํ‘œ์™€ + 1:1 โ€” ํ‘œ์˜ ๋„ท์€ ์ „๋ถ€ ์ฝ”๋“œ ๋ฐ– ๋ฌธํ•ญ). +- **ํ•œ ์ค„ ๋Œ€์กฐ(์ฝ”๋“œ โ†” `base/` ์ ˆ), ์–ด๊ธ‹๋‚œ ๊ณณ ์—†์Œ**: `Brand.luau` โ†” `brand-plan.md` "๊ตฌํ˜„ โ€” + ์ธ์Šคํ„ด์Šค ๋ธŒ๋žœ๋“œ"/"`isX` wrapper"(์ƒ์„ฑ์žยท15 ์ธ์Šคํ„ด์Šคยท11 ์ˆ ์–ดยทํ•ฉ์„ฑ ๋ฐฉํ–ฅยท์†Œ๋ฌธ์ž ๋ฉ”์†Œ๋“œยท`None` + ๋ฌด์˜์กด) / `Relate.luau` โ†” "API (ํ™•์ •)"/"์‹ค์ œ ๊ตฌ์กฐ (ํ™•์ •, 2026-08-08 ์„ธ์…˜)"(๋ฒ”์œ„ ์•ˆ diff๋Š” + ํƒ€์ž… ์žฌexport๋ฟ, ๋ณธ๋ฌธ ๋ฌด๋ณ€๊ฒฝ ํ™•์ธ) / `LifetimeHandle.luau` โ†” `lifecycle-pattern.md` "ํƒ‘๋ ˆ๋ฒจ + ํ‰๋ฒ”ํ•œ ํ•จ์ˆ˜๋กœ ํ™•์ •"์˜ 2026-08-28 ์ •์ • + `architecture.md` error ๊ณ„์•ฝ(์˜์–ด, `level 2`, ์Šคํ…์€ + ์กฐ์šฉํ•œ no-op ์•„๋‹˜) / `Ref.luau` โ†” `ref-plan.md` "`:Set(value)`์˜ ์ˆœ์„œ" ๋ธ”๋ก(ํ† ํฐ ๋‹จ์œ„ ๋™์ผ โ€” + `H-169`/`H-170`์€ ๋ธ”๋ก ์ž์ฒด์˜ ๋ฌธ์ œ), "API ๋ชจ์–‘"(self ๋ฐ˜ํ™˜, ๋“ฑ๋ก ์ฆ‰์‹œ 1ํšŒ, `fn(value, ref)`), + "`.Callbacks`๋Š” ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋ผ", "`:WeakCallback(fn)`"(weak-key ๋ณ„๋„ ํ…Œ์ด๋ธ”, `Uncallback`์€ + ์–‘์ชฝ), "`Ref`๋Š” `Epoch`๋ฅผ ๋งŒ์กฑํ•œ๋‹ค"(`Revision` ๊ณต๊ฐœ, `EpochBrand` ๋‹ค์ค‘ ํƒœ๊น…), + `state-epoch-plan.md` ยง2(`bit32.bnot(-rev)`) / `mock.luau` `installLifetime` โ†” (0)/(1)/(2) + ์Šค์ผ€์น˜(`isBoundAlive` ๋‘ ๊ฒฝ๋กœ, ๊ฒŒ์ดํŠธ ๋ชจ์–‘, `gchold[value]`, `BindData` ๋‘˜ ๋‹ค weak, Observer + `_catchUp`/Effect `_bindDestroying`ยท`_unbindDestroying`, `unbindLifetime`์ด cleanupยท์ฝœ๋ฐฑ์„ ์•ˆ + ๋—Œ) โ€” mock๋งŒ์˜ ์ถ”๊ฐ€๋Š” `isMockInstance` ๊ฒ€์‚ฌ์™€ `H-171` ๋ถ„๊ธฐ๋ฟ / `init.luau`ยท`quad-types` + `Quad` โ†” brief ยง6 ํ‘œ(์žฌexport ๋ชฉ๋กยท์ˆ ์–ด 11๊ฐœ ์ด๋ฆ„ ์ผ์น˜). +- **๋‹ค์Œ ๋‹จ์œ„๊ฐ€ ์“ธ ํ‘œ๋ฉด, ํƒ€์ž… ๋ ˆ๋ฒจ ์‹ค์ธก(`luau-analyze`, strict, ์ง„๋‹จ 0)**: `Ref`๊ฐ€ + `QuadTypes.Epoch`์— ๊ทธ๋Œ€๋กœ ๋“ค์–ด๊ฐ(`sync(e: Epoch)`์— `Ref(5)`), `Ref` โ†’ `Ref` + ์ธ์ž ์ „๋‹ฌ OK(`Effect(fn, ...deps)`์˜ dep ํ•ฉ์ง‘ํ•ฉ์— ํ•„์š”), `{ [Epoch]: number }` weak-key ๋งต์— + `Ref`๋ฅผ ํ‚ค๋กœ OK(`EpochMap` ๋‚ด๋ถ€ ๋ชจ์–‘), `Epoch | Ref` ํ•ฉ์ง‘ํ•ฉ OK, ์ฝœ๋ฐฑ ์ธ์ž ์ƒ๋žต + (`function(v)`/`function()`) OK, ๋‘ ๋ฒˆ์งธ ์ธ์ž๋ฅผ `Epoch`๋กœ ๋„˜๊ธฐ๊ธฐ OK. **`H-168`์˜ ์ „์ œ์™€ + (a) ๋‘˜ ๋‹ค ์‹ค์ธก**: `Quad.Ref()`๋Š” *"Function expects 1 argument"*, `Quad.Ref<>()`๋Š” + **์ธ์ž ์—†์ด๋„ ์ง„๋‹จ 0**์ด๊ณ  `.Value: number?` โ€” ๊ถŒ๊ณ  (a)์˜ ๊ด€์šฉ๊ตฌ๊ฐ€ ์‹ค์ œ๋กœ ์„ฑ๋ฆฝํ•œ๋‹ค. +- **๋Ÿฐํƒ€์ž„ ์‹ค์ธก(์Šคํฌ๋ž˜์น˜, ์ธ๋ผ์ธ)**: mock์˜ `.Subscribed` ๊ฒฝ๋กœ๋Š” ์ง€๊ธˆ ์ด๋ฏธ ๋ˆ๋‹ค(`ObserverBrand` + ๋“ฑ๋ก + `Subscribed = true` โ†’ `canExecute` true/`canBound` false, `bindLifetime` โ†’ *"already + subscribed"*) / `ObserverBrand` ๋“ฑ๋ก๊ฐ’์„ `_catchUp` ์—†์ด ๋ฐ”์ธ๋“œํ•˜๋ฉด `attempt to call missing + method '_catchUp'` โ€” ๋‹จ์œ„ 2์˜ `Observer`๊ฐ€ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ฐ–๋Š”๋‹ค๋Š” ๋œป(`EffectBrand`๋Š” + `_bindDestroying`/`_unbindDestroying`, ๋‹จ์œ„ 3) / `Ref`๋ฅผ `bindLifetime`์˜ value๋กœ โ€” ์ •์ƒ(๋ฐ”์ธ๋“œ + ํ›„ `canExecute` true, `Destroy` ํ›„ false) / `Effect` ๋ชจ์–‘(`handle`์„ ์žก๋Š” ํด๋กœ์ €๋ฅผ + `WeakCallback`)์˜ ํ•ญ๋ชฉ์€ `handle`์„ ๋†“์œผ๋ฉด GC ๋’ค 0๊ฐœ(`H-175`) / thread ํ‚ค๋ฅผ **์–‘์ชฝ** ํ…Œ์ด๋ธ”์— + ๋„ฃ์œผ๋ฉด ์ฒซ `:Set`์ด `.Callbacks`๋งŒ ๋น„์šฐ๊ณ  ๋‘˜์งธ `:Set`์ด ์ฃฝ์€ ์ฝ”๋ฃจํ‹ด์„ **์กฐ์šฉํžˆ** resume โ€” + `ref-plan.md`๊ฐ€ ์ ์€ ๋ถˆ๋ณ€์‹(*"๋Œ€๊ธฐ์ž๋Š” `.Callbacks`์—๋งŒ"*)์€ ๊ฐ€๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ด€๋ก€์ด๊ณ  M8 + `:Wait`๊ฐ€ ์œ ์ผํ•œ ์“ฐ๊ธฐ ์ง€์ ์ด๋ฏ€๋กœ ์ง€๊ธˆ์€ ๋ฌธ์ œ ์•„๋‹˜. +- **mock์˜ ์ธ์Šคํ„ด์Šค ๋ถˆ๋ฉธ์„ฑ(ํˆด๋ง ์‚ฌ์‹ค)**: `claim`๋œ mock ์ธ์Šคํ„ด์Šค๋Š” ์ฐธ์กฐ๋ฅผ ๋†“์•„๋„ `Destroy` + ์ „์—” GC๋˜์ง€ ์•Š๋Š”๋‹ค(์‹ค์ธก: inst๋ฅผ ๋–จ์–ด๋œจ๋ฆฌ๊ณ  GC 2ํšŒ ๋’ค์—๋„ ๋ฌถ์ธ ๊ฐ’ ์ƒ์กด). ์ด์œ ๋Š” ์˜๋„๊ฐ€ + ์•„๋‹ˆ๋ผ **`dataOf`๊ฐ€ weak-keyยท๊ฐ•ํ•œ ๊ฐ’(Luau์—” ephemeron ์—†์Œ)**์ด๋ผ `data โ†’ changed ์‹œ๊ทธ๋„ โ†’ + gcconn ํด๋กœ์ € โ†’ inst`๋กœ ํ‚ค๊ฐ€ ์ž๊ธฐ ๊ฐ’์„ ํ†ตํ•ด ์‚ด์•„๋‚จ๊ธฐ ๋•Œ๋ฌธ. ๊ฒฐ๊ณผ์ ์œผ๋กœ `lifecycle-pattern.md` + (0)์˜ *"quad๊ฐ€ ๋งŒ๋“  Instance๋Š” โ€ฆ ๋ฐ˜๋“œ์‹œ `Destroy`๋กœ ํšŒ์ˆ˜๋œ๋‹ค"*์™€ ๊ฐ™์€ ๊ด€์ธก์„ ์ฃผ์ง€๋งŒ ๊ทผ๊ฑฐ๊ฐ€ + ๋‹ค๋ฅด๋‹ค โ€” ๋‹ค์Œ ๋‹จ์œ„ GC ํ…Œ์ŠคํŠธ๋Š” ๋งŒ๋“  ์ธ์Šคํ„ด์Šค๋ฅผ **๋ฐ˜๋“œ์‹œ `Destroy`**ํ•  ๊ฒƒ(์•ˆ ํ•˜๋ฉด ๊ทธ + ์ธ์Šคํ„ด์Šค์— ๋ฌถ์ธ ๊ฐ’ ์ „๋ถ€๊ฐ€ ๋’ค ํ…Œ์ŠคํŠธ์˜ GC ๋‹จ์–ธ์— ๋‚จ๋Š”๋‹ค). **๋‹จ์œ„ 1 ๋ ์ ˆ์ฐจ ๊ธฐ๋ก**: ๊ฐ์‚ฌ ๋ฃจํ”„ 8๋ผ์šด๋“œ(๋ฐœ๊ฒฌ 3โ†’4โ†’1โ†’2โ†’4โ†’4โ†’1โ†’0, 5ยท6๋ผ์šด๋“œ ์ ˆ๋ฐ˜์€ ๊ฐ๋„๋ฅผ ๋„“ํ˜€ ์žกํžŒ ์˜› ๊ฐ™์€-ํŒŒ์ผ ์ ˆ ์ธ์šฉ ๋ถ€์ฑ„) โ†’ `/code-review high` 1ํšŒ 10๊ฑด: โ‘ก ์…‹(`H-168`~ @@ -150,3 +243,20 @@ (0)/(1) ๊ทธ๋Œ€๋กœ์ด๊ฑฐ๋‚˜ `claim-plan.md` ยง7-9๊ฐ€ ์ด๋ฏธ ๊ธฐ๊ฐํ•œ ๋ชจ์–‘). ## ยง6 ๋‚จ์€ ์˜์‹ฌ / ๋ชป ๋ณธ ๊ฒƒ + +**๋‹จ์œ„ 1 (ํƒ์‚ฌ์ž, 2026-08-28)**: +- **`H-174`์˜ ๊ฒฐ์ •์ด `EpochMap`์—” ์•ˆ ๊ฑธ๋ฆฌ์ง€๋งŒ `GateNode`/`Blocker`(๋‹จ์œ„ 4)์—” ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋‹ค** โ€” + `GateNode`๋Š” State ๋…ธ๋“œ๋ผ `canExecute`๋ฅผ ์•ˆ ๋ณด์ง€๋งŒ(`H-56`), `Blocker`๊ฐ€ Observer/Effect์˜ + ๊ตฌ๋… ํ‘œ๋ฉด์„ ๋งŒ์ง€๋ฉด ๊ฐ™์€ ์ธ์Šคํ„ด์Šค ๋ฌธ์ œ๋ฅผ ์ƒ์†ํ•œ๋‹ค. ๋‹จ์œ„ 4 ์ „์— ๋‹ค์‹œ ๋ณผ ๊ฒƒ. +- **`unbindLifetime`์„ ํ•œ ๋ฒˆ๋„ ์•ˆ ๋ฌถ์ธ `EffectBrand` ๊ฐ’์— ๋ถ€๋ฅด๋ฉด `value:_unbindDestroying()`์ด + ๋จผ์ € ๋ˆ๋‹ค**(mockยท์Šค์ผ€์น˜ ๋™์ผ) โ€” ๋‹จ์œ„ 3์˜ `_unbindDestroying`์€ ๋ฏธ์—ฐ๊ฒฐ ์ƒํƒœ์—์„œ no-op์ด์–ด์•ผ + ํ•œ๋‹ค(`unbindLifetime`์˜ *"์•ˆ ๊ฑธ๋ ค์žˆ๋˜ ๊ฐ’์— ๋ถˆ๋Ÿฌ๋„ ์•ˆ์ „ํ•œ no-op"* ๊ณ„์•ฝ์„ ์ง€ํ‚ค๋ ค๋ฉด). ๋ฌธ์„œ์—” + ๊ทธ ์š”๊ตฌ๊ฐ€ ๋ช…์‹œ๋ผ ์žˆ์ง€ ์•Š๋‹ค โ€” ๋‹จ์œ„ 3 ํƒ์‚ฌ์ž ๋ชซ. +- **quad-roblox ์ชฝ ๋งˆ์ผ์Šคํ†ค ํ‘œ๊ธฐ๊ฐ€ ๋‘˜๋กœ ๊ฐˆ๋ฆฐ๋‹ค**: `ROADMAP.md` M5์˜ `RobloxFactory.luau`๊ฐ€ + `bindLifetime`/`canExecute`๋ฅผ ์ฃผ์ž…ํ•œ๋‹ค๊ณ  ํ•˜๊ณ (`architecture.md` ์†Œ์Šค ํŠธ๋ฆฌ 300ํ–‰๋„ ๊ฐ™์Œ), + ์‹ค ๊ตฌํ˜„ ์ฒดํฌ๋ฐ•์Šค๋Š” M8(1523ํ–‰)์ด๋‹ค. `LifetimeHandle.luau` ๋„ํฌ์ŠคํŠธ๋ง์€ M8์„ ๋”ฐ๋ž๋‹ค. ์ด + ๋‹จ์œ„ ๋ฒ”์œ„ ๋ฐ–(์ฝ”๋“œ๋Š” ์–ด๋А ์ชฝ์ด๋“  ๊ฐ™์Œ)์ด๋ผ ๋ฐœ๊ฒฌ์œผ๋กœ ์„ธ์ง€ ์•Š๊ณ  ์—ฌ๊ธฐ๋งŒ ์ ๋Š”๋‹ค. +- **๋ชป ๋ณธ ๊ฒƒ**: `Relate` ํ•ซํŒจ์Šค ๋น„์šฉ(`relate-plan.md` "M2 ์ฐฉ์ˆ˜ ์‹œ ์‹ค์ธก ํ™•์ธ")์€ ์ธก์ •ํ•˜์ง€ + ์•Š์•˜๋‹ค โ€” ์•„์ง ํ•ซํŒจ์Šค๋ฅผ ๋ถ€๋ฅด๋Š” ์ฝ”๋“œ๊ฐ€ ์—†๋‹ค. `ref-plan.md` "API ๋ชจ์–‘"์˜ *"`.Value`(์ฝ๊ธฐ + ์ „์šฉ ํ•„๋“œ)"*๋Š” ํƒ€์ž… ๋ ˆ๋ฒจ(`read` ํ”„๋กœํผํ‹ฐ)๋กœ๋Š” ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š”๋‹ค โ€” ๋ฌธ์„œ๊ฐ€ ํƒ€์ž… ๊ฐ•์ œ๋ฅผ + ์š”๊ตฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฐœ๊ฒฌ์œผ๋กœ ์•ˆ ์˜ฌ๋ฆผ. diff --git a/quad-base/test/spec.ref.luau b/quad-base/test/spec.ref.luau index 32d1c7b..479e1da 100644 --- a/quad-base/test/spec.ref.luau +++ b/quad-base/test/spec.ref.luau @@ -121,9 +121,10 @@ do local strongCalls, weakCalls = 0, 0 -- โš ๏ธ ๋‘ ๊ฐ€์ง€ GC ํ•จ์ •์„ ํ”ผํ•œ ๋ชจ์–‘: (1) ๋ณ„๋„ ํ•จ์ˆ˜ ์•ˆ์—์„œ ๋“ฑ๋ก โ€” ๊ฐ™์€ ํ”„๋ ˆ์ž„์˜ -- ์ฃฝ์€ ๋ ˆ์ง€์Šคํ„ฐ๊ฐ€ ํด๋กœ์ €๋ฅผ ๋ถ™์žก๋Š” ์Šคํƒ ์ž”์žฌ๋ฅผ ํ”ผํ•œ๋‹ค. (2) ํด๋กœ์ €๊ฐ€ ์—…๋ฐธ๋ฅ˜๋ฅผ - -- **์ง์ ‘ ๋ณ€๊ฒฝ**ํ•œ๋‹ค โ€” ๋ถˆ๋ณ€ ์—…๋ฐธ๋ฅ˜๋งŒ ์žก๋Š” ํด๋กœ์ €๋Š” Luau๊ฐ€ ํ”„๋กœํ† ์— ์บ์‹œํ•ด - -- ๊ฐ•์ฐธ์กฐ๋กœ ๋ถ™๋“ค์–ด ์˜์˜ GC๋˜์ง€ ์•Š๋Š”๋‹ค(`lifecycle-pattern.md`์˜ `false or` - -- ํŠธ๋ฆญ์ด ๋ง‰๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ตœ์ ํ™”). + -- **์ง์ ‘ ๋ณ€๊ฒฝ**ํ•œ๋‹ค โ€” ์—…๋ฐธ๋ฅ˜๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ „๋ถ€ ํ†ฑ๋ ˆ๋ฒจ ๋ถˆ๋ณ€ ๋กœ์ปฌ์ธ ํด๋กœ์ €๋Š” Luau๊ฐ€ + -- ํ”„๋กœํ† ์— ์บ์‹œํ•ด ๊ฐ•์ฐธ์กฐ๋กœ ๋ถ™๋“ค์–ด ์˜์˜ GC๋˜์ง€ ์•Š๋Š”๋‹ค(์ด ํ…Œ์ŠคํŠธ ํŒŒ์ผ์˜ ํƒ‘๋ ˆ๋ฒจ์ด + -- ์ •ํ™•ํžˆ ๊ทธ ์ž๋ฆฌ; `lifecycle-pattern.md`์˜ `false or` ํŠธ๋ฆญ์ด ๋ง‰๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ตœ์ ํ™”. + -- ํ•จ์ˆ˜ ์ธ์žยท์ง€์—ญ์„ ์žก๋Š” ํด๋กœ์ €๋Š” ํ•ด๋‹น ์—†์Œ โ€” `H-175`). local function register() r:Callback(function() strongCalls += 1