quad/quad-base/test/spec.init.luau
qwreey 1e070e3f1f
feat(m2): 단위 2 — EpochMap / State(Init 팩토리, H-174) / Source / Store + quad-types 최종형 타입 + spec 4개
- EpochMap.luau: Update/Peek/Refresh/Sync/TrackFrom, EpochSet은 집합, 키 weak (state-epoch-plan §3).
- State.luau: InitState(module) → 인스턴스별 임플(implFor로 Source/Store에 전달). _emitDown은
  스냅샷 후 sub:_receive(from)(H-163), _receive 규칙 1~3, 시딩 Sync/TrackFrom, 카운터 쌍(H-85),
  Get의 Refresh 순회(값만), fn(self=리시버 lazy 핸들, previous?, ...deps), With pass-through,
  Apply(fn | __apply 객체, H-158), _hold 강참조. Compute 결과 isModifier 가드, dep isState 검증.
- Source.luau: Set 동일값도 emit(H-68)/Emit/isModifier 가드, SourceBrand+EpochBrand.
- Store.luau: 그림자=store 자신, defaults isSource 화이트리스트 + RESERVED 가드(H-122/H-153),
  Of(모듈의 Source를 호출 시점에)/Names.
- quad-types: StateData/State/Source/Store 타입(ty11 최종형), export type function CheckReservedKeys,
  Quad에 Source/Store. Compute deps는 ...any — 타입팩 D...는 strict에서 기각(H-176, 스파이크 15 닫힘).
- spec.{epochmap,source,state,store}.luau, spec.init에 Source/Store. ROADMAP 단위 2 체크박스,
  round11 §5 단위 2 확인 목록, 세션 원문·요약.

Co-authored-by: qwreey <me@qwreey.moe>
2026-08-28 20:33:29 +09:00

34 lines
1.7 KiB
Text

--[[
`Quad` 탑레벨 값 존재 확인 — `quad-types`의 `Quad` 타입과 `New()`가 실제로 싣는 값의
드리프트(`ROADMAP.md` M2 `H-80`/`H-25` 부류)를 타입 검사 아래에서 잡는다.
`init.luau`의 `{...} :: Quad` 캐스트는 빠진 필드를 안 잡으므로(실측) 이 런타임 확인이
유일한 가드다 — 그래서 `smoke.*`(analyze 제외)가 아니라 `spec.*`에 둔다.
]]
local Quad = require("../src")
local QuadTypes = require("../roblox_packages/quad_types")
type Quad = QuadTypes.Quad
print("=== 1. New()마다 M2 첫 단위 탑레벨 값이 실려 있음 ===")
do
local m: Quad = Quad.New()
assert(type(m.Relate) == "function" and type(m.Void) == "function" and type(m.Ref) == "function", "Relate/Void/Ref constructors")
assert(type(m.Source) == "function" and type(m.Store) == "function", "Source/Store constructors (unit 2, per instance)")
assert(m.Source ~= Quad.Source, "Source is an instance-level factory (H-174), not a shared leaf")
local predicates: { (any) -> boolean } = {
m.isEpoch, m.isSource, m.isState, m.isStore, m.isObserver, m.isEffect,
m.isBlocker, m.isModifier, m.isRef, m.isPreRef, m.isPostRef,
}
for i, p in predicates do
assert(type(p) == "function", "predicate #" .. i .. " must be a function")
assert(p({}) == false, "predicate #" .. i .. " is false for an unregistered table")
end
assert(type(m.bindLifetime) == "function" and type(m.unbindLifetime) == "function", "lifetime stubs")
assert(type(m.canBound) == "function" and type(m.canExecute) == "function", "lifetime stubs")
assert(m.Void == Quad.Void and m.Ref == Quad.Ref and m.Relate == Quad.Relate, "leaf modules are shared across instances")
print("PASS")
end
print()
print("=== ALL PASS ===")