docs: 핸드오버 — Epoch/Brand 제안 승격을 다음 세션 첫 작업으로 지정
사용자 지시로 승격은 다음 세션에("이 세션은 너무 길어요"), 감사는 승격
이후에 돌린다. 이번 세션에서 알게 된 것 중 base/에 안 남아 있던 것을
전부 채웠다.
- base/ 네 문서 상단에 research/epoch-brand-composition.md를 가리키는 ⚠️
배너 신설: state-epoch-plan(두 맵 -> EpochMap 둘), source-state-plan
(Source가 Epoch를 구조적으로 만족 + Observer 클로저 fn(self, from)),
brand-plan(인스턴스 브랜드 전면 재작성), gate-plan(emit 페이로드 타입).
넷 다 "기제는 그대로 유효, 표현만 바뀐다 / 승격 전엔 이 문서가 정본"을
명시.
- ⭐ base/effect-plan.md에 다중 의존성 Effect 갭을 미해결로 기록. 이번
세션에 발견했는데 research 문서에만 있었다 — 제안이 기각되더라도 갭은
남으므로 base에 있어야 한다. 해법 후보(Effect가 자기 EpochMap을 듦)와
접은 대안(deps를 한 노드로 수렴), 그리고 "useEffect처럼 N번 허용"
선택지까지 같이 적었다.
- base/blocker-plan.md에 HasBlockedEmit == (next(withheld) ~= nil)이라는
것과 "빈 배치면 무통지"가 그 일반화라는 것 기록(구현 시 둘을 따로 들지
말 것).
- todos.md에 000번 신설 — 다음 세션 첫 작업, 고칠 문서 넷과 남은 미정
하나(bit32 랩 vs +1)까지 명시.
- question.md 1번에 리비전 증가 방식 항목 추가.
- session-summary.md의 이 세션 항목이 "Gate만 다음 세션 — M2를 막는 유일한
항목"에서 멈춰 있던 것을 전량 갱신(같은 날 Gate/에포크가 확정됐고,
code-review 두 번에 19건이 나왔으며, Epoch/Brand 제안이 대기 중).
doc-check.py ERROR 0.
Co-authored-by: qwreey <me@qwreey.moe>
Claude-Session: https://claude.ai/code/session_01TiW21rnti9SbLgF6twtn6D
This commit is contained in:
parent
782e576218
commit
168d3d8dcc
10 changed files with 138 additions and 1 deletions
|
|
@ -67,6 +67,13 @@ gated state의 동작:
|
|||
`OffWithoutEmit()`은 "밀린 전파를 버리며 끈다" — 어느 쪽이든 대기
|
||||
상태(`HasBlockedEmit`)는 항상 깨끗하게 리셋됨.
|
||||
|
||||
**⭐ [2026-08-21] `HasBlockedEmit`은 게이트 흡수 집합의 특수형이다.**
|
||||
`GateNode`가 드는 `withheld`(이번에 유보한 소스들)에 대해
|
||||
`HasBlockedEmit == (next(withheld) ~= nil)`이고, 아래 "밀린 전파가 없으면
|
||||
아무 것도 안 함(idempotent)"이 게이트 층위에서는 **"빈 배치면 통지 자체를
|
||||
안 한다"**로 일반화된다(`base/gate-plan.md`의 8번). 구현 시 두 개를 따로
|
||||
들지 말 것.
|
||||
|
||||
**⭐ [2026-08-21 신설] `state:Block(blocker)`는 `state:Gate(setup)` 위에
|
||||
얹힌다.** 위 "gated state의 동작"은 `Blocker`만의 특수 노드가 아니라
|
||||
`base/gate-plan.md`가 확정한 **`GateNode`**(`ComputeNode`와 같은 층위)의
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@
|
|||
**상태**: base — 동작/구현 방식은 확정, **이름 `Brand` 자체만 용어 정리
|
||||
대기**(`question.md` 1번).
|
||||
|
||||
**⚠️ [2026-08-21] 이 문서를 전면 재작성하는 제안이 `research/`에 대기 중이다** —
|
||||
단일 공유 레지스트리 + `Brand.get(x) -> tag`(객체당 태그 하나)를 **인스턴스
|
||||
브랜드**(`Brand()` + `:register`/`:is`, **다중 태깅 허용**)로 바꾸는 안
|
||||
(`research/epoch-brand-composition.md`). 발단은 `Source`가 `SourceBrand`이면서
|
||||
동시에 `EpochBrand`여야 하는데 지금 구조로는 표현이 안 되는 것. **역조회
|
||||
`Brand.get`은 불필요로 확정**됐고, 아래 "포함 관계가 코드 모양에 드러난다"는
|
||||
성질은 **그대로 유지된다**(predicate 합성을 계속 쓰면 됨). **커밋된 M1 코드는
|
||||
아직 `Brand`를 안 쓰므로 전환 비용은 문서뿐.** 승격 전엔 이 문서가 정본.
|
||||
|
||||
## `Brand` — 런타임 nominal 타입 판별 통합 메커니즘, `isState`를 일반화 (2026-08-07 여덟 번째 세션)
|
||||
|
||||
**배경**: `isState`(2026-08-07 다섯 번째 세션 확정, `:Peek<<T>>(key):
|
||||
|
|
|
|||
|
|
@ -266,6 +266,21 @@ Effect의 의존성이 될 방법이 아예 없다.** 사용자 제기: *"Effect
|
|||
성립하지 않는 게 확인됐다(`base/gate-plan.md`의 8번) — 설치 구간엔 어떤
|
||||
`Set`도 안 일어나 게이트에 쌓이는 소스가 없으므로 게이트가 내보낼 것 자체가
|
||||
없다. 설치 중 발화를 누르는 플래그 하나면 되고 새 메커니즘이 필요 없다.
|
||||
- **⚠️ [2026-08-21 신설 — 미해결] 의존성들이 공통 상류를 공유하면 한 파동에
|
||||
`fn`이 여러 번 돈다.** `A → b`, `A → c`, `Effect(fn, b, c)`에서 `A:Set()`
|
||||
한 번에 `b`가 자기 observer를, `c`가 자기 observer를 **각각 정당하게** 깨워
|
||||
`fn`이 두 번 돈다. **소스 에포크 dedup으로는 안 접힌다** — `b`와 `c`는 서로
|
||||
다른 노드라 접어줄 **공통 하류가 없고**, 둘 다 규칙 1에 정당하게 걸린다
|
||||
(`base/state-epoch-plan.md`). 위의 "설치 구간 억제"도 이건 안 덮는다(그건
|
||||
등록 시점만).
|
||||
- **해법 후보**: `Effect`가 **자기 `EpochMap`을 하나 들고** 각 내부 observer가
|
||||
그걸 `Update`해서 첫 번째만 통과시키는 것 —
|
||||
`research/epoch-brand-composition.md`가 정확히 이걸 노린 제안이고
|
||||
승격 대기 중이다. (검토했다 접은 대안: deps를 하나의 파생 노드로 수렴시켜
|
||||
다이아몬드 dedup에 태우기 — 노드가 늘고 "N deps → N observers" 구조를
|
||||
바꿔야 해서 위 안보다 못하다.)
|
||||
- **그 제안을 안 쓴다면** `useEffect`처럼 "N번 돌아도 무방"으로 계약을
|
||||
명시하는 선택지도 있다. **어느 쪽이든 M3 구현 전에 정할 것.**
|
||||
- **leaf dedup/cascade가 전부를 덮어야 한다** — 의존성이 N개면 내부 Observer도
|
||||
N개라, `EffectHandle`의 bind/unbind cascade와 dedup 분기가 **그 전부**를
|
||||
같이 처리해야 한다(위 `E-10`/`EF-5`와 같은 함정). 사용자 확인: *"어차피
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ GateNode(ComputeNode 처럼) 생성된다 그리고 Blocker 는 해당 내부
|
|||
표면을 주기도 하구요."* 아래 본문 중 "공개 프리미티브로 꺼낸다"류 서술은 그
|
||||
이전 시점 표현이니 이 배너 기준으로 읽을 것.
|
||||
|
||||
**⚠️ [2026-08-21] emit 페이로드 표현을 바꾸는 제안이 `research/`에 대기 중**
|
||||
(`research/epoch-brand-composition.md`) — 하류가 게이트 identity를 한 번도 안
|
||||
쓰므로 페이로드를 `Epoch|{Epoch}`로 일반화하는 안. 아래 4번의 **기제(흡수 집합,
|
||||
flush 시 스왑, 게이트-게이트 unfold, 빈 배치 무통지)는 그대로 유효**하고 넘기는
|
||||
값의 타입만 바뀐다. 승격 전엔 이 문서가 정본.
|
||||
|
||||
**한 줄**: `Blocker`가 쓰던 "게이티드 State 노드"를 한 겹 일반화해서, **상류
|
||||
emit을 가로채 내려보낼지 말지를 정책이 정하는** 노드를 **`state:Gate(setup)`
|
||||
공개 메소드**로 낸다(탑레벨 생성자가 아니라 — 위 배너 참고).
|
||||
|
|
|
|||
|
|
@ -180,6 +180,14 @@ Handler가 애초에 다른 층위. 관련해서 Handler를 담는 엔진(`Dispa
|
|||
왜 프리미티브가 아니라 탑레벨 싱글톤인지는 `base/dispatch-core-plan.md`의
|
||||
"Dispatch는 프리미티브가 아니다" 절 참고.
|
||||
|
||||
> **⚠️ [2026-08-21] 이 문서의 두 자리를 바꾸는 제안이 `research/`에 대기 중**
|
||||
> (`research/epoch-brand-composition.md`, 승격만 남음) — (1) `Source`가
|
||||
> **`Epoch` 인터페이스**(`{Revision: number}`)를 구조적으로 만족한다는 서술
|
||||
> 추가(`State`를 만족하는 기존 패턴과 같은 모양, 리비전 필드는 **공개**여야
|
||||
> 타입 레벨에서 성립), (2) 아래 "`state:Observer(fn)`" 절의 클로저가
|
||||
> `:Compute`와 같은 모양인 **`fn(self, from: Epoch|{Epoch})`**로 인자를 받음.
|
||||
> 값은 여전히 안 실어주므로 그 계약은 안 깨진다.
|
||||
|
||||
## 전파 모델 확정: push-invalidate(신호만) / pull-recompute(`Get()` 시점에만)
|
||||
|
||||
**Fusion식 eager 노드·생성순 정렬은 안 만듦.**
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
얹는다.** 그 절이 원래 갖고 있던 두 서술은 이 채택으로 뒤집혔고(아래 §3),
|
||||
역전 원문은 `archive/always-propagate-no-dedup-superseded.md`에 있다.
|
||||
|
||||
**⚠️ [2026-08-21] 이 문서의 구조를 바꾸는 제안이 `research/`에 대기 중이다** —
|
||||
두 맵을 `EpochMap`으로 컴포지션하고 `Source` 대신 **`Epoch` 인터페이스**로
|
||||
일반화하는 안(`research/epoch-brand-composition.md`). **사실상 전량 확정됐고
|
||||
승격만 남았다**(같은 날 세션이 길어져 다음 세션으로 미룸). 여기 적힌 규칙 자체는
|
||||
그대로 성립하고 표현만 바뀐다 — 승격 전엔 이 문서가 정본.
|
||||
|
||||
**읽는 순서**: 규칙만 필요하면 **§2**만 보면 된다. §1은 왜 이걸 하는가(실재하는
|
||||
glitch), §3은 무엇이 고쳐지는가, §5는 세부 계약, §7은 구현 시 확인할 것.
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@
|
|||
만들고 `state:Gate(setup)` 메소드로 가면서 `Gater` 문제 자체가 사라짐 —
|
||||
메소드 자리에서는 `:With`/`:Compute`와 나란히 자연스럽다). 노드 타입 이름은
|
||||
`GateNode`. `base/gate-plan.md`의 1번이 소스.
|
||||
- **`Epoch`의 리비전 필드 증가 방식(3순위, 2026-08-21 신설)**: `bit32` 랩
|
||||
(uint32 랩어라운드라 double 포화가 없음, 사용자가 염두에 둔 쪽) vs 평이한
|
||||
`+1`(할당·연산 더 쌈, 포화가 `2^53`이라 `bit32`의 `2^32` 랩보다 충돌 거리가
|
||||
오히려 넓음). **둘 다 도달 불가능이라 실질 위험은 없고 취향 문제다.**
|
||||
필드 이름은 `Revision` 권고(코퍼스 공개 필드 PascalCase 관례).
|
||||
`research/epoch-brand-composition.md` §4의 4번.
|
||||
- **`Slot`(2순위)**: Vue의 "slot"(콘텐츠 주입 지점)과 이름은 같지만 의미가
|
||||
다름(quad의 Slot은 자식 배열 재조정 프리미티브) — Vue 배경 있는 사람이
|
||||
헷갈릴 수 있음.
|
||||
|
|
|
|||
|
|
@ -1654,7 +1654,7 @@ quad-제작 Instance는 **GC 폴백이 없다**는 걸 근거로 보존 주체
|
|||
안에선 동시 만족 불가라는 진단이 근거였고, 사용자가 "지금 의사코드를
|
||||
건들이는 비용이 추후 실수가 누적되는 비용보다 싸다"로 확정.
|
||||
|
||||
## 2026-08-21-02 — QA 5라운드(문항지·회신·1차 처리) + `Gate`/에포크 리서치 신설
|
||||
## 2026-08-21-02 — QA 5라운드 전량 처리 + `Gate` 표면·State 에포크 확정, `Epoch`/`Brand` 제안
|
||||
|
||||
원문: `session/2026-08-21-02-qa-round5-and-gate-epoch-research.md`
|
||||
|
||||
|
|
@ -1688,3 +1688,41 @@ lazy화, `KeyGone`엔 새 값 반환도 error, **`Owned=false`에서 `Detach`는
|
|||
물리보다 먼저")이 역전**됐다 — base엔 자리를 비워둘 수단이 없고 미는 주체는
|
||||
백엔드 삽입 연산 자신이라, 규칙이 "자기 자리 먼저 / 뒤를 미는 것 나중" 하나로
|
||||
줄었다. **`Gate`만 사용자 지시로 다음 세션 — M2를 막는 유일한 항목.**
|
||||
|
||||
**같은 세션 후반 — 리서치로 신설했던 둘이 그 자리에서 확정됐다.**
|
||||
`Gate`는 **탑레벨 프리미티브 없이 `state:Gate(setup)` 메소드 + `GateNode`**로,
|
||||
State의 재계산/전파 판정은 **소스 에포크 비교 채택**으로 닫히며 두 문서가
|
||||
`research/` → `base/`로 승격(`base/gate-plan.md`, `base/state-epoch-plan.md`).
|
||||
그 여파로 `source-state-plan.md`의 확정 서술 둘("emit은 **항상** 전파 / quad가
|
||||
접지 않는 것은 중복 *통지*뿐")이 역전돼
|
||||
`archive/always-propagate-no-dedup-superseded.md`로 갔다 — **2026-08-14의
|
||||
`invalid` 기반 dedup 금지를 되돌린 게 아니라는 것**을 세 곳에 못박았고,
|
||||
스파이크 `05`는 핵심 assert가 정반대가 되어 `rewrite-required/`로 돌아갔다.
|
||||
|
||||
**에포크 기제는 네 라운드에 걸쳐 사용자 정정으로 다듬어졌다** — 순회 조건이
|
||||
`rawInvalid == false`로 뒤집히고, emit은 count 없이 출처만 싣고, 순회가 값만
|
||||
앞당기고 통지는 상류 emit을 기다리게 하려고 맵이
|
||||
`sourceCountMap`/`sourceEmitMap` 둘로 갈렸다(에이전트가 한 번 철회했던 분리가
|
||||
**다른 근거로** 되살아난 것). 새 노드의 두 맵은 **비대칭 초기화**
|
||||
(emit 맵은 비우고, count 맵은 실제 값으로 채운 뒤 `rawInvalid = true`).
|
||||
게이트는 흡수 집합을 들고 **flush 시 스왑**해 배치를 떼어 넘기며, 게이트가
|
||||
게이트 emit을 받으면 **풀어서 자기 집합에 합치고**, **빈 배치면 통지 자체를
|
||||
안 한다**(기존 `HasBlockedEmit` 계약의 일반화). 그 따름정리로
|
||||
`Effect`의 설치 구간 억제가 `Gate` 소비자에서 빠졌다.
|
||||
|
||||
**`/code-review high`를 두 번 돌려 19건이 나왔고 전부 유효했다** — 그중
|
||||
재진입 시 빈 배치가 새던 것과 `OffWithoutEmit`이 흡수 집합을 안 비우던 것은
|
||||
실제 유실 경로였다. 반대로 리뷰가 제기한 것 중 **에이전트 서술 자체가
|
||||
틀렸던 것도 셋** — "Gate 재진입 계약"은 `Blocker`의 인스턴스 중첩 규칙을
|
||||
잘못 옮긴 것이었고, "다중 소스 배치의 중복 계산"은 동기 전파를 놓친 것이었고,
|
||||
"빈 배치 = 무조건 통지" 권고는 State 층에 `Source:Emit`을 추가하는 격이라
|
||||
기각됐다.
|
||||
|
||||
**마지막으로 사용자가 `Epoch`/`EpochMap`/`Brand` 재구성을 제안**했다 — 에포크
|
||||
부기를 State에서 떼어 컴포지션하고, emit 페이로드를 `Epoch` 인터페이스
|
||||
(`{Revision: number}`, 그 자체로 키)로 일반화하고, 그러려면 `Brand`를
|
||||
**인스턴스 브랜드**(다중 태깅)로 바꾸는 안. 발단은 **다중 의존성 `Effect`에서
|
||||
한 파동에 `fn`이 두 번 도는 갭**(공통 하류가 없어 에포크 dedup이 못 접는다)이고,
|
||||
`Effect`가 자기 `EpochMap`을 들면 그게 공통 하류가 되어 닫힌다. **사실상 전량
|
||||
확정됐으나 세션 길이 때문에 `base/` 승격은 다음 세션으로 미뤄졌다** —
|
||||
`research/epoch-brand-composition.md`가 소스, `todos.md` 000번이 진입점.
|
||||
|
|
|
|||
|
|
@ -377,3 +377,27 @@ emit(빈 배치)"은 사용자 판단 항목으로 승격 — 후자는 `Effect(
|
|||
없고, `Effect` 내부 플래그면 충분하다. `effect-plan.md`의 "`Gate`보다 뒤"
|
||||
순서 제약도 같이 사라졌다. 이로써 `Gate`에 사용자 판단 항목은 남지 않았다.
|
||||
전량은 V절.
|
||||
|
||||
## 19. `Epoch`/`EpochMap`/`Brand` 제안, 그리고 핸드오버 (세션 종료)
|
||||
|
||||
에이전트가 "다중 의존성 `Effect`에서 한 파동에 `fn`이 두 번 돈다"는 갭을
|
||||
제기하자(`A → b`, `A → c`일 때 접어줄 공통 하류가 없어 에포크 dedup이
|
||||
못 접는다), 사용자가 그걸 계기로 더 큰 재구성을 제안했다 — 에포크 부기를
|
||||
State에서 떼어 `EpochMap`으로 컴포지션하고, emit 페이로드를 `Epoch`
|
||||
인터페이스로 일반화하고, 그러려면 `Brand`를 인스턴스 브랜드(다중 태깅)로
|
||||
바꾸는 것. `Effect`가 자기 `EpochMap`을 들면 **그 지점이 공통 하류가 되어**
|
||||
갭이 닫힌다.
|
||||
|
||||
두 차례 회신으로 사실상 전량 확정됐다. 그 과정에서 에이전트 주장 셋이
|
||||
반증됐다 — (a) "포함 관계가 생성자로 흩어진다"는 자기 등록이 다중 등록을
|
||||
강제하지 않으므로 틀렸고, (b) "재계산 후 sync 연산이 따로 필요하다"는
|
||||
`Update`가 `{Epoch}`를 받는다는 걸 놓친 것이었으며, (c) "오버플로해도
|
||||
다르다"는 사용자 근거는 double이 랩이 아니라 **포화**한다는 점에서
|
||||
정정됐다(도달 불가능이라 결론은 유지).
|
||||
|
||||
**승격은 사용자 지시로 다음 세션** — *"전면 승격을 하고 싶지만, 이 세션은
|
||||
너무 길어요."* 감사도 승격 이후에 돌리기로 했다. 핸드오버로 `base/` 네
|
||||
문서(`state-epoch-plan`/`source-state-plan`/`effect-plan`/`brand-plan`)
|
||||
상단에 이 제안을 가리키는 ⚠️ 배너를 달았고, `todos.md`에 **000번**을 신설해
|
||||
다음 세션의 첫 작업으로 지정했다. 다중 dep `Effect` 갭 자체도
|
||||
`effect-plan.md`에 미해결로 기록했다 — 제안이 기각되더라도 갭은 남으므로.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,24 @@
|
|||
(`.claude/question.md`, `luau-test/STATUS.md` 등).
|
||||
|
||||
|
||||
000. **⭐⭐⭐ [2026-08-21 신설] 다음 세션의 첫 작업 — `Epoch`/`EpochMap`/`Brand`
|
||||
제안을 `base/`로 승격할 것.** 설계는 **사실상 전량 확정**됐고
|
||||
(`research/epoch-brand-composition.md`가 소스, §4에 결정 상태 전부),
|
||||
같은 날 세션이 너무 길어져 **사용자 지시로 승격만 다음 세션에 미뤘다**
|
||||
(*"전면 승격을 하고 싶지만, 이 세션은 너무 길어요. 컨텍스트 피로 상
|
||||
핸드오버 이후 승격조치를 해야할것 같습니다"*).
|
||||
- **고쳐야 할 문서 넷**: `base/state-epoch-plan.md`(두 맵 → `EpochMap` 둘,
|
||||
"Source의 에포크" → `Epoch`), `base/source-state-plan.md`(`Source`가
|
||||
`Epoch`를 구조적으로 만족 + `Observer` 클로저가 `fn(self, from)`),
|
||||
`base/effect-plan.md`(`Effect`가 자기 `EpochMap`을 들어 다중 dep 중복
|
||||
발화를 접음 — 그 문서의 ⚠️ 미해결 항목이 이걸로 닫힌다),
|
||||
`base/brand-plan.md`(인스턴스 브랜드로 전면 재작성).
|
||||
넷 다 상단에 이 제안을 가리키는 ⚠️ 배너가 이미 달려 있다.
|
||||
- **남은 미정은 하나** — 리비전 증가를 `bit32` 랩으로 할지 평이한 `+1`로
|
||||
할지(둘 다 실질 위험 없음, `question.md` 1번).
|
||||
- **감사는 승격 이후에 돌린다**(사용자 지시) — 지금 돌리면 곧 바뀔 서술을
|
||||
감사하게 된다.
|
||||
|
||||
00. **⭐⭐ [2026-08-18 신설] 구현 전 QA — [2026-08-21] 1~5라운드 전부 `base/`
|
||||
반영 완료. ⭐ 같은 날 마지막에 `Gate`와 State 에포크까지 확정되면서
|
||||
**M2 착수를 막는 설계 항목은 더 이상 없다.**** `Gate`는
|
||||
|
|
|
|||
Loading…
Reference in a new issue