# SSOT에서 글감을 뽑는 기준 `final/document.md` 하나가 정본(SSOT)이다. 거기서 Studio에 올릴 기록을 뽑아낸다. 이 문서는 **무엇을 몇 건으로 나눌지**를 정하는 기준이다. 나눈 결과는 `tech-log-tree.json` 하나에 적는다 — 분해 계약과 색인이 같은 파일이라 둘이 어긋날 자리가 없다. ## 어느 파일에서 뽑나 | 층 | 하는 일 | |---|---| | 코드·설정·실행 증거 | 사실의 근거 | | `final/document.md` | **글감 범위의 SSOT** — 후보를 발견하는 유일한 입력 | | `analysis/**/*.md` | final이 이미 채택한 주장을 상세히 확인하는 보조 근거 | | `tech-log-tree.json` | 사람이 고른 글감. 분해 계약이자 색인이고 이 파일이 정본이다 | **`analysis/**`를 글감을 찾으려고 열지 않는다.** 이미 final에 있는 주장의 세부를 확인할 때만 연다. 분석에만 있고 final에는 없는 자료를 발견하면 트리에 바로 넣지 말고 `final/document.md`를 먼저 보강한다. 그러지 않으면 모듈 문서 61편이 각각 정본 노릇을 하고, 트리는 그 절 수의 합만큼 자란다. ## 후보를 찾는 범위 접어 넣은 `final/document.md`가 전부 후보 자리는 아니다. **제1부(통합 분석)가 후보를 찾는 범위**이고, 제2부(모듈 분석 전문)와 제3부(분석 재료)는 근거다. 제2부의 절 제목을 후보로 읽으면 모듈 분석 편수만큼 글감이 늘어난다 — 접어 넣기 전에 있던 문제가 그대로 돌아온다. 범위는 기억하지 말고 계약에 적는다. ```json "candidateScope": { "document": "final/document.md", "sections": ["§3", "§4", "§5", "§6", "§7", "§8", "§9", "§10", "§11"], "excluded": ["제2부 — 모듈 분석 전문", "제3부 — 분석 재료"] } ``` 범위 밖의 앵커는 후보가 아니라 근거다. 제1부에서 나온 글감의 `source`로 건다. ## 왜 먼저 나누는가 긴 글을 앞에서부터 잘라 기록으로 만들면 절 하나가 기록 하나가 된다. 그러면 Case의 칸도 Reference의 칸도 반쯤만 맞는 기록이 나온다. 종류를 먼저 정하고 그 종류가 요구하는 것이 SSOT에 있는지 확인해야 한다. ## 고르는 것이지 남김없이 내는 것이 아니다 분석에 빠진 것이 없는지 볼 때는 recall 100%가 맞다. 공개할 글을 정할 때는 아니다. 「분석에서 보존할 가치」와 「독립된 글로 읽을 가치」는 다른 물음이고, 둘을 한 축으로 재면 분석 부산물이 전부 글이 된다. 물음은 하나다. > **이 기록을 없애고 관련 Case나 Concept의 한 절로 넣어도 이해·결정·재사용성이 그대로라면 > 독립 기록으로 만들지 않는다.** 후보마다 처분을 적는다 — `PROMOTE` · `MERGE_INTO` · `KEEP_IN_SSOT` · `NEEDS_EVIDENCE` · `NEEDS_DECISION` · `BLOCKED`. `KEEP_IN_SSOT`은 버린 것이 아니라 분석에 남기고 글로 만들지 않기로 한 것이고, 그것도 정상적인 결과다. 자세한 것은 `.agents/skills/deriving-tech-log-root-tree/references/candidate-disposition.md`. ## 한 건으로 자르는 단위 **절이 아니라 주장이다.** SSOT의 `##` 하나가 기록 하나가 아니다. 다음 넷 중 하나가 한 건이다. | 단위 | 무엇 | 종류 | |---|---|---| | 재현한 관측 하나 | 조건을 갖추고 돌려서 얻은 수치·실행계획·로그 | Case | | 남의 것의 동작 하나 | 문서와 코드를 읽어 정리한 규칙·흐름 | Concept | | 반복 적용할 기준 하나 | 다음에도 같게 하기로 한 규칙 | Reference | | 프로젝트가 고른 방향 하나 | 대안을 두고 정한 것 | Decision | | 닫히지 않은 판단 하나 | 아직 모르는 것과 무엇을 하면 닫히는지 | Question | ## 종류를 정하는 물음 순서대로 묻는다. 먼저 걸리는 것이 그 글감의 종류다. 1. **내가 돌려서 얻은 결과인가** → Case. 수치·실행계획·로그가 SSOT에 있어야 한다. 없으면 Case가 아니다 2. **남의 것이 어떻게 동작하는지인가** → Concept. 무엇을 보고 썼는지(버전)가 있어야 한다 3. **다음에도 같게 하기로 한 규칙인가** → Reference 4. **대안을 두고 고른 것인가** → Decision. 근거로 걸 기록이 최소 하나 필요하다 5. **아직 모르는 것인가** → Question. 미지수가 최소 하나 필요하다 ## 나눌 때 지키는 것 **한 건에 종류를 섞지 않는다.** N+1을 재현해 고쳤고 그 과정에서 조회 기준을 굳혔다면 Case 하나와 Reference 하나로 나누고 `관계`로 잇는다. **증거가 없는 Case는 만들지 않는다.** SSOT에 그 수치가 없으면 글감 목록에는 남기되 `file` 없이 두고, 측정을 먼저 한다. 없는 수치를 쓰지 않는다. **Decision은 근거 없이 만들지 않는다.** 게시가 거절된다. 근거로 걸 Case나 Concept이 먼저 있어야 한다. 그래서 Decision은 대개 마지막에 뽑는다. **같은 관측을 두 건으로 쪼개지 않는다.** 「N+1이 났다」와 「그래서 몇 개가 나갔다」는 한 건이다. 쪼개면 둘 다 반쪽이 된다. **Concept은 거꾸로 뽑는다.** Case·Reference·Decision·Question을 먼저 고르고, 그것을 읽는 사람이 미리 알아야 하는 구조가 있을 때만 Concept을 만든다. 메커니즘처럼 보이는 절을 훑어 채우면 어느 기록도 필요로 하지 않는 개념이 쌓인다. **주제 하나에 독자 질문 하나.** Studio는 주제 아래에 다섯 종류를 나눠 보여 준다. 그 주제의 기록들이 함께 답하는 물음을 한 줄로 적고, 그 물음에 답하지 않는 글감은 다른 주제로 옮긴다. 주제 slug는 Studio의 것을 그대로 쓴다. ## `tech-log-tree.json` **주제·글감·`readiness`·`source`·`classification`·`relations`는 사람이 적는다.** 스크립트가 채우는 것은 기록 파일에서 읽을 수 있는 넷뿐이다 — `file`·`publication`·`status`·`studioId`. 주제 → 종류 → 글감 순서로 담고, 아직 쓰지 않은 글감은 `file` 없이 남는다. `readiness`는 증거가 갖춰진 정도이고 `publication`은 Studio에 올렸는지다 — 둘은 다른 것이라 섞지 않는다. ```json { "project": "n+1liner", "ssot": "final/document.md", "topics": { "jpa-feed-query-performance": { "topic": "jpa-feed-query-performance", "kinds": { "case": [ { "title": "Fetch 타입이 아니라 조회 방식이 만든 ToOne N+1", "slug": "eager-toone-nplus1-without-access", "file": "jpa-feed-query-performance/case/case-eager-toone-nplus1-without-access.md", "status": "게시 전", "studioId": "32d0be7d-…", "assets": 1, "evidence": 3 }, { "title": "아직 쓰지 않은 글감" } ], "concept": [], "reference": [], "question": [], "decision": [] } } } } ``` 기록을 쓰거나 지운 뒤에는 파생 칸을 다시 채운다. 사람이 적은 칸은 그대로 남는다. 디렉터리를 훑어 주제를 만들지 않으므로, 계약에서 뺀 주제의 폴더가 남아 있어도 되살아나지 않고 `unlisted`에 적힌다. ```bash python3 scripts/build-tech-log-tree.py [프로젝트] python3 scripts/verify-tech-log-tree.py [프로젝트] # error 0 이어야 한다 ``` ## 순서 1. SSOT를 끝까지 읽는다. 절 제목만 훑지 않는다 — 수치와 근거가 어디 있는지 알아야 종류를 정한다 2. §3~§8에서 Case, §9에서 Reference, §10에서 Decision, §11에서 Question을 고른다 3. 그 넷을 이해하는 데 필요한 Concept만 거꾸로 더한다 4. 후보마다 처분을 적고, 사람이 다시 읽은 것만 `dispositionReview: CONFIRMED`로 둔다. `PROMOTE`이면서 `CONFIRMED`인 것만 글감이 된다 5. 주제를 묶고 주제마다 독자 질문을 한 줄 적는다 6. 글감 하나를 골라 `<주제>/<종류>/`에 기록을 쓴다. 형식은 `writing-each-kind.md` 7. 색인을 다시 만들고 검사기를 돌린다 8. Studio에 넣고 저장한다