docs: CLAUDE.md 4분할(매 세션 로드 1537→354줄), 워크플로 가짜 초록불 수정
## CLAUDE.md 분할
1537줄이라 (a) 사람이 검토 불가, (b) 공식 권장치(파일당 200줄) 7.7배
초과로 지침 준수도 자체가 저하, (c) 긴 파일 편집 시 에이전트 실수 증가.
CLAUDE.md (39줄, 진입점)
├─ @.claude/conventions.md 언어/모델 관례 + 작업 방식
├─ @.claude/project-context.md 프로젝트 설명 + 문서 구조
└─ @.claude/todos.md 지금 할 일
.claude/session-summary.md ← import 안 함(의도적, 온디맨드)
세션 히스토리 1231줄(전체의 80%)은 그 문서 스스로 "항상 읽을 필요 없음,
base/가 소스"라고 명시해온 색인이라 @import에서 뺐음. 내용 유실 없음
(1537→1647줄, 추가 헤더만큼 증가).
주의: @import는 컨텍스트를 줄이지 않음(전부 로드됨). 분할이 사는 건
사람 검토성 + 편집 정확도 + 파일 단위 자동생성 가능성.
CLAUDE.md 계열의 블록 HTML 주석은 주입 전 제거되므로 지시는 본문에 쓸 것.
## 워크플로 가짜 초록불 수정
첫 실측에서 감사 에이전트 6개 전원 실패했는데 converged:true가 나왔음
(전멸하면 fresh가 비어 "깨끗한 라운드"와 구분 불가). 감사 도구 최악의
실패 모드라 (1) 전멸이면 throw, (2) 반영 에이전트 실패 시 그 발견을
seen에서 빼 다음 라운드가 재시도하도록 수정.
## 부수
- 분할로 깨진 상호참조 20여 곳 정정(병렬 에이전트 3개).
ref-plan.md:541의 사전 존재 오류(→ pre-implementation-audit 1-5)도 정정.
- doc-check.py: 새 파일 4개를 OURS에 등록(안 하면 깨진 참조가 WARN으로만
잡힘), is_history()로 session-summary.md를 archive/와 같이 면제.
- doc-include-plan.md: 목적지가 통째로 생성되는 파일이 되면서 양방향
마커 설계의 절반(목적지 마커)이 불필요해져 단방향 생성으로 단순화.
doc-check.py ERROR 0 유지.
미해결: session-summary.md 자동생성 미착수(91개 세션 파일 마커 삽입 필요),
orphan 인용 3건(modifier-plan.md:536, v1-compat-plan.md:50,
pre-implementation-audit.md:434 — 분할 이전부터 존재).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HvEKn9f67kkx2nGLG8PsP
This commit is contained in:
parent
a1c0e44258
commit
8aeec7644f
24 changed files with 2035 additions and 1578 deletions
|
|
@ -1,9 +1,21 @@
|
||||||
# .claude/ — quad-v2 계획/설계 문서 색인
|
# .claude/ — quad-v2 계획/설계 문서 색인
|
||||||
|
|
||||||
이 레포 전체가 quad-v2(재작성) 프로젝트이므로, webmanager류 서브프로젝트 구분 없이
|
이 레포 전체가 quad-v2(재작성) 프로젝트이므로, webmanager류 서브프로젝트 구분 없이
|
||||||
`.claude/` 바로 아래에 전부 있음. **루트 `CLAUDE.md`가 현재 상태+TODO 색인의
|
`.claude/` 바로 아래에 전부 있음. **루트 `CLAUDE.md`가 진입점** — 먼저 그걸 보고,
|
||||||
최종 소스** — 먼저 그걸 보고, 특정 결정의 자세한 근거/논의가 필요할 때만 아래
|
특정 결정의 자세한 근거/논의가 필요할 때만 아래 개별 문서를 열어볼 것.
|
||||||
개별 문서를 열어볼 것.
|
|
||||||
|
**[2026-08-16 재구조화]** `CLAUDE.md`가 1537줄까지 불어나 사람이 검토할 수
|
||||||
|
없고 지침 준수도도 떨어져서, 주제별로 쪼개고 `@import`로 다시 합침. 지금
|
||||||
|
`CLAUDE.md`는 39줄짜리 진입점이고 실제 내용은 아래 세 파일에 있음(전부 매
|
||||||
|
세션 자동 로드됨):
|
||||||
|
|
||||||
|
| 파일 | 무엇이 들어있나 |
|
||||||
|
|---|---|
|
||||||
|
| `conventions.md` | 언어/모델 관례 + **작업 방식**(핸드오버 체크리스트, `doc-check.py`, `quad-doc-auditor`, SAFETY 준수 등 에이전트가 따라야 할 절차 전부) |
|
||||||
|
| `project-context.md` | 이 프로젝트가 뭔지 + 계획 문서 구조(폴더별 성격 요약 — 상세 색인은 이 README가 소스) |
|
||||||
|
| `todos.md` | 지금 할 일(우선순위순). 가장 자주 바뀜 |
|
||||||
|
| `session-summary.md` | 세션별 2~4줄 요약 색인. **`@import` 안 됨(의도적)** — 1231줄을 매 세션 올릴 이유가 없어 온디맨드로 둠, 선행 맥락이 필요할 때 grep해서 열 것. 자동생성 전환 예정(`research/doc-include-plan.md`) |
|
||||||
|
| `question.md` | 사용자가 답해야 할 열린 질문(우선순위순) |
|
||||||
|
|
||||||
## 폴더 기준
|
## 폴더 기준
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
name: quad-doc-auditor
|
name: quad-doc-auditor
|
||||||
description: quad 프로젝트의 `.claude/` 설계 문서 코퍼스(base/research/reference/archive, README.md, question.md, CLAUDE.md, 루트 ROADMAP.md/HUMAN_TODO.md)에서 `doc-check.py`가 못 잡는 의미론적 stale/모순을 찾는다. 설계 결정이 뒤집히거나 확정되는 등 이 코퍼스에 중대한 변경이 있은 뒤, 특히 그런 변경을 커밋하기 전에 사용. 읽기 전용 — 문제를 리포트만 하고 직접 고치지 않는다.
|
description: quad 프로젝트의 `.claude/` 설계 문서 코퍼스(base/research/reference/archive, README.md, question.md, conventions.md, project-context.md, todos.md, 루트 CLAUDE.md/ROADMAP.md/HUMAN_TODO.md)에서 `doc-check.py`가 못 잡는 의미론적 stale/모순을 찾는다. 설계 결정이 뒤집히거나 확정되는 등 이 코퍼스에 중대한 변경이 있은 뒤, 특히 그런 변경을 커밋하기 전에 사용. 읽기 전용 — 문제를 리포트만 하고 직접 고치지 않는다.
|
||||||
tools: Read, Grep, Glob, Bash
|
tools: Read, Grep, Glob, Bash
|
||||||
model: sonnet
|
model: sonnet
|
||||||
memory: project
|
memory: project
|
||||||
|
|
@ -34,7 +34,8 @@ memory: project
|
||||||
부정하는 *본문 bullet*은 안 고쳐진 경우 — 배너만 보고 넘어가지 말고
|
부정하는 *본문 bullet*은 안 고쳐진 경우 — 배너만 보고 넘어가지 말고
|
||||||
반드시 본문까지 읽어라.
|
반드시 본문까지 읽어라.
|
||||||
4. 뒤집힌 결정의 원문이 `archive/`로 옮겨지지 않고 라이브 문서(`base/`,
|
4. 뒤집힌 결정의 원문이 `archive/`로 옮겨지지 않고 라이브 문서(`base/`,
|
||||||
`research/`, `reference/`, `README.md`, `CLAUDE.md`, `ROADMAP.md`)에
|
`research/`, `reference/`, `README.md`, `conventions.md`,
|
||||||
|
`project-context.md`, `todos.md`, `CLAUDE.md`, `ROADMAP.md`)에
|
||||||
"히스토리로만 보존" 같은 말과 함께 전체 서술로 남아있는지 확인해라.
|
"히스토리로만 보존" 같은 말과 함께 전체 서술로 남아있는지 확인해라.
|
||||||
앞에서부터 읽는 구현자가 그걸 "확정"으로 오인할 여지가 있으면 문제다.
|
앞에서부터 읽는 구현자가 그걸 "확정"으로 오인할 여지가 있으면 문제다.
|
||||||
5. 이번 변경으로 개수·목록·상태 서술("N개 문서", "남은 항목은 이것뿐",
|
5. 이번 변경으로 개수·목록·상태 서술("N개 문서", "남은 항목은 이것뿐",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
**배경**: 2026-08-09 열두 번째 세션에 스파이크를 만들기 시작한 이래
|
**배경**: 2026-08-09 열두 번째 세션에 스파이크를 만들기 시작한 이래
|
||||||
**처음으로 `luau`/`luau-analyze` 바이너리가 사용 가능해져 실제로 돌려본
|
**처음으로 `luau`/`luau-analyze` 바이너리가 사용 가능해져 실제로 돌려본
|
||||||
결과**. 그동안 CLAUDE.md가 "M0 착수 전 남은 유일한 게이트"로 꼽아온 항목.
|
결과**. 그동안 `.claude/todos.md`가 "M0 착수 전 남은 유일한 게이트"로 꼽아온 항목.
|
||||||
|
|
||||||
사용자 요청: "지금 상황에서 문제가 생겨 프로젝트의 구조 변경이 생기면 큰
|
사용자 요청: "지금 상황에서 문제가 생겨 프로젝트의 구조 변경이 생기면 큰
|
||||||
작업인데, 이것이 더 큰 스파이크로 번지기 전에 미리 확인하고싶습니다."
|
작업인데, 이것이 더 큰 스파이크로 번지기 전에 미리 확인하고싶습니다."
|
||||||
|
|
|
||||||
|
|
@ -299,7 +299,7 @@ CollectionService 태그 등)를 흉내낼 필요가 없고, quad-base 자체
|
||||||
|
|
||||||
**백로그**: 나중에 범용 렌더 결과 디버깅 도구로 키우고 싶어지면(정적
|
**백로그**: 나중에 범용 렌더 결과 디버깅 도구로 키우고 싶어지면(정적
|
||||||
스냅샷을 넘어 Tween mock 같은 동적 동작까지 포함) 그때 스코프를 넓히는
|
스냅샷을 넘어 Tween mock 같은 동적 동작까지 포함) 그때 스코프를 넓히는
|
||||||
걸로 — 지금은 quad-base 테스트 전용 최소 mock까지만(`CLAUDE.md` 백로그
|
걸로 — 지금은 quad-base 테스트 전용 최소 mock까지만(`.claude/todos.md` 백로그
|
||||||
참고).
|
참고).
|
||||||
|
|
||||||
## Store/State/Source 온톨로지 — 확정됨 (요약)
|
## Store/State/Source 온톨로지 — 확정됨 (요약)
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,6 @@ Store/Dispatch 어디에도 안 걸림, 엔진 지식이 전혀 필요 없음. `
|
||||||
|
|
||||||
**형제 백로그 항목들(`quad-mock`/`quad-debug`/문서 사이트/`Operator`)과
|
**형제 백로그 항목들(`quad-mock`/`quad-debug`/문서 사이트/`Operator`)과
|
||||||
동급, 맨 뒤 — "quad 개발 상당 부분 끝난 뒤"로 사용자가 못박은 후순위**
|
동급, 맨 뒤 — "quad 개발 상당 부분 끝난 뒤"로 사용자가 못박은 후순위**
|
||||||
(`CLAUDE.md` "지금 할 일" 4번). 이 문서가 `base/`로 승격된 건 설계가 다
|
(`.claude/todos.md` 4번). 이 문서가 `base/`로 승격된 건 설계가 다
|
||||||
확정됐다는 뜻이지, 구현 착수 순서가 앞당겨졌다는 뜻이 아님 — `Operator`처럼
|
확정됐다는 뜻이지, 구현 착수 순서가 앞당겨졌다는 뜻이 아님 — `Operator`처럼
|
||||||
순수 슈가라 없어도 quad 기능상 완전함(`pcall`을 직접 쓰면 되므로).
|
순수 슈가라 없어도 quad 기능상 완전함(`pcall`을 직접 쓰면 되므로).
|
||||||
|
|
|
||||||
|
|
@ -538,7 +538,7 @@ flatten된 값은 해시 파트(프로퍼티 키)로 존재하게 되고, Store
|
||||||
이 위험을 원천 회피함(검증 불필요, 애초에 구멍을 안 만드므로).
|
이 위험을 원천 회피함(검증 불필요, 애초에 구멍을 안 만드므로).
|
||||||
**여전히 M0에서 검증해야 하는 건 다른 케이스**: `props.Modifier`/
|
**여전히 M0에서 검증해야 하는 건 다른 케이스**: `props.Modifier`/
|
||||||
`props.Ref`를 caller가 안 넘겨 생기는 리터럴 `nil`-hole(`{nil, ref,
|
`props.Ref`를 caller가 안 넘겨 생기는 리터럴 `nil`-hole(`{nil, ref,
|
||||||
child}`, 위 "지금 할 일" 우선순위1 항목)은 caller가 직접 쓰는 raw
|
child}`, `research/pre-implementation-audit.md` 1-5)은 caller가 직접 쓰는 raw
|
||||||
Lua 리터럴이라 프레임워크가 `None`으로 대신 못 채워줌 — 이번 REPL
|
Lua 리터럴이라 프레임워크가 `None`으로 대신 못 채워줌 — 이번 REPL
|
||||||
실측으로 그 케이스의 실제 위험도가 이전 서술("뒤 항목까지 무시될 수
|
실측으로 그 케이스의 실제 위험도가 이전 서술("뒤 항목까지 무시될 수
|
||||||
있음", 국소적 피해로 서술돼 있었음)보다 훨씬 큼이 드러남: 구멍이 하나만
|
있음", 국소적 피해로 서술돼 있었음)보다 훨씬 큼이 드러남: 구멍이 하나만
|
||||||
|
|
|
||||||
114
.claude/conventions.md
Normal file
114
.claude/conventions.md
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
# 관례와 작업 방식
|
||||||
|
|
||||||
|
이 파일은 루트 `CLAUDE.md`가 `@import` 하므로 **매 세션 컨텍스트에 로드된다**
|
||||||
|
— 늘리기 전에 "정말 매 세션 필요한가"를 따질 것. 세션마다 필요하진 않은
|
||||||
|
상세는 `.claude/` 아래 개별 문서로.
|
||||||
|
|
||||||
|
<!-- 참고: CLAUDE.md 계열 파일의 블록 HTML 주석은 컨텍스트 주입 전에 제거된다.
|
||||||
|
즉 여기 주석으로 쓴 것은 에이전트가 못 본다 — 지시는 반드시 본문에 쓸 것. -->
|
||||||
|
|
||||||
|
## 언어/모델 관례 (기존 메모, 유지)
|
||||||
|
|
||||||
|
사용자는 한국 유저임을 유의해. 사용자가 보게 될 것은 한국어로 띄워주는 게
|
||||||
|
좋아. 너가 보는 것들(코드 주석 등)은 원하는 언어여도 되는 것(가장 성능이 좋을
|
||||||
|
영어를 쓰든 그래도 됨, 예를 들어 이 문서도 영어여도 무방하지만 지금은
|
||||||
|
한국어로 유지). 사용자가 검토해야 하는 것(plan, backlog 등)은 한국어로 써.
|
||||||
|
코드 안 주석은 공식성을 유지하기 위해 굳이 한국어일 필요 없음, 영어 가능.
|
||||||
|
|
||||||
|
또 토큰 맥싱에 유의해 — 아주 작은 테스크라 충분히 작은 모델이 쓸 수 있으면
|
||||||
|
haiku, 일반 작업은 sonnet. 특히 소스코드를 많이 읽어야 하는 리서치는 메인
|
||||||
|
컨텍스트를 부패시키니 Agent로 위임할 것(아래 "작업 방식" 참고).
|
||||||
|
|
||||||
|
## 작업 방식
|
||||||
|
|
||||||
|
- **소스코드를 많이 읽어야 하는 리서치는 Agent(Explore)로 위임** — 메인
|
||||||
|
컨텍스트 보호. 이미 완료된 v1/rbvm/tbox/Fusion/Vide 리서치 결과는
|
||||||
|
`.claude/base/`에 정리되어 있으니 중복 조사하지 말고 먼저 그걸 볼 것.
|
||||||
|
- **병렬화 가능한 작업은 Agent 여러 개를 한 메시지에 동시 호출.** 서로 독립적인
|
||||||
|
파일/주제를 다루는 리서치나 구현 조사, 또는 서로 다른 문서 파일을 고치는
|
||||||
|
문서 정리 작업이 여기 해당(단, 같은 파일을 동시에 고치는 에이전트를 병렬로
|
||||||
|
띄우지 말 것 — 충돌함).
|
||||||
|
- **크리티컬한 설계 결정은 구현으로 밀어붙이지 말고 plan을 research/에 남긴 채
|
||||||
|
연기.** 사용자는 Lua/Roblox 엔진을 깊이 아는 사람 — 근거와 선택지를 문서에
|
||||||
|
정리해두면 사용자가 깨어있을 때 훑어보고 답해줄 것. `.claude/question.md`에
|
||||||
|
반드시 반영.
|
||||||
|
- **작업이 끝나면(또는 방향이 바뀌면) 항상 자기 문서화** — 완료된 걸 다시
|
||||||
|
조사하게 되는 재작업을 막기 위함. `.claude/base/`로 승격, `.claude/qa-request/`로
|
||||||
|
이동, 또는 문서 자체를 갱신. code-docker/webmanager의 `.claude/` 관리 방식이
|
||||||
|
좋은 예시(`.claude/initreq/code-docker/webmanager/.claude/README.md` 참고).
|
||||||
|
- **⭐ 중대 변경 핸드오버 체크리스트 — 확정된 결정을 뒤집거나 문서를
|
||||||
|
쪼갤 때 반드시 이 순서를 밟을 것.** 2026-08-13 일곱/여덟 번째 세션에
|
||||||
|
6+6라운드 수동 감사로 55건을 찾았는데, **거의 전부가 "변경한 세션이
|
||||||
|
그 자리에서 안 한 일"이 나중에 stale로 쌓인 것**이었음. 감사로 뒤늦게
|
||||||
|
줍지 말고 바꾸는 그 순간에 닫을 것:
|
||||||
|
1. **`python3 .claude/tools/doc-check.py`를 돌릴 것**(아래 항목 참고) —
|
||||||
|
ERROR 0을 유지한 채로 커밋. 이게 규율 대부분을 기계가 대신함.
|
||||||
|
2. **바꾼 주장을 부정당하는 *본문 문장*을 grep으로 전수 찾을 것**(또는
|
||||||
|
`.claude/agents/quad-doc-auditor.md`로 위임 — 아래 항목 참고, 신선한
|
||||||
|
맥락에서 도는 서브에이전트가 이 항목을 실제로 더 잘 잡아왔음).
|
||||||
|
헤더에 정정 배너만 달고 본문 bullet을 안 고치는 게 가장 잦은 실패 —
|
||||||
|
실제로 `CLAUDE.md`가 "스파이크를 아직 안 돌려봄"이라고 서술한 채
|
||||||
|
한 라운드를 통과했음. **배너를 달았으면 그 배너가 부정하는 문장을
|
||||||
|
같은 커밋에서 고쳤는지 확인.**
|
||||||
|
3. **뒤집힌 원문은 `archive/`로 옮기고 포인터만 남길 것** — 본문에
|
||||||
|
"히스토리로만 보존"이라며 두면 구현자가 앞에서부터 읽다가 그
|
||||||
|
"확정"을 그대로 믿음(`slot-plan.md`에서 실제로 발생).
|
||||||
|
4. **개수·목록·상태는 소스를 하나만 둘 것.** "20개 중 19개", "4개
|
||||||
|
문서", "남은 건 X뿐" 류는 두 곳 이상에 적는 순간 반드시 갈라짐 —
|
||||||
|
한 곳(예: `luau-test/STATUS.md`, 폴더 구조)을 소스로 하고 나머지는
|
||||||
|
가리키기만.
|
||||||
|
5. **시한부 주장엔 날짜를 붙일 것.** "아직 안 돌려봄"이 아니라
|
||||||
|
"[2026-08-09 기준] 아직 안 돌려봄" — 날짜가 있으면 다음 세션이
|
||||||
|
의심할 수 있지만, 없으면 영원히 현재형으로 읽힘.
|
||||||
|
6. **인덱스 레이어 3개를 같이 갱신**: `.claude/README.md`(색인),
|
||||||
|
`question.md`(사용자가 답할 것만), 루트 `ROADMAP.md`/`HUMAN_TODO.md`.
|
||||||
|
- **기계 점검 — `python3 .claude/tools/doc-check.py`.** 깨진 파일/절
|
||||||
|
참조, README 색인 누락, 날짜 없는 시한부 주장, 미반영 배너를 한 번에
|
||||||
|
훑음. **커밋 전에 돌리는 게 기본** — 수동 감사에서 나온 발견의 대부분이
|
||||||
|
이걸로 잡히는 종류였고, 실제로 여덟 번째 세션에 문서를 쪼개면서 잘못
|
||||||
|
옮긴 참조를 이 스크립트가 잡아냈음. ERROR는 고치고, WARN은 판단이
|
||||||
|
필요한 것(절 제목을 의역해 인용한 관례 등)이라 늘 0일 필요는 없음.
|
||||||
|
- **[2026-08-16 도입] `.claude/agents/quad-doc-auditor.md` 서브에이전트 —
|
||||||
|
위 체크리스트 2~4번(본문 문장 grep, archive 이전, 개수/목록 단일화)을
|
||||||
|
신선한 맥락에서 대신 수행.** 읽기 전용, 발견만 리포트(직접 수정 안 함).
|
||||||
|
**`.claude/base`/`.claude/research`/이 문서/`.claude/todos.md` 등 라이브
|
||||||
|
문서에 중대한 변경이 있은 뒤, 특히 커밋 전에 돌리는 게 기본** — 지난
|
||||||
|
세션들에서 "변경한 세션 자신의
|
||||||
|
self-audit은 자기가 뭘 안 건드렸는지 몰라서 놓친다"는 패턴이 반복
|
||||||
|
확인됐고(세션 히스토리 7·8·10·11차 등), 이걸 매번 즉흥적으로 프롬프트
|
||||||
|
짜는 대신 고정 정의로 옮긴 것. **아주 큰 변경**(설계 반전 규모)엔 이걸로
|
||||||
|
대체하지 말고 `/code-review`(diff 기반)와 사용자의 직접 diff 검토를
|
||||||
|
병행할 것 — 이 서브에이전트는 diff가 아니라 코퍼스 전체의 정합성만 봄.
|
||||||
|
- **[2026-08-16 도입] "핸드오버 준비하고 커밋해" 류 요청엔 되묻지 말고
|
||||||
|
`.claude/workflows/quad-handover-audit.js`(Workflow 이름
|
||||||
|
`quad-handover-audit`)를 먼저 돌릴 것.** 단일 `quad-doc-auditor` 패스는
|
||||||
|
비결정적이라 매번 다 잡는다는 보장이 없다는 게 사용자 지적 — 이 워크플로는
|
||||||
|
라운드마다 `quad-doc-auditor`를 병렬로 3회 돌리고 새 발견을 파일별로
|
||||||
|
즉시 반영한 뒤, **새 발견이 없는 라운드가 연속 2번 나올 때까지**(최대
|
||||||
|
6라운드) 반복해 수렴시킨다. 사용자가 정확성을 시간보다 우선한다고
|
||||||
|
명시했으므로 기본 워크플로 크기 가이드라인(15 에이전트 이하)을 의도적으로
|
||||||
|
넘을 수 있음 — 이 워크플로 자체가 그 예외 대상. Workflow는 백그라운드로
|
||||||
|
돌고 완료 시 알림이 오므로, 호출 직후 대화를 막지 말고 진행 상황만
|
||||||
|
알린 뒤 알림을 기다릴 것. 알림이 오면 `python3 .claude/tools/doc-check.py`로
|
||||||
|
ERROR 0을 최종 확인한 뒤 평소 커밋 절차(git status/diff 검토, 메시지 작성)로
|
||||||
|
넘어갈 것 — **실제 `git commit`은 이 워크플로 안이 아니라 항상 메인 세션이
|
||||||
|
직접 함**(커밋 전 diff 재검토는 대화형 맥락이 필요해서 워크플로에 위임 안 함).
|
||||||
|
- **문서가 쌓이면서 모순/중복/stale 마커가 생기기 쉬움 — 주기적으로 감사할
|
||||||
|
것.** 다만 위 체크리스트+`doc-check.py`+`quad-doc-auditor`가 자리잡으면
|
||||||
|
이 감사는 "기계도 서브에이전트도 못 보는 것"(설계 자체의 자기모순, 의사코드
|
||||||
|
손 트레이싱)에만 집중하면 됨. 2026-08-04 세션에 실제로 전체 `.claude/`
|
||||||
|
코퍼스에서 이런 문제가 다수 발견되어 정리함(`.claude/session-summary.md` 참고) —
|
||||||
|
여러 라운드에 걸쳐 같은 문서를 계속 고치다 보면 "정정됨" 표시가 원래
|
||||||
|
문장에 안 반영되고 방치되는 패턴이 반복되니, 큰 방향 전환이 있을 때마다
|
||||||
|
관련 문서 전체를 훑어 확인할 것.
|
||||||
|
- **Roblox Studio MCP 연결 시 주의**: Studio는 잘 죽는 편 — 죽었을 때 살리려고
|
||||||
|
위험한 명령을 반복 시도하지 말 것. 그런 상황이면 MCP 없이 할 수 있는 작업만
|
||||||
|
하거나 대기. 연결 방법은 `HUMAN_TODO.md` 1번 항목 참고(사용자가 Studio에서
|
||||||
|
베타 기능을 켜줘야 함).
|
||||||
|
- **`SAFETY.md` 반드시 지킬 것** — (1) GitHub 등 외부 git 호스팅에 이 레포를
|
||||||
|
push하지 말 것, 모델의 git 작업 공간은 사용자가 별도로 마련해줄 제한 계정
|
||||||
|
(예: git.qwreey.moe) 전용으로 국한됨 — 그 계정/원격이 설정되기 전까지는
|
||||||
|
**로컬 git 커밋까지만** 하고 원격 추가/푸시는 하지 말 것. (2) Roblox Studio는
|
||||||
|
메인 계정이 아닌 별도 계정으로만 사용 — 로그인 계정 전환을 사용자가 안 해줬다면
|
||||||
|
Studio 관련 작업(MCP 연결 등)을 진행하지 말고 대기.
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ ROADMAP 항목 근거인지, 어떻게 실행하는지, 실행 후 뭘 확인해
|
||||||
| `07-relate-weak-table-gc.luau` | `Relate`의 lazy 서브테이블 생성 + weak-key GC가 실제로 동작하는지 | `relate-plan.md` "M2 착수 시 실측 확인" **[2026-08-13 보강]** 4번 섹션 신설 — `_countEntries()`(테스트 전용) + weak-value canary로 **"inst가 죽으면 중첩 StrongMap 안의 payload까지 연쇄 GC되는가"를 직접 검증**(원래는 sanity check만 하고 헤더의 핵심 주장은 미검증이었음). 파일이 스스로 적어둔 "weak table 엔트리를 셀 표준 API가 없다"는 전제도 틀렸음 — outer가 `__mode="k"`라 GC 후 `pairs`에서 사라짐 |
|
| `07-relate-weak-table-gc.luau` | `Relate`의 lazy 서브테이블 생성 + weak-key GC가 실제로 동작하는지 | `relate-plan.md` "M2 착수 시 실측 확인" **[2026-08-13 보강]** 4번 섹션 신설 — `_countEntries()`(테스트 전용) + weak-value canary로 **"inst가 죽으면 중첩 StrongMap 안의 payload까지 연쇄 GC되는가"를 직접 검증**(원래는 sanity check만 하고 헤더의 핵심 주장은 미검증이었음). 파일이 스스로 적어둔 "weak table 엔트리를 셀 표준 API가 없다"는 전제도 틀렸음 — outer가 `__mode="k"`라 GC 후 `pairs`에서 사라짐 |
|
||||||
| `08-type-source-satisfies-state.luau` (타입체크 전용) | `Source<T>`가 `State<T>`를 구조적으로 만족하는 제네릭 타입이 솔버에서 안전한지 | `base/source-state-plan.md` "Source가 State를 만족함", ROADMAP M0-2 |
|
| `08-type-source-satisfies-state.luau` (타입체크 전용) | `Source<T>`가 `State<T>`를 구조적으로 만족하는 제네릭 타입이 솔버에서 안전한지 | `base/source-state-plan.md` "Source가 State를 만족함", ROADMAP M0-2 |
|
||||||
| `09-type-modifier-overridden-subtype.luau` (타입체크 전용) | `FrameModifier <: GuiObjectModifier`처럼 서브타입 관계인 Modifier를 `Overridden`으로 섞을 때 타입이 통과하는지 | `modifier-plan.md` 9-2번, ROADMAP M7 |
|
| `09-type-modifier-overridden-subtype.luau` (타입체크 전용) | `FrameModifier <: GuiObjectModifier`처럼 서브타입 관계인 Modifier를 `Overridden`으로 섞을 때 타입이 통과하는지 | `modifier-plan.md` 9-2번, ROADMAP M7 |
|
||||||
| `10-roblox-studio-checks.server.luau` (Studio 전용) | **[⚠️ 2026-08-14 다섯 번째 세션: A 섹션이 폐기된 모델을 검증 중 → `rewrite-required/`, 열한 번째 세션에 `canBound` 재도입으로 재작성 사유 하나 더 추가]** (A) `bindLifetime`/`unbindLifetime`/`canBound`/`canExecute`의 gcconn 트릭 + 이중 바인딩 게이트(Destroy 시 Connected 전환 포함), (B) Attribute의 Instance 참조 타입 지원, (C) CollectionService 태그/GetTagged 왕복. **A는 재작성 대상** — 파일 속 옛 `canBound`(9차 세션 정의)와 `bindLifetime`의 `value.Subscribed = true` 세팅, 2-인자 `canExecute(inst, value)`는 전부 낡음(현재 게이트는 이중 바인딩 확인은 `canBound(v)`, emit 게이팅은 `canExecute(v)` — 둘 다 `value` 단독 1-인자로 비공개 헬퍼를 공유, gcconn/gchold는 **Instance 생성 시점**에 생성). **[2026-08-13]** A 섹션 앞부분(ClassName 신호 미발화, Destroy 시 Connected 즉시 전환)은 사용자 자작 스크립트로 부분 확인됐고 **새 모델에서도 그대로 유효**(오히려 더 중요 — `canBound`/`canExecute`가 `.Connected`를 직접 읽는 게 leaf 경로 판정의 전부), `audit/gcconn-trick-verification.md` 참고. 이중 바인딩 게이트/재바인딩 허용/B/C는 이 공식 파일로 아직 확인 안 됨 | `lifecycle-pattern.md` "`bindLifetime`/`canBound`/`canExecute`/`unbindLifetime` — 확정", `archive/canexecute-inst-arg-reversed.md`, `source-state-plan.md` "이중 바인딩 금지", CLAUDE.md 2026-08-06 세션, `debug-tooling-plan.md` |
|
| `10-roblox-studio-checks.server.luau` (Studio 전용) | **[⚠️ 2026-08-14 다섯 번째 세션: A 섹션이 폐기된 모델을 검증 중 → `rewrite-required/`, 열한 번째 세션에 `canBound` 재도입으로 재작성 사유 하나 더 추가]** (A) `bindLifetime`/`unbindLifetime`/`canBound`/`canExecute`의 gcconn 트릭 + 이중 바인딩 게이트(Destroy 시 Connected 전환 포함), (B) Attribute의 Instance 참조 타입 지원, (C) CollectionService 태그/GetTagged 왕복. **A는 재작성 대상** — 파일 속 옛 `canBound`(9차 세션 정의)와 `bindLifetime`의 `value.Subscribed = true` 세팅, 2-인자 `canExecute(inst, value)`는 전부 낡음(현재 게이트는 이중 바인딩 확인은 `canBound(v)`, emit 게이팅은 `canExecute(v)` — 둘 다 `value` 단독 1-인자로 비공개 헬퍼를 공유, gcconn/gchold는 **Instance 생성 시점**에 생성). **[2026-08-13]** A 섹션 앞부분(ClassName 신호 미발화, Destroy 시 Connected 즉시 전환)은 사용자 자작 스크립트로 부분 확인됐고 **새 모델에서도 그대로 유효**(오히려 더 중요 — `canBound`/`canExecute`가 `.Connected`를 직접 읽는 게 leaf 경로 판정의 전부), `audit/gcconn-trick-verification.md` 참고. 이중 바인딩 게이트/재바인딩 허용/B/C는 이 공식 파일로 아직 확인 안 됨 | `lifecycle-pattern.md` "`bindLifetime`/`canBound`/`canExecute`/`unbindLifetime` — 확정", `archive/canexecute-inst-arg-reversed.md`, `source-state-plan.md` "이중 바인딩 금지", `.claude/session-summary.md` 2026-08-06 세션, `debug-tooling-plan.md` |
|
||||||
| `11-modifier-illegal-value-error.luau` | Modifier 필드에 Ref/PreRef/Observer/Effect/Slot/Modifier가 들어오면 즉시 error, State/Source가 확정하는 값이 Modifier면 즉시 error(2026-08-09 세션에 "UB"에서 전환된 규칙) | `modifier-plan.md` "핸들러 계층 값 즉시 error" 절 + 7번 절 |
|
| `11-modifier-illegal-value-error.luau` | Modifier 필드에 Ref/PreRef/Observer/Effect/Slot/Modifier가 들어오면 즉시 error, State/Source가 확정하는 값이 Modifier면 즉시 error(2026-08-09 세션에 "UB"에서 전환된 규칙) | `modifier-plan.md` "핸들러 계층 값 즉시 error" 절 + 7번 절 |
|
||||||
| `12-type-attribute-generic-key-narrowing.luau` (타입체크 전용) | `[AttributeKey<<T>> "name"] = value`(구 `Attribute<<T>>`)처럼 제네릭 DI 키를 쓸 때 `value`의 타입이 실제로 `T`로 좁혀지는지 — base 문서 자신이 "미검증"이라 명시한 항목 | `attribute-plan.md` "[실측 필요, M0/M10]" (2026-08-09 열한 번째 세션 신설) |
|
| `12-type-attribute-generic-key-narrowing.luau` (타입체크 전용) | `[AttributeKey<<T>> "name"] = value`(구 `Attribute<<T>>`)처럼 제네릭 DI 키를 쓸 때 `value`의 타입이 실제로 `T`로 좁혀지는지 — base 문서 자신이 "미검증"이라 명시한 항목 | `attribute-plan.md` "[실측 필요, M0/M10]" (2026-08-09 열한 번째 세션 신설) |
|
||||||
| `13-type-ref-preref-subtype.luau` | (A, 타입) `PreRef<T>`가 `Ref<T>`를 구조적으로 만족하는지, (B, 런타임) `isRef`/`isPreRef` 합성이 재정정대로 동작하는지(`isRef(preRefInstance)`가 이제 `true`) + Leaf 핸들러가 `isRef(v) and not isPreRef(v)`로 명시적으로 좁혀야 하는 이유. **[2026-08-14 아홉 번째 세션] 재작성 시 `PostRef`도 같이 커버할 것** — 같은 `Ref` 런타임 재사용 + 브랜드 태그만 다른 형제라 A/B 둘 다 그대로 확장되고, Leaf predicate도 `isRef(v) and not isPreRef(v) and not isPostRef(v)`로 늘어남 | `brand-plan.md`의 `Brand` 절(2026-08-09 열한 번째 세션 재정정) |
|
| `13-type-ref-preref-subtype.luau` | (A, 타입) `PreRef<T>`가 `Ref<T>`를 구조적으로 만족하는지, (B, 런타임) `isRef`/`isPreRef` 합성이 재정정대로 동작하는지(`isRef(preRefInstance)`가 이제 `true`) + Leaf 핸들러가 `isRef(v) and not isPreRef(v)`로 명시적으로 좁혀야 하는 이유. **[2026-08-14 아홉 번째 세션] 재작성 시 `PostRef`도 같이 커버할 것** — 같은 `Ref` 런타임 재사용 + 브랜드 태그만 다른 형제라 A/B 둘 다 그대로 확장되고, Leaf predicate도 `isRef(v) and not isPreRef(v) and not isPostRef(v)`로 늘어남 | `brand-plan.md`의 `Brand` 절(2026-08-09 열한 번째 세션 재정정) |
|
||||||
|
|
@ -162,7 +162,7 @@ GC가 안 풂" 주장이 지금까지 공식 문서 인용으로만 뒷받침돼
|
||||||
Luau로 재현해본 적이 없었던 갭 — `Slot`의 `kSlotMap`/`slotOwner` GC 수정
|
Luau로 재현해본 적이 없었던 갭 — `Slot`의 `kSlotMap`/`slotOwner` GC 수정
|
||||||
사례(session 13/14) 전체가 이 사례 하나에 기대고 있어 우선순위 있게 추가.
|
사례(session 13/14) 전체가 이 사례 하나에 기대고 있어 우선순위 있게 추가.
|
||||||
|
|
||||||
**9차 (2026-08-13)**: CLAUDE.md 세션 8~21(대부분 2026-08-12) 전체를 대상으로
|
**9차 (2026-08-13)**: `.claude/session-summary.md` 세션 8~21(대부분 2026-08-12) 전체를 대상으로
|
||||||
"새 메커니즘 중 실 Luau로 안 부딪혀본 게 더 있는가"를 재점검 — Ref/Slot의
|
"새 메커니즘 중 실 Luau로 안 부딪혀본 게 더 있는가"를 재점검 — Ref/Slot의
|
||||||
`Relate` diff 기반 retract(세션 8/9)는 03/04번이 이미 검증한 것과 같은
|
`Relate` diff 기반 retract(세션 8/9)는 03/04번이 이미 검증한 것과 같은
|
||||||
클래스의 재귀 dispatch/체인 로직이라 스킵. 반면 Tag 참조 카운트(세션 11/16)
|
클래스의 재귀 dispatch/체인 로직이라 스킵. 반면 Tag 참조 카운트(세션 11/16)
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,14 @@
|
||||||
gchold를 배열이 아니라 value를 키로 쓰는 테이블로 바꾼 것까지 반영
|
gchold를 배열이 아니라 value를 키로 쓰는 테이블로 바꾼 것까지 반영
|
||||||
— 이전 버전의 이 스크립트는 array 기반 gchold였음, 이번에 정정).
|
— 이전 버전의 이 스크립트는 array 기반 gchold였음, 이번에 정정).
|
||||||
B) Attribute가 Instance 참조 타입을 실제로 지원하는가(ObjectValue
|
B) Attribute가 Instance 참조 타입을 실제로 지원하는가(ObjectValue
|
||||||
없이 Ref 용도로 쓸 수 있다는 CLAUDE.md 서술의 실측).
|
없이 Ref 용도로 쓸 수 있다는 .claude/session-summary.md 서술의 실측).
|
||||||
C) CollectionService 태그 + GetTagged 왕복이 quad-debug가 기대하는
|
C) CollectionService 태그 + GetTagged 왕복이 quad-debug가 기대하는
|
||||||
대로 동작하는가(태그 추가/제거, GetTagged로 조회).
|
대로 동작하는가(태그 추가/제거, GetTagged로 조회).
|
||||||
|
|
||||||
배경: .claude/base/lifecycle-pattern.md "bindLifetime/canExecute/
|
배경: .claude/base/lifecycle-pattern.md "bindLifetime/canExecute/
|
||||||
unbindLifetime — 확정" 절 + "실측 필요(M0/M2)" 캐비엇,
|
unbindLifetime — 확정" 절 + "실측 필요(M0/M2)" 캐비엇,
|
||||||
.claude/base/bind-system-plan.md "이중 바인딩 금지" 절(canBound),
|
.claude/base/bind-system-plan.md "이중 바인딩 금지" 절(canBound),
|
||||||
CLAUDE.md 2026-08-06 세션의 Attribute Instance 참조 지원 언급,
|
.claude/session-summary.md 2026-08-06 세션의 Attribute Instance 참조 지원 언급,
|
||||||
.claude/research/debug-tooling-plan.md의 CollectionService 노출 방식.
|
.claude/research/debug-tooling-plan.md의 CollectionService 노출 방식.
|
||||||
|
|
||||||
실행 방법:
|
실행 방법:
|
||||||
|
|
|
||||||
93
.claude/project-context.md
Normal file
93
.claude/project-context.md
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
# 프로젝트 컨텍스트
|
||||||
|
|
||||||
|
루트 `CLAUDE.md`가 `@import` 하는 파일. 폴더별 **상세** 색인은
|
||||||
|
`.claude/README.md`가 소스 — 여기선 중복 서술하지 말고 가리키기만 할 것.
|
||||||
|
|
||||||
|
## 이 프로젝트가 뭔지
|
||||||
|
|
||||||
|
Roblox 엔진에서 동작하는 DOMless UI 렌더러 **quad**를 처음부터 다시 짜는
|
||||||
|
프로젝트. 목표는 개별 프로덕트가 아니라 **라이브러리**로서의 코드 퀄리티와
|
||||||
|
지속 가능성 — 빠른 이터레이션보다 정확성/설계 정합성이 우선. 작업 기간은
|
||||||
|
길게 잡음.
|
||||||
|
|
||||||
|
**지금은 설계/계획 단계이고 구현은 아직 시작 전** — 저장소 루트에 실제 소스
|
||||||
|
코드(`src/` 등)가 없음. 핵심 아키텍처(Store 책임 분리, `process`/`retract`
|
||||||
|
디스패치 모델, Store/State/Source 온톨로지, 소스 트리 구조, Modifier 메커니즘,
|
||||||
|
컴포넌트=플레인 함수, 컴포넌트 경계 modifier/Ref 전달)는 전부 `.claude/base/`에
|
||||||
|
문서로 확정돼 있음 — 먼저 `.claude/base/architecture.md`를 읽을 것. 사용자가
|
||||||
|
직접 "지금 quad에서 가장 문제되는 부분"으로 지목했던 컴포넌트화(특히
|
||||||
|
modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션에서 수렴
|
||||||
|
완료(`base/component-composition-plan.md`) — 남은 핵심 설계 질문은 없고,
|
||||||
|
용어 정리(진행 중)와 실제 스캐폴딩만 남음, 아래 "지금 할 일" 참고.
|
||||||
|
|
||||||
|
이전에 시도했다 폐기한 v2 재작성 시도(`.claude/initreq/quad2-try`)도 리서치
|
||||||
|
완료 — OOP 상속/커스텀 파서/Slot 스텁/`Pipe` copy-on-write 절충안은 확인된
|
||||||
|
죽은 접근이라 반복 조사 금지(`base/bind-system-plan.md` "확정된 것" 절 참고).
|
||||||
|
|
||||||
|
## 계획 문서 구조
|
||||||
|
|
||||||
|
`.claude/README.md`가 색인. 요약:
|
||||||
|
- **[2026-08-16]** 루트 `CLAUDE.md`는 39줄짜리 진입점일 뿐이고, 실제 내용은
|
||||||
|
`.claude/conventions.md`(관례·작업 방식) / 이 문서 / `.claude/todos.md`
|
||||||
|
(지금 할 일)로 쪼개져 `@import`로 다시 합쳐짐. `.claude/session-summary.md`
|
||||||
|
(세션 요약 색인)만 **import 안 됨** — 필요할 때 직접 열 것.
|
||||||
|
- `.claude/base/` — 확정된 아키텍처/컨텍스트, plan/done 개념 없음. 먼저
|
||||||
|
`.claude/base/architecture.md`를 읽을 것.
|
||||||
|
- `.claude/reference/` — **[2026-08-07 신설]** base처럼 확정된 건 아니지만
|
||||||
|
base 문서가 근거로 인용하는 온디맨드 참고 자료(v1 내부 동작 스냅샷,
|
||||||
|
Fusion/Vide 비교 리서치) — 항상 읽을 필요는 없고 인용될 때만 열어볼 것.
|
||||||
|
- `.claude/research/` — 아직 착수 전, 사용자와 상의 필요한 설계 논의.
|
||||||
|
`debug-tooling-plan.md`/
|
||||||
|
`documentation-plan.md`/`documentation-content-map.md`/
|
||||||
|
`framework-comparison-findings.md`/`additional-primitives-plan.md`(2026-08-09
|
||||||
|
세 번째 세션에 마지막 열린 항목까지 전부 해소, 이제 배경 자료용)/
|
||||||
|
`pre-implementation-audit.md`/`v1-compat-plan.md`
|
||||||
|
— 전부 후순위(`tween-plan.md`는 2026-08-12 세션에 마지막 열린 항목까지
|
||||||
|
전부 해소돼 `base/`로 승격, 이미 생성된 인스턴스 재바인드는
|
||||||
|
2026-08-14 세션에 기각돼 `archive/existing-instance-bind-rejected.md`로 이전, 더 이상 여기 없음). 최신 목록·우선순위는
|
||||||
|
`.claude/README.md`가 소스, 여기서 개수 반복 안 함(과거에 "두 개뿐"이라
|
||||||
|
적어놨다가 새 문서 추가될 때마다 안 갱신되는 패턴이 반복돼서 아예 안
|
||||||
|
세기로 함).
|
||||||
|
- `.claude/luau-test/` — **[2026-08-09 신설]** "추론만으로 확정하고 실제
|
||||||
|
Luau로 부딪혀본 적 없는 것"을 미리 검증하는 독립 실행 스파이크 20개
|
||||||
|
(`luau <파일>` / `luau-analyze <파일>`). **상태의 소스는 항상 `STATUS.md`**
|
||||||
|
(pass / 사람 결정 필요 / 스파이크 깨짐 / 미실행, 폴더 구조 자체가 상태),
|
||||||
|
각 파일이 뭘 왜 검증하는지는 `README.md`. 2026-08-13에 첫 실측 완료(당시
|
||||||
|
런타임 12개 전원 통과) — 이후 여러 세션에 걸쳐 재설계로 몇 건이 추가로
|
||||||
|
`rewrite-required/`에 합류했으니 **지금 몇 개가 어디 있는지는 여기서
|
||||||
|
나열 안 하고 `STATUS.md`로 미룸**(나열하다 stale해지는 패턴이 실제로
|
||||||
|
반복됐음, 아래 "지금 할 일" 0번 참고).
|
||||||
|
- `.claude/audit/` — **[2026-08-13 신설]** 스파이크를 실제로 돌린 **실측
|
||||||
|
결과** 기록(계획 아님). 부분 확인도 있는 그대로 남김 — **지금 몇 개가
|
||||||
|
있는지·각각 뭘 확인했는지는 여기서 나열 안 하고 `.claude/README.md`의
|
||||||
|
`audit/` 행으로 미룸**(luau-test와 같은 이유 — 나열하다 새 폴더가
|
||||||
|
추가될 때마다 stale해지는 패턴이 실제로 반복됐음, 가장 최근엔
|
||||||
|
2026-08-15에 이 목록이 3개에서 멈춰 있는 걸 `/code-review`가 발견).
|
||||||
|
`type-recursion-issue/`만 참고로 짚으면: **[13차 세션]** 0-Y 재실측
|
||||||
|
전체 — `REPORT.md` + `spikes/` 44개, **스크립트를 같이 두는** 예외적
|
||||||
|
구성(판정이 "여러 formulation 대조"라 개별 파일을 직접 돌려야 재현됨),
|
||||||
|
결론은 `base/typing-limits.md`로 승격 — 이후 신설된 폴더들도 같은
|
||||||
|
구성 관례를 따름(`type-recursive-issue-with-typeof/`,
|
||||||
|
`type-recursive-issue-try-callback/` 등).
|
||||||
|
- `.claude/qa-request/`, `.claude/feedback/` — 구현 시작되면 쓰기 시작함,
|
||||||
|
지금은 비어있음. `.claude/archive/`는 원래 같은 취급이었으나
|
||||||
|
2026-08-06 세 번째 세션부터 **완전히 뒤집힌 설계 결정을 원문+역전
|
||||||
|
이유+diff와 함께 보존하는 용도로도 사용 시작**(구현 완료 대상만이
|
||||||
|
아님) — `archive/store-source-proxy-reversed.md`가 첫 사례, 나중
|
||||||
|
`quadnomicon` 콘텐츠 소재로 재사용 예정.
|
||||||
|
- `.claude/session/` — **[2026-08-11 신설]** 세션별 상세 로그 원문(시행착오·
|
||||||
|
정정 전 서술 포함, `quadnomicon` 개발로그 소재용) — 루트 `CLAUDE.md`가 3000줄
|
||||||
|
넘게 불어나 성능 저하를 유발해서 분리함. `.claude/session-summary.md`의 각
|
||||||
|
항목이 여기로 링크. **항상 읽을 필요 없음** — 특정 결정의 논의 과정/시행착오가
|
||||||
|
궁금할 때만 열어볼 것, 지금 유효한 설계는 항상 `base/`가 소스.
|
||||||
|
- `.claude/initreq/` — 클론해둔 참고 레포(quad v1, Fusion, Vide, rbvm, tbox,
|
||||||
|
code-docker) + PA님 실 코드(`artworks/`) + 원본 요청. **읽기 전용,
|
||||||
|
`.gitignore`로 커밋 제외됨** — 내용을 다른 곳으로 옮기지 말고 항상 원본
|
||||||
|
그대로 둘 것. 리서치가 더 필요하면 이 폴더를 다시 파고들 것.
|
||||||
|
- `.claude/question.md` — 사용자가 답해야 할 질문 전체 취합(우선순위순).
|
||||||
|
- 루트 `ROADMAP.md` — 설계 단계 종료 후 실제 구현 순서(M0, M1, ... 마일스톤 +
|
||||||
|
todo 체크박스). "무엇을 확정했는가"는 `.claude/base/`가 소스, "어떤 순서로
|
||||||
|
만드는가"는 이 문서가 소스 — 헷갈리지 말 것.
|
||||||
|
- 루트 `HUMAN_TODO.md` — 사람만 할 수 있는 일(로컬 GUI 조작, 스케줄/루프
|
||||||
|
설정 등).
|
||||||
|
|
||||||
|
|
@ -205,6 +205,6 @@
|
||||||
> `research/pre-implementation-audit.md`가 원본이자 최신.
|
> `research/pre-implementation-audit.md`가 원본이자 최신.
|
||||||
|
|
||||||
---
|
---
|
||||||
전체 순서/우선순위는 루트 `CLAUDE.md`가 최종 소스. 확정된 것들의 문서
|
전체 순서/우선순위는 `.claude/todos.md`가 최종 소스. 확정된 것들의 문서
|
||||||
색인은 `.claude/README.md`의 `base/` 표(예전에 이 문서 맨 아래에 있던
|
색인은 `.claude/README.md`의 `base/` 표(예전에 이 문서 맨 아래에 있던
|
||||||
요약표는 그것과 중복이라 archive로 옮김).
|
요약표는 그것과 중복이라 archive로 옮김).
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
# 문서 stale 감소용 include 도구 — `doc-include.py` (가칭)
|
# 문서 stale 감소용 include 도구 — `doc-include.py` (가칭)
|
||||||
|
|
||||||
**상태**: research — 2026-08-14 세션에 아이디어 확정, **플랜만 초안, 사용자가
|
**상태**: research — 2026-08-14 세션에 아이디어 확정, **[2026-08-16 갱신]**
|
||||||
다듬을 예정(내일 처리)**. 구현 착수 전.
|
CLAUDE.md 분할로 파일럿 설계가 **단방향 생성으로 단순화**됨(아래 "파일럿
|
||||||
|
범위" 참고). 구현 착수 전.
|
||||||
|
|
||||||
|
> **[2026-08-16] 이 문서의 원 설계에서 절반이 불필요해졌음.** 원래는 원본에
|
||||||
|
> `<!--#summary-->`, 인용처에 `<!--#include-->` 두 종류 마커를 두는 **양방향**
|
||||||
|
> 설계였는데, 같은 날 CLAUDE.md를 분할하면서 세션 히스토리가 독립 파일
|
||||||
|
> (`.claude/session-summary.md`)이 됐음 — 목적지가 "손으로 쓴 파일 속 구간"이
|
||||||
|
> 아니라 **통째로 생성되는 파일**이 되면서 목적지 마커가 필요 없어졌다. 남는
|
||||||
|
> 건 원본 쪽 마커 + 단방향 생성기뿐. 아래 본문은 이 정정을 반영해 갱신했다.
|
||||||
|
|
||||||
## 배경
|
## 배경
|
||||||
|
|
||||||
|
|
@ -45,38 +53,46 @@
|
||||||
Python 표준 라이브러리만으로 신설. `--write`(갱신 삽입)/`--check`(어긋나면
|
Python 표준 라이브러리만으로 신설. `--write`(갱신 삽입)/`--check`(어긋나면
|
||||||
ERROR, `doc-check.py` 파이프라인에 편입) 두 모드.
|
ERROR, `doc-check.py` 파이프라인에 편입) 두 모드.
|
||||||
|
|
||||||
## 파일럿 범위 — CLAUDE.md 세션 히스토리부터
|
## 파일럿 범위 — `.claude/session-summary.md` 전체 생성
|
||||||
|
|
||||||
사용자가 지목한 이유: 세션 히스토리 항목은 서로 독립적(과거 기록이라
|
사용자가 지목한 이유: 세션 히스토리 항목은 서로 독립적(과거 기록이라
|
||||||
다른 문서가 그 문장을 인용하는 경우가 거의 없음)이라 이 도구가 버그가
|
다른 문서가 그 문장을 인용하는 경우가 거의 없음)이라 이 도구가 버그가
|
||||||
있어도 **부작용이 다른 곳으로 안 번짐** — 첫 적용 대상으로 가장 안전.
|
있어도 **부작용이 다른 곳으로 안 번짐** — 첫 적용 대상으로 가장 안전.
|
||||||
|
|
||||||
- 지금 구조: `.claude/session/YYYY-MM-DD-NN-slug.md`에 세션 원문 전체가
|
- **[2026-08-16 기준] 지금 구조**: `.claude/session/YYYY-MM-DD-NN-slug.md`에
|
||||||
있고, `CLAUDE.md`의 "세션 히스토리" 절엔 사람이 손으로 압축한 2~4줄
|
세션 원문 전체가 있고, `.claude/session-summary.md`(CLAUDE.md 분할 전엔
|
||||||
요약 + 링크가 별도로 적혀있음(둘이 물리적으로 분리된 텍스트라 한쪽만
|
`CLAUDE.md`의 "세션 히스토리" 절이었음)에 사람이 손으로 압축한 2~4줄
|
||||||
갱신되면 어긋날 수 있음 — 실제로 아직 발생한 적은 없지만 구조적으로
|
요약 + 링크가 **별도 텍스트로** 적혀있음 — 한쪽만 갱신되면 어긋날 수
|
||||||
가능한 상태).
|
있는 구조.
|
||||||
- 적용 후: 각 세션 파일 안에 "이 요약이 CLAUDE.md에 들어갈 정본"이라고
|
- **적용 후**: 각 세션 파일 안에 "이게 이 세션의 정본 요약"이라고 표시하는
|
||||||
표시하는 마커 블록을 신설(**새로 요약을 쓸 필요 없음** — 지금
|
마커 블록을 신설(**새로 요약을 쓸 필요 없음** — 지금 `session-summary.md`에
|
||||||
`CLAUDE.md`에 이미 있는 압축 요약을 그대로 그 블록 안으로 옮기면 됨).
|
이미 있는 압축 요약을 그대로 그 블록 안으로 옮기면 됨). 생성기가 세션
|
||||||
`CLAUDE.md` 쪽엔 대응하는 include 마커만 남기고, `doc-include.py --write`가
|
파일들을 파일명 순으로 훑어 마커 블록을 모아 `session-summary.md`를
|
||||||
두 마커 사이 콘텐츠를 세션 파일에서 가져와 채움.
|
**통째로 다시 씀**. 그 시점부터 `session-summary.md`는 직접 편집 금지
|
||||||
|
대상이 되고(파일 상단에 그렇게 명시), 요약을 고치려면 세션 파일을 고침.
|
||||||
|
|
||||||
|
### 왜 목적지 마커가 필요 없어졌나
|
||||||
|
|
||||||
|
원안은 목적지(`CLAUDE.md`)가 손으로 관리되는 파일이라, 그 안의 특정
|
||||||
|
구간만 골라 갱신하려고 `<!--#include-->` 마커가 필요했음. 분할 후엔
|
||||||
|
목적지가 **파일 통째로 파생 데이터**라 "어디를 갱신할지"를 표시할 이유가
|
||||||
|
없음 — 파일 전체를 덮어쓰면 됨. 부품이 절반으로 줄고, "목적지 마커가
|
||||||
|
손실되면?" 같은 실패 모드도 같이 사라짐.
|
||||||
|
|
||||||
## 마커 문법 (초안 — 사용자가 확정할 것)
|
## 마커 문법 (초안 — 사용자가 확정할 것)
|
||||||
|
|
||||||
```
|
```
|
||||||
# 세션 파일(.claude/session/2026-08-14-14-....md) 안:
|
# 세션 파일(.claude/session/2026-08-14-14-....md) 안:
|
||||||
<!--#summary:2026-08-14-14-->
|
<!--#summary-->
|
||||||
**2026-08-14 열네 번째 세션 — ...** (`session/2026-08-14-14-....md`)
|
**2026-08-14 열네 번째 세션 — ...** (`session/2026-08-14-14-....md`)
|
||||||
... 2~4줄 압축 요약 ...
|
... 2~4줄 압축 요약 ...
|
||||||
<!--#/summary-->
|
<!--#/summary-->
|
||||||
|
|
||||||
# CLAUDE.md "세션 히스토리" 절 안:
|
|
||||||
<!--#include:2026-08-14-14 from=session/2026-08-14-14-....md-->
|
|
||||||
(doc-include.py --write가 여기를 원본 summary 블록 내용으로 갱신)
|
|
||||||
<!--#/include-->
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`session-summary.md` 쪽엔 마커가 없음 — 생성기가 헤더 + 각 세션 블록을
|
||||||
|
파일명 순으로 이어 붙여 전체를 씀. id도 불필요해짐(파일명이 곧 순서이자
|
||||||
|
식별자).
|
||||||
|
|
||||||
## 열린 질문 (사용자가 다듬을 것)
|
## 열린 질문 (사용자가 다듬을 것)
|
||||||
|
|
||||||
1. 마커 문법 자체(위 초안 확정 여부, id 네이밍 규칙 — 날짜+세션번호로
|
1. 마커 문법 자체(위 초안 확정 여부, id 네이밍 규칙 — 날짜+세션번호로
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
+ 백엔드별 트랙 분리)이 확정된 뒤, 실제로 각 축에 뭘 채울지 `.claude/base/*.md`
|
+ 백엔드별 트랙 분리)이 확정된 뒤, 실제로 각 축에 뭘 채울지 `.claude/base/*.md`
|
||||||
전체 + 관련 `research/*.md`(tween-plan, ui-shorthand-plan)를 2026-08-06 세션에
|
전체 + 관련 `research/*.md`(tween-plan, ui-shorthand-plan)를 2026-08-06 세션에
|
||||||
6개 에이전트로 병렬 서베이해 분류함. **아직 문서를 쓰라는 뜻 아님** — 착수
|
6개 에이전트로 병렬 서베이해 분류함. **아직 문서를 쓰라는 뜻 아님** — 착수
|
||||||
시점은 여전히 구현 우선(`CLAUDE.md` "지금 할 일" 1번). 나중에 실제 문서화를
|
시점은 여전히 구현 우선(`.claude/todos.md` 1번). 나중에 실제 문서화를
|
||||||
시작할 때 이 맵을 목차/우선순위표로 쓰면 됨.
|
시작할 때 이 맵을 목차/우선순위표로 쓰면 됨.
|
||||||
|
|
||||||
> **⚠️ [2026-08-14 아홉 번째 세션 감사] 이 서베이는 2026-08-06 시점의
|
> **⚠️ [2026-08-14 아홉 번째 세션 감사] 이 서베이는 2026-08-06 시점의
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ Roblox 코드(Frame 만들기 등) 안에서 자연스럽게 등장시키고,
|
||||||
하나)으로 구조화하고, "quad 코어가 뭔지"는 심화에서만 다룸.
|
하나)으로 구조화하고, "quad 코어가 뭔지"는 심화에서만 다룸.
|
||||||
|
|
||||||
**착수 시점**: 위 1~3번 항목과 동일하게 지금 당장 설계/작성할 필요는
|
**착수 시점**: 위 1~3번 항목과 동일하게 지금 당장 설계/작성할 필요는
|
||||||
없음(`CLAUDE.md` "지금 할 일" 1번 — 구현 착수가 최우선). 이 0번 항목은
|
없음(`.claude/todos.md` 1번 — 구현 착수가 최우선). 이 0번 항목은
|
||||||
"만약 시작한다면 이런 구조로"에 대한 합의이지, 착수 신호는 아님.
|
"만약 시작한다면 이런 구조로"에 대한 합의이지, 착수 신호는 아님.
|
||||||
|
|
||||||
**콘텐츠 분류 완료(2026-08-06)**: 위 3축을 실제로 뭘로 채울지
|
**콘텐츠 분류 완료(2026-08-06)**: 위 3축을 실제로 뭘로 채울지
|
||||||
|
|
@ -173,9 +173,9 @@ UICorner/UIPadding/UIScale 숏핸드가 만드는 자식)는 `_`나 `QUAD_` 같
|
||||||
|
|
||||||
## 다음 단계
|
## 다음 단계
|
||||||
|
|
||||||
셋 다 지금 당장 설계할 필요는 없음(`CLAUDE.md` "지금 할 일" 1번 —
|
셋 다 지금 당장 설계할 필요는 없음(`.claude/todos.md` 1번 —
|
||||||
구현 착수가 최우선). 사용자 판단이 필요한 것:
|
구현 착수가 최우선). 사용자 판단이 필요한 것:
|
||||||
- 이걸 `.claude/question.md`/`CLAUDE.md`에 정식 백로그 항목으로 올릴지,
|
- 이걸 `.claude/question.md`/`.claude/todos.md`에 정식 백로그 항목으로 올릴지,
|
||||||
아니면 이 파일 하나로 충분한지.
|
아니면 이 파일 하나로 충분한지.
|
||||||
- 착수 시점 — quad-debug처럼 "개발 상당 부분 끝난 뒤"로 볼지, 아니면
|
- 착수 시점 — quad-debug처럼 "개발 상당 부분 끝난 뒤"로 볼지, 아니면
|
||||||
M1(스캐폴딩) 즈음부터 조금씩 곁들일지(네이밍 컨벤션은 특히 초기부터
|
M1(스캐폴딩) 즈음부터 조금씩 곁들일지(네이밍 컨벤션은 특히 초기부터
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
3. **오버엔지니어링/단순화 후보**: 확정됐다고 적혀 있지만 목적에 비해 과한
|
3. **오버엔지니어링/단순화 후보**: 확정됐다고 적혀 있지만 목적에 비해 과한
|
||||||
추상화로 보이거나 더 간단한 대안이 있어 보이는 지점. (단, "이미 여러
|
추상화로 보이거나 더 간단한 대안이 있어 보이는 지점. (단, "이미 여러
|
||||||
라운드에 걸쳐 검증됨"이라고 문서가 스스로 못박은 결정 자체를 재론하는
|
라운드에 걸쳐 검증됨"이라고 문서가 스스로 못박은 결정 자체를 재론하는
|
||||||
건 배제 — `CLAUDE.md`의 반복 조사 금지 원칙과 같은 이유.)
|
건 배제 — `.claude/project-context.md`의 반복 조사 금지 원칙과 같은 이유.)
|
||||||
|
|
||||||
이미 `.claude/question.md`에 취합된 항목(용어 재검토, M0 스파이크 항목
|
이미 `.claude/question.md`에 취합된 항목(용어 재검토, M0 스파이크 항목
|
||||||
자체, Slot 형제 순서 보장 등)은 여기서 제외했다 — 아래는 **전부 새로 발견된
|
자체, Slot 형제 순서 보장 등)은 여기서 제외했다 — 아래는 **전부 새로 발견된
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ compat.lua나 어댑터 코드는 전혀 없고, README/커밋 메시지에도 "
|
||||||
|
|
||||||
→ `archive/question-resolved.md`가 "OOP 상속/커스텀 파서/Slot 스텁/`Pipe` COW는
|
→ `archive/question-resolved.md`가 "OOP 상속/커스텀 파서/Slot 스텁/`Pipe` COW는
|
||||||
확인된 죽은 접근"이라고 명시한 목록에 compat은 **포함돼 있지 않음**(정확한 서술).
|
확인된 죽은 접근"이라고 명시한 목록에 compat은 **포함돼 있지 않음**(정확한 서술).
|
||||||
즉 CLAUDE.md의 "반복 조사 금지"는 compat에는 적용되지 않는다 — 이 문서를
|
즉 `.claude/project-context.md`의 "반복 조사 금지"는 compat에는 적용되지 않는다 — 이 문서를
|
||||||
쓰는 게 규칙 위반이 아님.
|
쓰는 게 규칙 위반이 아님.
|
||||||
|
|
||||||
## 2. v1 공개 API 표면 — 두 계층으로 나뉨
|
## 2. v1 공개 API 표면 — 두 계층으로 나뉨
|
||||||
|
|
@ -266,7 +266,7 @@ v2 트리 안에 과거 v1 컴포넌트를 리프로 박아넣는 것, (B) 기
|
||||||
|
|
||||||
## 착수 시점
|
## 착수 시점
|
||||||
|
|
||||||
지금 당장 설계/착수 불필요 — `CLAUDE.md` "지금 할 일" 1번(구현 착수,
|
지금 당장 설계/착수 불필요 — `.claude/todos.md` 1번(구현 착수,
|
||||||
ROADMAP M0)이 최우선. 7-3의 Slot 관련 두 항목은 M0 이후 Slot 구현
|
ROADMAP M0)이 최우선. 7-3의 Slot 관련 두 항목은 M0 이후 Slot 구현
|
||||||
라운드에서 실제 코드와 함께 재확인해야 풀림 — 그 전까진 이 문서의 제안
|
라운드에서 실제 코드와 함께 재확인해야 풀림 — 그 전까진 이 문서의 제안
|
||||||
(7-1/7-2 규칙들)이 최선의 추정치.
|
(7-1/7-2 규칙들)이 최선의 추정치.
|
||||||
|
|
|
||||||
1276
.claude/session-summary.md
Normal file
1276
.claude/session-summary.md
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,258 @@
|
||||||
|
# 2026-08-16 세션 — 코퍼스 감사 서브에이전트/워크플로 신설, CLAUDE.md 4분할
|
||||||
|
|
||||||
|
## 발단
|
||||||
|
|
||||||
|
사용자 질문 두 갈래로 시작:
|
||||||
|
|
||||||
|
1. 문서 툴링(`doc-check.py`)만으로는 **'실수'가 안 잡힌다** — `/code-review`
|
||||||
|
같은 걸 핸드오버 전/커밋 전에 에이전트가 스스로 돌게 만들 수 있나?
|
||||||
|
2. 어렵거나 목적에 더 맞는 게 있다면, 프로젝트 서브에이전트를 구성하고
|
||||||
|
CLAUDE.md에서 쓰도록 명시하는 쪽이 나을지. "summary를 실제 파일 한쪽으로
|
||||||
|
옮겨서 해결"하는 방식으로는 **단순 언급으로 남는 stale**을 잡기 어렵고
|
||||||
|
모든 곳에 적용도 어려워 보인다 — 현실적으로는 에이전트가 유의하고
|
||||||
|
서브에이전트가 새 맥락에서 훑는 게 최선 아닌가.
|
||||||
|
|
||||||
|
추가로 "다른 사람들은 이런 큰 기술 계획 문서에 에이전트를 어떻게 쓰는지"
|
||||||
|
검색해서 stale/실수 전파의 현실적 완화책을 알아봐 달라는 요청.
|
||||||
|
|
||||||
|
## 조사 결과
|
||||||
|
|
||||||
|
### hook으로 code-review를 직접 부를 수는 없음
|
||||||
|
|
||||||
|
hook은 **셸 명령만** 실행한다. Claude 스킬이나 서브에이전트를 직접 호출하는
|
||||||
|
경로가 없다. 대신 실제로 쓰이는 패턴은 **PreToolUse 게이트**:
|
||||||
|
`git commit`을 매칭해 조건 미충족이면 `deny`하고, **거부 사유 문자열로
|
||||||
|
"서브에이전트를 먼저 돌려라"는 지시를 돌려주는** 것(imti.co의 "Pre-Commit
|
||||||
|
Review Gate"). 즉 hook이 직접 부르는 게 아니라, 에이전트가 부르도록
|
||||||
|
**막아서 유도**한다.
|
||||||
|
|
||||||
|
그 글이 남긴 캐비엇도 유효:
|
||||||
|
- 기준이 느슨하면 서브에이전트가 통과용 형식적 발견을 지어냄("review theater")
|
||||||
|
- 너무 엄격하면 사소한 걸로 라운드가 5번씩 돌아 게이트가 아끼려던 시간을 까먹음
|
||||||
|
- 유효성 기준을 **diff 해시**로 잡으면 포매팅만 바뀌어도 재감사가 걸림(브리틀)
|
||||||
|
|
||||||
|
**quad엔 diff 해시 기준이 안 맞는다**는 판단: 이 프로젝트의 반복 실패 패턴은
|
||||||
|
"diff 안"이 아니라 **diff 밖 파일에 남은 stale 참조**다. 기준을 잡는다면
|
||||||
|
`.claude/**/*.md` 전체 해시여야 함.
|
||||||
|
|
||||||
|
### `/code-review`도 스킬이 맞음
|
||||||
|
|
||||||
|
marketplace 플러그인의 `code-review.md`를 직접 읽어 확인. 구조는:
|
||||||
|
Haiku로 자격 검사 → 관련 CLAUDE.md 목록 수집 → **5개 병렬 Sonnet 렌즈**
|
||||||
|
(CLAUDE.md 준수 / 얕은 버그 스캔 / git blame·히스토리 / 과거 PR 코멘트 /
|
||||||
|
코드 주석 준수) → 발견마다 Haiku가 **0~100 confidence rubric**으로 채점 →
|
||||||
|
80 미만 필터링 → 코멘트. false-positive 예시 목록도 프롬프트에 명시돼 있음.
|
||||||
|
|
||||||
|
즉 사용자 추측대로 "프론트메터와 자연어로 적절히 적으면 되는" 것이고,
|
||||||
|
프로젝트 전용으로 다시 만드는 게 타당.
|
||||||
|
|
||||||
|
### 학계 자료는 새 게 별로 없었음
|
||||||
|
|
||||||
|
"LLM agent drift / stale context mitigation" 검색 결과는 대부분 이 프로젝트가
|
||||||
|
이미 경험적으로 재발견한 것("신선한 세션/맥락이 stale을 줄인다", "요약 압축",
|
||||||
|
"주기적 리셋") 수준. 실무에 추가로 얹을 만한 구체 기법은 없었음.
|
||||||
|
|
||||||
|
## 만든 것 1 — `.claude/agents/quad-doc-auditor.md`
|
||||||
|
|
||||||
|
읽기 전용(`tools: Read, Grep, Glob, Bash`), `model: sonnet`, `memory: project`.
|
||||||
|
|
||||||
|
절차를 고정으로 박음: `doc-check.py` 먼저 → 이번에 뒤집힌/확정된 주장 파악
|
||||||
|
(git diff + 대화 맥락, 없으면 최근 session 파일) → 그 키워드로 코퍼스 전체
|
||||||
|
grep해서 **부정당하는 본문 문장** 찾기 → archive 이전 여부 → 개수/목록
|
||||||
|
이중소스 → 인덱스 3레이어 동기화.
|
||||||
|
|
||||||
|
설계 판단 두 개:
|
||||||
|
- **수정 권한 없음.** 발견만 리포트하고 반영은 호출한 세션이 함. 감사와
|
||||||
|
수정을 분리하는 게 지금 워크플로우와 맞음.
|
||||||
|
- **판정은 "확실/의심" 2단계뿐.** `/code-review`의 0~100 rubric은 diff 하나가
|
||||||
|
대상일 때 얘기고, 코퍼스 정합성엔 과한 무게라고 봄. "발견 없으면 그대로
|
||||||
|
발견 없음이라고 보고하라, 그럴듯해 보이려고 지어내지 마라"를 명시.
|
||||||
|
|
||||||
|
`memory: project`를 준 이유: "6개 문서" stale, "8차 세션" 오표기처럼 이
|
||||||
|
프로젝트에서 **실제로 반복된** 실수 유형을 지금은 사람이 CLAUDE.md 프로즈로
|
||||||
|
수기 기록 중인데, 그걸 에이전트 자신의 기억으로 축적시키는 게 맞다고 판단.
|
||||||
|
|
||||||
|
## 만든 것 2 — `.claude/workflows/quad-handover-audit.js`
|
||||||
|
|
||||||
|
사용자 지적이 핵심이었음: **"subagent가 문제를 항상 찾는다고 결정론적으로
|
||||||
|
보장되는 게 아니다. 메인 에이전트가 여럿 굴려서 커밋 전에 다 잡게 할 수
|
||||||
|
있나."** 그리고 "시간은 걸려도 괜찮다, 부정확성이 문제다. 멀티패스로 여러 번
|
||||||
|
굴려야 all consistent가 되기도 한다."
|
||||||
|
|
||||||
|
그래서 단발 호출이 아니라 **수렴 루프**로 구성:
|
||||||
|
- 라운드마다 `quad-doc-auditor`를 **병렬 3회** 독립 실행(서로 뭘 찾았는지
|
||||||
|
모르게 — 비결정성을 커버리지로 바꾸는 방식)
|
||||||
|
- 새 발견(dedup)을 **파일별로 묶어** `general-purpose`가 즉시 반영
|
||||||
|
- **새 발견 없는 라운드가 연속 2번** 나올 때까지 반복(최대 6라운드 안전판)
|
||||||
|
- 다음 라운드 감사가 직전 라운드 수정의 검증을 겸함 → 별도 검증 단계 불필요
|
||||||
|
|
||||||
|
`git commit`은 **의도적으로 워크플로 밖**에 뒀음 — diff 재검토와 커밋 메시지
|
||||||
|
작성은 대화형 맥락이 필요.
|
||||||
|
|
||||||
|
과거 수동 감사의 발견 추이(8→7→11→9→4→0, 9→2→3→2→0→0)를 근거로 상수를
|
||||||
|
잡음(`MAX_ROUNDS = 6`).
|
||||||
|
|
||||||
|
## 첫 실측 — 실패, 그리고 더 나쁜 건 실패가 성공으로 보고된 것
|
||||||
|
|
||||||
|
커밋(`a1c0e44`) 후 바로 돌림. 결과:
|
||||||
|
|
||||||
|
```
|
||||||
|
converged: true, rounds: 2, totalFindingsFixed: 0
|
||||||
|
failures: parallel[0..2] agent type 'quad-doc-auditor' not found (×2 라운드)
|
||||||
|
```
|
||||||
|
|
||||||
|
**에이전트 6개 전원 실패했는데 워크플로는 "수렴했다"고 보고했다.**
|
||||||
|
|
||||||
|
- 1차 원인은 예상됐던 것: `.claude/agents/`가 **세션 도중** 생긴 디렉토리라
|
||||||
|
레지스트리에 없음(공식 문서: 감시자는 세션 시작 시 존재했던 디렉토리만 포함).
|
||||||
|
- **진짜 문제는 2차 원인**: 모든 패스가 `null`이 되면 `fresh.length === 0`이
|
||||||
|
되고, 이게 "깨끗한 라운드"와 코드상 구분이 안 돼서 그대로 dry 카운트가
|
||||||
|
올라가 수렴 판정이 났음. **감사 도구가 아무것도 감사하지 않고 통과 도장을
|
||||||
|
찍는 것** — 감사 도구로서 최악의 실패 모드.
|
||||||
|
|
||||||
|
즉시 가드 두 개 추가:
|
||||||
|
1. 라운드의 감사 패스가 **전멸하면 throw**(수렴 판정 자체를 못 내게).
|
||||||
|
일부만 실패하면 "커버리지가 그만큼 얕음"을 `log`.
|
||||||
|
2. **반영 에이전트가 실패하면 그 발견들을 `seen`에서 제거** — 안 그러면 다음
|
||||||
|
라운드 감사가 같은 문제를 다시 찾아와도 dedup에 걸려 조용히 사라지고,
|
||||||
|
안 고쳐진 채로 수렴 판정이 남(같은 클래스의 두 번째 버그).
|
||||||
|
|
||||||
|
### 부수 질문 — 서브에이전트 모델이 왜 Opus로 떴나
|
||||||
|
|
||||||
|
사용자가 진행 화면에서 `audit-r1-0 Opus 5 · failed`을 보고 물음(정의엔
|
||||||
|
`model: sonnet`인데). 답: **정의를 못 찾아서**. 공식 해석 순서는
|
||||||
|
`CLAUDE_CODE_SUBAGENT_MODEL` → 호출별 `model` → **정의의 frontmatter** →
|
||||||
|
메인 대화 모델인데, 정의가 없으니 3번이 통째로 건너뛰어지고 4번(당시
|
||||||
|
`/model opus`로 바뀐 Opus 5)으로 떨어진 것. 워크플로는 `opts.model`을 안
|
||||||
|
넘기므로 정의가 로드되면 `sonnet`이 이겨야 정상 — **재시작 후 첫 실행에서
|
||||||
|
표시 모델을 확인해야 확정.**
|
||||||
|
|
||||||
|
## CLAUDE.md 4분할
|
||||||
|
|
||||||
|
사용자 제안: CLAUDE.md가 사람이 검토하기 힘들다. `@name.md`로 flatten되어
|
||||||
|
컨텍스트에 들어가고 캐싱되니, 세션 히스토리 / 할 일 / 작업 방식+베이스
|
||||||
|
컨텍스트로 분화하는 게 나을 듯. **"같은 것끼리는 묶는다"가 아주 중요한
|
||||||
|
지점.** 그리고 `session-summary.md`는 절대 건들지 말라고 해놓고 **아예 전부
|
||||||
|
자동생성** 되게 하는 게 나을 것 같다.
|
||||||
|
|
||||||
|
### 실측 숫자
|
||||||
|
|
||||||
|
| 섹션 | 줄 수 | 비중 |
|
||||||
|
|---|---|---|
|
||||||
|
| 세션 히스토리 | 1231 | **80%** |
|
||||||
|
| 지금 할 일 | 116 | 8% |
|
||||||
|
| 작업 방식 | 92 | 6% |
|
||||||
|
| 계획 문서 구조 | 63 | 4% |
|
||||||
|
| 이 프로젝트가 뭔지 | 21 | 1% |
|
||||||
|
| 언어/모델 관례 | 12 | 1% |
|
||||||
|
| 합계 | 1537 | |
|
||||||
|
|
||||||
|
### 공식 문서에서 확인한 것 (셋 다 중요)
|
||||||
|
|
||||||
|
1. **권장치가 파일당 200줄**이고, 초과하면 컨텍스트만 더 쓰는 게 아니라
|
||||||
|
**"준수를 줄입니다"** — 사용자가 관찰한 "파일 길어지면 실수 더 하는
|
||||||
|
경향"이 문서에도 명시된 알려진 현상. 지금 7.7배 초과.
|
||||||
|
2. **`@import`는 컨텍스트를 안 줄인다** — "가져온 파일은 여전히 로드되고
|
||||||
|
시작 시 컨텍스트 윈도우에 들어갑니다". 분할이 사는 건 사람 검토성 +
|
||||||
|
에이전트 편집 정확도 + **파일 단위 자동생성 가능성**이지 토큰이 아님.
|
||||||
|
3. **블록 HTML 주석은 컨텍스트 주입 전 제거된다** — 사람용 메모를 토큰 0으로
|
||||||
|
남길 수 있는 대신, **거기 쓴 지시는 에이전트가 못 본다.**
|
||||||
|
|
||||||
|
(3)에서 이 세션이 자기 함정을 밟음: 새 CLAUDE.md의 "새 서술을 여기 직접 쌓지
|
||||||
|
말 것"을 HTML 주석에 넣었다가, 그게 스트립된다는 걸 문서로 확인하고 본문으로
|
||||||
|
옮김. 주석엔 "이 주석은 주입 전 제거되니 사람용 메모만 넣을 것"을 남김.
|
||||||
|
|
||||||
|
부수 발견: **`.claude/rules/*.md`** 라는 별도 메커니즘이 있음 — `@` 없이 자동
|
||||||
|
로드되고 `paths:` frontmatter로 **"특정 파일 작업할 때만 로드"**가 됨. 지금은
|
||||||
|
`src/`가 없어 쓸모없지만, M0 들어가면 "Handler 작성 체크리스트"를
|
||||||
|
`src/**/Dispatch/*.luau`에만 물리는 식으로 쓸 수 있음.
|
||||||
|
|
||||||
|
### 결정 — session-summary는 import 안 함
|
||||||
|
|
||||||
|
내가 사용자 안보다 한 발 더 나가는 제안을 함: 세션 히스토리의 고유 가치는
|
||||||
|
**"어느 세션 파일을 열지 찾는 색인"**뿐이고(그 문서 스스로 "항상 읽을 필요
|
||||||
|
없음, 지금 유효한 설계는 `base/`가 소스"라고 명시해왔음), 색인은 grep으로
|
||||||
|
온디맨드 조회하면 되는 종류다 → import 안 걸면 로드가 1537 → ~325줄.
|
||||||
|
|
||||||
|
사용자 동의: *"나도 session-summary.md 는 차라리 @ 안 붙이고, 그냥 거기에
|
||||||
|
있긴 하니까 만약에 선행 맥락이 필요하다면 그 때 가서 느리게 확인하도록
|
||||||
|
두는게 맞아보임."*
|
||||||
|
|
||||||
|
이름은 `code-of-conduct.md`를 제안받았으나 **OSS에서 "기여자 행동강령"이라는
|
||||||
|
다른 뜻으로 굳어진 말**이라 피하는 게 좋겠다고 제안 → `conventions.md` 채택.
|
||||||
|
|
||||||
|
### 최종 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
CLAUDE.md (39줄, 진입점)
|
||||||
|
├─ @.claude/conventions.md 108줄 언어/모델 관례 + 작업 방식
|
||||||
|
├─ @.claude/project-context.md 88줄 프로젝트 설명 + 문서 구조
|
||||||
|
└─ @.claude/todos.md 119줄 지금 할 일
|
||||||
|
.claude/session-summary.md 1241줄 ← import 안 함(온디맨드)
|
||||||
|
```
|
||||||
|
|
||||||
|
매 세션 로드: **1537 → 354줄 (77% 감소)**. `session-summary.md`는 상단에
|
||||||
|
"자동생성 전환 예정, 전환 후엔 직접 편집 금지"를 명시해둠.
|
||||||
|
|
||||||
|
## 분할이 깨뜨린 상호참조 정리
|
||||||
|
|
||||||
|
20여 곳. 파일 그룹별 병렬 에이전트 3개(`base/` / `research/` /
|
||||||
|
루트+luau-test+audit)로 정정. 매핑은 `"지금 할 일"`→`todos.md`,
|
||||||
|
`"반복 조사 금지"`→`project-context.md`, `"세션 히스토리"`→`session-summary.md`,
|
||||||
|
SAFETY 원칙→`conventions.md`.
|
||||||
|
|
||||||
|
**가장 값진 결과는 base/ 담당 에이전트가 내 전제를 반박한 것**: 내가
|
||||||
|
"`dispatch-core-plan.md:41`의 CLAUDE.md 참조는 기존 stale"이라고 지시에
|
||||||
|
적어 보냈는데, 실제로는 **줄바꿈에 걸친 `.claude/initreq/tbox/CLAUDE.md`
|
||||||
|
참조**(tbox의 type-check/constraint-check 분리 원칙 인용)로 완전히 유효한
|
||||||
|
것이었음. 같은 패턴이 `slot-plan.md:1285`, `ref-plan.md:190`에도 있음.
|
||||||
|
에이전트가 "다른 에이전트에게 같은 전제를 넘겼다면 정정이 필요하다"까지
|
||||||
|
보고함 — 지시를 그대로 믿지 않고 검증한 게 정확히 이 감사 구조가 노린 것.
|
||||||
|
|
||||||
|
같은 에이전트가 `ref-plan.md:541`의 `위 "지금 할 일" 우선순위1 항목`도
|
||||||
|
발견 — 분할과 무관한 **원래부터 잘못된 참조**였고(그 "우선순위1"은
|
||||||
|
`research/pre-implementation-audit.md`의 용어), 진단이 확실해서
|
||||||
|
`pre-implementation-audit.md` 1-5로 정정.
|
||||||
|
|
||||||
|
**추측 수정을 금지한 게 효과가 있었음.** 진짜 orphan 3건은 손대지 않고
|
||||||
|
보고만 하게 했고, 코퍼스 전체 grep으로 인용된 원칙이 어디에도 없음을 확인:
|
||||||
|
- `modifier-plan.md:536` — CLAUDE.md의 "드문 오용/가상 미래 요구까지
|
||||||
|
방어/최적화하려고 구조를 복잡하게 만들지 않는다" 원칙
|
||||||
|
- `v1-compat-plan.md:50` — CLAUDE.md에 "이 자동 위임/재렌더 매직은 v2에서
|
||||||
|
폐기하기로 확정"이라 기록됐다는 서술
|
||||||
|
- `pre-implementation-audit.md:434` — CLAUDE.md가 M2/M3/M5에서 quad-debug
|
||||||
|
훅 확장 지점을 고려하라고 명시해뒀다는 서술
|
||||||
|
|
||||||
|
셋 다 **분할 이전부터** 존재하지 않던 인용이다. 원칙을 복원할지 인용을
|
||||||
|
버릴지는 사용자 판단 영역이라 남겨둠.
|
||||||
|
|
||||||
|
## `doc-check.py` 갱신
|
||||||
|
|
||||||
|
1. **새 파일 4개를 `OURS` 정규식에 등록.** 안 하면 `.claude/todos.md`로 가는
|
||||||
|
깨진 참조가 ERROR가 아니라 WARN으로만 잡힘 — 일곱 번째 세션에
|
||||||
|
`store-semantics.md`로 실제로 당했던 사각지대와 같은 클래스.
|
||||||
|
2. **`is_history()` 헬퍼 신설** — `archive/`와 `session-summary.md`를 묶어
|
||||||
|
절 참조/시한부 주장 검사에서 면제. 둘 다 "그때는 그렇게 적었다"가 정상인
|
||||||
|
문서라 현재형 검사를 걸면 안 꺼지는 WARN만 쌓임.
|
||||||
|
|
||||||
|
최종 ERROR 0 유지(검사 대상 78 → 82개).
|
||||||
|
|
||||||
|
## `doc-include-plan.md` 단순화
|
||||||
|
|
||||||
|
이 분할이 그 플랜의 **설계 절반을 불필요하게 만들었음.** 원안은 원본에
|
||||||
|
`<!--#summary-->`, 인용처에 `<!--#include-->` 두 종류 마커를 두는 양방향
|
||||||
|
설계였는데, 세션 히스토리가 독립 파일이 되면서 목적지가 "손으로 쓴 파일 속
|
||||||
|
구간"이 아니라 **통째로 생성되는 파일**이 됨 → 목적지 마커가 필요 없어지고,
|
||||||
|
id도 불필요(파일명이 곧 순서이자 식별자). "목적지 마커가 손실되면?" 같은
|
||||||
|
실패 모드도 같이 사라짐. 파일럿 절을 이 정정으로 갱신.
|
||||||
|
|
||||||
|
## 남은 것
|
||||||
|
|
||||||
|
- **재시작 후 검증 필요**: (a) `/memory`로 `@import` 4개가 실제 로드되는지,
|
||||||
|
(b) `quad-doc-auditor`가 레지스트리에 잡히는지, (c) 워크플로에서 그
|
||||||
|
에이전트가 frontmatter의 `sonnet`으로 도는지(Opus로 뜨면 `opts.model`
|
||||||
|
명시가 필요).
|
||||||
|
- **`session-summary.md` 자동생성 미착수** — 91개 세션 파일에 마커를 넣고
|
||||||
|
생성기를 짜는 마이그레이션이 남음. 그 전까지는 손으로 관리 중이며 파일
|
||||||
|
상단에 그렇게 명시해둠.
|
||||||
|
- 위 orphan 인용 3건.
|
||||||
121
.claude/todos.md
Normal file
121
.claude/todos.md
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
# 지금 할 일 (우선순위순)
|
||||||
|
|
||||||
|
루트 `CLAUDE.md`가 `@import` 하는 파일. **가장 자주 바뀜** — 해소된 항목은
|
||||||
|
미루지 말고 그 자리에서 지우고, 개수·목록은 여기 적지 말고 소스를 가리킬 것
|
||||||
|
(`.claude/question.md`, `luau-test/STATUS.md` 등).
|
||||||
|
|
||||||
|
|
||||||
|
0. **⭐ M0 착수를 막는 결정은 이제 없음 (2026-08-14 열한 번째 세션 기준).**
|
||||||
|
`question.md`의 최우선 항목이 **전부 비었음** — `0-Y`(`:Compute` lazy
|
||||||
|
핸들 계약)는 13차 세션에, `0-Z`(Attribute 이름 소유권)와 `0-A`(재디스패치
|
||||||
|
하강 diff)는 14차 세션에, `0-B`(`dispose` 시그니처/범위)는 2026-08-14
|
||||||
|
열 번째 세션에 확정·`base/` 반영 완료. **`0-W`(같은 `Ref` 이중 배치,
|
||||||
|
M8 구현 세부만 막던 항목)도 2026-08-14 열한 번째 세션에 해소** —
|
||||||
|
선택지 (a) 채택(즉시 error), 메커니즘은 새 `Relate` 없이
|
||||||
|
`bindLifetime`/`unbindLifetime` 재사용(`base/ref-plan.md` "이중 배치
|
||||||
|
방지" 절). 부수 결정으로 **`canBound`가 `canExecute`와 별도 진입점으로
|
||||||
|
재도입**됨(2026-08-14 다섯 번째 세션에 하나로 합쳤던 걸 부분적으로
|
||||||
|
되짚음 — "이미 묶여 있는가"(bound 문맥)와 "지금 발화해도 되는가"
|
||||||
|
(execute 문맥)는 판정 로직은 공유해도 호출부의 질문이 다르다는 사용자
|
||||||
|
지적, `base/lifecycle-pattern.md`의 "`canBound` vs `canExecute`" 절).
|
||||||
|
`question.md`엔 이제 "결정 대기" 절 자체가 없음(비어서 헤딩째로 삭제).
|
||||||
|
|
||||||
|
**M0 착수 전 반드시 읽을 것 — 이 두 개는 "결정"이 아니라 "구현 규약"이라
|
||||||
|
여전히 유효**:
|
||||||
|
- **`base/typing-limits.md`**(0-Y의 산물) — 핵심은 "파생 State를 만드는
|
||||||
|
자리마다 결과 타입을 명시 주석으로 바인딩" + 7번 설계 체크리스트.
|
||||||
|
재귀 제네릭이 자기를 다른 타입 인자로 반환하면 Luau가 타입 안전성을
|
||||||
|
**에러 없이 조용히** 잃는 상위 한계라 quad 쪽에서 우회하지 않기로
|
||||||
|
확정(RFC `relax-recursive-type-restriction` 수혜 대기, 추적
|
||||||
|
`luau-lang/luau#2380`). 실측 근거는 `audit/type-recursion-issue/`.
|
||||||
|
- **`base/dispatch-core-plan.md`**(0-A/0-Z의 산물, 14차 세션에
|
||||||
|
`bind-system-plan.md`에서 분리 신설) — 재디스패치가 "철거 후 재구축"이
|
||||||
|
아니라 **하강 diff**임, `retractFrom`은 3-인자, 클로저 인자는
|
||||||
|
`nil`이거나 같은 핸들러가 처리할 값(타입 보장), `HANDLER_PRIORITY_FALLBACK`,
|
||||||
|
"base가 소유하는 핸들러와 주입되는 엔진 op"(`addTag`/`removeTag`/
|
||||||
|
`setAttribute`). **Handler 작성 체크리스트 8개**를 새 핸들러 짜기 전에
|
||||||
|
훑을 것 — 지난 세션들에서 실제로 반복된 실수 목록임.
|
||||||
|
|
||||||
|
해소 전 원문은 `archive/question-resolved.md`(0-Y/0-Z/0-A 절), 뒤집힌 옛
|
||||||
|
재디스패치 모델 전문은 `archive/dispatch-hintvalue-model-reversed.md`.
|
||||||
|
|
||||||
|
1. **구현 시작 — 루트 `ROADMAP.md`의 M0부터.** 설계 단계는 2026-08-04 로드맵
|
||||||
|
인수인계 라운드로 종료. `research/pre-implementation-audit.md` 우선순위1은
|
||||||
|
2026-08-12 열일곱 번째 세션에 마지막 넷(1-3/1-4/1-10/1-11)까지 전부
|
||||||
|
해소되어 **11개 전원 완료**. **[14차 세션 기준] 0-Y/0-Z/0-A까지 전부
|
||||||
|
해소돼 설계 게이트는 남아있지 않음** — 착수 전 읽을 것은 위 0번의 두
|
||||||
|
문서(`typing-limits.md`/`dispatch-core-plan.md`)뿐이고, 스파이크 상태는
|
||||||
|
아래 그대로:
|
||||||
|
- **`.claude/luau-test/`(2026-08-09 신설, 2026-08-13 기준 20개) 스파이크
|
||||||
|
결과 — [2026-08-13 여섯 번째 세션에 첫 실측 완료, 대부분 닫힘].**
|
||||||
|
**상태의 소스는 항상 `.claude/luau-test/STATUS.md`**(pass / 사람 결정
|
||||||
|
필요 / 스파이크 깨짐 / 미실행, 폴더 구조 자체가 상태) — 몇 개가 지금
|
||||||
|
어느 폴더에 있는지는 여기서 나열 안 함(04/05/10/13/15/16/19가 여러
|
||||||
|
세션에 걸쳐 재설계로 `rewrite-required/`에 들고나며 이 문단의 나열이
|
||||||
|
매번 stale해지는 패턴이 반복됐음, 최근엔 8차 세션의 "emit은 항상
|
||||||
|
전파" 정정으로 `05`도 합류). 실행 결과 상세는
|
||||||
|
`.claude/audit/luau-test-first-run-2026-08-13.md`. 첫 실측 요지만
|
||||||
|
(역사적 사실 — 이후 변동은 위처럼 `STATUS.md`가 소스):
|
||||||
|
- **런타임 12개 전원 통과**(01~07/11/17/18/19/20, crash 0 / FAIL 0) —
|
||||||
|
특히 `07`이 연쇄 GC를, `18`이 두-`Relate` 상호 순환 미해제를 실측
|
||||||
|
확정해 GC-native 아키텍처의 핵심 전제가 검증됨. `04`는 같은 세션
|
||||||
|
감사가 찾은 `chains:SetStrong` 순서 버그를 음성 대조군으로 재현.
|
||||||
|
- **타입 쪽에서 하나가 걸렸었음** → 그게 구 **0-Y**, **[13차 세션]
|
||||||
|
해소**(Luau 현 한계로 확정, `base/typing-limits.md`). 나머지 타입
|
||||||
|
스파이크는 판정 완료(`08`/`09` 통과, `12`는 실패지만 문서가 이미
|
||||||
|
fallback으로 예비해둔 결과라 설계 영향 없음, `14`는 부분).
|
||||||
|
지금 M0 착수를 막는 설계 결정은 없고, 0-Y/0-A가 남긴 규약
|
||||||
|
(`base/typing-limits.md`/`base/dispatch-core-plan.md`)은 착수 전 필독.
|
||||||
|
2. **용어 정리 — 1차 제안 이후 대부분 확정, 소수만 남음.** 최신 소스는
|
||||||
|
`.claude/question.md` 1번(개수 반복 안 함, 항목 추가/해소될 때마다 여기가
|
||||||
|
stale해지는 패턴이 반복됐어서). **[2026-08-13 정정]** `State`는
|
||||||
|
2026-08-12 스무 번째 세션에 현재 이름 그대로 유지로 이미 확정됐음(이
|
||||||
|
목록이 "위험도 높음, 1순위 open"으로 stale하게 남아있던 걸 발견해 수정)
|
||||||
|
— 아직 진짜로 열려있는 것만 짚으면: `DI`→`D`(1순위), `Slot`(2순위),
|
||||||
|
`canExecute`(3순위 — `isAlive`는 검토 후 기각, `can` 계열 접두 유지
|
||||||
|
방향으로 기울었으나 구체 대안 미정), `Brand`(3순위), `Tag`/`Added`/
|
||||||
|
`Removed`/`Merged`(3순위), `Attribute`/`AttributeKey`(3순위).
|
||||||
|
3. **[2026-08-14 세션에 해소]** 오래 열려 있던 "이미 생성된 인스턴스
|
||||||
|
재바인드"는 **기각**되어 `archive/existing-instance-bind-rejected.md`로
|
||||||
|
이전됨 — 더 이상 상의할 스코프 항목이 아님.
|
||||||
|
4. **[백로그]** 범용 렌더 디버깅 도구 `quad-mock`(Tween mock 등 동적 동작
|
||||||
|
지원, M0 mock 테스트 하네스와는 별개), 런타임 디버깅 플러그인
|
||||||
|
`quad-debug`(Studio 플러그인, 실물 Instance→코드 위치 역추적 — 채널
|
||||||
|
실현 가능성은 실측 검증 완료, 세부 API 이름만 남음), 문서 사이트 전체
|
||||||
|
구조(초심자/api/심화/`quadnomicon` 4축 + 콘텐츠 맵), `Operator` 콤비네이터
|
||||||
|
슈가(`Sum`/`Product`/`Not`/비트연산 등 `:Compute`/`:Apply`용 — 메커니즘은
|
||||||
|
확정, 네임스페이스 이름만 미정, 구현은 순수 슈가라 맨 마지막), 컴포넌트
|
||||||
|
에러 격리 유틸 `Fallback`/`Traceback`(**[2026-08-14 세션, 설계 확정 —
|
||||||
|
`research/`에서 `base/fallback-plan.md`로 승격]** `pcall` 기반
|
||||||
|
`Fallback`과 `xpcall`+`debug.traceback` 기반 `Traceback`으로 분리,
|
||||||
|
`err: any` 확정, 패키지·이름 전부 확정 — **설계만 끝났을 뿐 구현
|
||||||
|
우선순위는 그대로 맨 뒤**), 생명주기 훅
|
||||||
|
`OnCreated`/`OnRendered`/`OnDestroyed`(**[2026-08-14 아홉 번째 세션,
|
||||||
|
`research/`에서 `base/lifecycle-hooks-plan.md`로 승격]** 각각
|
||||||
|
`PreRef`/`PostRef`/`Effect`를 반환하는 순수 팩토리 함수 슈가 —
|
||||||
|
`OnRendered`도 **채택 확정**, 그게 얹히는 `PostRef` 프리미티브 자체는
|
||||||
|
슈가가 아니라 디스패치 코어라 **ROADMAP M8에서 `PreRef`와 같이 구현됨**
|
||||||
|
(백로그가 아님, `base/ref-plan.md`의 "`PostRef`" 절). 훅 슈가 셋만
|
||||||
|
후순위) — 전부
|
||||||
|
"quad 개발 상당 부분 끝난 뒤"로 사용자가 못박은 후순위. 상세는
|
||||||
|
`.claude/README.md`의 `base/` 표(`fallback-plan.md`/
|
||||||
|
`lifecycle-hooks-plan.md`)와 `research/` 표
|
||||||
|
(`debug-tooling-plan.md`/`documentation-plan.md`/
|
||||||
|
`documentation-content-map.md`/`framework-comparison-findings.md`/
|
||||||
|
`operator-sugar-plan.md`).
|
||||||
|
**[2026-08-14 추가, 성격이 다름]** 시간 기반 전파 게이트
|
||||||
|
`Debounce`/`Throttle`(`research/debounce-throttle-plan.md`)도 백로그이긴
|
||||||
|
하나 위 항목들과 달리 **사용자가 직접 요청한 실제 기능 갭**이고 순수
|
||||||
|
슈가가 아님 — M0/M3를 막지는 않지만, **M3에서 `Blocker`를 구현할 때
|
||||||
|
게이티드 노드를 공용 `Gate`로 빼두는 것만은 그 시점에 해야 함**(따로
|
||||||
|
하면 같은 설계를 두 번 함). 주입 op 2개(`setTimeout`/`clearTimeout`)가
|
||||||
|
백엔드 팩토리 표면에 추가될 예정이라는 것도 M1 설계 시 인지. 설계는
|
||||||
|
네 라운드로 대부분 확정됐고 남은 열린 질문은 `question.md` 3번(개수는
|
||||||
|
거기도 반복 안 함 — 소스는 `research/debounce-throttle-plan.md` 12절).
|
||||||
|
5. 자율 작업 루프/스케줄 설정 여부는 사용자 결정 대기 중
|
||||||
|
(`HUMAN_TODO.md` 2번 항목).
|
||||||
|
6. **[신규 백로그, 2026-08-14 열네 번째 세션]** 문서 stale 감소용 include
|
||||||
|
도구 `doc-include.py`(가칭, `doc-check.py`와 짝) — `research/
|
||||||
|
doc-include-plan.md` 참고. 플랜만 초안, **사용자가 내일 다듬을
|
||||||
|
예정**. M0/설계 게이트와 무관.
|
||||||
|
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
5. [WARN] 미반영 배너를 단 파일 vs 반영 목록 일치 여부
|
5. [WARN] 미반영 배너를 단 파일 vs 반영 목록 일치 여부
|
||||||
|
|
||||||
`session/`(원문 보존), `initreq/`(읽기 전용 클론)는 검사 대상에서 제외.
|
`session/`(원문 보존), `initreq/`(읽기 전용 클론)는 검사 대상에서 제외.
|
||||||
|
`archive/`와 `.claude/session-summary.md`는 검사 대상이되 **히스토리 문서**라
|
||||||
|
절 참조/시한부 주장 검사는 면제(`is_history()` 참고).
|
||||||
"""
|
"""
|
||||||
import os, re, sys, collections
|
import os, re, sys, collections
|
||||||
|
|
||||||
|
|
@ -92,7 +94,11 @@ def resolve(target, src):
|
||||||
# 안 걸리면 외부 문서명(Compose 가이드라인 등)일 수 있어 WARN으로 낮춤.
|
# 안 걸리면 외부 문서명(Compose 가이드라인 등)일 수 있어 WARN으로 낮춤.
|
||||||
OURS = re.compile(r'(-plan|-reversed|-rejected|-findings|-map|-audit|-verification'
|
OURS = re.compile(r'(-plan|-reversed|-rejected|-findings|-map|-audit|-verification'
|
||||||
r'|^README|^STATUS|^CLAUDE|^ROADMAP|^HUMAN_TODO|^SAFETY'
|
r'|^README|^STATUS|^CLAUDE|^ROADMAP|^HUMAN_TODO|^SAFETY'
|
||||||
r'|^question|^architecture|^agent-mistake)\.md$')
|
r'|^question|^architecture|^agent-mistake'
|
||||||
|
# [2026-08-16] CLAUDE.md 분할 산물. 여기 안 넣으면 이 파일들로
|
||||||
|
# 가는 깨진 참조가 ERROR가 아니라 WARN으로만 잡힌다 — 일곱 번째
|
||||||
|
# 세션에 store-semantics.md에서 실제로 당했던 사각지대.
|
||||||
|
r'|^conventions|^project-context|^todos|^session-summary)\.md$')
|
||||||
|
|
||||||
|
|
||||||
def headings(path):
|
def headings(path):
|
||||||
|
|
@ -121,11 +127,23 @@ def interesting(target):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def is_history(path):
|
||||||
|
"""히스토리 문서인가 — 절 참조/시한부 주장 검사를 면제한다.
|
||||||
|
|
||||||
|
`archive/`는 뒤집힌 결정의 원문 보존, `session-summary.md`는 세션별
|
||||||
|
과거 기록이라 둘 다 "그때는 그렇게 적었다"가 정상이다. 여기에 현재형
|
||||||
|
검사를 걸면 영원히 안 꺼지는 WARN만 쌓인다.
|
||||||
|
[2026-08-16] CLAUDE.md 분할로 세션 히스토리가 별도 파일이 되면서 추가.
|
||||||
|
"""
|
||||||
|
r = rel(path)
|
||||||
|
return '/archive/' in r or os.path.basename(r) == 'session-summary.md'
|
||||||
|
|
||||||
|
|
||||||
def check_refs(docs):
|
def check_refs(docs):
|
||||||
hcache = {}
|
hcache = {}
|
||||||
for d in docs:
|
for d in docs:
|
||||||
# archive는 히스토리라 절 참조까지 강제하지 않음(파일 존재만)
|
# 히스토리 문서는 절 참조까지 강제하지 않음(파일 존재만)
|
||||||
is_archive = '/archive/' in rel(d)
|
is_archive = is_history(d)
|
||||||
# 줄 단위가 아니라 **파일 전체**를 한 번에 스캔 — 파일명/절 제목이
|
# 줄 단위가 아니라 **파일 전체**를 한 번에 스캔 — 파일명/절 제목이
|
||||||
# 줄바꿈에 걸친 인용도 잡기 위함(위 REF 주석 참고). 줄 번호는 매치
|
# 줄바꿈에 걸친 인용도 잡기 위함(위 REF 주석 참고). 줄 번호는 매치
|
||||||
# 시작 오프셋으로 역산.
|
# 시작 오프셋으로 역산.
|
||||||
|
|
@ -186,7 +204,7 @@ DATED = re.compile(r'20\d\d-\d\d-\d\d|\[\s*(?:해소|정정|갱신|확정|역전
|
||||||
|
|
||||||
def check_temporal(docs):
|
def check_temporal(docs):
|
||||||
for d in docs:
|
for d in docs:
|
||||||
if '/archive/' in rel(d):
|
if is_history(d):
|
||||||
continue
|
continue
|
||||||
lines = open(d, encoding='utf-8').read().split('\n')
|
lines = open(d, encoding='utf-8').read().split('\n')
|
||||||
for i, line in enumerate(lines, 1):
|
for i, line in enumerate(lines, 1):
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ function fixPrompt(file, items) {
|
||||||
.join('\n')
|
.join('\n')
|
||||||
return (
|
return (
|
||||||
`아래는 quad-doc-auditor가 "${file}"에서 찾은 stale/모순 서술이다. ` +
|
`아래는 quad-doc-auditor가 "${file}"에서 찾은 stale/모순 서술이다. ` +
|
||||||
`이 파일을 읽고 CLAUDE.md의 관례(한국어 서술, 최소 수정, 뒤집힌 결정은 ` +
|
`이 파일을 읽고 .claude/conventions.md의 관례(한국어 서술, 최소 수정, 뒤집힌 결정은 ` +
|
||||||
`archive/로 이전+포인터, 날짜 없는 시한부 주장엔 날짜 붙이기)에 맞춰 직접 ` +
|
`archive/로 이전+포인터, 날짜 없는 시한부 주장엔 날짜 붙이기)에 맞춰 직접 ` +
|
||||||
`고쳐라. "의심"으로 표시된 항목은 실제로 문제인지 먼저 확인하고, 문제가 ` +
|
`고쳐라. "의심"으로 표시된 항목은 실제로 문제인지 먼저 확인하고, 문제가 ` +
|
||||||
`아니면 건드리지 말고 넘어가라(억지로 고치지 말 것).\n\n${lines}`
|
`아니면 건드리지 말고 넘어가라(억지로 고치지 말 것).\n\n${lines}`
|
||||||
|
|
@ -79,7 +79,28 @@ while (dry < DRY_ROUNDS_TO_CONVERGE && round < MAX_ROUNDS) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const all = passes.filter(Boolean).flatMap((p) => p.findings || [])
|
// ⚠️ 가짜 초록불 방지 — 2026-08-16 첫 실측에서 실제로 당한 것.
|
||||||
|
// 감사 패스가 전부 에러로 죽으면(예: agentType 미등록) fresh가 비어
|
||||||
|
// "깨끗한 라운드"와 구분이 안 되고, 그대로 converged:true가 나와서
|
||||||
|
// **아무것도 감사 안 하고 통과 도장을 찍는다**. 감사 도구의 최악
|
||||||
|
// 실패 모드라 살아남은 패스 수를 명시적으로 확인한다.
|
||||||
|
const alive = passes.filter(Boolean)
|
||||||
|
if (alive.length === 0) {
|
||||||
|
throw new Error(
|
||||||
|
`라운드 ${round}: 감사 패스 ${PASSES_PER_ROUND}개가 전부 실패 — ` +
|
||||||
|
`감사가 실제로 수행되지 않았으므로 수렴 판정을 낼 수 없음. ` +
|
||||||
|
`(quad-doc-auditor가 등록됐는지 확인: .claude/agents/ 를 만든 직후라면 ` +
|
||||||
|
`Claude Code 재시작 필요)`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (alive.length < PASSES_PER_ROUND) {
|
||||||
|
log(
|
||||||
|
`⚠️ 라운드 ${round}: 감사 패스 ${PASSES_PER_ROUND}개 중 ` +
|
||||||
|
`${PASSES_PER_ROUND - alive.length}개 실패 — 커버리지가 그만큼 얕음`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const all = alive.flatMap((p) => p.findings || [])
|
||||||
const fresh = all.filter((f) => !seen.has(keyOf(f)))
|
const fresh = all.filter((f) => !seen.has(keyOf(f)))
|
||||||
|
|
||||||
if (!fresh.length) {
|
if (!fresh.length) {
|
||||||
|
|
@ -99,8 +120,9 @@ while (dry < DRY_ROUNDS_TO_CONVERGE && round < MAX_ROUNDS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
phase('Fix')
|
phase('Fix')
|
||||||
await parallel(
|
const fileEntries = Object.entries(byFile)
|
||||||
Object.entries(byFile).map(([file, items]) => () =>
|
const fixed = await parallel(
|
||||||
|
fileEntries.map(([file, items]) => () =>
|
||||||
agent(fixPrompt(file, items), {
|
agent(fixPrompt(file, items), {
|
||||||
label: `fix:${file}`,
|
label: `fix:${file}`,
|
||||||
phase: 'Fix',
|
phase: 'Fix',
|
||||||
|
|
@ -109,7 +131,27 @@ while (dry < DRY_ROUNDS_TO_CONVERGE && round < MAX_ROUNDS) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
roundLog.push({ round, fresh: fresh.length, files: Object.keys(byFile) })
|
// 반영 에이전트가 죽으면 그 발견들을 `seen`에서 빼둔다 — 안 그러면
|
||||||
|
// 다음 라운드 감사가 같은 문제를 다시 찾아와도 dedup에 걸려 조용히
|
||||||
|
// 사라지고, 안 고쳐진 채로 수렴 판정이 난다(위와 같은 클래스의 버그).
|
||||||
|
const failedFiles = []
|
||||||
|
fixed.forEach((r, i) => {
|
||||||
|
if (r === null) {
|
||||||
|
const [file, items] = fileEntries[i]
|
||||||
|
failedFiles.push(file)
|
||||||
|
items.forEach((f) => seen.delete(keyOf(f)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (failedFiles.length) {
|
||||||
|
log(`⚠️ 라운드 ${round}: 반영 실패 ${failedFiles.length}건 — ${failedFiles.join(', ')} (다음 라운드에서 재시도)`)
|
||||||
|
}
|
||||||
|
|
||||||
|
roundLog.push({
|
||||||
|
round,
|
||||||
|
fresh: fresh.length,
|
||||||
|
files: fileEntries.map(([f]) => f),
|
||||||
|
fixFailed: failedFiles,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const converged = dry >= DRY_ROUNDS_TO_CONVERGE
|
const converged = dry >= DRY_ROUNDS_TO_CONVERGE
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ Roblox가 2026-02부터 Studio에 **MCP 서버를 내장**했음 — 예전처
|
||||||
|
|
||||||
**주의(사용자가 이미 말한 것)**: Roblox Studio는 잘 죽는 편 — 죽었을 때 살리려고
|
**주의(사용자가 이미 말한 것)**: Roblox Studio는 잘 죽는 편 — 죽었을 때 살리려고
|
||||||
위험한 명령을 반복 시도하지 않을 것이고, 그런 날엔 MCP 없이 할 수 있는 작업만
|
위험한 명령을 반복 시도하지 않을 것이고, 그런 날엔 MCP 없이 할 수 있는 작업만
|
||||||
하거나 대기함. 이 안전 원칙은 `CLAUDE.md`에도 적어둠.
|
하거나 대기함. 이 안전 원칙은 `.claude/conventions.md`에도 적어둠.
|
||||||
|
|
||||||
**해야 할 일**: 테스트용 place 파일(빈 place 하나, 또는 `quad/test.project.json`
|
**해야 할 일**: 테스트용 place 파일(빈 place 하나, 또는 `quad/test.project.json`
|
||||||
기반 rojo 싱크 대상)을 열어서 베타 기능만 켜주면 됨. 이후 MCP 서버 설정 파일
|
기반 rojo 싱크 대상)을 열어서 베타 기능만 켜주면 됨. 이후 MCP 서버 설정 파일
|
||||||
|
|
|
||||||
|
|
@ -826,9 +826,9 @@ Luau 코드로 부딪혀본 적 없는 세 가지**를 던지는 코드로 검
|
||||||
대체·해소됨) — `.claude/question.md` 1번, 최종 이름 확정되는 대로
|
대체·해소됨) — `.claude/question.md` 1번, 최종 이름 확정되는 대로
|
||||||
아무 시점에나
|
아무 시점에나
|
||||||
- [ ] 각 마일스톤 완료 시 `.claude/qa-request/`/`.claude/archive/`에 기록,
|
- [ ] 각 마일스톤 완료 시 `.claude/qa-request/`/`.claude/archive/`에 기록,
|
||||||
필요하면 `CLAUDE.md` "세션 히스토리"도 갱신(전체 원문은
|
필요하면 `.claude/session-summary.md` "세션 히스토리"도 갱신(전체 원문은
|
||||||
`.claude/session/`에, CLAUDE.md엔 2~4줄 요약+링크만 — 2026-08-11
|
`.claude/session/`에, `.claude/session-summary.md`엔 2~4줄 요약+링크만
|
||||||
재구조화 세션 참고)
|
— 2026-08-11 재구조화 세션 참고)
|
||||||
|
|
||||||
## 백로그 (스코프 밖 — 필요성이 실제로 드러나면 그때 설계)
|
## 백로그 (스코프 밖 — 필요성이 실제로 드러나면 그때 설계)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue