- 탐사자(신선한 컨텍스트, round12 brief §5): 코드-문서 한 줄 대조 1:1 확인,
spec 미태움 경로 셋(H-223 메시지 내용/H-103 NOOP 잔존/매치 실패 후 재등록)
프로브 실측 전부 계약대로, TODO 마커 0 — 발견은 H-228(①, 🟢) 하나
- H-228: describeHandler가 name 부재 시 "?"를 찍던 것을 문서("없으면
priority만 보인다")에 맞춰 (priority N)만 — 순수 진단 문자열
- round12.md §5 이상 없음 확인 3건은 탐사자가 직접 기록(getHandler nil 반환
정본 정합 / Handler 타입 배치 방향 / table.sort 불안정성은 확정 범위 안)
Co-authored-by: qwreey <me@qwreey.moe>
Claude-Session: https://claude.ai/code/session_01LF78pXeFGD1ZSVD3ifteYG
① 반영:
- H-220: BRAND_PROBES specific-first(isPreRef/isPostRef가 isRef 앞) + 손 복사
목록 확장 주의 주석 — 상위 술어가 앞이라 둘이 도달 불능이었음
- H-223: retractor 생략 error에 위반 핸들러 특정 정보(name/priority/k/index)
— h.process 프레임은 반환돼 도달 불가라 메시지가 유일한 단서. 동률 경고도
같은 describeHandler. base 의사코드 동기
- H-227: local Dispatch = {} :: any → 로컬 함수 + 타입 주석 조립로 생산자
표면을 quad-types 선언과 analyze 대조 가능하게
- H-221: ROADMAP 우선순위 체크박스의 stale H-214 주석("§4 대기") 종결로 갱신
- H-224: M4 잔여 몫 문구에 효과 수준 단언(옛 구독 0, stale Set 불전파) 복원
- H-225: 세션 파일에 감사 6라운드 수렴·리뷰 결과 기록
② §4 합류(증상 확정, 처방 대기 — 거짓 사실 주장만 선반영):
- H-218: chains retractor 클로저의 inst 캡처 → H-71 "버킷 값이 weak 키
되참조" 누수 패턴. dispatch-core-plan·ui-shorthand-plan의 "버리면 결국
GC" 주장 정정(retractFrom 의무화 여부는 §4)
- H-219: drive 경로 매치 실패 error의 도착지가 내부 프레임
- H-222: "제공자 계약 위반" level 분류가 계약 표에 없음 — H-212 문단을
잠정 표시로 완화
기각: H-226(process 꼬리 병합 리팩터 — 확정 의사코드 1:1 유지 우선, 실측
병목 아님. 메시지 drift 우려는 H-223 공용 함수로 소멸)
감사 6라운드는 da67a8c diff 전수 점검으로 확실 0건 수렴(의심 1건 표현
정밀도만 정정). 테스트·analyze·doc-check ERROR 0 클린.
Co-authored-by: qwreey <me@qwreey.moe>
Claude-Session: https://claude.ai/code/session_01LF78pXeFGD1ZSVD3ifteYG
- pre-implementation-handtrace-round11(.md/-brief.md) → m2-implementation-round11*
(사용자: 구현 중 문서라 pre-implementation이 안 맞음), 인용처 22곳 일괄 치환
- 명명 규약(사용자 확정, README qa-request/ 행): mN-implementation-roundNN —
라운드 번호는 마일스톤을 가로질러 단순 증가("m3 진행 중 m2 하자로 돌아가는
경우도 있을 것"), 마일스톤 접두가 소속을 담음. round1~10 옛 이름은 실제로
구현 전 라운드라 유지
- CLAUDE.md/project-context.md 머리말: M0~M2 완료, 다음은 M3(디스패치 엔진);
todos 00 종결 표기 — 다음 액션은 M3 착수 규약 문항(사용자와 정할 것)
Co-authored-by: qwreey <me@qwreey.moe>
Claude-Session: https://claude.ai/code/session_01LF78pXeFGD1ZSVD3ifteYG
- H-198(사용자 안): 상류 스탬프(dep:_track)를 fn 직전으로 + Get을 수렴까지의
재시작 루프로 — 계약 강화: 모든 Get이 fn 도중 변경(재진입·게이트 유보)을
같은 호출 안에서 수렴시켜 항상 최신 반환. 매 패스 자기 dep Set은 UB.
state-epoch-plan §4 세 절 + H-85 bullet 정정, spec.state 6 새 계약,
spec.gate 10(리뷰의 영구 stale 재현 → 같은 Get에서 99 + flush 통지만)
- H-186(b): 교차 인스턴스 값 혼용 UB 문서화 — architecture 13번 + content-map
§4 22번(H-116 이웃), 코드 주석. M5 재검토
- H-205(a): Modifier 가드 level 2→3(직접 Get이면 유저 호출부), spec.state 12 단언
- H-208: Ref:Set 스냅샷을 table.clone + 집합 병합으로(사용자 — 더 싸고 dedup 공짜)
- H-209: src 전 파일 pairs/ipairs → generalized iteration(사용자 — 최적화로 더
빠름; 메타테이블 있는 테이블의 raw 순회 실측 확인). 문서 의사코드 표기는
H-178과 같은 급으로 무변경
- H-211: Relate:SetWeak의 캐스트 없는 setmetatable 대입이 IDE(strict)에서
TypeError(플레인 luau-analyze는 솔버 차로 조용) → 로컬 주석 + :: any 경유
- §4 열린 문항 0, 코드 마커 0. 감사 2라운드 수렴(확실 1·의심 1 → 0)
Co-authored-by: qwreey <me@qwreey.moe>
Claude-Session: https://claude.ai/code/session_01LF78pXeFGD1ZSVD3ifteYG
quad-spring-roblox류 독립 게시 플러그인엔 정확 버전 일치가 과하다는 지적에
따라, 버전 패턴 매칭(글롭 "*"/캐럿 "N^")을 quad에 종속되지 않은 범용
워크스페이스 멤버 type-version-check로 분리하고 quad-types의 CheckedQuad를
CheckedQuad<T, Pattern>으로 확장. 새 Luau 함정 2건(type function의 outer
local 참조 불가, cross-package엔 export type function + 이중 꺾쇠 제네릭
인스턴스화 필요) 발견·문서화. 독립 저장소 분리는 HUMAN_TODO로 위임.
Co-authored-by: qwreey <me@qwreey.moe>
quad-roblox가 quad-base를 런타임 주입(QuadRoblox(Quad): QuadRoblox)으로만
받으면 pesde 의존 선언이 필요 없어 보이지만, 타입 참조용 require도
런타임에 실제 실행됨을 실측 확인 — dev-dependency로 두면 게시 후
소비자 환경에서 크래시함. 해법으로 구현 없는 타입 계약 전용 워크스페이스
패키지 quad-types 신설, quad-base/quad-roblox 모두 이것만 의존하도록
전환.
AddPlugin<Self,P>(self:Self,fn:(Self)->P):Self&P — 제네릭 self로 둬야
체이닝이 누적됨을 실측 확인(고정하면 이전 확장을 잃음), quad-base에
실제 mutate 기반 구현 반영.
CheckedQuad<T> 버전 체크는 배선하며 세 번 깨짐 — error() 대신
print+types.never, 함수 본문 로컬 별칭 대신 리턴 타입 표현식에 직접,
그리고 가장 중요하게 type function을 한 번이라도 거친 값(패스스루
포함)은 이후 AddPlugin 같은 제네릭 self 체이닝이 조용히 깨진다는 새
Luau 함정 발견 — typing-limits.md §6으로 승격. 최종 설계(검증 결과를
원본과 격리된 가상 필드로)만 AddPlugin과 완전히 호환.
부수로 quad-base 자신도 quad-types workspace 의존 때문에 CLI symlink
함정(지난 세션 발견)에 걸림 — 로컬 테스트용 symlink 실체화로 임시 우회.
Co-authored-by: qwreey <me@qwreey.moe>
New()의 멱등 Init 가드를 파일마다 Relate+센티널을 두던 방식에서
module:RunInit(initFn) 하나로 통합 — 함수 자체를 릴레이션 키로 써서
"이 함수, 이 모듈에 실행했는가"를 (module, initFn) -> boolean? 하나로
표현(사용자 제안). Debug/init.luau는 가드 없이 순수 뮤테이션만 하도록
단순화. smoke.init.luau로 재호출 무시/인스턴스별 독립/함수별 독립 3개
시나리오 검증(luau/luau-analyze/selene 클린).
darklua process를 실제로 돌려 @self/@game은 안 건드리고 커스텀 .luaurc
alias(@pkg)만 script.Parent류로 치환한다는 걸 확인 — project-setup-plan.md의
darklua 기각 근거를 "지금은 커스텀 alias를 안 쓰니 불필요, 나중에 도입하면
그때 필요해짐"으로 정밀화.
⚠️ 미결: RunInit을 backend 설치 진입점(QuadRoblox(Quad))에도 재사용할지
— 함수 identity 추적으로는 "다른 팩토리 재호출은 에러" 계약을 못 만족.
module-lifecycle-plan.md에 반영, M2/M5 착수 전 확인 필요.
Co-authored-by: qwreey <me@qwreey.moe>
Word30210/roblox-project-example(initreq/에 클론)를 참고해 두 가지 채택:
(1) rokit.toml → mise.toml — mise install이 pesde/rojo/luau-lsp/selene을
GitHub attestation+SLSA provenance 검증까지 거쳐 설치하는 걸 이 샌드박스
에서 직접 확인(rokit은 끝내 검증 불가), 이 환경 자체가 이미 mise로
luau를 관리 중이라 더 자연스러움. (2) selene 린터 — 참고 레포의
selene.toml을 패키지별로 채택, 단 CWD 상대 config 탐색 함정을 발견
(루트 단일 설정으로 두면 다른 디렉토리에서 실행 시 조용히 Lua 5.1
std로 폴백해 Luau 타입 문법 전체가 파싱 에러로 잘못 보임) — 참고 레포
그대로 패키지별 selene.toml + 패키지 안에서 실행하는 걸로 확정. 도입
즉시 smoke.mock.luau의 assert 메시지 누락 3건을 잡아 수정.
darklua의 convert_require 변환은 검토 후 기각 — 사용자 판단: Roblox
엔진 자체도 이미 같은 require-by-string 의미론(@self/@game)을 지원해
변환 계층이 불필요.
Co-authored-by: qwreey <me@qwreey.moe>