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:
DongHyeonka
2026-09-07 12:39:20 +09:00
co-authored by Claude Fable 5.1
parent 73026cada6
commit 9d2a3725c5
54 changed files with 3583 additions and 871 deletions
@@ -0,0 +1,117 @@
---
name: writing-as-the-person-who-did-it
description: Use when a Korean technical document is accurate, well-ordered and well-evidenced but reads like a report produced by nobody — no one chose anything, nothing surprised anyone, and the limits are an inventory instead of an admission.
---
# 일한 사람이 쓴 글로 만들기
## 무엇을 고치는 스킬인가
문장도 맞고 순서도 맞고 근거도 붙어 있는데 **아무도 쓰지 않은 글처럼 읽히는** 상태를 고친다.
증상은 셋이다.
- 무엇을 골랐다는 말은 있는데 **왜 그것을 골랐는지, 무엇과 견주었는지**가 없다
- 확인하지 못한 것이 **목록**으로 있고, 그것이 걸리는 대목에는 없다
- 어긋난 자리가 없다. 처음부터 지금 구조를 알고 있었던 것처럼 읽힌다
고치는 방법은 하나뿐이다. **자료에 남아 있는 사람의 흔적을 찾아서 제자리에 놓는다.**
## 절대 규칙 — 없는 사람을 만들지 않는다
이 스킬을 잘못 쓰면 지어낸 경험이 붙는다. 그것이 아무 목소리도 없는 글보다 나쁘다.
**쓸 수 있는 것은 자료가 기록한 사람의 행동과 판단뿐이다.** 넣은 문장마다 그것이 어느 파일,
어느 칸, 어느 줄에서 왔는지 댈 수 있어야 한다. 못 대면 지어낸 것이다.
| 이런 말이 떠오르면 | 실제로 벌어지는 일 |
|---|---|
| 「처음에는 X를 의심했다」 | 자료에 그런 기록이 없으면 없던 수사 과정을 만든 것이다 |
| 「놀랍게도」·「당황스럽게도」 | 감정을 지어냈다. 관측이 뜻밖이었다는 근거가 자료에 없다 |
| 「고민 끝에 Y를 골랐다」 | 대안을 견주었다는 기록이 없으면 고민도 없었다 |
| 「많은 시행착오를 겪었다」 | 시행착오가 자료에 있으면 그것을 적고, 없으면 이 문장도 없다 |
| 「이 글이 도움이 되길 바란다」 | 기록에는 독자에게 인사하는 자리가 없다. 참고 글의 습관을 옮겨 온 것이다 |
| 「~로 읽기 쉽다. 그렇지 않다」 | 자료에 그런 오독 기록이 없으면 독자를 지어낸 것이다. 관측부터 적는다 |
`../rewriting-technical-prose-naturally/references/protected-content.md`가 함께 걸린다. 수치·버전·
식별자는 이 스킬에서도 한 글자도 바뀌지 않는다.
## 자료 어디에 사람이 남아 있나
기록을 열기 전에 이것부터 찾는다. 대개 **이미 문서 안에 있고 자리가 틀렸을 뿐**이다.
| 어디 | 무엇이 있나 |
|---|---|
| `확인하지 못한 것` 칸 | 재지 않은 것을 아는 사람이 적어 둔 것이다. 목록이 아니라 그 대목에서 할 말이다 |
| `재현 조건` 칸 | 누군가 실제로 이 순서로 돌렸다. 그 순서가 왜 그 순서인지가 대개 빠져 있다 |
| javadoc·README·주석 | 코드를 쓴 사람이 남긴 말. 그대로 옮길 수 있다 |
| 커밋 메시지 | 왜 지웠는지·왜 바꿨는지가 한 줄로 남아 있다 |
| `final/document.md` | 기록으로 뽑으면서 잘라낸 판단이 여기 남아 있는 경우가 많다 |
| 결정 기록의 `판단 이유`·`영향` | 감수한 비용이 적혀 있다 |
찾은 것이 없으면 **이 스킬은 여기서 끝난다.** 없는 목소리를 채우지 않는다.
## 옮길 수 있는 다섯 가지
참고 여섯 편에서 뽑았고, 각 항목이 어느 글에서 왔는지는
[references/voice-moves.md](references/voice-moves.md)에 있다. 여섯 편이 다 쓰는 것이 아니다 —
13569 한 편에 몰려 있고 23625는 거의 쓰지 않는다. **글마다 자료가 허락하는 만큼만 쓴다.**
1. **고른 이유를 견준 대상과 함께 적는다** — 무엇을 놓고 무엇을 골랐고 무엇을 감수했나
2. **확인하지 못한 것을 그 대목에서 말한다** — 끝의 목록이 아니라 그 주장 옆에서
3. **어긋난 자리를 남긴다** — 예상과 결과가 달랐던 지점이 자료에 있으면 지우지 않는다
4. **남의 말을 그대로 옮긴다** — javadoc·문서·커밋 메시지·사용자 문의. 요약하지 않는다
5. **자료에 남은 오독을 그 자리에 둔다** — 누군가 실제로 틀리게 읽었다는 기록(버그·정정·문의)이 있을 때만.
독자가 틀릴 것이라고 가정해서 만든 「~로 읽기 쉽다」는 이 항목이 아니라 지어낸 독자다
다섯을 다 쓰지 않는다. 한 기록에 둘이면 충분하고 **하나도 없어도 된다.** 이미 충분히 설명된 문단에
사람의 목소리를 더하려고 문장을 붙이면 그것이 「설명 뒤의 평가」가 된다. 다섯을 채우면 그것이 또 다른 틀이 된다.
## 문체는 옮기지 않는다
참고 글은 합니다체이고 `~는데요`·`~텐데요`·`~거든요`로 말을 부드럽게 한다. 이 저장소의 기록은
한다체다. **부드러움을 흉내 내면 그 회사 목소리가 되고, 기록의 어조가 무너진다.**
한다체에서 사람이 드러나는 자리는 어미가 아니라 **무엇을 말하기로 했는가**다.
```text
없는 목소리 컨트롤러가 직접 내부 토큰을 확인한다.
지어낸 목소리 컨트롤러가 직접 내부 토큰을 확인하는데요, 이게 좀 아쉬운 부분입니다.
평가만 더한 것 컨트롤러가 직접 내부 토큰을 확인한다. 지금 구조에서 이것을 막는 것은 없다.
있는 목소리 컨트롤러가 직접 내부 토큰을 확인한다. /edge/** 전체를 보호하는 filter 는 없어서,
새 엔드포인트가 같은 메서드를 부르지 않으면 그 엔드포인트는 검사를 지나친다.
```
네 번째가 사람이 쓴 글이다. 어미는 그대로이고, 아는 사람만 할 수 있는 말이 하나 붙었다 — 그리고 그
말이 **사실을 더한다**(filter 가 없다, 어느 경로가 검사를 지나치는가). 세 번째처럼 판정만 더하면
(「막는 것은 없다」) 그것은 목소리가 아니라 평가다. 그런 문장은 빼는 쪽이 맞다.
## 절차
1. **자료를 먼저 훑는다.** 위 표의 자리를 다 열고, 쓸 수 있는 흔적을 목록으로 적는다
2. **흔적이 없으면 멈춘다.** 문서에 그렇게 보고한다
3. **흔적마다 놓일 자리를 정한다.** 대개 그 주장이 나오는 문단 바로 뒤다
4. **옮긴다.** 문장을 새로 짓지 말고, 자료의 말을 그 자리에 놓는 것으로 시작한다
5. **검사한다**`scripts/check_voice.mjs`. 이 검사기는 목소리가 **모자란지** 재지 않는다.
**지어낸 목소리**를 잡는다
6. `../rewriting-technical-prose-naturally``check_prose.mjs`를 다시 돌린다
## 검사
```bash
node .agents/skills/writing-as-the-person-who-did-it/scripts/check_voice.mjs <파일.md>
```
세 가지를 본다.
- **지어낸 경험** — 자료가 뒷받침하지 않으면 error인 표현들
- **참고 글에서 옮겨 온 인사말** — 「도움이 되길 바랍니다」 계열
- **합니다체 부드러움을 한다체에 섞은 자리**
검사기가 조용하다고 목소리가 생긴 것은 아니다. **모자란 것은 사람이 읽어야 안다.**
## 참조
- [references/voice-moves.md](references/voice-moves.md) — 다섯 가지가 여섯 편에서 어떻게 쓰였나
- `../rewriting-technical-prose-naturally/examples/` — 원문 여섯 편
- `../rewriting-technical-prose-naturally/references/article-shape.md` — 밀도. 이 스킬보다 먼저 본다
- `../writing-tech-log-records/references/writing-each-kind.md` — 종류마다 어느 칸이 사람의 자리인가