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>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
73026cada6
commit
9d2a3725c5
@@ -1,38 +1,142 @@
|
||||
---
|
||||
name: deriving-tech-log-root-tree
|
||||
description: Use when a completed or substantially completed docs project analysis must be decomposed into grounded Tech Log Topics and candidate Case, Reference, Open Question, and Decision records.
|
||||
description: 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
|
||||
|
||||
**Discover record candidates from evidence already present in the detailed analysis. Do not brainstorm a content calendar.**
|
||||
**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.
|
||||
|
||||
```json
|
||||
"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 project `state.json`, `final/document.md`, and `source-index.md`.
|
||||
2. Read bounded analysis files when the final document's anchor is not enough to judge classification.
|
||||
3. Identify coherent Topics from shared engineering problem spaces, not merely folder/module names.
|
||||
4. Within each Topic, identify concrete incidents first (Case), then reusable rules (Reference), unresolved unknowns (Open Question), and explicit project choices (Decision).
|
||||
5. Write the human-readable PROJECT/TOPIC tree.
|
||||
6. Add a Node Specification for every title with source anchors, readiness, relations, and kind-specific metadata.
|
||||
7. Run `references/decomposition-checklist.md`.
|
||||
8. Hash the source detailed document and record the project revision so downstream generation can detect staleness.
|
||||
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/root-tree-contract.md` as the output contract.
|
||||
Use `.agents/skills/writing-tech-log-records/references/tech-log-tree-contract.md` as the
|
||||
output contract.
|
||||
|
||||
## Topic boundary
|
||||
|
||||
A Topic is a stable problem/decision area whose records share terminology, evidence, and relations. It should be broad enough to connect several records when the evidence supports them, but narrow enough that its References and Decisions remain coherent.
|
||||
**A Topic is one reader question.** Write it under the topic slug:
|
||||
|
||||
Do not create one Topic per source file. Do not force unrelated incidents into one Topic because they use the same framework.
|
||||
```text
|
||||
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 title names the concrete engineering problem/verification, not a generic technology lesson.
|
||||
- Reference title names a reusable criterion/distinction.
|
||||
- Open Question title states an uncertainty that is still unresolved.
|
||||
- Decision title states an actual/proposed project direction evidenced in sources.
|
||||
- **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.
|
||||
|
||||
Branches may be empty. Symmetry is not a quality goal.
|
||||
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.
|
||||
|
||||
```bash
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user