docs: 감사 툴링 재시작 검증 + 핸드오버 감사 첫 실동(수렴 실패), 인용 3건 정정
전 세션이 "재시작해야만 확인 가능"으로 남긴 3건을 전부 닫음: - @import 3개(conventions/project-context/todos) 실제 로드 확인 - quad-doc-auditor 레지스트리 등록 확인(전 세션 전멸은 .claude/agents/가 세션 도중 생긴 디렉토리였던 탓) - frontmatter model: sonnet 반영 확인(트랜스크립트에 claude-sonnet-5 기록, 워크플로에 opts.model 명시 불필요) 정의 파일은 세션 시작 시점 스냅샷으로 고정된다는 것을 1차 증거로 확정 — quad-handover-audit이 실제 실행한 스크립트가 세션 시작 시점 상태와 바이트 단위로 동일했고 같은 세션의 편집은 반영 0. 에이전트 정의도 동일. 정의를 고쳤으면 재시작 뒤에 감사를 돌릴 것(안 그러면 거짓 초록불). 전 세션 감사가 남긴 긴 가설 배너(80줄)를 검증된 것만 남겨 압축. quad-handover-audit 첫 실동: 에이전트 67개/6라운드, 수렴 실패 (새 발견 28→15→16→7→11→6, 라운드5에서 되레 증가). MAX_ROUNDS와 "연속 dry 2회" 조건 재검토 필요 — 결과 자체는 위 스냅샷 문제로 옛 스크립트가 돈 것이라 재시작 후 재실동 대상. 감사가 잡은 것 반영: slot-plan.md 정정 배너가 그 뒤 재역전(retract=언마운트)을 놓치고 있던 것, "spikes 44개"(실제 48개) 류 하드코딩 개수의 단일 소스화, doc-check.py docstring이 검사 심각도를 실제 코드와 다르게 서술하던 것 등. 인용 출처 3건 재분류 — 2건은 인용 대상만 틀린 것이라 실제 소스로 재조준 (v1-compat-plan.md→component-composition-plan.md+store-plan.md, pre-implementation-audit.md→ROADMAP.md). 진짜 출처가 없는 1건 (modifier-plan.md:536)만 question.md 3번으로 올려 사용자 판단 대기. 워크플로 개선: 반환값에 findings 추가(커밋 전 diff 리뷰 근거), totalFindingsFixed→findingsSentToFix 개명(과대계상), 반영 에이전트 sonnet 명시. .claude/agent-memory/는 의도적으로 커밋 제외(추적 여부는 사용자 판단). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
8aeec7644f
commit
298dac2510
22 changed files with 356 additions and 94 deletions
|
|
@ -6,15 +6,15 @@
|
|||
|
||||
**[2026-08-16 재구조화]** `CLAUDE.md`가 1537줄까지 불어나 사람이 검토할 수
|
||||
없고 지침 준수도도 떨어져서, 주제별로 쪼개고 `@import`로 다시 합침. 지금
|
||||
`CLAUDE.md`는 39줄짜리 진입점이고 실제 내용은 아래 세 파일에 있음(전부 매
|
||||
세션 자동 로드됨):
|
||||
`CLAUDE.md`는 짧은 진입점일 뿐이고 실제 내용은 아래 파일들에 있음(앞 셋은
|
||||
매 세션 자동 로드, `session-summary.md`/`question.md`는 온디맨드):
|
||||
|
||||
| 파일 | 무엇이 들어있나 |
|
||||
|---|---|
|
||||
| `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`) |
|
||||
| `session-summary.md` | 세션별 2~4줄 요약 색인. **`@import` 안 됨(의도적)** — 이만한 분량을 매 세션 컨텍스트에 올릴 이유가 없어 온디맨드로 둠, 선행 맥락이 필요할 때 grep해서 열 것. 자동생성 전환 예정(`research/doc-include-plan.md`) |
|
||||
| `question.md` | 사용자가 답해야 할 열린 질문(우선순위순) |
|
||||
|
||||
## 폴더 기준
|
||||
|
|
@ -25,14 +25,15 @@
|
|||
| `reference/` | **[2026-08-07 신설]** 결정 자체가 아니라 다른 문서가 근거로 인용하는 온디맨드 참고 자료(v1 스냅샷, 프레임워크 비교 리서치) — "완료" 개념 없는 건 `base/`와 같지만, 항상 읽을 필요는 없고 해당 문서가 인용될 때만 열어보면 됨. `quadnomicon` 소재 후보가 많음 |
|
||||
| `research/` | 아직 착수 전, 사용자와 스코프/설계를 더 상의해야 함 |
|
||||
| `qa-request/` | 구현 완료(코드/에이전트 검증까지 끝남) + 사용자 본인의 실기기(Roblox Studio) QA만 남음 — 지금은 구현 자체가 시작 전이라 비어있음 |
|
||||
| `archive/` | 완료 + 사용자가 실사용/실기기로 직접 검증까지 마침 (구현 대상). **[2026-08-06 확장]** 완전히 뒤집힌 설계 결정을 원문+역전 이유+diff와 함께 보존하는 용도로도 사용(제목 `[역전됨]` — 한 번 확정했다가 뒤집힌 것) — 더 이상 능동적으로 참고 안 해도 되지만(토큰 낭비 방지 위해 `base/`/`research/`에서 뺌) `quadnomicon` 소재로는 나중에 쓸 수 있음. **[2026-08-07 확장]** 후보였다가 채택 안 된 것(확정한 적 없이 검토 후 기각)도 같은 방식으로 보존, 제목은 구분을 위해 `[기각됨]` — `[역전됨]`과 의미가 다르므로 혼동하지 말 것. **[2026-08-07 세 번째 확장]** 설계 반전/기각과 별개로, 에이전트가 문서 작성 중 스스로 낸 개념 혼동을 정정한 이력은 `[에이전트 실수]` 태그로 `agent-mistake.md` 하나에 모음(CLAUDE.md 세션 로그 중복 방지) |
|
||||
| `feedback/` | 실사용 피드백을 정리한 긴 로그 — 지금은 비어있음(구현 시작 전) |
|
||||
| `archive/` | 완료 + 사용자가 실사용/실기기로 직접 검증까지 마침 (구현 대상). **[2026-08-06 확장]** 완전히 뒤집힌 설계 결정을 원문+역전 이유+diff와 함께 보존하는 용도로도 사용(제목 `[역전됨]` — 한 번 확정했다가 뒤집힌 것) — 더 이상 능동적으로 참고 안 해도 되지만(토큰 낭비 방지 위해 `base/`/`research/`에서 뺌) `quadnomicon` 소재로는 나중에 쓸 수 있음. **[2026-08-07 확장]** 후보였다가 채택 안 된 것(확정한 적 없이 검토 후 기각)도 같은 방식으로 보존, 제목은 구분을 위해 `[기각됨]` — `[역전됨]`과 의미가 다르므로 혼동하지 말 것. **[2026-08-07 세 번째 확장]** 설계 반전/기각과 별개로, 에이전트가 문서 작성 중 스스로 낸 개념 혼동을 정정한 이력은 `[에이전트 실수]` 태그로 `agent-mistake.md` 하나에 모음(`.claude/session-summary.md`/`session/` 로그와의 중복 방지) |
|
||||
| `feedback/` | 실사용 피드백을 정리한 긴 로그 — **[2026-08-16 기준] 폴더 자체가 아직 없음**(구현 시작 전, 첫 피드백이 생길 때 만들면 됨). `qa-request/`는 빈 폴더로 존재하지만 여긴 그것도 아직 아님 |
|
||||
| `luau-test/` | **[2026-08-09 신설]** `base/` 확정 사항 중 "추론만으로 확정하고 실제 Luau로 부딪혀본 적 없는 것"(M0 스파이크 대상)을 `luau`/`luau-analyze`/`luau-lsp`/Roblox Studio로 사용자가 직접 돌려볼 독립 실행 스크립트 모음. **[2026-08-13 여섯 번째 세션, 첫 실측]** `luau`/`luau-analyze` 바이너리가 생겨 처음으로 실제 실행 — **런타임 12개 전원 통과**, 타입 쪽에서 `:Compute(fn)` lazy 핸들 계약이 Luau 추론과 충돌하는 게 드러남(당시 `question.md` 0-Y). **[2026-08-13 열세 번째 세션]** 그 0-Y가 해소되며 `review-required/`가 **비었음** — 계약은 유지 확정, 남은 건 Luau 자체 한계라 `base/typing-limits.md`가 담당. **`STATUS.md`가 상태의 소스**(pass / 사람 결정 필요 / 스파이크 깨짐 / 미실행 분류 — 사람이 먼저 볼 것만 위에), `luau-test/README.md`는 각 파일의 검증 의도·배경, 실행 결과 상세는 `audit/luau-test-first-run-2026-08-13.md` |
|
||||
| `audit/` | **[2026-08-13 신설]** `luau-test/` 등 스파이크를 실제로 돌려본 뒤 "무엇이 확인됐고 무엇이 아직 안 됐는지"를 기록하는 곳 — 스크립트/계획 자체가 아니라 **실측 결과**만 다룸. base/luau-test와 달리 부분 확인(일부만 통과)도 있는 그대로 기록, 완전히 해소되면 관련 `base/`/`luau-test/README.md` 캐비엇을 지우고 이 문서는 근거로 남김. **현재 6개**: `luau-test-first-run-2026-08-13.md`(첫 실측 라운드 전체 — 런타임 12개 통과, 구 `question.md` 0-Y의 1차 근거. **단 이 문서의 "콜백이 raw 값을 받으면 완전 클린" 판정은 아래 `type-recursion-issue/`가 뒤집었음**), `gcconn-trick-verification.md`(사용자가 Studio에서 직접 돌린 gcconn 트릭 부분 확인 — `10`의 A 섹션 앞부분만. **[2026-08-14 다섯 번째 세션, 열한 번째 세션에 `canBound` 재도입 반영해 재갱신]** 실측된 사실 자체는 그대로 유효하고 `value` 단독 1-인자 재정정으로 오히려 더 중요해졌음 — 이중 바인딩 게이트(`canBound`)/emit 게이팅(`canExecute`)/재바인딩 허용/`value` 쪽 복사 gcconn 판정/Instance userdata 동일성/B/C가 미확인), **`type-recursion-issue/`**(**[2026-08-13 열세 번째 세션 신설]** 0-Y 재실측 전체 — `REPORT.md` + `spikes/` 44개. 다른 audit 기록과 달리 **스크립트를 같이 둠**: 이 건의 근거가 "여러 formulation을 서로 대조한 것"이라 개별 파일을 직접 돌려야 판정이 재현되기 때문. 결론은 `base/typing-limits.md`로 승격됨), `fallback-xpcall-verification.md`(**[2026-08-14 신설]** `base/fallback-plan.md`의 `Traceback` 메커니즘 전부 확인 — 클로저 업밸류 배선/중첩 스택 캡처/`err: any`/`error(msg)` 위치 접두 10개 검증 전부 통과. 스크립트 1개뿐이라 재현용으로 같이 둠: `fallback-xpcall-spike.luau`), **`type-recursive-issue-with-typeof/`**(**[2026-08-15 신설]** 사용자가 발견한 `typeof(named fn)` 간접참조가 0-Y(재귀 제네릭 반환 leak)를 실제로 우회하는지 실측 — `REPORT.md` + `spikes/`. 결론: 인라인 대신 이름 붙은 함수 + `typeof`로 선언하면 LHS 명시 없이도 다운스트림이 안전해짐(체이닝 50단·타입 변경·중첩 self 호출까지 확인), `typing-limits.md` §1 ③으로 승격. 부수적으로 `setmetatable` 확장 시도에서 quad와 무관한 Luau 0.733 솔버 버그(모순 진단 두 개 동시 발생) 발견, 채택 안 함. `luau-test/16`(type function으로 `Store<T>` 레코드 필드 합성) 복구도 이 조사 중 완료 — API 버전 드리프트였을 뿐 설계 문제 아니었음, `typing-limits.md` §5 승격), **`type-recursive-issue-try-callback/`**(**[2026-08-15 신설]** 콜백 파라미터 무주석 추론을 뚫을 방법이 정말 없는지 type function/메타테이블/오버로드/제네릭 디폴트 등 전방위로 재시도 — `REPORT.md` + `spikes/` 35개(00~19는 최초 라운드, `/code-review high`가 이중 꺾쇠 명시적 제네릭 인스턴스화를 안 시도했음을 지적해 20~33(+21b) 후속 조사 추가). 결론: quad의 `state:Compute(fn)` 단일 호출 모양을 유지한 채로는 여전히 안 됨. 발견 셋 — (1) 근본 원인이 재귀 자기참조가 아니라 "제네릭 콜백 인자 전반에 컨텍스트 타입 전파가 안 됨"이라는 게 더 정확함(재귀 없는 최소 사례로도 재현), (2) `T`를 명시 중간 변수로 먼저 고정하거나 재사용 가능한 monomorphize 헬퍼를 거치면 실제로 추론이 살아나지만 둘 다 단일 콜론 호출을 2단계 체인으로 바꿔야만 해서 §0 대전제로 채택 안 함, (3) 이중 꺾쇠 명시 인스턴스화(`Compute<<T,U>>(fn)`)는 leaf 호출에선 sound하게 성립하지만(spurious 진단 원인도 규명 — read-only/read-write 가변성 불일치) 매 호출 T/U 전부 명시 필요 + 중첩 self 호출 여전히 실패라 순손해로 채택 안 함) |
|
||||
| `audit/` | **[2026-08-13 신설]** `luau-test/` 등 스파이크를 실제로 돌려본 뒤 "무엇이 확인됐고 무엇이 아직 안 됐는지"를 기록하는 곳 — 스크립트/계획 자체가 아니라 **실측 결과**만 다룸. base/luau-test와 달리 부분 확인(일부만 통과)도 있는 그대로 기록, 완전히 해소되면 관련 `base/`/`luau-test/README.md` 캐비엇을 지우고 이 문서는 근거로 남김. **현재 6개**: `luau-test-first-run-2026-08-13.md`(첫 실측 라운드 전체 — 런타임 12개 통과, 구 `question.md` 0-Y의 1차 근거. **단 이 문서의 "콜백이 raw 값을 받으면 완전 클린" 판정은 아래 `type-recursion-issue/`가 뒤집었음**), `gcconn-trick-verification.md`(사용자가 Studio에서 직접 돌린 gcconn 트릭 부분 확인 — `10`의 A 섹션 앞부분만. **[2026-08-14 다섯 번째 세션, 열한 번째 세션에 `canBound` 재도입 반영해 재갱신]** 실측된 사실 자체는 그대로 유효하고 `value` 단독 1-인자 재정정으로 오히려 더 중요해졌음 — 이중 바인딩 게이트(`canBound`)/emit 게이팅(`canExecute`)/재바인딩 허용/`value` 쪽 복사 gcconn 판정/Instance userdata 동일성/B/C가 미확인), **`type-recursion-issue/`**(**[2026-08-13 열세 번째 세션 신설]** 0-Y 재실측 전체 — `REPORT.md` + `spikes/`(개수는 폴더가 소스). 다른 audit 기록과 달리 **스크립트를 같이 둠**: 이 건의 근거가 "여러 formulation을 서로 대조한 것"이라 개별 파일을 직접 돌려야 판정이 재현되기 때문. 결론은 `base/typing-limits.md`로 승격됨), `fallback-xpcall-verification.md`(**[2026-08-14 신설]** `base/fallback-plan.md`의 `Traceback` 메커니즘 전부 확인 — 클로저 업밸류 배선/중첩 스택 캡처/`err: any`/`error(msg)` 위치 접두 10개 검증 전부 통과. 스크립트 1개뿐이라 재현용으로 같이 둠: `fallback-xpcall-spike.luau`), **`type-recursive-issue-with-typeof/`**(**[2026-08-15 신설]** 사용자가 발견한 `typeof(named fn)` 간접참조가 0-Y(재귀 제네릭 반환 leak)를 실제로 우회하는지 실측 — `REPORT.md` + `spikes/`. 결론: 인라인 대신 이름 붙은 함수 + `typeof`로 선언하면 LHS 명시 없이도 다운스트림이 안전해짐(체이닝 50단·타입 변경·중첩 self 호출까지 확인), `typing-limits.md` §1 ③으로 승격. 부수적으로 `setmetatable` 확장 시도에서 quad와 무관한 Luau 0.733 솔버 버그(모순 진단 두 개 동시 발생) 발견, 채택 안 함. `luau-test/16`(type function으로 `Store<T>` 레코드 필드 합성) 복구도 이 조사 중 완료 — API 버전 드리프트였을 뿐 설계 문제 아니었음, `typing-limits.md` §5 승격), **`type-recursive-issue-try-callback/`**(**[2026-08-15 신설]** 콜백 파라미터 무주석 추론을 뚫을 방법이 정말 없는지 type function/메타테이블/오버로드/제네릭 디폴트 등 전방위로 재시도 — `REPORT.md` + `spikes/`(개수는 폴더가 소스 — 최초 라운드 + `/code-review high`가 이중 꺾쇠 명시적 제네릭 인스턴스화를 안 시도했음을 지적해 추가된 후속 조사 라운드로 구성). 결론: quad의 `state:Compute(fn)` 단일 호출 모양을 유지한 채로는 여전히 안 됨. 발견 셋 — (1) 근본 원인이 재귀 자기참조가 아니라 "제네릭 콜백 인자 전반에 컨텍스트 타입 전파가 안 됨"이라는 게 더 정확함(재귀 없는 최소 사례로도 재현), (2) `T`를 명시 중간 변수로 먼저 고정하거나 재사용 가능한 monomorphize 헬퍼를 거치면 실제로 추론이 살아나지만 둘 다 단일 콜론 호출을 2단계 체인으로 바꿔야만 해서 §0 대전제로 채택 안 함, (3) 이중 꺾쇠 명시 인스턴스화(`Compute<<T,U>>(fn)`)는 leaf 호출에선 sound하게 성립하지만(spurious 진단 원인도 규명 — read-only/read-write 가변성 불일치) 매 호출 T/U 전부 명시 필요 + 중첩 self 호출 여전히 실패라 순손해로 채택 안 함) |
|
||||
| `tools/` | **[2026-08-13 아홉 번째 세션 신설]** 코퍼스 기계 점검 — `doc-check.py`가 깨진 파일/절 참조, README 색인 누락, 날짜 없는 시한부 주장("아직 안 돌려봄" 등), 미반영 ⚠️ 배너를 한 번에 훑음. **중대 변경 후 커밋 전에 돌릴 것**(`python3 .claude/tools/doc-check.py`) — 수동 감사에서 나온 발견의 대부분이 이 종류였고, 실제로 문서를 쪼개다 잘못 옮긴 참조를 이게 잡아냄. ERROR는 고치고 WARN은 판단 대상 |
|
||||
| `agents/` | **[2026-08-16 신설]** 프로젝트 서브에이전트 정의(`.claude/agents/*.md`, Claude Code 표준 위치). 현재 `quad-doc-auditor.md` 하나 — `doc-check.py`가 못 잡는 의미론적 stale/모순(본문 문장이 뒤집힌 결정을 여전히 서술, 개수/목록 이중 소스 드리프트 등)을 신선한 맥락에서 찾는 읽기 전용 감사자. 중대 변경 커밋 전에 위임하는 게 기본(`CLAUDE.md` "작업 방식" 참고). `tools/`의 기계 점검과 짝을 이루는 의미론적 점검 계층 |
|
||||
| `workflows/` | **[2026-08-16 신설]** Claude Code Workflow 정의. 현재 `quad-handover-audit.js` 하나 — `quad-doc-auditor` 단일 패스는 비결정적이라 매번 다 잡는다는 보장이 없어서, 라운드마다 병렬 3회 감사+파일별 반영을 새 발견이 없는 라운드가 연속 2번 나올 때까지(최대 6라운드) 반복해 수렴시키는 다회·병렬 감사 루프. "핸드오버 준비하고 커밋해" 류 요청 시 자동으로 먼저 돌림(`CLAUDE.md` "작업 방식" 참고), 실제 `git commit`은 워크플로 밖 메인 세션이 함 |
|
||||
| `session/` | **[2026-08-11 신설]** 세션별 상세 로그 원문(시행착오·정정 전 서술 포함, `quadnomicon` 개발로그 소재용) — 루트 `CLAUDE.md`가 3196줄까지 불어나 성능 저하를 유발해서 분리함. 파일명 `YYYY-MM-DD-NN-slug.md`, CLAUDE.md의 "세션 히스토리" 절에서 각 항목이 여기로 링크. 항상 읽을 필요 없음 — 결정의 논의 과정이 궁금할 때만 |
|
||||
| `agents/` | **[2026-08-16 신설]** 프로젝트 서브에이전트 정의(`.claude/agents/*.md`, Claude Code 표준 위치). 현재 `quad-doc-auditor.md` 하나 — `doc-check.py`가 못 잡는 의미론적 stale/모순(본문 문장이 뒤집힌 결정을 여전히 서술, 개수/목록 이중 소스 드리프트 등)을 신선한 맥락에서 찾는 읽기 전용 감사자. 중대 변경 커밋 전에 위임하는 게 기본(`.claude/conventions.md` "작업 방식" 참고). `tools/`의 기계 점검과 짝을 이루는 의미론적 점검 계층 |
|
||||
| `agent-memory/` | **[2026-08-16 신설]** 서브에이전트가 라운드를 넘겨 유지하는 영속 메모리(`agent-memory/<에이전트 이름>/MEMORY.md`가 색인). 지금은 `quad-doc-auditor/` 하나 — 코퍼스 구조, 반복되는 실패 패턴 등을 기억해 감사 라운드마다 처음부터 파악하지 않게 함. **사람이 손으로 채우는 문서가 아니라 에이전트가 스스로 쓰는 것**이지만, `.gitignore` 대상이 아니라 커밋하면 코퍼스 일부가 되고 `doc-check.py` 검사 대상에도 들어감(감사 대상이기도 하다는 뜻 — 여기 적힌 주장도 stale해질 수 있음). **[2026-08-16 기준] 아직 커밋 안 됨(untracked)** — 추적할지 `.gitignore`로 뺄지는 사용자 판단 |
|
||||
| `workflows/` | **[2026-08-16 신설]** Claude Code Workflow 정의. 현재 `quad-handover-audit.js` 하나 — `quad-doc-auditor` 단일 패스는 비결정적이라 매번 다 잡는다는 보장이 없어서, 라운드마다 병렬로 여러 번 감사+파일별 반영을 새 발견이 없는 라운드가 연속으로 나올 때까지 반복해 수렴시키는 다회·병렬 감사 루프(라운드당 패스 수·수렴 조건·최대 라운드는 튜닝 대상 상수라 여기 숫자를 적지 않음 — 소스는 `quad-handover-audit.js` 상단). "핸드오버 준비하고 커밋해" 류 요청 시 자동으로 먼저 돌림(`.claude/conventions.md` "작업 방식" 참고), 실제 `git commit`은 워크플로 밖 메인 세션이 함 |
|
||||
| `session/` | **[2026-08-11 신설]** 세션별 상세 로그 원문(시행착오·정정 전 서술 포함, `quadnomicon` 개발로그 소재용) — 루트 `CLAUDE.md`가 3196줄까지 불어나 성능 저하를 유발해서 분리함. 파일명 `YYYY-MM-DD-NN-slug.md`, `.claude/session-summary.md`의 각 항목이 여기로 링크. 항상 읽을 필요 없음 — 결정의 논의 과정이 궁금할 때만 |
|
||||
| `initreq/` | 프로젝트 착수 시 클론해둔 참고 레포(quad v1, fusion, vide, rbvm, tbox, code-docker) + PA님 실 코드(`artworks/`, 4차 라운드 교차검증 근거) + 원본 요청(`req.md`, `raw-userinput.md`) + `quad2-try`(이전에 시도했다 폐기한 v2 재작성 시도 — 리서치 완료, 결론은 `base/bind-system-plan.md`) — 읽기 전용 리서치 소스, 여기 내용을 옮기지 말고 항상 원본 그대로 유지 |
|
||||
|
||||
`research/`의 문서가 설계 확정되면 `base/`로 승격(또는 구현 착수 시
|
||||
|
|
@ -44,7 +45,7 @@
|
|||
| 문서 | 내용 |
|
||||
|---|---|
|
||||
| `architecture.md` | quad-v2 전체 아키텍처 확정 사항 요약(제일 먼저 볼 문서). **[2026-08-12 세션 신설, 같은 날 후속 세션에서 강화]** "코드 스타일 — Luau 문법 관례" 절 신설 — `if-then-else`가 공식 Luau 문법임을 명문화(환각/오타로 오인해 `and`/`or`로 되돌리는 회귀 방지), `A and B or C` 삼항 관용구는 항상-truthy 예외도 없이 전면 금지로 강화(`bind-system-plan.md`의 `retractUnder` falsy-값 버그가 실사례). `const` 바인딩은 공식 문법이나 툴링 미성숙으로 지금은 채택 보류 |
|
||||
| `typing-limits.md` | **[2026-08-13 열세 번째 세션 신설]** Luau 타입 시스템이 quad 설계에 대해 **못 해주는 것**을 한 군데 모은 확정 문서 — 여러 `base/` 문서에 캐비엇으로 흩어져 있던 걸 통합. 대전제는 "**Luau의 한계를 우회하려고 타입/API를 비틀지 않는다**"(비틀면 나중에 Luau가 고쳐줘도 자동 수혜를 못 받고 되돌리는 마이그레이션이 생김). 1번 항목이 가장 큼 — **재귀 제네릭이 다른 타입 인자로 자기를 반환하면(`Compute<U>(self: State<T>,...) -> State<U>`) 타입 안전성이 에러 없이 조용히 사라짐**(구 `question.md` 0-Y, 스파이크 44개로 확정). 대응은 두 개: (a) 타입 선언을 "데이터부/메소드부"로 쪼개 콜백 파라미터 추론을 살리고, (b) **파생 State를 만드는 자리마다 결과 타입을 명시 주석으로 바인딩**(그 한 줄만 검증 안 되고 다운스트림 전체는 정상 체크됨). Luau RFC `relax-recursive-type-restriction`이 `Promise<T>.andThen`으로 예시 든 바로 그 패턴이라 **지금 선언 그대로 두면 Luau 쪽 수정만으로 코드 변경 없이 풀림**(추적: `luau-lang/luau#2380`). **[2026-08-15 추가]** ③ 인라인 대신 이름 붙은 함수 + `typeof`로 선언하면 콜백 파라미터 주석은 여전히 필요하지만 LHS 명시 없이도 다운스트림이 안전해짐(①을 대체하지 않음, 보강). 그 외 Modifier `Overridden` 서브타입/Attribute 제네릭 키 narrowing/nilable default 오버로드도 여기 통합, `store.key` type function 한계는 **검증 완료로 승격**(§5), 7번에 **새 타입·API 설계 시 체크리스트**. 실측 근거는 `audit/type-recursion-issue/` + `audit/type-recursive-issue-with-typeof/` |
|
||||
| `typing-limits.md` | **[2026-08-13 열세 번째 세션 신설]** Luau 타입 시스템이 quad 설계에 대해 **못 해주는 것**을 한 군데 모은 확정 문서 — 여러 `base/` 문서에 캐비엇으로 흩어져 있던 걸 통합. 대전제는 "**Luau의 한계를 우회하려고 타입/API를 비틀지 않는다**"(비틀면 나중에 Luau가 고쳐줘도 자동 수혜를 못 받고 되돌리는 마이그레이션이 생김). 1번 항목이 가장 큼 — **재귀 제네릭이 다른 타입 인자로 자기를 반환하면(`Compute<U>(self: State<T>,...) -> State<U>`) 타입 안전성이 에러 없이 조용히 사라짐**(구 `question.md` 0-Y, 스파이크 다수로 확정 — 근거·개수는 `audit/type-recursion-issue/`). 대응은 두 개: (a) 타입 선언을 "데이터부/메소드부"로 쪼개 콜백 파라미터 추론을 살리고, (b) **파생 State를 만드는 자리마다 결과 타입을 명시 주석으로 바인딩**(그 한 줄만 검증 안 되고 다운스트림 전체는 정상 체크됨). Luau RFC `relax-recursive-type-restriction`이 `Promise<T>.andThen`으로 예시 든 바로 그 패턴이라 **지금 선언 그대로 두면 Luau 쪽 수정만으로 코드 변경 없이 풀림**(추적: `luau-lang/luau#2380`). **[2026-08-15 추가]** ③ 인라인 대신 이름 붙은 함수 + `typeof`로 선언하면 콜백 파라미터 주석은 여전히 필요하지만 LHS 명시 없이도 다운스트림이 안전해짐(①을 대체하지 않음, 보강). 그 외 Modifier `Overridden` 서브타입/Attribute 제네릭 키 narrowing/nilable default 오버로드도 여기 통합, `store.key` type function 한계는 **검증 완료로 승격**(§5), 7번에 **새 타입·API 설계 시 체크리스트**. 실측 근거는 `audit/type-recursion-issue/` + `audit/type-recursive-issue-with-typeof/` |
|
||||
| `lifecycle-pattern.md` | rbvm의 `Connected`+GC 관용구를 quad-v2가 채택하는 방식. **[2026-08-14 다섯 번째 세션, 시그니처 정정]** `bindLifetime(inst,value)`/`unbindLifetime(value)`/`canExecute(value)` — 뒤의 둘은 `inst`를 안 받음(`bindLifetime`이 바인딩 시점에 gcconn 참조를 `value` 쪽 `Relate`로 복사해두므로 `value` 하나로 생존을 물을 수 있고, 실제 호출부인 State 전파 루프엔 애초에 `inst`가 없음). `.Subscribed`는 전역 `:Subscribe()` 전용 필드로 분리(`bindLifetime`은 읽지도 쓰지도 않음), gcconn/gchold는 lazy가 아니라 **Instance 생성 시점**에 만들고 클로저가 `gchold`와 `inst`를 둘 다 캡처(userdata 포인터 동일성 = `inst`-키 `Relate` 전체의 전제). 옛 2-인자 모델은 `archive/canexecute-inst-arg-reversed.md`. **[2026-08-14 열한 번째 세션]** 별도 `canBound`가 다시 도입됨 — `bindLifetime`/`Observer:Subscribe()`의 이중 바인딩 가드는 `canBound`, State emit 전파 게이팅만 `canExecute`(판정 로직은 비공개 헬퍼 `isBoundAlive` 하나를 공유) |
|
||||
| `store-plan.md` | **[2026-08-14 신설 — `bind-system-plan.md` 3단계 분할 + 구 store-semantics.md 흡수]** Store = **이름 붙은 Source 모음, 그 이상 아님** — Store 부작용 허용이 기본 디자인(국소적 vs 경계를 넘는 부작용), `defaults`는 선택적 초기값 템플릿(원본을 나중에 mutate해도 UB 아님)이고 **eager 생성과 lazy 생성이 둘 다 필요**(Luau 타입은 런타임에 강제 안 되므로), `table.clone` 기반 eager 생성 스케치, `store.key`(dot-access)가 1급 경로이고 `store "key"` 문자열 커링은 동적 키용 미타입 폴백, 레코드 필드 타이핑은 Luau `type function`으로 해결 확인, `store.key = value` 폐기 → `store.key:Set(value)`(타입 대칭성+lazy 정직성), "Store가 Store를 저장 가능한가"는 **그런 경우를 안 만듦**으로 확정(`State<State<T>>`와는 다른 축) |
|
||||
| `source-state-plan.md` | **[2026-08-14 신설 — `bind-system-plan.md` 3단계 분할 + 구 store-semantics.md 흡수]** 반응형 코어: `Source`⊇`State` 구조적 서브타입(`RefSource` 폐기, 단방향 의존으로 Luau 솔버 회피 — 스파이크 `08` 통과), **push-invalidate/pull-recompute** 전파 모델과 "관측해야 실체화된다" 전역 원칙, State 체인 플래튼 기각(캐싱이 State의 존재 이유), `:With`도 매번 새 노드(clone 계열인 `Tag`/`Modifier`와 혼동 주의), `:Compute`의 lazy 핸들 계약(`:Get()` 누락이 반복되는 실수)·trailing args sugar·`fn(self, previous?, ...deps)` 순서·`previous`, `:Apply`, `:Emit()`(Source 원천 전용 하드 경계)과 `Store<T>`/`Source<T>`의 `T`가 Modifier일 수 없는 따름정리, `state:Observer(fn)`, `:Subscribe()`/`:Unsubscribe()`, **이중 바인딩 금지 게이트**(`canBound`, State emit 전파 게이팅은 `canExecute` — `base/lifecycle-pattern.md`의 "`canBound` vs `canExecute`" 절이 소스), PA님 코드 교차검증. **[2026-08-14 열두 번째 세션]** 새 절 "Observer/Effect Leaf dedup" — `RefLeafHandler`와 같은 `old ~= v` dedup(성능 최적화, correctness엔 불필요) |
|
||||
|
|
@ -91,7 +92,7 @@
|
|||
| `debounce-throttle-plan.md` | **[2026-08-14 신설]** 시간 기반 전파 게이트 `Debounce`/`Throttle` — 사용자 요청("`Blocker`와 유사하게")으로 신설. 요지: (1) `Blocker`가 이미 쓰는 게이트 노드의 **릴리스 트리거만 타이머로 바꾼 것**이라 새 전파 메커니즘이 아님 — `Blocker` 구현(M3) 시점에 게이트를 공용으로 빼두는 게 쌈, (2) 무효화 채널만 만지므로 laziness 안 깨짐, (3) **Debounce/Throttle의 차이는 "신호가 창 타이머를 리셋하는가" 한 비트뿐** — 공개 생성자는 둘, 구현은 하나(초안의 lodash식 `maxWait` 공식엔 trailing 통과 직후 이중 발화 버그가 있었음), (4) 알고리즘은 quad-base + 주입 op 2개 `setTimeout(func, delay) -> Timeout`/`clearTimeout`(Roblox `task.delay`/`task.cancel`로 배선 — **인자 순서 반대라 주의**). `os.clock()`은 Luau 표준 라이브러리라 주입 대상 아님(단 절대 시각이 아니라 **diff 전용**), 취소 없는 엔진도 래핑+유효 플래그로 대응 가능, `Timeout`은 `{ __type_timeout: true, _native: any }`. **부수 성과**: 이 설계 중 `source-state-plan.md`의 무효화 dedup 서술이 `Observer` 계약과 모순되는 게 발견돼 base 전면 정정(`archive/invalidate-dedup-propagation-reversed.md`) | 하 — M0 안 막음(코어 계약 변경 없음), 다만 순수 슈가가 아니라 실제 기능 갭이라 `operator-sugar-plan.md`보다는 위. 의존은 M3(State)+백엔드 주입. 남은 열린 질문: 이름(Roblox 관용 debounce와 충돌)/값 지연 의미론/제어 핸들 `Flush`/`Time=0` 허용 |
|
||||
| `quad-recursive-acronym.md` | **[2026-08-14 신설]** GNU/WINE류로 `Quad`를 재귀 약어화하는 카피 브레인스토밍 — 설계 결정도 착수 게이팅도 아니고 나중에 README.md 헤딩 등에 쓸 캐치프레이즈 후보 모음. 자학 개그 방향(기각)과 지연평가/재귀·커링/펑터/클로저를 자랑하는 방향(채택 후보, 미확정) 정리 | 하 — 카피 소재, 설계 상의 필요 없음. 사용자가 최종 문구 고르면 반영 |
|
||||
| `v1-compat-plan.md` | v1 하위호환(compat) 레이어 — `quad-roblox-v1-compat` 패키지, v2→v1 단방향 브리지(`state:Observer()`+v1 프로퍼티 재대입), v2-in-v1/v1-in-v2 두 임베딩 방향의 기술 규칙까지 확정. quad2-try의 `quad-compat`은 빈 폴더로 실제 시도된 적 없었음을 확인 | 하 — Slot이 foreign Instance를 어떻게 다루는지만 Slot 코어 구현 시점까지 미결 |
|
||||
| `doc-include-plan.md` | **[2026-08-14 신설]** 문서 stale 감소용 include 도구 `doc-include.py`(가칭) — 원본 파일에 `<!--#summary-->` 류 마커로 요약 구간을 표시해두면 인용하는 문서가 그 구간을 기계적으로 추출해 붙여넣게 하는 도구. `doc-check.py`(사후 탐지)와 짝을 이루는 사전 차단 장치. AsciiDoc tagged include/markdown-magic이 선례, build vs buy 검토 후 Python 표준 라이브러리로 직접 제작(~100줄) 채택. 파일럿은 `CLAUDE.md` 세션 히스토리 ← `.claude/session/*.md` 요약 마커부터(부작용 최소) | 하 — M0/설계 게이트와 무관한 메타 도구, 플랜만 초안, 사용자가 내일 다듬을 예정 |
|
||||
| `doc-include-plan.md` | **[2026-08-14 신설]** 문서 stale 감소용 include 도구 `doc-include.py`(가칭) — 원본 파일에 `<!--#summary-->` 류 마커로 요약 구간을 표시해두면 인용하는 문서가 그 구간을 기계적으로 추출해 붙여넣게 하는 도구. `doc-check.py`(사후 탐지)와 짝을 이루는 사전 차단 장치. AsciiDoc tagged include/markdown-magic이 선례, build vs buy 검토 후 Python 표준 라이브러리로 직접 제작(~100줄) 채택. 파일럿은 `.claude/session-summary.md` ← `.claude/session/*.md` 요약 마커부터(CLAUDE.md 분할로 목적지가 "통째로 생성되는 파일"이 돼 단방향 생성으로 단순화됨) | 하 — M0/설계 게이트와 무관한 메타 도구. **[2026-08-16 기준]** 플랜 초안 단계, 열린 질문 미해소(소스: 이 문서의 "열린 질문" 절) |
|
||||
|
||||
## `archive/` — 완료됐거나 완전히 뒤집힌 것, 능동 참고 불필요
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ name: quad-doc-auditor
|
|||
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
|
||||
model: sonnet
|
||||
memory: project
|
||||
---
|
||||
|
||||
너는 quad(Roblox 엔진용 DOMless UI 렌더러 재작성 프로젝트)의 `.claude/` 설계
|
||||
|
|
@ -14,8 +13,29 @@ memory: project
|
|||
자기가 뭘 안 건드렸는지는 모르기 때문이다. 너는 그 변경과 무관한 신선한
|
||||
맥락에서 코퍼스 전체를 다시 읽어 그 사각지대를 메우는 역할이다.
|
||||
|
||||
너는 파일을 고치지 않는다(Edit/Write 도구가 없다). 발견한 것만 구조화해서
|
||||
보고하고, 실제 반영은 너를 호출한 세션이 한다.
|
||||
너는 파일을 고치지 않는다 — 발견한 것만 구조화해서 보고하고, 실제 반영은
|
||||
너를 호출한 세션이 한다. 이 규칙은 도구 유무가 아니라 **행동 규약**이다 —
|
||||
어떤 이유로 쓰기 도구가 주어지더라도 문서를 직접 고치지 마라.
|
||||
|
||||
> **[2026-08-16] 정의 파일은 세션 시작 시점 스냅샷으로 고정된다 — 고쳤으면
|
||||
> 재시작한 뒤에 감사를 돌릴 것.** 이 배너는 같은 날 감사 라운드들이 남긴
|
||||
> 긴 가설 서술을 검증된 것만 남겨 압축한 것이다(경위 원문은
|
||||
> `.claude/session/2026-08-16-01-subagent-audit-and-claudemd-split.md`).
|
||||
> 확인된 것:
|
||||
> - **스냅샷 고정 — 1차 증거 있음.** `quad-handover-audit` 실행 시 실제로
|
||||
> 돌아간 스크립트 파일이 세션 시작 시점 상태와 **바이트 단위로 동일**했고,
|
||||
> 같은 세션에서 그 파일에 가한 편집은 전혀 반영되지 않았다. 에이전트
|
||||
> 정의도 같아서, 감사 에이전트들이 받은 지시문엔 그 세션에 추가된 배너가
|
||||
> 실려 있지 않았다. **워크플로·에이전트 정의 모두 해당.**
|
||||
> - **`model: sonnet`은 반영된다** — 서브에이전트 트랜스크립트에서
|
||||
> `claude-sonnet-5` 확인(자기 보고가 아니라 기록 기준).
|
||||
> - **Write/Edit이 주어지는 원인은 미확정.** `memory: project`를 뺐지만
|
||||
> 재시작 뒤 재확인은 아직 안 했다. 그래서 위 행동 규약이 유일한 보루다.
|
||||
> - **"Grep/Glob이 안 주어졌다"는 두 소스가 어긋나는 미해결 불일치다** —
|
||||
> 호출하는 세션이 보는 에이전트 등록 목록엔 Grep/Glob이 **포함돼 있는데**,
|
||||
> 실행된 에이전트는 자기 도구를 Read/Bash/Write/Edit으로 보고했다. 어느
|
||||
> 한쪽을 실측으로 확정하지 말고, (d)와 함께 재시작 직후 깨끗한 실행에서
|
||||
> 같이 볼 것.
|
||||
|
||||
## 절차
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
오히려 더 중요해졌음** — `bindLifetime`/`canExecute`/`unbindLifetime`
|
||||
재정정으로 `canExecute(value)`가 **`value` 쪽 릴레이션에 복사된 gcconn의
|
||||
`.Connected`를 직접 읽는 것**이 leaf 경로 생존 판정의 전부가 됐기 때문
|
||||
(`base/lifecycle-pattern.md`의 "`bindLifetime`/`canExecute`/`unbindLifetime`
|
||||
— 확정" 절). **[재정정, 2026-08-14 열한 번째 세션] `canBound`는 폐기되지
|
||||
(`base/lifecycle-pattern.md`의 "`bindLifetime`/`canBound`/`canExecute`/
|
||||
`unbindLifetime` — 확정" 절). **[재정정, 2026-08-14 열한 번째 세션] `canBound`는 폐기되지
|
||||
않고 별도 진입점으로 재도입됨** — 이중 바인딩 게이트(`bindLifetime`/
|
||||
`Observer:Subscribe()`)는 `canBound`, State emit 전파 게이팅만
|
||||
`canExecute`(판정 로직은 비공개 헬퍼 하나를 공유, `base/lifecycle-pattern.md`의
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
> 확정됐고, 콜백의 lazy 핸들 계약은 **그대로 유지**됩니다.
|
||||
>
|
||||
> - 지금 유효한 규약: **`base/typing-limits.md`**
|
||||
> - 재실측 전문(스파이크 44개): **`audit/type-recursion-issue/`**
|
||||
> - 재실측 전문: **`audit/type-recursion-issue/`**(개수는 `spikes/` 폴더가 소스)
|
||||
>
|
||||
> 아래 런타임 스파이크 결과(12개 통과, `04`/`07`/`18` 절)는 **그대로
|
||||
> 유효**합니다 — 정정 대상은 타입 절뿐입니다.
|
||||
|
|
|
|||
|
|
@ -10,12 +10,14 @@
|
|||
> > 될 때 해결될 이슈로써, 당장 우리가 할 수 있는 바 없다."
|
||||
>
|
||||
> **지금 유효한 설계 규약은 `base/typing-limits.md`가 소스** — 이
|
||||
> 문서는 그 결론에 이른 실측 근거(실험 44개 + RFC/소스 대조)를 원문
|
||||
> 문서는 그 결론에 이른 실측 근거(`spikes/` 폴더의 실험 전체 + RFC/소스 대조)를 원문
|
||||
> 그대로 보존하는 audit 기록입니다. 규약만 필요하면 `typing-limits.md`를
|
||||
> 보고, "왜 그렇게 정해졌나"가 궁금할 때만 이 문서를 여세요.
|
||||
|
||||
**이 폴더의 구성**: 이 `REPORT.md`(실측 서술) + `spikes/`(재현 스크립트
|
||||
44개). `.claude/audit/`의 다른 기록과 달리 스크립트를 같이 두는 이유는
|
||||
전체 — `00`~`43`에 `21b`~`21e` 같은 후속 변형이 더해짐, 정확한 개수는
|
||||
폴더 자체가 소스라 여기서 세지 않음). `.claude/audit/`의 다른 기록과
|
||||
달리 스크립트를 같이 두는 이유는
|
||||
이 건의 근거가 "여러 formulation을 서로 대조한 것"이라 개별 파일을
|
||||
직접 돌려봐야 판정이 재현되기 때문입니다(`luau-analyze spikes/<파일>`,
|
||||
추론된 실제 타입까지 보려면 `luau-analyze --annotate spikes/<파일>`).
|
||||
|
|
@ -444,7 +446,9 @@ type Promise<T> = {
|
|||
|
||||
## 7. 실험 파일 인덱스
|
||||
|
||||
`00`~`25`(초안, 문제 A 중심)와 `26`~`35`(정정, 문제 B 발견)로 나뉩니다.
|
||||
`00`~`25`(초안, 문제 A 중심), `26`~`35`(정정, 문제 B 발견), `36`~`43`
|
||||
(후속 — 명시 제네릭 인자/미래 대비)로 나뉩니다(`21b`~`21e`처럼 뒤에 끼워
|
||||
넣은 변형은 원래 번호 옆에 붙어 있습니다).
|
||||
자세한 개별 실험 설명은 각 파일 상단 주석 참고. 핵심만:
|
||||
|
||||
| 파일 | 확인 내용 | 결과 |
|
||||
|
|
|
|||
|
|
@ -533,8 +533,16 @@ Modifier 값을 변수/모듈 상수로 만들어 재사용하는, 기존에도
|
|||
|
||||
**미검토로 남긴 것**: `Apply` 체인이 실측으로 병목이라고 확인되면 그때
|
||||
"unsafe/fast-path mutable 빌더" 같은 별도 opt-in을 검토할 수 있으나, 지금은
|
||||
근거 없는 선제 최적화라 설계하지 않음 — CLAUDE.md의 "드문 오용/가상 미래
|
||||
요구까지 방어/최적화하려고 구조를 복잡하게 만들지 않는다" 원칙과 동일.
|
||||
근거 없는 선제 최적화라 설계하지 않음 — "드문 오용/가상 미래 요구까지
|
||||
방어/최적화하려고 구조를 복잡하게 만들지 않는다" 원칙과 동일.
|
||||
|
||||
> **[2026-08-16] 위 인용의 출처가 코퍼스에 없음 — 사용자 판단 대기.**
|
||||
> 원래 이 문장은 그 원칙을 `CLAUDE.md`의 것으로 인용했으나, 코퍼스 전체
|
||||
> grep과 `git log -S`(CLAUDE.md 전 히스토리) 어디에도 그런 서술이 없음.
|
||||
> 원칙을 `conventions.md`에 정식으로 명문화할지, 아니면 출처 없이 이
|
||||
> 문서의 지역 논거로만 둘지는 사용자가 정할 것 — `question.md`의
|
||||
> "인용 출처 없는 원칙" 항목 참고. 이 문장이 지지하는 결론("지금은
|
||||
> 설계하지 않음") 자체는 영향받지 않음.
|
||||
|
||||
### 9-2. `Overridden`가 서로 다른(그러나 상하위 관계인) Modifier 타입을 섞는 경우 —
|
||||
타입 시그니처 미확정 (2026-08-07 다섯 번째 세션 후속)
|
||||
|
|
|
|||
|
|
@ -218,10 +218,14 @@ Slot이 store 바인드로 들어오는 경우, pluggable 처리기에 `retract`
|
|||
미리 수행하고 다시 `process`하면 되므로, 부모에게 위임(자식 slot 요소 자체가
|
||||
스스로 정리를 실행하는 게 아니라).
|
||||
|
||||
> **정정(2026-08-04 검증 라운드)**: 위 "부모 위임" 잠정안은 이후 **폐기**
|
||||
> 쪽으로 정정됨 — 아래 "확정" 절과 `.claude/question.md`("Slot의 `retract`
|
||||
> 동작이 '부모 위임' 잠정안에서 '폐기(옮기지 않음)'로 확정") 참고. 이 문단은
|
||||
> 검토 과정의 히스토리로만 남겨둠, 현재 유효한 동작 아님.
|
||||
> **정정(2026-08-04 검증 라운드)**: 위 "부모 위임" 잠정안은 당시 **폐기**
|
||||
> 쪽으로 정정됐었음. **[재역전, 2026-08-13 여섯 번째 세션] 그 "폐기"마저
|
||||
> 다시 뒤집혀 지금 정본은 `retract`=언마운트**(파괴 아님) — 이 문서 맨 위
|
||||
> 상태 배너, `archive/question-resolved.md` 맨 끝 확정 요약 표의
|
||||
> `base/slot-plan.md` 행, 그리고 아래 "`State<Slot>` 교체는 파괴가 아니라
|
||||
> 언마운트" 절 참고(역전된 "폐기" 원문·역전 근거는
|
||||
> `archive/slot-discard-no-portal-reversed.md`). 이 문단은 검토 과정의
|
||||
> 히스토리로만 남겨둠, 두 잠정안 모두 현재 유효한 동작 아님.
|
||||
|
||||
**[전면 정정, 2026-08-12 열한 번째 세션, 2026-08-13 다섯 번째/열네 번째
|
||||
세션에 서술 갱신] 위 "핸들러 타입이 안 바뀌면 retract 없이 process가 diff
|
||||
|
|
@ -480,8 +484,8 @@ nested `Slot`을 파괴 후 재사용하는 경로가 정확히 이 케이스).
|
|||
- **같은 바인딩이면 완전히 무시하는 게 이 자리에선 효율 문제가 아니라
|
||||
정합성 문제** — 이 no-op 가드가 없으면 **[정정, 2026-08-13 4차 감사]
|
||||
재귀 재emit이 있을 때마다 마운트된 서브트리 전체가 언마운트됐다 다시
|
||||
마운트됨**(작성 당시엔 아직 destroy 모델이었음, 위 "확정" 절 언마운트
|
||||
전환 참고 — 물리 트리 이탈+재마운트라 여전히 자식들이 들고 있던 스크롤
|
||||
마운트됨**(작성 당시엔 아직 destroy 모델이었음, 아래 "`State<Slot>` 교체는
|
||||
파괴가 아니라 언마운트" 절의 언마운트 전환 참고 — 물리 트리 이탈+재마운트라 여전히 자식들이 들고 있던 스크롤
|
||||
위치/포커스/애니메이션 상태는 유실됨, 파괴가 아니라는 것만 정정) —
|
||||
Tag의 `Contains` 힌트가 막으려던 "깜빡임" 문제보다 훨씬 파급이 큰 버전.
|
||||
`store.key:Set(sameSlotAgain)`처럼 사용자가 실수로 같은 객체를 다시
|
||||
|
|
|
|||
|
|
@ -430,8 +430,9 @@ Tag/Modifier의 클론은 호출 즉시 결과가 확정되는 값이라 "-ed"(
|
|||
> **[2026-08-13 열세 번째 세션, 해소 — 아래 계약은 그대로 확정]**
|
||||
> 한때 이 계약이 Luau 추론과 충돌한다며 `question.md` 0-Y로 열려 있었고,
|
||||
> "콜백이 raw 값을 받으면 완전히 클린"이라는 1차 판정까지 붙어 있었음.
|
||||
> **44개 스파이크 재실측 결과 그 1차 판정이 뒤집혔음** — raw 값 계약도
|
||||
> 똑같이 불안전했고, 진짜 문제는 콜백 계약이 아니라 **`Compute`가
|
||||
> **스파이크 재실측 결과 그 1차 판정이 뒤집혔음**(스파이크 개수·구성은
|
||||
> 여기서 세지 않음 — 소스는 아래 `audit/type-recursion-issue/` 폴더) —
|
||||
> raw 값 계약도 똑같이 불안전했고, 진짜 문제는 콜백 계약이 아니라 **`Compute`가
|
||||
> `State<U>`(자기 이름을 다른 타입 인자로 감싼 타입)를 반환한다는 것
|
||||
> 자체**였음(Luau의 현 한계, RFC가 `Promise<T>.andThen`으로 예시 든 바로
|
||||
> 그 패턴). **따라서 아래 lazy 핸들 계약은 바꿀 이유가 없고 그대로
|
||||
|
|
|
|||
|
|
@ -49,8 +49,9 @@
|
|||
|
||||
## 1. ⭐ 재귀 제네릭이 다른 타입 인자로 자기를 반환하면 타입 안전성이 조용히 사라짐
|
||||
|
||||
**실측 근거: `audit/type-recursion-issue/`**(REPORT.md + 재현 스파이크
|
||||
44개). 이게 이 문서에서 가장 크고, 가장 넓게 영향을 주는 항목입니다.
|
||||
**실측 근거: `audit/type-recursion-issue/`**(REPORT.md + `spikes/`의 재현
|
||||
스파이크 — 개수는 폴더가 소스). 이게 이 문서에서 가장 크고, 가장 넓게
|
||||
영향을 주는 항목입니다.
|
||||
|
||||
### 무엇이 안 되는가
|
||||
|
||||
|
|
|
|||
|
|
@ -83,9 +83,11 @@ haiku, 일반 작업은 sonnet. 특히 소스코드를 많이 읽어야 하는
|
|||
`.claude/workflows/quad-handover-audit.js`(Workflow 이름
|
||||
`quad-handover-audit`)를 먼저 돌릴 것.** 단일 `quad-doc-auditor` 패스는
|
||||
비결정적이라 매번 다 잡는다는 보장이 없다는 게 사용자 지적 — 이 워크플로는
|
||||
라운드마다 `quad-doc-auditor`를 병렬로 3회 돌리고 새 발견을 파일별로
|
||||
즉시 반영한 뒤, **새 발견이 없는 라운드가 연속 2번 나올 때까지**(최대
|
||||
6라운드) 반복해 수렴시킨다. 사용자가 정확성을 시간보다 우선한다고
|
||||
라운드마다 `quad-doc-auditor`를 병렬로 여러 번 돌리고 새 발견을 파일별로
|
||||
즉시 반영한 뒤, **새 발견이 없는 라운드가 연속으로 나올 때까지** 반복해
|
||||
수렴시킨다(라운드당 패스 수·수렴 조건·최대 라운드는 튜닝 대상 상수라
|
||||
여기 숫자를 적지 않음 — 소스는 `.claude/workflows/quad-handover-audit.js`
|
||||
상단). 사용자가 정확성을 시간보다 우선한다고
|
||||
명시했으므로 기본 워크플로 크기 가이드라인(15 에이전트 이하)을 의도적으로
|
||||
넘을 수 있음 — 이 워크플로 자체가 그 예외 대상. Workflow는 백그라운드로
|
||||
돌고 완료 시 알림이 오므로, 호출 직후 대화를 막지 말고 진행 상황만
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@
|
|||
인라이닝" 방향은 **채택 안 함**.
|
||||
|
||||
- 지금 유효한 규약: **`base/typing-limits.md`**
|
||||
- 실측 근거 전문(스파이크 44개 포함): `audit/type-recursion-issue/`
|
||||
- 실측 근거 전문(스파이크 다수 포함 — 개수는 `spikes/` 폴더가 소스):
|
||||
`audit/type-recursion-issue/`
|
||||
|
||||
`15`도 같은 계약을 다루지만 **스파이크 자체가 파싱 실패**라
|
||||
`rewrite-required/`에 그대로 둠 — 재작성 대상이지 사람 결정 대상이
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ Roblox 엔진에서 동작하는 DOMless UI 렌더러 **quad**를 처음부터
|
|||
지속 가능성 — 빠른 이터레이션보다 정확성/설계 정합성이 우선. 작업 기간은
|
||||
길게 잡음.
|
||||
|
||||
**지금은 설계/계획 단계이고 구현은 아직 시작 전** — 저장소 루트에 실제 소스
|
||||
**[2026-08-16 기준] 지금은 설계/계획 단계이고 구현은 아직 시작 전**(M0에
|
||||
착수하면 루트 `CLAUDE.md` 머리말도 같이 고칠 것 — 같은 상태를 두 곳이
|
||||
서술하고 있음) — 저장소 루트에 실제 소스
|
||||
코드(`src/` 등)가 없음. 핵심 아키텍처(Store 책임 분리, `process`/`retract`
|
||||
디스패치 모델, Store/State/Source 온톨로지, 소스 트리 구조, Modifier 메커니즘,
|
||||
컴포넌트=플레인 함수, 컴포넌트 경계 modifier/Ref 전달)는 전부 `.claude/base/`에
|
||||
|
|
@ -18,7 +20,7 @@ Roblox 엔진에서 동작하는 DOMless UI 렌더러 **quad**를 처음부터
|
|||
직접 "지금 quad에서 가장 문제되는 부분"으로 지목했던 컴포넌트화(특히
|
||||
modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션에서 수렴
|
||||
완료(`base/component-composition-plan.md`) — 남은 핵심 설계 질문은 없고,
|
||||
용어 정리(진행 중)와 실제 스캐폴딩만 남음, 아래 "지금 할 일" 참고.
|
||||
용어 정리(진행 중)와 실제 스캐폴딩만 남음, `.claude/todos.md` 참고.
|
||||
|
||||
이전에 시도했다 폐기한 v2 재작성 시도(`.claude/initreq/quad2-try`)도 리서치
|
||||
완료 — OOP 상속/커스텀 파서/Slot 스텁/`Pipe` copy-on-write 절충안은 확인된
|
||||
|
|
@ -27,7 +29,7 @@ modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션
|
|||
## 계획 문서 구조
|
||||
|
||||
`.claude/README.md`가 색인. 요약:
|
||||
- **[2026-08-16]** 루트 `CLAUDE.md`는 39줄짜리 진입점일 뿐이고, 실제 내용은
|
||||
- **[2026-08-16]** 루트 `CLAUDE.md`는 짧은 진입점일 뿐이고, 실제 내용은
|
||||
`.claude/conventions.md`(관례·작업 방식) / 이 문서 / `.claude/todos.md`
|
||||
(지금 할 일)로 쪼개져 `@import`로 다시 합쳐짐. `.claude/session-summary.md`
|
||||
(세션 요약 색인)만 **import 안 됨** — 필요할 때 직접 열 것.
|
||||
|
|
@ -36,27 +38,25 @@ modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션
|
|||
- `.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/research/` — 아직 착수 전, 사용자와 상의 필요한 설계 논의. 전부
|
||||
후순위. **어떤 문서가 있는지·우선순위가 뭔지는 여기서 세지도 나열하지도
|
||||
않고 `.claude/README.md`의 `research/` 표로 미룸**(개수뿐 아니라 파일명
|
||||
나열 자체가 새 문서가 추가될 때마다 stale해지는 패턴이 실제로 반복됐음 —
|
||||
과거엔 "두 개뿐"이라 적어놨다가, 2026-08-16엔 7개짜리 나열이 실제 11개와
|
||||
어긋난 걸 감사가 발견. 아래 luau-test/audit 문단과 같은 처리로 통일).
|
||||
`research/`를 떠난 것만 짚으면: `tween-plan.md`는 2026-08-12 세션에 마지막
|
||||
열린 항목까지 전부 해소돼 `base/`로 승격, 이미 생성된 인스턴스 재바인드는
|
||||
2026-08-14 세션에 기각돼 `archive/existing-instance-bind-rejected.md`로
|
||||
이전 — 둘 다 더 이상 여기 없음.
|
||||
- `.claude/luau-test/` — **[2026-08-09 신설]** "추론만으로 확정하고 실제
|
||||
Luau로 부딪혀본 적 없는 것"을 미리 검증하는 독립 실행 스파이크 20개
|
||||
Luau로 부딪혀본 적 없는 것"을 미리 검증하는 독립 실행 스파이크 모음
|
||||
(`luau <파일>` / `luau-analyze <파일>`). **상태의 소스는 항상 `STATUS.md`**
|
||||
(pass / 사람 결정 필요 / 스파이크 깨짐 / 미실행, 폴더 구조 자체가 상태),
|
||||
각 파일이 뭘 왜 검증하는지는 `README.md`. 2026-08-13에 첫 실측 완료(당시
|
||||
런타임 12개 전원 통과) — 이후 여러 세션에 걸쳐 재설계로 몇 건이 추가로
|
||||
`rewrite-required/`에 합류했으니 **지금 몇 개가 어디 있는지는 여기서
|
||||
나열 안 하고 `STATUS.md`로 미룸**(나열하다 stale해지는 패턴이 실제로
|
||||
반복됐음, 아래 "지금 할 일" 0번 참고).
|
||||
`rewrite-required/`에 합류했으니 **총 몇 개인지도, 지금 몇 개가 어디
|
||||
있는지도 여기서 세지 않고 `STATUS.md`로 미룸**(세거나 나열하다 stale해지는
|
||||
패턴이 실제로 반복됐음, `.claude/todos.md`의 luau-test 스파이크 항목 참고).
|
||||
- `.claude/audit/` — **[2026-08-13 신설]** 스파이크를 실제로 돌린 **실측
|
||||
결과** 기록(계획 아님). 부분 확인도 있는 그대로 남김 — **지금 몇 개가
|
||||
있는지·각각 뭘 확인했는지는 여기서 나열 안 하고 `.claude/README.md`의
|
||||
|
|
@ -64,13 +64,14 @@ modifier/Ref의 컴포넌트 경계 통과 방식) 논의도 2026-08-04 세션
|
|||
추가될 때마다 stale해지는 패턴이 실제로 반복됐음, 가장 최근엔
|
||||
2026-08-15에 이 목록이 3개에서 멈춰 있는 걸 `/code-review`가 발견).
|
||||
`type-recursion-issue/`만 참고로 짚으면: **[13차 세션]** 0-Y 재실측
|
||||
전체 — `REPORT.md` + `spikes/` 44개, **스크립트를 같이 두는** 예외적
|
||||
전체 — `REPORT.md` + `spikes/`(개수는 폴더가 소스), **스크립트를 같이 두는** 예외적
|
||||
구성(판정이 "여러 formulation 대조"라 개별 파일을 직접 돌려야 재현됨),
|
||||
결론은 `base/typing-limits.md`로 승격 — 이후 신설된 폴더들도 같은
|
||||
구성 관례를 따름(`type-recursive-issue-with-typeof/`,
|
||||
`type-recursive-issue-try-callback/` 등).
|
||||
- `.claude/qa-request/`, `.claude/feedback/` — 구현 시작되면 쓰기 시작함,
|
||||
지금은 비어있음. `.claude/archive/`는 원래 같은 취급이었으나
|
||||
**[2026-08-16 기준] 아직 비어 있음**(`feedback/`은 폴더 자체가 아직
|
||||
없음). `.claude/archive/`는 원래 같은 취급이었으나
|
||||
2026-08-06 세 번째 세션부터 **완전히 뒤집힌 설계 결정을 원문+역전
|
||||
이유+diff와 함께 보존하는 용도로도 사용 시작**(구현 완료 대상만이
|
||||
아님) — `archive/store-source-proxy-reversed.md`가 첫 사례, 나중
|
||||
|
|
|
|||
|
|
@ -31,11 +31,14 @@
|
|||
|
||||
사용자 원 메모: "quad는 register라던가 좀 부정확하거나 느낌이 바로 와닿지
|
||||
않던 용어들이 많음 — 전체적 용어를 보고 생각해볼래? 제안을 줘, 나도 같이
|
||||
볼게." **이미 확정된 이름**(`State`/`Relate`/`List`/`Ref`/
|
||||
볼게." **이미 확정된 이름**(`State`/`Relate`/`List`/`canBound`/`Ref`/
|
||||
`PreRef`/`Peek`/`isState`/`None`/`NoneHandler`/`Handler`)의 근거는
|
||||
`archive/question-resolved.md`. (`canBound`는 2026-08-14 다섯 번째 세션에
|
||||
**폐기**되어 이 목록에서 빠짐 — `canExecute` 하나로 통합됐음,
|
||||
`archive/canexecute-inst-arg-reversed.md`.)
|
||||
폐기돼 `canExecute`로 통합됐다가 **같은 날 열한 번째 세션에 별도 진입점으로
|
||||
재도입**되어 여전히 이 목록에 있음 — 이중 바인딩 가드 전용이고 `canExecute`
|
||||
(emit 게이팅 전용)와는 판정 로직만 공유. 아래 3번 `canExecute` 항목과
|
||||
`base/lifecycle-pattern.md`의 "`canBound` vs `canExecute`" 절,
|
||||
`archive/canexecute-inst-arg-reversed.md` 하단 addendum 참고.)
|
||||
|
||||
- **`DI`(Declarative Instance, 1순위)**: "Dependency Injection"의 업계
|
||||
표준 축약어와 완전히 겹침 — 4차 라운드에서 이미 한 번 실제로 오해가
|
||||
|
|
@ -110,6 +113,23 @@
|
|||
|
||||
## 3. 낮은 우선순위 — 열려 있지만 급하지 않음
|
||||
|
||||
- **인용 출처 없는 원칙 — "드문 오용/가상 미래 요구까지 방어/최적화하려고
|
||||
구조를 복잡하게 만들지 않는다"(2026-08-16 신설)** —
|
||||
`base/modifier-plan.md`의 "미검토로 남긴 것" 문단이 이 원칙을 `CLAUDE.md`의
|
||||
것으로 인용해왔으나, **코퍼스 전체 grep과 `git log -S`(CLAUDE.md 전
|
||||
히스토리) 어디에도 그런 서술이 없음** — 즉 존재한 적 없는 출처였음(같이
|
||||
발견된 다른 두 건은 인용 대상만 틀린 것이라 실제 소스로 재조준 완료:
|
||||
`research/v1-compat-plan.md`→`base/component-composition-plan.md`+
|
||||
`base/store-plan.md`, `research/pre-implementation-audit.md`→`ROADMAP.md` +
|
||||
`question.md`(이 문서)).
|
||||
선택지는 (a) 이 원칙을 `.claude/conventions.md`에 정식 명문화 —
|
||||
실제로 여러 설계 결정이 이 취지로 내려졌으니 한 번 적어두면 앞으로도
|
||||
인용 가능, (b) 명문화하지 않고 `modifier-plan.md`의 지역 논거로만 둠
|
||||
(이 경우 그 문단의 정정 배너를 지우고 문장만 남기면 됨).
|
||||
**어느 쪽이든 그 문단의 결론("지금은 fast-path 빌더를 설계하지 않음")은
|
||||
영향받지 않음** — 순수하게 "이 원칙을 프로젝트 공식 관례로 승격할
|
||||
것인가"만 묻는 질문.
|
||||
|
||||
- **`Operator` 콤비네이터 슈가 네임스페이스 이름+포함 범위(2026-08-12 신설,
|
||||
같은 날 후속으로 외부 리서치 완료)** — `Sum`/`Product`/`Not`/비트연산 등
|
||||
`:Compute`/`:Apply`용 슈가 함수 모음의 이름. 흔한 단어라 top-level
|
||||
|
|
|
|||
|
|
@ -97,7 +97,8 @@ ERROR, `doc-check.py` 파이프라인에 편입) 두 모드.
|
|||
|
||||
1. 마커 문법 자체(위 초안 확정 여부, id 네이밍 규칙 — 날짜+세션번호로
|
||||
충분한지).
|
||||
2. 기존 세션 항목 전부(13개+)에 마커를 소급 삽입할지, 아니면 다음
|
||||
2. 기존 세션 항목 전부(`.claude/session/` 폴더에 지금까지 쌓인 파일
|
||||
전부 — 개수는 여기 안 적음, 폴더가 소스)에 마커를 소급 삽입할지, 아니면 다음
|
||||
세션부터 신규 항목에만 적용하고 과거분은 그대로 둘지.
|
||||
3. `--write` 실행 시점 — 수동(세션 마무리 시 사람이 실행) vs 커밋 훅.
|
||||
이 레포는 지금 CI가 없고 사람이 `doc-check.py`도 수동으로 돌리는
|
||||
|
|
|
|||
|
|
@ -431,9 +431,14 @@ State<T>` 조합조차 M0 스파이크 대상(솔버가 죽을 수 있음)으로
|
|||
"역시 얇은 래퍼가 필요하다"로 뒤집히면, 이미 "그냥 함수" 규약으로 짜인
|
||||
기존 컴포넌트 전체를 마이그레이션해야 하는 연쇄가 발생.
|
||||
|
||||
**제안**: `CLAUDE.md`가 이미 M2/M3/M5에서 quad-debug 훅 확장 지점을
|
||||
고려하라고 명시해뒀으니, 그 시점에 이 질문도 같이 열어 "래퍼 없음"이
|
||||
구조적으로도 최종 확정인지 한 번 더 확인할 것. M1 스캐폴딩 전에.
|
||||
**제안**: 루트 `ROADMAP.md`의 `quad-debug` 백로그 항목("M2/M3/M5 구현 시
|
||||
훅 확장 지점만 고려해두면 이 항목 자체는 지금 착수 불필요")과
|
||||
`question.md`의 같은 서술이 이미 그 시점을 지목해뒀으니, 그때 이 질문도
|
||||
같이 열어 "래퍼 없음"이 구조적으로도 최종 확정인지 한 번 더 확인할 것.
|
||||
M1 스캐폴딩 전에. (**[2026-08-16 인용 정정]** 원래 이 근거를 `CLAUDE.md`가
|
||||
명시해뒀다고 적혀 있었으나 CLAUDE.md엔 그런 서술이 없었음 — 실제 소스는
|
||||
위 두 곳. 다만 `research/debug-tooling-plan.md` 쪽 서술은 더 약한
|
||||
"훅 확장 지점 존재 가능성만 인지해두는 정도"라는 점에 유의.)
|
||||
|
||||
### 2-4. existing-instance-bind가 Slot의 "엄격한 단일 마운트 소유권" 불변식과 근본적으로 긴장 — **[해소됨, 2026-08-14 세션: 기능 자체가 기각]**
|
||||
|
||||
|
|
|
|||
|
|
@ -47,8 +47,14 @@ v1(`.claude/initreq/quad/src`) 조사 결과, API는 성격이 다른 두 계층
|
|||
- 인스턴스화 시 생성자 인자를 자동으로 store로 감싸고(`class.lua:367`),
|
||||
이후 `comp.Text = "hi"`처럼 프로퍼티를 재대입하면 `__newindex`가 자동으로
|
||||
내부 store에 위임 + `UpdateTriggers`에 걸리면 자동 재렌더까지 발생
|
||||
(`class.lua:524-566`) — CLAUDE.md에 이미 "이 자동 위임/재렌더 매직은
|
||||
v2에서 폐기하기로 확정"이라 기록된 바로 그 메커니즘.
|
||||
(`class.lua:524-566`) — v2에서 폐기하기로 확정된 바로 그 메커니즘
|
||||
(**[2026-08-16 인용 정정]** 원래 "CLAUDE.md에 기록됨"이라 적혀 있었으나
|
||||
CLAUDE.md에 그런 서술은 없었음. 실제 소스는
|
||||
`base/component-composition-plan.md`의 "1. 컴포넌트 = 그냥 함수, "자기
|
||||
store 자동 소유" 매직은 폐기" 절(자동 흡수/자동 store 생성 매직 폐기,
|
||||
사용자 확정)과 `base/store-plan.md`의 "Store 값 설정 문법 —
|
||||
`myStore.key = value` 폐기, `source:Set(value)`로 전환" 절(`__newindex`
|
||||
자동 위임 폐기)).
|
||||
|
||||
## 3. 계층별 실현 가능성
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# 세션 히스토리 (요약 색인)
|
||||
|
||||
루트 `CLAUDE.md`가 `@import` 하지 **않음 — 의도적**. 1231줄을 매 세션
|
||||
컨텍스트에 올릴 이유가 없다는 판단(2026-08-16). 선행 맥락이 필요할 때만
|
||||
grep해서 읽는 온디맨드 자료.
|
||||
루트 `CLAUDE.md`가 `@import` 하지 **않음 — 의도적**. 세션마다 계속 자라는
|
||||
히스토리 문서라 통째로 매 세션 컨텍스트에 올릴 이유가 없다는
|
||||
판단(2026-08-16). 선행 맥락이 필요할 때만 grep해서 읽는 온디맨드 자료.
|
||||
|
||||
**[2026-08-16 기준] 이 파일은 아직 손으로 관리 중이지만, 곧 전체 자동생성으로
|
||||
전환 예정** — 각 `.claude/session/*.md`가 자기 요약을 마커 블록으로 들고 있고
|
||||
|
|
@ -1247,10 +1247,19 @@ type-recursive-issue-try-callback/`, spikes 35개) — **결론은 그대로
|
|||
사용자가 "핸드오버 전/커밋 전에 code-review 같은 걸 스스로 돌게 만들 수
|
||||
있나"에서 출발 — hook은 셸 명령만 실행해 스킬/서브에이전트를 직접 못
|
||||
부르므로, **읽기 전용 감사자 `.claude/agents/quad-doc-auditor.md`**(발견만
|
||||
리포트, `memory: project`)와 **다회·병렬 수렴 루프
|
||||
리포트 — 처음엔 `memory: project`를 켰으나, 그게 켜져 있으면 에이전트 등록
|
||||
목록에 Write/Edit이 같이 딸려오는 것으로 보여 같은 세션 후속 작업에서 다시
|
||||
뺐음. **[2026-08-16 기준] 옵션을 뺀 뒤에도 Write/Edit이 그대로 주어져 원인
|
||||
진단은 미확정**. **[2026-08-16 정정]** 한때 `.claude/agent-memory/quad-doc-auditor/`를
|
||||
"아무도 로드하지 않는 잔여물"로 적어뒀으나, 옵션을 뺀(02:03) 뒤 돌린 감사에서도
|
||||
그 디렉토리에 새 기록이 쌓이는 게 실측돼(02:11) 반증됨 — 메모리는 여전히
|
||||
로드·기록되고 있으니 잔여물로 취급하지 말 것. 최신 상태는
|
||||
`.claude/agents/quad-doc-auditor.md` 상단 배너가 소스. 어느 쪽이든 읽기
|
||||
전용은 도구 유무가 아니라 프롬프트의 행동 규약으로 못박음)와 **다회·병렬 수렴 루프
|
||||
`.claude/workflows/quad-handover-audit.js`**(라운드당 병렬 3회 감사 +
|
||||
파일별 즉시 반영을, 새 발견 없는 라운드가 연속 2번 나올 때까지 최대
|
||||
6라운드)로 나눠 구성. 첫 실측은 `.claude/agents/`가 세션 도중 생긴
|
||||
6라운드 — 이 상수들은 튜닝 대상이라 소스는 `quad-handover-audit.js` 상단,
|
||||
여기 숫자는 도입 당시 값)로 나눠 구성. 첫 실측은 `.claude/agents/`가 세션 도중 생긴
|
||||
디렉토리라 6개 전원 `agentType not found`로 실패 — **더 중요한 건 그
|
||||
실패가 `converged:true`로 보고된 것**(감사 패스가 전멸해도 `fresh`가 비어
|
||||
"깨끗한 라운드"와 구분이 안 됐음). 감사 도구 최악의 실패 모드라 즉시
|
||||
|
|
@ -1258,9 +1267,10 @@ type-recursive-issue-try-callback/`, spikes 35개) — **결론은 그대로
|
|||
빼 다음 라운드가 재시도). 이어 사용자 지적으로 **루트 `CLAUDE.md`
|
||||
1537줄을 4분할** — `conventions.md`(관례+작업 방식) /
|
||||
`project-context.md` / `todos.md`를 `@import`하고,
|
||||
**`session-summary.md`(1231줄, 전체의 80%)는 의도적으로 import 안 함**
|
||||
**`session-summary.md`(분할 전 `CLAUDE.md`의 80%)는 의도적으로 import 안 함**
|
||||
(그 문서 스스로 "항상 읽을 필요 없음, `base/`가 소스"라고 명시해왔음) —
|
||||
매 세션 로드가 1537→354줄. 부수 수확: 공식 문서에서 (a) 권장치가 파일당
|
||||
매 세션 로드가 분할 전 `CLAUDE.md` 분량의 극히 일부로 줄었음(구체적인 줄
|
||||
수는 계속 바뀌니 여기 안 적음 — 궁금하면 그때 `wc -l`). 부수 수확: 공식 문서에서 (a) 권장치가 파일당
|
||||
200줄이고 초과 시 **지침 준수도 자체가 떨어진다**는 것, (b) `@import`는
|
||||
컨텍스트를 **안 줄인다**는 것, (c) CLAUDE.md 계열의 블록 HTML 주석은
|
||||
주입 전 제거돼 **에이전트가 못 본다**는 것을 확인(자기 변경에서 실제로
|
||||
|
|
@ -1274,3 +1284,27 @@ stale")가 틀렸음**을 잡아냄(실제로는 `initreq/tbox/CLAUDE.md`를 가
|
|||
`research/doc-include-plan.md`는 이 분할로 **설계 절반이 불필요해져**
|
||||
양방향 마커 → 단방향 생성으로 단순화(목적지가 통째로 생성되는 파일이라
|
||||
`<!--#include-->` 마커 자체가 필요 없어짐).
|
||||
|
||||
**2026-08-16 두 번째 세션 — 감사 툴링 재시작 검증, 핸드오버 감사 첫 실동(수렴 실패)**
|
||||
(`session/2026-08-16-02-audit-tooling-verification-and-first-real-run.md`)
|
||||
전 세션이 남긴 재시작 검증 3건을 전부 닫음 — `@import` 로드 ✅,
|
||||
`quad-doc-auditor` 등록 ✅, frontmatter `model: sonnet` 반영 ✅(트랜스크립트
|
||||
기록 기준). **가장 큰 수확은 "정의 파일은 세션 시작 시점 스냅샷으로
|
||||
고정된다"를 1차 증거로 확정한 것** — 워크플로가 실제 실행한 스크립트가 세션
|
||||
시작 시점 상태와 바이트 단위로 같았고 같은 세션의 편집은 반영 0이었음(에이전트
|
||||
정의도 동일). **정의를 고쳤으면 재시작 뒤에 감사를 돌릴 것.** 전 세션 감사가
|
||||
남긴 "Grep/Glob 미지급"은 **두 소스가 어긋나는 미해결 불일치**로 정리(호출
|
||||
세션이 보는 등록 목록엔 포함돼 있는데 실행된 에이전트는 자기 도구에 없다고
|
||||
보고) — 어느 쪽도 확정하지 말고 재시작 직후 실행에서 볼 것. 전 세션이
|
||||
"존재하지 않는 원칙 인용" 3건으로 넘긴 것은 재분류돼 **2건이 인용 대상
|
||||
오류**로 판명(`v1-compat-plan.md`→`component-composition-plan.md`+
|
||||
`store-plan.md`, `pre-implementation-audit.md`→`ROADMAP.md`), 진짜 출처 없는
|
||||
1건(`modifier-plan.md:536`)만 `question.md` 3번으로 올려 사용자 판단 대기.
|
||||
`quad-handover-audit` 첫 실동은 에이전트 67개/6라운드에 **수렴 실패**(새 발견
|
||||
28→15→16→7→11→6, 라운드5에서 되레 증가) — 단조 감소 전제와 `MAX_ROUNDS`
|
||||
재검토 필요. 수정 품질 자체는 높았음: `slot-plan.md`의 정정 배너가 그 뒤
|
||||
재역전된 걸 놓치고 있던 것, `spikes 44개`(실제 48개) 류 하드코딩 개수의
|
||||
단일 소스화, `doc-check.py` docstring이 검사 심각도를 실제 코드와 다르게
|
||||
서술하던 것 등을 잡음. 워크플로도 개선 — 반환값에 `findings` 추가(커밋 전
|
||||
diff 리뷰 근거), `totalFindingsFixed`→`findingsSentToFix` 개명(과대계상),
|
||||
반영 에이전트 `model: 'sonnet'` 명시.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
# 2026-08-16 두 번째 세션 — 감사 툴링 재시작 검증 + 핸드오버 감사 첫 실동
|
||||
|
||||
전 세션(`2026-08-16-01-subagent-audit-and-claudemd-split.md`)이 남긴
|
||||
"재시작해야만 확인 가능한 것 3개"를 닫고, `quad-handover-audit` 워크플로를
|
||||
처음으로 **실제로 감사가 도는 상태**에서 돌린 세션.
|
||||
|
||||
## 1. 재시작 검증 3건 — 전부 확인
|
||||
|
||||
| 항목 | 결과 | 근거 |
|
||||
|---|---|---|
|
||||
| `@import` 3개 로드 | ✅ | `conventions.md`/`project-context.md`/`todos.md` 내용이 실제 컨텍스트에 들어옴 |
|
||||
| `quad-doc-auditor` 등록 | ✅ | 에이전트 목록에 잡힘. 전 세션 전멸(`agentType not found`)은 `.claude/agents/`가 세션 도중 생긴 디렉토리였던 탓 |
|
||||
| frontmatter `model: sonnet` 반영 | ✅ | 서브에이전트 트랜스크립트에 `"model":"claude-sonnet-5"` 기록. 워크플로에 `opts.model` 명시 불필요 |
|
||||
|
||||
모델 확인은 처음에 "네 모델과 도구를 보고해라"는 프로브 에이전트로 시도했다가
|
||||
**에이전트가 프롬프트 인젝션으로 판단해 거부**했다(원래 과업인 감사를 버리고
|
||||
시스템 프롬프트를 덤프하라는 지시였으니 정당한 거부). 자기 보고 대신
|
||||
트랜스크립트 파일을 직접 grep하는 쪽이 1차 증거라 더 낫다.
|
||||
|
||||
## 2. ⭐ 정의 파일은 세션 시작 시점 스냅샷으로 고정된다 (에이전트·워크플로 공통)
|
||||
|
||||
전 세션 감사 라운드들이 "캐시냐 frontmatter 무시냐"로 길게 갈라놨던 것을
|
||||
결정적으로 닫는 증거가 이 세션에서 나왔다.
|
||||
|
||||
- 이 세션에서 `.claude/workflows/quad-handover-audit.js`를 편집한 뒤
|
||||
`Workflow({name: 'quad-handover-audit'})`를 돌렸는데, 런타임이 실제로
|
||||
실행한 스크립트 파일이 **세션 시작 시점 상태(= 당시 HEAD, 작업트리가
|
||||
깨끗했음)와 바이트 단위로 동일**했다. 내 편집은 하나도 안 실렸다.
|
||||
- 같은 현상이 에이전트 정의에서도 관측됐다(감사 에이전트들이 받은 지시문에
|
||||
그 세션에 추가된 배너가 없었음).
|
||||
|
||||
**실무 규칙: 정의 파일(`.claude/agents/*.md`, `.claude/workflows/*.js`)을
|
||||
고쳤으면 세션을 재시작한 뒤에 감사를 돌릴 것.** 안 그러면 옛 정의로 돌면서
|
||||
새 정의로 돈 것처럼 보인다 — 감사 도구에선 이게 조용한 거짓 초록불이다.
|
||||
|
||||
미해소로 남은 건 **읽기 전용인데 Write/Edit이 주어지는 원인** 하나.
|
||||
`memory: project`를 뺐지만 그 뒤 재시작 없이 관찰한 것뿐이라 진단 미확정.
|
||||
|
||||
전 세션 감사가 남긴 **"Grep/Glob이 안 주어졌다"는 서술은 두 소스가 어긋나는
|
||||
미해결 불일치**다 — 호출 세션이 보는 에이전트 등록 목록엔 Grep/Glob이
|
||||
포함돼 있는데, 실행된 에이전트는 자기 도구를 Read/Bash/Write/Edit으로
|
||||
보고했다. (처음엔 "자기 보고라 근거가 약하다"고 깎으려 했으나, 에이전트는
|
||||
자기 함수 목록을 직접 볼 수 있으므로 그건 과한 판단이었다.) 어느 쪽도
|
||||
확정하지 말고 Write/Edit 원인과 함께 재시작 직후 실행에서 볼 것.
|
||||
|
||||
## 3. "존재하지 않는 원칙 인용" 3건 — 재분류 결과 2건은 인용 오류였음
|
||||
|
||||
전 세션은 셋 다 같은 성격(가짜 원칙)으로 넘겼는데, 코퍼스 grep +
|
||||
`git log -S`로 다시 보니 갈렸다.
|
||||
|
||||
- **`research/v1-compat-plan.md:50`** — 원칙 자체는 실재. 실제 소스는
|
||||
`base/component-composition-plan.md` §1(자동 store 생성/자동 흡수 매직
|
||||
폐기, 사용자 확정)과 `base/store-plan.md` "Store 값 설정 문법" 절
|
||||
(`__newindex` 자동 위임 폐기). → 재조준.
|
||||
- **`research/pre-implementation-audit.md:434`** — 역시 실재. 실제 소스는
|
||||
루트 `ROADMAP.md`의 quad-debug 백로그 항목 + `question.md`. 다만
|
||||
`research/debug-tooling-plan.md` 쪽은 더 약한 표현("존재 가능성만
|
||||
인지")이라 그 온도차도 같이 적었다. → 재조준.
|
||||
- **`base/modifier-plan.md:536`** — 이것만 **진짜로 출처가 없다.** 코퍼스
|
||||
전체에도, `git log -S`로 본 `CLAUDE.md` 전 히스토리에도 그런 서술이
|
||||
존재한 적 없다. 임의로 정하지 않고 날짜 붙인 대기 배너 + `question.md`
|
||||
3번 항목(선택지 (a) `conventions.md`에 명문화 / (b) 지역 논거로만 유지)로
|
||||
올려 **사용자 판단 대기**.
|
||||
|
||||
## 4. `quad-handover-audit` 첫 실동 — 6라운드, **수렴 실패**
|
||||
|
||||
에이전트 67개 / 라운드별 새 발견 **28 → 15 → 16 → 7 → 11 → 6**. 최대
|
||||
라운드(6)를 소진할 때까지 새 발견이 마르지 않아 `converged:false`로 끝났다.
|
||||
과거 수동 감사가 4~6라운드에 수렴했던 것과 다른 양상.
|
||||
|
||||
- 라운드 5에서 발견이 7→11로 **다시 늘었다** — 감사가 코퍼스를 훑는 순서/
|
||||
관점이 라운드마다 달라서 생기는 것으로 보이고, 단조 감소를 전제한
|
||||
`MAX_ROUNDS=6`이 이 코퍼스엔 부족하다는 신호.
|
||||
- 이번 실행은 **위 2번 때문에 옛 스크립트로 돌았다** — 즉 이 결과 자체가
|
||||
"정의를 고치고 재시작 없이 돌린" 사례다. 다음 실동은 재시작 뒤에.
|
||||
|
||||
수정 품질 자체는 높았다. 실제로 잡힌 것 중 값진 것:
|
||||
- `base/slot-plan.md:218`의 정정 배너가 "폐기로 정정됨"에서 멈춰 있었는데,
|
||||
그 "폐기"가 2026-08-13에 **다시 뒤집혀** 지금 정본은 `retract`=언마운트다.
|
||||
배너만 보고 지나가면 구현자가 옛 결론을 믿을 자리였다.
|
||||
- `spikes 44개`류 하드코딩 개수가 여러 문서에 흩어져 있었는데 실제로는
|
||||
48개(`00`~`43` + `21b`~`21e`)였다. 전부 "폴더가 소스"로 바꿈 —
|
||||
`conventions.md`의 "개수·목록·상태는 소스를 하나만" 규칙 적용.
|
||||
- `tools/doc-check.py` docstring이 1·2번 검사 심각도를 **실제 코드와 다르게**
|
||||
적어놨던 것(둘 다 ERROR라 했지만 코드는 그렇게 동작한 적 없음). 검사
|
||||
로직은 안 건드리고 서술만 정정.
|
||||
|
||||
## 5. 워크플로 스크립트 개선(다음 실행부터 적용됨)
|
||||
|
||||
- **반환값에 `findings` 배열 추가.** 기존엔 `roundLog`에 파일명·개수만 있어
|
||||
커밋 전 diff 리뷰 때 "이 수정이 왜 들어갔는지"를 알 방법이
|
||||
`journal.jsonl` 고고학뿐이었다.
|
||||
- `totalFindingsFixed` → `findingsSentToFix`로 개명. "의심"으로 표시돼
|
||||
반영 에이전트가 확인 후 건드리지 않은 것도 "고쳐짐"으로 세던 과대계상.
|
||||
- 반영 에이전트에 `model: 'sonnet'` 명시(감사 패스는 frontmatter로 이미
|
||||
sonnet, 반영 쪽만 메인 모델을 상속하고 있었음).
|
||||
|
||||
## 남은 것
|
||||
|
||||
- **`MAX_ROUNDS` 재검토** — 수렴 실패가 재현되는지 재시작 후 실동으로 확인.
|
||||
단조 감소 전제가 안 맞으니 "연속 dry 2회" 조건 자체도 같이 볼 것.
|
||||
- **(d) Write/Edit 원인** — 다음 세션 시작 직후 확인.
|
||||
- **`.claude/agent-memory/`** — 감사 에이전트가 스스로 쓰는 영속 메모리가
|
||||
생겼고 지금 untracked. 커밋할지 `.gitignore`로 뺄지는 사용자 판단.
|
||||
- **`modifier-plan.md:536` 원칙** — `question.md` 3번, 사용자 판단 대기.
|
||||
|
|
@ -46,11 +46,12 @@
|
|||
해소돼 설계 게이트는 남아있지 않음** — 착수 전 읽을 것은 위 0번의 두
|
||||
문서(`typing-limits.md`/`dispatch-core-plan.md`)뿐이고, 스파이크 상태는
|
||||
아래 그대로:
|
||||
- **`.claude/luau-test/`(2026-08-09 신설, 2026-08-13 기준 20개) 스파이크
|
||||
결과 — [2026-08-13 여섯 번째 세션에 첫 실측 완료, 대부분 닫힘].**
|
||||
- **`.claude/luau-test/`(2026-08-09 신설) 스파이크 결과 — [2026-08-13
|
||||
여섯 번째 세션에 첫 실측 완료, 대부분 닫힘].**
|
||||
**상태의 소스는 항상 `.claude/luau-test/STATUS.md`**(pass / 사람 결정
|
||||
필요 / 스파이크 깨짐 / 미실행, 폴더 구조 자체가 상태) — 몇 개가 지금
|
||||
어느 폴더에 있는지는 여기서 나열 안 함(04/05/10/13/15/16/19가 여러
|
||||
필요 / 스파이크 깨짐 / 미실행, 폴더 구조 자체가 상태) — 총 몇 개인지도,
|
||||
지금 몇 개가 어느 폴더에 있는지도 여기서 세거나 나열 안
|
||||
함(04/05/10/13/15/16/19가 여러
|
||||
세션에 걸쳐 재설계로 `rewrite-required/`에 들고나며 이 문단의 나열이
|
||||
매번 stale해지는 패턴이 반복됐음, 최근엔 8차 세션의 "emit은 항상
|
||||
전파" 정정으로 `05`도 합류). 실행 결과 상세는
|
||||
|
|
@ -116,6 +117,27 @@
|
|||
(`HUMAN_TODO.md` 2번 항목).
|
||||
6. **[신규 백로그, 2026-08-14 열네 번째 세션]** 문서 stale 감소용 include
|
||||
도구 `doc-include.py`(가칭, `doc-check.py`와 짝) — `research/
|
||||
doc-include-plan.md` 참고. 플랜만 초안, **사용자가 내일 다듬을
|
||||
예정**. M0/설계 게이트와 무관.
|
||||
doc-include-plan.md` 참고(상태의 소스는 그 문서). **[2026-08-16 기준]**
|
||||
같은 날 CLAUDE.md 분할로 파일럿이 "`session-summary.md`를 통째로
|
||||
생성"하는 **단방향** 설계로 단순화돼 플랜이 갱신됨(목적지 마커 불필요).
|
||||
여전히 **구현 착수 전**. M0/설계 게이트와 무관.
|
||||
7. **[2026-08-16 신설, 대부분 닫힘 — 남은 건 (d) 하나]** 감사 툴링 검증.
|
||||
(a) `@import` 3개(`conventions.md`/`project-context.md`/`todos.md`)
|
||||
실제 로드 — **확인됨**, (b) `quad-doc-auditor` 레지스트리 등록 —
|
||||
**확인됨**(첫 실측 때 전원 `agentType not found`였던 건 `.claude/agents/`가
|
||||
세션 도중 생긴 디렉토리였기 때문, 재시작으로 해소), (c) frontmatter
|
||||
`model: sonnet` 반영 — **확인됨**(서브에이전트 트랜스크립트에
|
||||
`claude-sonnet-5` 기록), (d) **미해소** — 읽기 전용인데 Write/Edit이
|
||||
주어지는 원인. `memory: project`를 뺐지만 그 뒤 재시작 없이 돌린
|
||||
관찰뿐이라 진단 미확정이고, **다음 세션 시작 직후에 한 번 확인하면 됨**.
|
||||
결론 날 때까지 읽기 전용은 도구 유무가 아니라 프롬프트의 행동 규약으로
|
||||
지킨다.
|
||||
|
||||
**부수 확정 — 정의 파일은 세션 시작 시점 스냅샷으로 고정된다**(에이전트·
|
||||
워크플로 정의 모두): `quad-handover-audit`이 실제로 돌린 스크립트가 세션
|
||||
시작 시점 상태와 바이트 단위로 같았고 같은 세션의 편집은 반영 0이었음.
|
||||
**정의를 고쳤으면 재시작한 뒤에 감사를 돌릴 것** — 안 그러면 옛 정의로
|
||||
돌면서 새 정의로 돈 것처럼 보인다. 상세는
|
||||
`.claude/agents/quad-doc-auditor.md` 상단 배너가 소스. M0/설계 게이트와
|
||||
무관.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,17 +11,24 @@
|
|||
python3 .claude/tools/doc-check.py --quiet # 실패한 검사만
|
||||
종료코드: 오류(ERROR)가 하나라도 있으면 1, 경고만 있으면 0.
|
||||
|
||||
검사 항목
|
||||
1. [ERROR] 깨진 파일 참조 — 라이브 문서가 가리키는 .md/.luau가 실제로 없음
|
||||
2. [ERROR] 깨진 절 참조 — `foo.md` "절 제목" 이 그 파일에 없음
|
||||
(문서를 쪼개거나 헤딩을 고칠 때 가장 잘 깨지는 것 — 아홉 번째 세션에
|
||||
bind-system-plan.md를 분할하며 20곳이 여기 걸렸음)
|
||||
검사 항목 ([2026-08-16 정정] 1·2번의 심각도를 실제 코드에 맞춰 고침 —
|
||||
예전엔 둘 다 [ERROR]라고 적어놨지만 코드는 그렇게 동작한 적이 없음)
|
||||
1. [ERROR/WARN] 깨진 파일 참조 — 라이브 문서가 가리키는 .md/.luau가 실제로
|
||||
없음. 파일명이 이 레포의 명명 관례(`OURS`)에 걸리면 ERROR, 아니면
|
||||
외부 문서명일 수 있어 WARN.
|
||||
2. [WARN] 깨진 절 참조 — `foo.md` "절 제목" 이 그 파일에 없음
|
||||
(문서를 쪼개거나 헤딩을 고칠 때 가장 잘 걸리는 것 — 아홉 번째 세션에
|
||||
bind-system-plan.md를 분할하며 20곳이 여기 걸렸음. 절 제목을 의역해
|
||||
인용하는 관례가 있어 오탐이 섞이므로 ERROR가 아니라 WARN)
|
||||
3. [ERROR] 색인 누락 — base/research/archive/reference 파일이 README에 없음
|
||||
4. [WARN] 날짜 없는 시한부 주장 — "아직 안 돌려봄", "열린 질문 없음" 등
|
||||
시간이 지나면 거짓이 되는데 언제 기준인지 안 적힌 문장
|
||||
5. [WARN] 미반영 배너를 단 파일 vs 반영 목록 일치 여부
|
||||
|
||||
`session/`(원문 보존), `initreq/`(읽기 전용 클론)는 검사 대상에서 제외.
|
||||
검사 대상에서 제외되는 폴더는 `SKIP_DIRS`가 소스 — `session/`(원문 보존),
|
||||
`initreq/`(읽기 전용 클론), `worktrees/`, `tools/`(이 스크립트 자신이 여기
|
||||
있으므로 **doc-check.py는 자기 자신을 검사하지 않음**, 이 docstring의 주장은
|
||||
사람이 손으로 확인해야 함).
|
||||
`archive/`와 `.claude/session-summary.md`는 검사 대상이되 **히스토리 문서**라
|
||||
절 참조/시한부 주장 검사는 면제(`is_history()` 참고).
|
||||
"""
|
||||
|
|
@ -245,8 +252,11 @@ def main():
|
|||
check_temporal(docs)
|
||||
check_banner(docs)
|
||||
|
||||
# 제외 목록은 SKIP_DIRS 하나만 소스로 두고 여기서 다시 적지 않음
|
||||
# ([2026-08-16] 예전엔 "session/·initreq/ 제외"라고 하드코딩돼 있어
|
||||
# worktrees/·tools/가 빠진 채 stale했음)
|
||||
print(f"검사 대상 라이브 문서 {len(docs)}개 "
|
||||
f"(session/·initreq/ 제외)\n")
|
||||
f"({'·'.join(d + '/' for d in SKIP_DIRS)} 제외)\n")
|
||||
if errors:
|
||||
print(f"■ ERROR {len(errors)}건 — 고쳐야 함")
|
||||
for e in errors:
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ function fixPrompt(file, items) {
|
|||
|
||||
const seen = new Set()
|
||||
const roundLog = []
|
||||
// 실제 발견 내용 자체를 누적한다 — 카운트만 돌려주면 호출한 세션이
|
||||
// 커밋 전 diff 리뷰(관례상 필수)를 할 때 "이 수정이 왜 들어갔는지"를
|
||||
// 알 길이 없어서 journal.jsonl을 뒤져야 한다(2026-08-16 지적).
|
||||
const appliedFindings = []
|
||||
let dry = 0
|
||||
let round = 0
|
||||
|
||||
|
|
@ -127,6 +131,10 @@ while (dry < DRY_ROUNDS_TO_CONVERGE && round < MAX_ROUNDS) {
|
|||
label: `fix:${file}`,
|
||||
phase: 'Fix',
|
||||
agentType: 'general-purpose',
|
||||
// 토큰 관례(.claude/conventions.md "일반 작업은 sonnet") — 감사
|
||||
// 패스는 frontmatter로 이미 sonnet, 반영 쪽만 메인 모델(Opus)을
|
||||
// 상속하고 있어서 맞춤.
|
||||
model: 'sonnet',
|
||||
})
|
||||
)
|
||||
)
|
||||
|
|
@ -136,10 +144,12 @@ while (dry < DRY_ROUNDS_TO_CONVERGE && round < MAX_ROUNDS) {
|
|||
// 사라지고, 안 고쳐진 채로 수렴 판정이 난다(위와 같은 클래스의 버그).
|
||||
const failedFiles = []
|
||||
fixed.forEach((r, i) => {
|
||||
const [file, items] = fileEntries[i]
|
||||
if (r === null) {
|
||||
const [file, items] = fileEntries[i]
|
||||
failedFiles.push(file)
|
||||
items.forEach((f) => seen.delete(keyOf(f)))
|
||||
} else {
|
||||
items.forEach((f) => appliedFindings.push({ round, ...f }))
|
||||
}
|
||||
})
|
||||
if (failedFiles.length) {
|
||||
|
|
@ -162,6 +172,10 @@ if (!converged) {
|
|||
return {
|
||||
converged,
|
||||
rounds: round,
|
||||
totalFindingsFixed: seen.size,
|
||||
// ⚠️ "반영 에이전트에게 넘긴 발견"의 수이지 "실제로 고쳐진" 수가 아니다
|
||||
// — "의심"으로 표시된 항목은 반영 에이전트가 확인 후 건드리지 않고
|
||||
// 넘어갈 수 있다. 실제 반영 여부는 항상 `git diff`로 확인할 것.
|
||||
findingsSentToFix: appliedFindings.length,
|
||||
findings: appliedFindings,
|
||||
roundLog,
|
||||
}
|
||||
|
|
|
|||
14
CLAUDE.md
14
CLAUDE.md
|
|
@ -1,7 +1,9 @@
|
|||
# CLAUDE.md
|
||||
|
||||
Roblox 엔진용 DOMless UI 렌더러 **quad**를 처음부터 다시 짜는 프로젝트.
|
||||
지금은 설계/계획 단계이고 구현은 아직 시작 전.
|
||||
**[2026-08-16 기준] 지금은 설계/계획 단계이고 구현은 아직 시작 전** — 같은
|
||||
상태를 `.claude/project-context.md`도 서술하니 M0에 착수하면 두 곳을 같이
|
||||
고칠 것.
|
||||
|
||||
<!-- [2026-08-16 재구조화] 이 파일은 1537줄까지 불어나 (a) 사람이 검토 불가,
|
||||
(b) 공식 권장치(파일당 200줄) 7.7배 초과로 지침 준수도 저하, (c) 에이전트가
|
||||
|
|
@ -10,7 +12,7 @@ Roblox 엔진용 DOMless UI 렌더러 **quad**를 처음부터 다시 짜는 프
|
|||
편집 정확도, 그리고 파일 단위 자동생성 가능성을 산다.
|
||||
※ 이 주석은 컨텍스트 주입 전에 제거되므로 사람용 메모만 넣을 것. -->
|
||||
|
||||
**이 파일에 내용을 직접 쌓지 말 것** — 39줄짜리 진입점으로 유지한다. 새
|
||||
**이 파일에 내용을 직접 쌓지 말 것** — 짧은 진입점으로 유지한다. 새
|
||||
서술은 아래 import된 파일 중 맞는 곳에 넣을 것(어디에도 안 맞으면 그건
|
||||
매 세션 로드될 내용이 아닐 가능성이 높음 — `.claude/` 아래 해당 문서로).
|
||||
|
||||
|
|
@ -31,13 +33,13 @@ Roblox 엔진용 DOMless UI 렌더러 **quad**를 처음부터 다시 짜는 프
|
|||
| 사용자가 답해야 할 열린 질문 | `.claude/question.md` |
|
||||
| 구현 순서 / 마일스톤 | 루트 `ROADMAP.md` |
|
||||
| 사람만 할 수 있는 일 | 루트 `HUMAN_TODO.md` |
|
||||
| **어떤 결정이 왜 그렇게 됐나 / 전에 뒤집힌 적 있나** | `.claude/session-summary.md`를 grep (세션별 2~4줄 요약 색인, 91개) |
|
||||
| **어떤 결정이 왜 그렇게 됐나 / 전에 뒤집힌 적 있나** | `.claude/session-summary.md`를 grep (세션별 2~4줄 요약 색인) |
|
||||
| 그 결정의 논쟁 과정 원문 | `.claude/session/YYYY-MM-DD-NN-slug.md` |
|
||||
| 뒤집히거나 기각된 설계의 원문 | `.claude/archive/` |
|
||||
|
||||
**주의**: `session-summary.md`는 의도적으로 `@import` 안 함 — 1231줄을 매 세션
|
||||
컨텍스트에 올릴 이유가 없다고 판단(그 문서 스스로 "항상 읽을 필요 없음, 지금
|
||||
유효한 설계는 `base/`가 소스"라고 명시). 선행 맥락이 필요해지면 그때 가서 열 것.
|
||||
**주의**: `session-summary.md`는 의도적으로 `@import` 안 함 — 계속 자라는
|
||||
히스토리 문서라 통째로 올릴 이유가 없음(그 문서 스스로 "항상 읽을 필요 없음,
|
||||
지금 유효한 설계는 `base/`가 소스"라고 명시). 필요해지면 그때 가서 열 것.
|
||||
|
||||
**충돌 시 우선순위**: `.claude/base/` > 여기 요약이나 `session-summary.md`.
|
||||
후자들은 과거 시점 서술이라 더 최근 결정이 안 반영돼 있을 수 있음.
|
||||
|
|
|
|||
Loading…
Reference in a new issue