리뷰 두 건을 반영했다. 계약 - tech-log-tree.json 하나가 분해 계약이자 색인이다. 사람이 읽는 트리·Node Specification· 후보 대장은 없어졌고, 문서에 남아 있던 그 개념을 걷어냈다 - candidateScope — 후보를 찾는 SSOT 범위. 접어 넣은 제2부·제3부는 근거이지 후보가 아니다 - sourceRepository — 분석한 저장소의 경로·리비전·판단 근거. 리비전을 모르면 null 로 두고 지어내지 않는다. 갈래가 여럿이면 revisions - 검사기: 계약 미채택·PENDING·PROMOTE↔글감 양방향·candidateScope·sourceRepository 를 error/warn 으로 센다. 옛 스키마도 검사를 피하지 못한다. 테스트 22 → 31 기록 쓰기 - 템플릿 5종에 source·sourceRevision·topicName, Question 에 닫는 조건, 본문 없는 종류에서 assets 제거. 고정 절 개수 삭제 - check_evidence.mjs — 인용한 코드가 SSOT 에 있는지, 앵커가 SSOT 를 가리키는지, 제목이 계약과 같은지, 리비전이 저장소에 있는지. 게시된 기록에서 SSOT 와 다른 URL 을 잡았다 문체 - 문체 규칙의 정본을 ai-tells.md 로. explaining.md 의 질문체 제목·절 끝 대조 반복·그림 예고 규칙을 삭제해 충돌을 없앴다. 첫 절 「설명 뒤에 평가를 붙이지 않는다」에 지우는 사례 네 유형 - voice 스킬의 「독자 쪽을 본다」를 자료에 오독 기록이 있을 때로 좁히고, 평가만 더한 예시를 교체 - check_prose: 안내 문장을 요구하던 경고 제거, 문장이 끝나지 않은 채 문단이 끝나는 조각 검사 추가 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
95 lines
4.4 KiB
JSON
95 lines
4.4 KiB
JSON
{
|
|
"schemaVersion": 4,
|
|
"project": "<project>",
|
|
"ssot": "final/document.md",
|
|
"sourceRepository": {
|
|
"path": "<분석한 저장소의 체크아웃 경로 또는 URL>",
|
|
"revision": "<문서가 서술한 상태의 커밋. 모르면 null 로 두고 지어내지 않는다>",
|
|
"revisions": {"<갈래가 여럿이면 이름>": "<커밋>"},
|
|
"verified": "<이 값이 맞다고 판단한 근거 — 무엇을 어디서 대조했는지>"
|
|
},
|
|
"ssotSha256": "<sha256>",
|
|
"sourceRevision": "<git-revision-or-snapshot>",
|
|
"generatedAt": "<YYYY-MM-DD>",
|
|
"candidateScope": {
|
|
"document": "final/document.md",
|
|
"sections": ["§3", "§4", "§5", "§6", "§7", "§8", "§9", "§10", "§11"],
|
|
"excluded": ["제2부 — 모듈 분석 전문", "제3부 — 분석 재료"],
|
|
"note": "후보를 찾는 범위다. 제2부·제3부는 근거이지 후보 자리가 아니다. excludedAnchorPattern 을 적으면 그 정규식에 걸리는 앵커에서만 나온 글감을 검사기가 error 로 센다"
|
|
},
|
|
"note": "이 프로젝트의 글감 전부다. 분해 계약이자 색인이고, 이 파일이 정본이다. 노드의 칸(readiness·source·classification·relations…)은 사람이 적고, file·publication·status 는 기록 파일에서 읽어 채운다 — python3 scripts/build-tech-log-tree.py <프로젝트>",
|
|
"contract": {
|
|
"decomposition": [
|
|
"글감을 찾는 입력은 final/document.md 하나다. 거기에 없는 근거는 먼저 SSOT 에 넣는다.",
|
|
"후보 전부는 candidates 에 처분과 함께 남고 PROMOTE 만 topics 로 올라간다.",
|
|
"없애고 관련 Case 나 Concept 의 한 절로 넣어도 이해·결정·재사용성이 그대로라면 독립 기록으로 만들지 않는다.",
|
|
"Topic 은 독자 질문 하나다. 그 물음에 답하지 않는 글감은 다른 Topic 으로 옮긴다.",
|
|
"Concept 은 Case·Decision·Question 을 먼저 고른 뒤 그것을 이해하는 데 필요한 것만 거꾸로 더한다."
|
|
],
|
|
"readinessValues": ["READY", "OPEN", "NEEDS_EVIDENCE", "NEEDS_DECISION", "BLOCKED"],
|
|
"dispositionValues": {
|
|
"PROMOTE": "독립 Tech Log 로 쓴다",
|
|
"MERGE_INTO": "다른 기록의 한 절로 흡수한다",
|
|
"KEEP_IN_SSOT": "분석에는 남기고 독립 기록으로 만들지 않는다 — 정상적인 성공 결과다",
|
|
"NEEDS_EVIDENCE": "주장에 아직 검증이 없다",
|
|
"NEEDS_DECISION": "방향이 그럴듯하지만 프로젝트가 정하지 않았다",
|
|
"BLOCKED": "원본이 불완전하거나 서로 어긋난다"
|
|
}
|
|
},
|
|
"counts": { "topics": 1, "nodes": 2, "written": 0, "unwritten": 2, "unlisted": 0, "candidates": 1 },
|
|
"topics": {
|
|
"<topic-slug>": {
|
|
"topic": "<topic-slug>",
|
|
"title": "<Topic 제목>",
|
|
"readerQuestion": "<이 Topic 의 기록들이 함께 답하는 물음 하나?>",
|
|
"kinds": {
|
|
"case": [
|
|
{
|
|
"title": "<Case 제목>",
|
|
"kind": "case",
|
|
"slug": "<slug>",
|
|
"readiness": "READY",
|
|
"source": ["final/document.md#<anchor>"],
|
|
"code": ["<path>:<line-or-symbol>"],
|
|
"evidence": ["evidence/raw/<file>"],
|
|
"classification": "<재현·진단·결론이 닫히는 하나의 사건. 정적 카운트나 문구 수정이 아니다>",
|
|
"missing-verification": "<없음 또는 하지 못한 확인>",
|
|
"relations": ["concept:<slug>"],
|
|
"publication": "미작성"
|
|
}
|
|
],
|
|
"concept": [
|
|
{
|
|
"title": "<Concept 제목>",
|
|
"kind": "concept",
|
|
"slug": "<slug>",
|
|
"readiness": "READY",
|
|
"source": ["final/document.md#<anchor>"],
|
|
"basis-version": "<무엇을 보고 썼는지 — 예: Keycloak 26.7.0 identity brokering>",
|
|
"classification": "<이 구조를 처음부터 설명해야 어떤 Case 를 이해할 수 있는지>",
|
|
"relations": ["case:<slug>"],
|
|
"publication": "미작성"
|
|
}
|
|
],
|
|
"reference": [],
|
|
"question": [],
|
|
"decision": []
|
|
}
|
|
}
|
|
},
|
|
"candidates": [
|
|
{
|
|
"id": "<A05-F012>",
|
|
"kindCandidate": "CASE",
|
|
"sourceRefs": ["final/document.md#<anchor>"],
|
|
"summary": "<한 줄>",
|
|
"disposition": "KEEP_IN_SSOT",
|
|
"dispositionReview": "CONFIRMED",
|
|
"target": null,
|
|
"reason": "<왜 독립 기록으로 만들지 않았는지>"
|
|
}
|
|
],
|
|
"unlisted": [],
|
|
"history": {}
|
|
}
|