Files
document-haness/.agents/skills/deriving-tech-log-root-tree/SKILL.md
T
DongHyeonkaandClaude Fable 5.1 9d2a3725c5 pipeline: make tech-log-tree.json the one decomposition contract and enforce it
리뷰 두 건을 반영했다.

계약
- 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>
2026-09-07 12:39:20 +09:00

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

  1. Read the candidate scope of final/document.md end to end.
  2. Pick representative Cases from the confirmed-problem and execution sections (in the standard layout, §3–§8).
  3. Pick References from the reusable-criteria section (§9).
  4. Pick Decisions from the explicit-decision section (§10).
  5. Pick Questions from the unresolved section (§11).
  6. 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.
  7. Give every candidate a disposition — references/candidate-disposition.md — and set dispositionReview to CONFIRMED only for the ones a person actually re-read.
  8. Group PROMOTE candidates into Topics. Write one reader question per Topic.
  9. Write every promoted candidate into tech-log-tree.json as a node under its Topic, with the fields its kind requires. There is no second tree to keep in step.
  10. Run references/decomposition-checklist.md.
  11. Record candidateScope, the source document hash, and the project revision.
  12. 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.