ko-tech-writer · diff
git:20260814.549a4bc to git:20260917.73e634c
268 added, 25 removed. Audit A to A.
---
name: ko-tech-writer
- description: 'Writes or revises Korean technical prose across three registers — reader-facing documents (tech-blog posts, technical docs), spoken scripts, and derived compressed assets (teasers, summaries) — through a fixed pipeline: register detection, real-sample calibration of the target venue, a translationese-removal pass, honesty-level layering (reader information vs internal audit vocabulary), a number/claim gate, and a rendition + perceptual QA pass. Triggers: "기술문서 써줘", "테크블로그 초안 잡아줘", "이 문서 번역투 고쳐줘", "블로그체로 다듬어줘", "이 글 회사 기술블로그에 올릴 수 있게 다듬어줘".'
+ description: 'Writes or revises Korean technical prose across three registers — reader-facing documents (tech-blog posts, technical docs), spoken scripts, and derived compressed assets (teasers, summaries) — through a fixed pipeline: register detection, real-sample calibration of the target venue, a translationese-removal pass, honesty-level layering (reader information vs internal audit vocabulary), a number/claim gate, and a rendition + perceptual QA pass. Triggers: "기술문서 써줘", "테크블로그 초안 잡아줘", "이 문서 번역투 고쳐줘", "블로그체로 다듬어줘", "이 글 회사 기술블로그에 올릴 수 있게 다듬어줘", "발표 대본 다듬어줘", "낭독 대본 점검해줘", "이 스크립트 소리 내서 읽을 때 걸리는 데 있나".'
user-invocable: true
allowed-tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob", "WebFetch"]
model: sonnet
---
# ko-tech-writer — 한국어 기술문서 집필·개고 파이프라인
- 독자 대면 한국어 기술 산출물(테크블로그 글 · 기술문서 · 발표 파생 자산)을 쓰거나 개고한다.
+ 한국어 기술 산출물을 쓰거나 개고한다 — **독자 대면**(테크블로그 글 · 기술문서 · 발표 파생 자산)과
+ **청자 대면**(발표 대본 자체) 둘 다이며, 레지스터는 Step 0 에서 가른다.
핵심 전제: **좋은 문장은 취향이 아니라 절차다** — 실물 표본으로 톤을 캘리브레이션하고,
번역투를 패턴 목록으로 제거하고, 수치는 근거와 창을 달고, 렌더 결과를 눈으로 확인한다.
> 출처: 2026-08-10 발표 기술문서 세션에서 실측으로 벼려진 규율의 자산화. 이 문서의 규칙
> 클래스는 그 세션의 개고에서 실제로 검출·수리된 것들이다 — 근거 원장은 그 세션 기록
> (`fh_completed_2026-08-10` 및 해당 개고 커밋 이력. 비공개 세션 기록이라 외부 배포본
> 독자에게는 도달하지 않는 내부 포인터다). **실측 근거가 없는 클래스를 추가하지 않는 것**이
> 이 문서의 유지 규칙이다. 이 SKILL.md 자체는 독자 대면 문서가 아니라 하네스 자산이므로
> 이 파이프라인의 적용 대상이 아니다(FH 하우스 스타일을 따른다).
## Step 0 — 대상 판별 (레지스터 분기)
같은 내용도 매체에 따라 규율이 다르다. 먼저 셋 중 무엇인지 정한다:
| 대상 | 레지스터 | 이 스킬의 적용 |
|---|---|---|
| **독자용 문서** (블로그 글·기술문서) | 문어 존댓말 (습니다체) | Step 1~5 전체 |
- | **낭독 대본** (발표 스크립트) | 구어 발표체 | Step 2~4 만 — 구어 리듬 유지, 줄표는 «쉼»으로만 실현되므로 소리로 안 들리는 동격·재진술 줄표 제거 |
+ | **낭독 대본** (발표 스크립트) | 구어 발표체 | Step 2~4 + **Step 5 콜드리드** + **Step 5-s(소리 렌더)** — 구어 리듬 유지, 줄표는 «쉼»으로만 실현되므로 소리로 안 들리는 동격·재진술 줄표 제거. 🟥 **Step 5 를 N/A 로 비우지 않는다**: 낭독은 «소리로 렌더»되므로 렌더 산출물이 없는 게 아니라 **렌더 매체가 소리**다 |
| **파생 압축 자산** (티저·요약 이미지·1장 슬라이드) | 자립형 평문 | Step 2~**5** + **자립성 검사**: 화면·본문 맥락 없이 서야 하므로 정본 어휘·주장 범위·은어를 따로 대조. 렌더 산출물을 만들면 Step 5 지각 QA 필수 |
검증된 원문에서 파생 자산을 만들 때도 재검사한다 — 압축은 주장 범위를 움직일 수 있다
(예: «지점 앞에서 벼려졌다» → «도메인에서 확인해 온»으로 줄면 담당 범위가 넓어져 읽힌다).
## Step 1 — 실물 캘리브레이션 (표본 없이 톤 단정 금지)
게재 매체가 지정되지 않았으면 **먼저 묻는다**(한 줄). 답을 받을 수 없는 환경이면 일반
규율로 진행하고 그 사실을 이력에 명기한다.
게재 목표 매체의 **실제 표본을 1편 이상** 확인(WebFetch)하고 세 가지를 기록한다:
1. **문체**: 존댓말 변형(습니다/해요), 도입 형식(질문형/선언형)
2. **구성**: 소제목 밀도, 마무리 관행(일반화 + 트레이드오프 + 실무 조언 등)
3. **시각물**: 다이어그램/그래프/표를 어느 밀도로 쓰는가
캘리브레이션 기록은 **산출물 이력**(작업 로그·PR 본문·문서 frontmatter)에 남긴다 — 게재
본문에는 노출하지 않는다. 표본을 확인할 수 없으면 **무엇을 시도했고 왜 안 됐는지**(호출
실패·매체 미상 등)를 같은 이력에 명기하고 일반 규율(습니다체·소제목 세분화)로 진행한다 —
확인 안 된 톤을 확정처럼 쓰지 않는다. **시도 기록 없는 «확인 불가»는 Done When 1조를
충족하지 않는다.**
## Step 2 — 문체 규율 (번역투 클래스 목록)
아래는 실측으로 검출된 클래스다. **기계 스캔 + 눈 판정**으로 제거한다
(grep은 후보를 표시할 뿐, 남길지 판정은 문맥으로):
- | 클래스 | 검출 힌트 | 수리 |
+ 🟥 **정규식을 표 안에 두지 않는다.** GFM 표 셀에서 `|` 는 열 구분자라, **이스케이프하면 복붙
+ 실행이 깨지고**(rg 에서 `\|` 는 리터럴 파이프) **안 하면 렌더가 깨진다.** 두 뿔 어느 쪽도 답이
+ 아니므로 패턴은 전부 아래 코드블록에 두고 표는 번호로만 가리킨다.
+ 🟥 **여기에 숫자를 적지 마라 — 계측 대상은 Step 2-a 의 정본 픽스처다.** 파일은 편집할 때마다
+ 자라므로 **자기 자신을 대상으로 적은 크기는 다음 편집에서 조용히 거짓이 된다.** 초판이 그렇게
+ 적었고, 적대 라운드가 그 숫자들이 **같은 커밋 안에서 이미 죽어 있는 것**을 실측으로 보였다.
+ 기전만 적는다: **이스케이프판은 리터럴 파이프를 찾으므로 0건을 내고, 저자는 그걸 「잔여 0」으로
+ 읽는다.** 크기가 필요하면 Step 2-a 의 레인을 돌려라.
+
+ | # | 클래스 | 검출 | 수리 | check-class |
+ |---|---|---|---|---|
+ | **S1** | 줄표 이어붙임 「~다 — ~고,」 | `S1a` 분모(2분할) + `S1b` 판정 대상 | 문장 분리. 줄표는 **일을 하는 곳만** 남긴다(열거 매달기·리듬 결속·**인용된 원문**) — 남긴 이유를 적는다 | measured |
+ | ~~S2~~ | *(비어 있다 — 「범위 표기의 물결표」가 여기 있었다. 2026-08-25 Added-Scope 판정으로 **별건 분리**: 그 클래스는 자기 행에 「낭독 대본은 N/A」라고 적어, 이 변경의 명시된 일과 다른 일이었다. 번호는 재사용하지 않는다 — 후속 변경이 이 자리로 돌아온다)* | — | — | — |
+ | **S3** | 용어-머리 「**X** — 설명」 | `S3` | 「**X**: 설명」 콜론형 | measured |
+ | **S4** | 콜론 나열투 「관측된 분업은: …」 | 서술어 없는 `:` 도입. ⚠️ **정본 레인 C3 에 후보 패턴이 있다** — 다만 후보 표시용이고 판정은 눈이다 | 완결 문장으로 (「…분업은 ~라는 것입니다」) | judged |
+ | **S5** | 조각문 「걸리는 층.」 | 서술어 없는 마침. ⚠️ **정본 레인 C4 에 후보 패턴이 있으나 «닫힌 명사 어휘»라 recall 이 낮다**(스크립트 주석이 그렇게 적는다) — 넓히려면 형태소 분석이 필요하다 | 서술어 복원 (「걸리는 층입니다」) | judged |
+ | **S6** | 소유 직역 「~을 갖다/가지다」 | `S6` | 존재문으로 (**「이전 상태를 갖지 않는다」 → 「이전 상태가 없다」**). 영어 `have` 의 직역이고, 한국어는 소유보다 존재로 말한다. 소유가 실제 논점인 자리(권한·지분)는 남긴다 | measured |
+ | **S7** | 내부 조어·은어 | `S7` — 후보 낱말을 목록화해 전수 세고, 각 낱말의 **첫 등장 ±40자에 풀이가 있는지**를 기계로 본다. 「3회 이상 나오는데 첫 등장 풀이 0」이 우선 후보 | 청중 어휘로 평문화. 단 **화면이 어휘를 받치면**(실제 빨간 화면을 가리키는 발화) 유지 가능 — 근거를 적는다. 🟥 **독자층 눈금을 먼저 정한다** — 기술 청중에게 「레포·커밋·도메인」은 일상어다 | judged |
+ | **S8** | 지시 불명확 대상어 (조어와 다른 축) | 타동사인데 목적어가 문장 안에 없는 낱말 — 「낸 것」·「돌렸다」·「그거」. **기계 패턴 없음, 눈**. 🟥 **풀이를 붙여도 안 닫힌다** — 어려운 게 아니라 「무엇을」이 비어 있다 | 목적어를 문장 안에 복원한다 (「낸 것」 → 「변경분」·「작성자」) | judged |
+ | **S9** | 레지스터 드리프트 | 습니다↔해요↔평어 혼재 — 눈 | 표본 기준 단일화 | judged |
+
+ > **S8 의 1차 출처 (2026-08-24, 필드 리뷰)**: 발표 대본의 「낸것 / 안낸것」이 「**인풋 /
+ > 아웃풋으로 직관화**」 권고를 받았다 — 내부 전용 축약어를 일반 청중 언어로 번역하라는 지적이다.
+ > 🟥 **「낸 쪽」은 그 리뷰가 지목한 결함이 아니다** — 2026-08-18 에 「저자」→「낸 쪽」으로 이미
+ > 수리된 형태였다. **처방을 결함으로 인용하지 마라**(이 파일에서 두 번 났다).
+ > ⚠️ 그렇다고 최종형도 아니다 — 같은 2026-08-25 에 다시 「작성자」로 갔다. 한 낱말이 두 라운드에
+ > 걸쳐 움직였다는 사실 자체가 S8 이 **눈 판정 클래스**인 이유다.
+
+ ```bash
+ F='대상.md' # 🟥 <> 는 셸 메타문자다. 따옴표로 감싼 실제 경로를 넣어라
+
+ # ── S1a 줄표 분모 — 🟥 2분할. en dash 는 «줄표»와 «범위 표기» 둘로 쓰이므로 한 통에 세면
+ # 분모가 부푼다. 줄표 분모 = ①전수 + (②−③)
+ rg -c '[—―]' "$F" # ① em·horizontal — 전량 줄표 후보
+ rg -c '–' "$F" # ② en dash 전수
+ rg -c '[0-9]\s*–\s*[0-9]' "$F" # ③ 그중 범위 표기 = 정상. 줄표 분모에서 뺀다
+
+ # ── S1b 줄표 판정 대상 — 위험 부분집합만 건별로 판정
+ rg -n '(습니다|입니다|다|것|음)\s*[—–―]\s*\S' "$F" # 거짓 종결: 종결어미 뒤로 문장이 계속된다
+ rg -n '[—–―]\s*$' "$F" # 줄끝
+ # ⚠️ `" — "`(양쪽 공백) 금지 — 줄 끝 em dash 는 오른쪽 공백이 없어 구조적으로 안 잡힌다.
+ # 🟥 여기에 크기를 적지 마라 — 대상이 움직이는 파일이면 그 숫자는 다음 편집에 죽는다.
+ # ⚠️ 문자군은 `[—–―]` — em(U+2014)만 잡으면 en(U+2013)·horizontal(U+2015)이 샌다.
+
+ # ── S3 용어-머리 「- **X** — 설명」. 🟥 `^\S+` 로 쓰면 «볼드 글머리»라는 자기 클래스 정의를
+ # 못 잡는다 — 정본 픽스처의 known-positive 를 0건으로 놓쳤다(2026-08-25 적대 라운드 적발).
+ rg -n '^\s*[-*]\s+\*\*[^*]+\*\*\s*[—–―]\s' "$F"
+ # ── S6 소유 직역
+ rg -n '(을|를) ?(갖|가지)' "$F"
+
+ # ── S7 내부 조어: 후보 낱말의 첫 등장 ±40자에 풀이가 있는지
+ # 🟥 W 를 리터럴로 두지 마라 — 복붙하면 글자 `W` 를 찾아 **무음 0건**이 되고 「잔여 0」으로 읽힌다
+ W='후보낱말'
+ rg -n "${W}.{0,40}(=|즉|라고 부|라는 뜻)|(=|즉|라고 부|라는 뜻).{0,40}${W}" "$F"
+ ```
+
+ 🟥 **en dash 를 줄표로 쓰지 마라** — 범위 표기(`30–50%`)와 시각적으로 안 갈린다. 그래서 S1a
+ 분모를 2분할해 «줄표로 쓰인 en dash»와 «범위 표기»를 따로 센다.
+
+ ### Step 2-a — 계기 보정 (돌리기 전에 갈리는지 본다)
+
+ 🟥 **새로 만들지 마라 — 이미 있다. 2026-08-17 에 갚힌 부채다.**
+
+ ```
+ plugins/fh-commons/skills/ko-tech-writer/fixtures/known_positive.md ← 일부러 심은 번역투
+ plugins/fh-commons/skills/ko-tech-writer/fixtures/known_negative.md ← 같은 내용의 정상 산문
+ scripts/ko_tech_writer_calibrate.py ← 엔진 + 레인 정의
+ scripts/test_ko_tech_writer_lanes.sh ← 재현 커맨드
+
+ bash scripts/test_ko_tech_writer_lanes.sh # ← 이 한 줄이 보정이다
+ ```
+
+ 🟥 **레인을 골라 돌리지 마라 — 위 한 줄이 전부 돈다.** 고르는 순간 **안 돈 축이 침묵으로 0이
+ 된다.** 실측 2026-08-25(병렬 세션): Step 2 레인만 돌리고 Step 4-b 전칭 단정 두 레인을 안 돌렸다.
+ 🟥 **그 세션은 축을 숨기지 않았다** — 잰 축을 명시해 보고했다.
+ ⚠️ `LOCAL-ONLY ATTESTATION — UNVERIFIED`: 그 수치와 「정본 계기로도 참」은 **그 세션의 자기신고**
+ 이고 이 문서의 저자가 재측정하지 않았다. 이 규율은 그 수치가 참인지에 **기대지 않는다** —
+ 오히려 보고가 **참일 때** 논지가 성립한다. 나중에 두 레인을 돌리니 후보 17건이 나왔고 그중
+ 16건은 정당한 전칭 — **결함이 아니라 판정 대기**였다.
+ ⇒ **여기가 이 규율의 하중선이다: 성실히 축을 밝혀도, 안 돈 축은 독자에게 안 보인다.** 읽는 쪽은
+ 「명시된 축 = 전부」로 받는다. 그래서 처방이 「축을 밝혀라」가 아니라 **「고르지 마라」**다.
+
+ 넷 다 `package.json` `files[]` 에 실려 **소비자 설치에 그대로 간다.** 클래스를 추가하면
+ `known_positive.md` / `known_negative.md` 에 표본을 **더하고** `calibrate.py` 의 `LANES` 에
+ 레인을 **더한다** — 별도 픽스처를 짓지 않는다.
+
+ 🟥 **이 자리에서 실제로 그 실수를 했다(2026-08-25, 기록으로 남긴다).** 챔버 판정의
+ carry-forward 를 인용하는 문단 세 줄 아래에서, 위 자산을 **한 번도 grep 하지 않고**
+ `/tmp` 에 두 번째 known-pair 를 heredoc 으로 지었다. 그리고 그때 새로 쓴 용어-머리 패턴은
+ **정본 픽스처의 known-positive 를 0건으로 놓쳤다** — 픽스처를 계기에 맞춰 쓴 탓에 자기 픽스처
+ 에서는 통과했다. 챔버가 「미보정 계기의 증식」이라 이름 붙인 형태 그대로다.
+ ⇒ **보정 계기를 새로 짓기 전에 `ls plugins/*/skills/<이 스킬>/fixtures/` 를 먼저 쳐라.**
+
+ **엔진 — 여기서 갈린다. 섞지 마라.**
+
+ | 자리 | 엔진 | 왜 |
|---|---|---|
- | 줄표 이어붙임 「~다 — ~고,」 | `grep "다 — \|것 — \|음 — "` | 문장 분리. 줄표는 **일을 하는 곳만** 남긴다(열거 매달기·리듬 결속 — 남긴 이유를 적는다) |
- | 용어-머리 «**X** — 설명» | 글머리 기호 뒤 `** — ` | «**X**: 설명» 콜론형 |
- | 콜론 나열투 («관측된 분업은: …») | 서술어 없는 `:` 도입 | 완결 문장으로 («…분업은 ~라는 것입니다») |
- | 조각문 («걸리는 층.») | 서술어 없는 마침 | 서술어 복원 («걸리는 층입니다») |
- | 소유 직역 「~을 갖다/가지다」 | `grep -nE "을 갖|를 갖|을 가지|를 가지"` | 존재문으로 (**«이전 상태를 갖지 않는다» → «이전 상태가 없다»**). 영어 `have`의 직역이고, 한국어는 소유보다 존재로 말한다. 소유가 실제 논점인 자리(권한·지분)는 남긴다 |
- | 내부 조어·은어 | 팀 밖에서 안 쓰는 단어 (예: 렌더하다, 초록/빨강을 CI 결과 뜻으로) | 청중 어휘로 평문화. 단, **화면이 어휘를 받치면**(실제 빨간 화면을 가리키는 발화) 유지 가능 — 근거를 적는다 |
- | 레지스터 드리프트 | 습니다↔해요↔평어 혼재 | 표본 기준 단일화 |
+ | **보정 레인**(위 스크립트) | **Python `re`** | 2026-08-17 실측: `rg` 로 고정했더니 **CI 에서 죽었다**(ubuntu-latest 에 ripgrep 부재, exit 10). 셸 안의 `[가-힣]` 은 GNU grep C 로케일에서 exit 2 → **«무매치»로 읽히는 fail-open**. `re` 는 세 허용 엔진 중 어디에나 있고 로케일을 안 탄다 |
+ | **손으로 도는 임시 스캔** | `rg` | 로컬 대화형. ⚠️ `grep -P` 는 `\w` 가 ASCII 한정이라 금지(Step 4) |
- 클래스의 성격이 갈린다: 앞 다섯 줄(줄표·용어-머리·콜론·조각문·소유 직역)은 **기계 검출
- 가능**(grep 후보 + 눈 판정)이고, 뒤 두 줄(내부 조어·레지스터)은 **판정 클래스**다 —
- Done When에서 서로 다른 check-class로 채점된다.
+ **클래스 라벨 대응** — 레인은 `C`, 이 문서는 `S` 다. 이름이 갈린 채로 두면 다음 사람이 다시 포크한다:
+ | 레인 | 이 문서 | 레인 | 이 문서 |
+ |---|---|---|---|
+ | C1 줄표 이어붙임 | **S1** | C4 조각문 | **S5** |
+ | C2 용어-머리 | **S3** | C5 소유 직역 | **S6** |
+ | C3 콜론 나열투 | **S4** | C6 · C6b 전칭 | **Step 4-b** (S 번호 없음 — 다른 Step 소속) |
+
+ 🟥 **대응표는 «라벨» 대응이지 «패턴» 대응이 아니다.** 레인의 정규식과 위 코드블록의 정규식은
+ **서로 다른 문자열**이다(레인 C1 은 `" — "` 양쪽 공백형인데 이 문서는 그 형태를 금지한다).
+ ⇒ **레인이 초록이라고 코드블록 패턴이 보정된 것이 아니다.** 둘을 한 벌로 만드는 것이 옳은
+ 방향이나 오늘 안 했다 — 지금은 두 벌이고, 그 사실을 여기 적어 둔다.
+
+ 🟥 **C6 · C6b 를 지우지 마라** — 챔버 carry-forward 는 Step 2 **와 Step 4** 둘 다를 대상으로
+ 지정했고, 그 둘이 Step 4-b 쪽 절반이다. 레인을 손볼 때 같이 날아가기 쉬운 자리다.
+
+ **미보정으로 남은 것 — 이름으로 남긴다**: `S7`(내부 조어) · `S8`(지시 불명확) · `S9`(레지스터 드리프트) ·
+ `P1`~`P3`(Step 5-s) 는 아직 레인이 없다. 「레인이 없다」는 **「결함이 없다」가 아니다.**
+
### Step 2-b — 부분 개고 전용: 기존 본문과의 리듬 대조
**문서 전체를 새로 쓰는 경우가 아니라 기존 문서에 문단·문장을 끼워 넣는 경우**, 위 클래스가
전부 0이어도 **삽입분만 이질적으로 읽힐 수 있다.** 클래스 목록은 «틀린 표현»을 잡지
«튀는 표현»을 못 잡기 때문이다. 삽입·개고분에 한해 두 가지를 **수치로** 대조한다:
1. **문장 길이 분포** — 본문 평문 문장의 길이 중앙값·상위 10%를 먼저 구하고, 삽입분의 각
문장이 상위 10% 안에 드는지 본다. 넘으면 끊는다. (본문에 더 긴 문장이 있어도 근거가
못 된다 — 그건 그 문단의 리듬이지 삽입분의 것이 아니다.)
2. **어휘 반복** — 삽입분 안에서, 그리고 **직전·직후 문장까지 포함해** 같은 어간이 3회
이상 연달아 나오는지. 특히 같은 글자가 뜻이 다른 채로 반복되면(«검사를 더 **붙**여도 …
지점 쪽에 **붙**습니다») 읽는 눈이 걸린다.
> 실측(2026-08-11, 기술문서 v2.1 작업): 클래스 스캔 잔여 0인 삽입분이 본문 112문장 중
> 유일한 소유 직역 1건을 들여왔고, 문장 길이 **124자**(본문 중앙값 40자 · 상위 10% 78자),
> 「내려가」 앞 문장 포함 4회 연속 · 「붙」 한 문장 안 2회였다. 셋 다 기존 클래스 목록으로는
> 안 잡혔고, **읽는 사람이 «톤이 다르다»로 먼저 알아챘다.** 의도 보존으로 제외하는 항목은 **명명된 사유**(열거
- 매달기·리듬 결속·화면 받침)에 한하며, 제외 목록은 Step 5 콜드리드 짝에게 **통독이 끝난
+ 매달기·리듬 결속·화면 받침·**인용된 원문** — 도구가 찍은 출력이나 남의 글을 축자 인용한 자리는 고치면 «출력 그대로»가 거짓이 된다)에 한하며, 제외 목록은 Step 5 콜드리드 짝에게 **통독이 끝난
뒤** 별도 패스로 전달해 대조받는다 — 사전 전달은 첫-읽기 눈을 오염시키고, 자기가 쓴
사유만으로 무제한 제외하지 않는다.
## Step 3 — 정직 수위 층 분리
정직함에는 두 층이 있고, 독자 문서에는 한 층만 싣는다:
- **싣는다 — 논지를 받치는 정직**: 한계 절, 소표본 명시, 자기 철회 사례, "측정 중".
이걸 빼면 글의 등뼈가 빠진다.
- **뺀다 — 내부 감사 어휘**: 검증 원장의 자기감사 디테일("실적은 X만 주장한다",
"도달만·채택 아님" 같은 규율-말투), 내부 등급/게이트 상태 세부. 내부 기록에는 남기고
독자 본문에서는 뺀다.
판단 기준 한 줄: **"이 문장이 독자의 다음 행동이나 판단을 바꾸는가?"** — 바꾸면 정보,
안 바꾸면 자기감사다. **문장 단위로 적용**하고, 한 절의 문장 대부분이 걸리면 절 단위로
제거를 검토한다. 경계 예시: «실패 3건은 내부 전용 API 의존이라 외부 재현이 안 된다»는
독자의 재현 판단을 바꾸므로 **정보**다. «실적은 머지된 것만 주장한다»는 저자의 집계 규율
서술이라 **자기감사**다.
## Step 4 — 수치·주장 게이트 (기존 검증 자산으로 라우팅 — 재발명 금지)
**분모는 기계로 연다**: 본문의 **아라비아 숫자 전수**를 grep으로 추출해 목록을 만들고,
수치 주장이 아닌 항목(버전 표기·목차 번호·연도 등)을 **사유와 함께 제외**한 뒤, 남은 각
행에 아래 라벨 중 하나를 단다. 단위 목록으로 좁혀 시작하지 않는다 — 영문 단위(ms·GB)가
새기 때문이다. 한글 수사("세 배")는 아라비아 전수로도 못 잡으므로 **눈 판정 잔여**로
명기하고 통독에서 본다. 자기 눈으로 고른 수치만 채점하는 것은 measured가 아니다.
⚠️ **`\b` 경계 금지** — 유니코드 인식 엔진(ripgrep·GNU grep UTF-8 로케일·Python `re` —
**`grep -P`는 예외다**: `(*UCP)` 없이는 `\w`가 ASCII 한정이라 숫자-한글 사이에 경계가
생긴다. 반드시 `rg` 로 고정)에서 **한글은 word 문자**라 숫자와 한글 사이엔 경계가 생기지
않는다. `\b\d[\d,]*\b`류 패턴은 숫자 뒤에 한글 조사·단위가 바로 붙는 표기(예: «7개»)를
놓친다. **known-pair로 직접 확인**(엔진 고정, 복붙 실행): 이 SKILL.md 자신에 `rg -n
'\b\d[\d,]*\b'`와 `rg -n '\d(?:[\d,]*\d)?'`(끝자리 콤마를 삼키지 않게 끝을 숫자로 고정)를
각각 돌려 델타를 세면, 경계판이 놓치는 숫자가 나온다(측정일 기준 델타 수를 이력에
기록 — 놓치는 쪽은 대부분 조사·단위가 바로 붙는 주장 수치이고, 날짜·Step 번호처럼 뒤에
공백·기호가 오는 숫자는 양쪽 다 잡힌다). **경계 없는 추출**로 시작하고, 과다추출된
비주장 항목은 위 문장대로 사유와 함께 제외한다.
### Step 4-b — 전칭 단정 후보 검출 (오탐 허용 — 후보 표시용, 판정은 사람)
«전부/모두/하나도 없다/전혀/일절/예외 없이» 류 전칭 단정 어휘 + **부정형 전칭**을
`rg -n '(안|못) ?(했|만들|나오|잡히)|지 않았(다|습니다)'`(엔진 고정, 복붙 실행)로 걸러
후보로 표시하고, 각 후보의 반례가 정말 없는지 본문·근거를 다시 대조한다. grep은 후보만
내고 판정은 사람이 한다 — 오탐 다수가 정상이다. **단, 후보를 세지 않거나 판정을
비워두는 것은 결함이다** — 판정할 사람을 구할 수 없으면 후보 목록을 그대로 남기고 이
조건을 **미충족으로 명시**하고 발행 판단자에게 넘긴다(자기 판정으로 대체 금지 — Step 5
격리 규율과 동형).
실측(비공개 원장, 2026-08-14): 같은 개고 세션에서 반례 탐색 없는 전칭 단정을 두 번
썼고, 한 번은 위 어휘 목록에 없는 **부정형**("~을 안 만들었다")이었다 — grep 어휘만으로
못 잡는 계열이 실재한다는 뜻이라 부정형 패턴을 함께 넣는다. **반례 탐색 없이 쓴 전칭
단정은 원문보다 개고본에서 더 잘 나온다** — 다듬는 행위 자체가 근거 재확인 없이 서술을
넓히기 때문이다. Step 5 재콜드리드가 뒤늦게 잡을 수도 있지만, 앞단에서 후보를 먼저
좁혀두면 그 라운드의 비용이 준다.
수치·주장에는 **두 가지 라벨**이 있고 서로 다른 상태다 — 섞지 않는다:
- **«발행 직전 재측정 대상»** — 근거는 확인됐으나 **시간이 지나면 값이 변하는** 것
(다운로드·별 수·테스트 수). 측정 시점·조건(창)을 병기하고 이 라벨을 단다.
- **«미확인»** — **근거 실물을 아직 확인하지 못한** 주장. 창을 지어 붙이지 않는다(조작된
정밀도). 라벨과 확인 경로(어느 저장소·로그를 보면 닫히는지)를 적고, 발행 전 해소를
필수로 남긴다. 미발견은 "미확인"이지 "없음"이 아니다.
기록에 없는 실적·사례는 1차 출처(저장소·PR·로그)를 직접 조회해 확인하고 나서 싣는다.
- - **출처 역추적이 필요하면** `/phantom-quench` 로, **차트를 그리게 되면** 차트 작성 전에
- dataviz 스킬을 먼저 로드한다. 프로젝트에 금지·조건 수치 목록(원장)이 있으면 발행 전
+ - **출처 역추적이 필요하면** `/phantom-quench` 로 라우팅한다. 🟥 **차트 검증 스킬은 «있다»고
+ 전제하지 마라 — 그러나 «없다»고도 적지 마라.** 이 줄의 이전 판은 「`dataviz` 스킬은 이 레포에
+ 없다」고 적었는데 **그 명제는 거짓이다** — `dataviz` 는 런타임이 공급하는 **번들 스킬로 실재**한다
+ (2026-09-17 확인 — 근거는 세션의 스킬 목록이고, 🟥 **레포 grep 으로는 구조적으로 안 나온다**).
+ 「레포 자산이 아니다」와 「그런 스킬은 없다」는 다른 명제다 — 전자를 후자로 접으면 **실재하는
+ 스킬로 가는 포인터를 잃는다**. 차트를 그리게 되면 그 시점의 런타임에서 **확인하고** 쓰되,
+ 없으면 「없음」으로 적는다. 프로젝트에 금지·조건 수치 목록(원장)이 있으면 발행 전
1패스 대조한다. 이 스킬은 **외부 검증 도구를 재발명하지 않는다**(출처 검증·차트 검증은
위 라우팅으로) — 스킬 안의 grep 열거·스캔은 절차의 일부이지 검증기 신설이 아니다.
## Step 5 — 렌디션 + 지각 QA
- **md 정본은 항상** 만든다. 다이어그램은 mermaid(GitHub·주요 뷰어 네이티브 렌더).
- **HTML/PDF 렌디션은 조건부** — 요청이 명시했거나 게재 채널이 요구할 때만 만든다(판단
주체는 요청/채널이지 저자의 재량이 아니다): 자체완결 HTML(외부 의존 없는 인라인 SVG
다이어그램, 시스템 한글 폰트 스택, `@page` 인쇄 규칙) → headless Chrome `--print-to-pdf`.
- **md-only 예외의 범위는 좁다** — 게재 매체가 md 를 렌더하면(위키·GitHub 등) **md-only
산출물도 렌더 산출물이다.** N/A 는 게재 매체가 렌더를 하지 않음을 확인한 경우에만 쓴다.
**매체가 미상이면**(Step 1 «확인 불가» 경로로 진행한 경우) N/A 자격이 없다 — GitHub
렌더를 기본 렌더러로 가정하고 지각 확인을 수행하며, 그 가정 사실을 산출물 이력에
남긴다.
실측(비공개 원장, 2026-08-14): 렌더된 표의 한 셀에 여러 항목이 뭉쳐 기호-뜻 대응이
깨졌는데, 원문엔 항목이 전부 적혀 있어 논리적 누락이 없었고 열 수·이스케이프 같은
기계 검사도 통과했다. 배경지식 0 콜드리드를 여러 라운드 돌렸는데도 **렌더된 표를 보는
사람만** 그 결함을 알아챘다 — «md-only니까 N/A»로 판단한 것이 오판이었다 — 위키가
md를 렌더하는 순간 렌더 산출물이 생긴다.
- **지각 QA(필수 — 렌더 산출물이 있을 때, md-only라도 게재 매체가 렌더하면 포함)**: 렌더
결과를 **전 페이지 눈으로** 확인한다 — 라벨 잘림(한글 받침), 페이지 나눔, 표/그림 겹침,
다이어그램 텍스트 가림, **표 셀 안에 여러 항목이 한 줄로 뭉쳐 있는지**(구분자 반복 —
렌더된 표에서만 보이고 원문 grep으론 안 잡힌다). 도구 exit 0은 렌더 성공이지 가독성
판정이 아니다. 판정 짝은 **독립 2차 지각 패스**(다른 눈이 같은 렌더를 봄)다 — 콜드리드는
내용을 읽지 렌더 결함을 보지 않으므로 짝이 될 수 없다.
- **발행 전 콜드리드 1패스**: 격리된 검토가 처음 읽는 눈으로 통독한다. 저자는 자기 글의
전제 결손을 못 본다. **격리의 정의**: 저작 맥락을 상속하지 않는 실행이다. 같은 레포에서
띄운 서브에이전트는 프로젝트 지침·메모리를 상속하므로 **완전 블라인드가 아니다** — 저작
맥락 차단이 필요한 판정(전제 결손·자기 어휘 검사)은 레포 밖 cwd의 headless 실행 +
컨트롤(알려진 결함 1건 동반)로 하고, 통독 수준 검토는 다른 에이전트로도 되지만 **어느
격리 수준이었는지 이력에 적는다.** 에이전트 디스패치는 호출 세션의 권한·도구를 따른다
(이 스킬의 allowed-tools 밖의 일이다). 강격리도 비저자 짝도 구할 수 없으면 해당 judged
조건을 **미충족으로 명시**하고 발행 판단자에게 넘긴다 — 자기 검토로 대체하지 않는다.
- 🟥 **재콜드리드 — 지적을 반영해 고쳐 썼으면 고친 것을 다시 읽힌다.** 콜드리드 1회는
*초안*을 검증할 뿐이고, **발행되는 것은 수리본**이다. 수리는 결함의 주된 출처라서
«지적 반영»과 «통과»는 다른 사건이다. 본문이 바뀌었으면 라운드를 하나 더 돈다.
**정지 조건은 라운드 수가 아니라 변경이다** — 그 라운드에 **새 지적이 0건이고 본문
변경이 0건일 때만** 닫는다(어느 하나만으로는 안 닫힌다). 고쳤으면 아직 안 닫힌 것이다.
**미반영 지적이 남으면** 각 건에 명명된 사유 + 발행 판단자 수락 기록을 붙인다 — 없으면
미충족으로 명시(Step 5 다른 judged 조건과 동형 라우팅). 라운드마다 «지적 n건 · 반영
n건 · 본문 변경 여부 · **Step 4/4-b 스캔을 이 수리본에 재실행했는가(y/n)**»를 이력에
적는다 — 수리가 결함의 주된 출처인데 수치·전칭단정 게이트가 초안 기준에 머물면 바로
그 자리에서 새 결함이 태어난다.
> 실측(2026-08-11): 1차 콜드리드가 초안의 삽입 지점 오류를 잡았고, **그 수리가 새 결함
> 3종**(소유 직역 · 문장 길이 124자 · 어휘 반복)을 낳았다. 재콜드리드를 안 돌아 그대로
> 발행될 뻔했고, 읽는 사람이 «톤이 다르다»로 먼저 잡았다. 돌려 보니 문체보다 큰 것까지
> 나왔다 — 삽입분의 주장이 **반례가 흔한 단정**이었고(«검사를 아무리 늘려도 잡히지
> 않는다»), 자리도 닫는 절이 아니라 한계 절이 맞았다. 문장 다듬기 라운드가 **주장 범위와
> 배치**를 되돌렸다.
+ > 추가 관측(2026-08-25, 병렬 세션이 이 스킬을 비공개 문서 2종에 적용): 콜드리드 3라운드에서
+ > 지적이 **14 → 4 → 8** 로 갔고, **3차 8건 중 4건이 2차 수리가 만든 것**이었다.
+ > ⚠️ `LOCAL-ONLY ATTESTATION — UNVERIFIED`: 그 세션의 자기신고이고 이 문서의 저자가
+ > 재측정하지 않았다. 논지의 하중선은 위 2026-08-11 실측이고 이건 보강이다.
+ > ⚠️ **「독립 재현」이라 부르지 않는다** — 그쪽은 판정자가 하나인 약격리 콜드리드고 이쪽은
+ > 게이트라 관측 방식이 다르다. 정확한 표현은 **「관측 방식이 다른 둘에서 같은 방향이 나왔다」**
+ > 까지이고, `n=2` 는 센 표현이다(그 세션이 스스로 이 조건을 붙여 넘겼다).
+ ## Step 5-s — 소리 렌더 + 청취 QA (낭독 레지스터 전용)
+
+ 🟥 **낭독 대본은 렌더 산출물이 「없는」 게 아니라, 렌더 매체가 「소리」다.** Step 5 를 N/A 로
+ 비우면 그 표면은 한 번도 검사되지 않은 채 발행된다. **Step 5 콜드리드는 낭독에도 그대로
+ 적용된다** — 이 절이 대체하는 것은 *지각 QA*(눈 → 귀)이지 콜드리드가 아니다.
+
+ > **출처와 그 한계 (읽고 인용해라)**: 이 절의 축은 2026-08-09 낭독 렌즈 필드런의 **교정판**
+ > A~F 에서 가져왔다. 🟥 **그 필드런이 자기 축 셋을 반증했으므로 초안 판본을 인용하면 안 된다** —
+ > A 호흡은 계기가 틀렸고(아래), E 볼드 개수 기준은 판별력 0, D 어미 기준은 재조정됐다.
+ > 그 렌즈 자체는 **챔버 KILL 판정**을 받았고(별도 자산으로 출하하지 않는다), 그 판정의 운영자
+ > 확정 carry-forward 는 「**새 계기를 짓기 전에 이미 있는 계기의 판별력을 세운다**」였다 —
+ > 그래서 이 절은 축을 넓히지 않고 **텍스트로 기계화되는 셋만** 들여왔다. 🟥 **「실측 근거가 있는
+ > 셋」이 아니다** — 정본이 유효 판정한 축은 **넷**이고(B 지시어 · B′ 동음이의 · C 낭독불가 ·
+ > F 대구 음절 — 🟥 축자를 정확히 적는다: **✅ 를 받은 축은 B·C·F 셋**이고, 그중 **`✅ 유효` 라는
+ > 축자가 붙은 것은 C·F 둘**이다(B 는 `✅ 예측 적중 — 심장 맞다`). **B′ 는 `★ net-new`**.
+ > ⚠️ **「유효 판정」이라는 표현은 정본에 한 번도 안 나온다** — 이 문서가 만든 말이다.
+ > 🟥 이 줄은 **정정하면서 새 팬텀을 낳았던 자리다**: 적대 검토가 준 「유효 판정은 셋」이라는
+ > *지적자의 어휘*를 축자 확인 없이 그대로 옮겨 적었다. **정정도 인용이다 — 원문을 열어라.**), 그중 **C 낭독불가에서 P1·P2 둘이** 나왔다. 🟥 **P2 를 B′ 의
+ > 절반이라 적지 마라** — 정본은 `2,017` 연도 오독을 **C 행**에 싣고, B′ 행의 내용은 「계기」
+ > 計器/契機 하나뿐이라 「나머지 절반」이라 부를 것이 없다. 안 들어온 것은 아래 미측정 목록에
+ > 이름으로 있다. 보정은 Step 2-a 의 정본 레인을 쓴다 — **이 절을 위해 픽스처를 새로 짓지 마라.**
+
+ **텍스트 렌즈로 잡히는 것 (기계 · 이 절의 분모)**
+
+ 🟥 **엔진은 `rg` 로 고정한다** — `.{60,}` 류의 문자 계수와 `[가-힣]` 인식이 엔진마다 다르다.
+ 축은 **셋뿐이고, 넷째는 미보정으로 이름만 남긴다.** 실측 근거 없는 축을 추가하지 않는 것이
+ 이 파일의 유지 규칙이다(초판이 「한자어 연쇄」·「의 3연」 두 축을 근거 없이 넣었다가 뺐다).
+
+ ```bash
+ F='낭독본.md' # 🟥 <> 금지 — 실제 경로로 치환
+ # ── P1 낭독 불가 토큰 — 창: 줄. 소리로 읽는 법이 안 정해진 것
+ rg -n '[0-9]+/[0-9]+|★|%|[A-Za-z]{2,}' "$F" # 🟥 {2,} 다 — PR·CI·QA·AI·ML 이 가장 안 정해진다
+ # ── P2 단위 없는 숫자 — 분모 opener. 숫자 + 뒤 3글자를 다 뽑아 «단위가 붙었나»를 눈으로 본다
+ rg -on '[0-9][0-9,]*.{0,3}' "$F"
+ # ── P3 거짓 종결 — 종결어미 뒤로 문장이 계속된다. Step 2 의 S1b 와 같은 계기다
+ rg -n '(습니다|입니다|다|것|음)\s*[—–―]\s*\S' "$F"
+ ```
+
+ | 축 | 왜 (1차 출처 = 2026-08-09 필드런) | 계기의 성격 |
+ |---|---|---|
+ | **P1** 낭독 불가 토큰 | 기호·분수·영문·**2글자 약어**를 대본에 그대로 두면 **발표자가 무대에서 즉석에 정한다**. 실측: 26건 중 **8종이 읽는 법 미정**. 읽는 법을 대본에 박아라(「XYZ, 즉 <풀어 읽는 이름>」 — 약어를 처음 쓰는 자리에서 한 번) | 잔여 0 스캔. ⚠️ **오탐이 정상** — `ms`·`GB` 같은 단위는 사유를 붙여 제외한다 |
+ | **P2** 단위 없는 숫자 | 실측: **단위 없는** `2,017` 이 「이천십칠」 = **연도로 들렸다**. 🟥 **계기는 「단위 없는 숫자」를 찾는 것이지 「한글 수사+단위」를 찾는 게 아니다** — 후자는 **수리된 형태**라, 그걸 스캔하면 처방을 결함으로 세게 된다(초판이 그렇게 틀렸다) | **분모 + 눈 판정**(Step 4 와 같은 형태). 잔여 0 이 아니라 «전건에 판정이 붙었나»로 채점한다 |
+ | **P3** 거짓 종결 | A축의 **실제 얼굴**. 필드런에서 「60자 초과」는 **4건 전부 오탐**이었고, 그 자리에서 진짜로 나온 결함이 이것이다(3건) — 「습니다 —」 뒤로 문장이 계속되면 청중은 **문장이 끝난 줄 알고 주의를 놓는다** | 잔여 0 스캔 |
+
+ **🟥 P4 호흡 — 미보정(UNCALIBRATED). measured 에서 뺀다.**
+ 정본 상수는 **「한 호흡 ≤22자 · 38자는 아님」**(운영자 반복 낭독으로 실측)이고, 재는 단위는
+ **문장 길이가 아니라 「끊을 수 있는 자리 사이의 최장 구간」**이며, 세는 것은 **문자수가 아니라
+ 낭독 음절수**다(`1,857` 은 5문자지만 6음절, `QA` 는 2문자지만 3음절 — 문자수로 재면 숫자·라틴이
+ 든 문장이 **조직적으로 과소평가**된다). 이 셋을 다 만족하는 계기를 아직 안 만들었으므로
+ **축을 「미보정」으로 표기하고 measured 조건에서 제외**한다.
+ **🟥 엔진 부재 시 degrade — 이 절은 `rg` 에 고정되어 있고, 그것이 §Step 2-a 와 긴장한다.**
+ Step 2-a 는 보정 레인을 **Python `re`** 로 고정했다 — 이유는 ubuntu CI 에 `rg` 가 없기 때문이다.
+ 그런데 위 `P1`~`P3` 는 `rg` 로 적혀 있고, §Done When 은 그 셋을 **`measured`** 로 건다. 두 줄이 같은
+ 문서 안에 있으므로 부재 경로를 명시한다:
+ - **`rg` 가 있는 노드** — 위 세 줄을 그대로 복붙해 실행한다(의도된 경로).
+ - **`rg` 가 없는 노드** — 다른 엔진으로 바꿔도 되나, 🟥 **바꾸기 전에 known-pair 로 확인하고
+ 바꿔라.** 정규식 방언이 달라지면 세 스캔은 에러를 내지 않고 **조용히 0건을 낸다** — 그것은
+ 「결함이 없다」가 아니라 「계기가 안 돌았다」이고, **둘은 출력이 같다**.
+ ⚠️ 어느 종류의 grep 이 `\s`·`\d` 를 지원하는지를 **기억으로 단정하지 마라** — POSIX ERE 는 그 둘을
+ 정의하지 않아 구현마다 갈리고, 도는 것과 안 도는 것이 **같은 이름**을 쓴다.
+ (이 문단의 초판이 「BSD `grep -E` 는 `\s` 를 리터럴 `s` 로 읽는다」고 단언했는데,
+ 2026-09-17 실측이 **반증했다** — 그 머신의 `/usr/bin/grep -E 'a\sb'` 는 `a b` 만 잡고 `asb` 는
+ 안 잡았다. 단언이 틀렸고, 그래서 이 줄은 «어느 구현이 뭐를 한다» 대신 «확인하고 써라»로 바뀐다.)
+ known-pair: 이 문서가 이미 가진 양성 사례 한 줄 + 안 걸려야 할 한 줄을 같은 실행에 통과시켜 둘이 **갈리는지**를 본다.
+ ⇒ **해당 행을 «미충족»으로 명시**하고 어떤 엔진이 없었는지 적는다. 통과를 주장하지 않는다
+ (`P4` 가 «미보정»으로 빠진 것과 같은 방향 — 없는 계기를 초록으로 접지 않는다).
+ 파이썬 포팅은 **아직 안 만들었다** — 만들면 Step 2-a 레인으로 가야 하고, 그때까지는 이 칸이 비어 있다.
+
+ 🟥 **`rg -n '.{60,}'` 를 쓰지 마라** — 초판이 그걸 넣었는데, 필드런이 이미 반증한 판본이다
+ (단위가 틀렸고, 「40~55자」조차 정본이 「출처 없이 쓴 값, **거의** 두 배 과대」로 교정한 값이었다.
+ 60 을 22 로 나누면 약 2.7 배이나 그 수는 **정본에 없는 유도값**이라 라벨을 붙여 둔다). 잘못된 계기는 없는 계기보다 나쁘다 — 초록을 내주기 때문이다.
+
+ **🟥 텍스트로는 구조적으로 못 잡는 것 — 이름으로 남기고 미측정으로 표기한다**
+ 발음 충돌·혀 꼬임 · 억양과 강세 위치 · **실제 호흡 지점**(P4) · 말버릇·군말 ·
+ **5분 넘게 떨어진 지시어**(B 축 — 필드런의 심장이나 슬라이드-시각 매핑이 있어야 기계화된다) ·
+ **대구 음절 어긋남**(F 축 — 정본이 8건 중 6통과로 유효 판정했으나 여기 계기가 없다) ·
+ **동음이의 낱말**(B′ 축 **통째로** — 「계기」가 計器인지 契機인지는 숫자 단위로 안 갈리고, 문법적으로
+ 완벽히 파싱되므로 청중은 *다른 문장*을 듣고 그냥 넘어간다. 화면에 없으면 복구 경로 0).
+ 🟥 **이 넷은 「없는 축」이 아니라 「안 가져온 축」이다** — 정본에 있고, 여기에 계기가 없을 뿐이다.
+ ⇒ **닫는 방법은 하나뿐이다: 소리 내어 통독 1패스.** 그리고 **짝은 「듣는 사람」**이다 —
+ 저자가 자기 대본을 읽는 것은 생성자=평가자이므로 충족이 아니다(Step 5 지각 QA 와 동형).
+
+ **🎧 청취 라운드 — 정지 조건 (Step 5 재콜드리드와 동형)**
+ 소리를 실제로 렌더해 **듣는 사람**이 듣는다. 지적을 반영해 고쳤으면 **고친 것을 다시 들린다.**
+ **정지 조건은 라운드 수가 아니라 변경이다** — 그 라운드에 **새 지적 0건 ∧ 본문 변경 0건**일 때만 닫는다.
+ 라운드별 「지적 n · 반영 n · 본문 변경 여부」를 이력에 적는다.
+ 🟥 **수리는 결함의 주된 출처다** — 낭독을 고치면 리듬이 바뀌므로 P1~P3 기계 스캔도 **그 수리본에서 재실행**한다.
+
+ **🔧 기계 앵커 — 소리를 「산출물」로 만든다 (주체: 발표자·사람)**
+ 🟥 **md 정본을 그대로 먹이지 마라** — TTS 는 `**`·`|`·`#` 를 그대로 읽는다. 평문으로 먼저 내린다:
+ ```bash
+ sed -E 's/`[^`]*`//g; s/\*\*//g; s/^#+ //; s/^\| *//; s/ *\| */ /g' "$F" > /tmp/script.txt
+ say -o /tmp/script.aiff -v Yuna -f /tmp/script.txt # macOS 내장 TTS · 임의 TTS 가능
+ ```
+ 소리 파일을 산출물 이력에 첨부하고, 듣는 사람은 그 파일을 듣는다. 그러면 「렌더 매체가 소리다」가
+ 비유가 아니라 **첨부 가능한 산출물**이 되고, Step 5 의 「스크린샷 첨부 + 미충족 명시」 degrade 와
+ 같은 형태가 된다. ⚠️ **평문화 자체가 손실이다** — 표는 줄로 눌리고 강조는 사라진다. 무엇이
+ 눌렸는지 확인하고, 눌린 자리가 발화에 필요하면 대본을 고쳐라(변환기를 고치는 게 아니다).
+ ⚠️ TTS 는 사람 낭독의 **대리물**이다 — 억양·강세·말버릇을 보존하지 않는다. 대리물로 본 사실을 이력에 적는다.
+
+ **degrade**: 듣는 사람을 못 구하면 **소리 렌더 파일을 이력에 첨부하고** 해당 Done When 을
+ **미충족으로 명시**하여 발행 판단자에게 넘긴다. 자기 낭독으로 대체하지 않는다(생성자=평가자).
+
## Done When
+ 🟥 **클래스 목록을 여기에 다시 열거하지 않는다** — Step 2 표의 **check-class 열이 정본**이다.
+ 괄호로 닫힌 열거를 여기 두면, Step 2 에 행을 추가할 때마다 새 클래스가 **채점되지 않은 채**
+ 남는다(관측 2026-08-25: 그때 새로 넣은 클래스들이 어느 Done When 행에도 안 걸렸다. ⚠️ 그중
+ 하나는 이후 Added-Scope 판정으로 별건 분리됐으므로 «둘»이라는 당시 개수는 지금 표와 안 맞는다).
+ ⚠️ **아래 라우팅은 `measured`·`judged` 둘만 받는다** — Step 2 표에 `mandatory-pass` 행을 만들면
+ 그 행을 받는 Done When 줄도 같이 만들어라. 안 그러면 이 문단이 막으려던 고아가 그대로 재발한다.
+
| 조건 | check-class |
|---|---|
- | 대상 매체 실물 표본 확인 기록이 산출물 이력에 존재 — 불가 시 **시도 내용·사유 포함** 명기(시도 기록 없는 «불가»는 불충족) | mandatory-pass |
- | Step 2 **기계 클래스**(줄표·용어-머리·콜론·조각문·소유 직역) 스캔 잔여 0 — 컨트롤(알려진 양성 1건) 동반, 제외는 명명 사유와 함께 목록화 | measured |
- | Step 2 **판정 클래스**(내부 조어·레지스터) 통과 | judged — 짝: 콜드리드 통독(통독 후 제외 목록 대조) |
+ | 대상 매체 실물 표본 확인 기록이 산출물 이력에 존재 — 불가 시 **시도 내용·사유 포함** 명기(시도 기록 없는 「불가」는 불충족) | mandatory-pass |
+ | Step 2 표에서 check-class 가 **`measured` 인 전 행**의 스캔 잔여 0 — **Step 2-a 보정을 먼저 실행**(`bash scripts/test_ko_tech_writer_lanes.sh` — 전 레인 `discriminates`)한 뒤 스캔. 🟥 레인이 없는 클래스는 **「보정 안 됨」으로 적고 measured 로 세지 않는다**(레인 부재는 결함 부재가 아니다). 분모 opener(S1a·P2)는 `neg=0` 이 원리적으로 불가능하므로 「양성이 출력에 나오는가」로 본다. 제외는 **명명 사유와 함께 목록화**하되, 전수가 큰 분모(S1a)는 **집계 1줄로 제외**하고 위험 부분집합만 건별로 적는다 | measured |
+ | Step 2 표에서 check-class 가 **`judged` 인 전 행**의 통과 | judged — 짝: 콜드리드 통독(통독 후 제외 목록 대조) |
| **부분 개고인 경우**(기존 문서에 삽입·수정): Step 2-b 리듬 대조 — 삽입분 각 문장이 본문 길이 상위 10% 이내 ∧ 어간 3회 연속 반복 0. 전문 신규 집필이면 N/A 명기 | measured |
- | 본문 수치 전건(기계 추출 분모 기준, `\b` 미사용 경계없는 추출, **발행 직전 최종본 기준**)이 라벨(창 병기/재측정 대상/미확인) 동반 + **한글 수사(세 배·두 배 등) 눈 판정 잔여 목록이 이력에 명기됨(0건이면 «0»으로 기록)** | measured |
+ | 본문 수치 전건(기계 추출 분모 기준, `\b` 미사용 경계없는 추출, **발행 직전 최종본 기준**)이 라벨(창 병기/재측정 대상/미확인) 동반 + **한글 수사(세 배·두 배 등) 눈 판정 잔여 목록이 이력에 명기됨(0건이면 「0」으로 기록)** | measured |
| 전칭 단정(부정형 포함) 후보 grep 스캔을 **발행 직전 최종본**에서 실행 — 후보 n건 수치 기록 | measured |
- | 위 후보 n건 각각에 반례 확인 결과(«확인함»/«확인 못 함»)가 붙음 — 미판정 0 | judged — 짝: Step 5 콜드리드(통독 후 후보 목록 대조) |
+ | 위 후보 n건 각각에 반례 확인 결과(「확인함」/「확인 못 함」)가 붙음 — 미판정 0 | judged — 짝: Step 5 콜드리드(통독 후 후보 목록 대조) |
| **파생 압축 자산인 경우**(Step 0 세 번째 레지스터): 자립성 검사(정본 어휘·주장 범위·은어 대조) 결과가 이력에 존재 — 해당 없으면 N/A 명기 | judged — 짝: 배경지식 0 콜드리드(원문 비열람) |
- | 렌더 산출물(HTML/PDF/이미지 — 파생 압축 자산 포함)이 존재하거나 **게재 매체가 md를 렌더하는 경우**(위키·GitHub 등) 전 페이지 지각 확인 — 게재 매체가 md를 렌더하지 않음을 확인한 경우만 N/A 명기(사유 기록). **매체 미상이면** GitHub 렌더 가정으로 지각 확인 수행(가정 기록) — N/A 불가. Step 5 미적용 레지스터(낭독 대본)는 N/A 명기 | judged — 짝: **독립 2차 지각 패스**(다른 눈이 같은 렌더를 봄) |
- | 콜드리드가 **변경 없음으로 닫혔다** — 마지막 라운드에 **새 지적이 0건이고 본문 변경이 0건**일 때 닫는다(어느 하나만으로는 안 닫힌다). 지적을 반영해 고쳤으면 그 수리본으로 한 라운드 더. **미반영 지적이 남으면** 각 건에 명명된 사유 + 발행 판단자 수락 기록을 붙인다 — 없으면 미충족으로 명시. 라운드별 «지적 n · 반영 n · 본문 변경 여부» + 격리 수준(강/약) 이력 기록. Step 5 미적용 레지스터(낭독 대본)는 N/A 명기 | judged — 짝: 격리 검토(Step 5 정의) |
+ | 렌더 산출물(HTML/PDF/이미지 — 파생 압축 자산 포함)이 존재하거나 **게재 매체가 md를 렌더하는 경우**(위키·GitHub 등) 전 페이지 지각 확인 — 게재 매체가 md를 렌더하지 않음을 확인한 경우만 N/A 명기(사유 기록). **매체 미상이면** GitHub 렌더 가정으로 지각 확인 수행(가정 기록) — N/A 불가. **낭독 대본은 N/A 가 아니라 Step 5-s 청취 QA 로 간다**(렌더 매체가 소리다) | judged — 짝: **독립 2차 지각 패스**(다른 눈이 같은 렌더를 봄) |
+ | 콜드리드가 **변경 없음으로 닫혔다** — 마지막 라운드에 **새 지적이 0건이고 본문 변경이 0건**일 때 닫는다(어느 하나만으로는 안 닫힌다). 지적을 반영해 고쳤으면 그 수리본으로 한 라운드 더. **미반영 지적이 남으면** 각 건에 명명된 사유 + 발행 판단자 수락 기록을 붙임 — 없으면 미충족 명시. 라운드별 「지적 n · 반영 n · 본문 변경 여부」 + 격리 수준(강/약) 이력 기록. 🟥 **낭독 대본도 이 행의 대상이다** — Step 5-s 가 대체하는 것은 *지각 QA* 이지 콜드리드가 아니다 | judged — 짝: 격리 검토(Step 5 정의) |
+ | **낭독 레지스터인 경우**: Step 5-s **P1·P2·P3** 실행 — P3 은 잔여 0. **P1 은 오탐이 정상이므로 「잔여 0」이 아니라 «전건에 판정 + 제외는 명명 사유와 함께 목록화»로 채점한다**(단위·고유명사가 늘 걸린다). P2 는 분모 전건에 판정. **P4 호흡은 미보정이라 이 조건에 안 들어간다**(빠뜨린 게 아니라 제외한 것이며, 그 사실을 이력에 적는다). **낭독 레지스터가 아니면 N/A 명기** | measured |
+ | **낭독 레지스터인 경우**: 소리 렌더(md→평문 변환 후 TTS) 파일이 이력에 존재 + **듣는 사람**의 확인. 못 구하면 파일만 첨부하고 미충족 명시(자기 낭독 대체 금지). **낭독 레지스터가 아니면 N/A 명기** | judged — 짝: 듣는 사람 |
| 정직 수위 분리(Step 3)가 적용됨 | judged — 짝: 발행 승인자 확인 또는 격리 적대 검토. 둘 다 불가하면 **미충족으로 명시 보고**(자기 검토로 대체 금지) |
## 역할 경계 (중복 아님을 명시)
- `hub-persona-auditor` **에이전트** — 완성된 대외 초안의 **페르소나 감사**(검토). 이 스킬은
**저작·개고 절차**다. Step 5 콜드리드에서 그 에이전트를 짝으로 쓸 수 있다(라우팅 관계).
+ - `fh-preprep:preprep` — 발표 **표면 사이**(덱↔원고↔노트)의 정합을 본다. 이 스킬은 **한 편의
+ 산문/대본 자체**를 본다. 🟢 경계는 preprep 쪽이 먼저 그어 놓았다 — 그 스킬은 초판에 있던
+ Step 2 복제 레인(`L9`)을 **빼면서** «번역투·레지스터·수치 게이트·지각 QA 는 `ko-tech-writer` 로
+ 간다» 고 명시했다. **Step 5-s 는 그중 «낭독의 지각 QA»** 자리다 — 재발명이 아니다.
+ ⚠️ **겹치는 축 하나**: preprep 의 `L5 jargon`(조어가 낭독면 첫 등장에 풀이를 달았나, 차단)
+ ↔ 이 문서의 `S7`. 같은 것을 두 번 재지 않도록, preprep 을 돌린 발표 대본은 `S7` 을
+ «preprep `L5` 로 대체»로 적는다. 🟥 그 둘이 정말 같은 것을 잡는지는 **정의 대조로만 판단했고
+ 같은 대본에 둘 다 돌려본 적은 없다** — 측정이 아니다.
- `harness-doctor --lint` — **하네스 자산**의 언어 패턴(자기마케팅) 검출. 이 스킬은 독자
대면 문서가 대상이고 번역투·레지스터·정직 수위까지 다룬다.
- 플랫폼 내장 문서 기능 — 특정 문체 캘리브레이션·정직 수위 층 분리·지각 QA 파이프라인은
내장에 없다(이 스킬이 더하는 것은 거버넌스다).
- 독립 실행 및 degrade 경로: phantom-quench·dataviz 미설치 → 해당 라우팅을 수동 대조로 ·
+ 독립 실행 및 degrade 경로: phantom-quench 미설치 → 해당 라우팅을 수동 대조로 ·
WebFetch 불가 → Step 1 «확인 불가» 경로(시도 기록 의무) · headless Chrome 부재 →
HTML/PDF 렌디션을 «미생성»으로 명기하고 md 정본만 산출 · **Step 4-b 판정 주체(사람) 부재
→ 후보 목록을 그대로 두고 해당 Done When 을 미충족으로 명시**(자기 판정 대체 금지) ·
**독립 2차 지각 패스 부재 → 렌더 스크린샷을 산출물 이력에 첨부하고 해당 Done When 을
미충족으로 명시**(저자가 같은 렌더를 두 번 보는 것으로 대체 금지 — 생성자=평가자가 된다).
+ **듣는 사람 부재 → 소리 렌더 파일 첨부 + 해당 Done When 미충족 명시**(자기 낭독 대체 금지) ·
+ 🟥 **TTS 부재**(macOS 아닌 노드 · `say` 없음 · 한국어 보이스 미설치) **→ 소리 렌더를 「미생성」으로
+ 명기하고, 사람이 직접 소리 내어 읽은 뒤 듣는 사람이 확인한다** — 기계 앵커가 없어지는 것이지
+ 청취 라운드가 없어지는 게 아니다. 듣는 사람까지 없으면 그 Done When 은 미충족이다.
+ ⚠️ 이 스킬은 `say` 를 **어느 노드에서도 실행해 본 적이 없다** — 플래그 형태만 확인했다. ·
각 degrade는 산출물 이력에 적는다.
**언어 범위**: 이름 그대로 **한국어 전용**이다. Step 0·1·3·4·5의 구조는 언어 무관이지만
Step 2 문체 클래스가 전부 한국어 실측이라, 영어 지원은 영어 실측 클래스가 쌓인 뒤 별도
확장(`en-` 자매 또는 일반화)으로 간다 — 실측 없는 클래스를 미리 짓지 않는다(유지 규칙).