리뷰 두 건을 반영했다. 계약 - 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>
6.8 KiB
name, description
| name | description |
|---|---|
| deriving-tech-log-root-tree | Use when a completed or substantially completed docs project analysis must be decomposed into grounded Tech Log Topics and candidate Case, Concept, Reference, Open Question, and Decision records. |
Deriving Tech Log Root Tree
Core rule
Select what is worth publishing. Do not emit everything the analysis found.
Recall is the objective function of an analysis-coverage audit. It is not the objective function of an editorial decomposition. When the two are measured on one axis, every analysis by-product becomes a record. A decomposition that excludes nothing has not selected anything.
SSOT hierarchy
Four layers, and only one of them is the input for finding candidates.
| Layer | Role |
|---|---|
| code · config · execution evidence | ground truth for facts |
final/document.md |
SSOT for the candidate scope — the only input for discovering candidates |
analysis/**/*.md |
supporting detail for a claim final already adopted — exists only while the analysis is running |
tech-log-tree.json |
the decomposition contract and the index at once, and the source of truth. Written by hand; a script refreshes only the fields it can read back from the record files |
Do not open analysis/** to discover candidates. Open it to check the detail of a claim
that is already in final/document.md. If the analysis holds material that final does
not, fix final/document.md first, then decompose. Otherwise 61 module documents
become 61 competing SSOTs and the tree grows to their combined section count.
Candidate scope
A folded final/document.md is not uniformly candidate material. Part 1 is the integrated
analysis and it is where candidates come from. Part 2 holds the module analyses that were
folded in, and Part 3 holds the analysis material — both are supporting evidence, and
reading them as candidate material recreates the failure the fold was meant to end: one
candidate per module-analysis heading.
Declare the boundary in the contract so it is checkable rather than remembered.
"candidateScope": {
"document": "final/document.md",
"sections": ["§3", "§4", "§5", "§6", "§7", "§8", "§9", "§10", "§11"],
"excluded": ["제2부 — 모듈 분석 전문", "제3부 — 분석 재료"]
}
An anchor outside that scope is a source anchor, not a candidate. Cite it from a node whose candidate came from Part 1.
Which files exist, and when
Decomposition happens after the analysis has been folded in, and the folded project has fewer files than the one that was being analyzed. Read what is actually there.
| Phase | Files | Where candidates come from |
|---|---|---|
| analysis running | state.json · source-index.md · analysis/** · final/document.md |
final/document.md |
| analysis folded in | final/document.md only |
final/document.md, candidate scope |
| decomposition | final/document.md · tech-log-tree.json |
candidate scope |
state.json and source-index.md say how far the analysis got and which code it covered.
They do not hold candidates, and in a folded project they are gone.
Required sequence
- Read the candidate scope of
final/document.mdend to end. - Pick representative Cases from the confirmed-problem and execution sections (in the standard layout, §3–§8).
- Pick References from the reusable-criteria section (§9).
- Pick Decisions from the explicit-decision section (§10).
- Pick Questions from the unresolved section (§11).
- Only now add the Concepts those four need in order to be understood. Concept is derived backwards from the records that require it, never by sweeping headings.
- Give every candidate a disposition —
references/candidate-disposition.md— and setdispositionReviewtoCONFIRMEDonly for the ones a person actually re-read. - Group
PROMOTEcandidates into Topics. Write one reader question per Topic. - Write every promoted candidate into
tech-log-tree.jsonas a node under its Topic, with the fields its kind requires. There is no second tree to keep in step. - Run
references/decomposition-checklist.md. - Record
candidateScope, the source document hash, and the project revision. python3 scripts/verify-tech-log-tree.py <project>— errors must be 0.
Use .agents/skills/writing-tech-log-records/references/tech-log-tree-contract.md as the
output contract.
Topic boundary
A Topic is one reader question. Write it under the topic slug:
TOPIC
OAuth 자격증명과 세션의 보관 경계
oauth-oidc-auth-boundary
독자 질문 — 자격증명과 세션을 누가 보관하고, 누가 API 요청을 만들며, 보호 자원은 무엇을 신뢰하는가?
A node that does not help answer that question belongs to another Topic. If a Topic needs two questions, it is two Topics. If two Topics share one question, they are one Topic.
This is the test that catches both failures at once — splitting one problem space across
state-machines-and-ownership, state-ownership-and-concurrency, and
owner-safe-state-machines, and packing forwarded-header trust, fileserver mapping,
Redis key APIs, and permission normalization into one admission-budget-and-backpressure.
Do not create one Topic per source file or module. A directory is not a Topic.
Classification discipline
- Case — one problem, an observation or reproduction, a diagnosis, a closed conclusion.
- Concept — structure or behavior that must be explained from the beginning before a
Case can be understood. Has a
basis-version. - Reference — a rule that applies to the next project, with scope and exceptions.
- Open Question — no answer yet, the design turns on the answer, and there is a next verification and a closing criterion.
- Decision — the project actually chose a direction, with grounds and an accepted cost.
The independence test decides all five:
Delete this record and fold it into a related Case or Concept as one section. If understanding, decisions, and reuse are unchanged, it is not an independent record.
Branches may be empty. Symmetry is not a quality goal. Neither is volume — a large
denominator justifies a long final/document.md, not a long tree.
Refreshing the derived fields
There is one file. tech-log-tree.json is written by hand, and the build refreshes only
what it can read back from the record files — file, publication, status, studioId,
assets, evidenceFiles — plus counts, ssotSha256, and the unlisted list.
python3 scripts/build-tech-log-tree.py <project>
readiness, source, classification, relations, and the rest of each kind's fields
survive a rebuild untouched. The build never reads the directory listing for Topics: a
folder left behind after a node is dropped from the contract shows up in unlisted, and it
does not come back as a Topic.