@tienne/gestalt 0.72.1 → 0.72.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CLAUDE.md +22 -0
  2. package/README.ko.md +33 -7
  3. package/README.md +33 -6
  4. package/dist/package.json +1 -1
  5. package/dist/plugin/role-agents/_shared/references/README.md +1 -1
  6. package/dist/plugin/role-agents/_shared/references/ai-tell-quick-rules.md +24 -14
  7. package/dist/plugin/role-agents/_shared/references/author-voice.md +35 -9
  8. package/dist/plugin/role-agents/code-review-responder/AGENT.md +2 -2
  9. package/dist/plugin/role-agents/code-review-writer/AGENT.md +7 -4
  10. package/dist/plugin/role-agents/humanize-monolith/AGENT.md +1 -1
  11. package/dist/plugin/role-agents/jira-writer/AGENT.md +1 -1
  12. package/dist/plugin/role-agents/presentation-writer/references/content-playbook.md +1 -1
  13. package/dist/plugin/skills/local-pr/SKILL.md +5 -5
  14. package/dist/plugin/skills/review/SKILL.md +1 -1
  15. package/dist/plugin/skills/review-reply/SKILL.md +9 -9
  16. package/dist/plugin/skills/ship/SKILL.md +10 -10
  17. package/dist/src/cli/commands/pr.js +2 -2
  18. package/dist/src/cli/commands/pr.js.map +1 -1
  19. package/dist/src/cli/index.js +4 -4
  20. package/dist/src/cli/index.js.map +1 -1
  21. package/dist/src/humanize/detectors.d.ts +3 -3
  22. package/dist/src/humanize/detectors.d.ts.map +1 -1
  23. package/dist/src/humanize/detectors.js +12 -5
  24. package/dist/src/humanize/detectors.js.map +1 -1
  25. package/dist/src/local-pr/engine.d.ts +1 -1
  26. package/dist/src/local-pr/engine.d.ts.map +1 -1
  27. package/dist/src/local-pr/engine.js +1 -1
  28. package/dist/src/local-pr/engine.js.map +1 -1
  29. package/dist/src/local-pr/repository.js +1 -1
  30. package/dist/src/local-pr/repository.js.map +1 -1
  31. package/dist/src/mcp/schemas.js +2 -2
  32. package/dist/src/mcp/tools/review-passthrough.js +2 -2
  33. package/package.json +1 -1
  34. package/plugin/.codex-plugin/plugin.json +1 -1
  35. package/plugin/.mcp.json +1 -1
  36. package/plugin/mcp.json +1 -1
  37. package/plugin/role-agents/_shared/references/README.md +1 -1
  38. package/plugin/role-agents/_shared/references/ai-tell-quick-rules.md +24 -14
  39. package/plugin/role-agents/_shared/references/author-voice.md +35 -9
  40. package/plugin/role-agents/code-review-responder/AGENT.md +2 -2
  41. package/plugin/role-agents/code-review-writer/AGENT.md +7 -4
  42. package/plugin/role-agents/humanize-monolith/AGENT.md +1 -1
  43. package/plugin/role-agents/jira-writer/AGENT.md +1 -1
  44. package/plugin/role-agents/presentation-writer/references/content-playbook.md +1 -1
  45. package/plugin/skills/local-pr/SKILL.md +5 -5
  46. package/plugin/skills/review/SKILL.md +1 -1
  47. package/plugin/skills/review-reply/SKILL.md +9 -9
  48. package/plugin/skills/ship/SKILL.md +10 -10
@@ -45,7 +45,7 @@ export function handleReviewPassthrough(reviewEngine, executeEngine, roleAgentRe
45
45
  }
46
46
  }
47
47
  /**
48
- * 로컬 PR에서 리뷰 대상(변경 파일)을 끌어온다. 조회가 끝나면 저장소를 닫는다.
48
+ * 로컬 PR에서 리뷰 대상(변경 파일)을 끌어온다. 조회가 끝나면 저장소 연결을 끊는다.
49
49
  *
50
50
  * 실패는 PrError로 던진다. 바깥 catch가 exitCode를 kind로 접어서 ges_pr과 같은
51
51
  * 응답 규약을 쓴다. 3은 PR을 못 찾은 것이다. 4는 PR은 있는데 리뷰할 게 없는 상태다.
@@ -254,7 +254,7 @@ function actorOfAgent(name) {
254
254
  *
255
255
  * 세션의 진행 상태는 메모리에만 산다. 프로세스가 죽거나 세션이 다른 자리에서 열리면
256
256
  * 그 값이 통째로 사라진다. 그러면 같은 합의로 다시 부른 publish가 코멘트를 전부 다시 쓴다.
257
- * PR은 이벤트 소싱이라 그렇게 붙은 중복은 지울 수 없고 사람이 손으로 닫아야 한다.
257
+ * PR은 이벤트 소싱이라 그렇게 붙은 중복은 지울 수 없고 사람이 스레드를 하나씩 resolve로 접어야 한다.
258
258
  * 그래서 어디까지 썼는지를 PR 자신에게도 남긴다 — 재기동해도 여기서 되짚는다.
259
259
  *
260
260
  * 코멘트의 `marker` 필드에 넣는다. 본문에 실었더니 CLI에서도 웹에서도 그대로 보였다 —
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tienne/gestalt",
3
- "version": "0.72.1",
3
+ "version": "0.72.3",
4
4
  "description": "TypeScript AI Development Harness - Gestalt psychology-driven requirement clarification",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gestalt",
3
- "version": "0.72.1",
3
+ "version": "0.72.3",
4
4
  "description": "Gestalt psychology-driven AI development harness. Transforms scattered requirements into structured, validated specifications through interactive interviews.",
5
5
  "author": {
6
6
  "name": "tienne"
package/plugin/.mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "gestalt": {
4
4
  "command": "npx",
5
- "args": ["-y", "@tienne/gestalt", "serve"],
5
+ "args": ["-y", "@tienne/gestalt@0.72.3", "serve"],
6
6
  "startup_timeout_sec": 180,
7
7
  "tool_timeout_sec": 900
8
8
  }
package/plugin/mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "gestalt": {
4
4
  "command": "npx",
5
- "args": ["-y", "@tienne/gestalt", "serve"],
5
+ "args": ["-y", "@tienne/gestalt@0.72.3", "serve"],
6
6
  "startup_timeout_sec": 180,
7
7
  "tool_timeout_sec": 900
8
8
  }
@@ -29,7 +29,7 @@ pnpm verify:rules
29
29
 
30
30
  - **룰을 추가하면 그 문서가 스스로 그 룰을 지키는지 먼저 확인한다.** 룰 문서가 금지 어휘를
31
31
  본문에 쓰면 산출물로 샌다. 금지어를 넣었으면 같은 문서를 grep한다.
32
- - 어투 규칙은 **S1으로 올려야 실제로 강제된다.** S2는 모델이 우선순위를 알아서 정하면서 새어나간다.
32
+ - 어투 규칙은 **S1으로 올려야 실제로 강제된다.** S2는 모델이 우선순위를 알아서 정하면서 빠져나간다.
33
33
  - 심각도를 바꿀 때는 근거를 남긴다. A-2, I-1, C-8은 대조 코퍼스 측정으로 조정했고 그 근거가
34
34
  [룰북 측정 근거](ai-tell-quick-rules.md#측정-근거)에 있다. 감으로 올리고 내리면 다음 사람이 되돌린다.
35
35
  - 경로를 참조하는 자리가 여러 곳이다. 파일을 옮기거나 이름을 바꾸면 `plugin/` 전체에서
@@ -14,7 +14,7 @@
14
14
 
15
15
  **삭제 처방은 삭제다 (중요):** 처방에 "삭제"가 있는 항목은 **더 나은 표현으로 바꾸지 않는다.** 지우고 그 자리를 원문에 이미 있는 가장 구체적인 문장으로 대신한다. 모델은 D-2, D-3, D-4, D-6, C-10처럼 "삭제"라고 적힌 항목에서 리듬을 살리려고 새 마무리 문장이나 새 부제를 만들어 넣는 경향이 강한데, 그건 원문에 없던 수사를 추가하는 것이라 자체검증 6번에 걸린다. 지울 자리에 쓸 문장이 원문에 없으면 그냥 앞 문장에서 끝낸다.
16
16
 
17
- **말투 감도 (중요):** 같은 명사화, 번역투라도 **대화나 리뷰 코멘트에서는 문서보다 훨씬 튄다.** 문서(칼럼·리포트) 기준 S2인 A-2, A-5, F-4, F-5, F-6, F-7, I-1, I-5 계열은 대화, 리뷰 코멘트에서 **S1로 격상**해 교정한다. 사람은 대화에서 개념을 명사 덩어리로 뭉치지 않고 동사로 풀어 말하기 때문이다. 심각도 칸에 `S2 / **대화·리뷰 S1**`이라고 적힌 룰이 여기 해당한다.
17
+ **말투 감도 (중요):** 같은 명사화, 번역투라도 **대화나 리뷰 코멘트에서는 문서보다 훨씬 튄다.** 문서(칼럼·리포트) 기준 S2인 상당수가 대화, 리뷰 코멘트에서 **S1로 격상**된다. 사람은 대화에서 개념을 명사 덩어리로 뭉치지 않고 동사로 풀어 말하기 때문이다. 어느 룰이 격상되는지는 심각도 칸에 `S2 / **대화·리뷰 S1**`이라고 적힌 표기로 판단한다. 전체 목록이 필요하면 자체검증 5번을 본다 — **사본은 그 한 자리로 정한다.** 여기 또 적으면 세 자리가 갈라진다.
18
18
 
19
19
  **한자어를 피하는 게 목적이 아니다 (F-4·F-5 오적용 주의):** 겨냥하는 건 개념을 뭉친 **명사화**(-성/-적/-화)이지 한자어 동사가 아니다. "측정하다"를 "재다"로, "판단하다"를 "따지다"로 바꾸면 정확도만 잃는다. 그 자리의 정확한 말이 한자어면 한자어를 쓴다. 반대 방향 실수도 같다 — 한자어를 피하려고 비유 명사(축·증류)나 물리 동사(재다)로 도망가면 F-7에 걸린다. 셋 다 겪은 실례: `네 축을 따로 재고 판정한다` → `4가지 측면에서 각각 측정하고 판단한다`.
20
20
 
@@ -50,11 +50,11 @@
50
50
  | B-2 | 영어 어휘 직역 가능한데 그대로 | S2 | 한국어로 옮기되 업계 표준은 유지 |
51
51
  | B-3 | 안 굳어진 영어 구·단어 음차 표기 ("소스 오브 트루스"), 그 음차를 약어로 우회한 표기(`SSOT`·`SoT`) | S1 | 한글 의역 + 첫 등장만 원어 괄호 병기("기준 문서(source of truth)", "단일 기준점(source of truth)" 등), 이후 한글만. 단 위 "굳어진 음차 화이트리스트"에 있는 정착어는 Do-NOT — of/and 등 기능어까지 통째 음차한 구(룩 앤 필·로우 행잉 프룻)가 최우선 대상. 무엇을 가리키는지 보고 고르는 표는 [style-guide.md의 single source of truth를 뭐라고 쓸까](style-guide.md#single-source-of-truth를-뭐라고-쓸까)를 따른다 |
52
52
  | B-4 | 영어 개념을 어색하게 옮긴 조어("생산처" ← producer, "응답처") | S2 | 억지 신조어 대신 이미 쓰이는 말로. 코드 맥락이면 "호출부"·"사용처". **팀에서 이미 굳은 조어는 예외** — "소비처"는 팀 지라 티켓에서 라이브러리를 가져다 쓰는 쪽을 가리키는 말로 정착했으므로 교정 대상이 아니다 (→ 아래 [측정 근거](#측정-근거)) |
53
- | B-5 | 영어 추상 개념어를 사전 뜻으로 옮겨 레지스터가 어긋난 말 (materialize → "물질화", semantics → "의미론", virtue → "미덕", durably → "내구성 있게") | S1 | 그 자리에서 실제로 무슨 일이 벌어지는지를 동사로 쓴다. 아래 [B-5 대체어](#b-5-대체어) 표 참조. 음차로 도망가지 않는다 — "머티리얼라이즈"로 바꾸면 B-3에 걸린다 |
53
+ | B-5 | 영어 개념어나 다의어 동사를 한국어 단어로 몰아 옮겨 레지스터가 어긋난 말 (materialize → "물질화", semantics → "의미론", close → "닫다") | S1 | 그 자리에서 실제로 무슨 일이 벌어지는지를 동사로 쓴다. 아래 [B-5 대체어](#b-5-대체어) 표 참조. 음차로 도망가지 않는다 — "머티리얼라이즈"로 바꾸면 B-3에 걸린다 |
54
54
 
55
55
  ### B-5 대체어
56
56
 
57
- 영어 원문을 옮길 때 반복해서 새는 자리다. 사전 첫 뜻이 한국어에서 다른 영역의 말이라 그 자리만 톤이 튄다.
57
+ 영어 원문을 옮길 때 반복해서 틀리는 자리다. 사전 첫 뜻이 한국어에서 다른 영역의 말이라 그 자리만 톤이 튄다.
58
58
 
59
59
  | 원어 | 쓰지 말 것 | 이렇게 |
60
60
  |---|---|---|
@@ -64,9 +64,17 @@
64
64
  | durably persist | 내구성 있게 저장한다 | 유실 없이 기록한다 / 영속 저장소에 남긴다 |
65
65
  | opaque (system) | 불투명한 시스템으로 전락한다 | 아무도 들여다볼 수 없게 된다 |
66
66
  | deliberately (not) | 의도적으로 결정했다 | 일부러 안 했다 / 이번엔 빼기로 했다 |
67
+ | close (a comment, a talk) | 질문으로 닫는다 | 질문으로 끝낸다 / 마지막에 둔다 |
68
+ | close (an issue, PR, thread) | 이슈를 닫는다 | 이슈를 종료한다 / 스레드를 종료한다 |
69
+ | close (a connection, a repo) | 저장소를 닫는다 | 저장소 연결을 끊는다 |
70
+ | leak (자주 나온다는 뜻으로) | 자주 새는 룰 | 자주 걸리는 룰 / 반복해서 틀리는 자리 |
67
71
 
68
72
  "의미론적 검색"처럼 형용사로 굳은 자리(`의미론적`)는 대상이 아니다. 명사로 홀로 서서 시스템의 동작 규칙을 가리킬 때만 걸린다.
69
73
 
74
+ **한 동사에 여러 뜻을 몰지 않는다.** `close`는 한국어에서 자리마다 다른 동사로 갈린다 — 코멘트나 발표는 끝내고 이슈나 스레드는 종료하고 연결은 끊는다. 이걸 "닫다" 하나로 몰면 그 자리마다 조금씩 어긋난다. 코드 안의 `close()` 호출 그 자체를 가리킬 때만 "닫는다"를 둔다. 산문으로 동작을 설명하는 자리는 무엇을 어떻게 하는지 적는다 — "저장소 연결을 끊는다"처럼. 글이나 말을 "닫는다"고 쓰지 않는다. "맺는다"는 원래 한국어 연어라 그대로 쓸 수 있다. 다만 발표나 코멘트를 두고는 "끝낸다"가 더 흔하다. 자리마다 맞는 동사를 고른다. **상태를 가리키는 "닫힌 PR"은 대상이 아니다** — `CLOSED` 상태값을 옮긴 말이라 동사 교정과 결이 다르다.
75
+
76
+ **"새다"는 누출일 때만 쓴다.** 금지어가 산출물에 흘러나가는 자리에는 맞다. 검사를 빠져나가는 자리("어디까지 새는지")나 자주 나온다는 뜻("자주 새는 룰")에는 안 맞는다. 앞은 "놓친다", "빠져나간다"이고 뒤는 "자주 걸린다", "반복해서 틀린다"다.
77
+
70
78
  ## C. 구조적 AI 패턴
71
79
 
72
80
  | ID | 패턴 | 심각도 | 처방 |
@@ -79,6 +87,7 @@
79
87
  | C-11 | 연결어미 뒤 쉼표 (-고/-며/-지만/-며서/-아서/-어서 직후 쉼표) | S1 | 쉼표 제거. 6+회=강한 신호. KatFish 4.84배 분리도 |
80
88
  | C-12 | 가운뎃점(·) 나열 남발 — 본문 산문에서 "A·B·C"로 항목 압축 | S1 | 쉼표나 구어 연결로 풀기("A, B, C" / "A랑 B하고 C"). 사람은 산문에서 가운뎃점을 거의 안 쓴다. 단 표 안 압축, 용어 목록, 굳어진 합성어("입출력")는 예외 |
81
89
  | C-13 | 같은 문단에서 같은 수치를 다른 단위로 반복 표기("3%" 다음 "3할") — 참조 표현의 숫자만 바꿔 재사용하며 단위를 못 맞춘 경우 | S2 | 단위를 하나로 통일한다. 빌려 쓴 수치 예시는 값과 단위를 통째로 새로 쓴다("3%인데 3할이" → "3%인데 3%가") |
90
+ | C-14 | 수량 예고 — "두 가지", "세 가지 이유"처럼 할 말의 개수를 앞세워 문단을 엶 | S2 / **대화·리뷰 S1** | **문단 첫머리가 개수로 열리는 꼴만 본다.** 개수를 뒤로 보내 서술 안에 넣거나 뺀다("두 가지 짚을 것" → "확인이 필요한 게 2건 있습니다"). 개수가 문장 안에 서술의 일부로 들어간 꼴은 대상이 아니다 — 사람도 결과를 세어 말한다. 겨냥하는 건 먼저 선언하고 시작하는 꼴이다. **개수가 대상의 고정 속성이면 대상이 아니다** — 게슈탈트 원리가 실제로 다섯 개라서 "다섯 가지 원리"는 사실 서술이다. 다만 **필자가 나눈 분류의 개수는 고정 속성이 아니다** — "세 가지로 갈린다. 첫째는…"처럼 문단을 열고 뒤에 올 항목을 예고하면 위치 기준에 걸린다. C-9 숫자 인덱싱의 사촌인데 C-9는 표기만 보고 예고 자체는 안 본다. 이 경계는 뜻이라 탐지기가 없다. E-8·G-4와 겹치면 셋을 다 적용한 꼴이 최종형이다("제가 봤을 때는 확인이 필요한 게 2건 있습니다") |
82
91
 
83
92
  ## D. AI 특유의 관용구 (Signature Phrases)
84
93
 
@@ -89,9 +98,9 @@
89
98
  | D-3 | "본질적으로/핵심적으로" | S1 | 삭제. 다른 부사로 갈아끼우지 말고 그냥 뺀다 |
90
99
  | D-4 | hype 어휘(파격적·압도적·강력한·획기적·치명적) 3회+ | S1 | 원문에 수치·사실이 있으면 그걸로 환원, **없으면 수치를 만들지 말고 수식어만 삭제** |
91
100
  | D-5 | 의인화 추상 주어("기술이 묻는다·시대가 부른다") | S1 | 사람·기관 주어로 |
92
- | D-6 | 결말 공식 "~할 때다/~해야 한다/~지금이야말로" | S1 | 삭제하고 **원문에 이미 있는 가장 구체적인 문장으로 끝낸다.** 더 나은 마무리 문장으로 고쳐쓰지 말고, 리듬을 살리려 하지도 않는다. 닫는 느낌이 꼭 필요하면 원문 근거만으로 쓸 수 있는 평서 한 줄(다음 할 일 등)까지만 |
101
+ | D-6 | 결말 공식 "~할 때다/~해야 한다/~지금이야말로" | S1 | 삭제하고 **원문에 이미 있는 가장 구체적인 문장으로 끝낸다.** 더 나은 마무리 문장으로 고쳐쓰지 말고, 리듬을 살리려 하지도 않는다. 맺는 느낌이 꼭 필요하면 원문 근거만으로 쓸 수 있는 평서 한 줄(다음 할 일 등)까지만 |
93
102
  | D-7 | 변환 공식 "X에서 Y로" 반복 | S2 | 한 번만, 나머지는 일반 서술 |
94
- | D-8 | 과잉 자책, 감정 과장 반응("제일 아팠습니다·뼈아픕니다·부끄럽습니다·뜨끔했습니다") | S1 | 짧은 수긍으로 환원한다("아 그렇네요", "이거 놓쳤네요"). 사실 서술은 그대로 두고 감정 수식만 뺀다. D-4(hype 어휘)의 뒷면이다 — 칭찬 쪽만 막으면 같은 충동이 자책 쪽으로 샌다. 남긴 의견들 사이에 "제일"로 순위를 매기는 것도 여기 해당한다 |
103
+ | D-8 | 과잉 자책, 감정 과장 반응("제일 아팠습니다·뼈아픕니다·부끄럽습니다·뜨끔했습니다") | S1 | 짧은 수긍으로 환원한다("아 그렇네요", "이거 놓쳤네요"). 사실 서술은 그대로 두고 감정 수식만 뺀다. D-4(hype 어휘)의 뒷면이다 — 칭찬 쪽만 막으면 같은 충동이 자책 쪽으로 옮겨간다. 남긴 의견들 사이에 "제일"로 순위를 매기는 것도 여기 해당한다 |
95
104
  | D-9 | 추상명사에 이동 동사("방향도 맞게 갔습니다", "결론이 그쪽으로 갔어요") | S2 / **대화·리뷰 S1** | 방향, 결론, 판단, 논의가 스스로 움직이게 두지 않는다. 사람이나 대상을 주어로 되돌린다("맞는 방향 같아요", "그렇게 결론 냈어요"). D-5 의인화 추상 주어의 사촌이다 |
96
105
 
97
106
  ## E. 리듬, 종결어미
@@ -101,6 +110,7 @@
101
110
  | E-1 | 문장 길이 균일(stdev 8 미만) | S2 | 단문 1~2개 / 장문 1개를 각 문단에 의도적 삽입 |
102
111
  | E-2 | 동일 종결어미 "~다" 4문장 연속 + 진행형 "~고 있다" 자동 매핑 | S2 | "~었다·~ㄴ다·~는다·~기 마련이다·~ㄹ 것이다" 등 다양화. "~고 있다" 단순 시제 환원 가능 시 환원("읽고 있다" → "읽는다") |
103
112
  | E-7 | 청자 경어법 4단계(해라/하게/하오/해요/합쇼) 일관성 손실 (대화·구어 한정) | S2 | 한 단락 내 혼용 금지, 격식 일관 (김혜영 2019, 추정) |
113
+ | E-8 | 관형형 + 의존명사 종결 — 서술어 없이 "짚을 것", "고려할 점", "주의 사항"으로 문장을 끊음 | S2 / **대화·리뷰 S1** | 서술어를 붙여 문장을 끝낸다("두 가지 짚을 것" → "짚어볼 게 있습니다"). 목차 항목처럼 끊으면 사람이 한 말로 안 읽힌다. **헤딩, 표 셀, 체크리스트 항목, 문단을 여는 볼드 도입구는 대상이 아니다** — 거기서는 명사구 종결이 정상 문법이다. **볼드 예외는 규범, 참조 문서에서 문단 안 소제목 역할을 하는 자리에만 준다** — 리뷰 코멘트와 대화에서는 볼드를 씌워도 본문 산문으로 본다. 서식으로만 예외를 주면 "두 가지 짚을 것"을 볼드 처리해 그대로 통과시키게 된다. 본문 산문과 대화만 본다. 예외가 전부 문맥이라 줄 단위 정규식으로는 못 가르고, 그래서 탐지기가 없다. G-4와 겹치면 서술어를 붙이되 판단이면 화자도 함께 남긴다 |
104
114
 
105
115
  ## F. 과도한 수식, 중복
106
116
 
@@ -119,6 +129,7 @@
119
129
  | G-1 | "~것이다/~할 것이다" 미래 단정 남발 | S2 | 현재형·확정형으로 |
120
130
  | G-2 | "~로 보인다/~인 듯하다" 추정 남발 | S2 | 단언 가능한 곳은 단언 |
121
131
  | G-3 | 안전 균형 표현 "양쪽 모두/두 가지 모두/장점도 있지만/신중하게/균형" | S2 | 4회 초과 시 1~2건 화자 입장으로 치환 |
132
+ | G-4 | 화자 소거 — 의견인데 "확인이 필요합니다"처럼 화자가 없어 사실 선언으로 읽힘 | S2 / **대화·리뷰 S1** | 누가 하는 말인지 살린다("확인이 필요합니다" → "제가 봤을 때는 확인이 필요합니다"). **G-2와 방향이 반대라 경계를 지킨다** — 사실 서술에 붙은 추정 어미("~로 보인다")는 G-2로 빼고 판단이나 제안에서 빠진 화자는 여기서 넣는다. **규범, 절차, 명세 문서의 지시문은 대상이 아니다** — 룰북과 스킬 문서는 화자 없이 규칙을 적는 게 표준이다. 화자가 개인 판단으로 말하는 자리(리뷰 코멘트, 대화, 제안)만 본다. **코드를 읽고 확인한 결함은 화자를 붙이지 않고 그대로 단정한다** — 화자는 판단과 제안에만 붙인다. 부재를 봐야 해서 탐지기가 없다 |
122
133
 
123
134
  ## H. 접속사 남발
124
135
 
@@ -136,9 +147,9 @@
136
147
  | I-2 | "X은 ~라는 점에 있다" | S2 | "X는 ~다" 직설로 |
137
148
  | I-3 | "~다는 뜻이다/~다는 의미다" 결말 | S2 | 본문에 풀어 쓰기 |
138
149
  | I-4 | 권고형 결말 "~해야 한다·~합니다" 반복 | S2 | 평서·단언으로 |
139
- | I-5 | 사무투 분류사 "~ 건/해당 건/이번 건/그 건", 코드·문서 용어를 대화에 그대로("주석 건") | S2 / **대화·리뷰 S1** | 구체 명사로 풀기("Copilot이 짚은 주석 건" → "Copilot이 남긴 코멘트"). "건"은 공문서투 분류사라 대화에서 어색하다 |
150
+ | I-5 | 사무투 분류사 "~ 건/해당 건/이번 건/그 건", 코드·문서 용어를 대화에 그대로("주석 건") | S2 / **대화·리뷰 S1** | 구체 명사로 풀기("Copilot이 짚은 주석 건" → "Copilot이 남긴 코멘트"). "건"은 공문서투 분류사라 대화에서 어색하다. **수량 자리는 사물 명사가 바로 앞에 붙은 꼴만 본다** — "버그 8건", "코멘트 9건", "티켓 8건"을 "8개", "9개"로 고친다. 세는 사물이 안 적힌 자리("확인이 필요한 게 2건 있습니다")는 **대상이 아니다** — 무엇을 세는지 문장에 없으면 판정할 근거도 없고, 명사를 지웠다 살렸다로 답이 뒤집히는 기준은 쓸 수 없다. **이 규칙은 산출물 문장에만 적용된다** — 룰 문서나 스킬 문서가 자기 데이터를 집계해 적는 자리("인라인 리뷰 1,321건", "표본 282건")는 대상이 아니다. I-7이 같은 예외를 갖는 것과 같은 이유다. **탐지기는 한글 한 글자 + 공백 + "건" + 조사(은/이/을/에/도) 꼴을 전부 건다** — 수량인지 사무투 분류사인지, 준말 "것은"인지 못 가르므로 걸린 자리는 사람이 위 기준으로 다시 본다. 아라비아 숫자 꼴("8건 고쳤어요")은 정규식이 안 닿아 사람만 본다 |
140
151
  | I-6 | 측량·사무투 명사 "실측·계측·산출·오탐" 등으로 판정·근거를 명사 하나로 압축 (피동 "산출된다"도 같다. 파생어 예외는 "산출"에만 있다 — "산출물", "산출 근거", "산출도구"는 빠지고 "계측기", "실측값"은 걸린다. 서술격 "산출이에요"와 관형격 "산출의"는 탐지기가 못 본다) | S2 / **대화·리뷰 S1** | 동사로 풀어 말하기("레포 실측으로 1444개 중" → "레포 뒤져보니 1444개 중", "이건 오탐이에요" → "이건 잘못 감지한 거예요"). "잘못 걸리다"처럼 안 붙는 동사로 도망가지 말고 원래 짝이 맞는 동사(감지하다·측정하다)에 "잘못"을 붙인다 |
141
- | I-7 | 리뷰 코멘트를 "지적"이라 부르기 ("지적 사항", "지적 N건", "지적했던 부분"처럼 뒤에 명사가 붙은 꼴도 같다. 코멘트가 아닌 일반 동사 용법 "원칙 위반을 지적하고", "논문이 지적한 점"은 예외. 탐지기가 어디까지 보고 어디서 새는지는 `src/humanize/detectors.ts` 의 I-7 주석과 코퍼스가 갖는다) | S2 / **대화·리뷰 S1** | 내가 남긴 건 "남겼던 의견"이나 "드렸던 의견", 상대가 남긴 건 "짚어주신 부분"이나 "남겨주신 의견"으로. "지적"은 상대를 잡아세우는 뉘앙스가 붙어 코멘트를 판정으로 만든다. 룰 원문은 [리뷰 코멘트를 "지적"이라고 부르지 않는다](author-voice.md#리뷰-코멘트를-지적이라고-부르지-않는다-ai-tell-i-7) 절이다 |
152
+ | I-7 | 리뷰 코멘트를 "지적"이라 부르기 ("지적 사항", "지적 N건", "지적했던 부분"처럼 뒤에 명사가 붙은 꼴도 같다. 코멘트가 아닌 일반 동사 용법 "원칙 위반을 지적하고", "논문이 지적한 점"은 예외. 탐지기가 어디까지 보고 어디서 놓치는지는 `src/humanize/detectors.ts` 의 I-7 주석과 코퍼스가 갖는다) | S2 / **대화·리뷰 S1** | 내가 남긴 건 "남겼던 의견"이나 "드렸던 의견", 상대가 남긴 건 "짚어주신 부분"이나 "남겨주신 의견"으로. "지적"은 상대를 잡아세우는 뉘앙스가 붙어 코멘트를 판정으로 만든다. 룰 원문은 [리뷰 코멘트를 "지적"이라고 부르지 않는다](author-voice.md#리뷰-코멘트를-지적이라고-부르지-않는다-ai-tell-i-7) 절이다 |
142
153
  | I-8 | 형식명사 "수준"으로 정도 뭉개기("다듬는 수준", "확인만 하는 수준") | S2 / **대화·리뷰 S1** | "정도"를 쓰거나 형식명사를 빼고 동사로 푼다("가볍게 손보면 되는 것들"). "수준이 낮다"의 등급 어감이 딸려와 채점처럼 읽히기 때문이다. 남의 코드를 두고 쓰면 특히 그렇다. 등급을 실제로 말하는 자리("높은 수준의 격리")는 대상이 아니다 |
143
154
 
144
155
  ## J. 시각 장식
@@ -159,11 +170,11 @@
159
170
  2. **변경률**: 30% 이하인가 (50% 초과는 작업 중단)
160
171
  3. **장르 이탈 없음**: 칼럼이 에세이나 문학으로 변하지 않았는가, 리포트가 블로그체로 떨어지지 않았는가
161
172
  4. **말투 보존**: 원문 격식체면 결과도 격식체. 평어체로 떨어뜨리지 않는다
162
- 5. **잔존 S1 패턴 0건**: A-1, A-3, A-7, A-8, A-16, B-3, B-5, C-5, C-8, C-10, C-11, C-12, D-1~D-6, D-8, H-1, H-3, J-2가 남아있지 않은가 (대화·리뷰 말투면 A-2, A-5, D-9, F-4, F-5, F-6, F-7, F-8, I-1, I-5, I-6, I-7, I-8도 S1로 포함)
173
+ 5. **잔존 S1 패턴 0건** (탐지기 수치는 각 룰의 대상 기준으로 걸러 센다 — 룰이 예외로 둔 자리는 잔존 건수에 안 넣는다): A-1, A-3, A-7, A-8, A-16, B-3, B-5, C-5, C-8, C-10, C-11, C-12, D-1~D-6, D-8, H-1, H-3, J-2가 남아있지 않은가 (대화·리뷰 말투면 A-2, A-5, C-14, D-9, E-8, F-4, F-5, F-6, F-7, F-8, G-4, I-1, I-5, I-6, I-7, I-8도 S1로 포함)
163
174
  6. **인공 표현 자제**: 원문에 없던 비유, 수사, 문학적 표현을 윤문 과정에서 임의로 추가하지 않았는가
164
175
  7. **삭제 처방 준수**: D-2, D-3, D-4, D-6, C-10을 재작성으로 처리하지 않았는가. 마무리 문장, 부제, 수식어를 지우는 대신 더 그럴듯한 것으로 갈아끼운 자리가 없는가
165
176
 
166
- 위반 시: edit 롤백 → 다시 윤문 → 재점검. 자체 루프 최대 1회. 이상 미해결이면 결과를 그대로 출력하되 `summary.md`에 "자가검증 미통과 항목 N" 표기.
177
+ 위반 시: edit 롤백 → 다시 윤문 → 재점검. 자체 루프 최대 1회. 이상 미해결이면 결과를 그대로 출력하되 `summary.md`에 "자가검증 미통과 항목 N" 표기.
167
178
 
168
179
  ## 코드 검사 (자가 채점보다 위)
169
180
 
@@ -193,10 +204,9 @@ AI 생성 산문 60편(모델 3종)과 2022년 이전 발행이 확인된 한국
193
204
  | I-1 "~한 것이다" | AI 20.4 vs 인간 43.0 (G²=6.2) — 인간이 2배 더 씀. 단락 말 위치·연속 반복도 AI가 더 적음 | S1 → S2(연속 3회+), 대화·리뷰만 S1 |
194
205
  | C-8 부정 대구 | AI 5.8 vs 인간 0.6 (9.2배, G²=41.7) — 개인 글 대비로는 18배. 모델 3종 공통 | S2 → S1 |
195
206
 
196
- 읽을 때 두 가지를 같이 봐야 한다. 인간 코퍼스가 **편집된 출판 산문**이라 "인간 일반"이 아니라
207
+ 읽을 때 같이 봐야 게 있다. 인간 코퍼스가 **편집된 출판 산문**이라 "인간 일반"이 아니라
197
208
  "잘 쓴 글"과의 대조다. 그리고 이 측정은 **문서 산문**을 잰 것이라 대화, 리뷰 코멘트에는 그대로
198
209
  적용되지 않는다 — A-2와 I-1이 대화에서 S1로 남는 이유가 이것이다.
199
- 출처: [`epoko77-ai/im-not-ai`](https://github.com/epoko77-ai/im-not-ai)의 `empirical-validation.md`.
200
210
 
201
211
  ### 팀 실제 사용 (B-4)
202
212
 
@@ -204,10 +214,10 @@ AI 생성 산문 60편(모델 3종)과 2022년 이전 발행이 확인된 한국
204
214
 
205
215
  | 룰 | 확인한 것 | 조정 |
206
216
  |---|---|---|
207
- | B-4 "소비처" | 팀 지라 티켓 3건에서 섹션 헤딩과 본문으로 일관되게 쓴다. 작성자 본인 어휘다 | 교정 예시에서 제외 |
217
+ | B-4 "소비처" | 팀 지라 티켓 3개에서 섹션 헤딩과 본문으로 일관되게 쓴다. 작성자 본인 어휘다 | 교정 예시에서 제외 |
208
218
 
209
219
  **교정어를 정하기 전에 팀이 실제로 뭐라고 쓰는지 먼저 본다.** 지라, PR, 슬랙을 검색하면 답이 있다.
210
- "인수조건"도 같은 방법으로 걷어냈다 — 팀 지라 전체에 5건뿐이고 그중 넷이 2025년 9월 한 묶음,
220
+ "인수조건"도 같은 방법으로 걷어냈다 — 팀 지라 전체에 5개뿐이고 그중 넷이 2025년 9월 한 묶음,
211
221
  나머지 하나는 이 에이전트가 직접 넣은 것이었다. 팀이 쓰는 말이 아니라 템플릿이 심은 말이었다.
212
222
 
213
223
  ## 등급 기준 (자가 채점)
@@ -217,4 +227,4 @@ AI 생성 산문 60편(모델 3종)과 2022년 이전 발행이 확인된 한국
217
227
  - **C**: S1 잔존 1~2 또는 자체검증 5항 이하 통과 — 사용자에게 strict 모드 권고
218
228
  - **D**: S1 잔존 3+ 또는 변경률 50% 초과 — 작업 중단 권고
219
229
 
220
- > v2.0 신규/보강은 A-7, A-15, A-16, A-18, A-19, E-2, E-7, F-4 **8 (A-17 보류)**. 학술 인용 전문은 `references/scholarship.md`. post-editese 3축 지표는 본 룰북 미반영(metric only 트랙). A-17 무정물, 추상명사 '-들'은 학술 근거(전영철 2007·곽은주·진실로 2011) 강하나 외부 회차(2026-05-07 위키 6편)에서 양성 0 — NMT 원본 출력 회차 후 v2.1에서 동일 ID로 재평가.
230
+ > v2.0 신규/보강은 A-7, A-15, A-16, A-18, A-19, E-2, E-7, F-4 **8 (A-17 보류)**. 학술 인용 전문은 `references/scholarship.md`. post-editese 3축 지표는 본 룰북 미반영(metric only 트랙). A-17 무정물, 추상명사 '-들'은 학술 근거(전영철 2007·곽은주·진실로 2011) 강하나 외부 회차(2026-05-07 위키 6편)에서 양성 0 — NMT 원본 출력 회차 후 v2.1에서 동일 ID로 재평가.
@@ -149,7 +149,7 @@ OO님 이거 타겟 브랜치를 변경해주셔야 할 것 같아요!
149
149
  주 참조 구간이고 협업 한마디는 말투 B를 빌린다. 반영은 커밋 링크 + 한 줄로 짧게, 이견은
150
150
  근거 하나 대고 상대에게 판단을 넘긴다. **리뷰이는 강제성을 매기는 자리가 아니라 `r:`/`c:`/`a:`
151
151
  접두어를 붙이지 않는다** — 접두어는 리뷰어 쪽 도구다. 과잉 사과와 장문 변명이 이 장르에서
152
- 가장 자주 새는 AI-tell이다.
152
+ 가장 자주 걸리는 AI-tell이다.
153
153
  - **PR 설명, 변경 컨텍스트(change-context-writer)**: 본문은 "무엇을 왜 바꿨는지"를 서술하는
154
154
  성격이라 제안형보다 **담백한 서술체**가 맞다. 단 "~한 것 같습니다"의 부드러움과 온기는 유지하고
155
155
  딱딱한 단언, 결산 피벗으로 평탄화하지 않는다. 협업 한마디(요청·배려)는 말투 B를 빌린다.
@@ -157,11 +157,11 @@ OO님 이거 타겟 브랜치를 변경해주셔야 할 것 같아요!
157
157
 
158
158
  ---
159
159
 
160
- ## 명사로 뭉치지 말고 풀어 말하기 (자주 새는 사각지대)
160
+ ## 명사로 뭉치지 말고 풀어 말하기 (자주 놓치는 사각지대)
161
161
 
162
162
  가장 티 나는 AI 흔적은 번역투나 헤징이 아니라 **개념을 명사 덩어리로 압축하는 습관**이다.
163
163
  사람은 대화, 리뷰 코멘트에서 "무엇을 왜 했는지"를 동사로 풀어 말하지, 명사구를 이어붙여 뭉치지 않는다.
164
- 아래 쌍은 실제 리뷰 코멘트에서 나온 교정 사례다. 패턴만 참고하고 문장은 복붙하지 않는다.
164
+ 아래 표는 실제 리뷰 코멘트에서 나온 교정 사례다. 패턴만 참고하고 문장은 복붙하지 않는다.
165
165
 
166
166
  | AI가 쓴 것 (before) | 사람이 쓸 것 (after) | 원인 |
167
167
  |---|---|---|
@@ -171,7 +171,26 @@ OO님 이거 타겟 브랜치를 변경해주셔야 할 것 같아요!
171
171
  | 규칙을 전 소비자에게 배선했습니다 | 규칙을 소비자 전부에 연결해뒀어요 | 기술 비유 명사 "배선"(F-7) |
172
172
  | 코멘트에서 지식을 증류해 반영했어요 | 코멘트에서 쓸 만한 걸 추려서 반영했어요 | 기술 비유 명사 "증류"(F-7) |
173
173
  | 강등 방향도 맞게 갔습니다 | 심각도 내린 것도 맞는 방향 같아요 | 한자어 명사 "강등"(→ 동사로) + 추상명사에 이동 동사 |
174
- | c: 여섯 건은 매끄럽게 다듬는 수준이고 | c: 여섯 개는 가볍게 손보면 되는 것들이에요 | 형식명사 "수준"으로 정도 뭉개기 + 세는 단위 ""(I-5) |
174
+ | c: 코멘트 여섯 건은 매끄럽게 다듬는 수준이고 | c: 코멘트 여섯 개는 가볍게 손보면 되는 것들이에요 | 형식명사 "수준"으로 정도 뭉개기 + 사물을 세니 ""(I-5) |
175
+ | 두 가지 짚을 것 | 제가 봤을 때는 확인이 필요한 게 2건 있습니다 | 수량 예고(C-14) + 명사구 종결(E-8) + 화자 소거(G-4) |
176
+
177
+ **문장을 명사구로 끝내지 말 것.** "두 가지 짚을 것", "확인할 것", "고려할 점"처럼 서술어 없이
178
+ 관형형과 의존명사로 끊으면 목차 항목처럼 읽힌다. 사람은 말할 때 문장을 명사구로 안 끝낸다.
179
+ "짚어볼 게 있습니다"처럼 서술어를 붙인다. 판단을 말하는 자리면 화자까지 남겨
180
+ "제가 봤을 때는 확인이 필요합니다"로 간다 — G-4와 겹치는 자리다. 헤딩이나 체크리스트 항목,
181
+ 규범 문서에서 소제목 역할을 하는 볼드 도입구는 명사구 종결이 정상 문법이라 대상이 아니다
182
+ (ai-tell E-8).
183
+
184
+ **개수를 앞세워 예고하지 말 것.** "두 가지 짚을 것", "세 가지 이유가 있습니다"처럼 할 말의 개수를
185
+ 먼저 세어 선언하고 시작하면 발표문이 된다. 사람은 말하다 보니 몇 개가 되는 것이지 미리 세지 않는다.
186
+ 개수를 뒤로 보내 결과로 붙인다 — "확인이 필요한 게 2건 있습니다". 다만 개수가 대상의 고정 속성일
187
+ 때는 그냥 사실이다. 게슈탈트 원리가 실제로 다섯 개라 "다섯 가지 원리"는 고칠 자리가 아니다
188
+ (ai-tell C-14).
189
+
190
+ **의견에는 화자를 남길 것.** "확인이 필요합니다"는 사실 선언처럼 읽히지만 실제로는 내 판단이다.
191
+ "제가 봤을 때는", "제 생각엔"을 붙여 누가 하는 말인지 밝힌다. 이 voice의 본질이 제안이지 판정이
192
+ 아니라서, 화자가 지워지면 같은 내용이라도 통보가 된다. 헤징을 걷어내라는 규칙과 방향이 반대라
193
+ 경계를 지킨다 — 사실 서술에 붙은 "~로 보인다"는 빼고 판단에서 빠진 화자는 넣는다 (ai-tell G-4).
175
194
 
176
195
  **"수준"으로 정도를 말하지 말 것.** "다듬는 수준", "확인만 하는 수준"처럼 쓰면 정도를 말하려던 게
177
196
  채점처럼 읽힌다 — "수준이 낮다"의 등급 어감이 딸려오기 때문이다. 남의 코드를 두고 쓰면 특히 그렇다.
@@ -215,17 +234,24 @@ OO님 이거 타겟 브랜치를 변경해주셔야 할 것 같아요!
215
234
 
216
235
  - 내가 남긴 것을 가리킬 때: **"남겼던 의견", "드렸던 의견", "남긴 코멘트"**
217
236
  - 상대가 남긴 것을 가리킬 때: **"짚어주신 부분", "남겨주신 의견"** — 받는 쪽에서도 같은 결로 간다
218
- - 셀 있게 말할 때는 "8"보다 **"8개"** "여덟 개" (사무투 분류사 회피, ai-tell I-5)
237
+ - 사물을 때는 **"개"** 쓴다. "코멘트 8", "버그 3개", "티켓 8개" (ai-tell I-5)
219
238
 
220
- > **"건"을 글자로 매칭하면 안 된다.** 같은 글자가 층위가 다르게 쓰인다.
239
+ > **"건"을 글자로 매칭하면 안 된다.** 같은 글자가 층위마다 다르게 쓰인다.
221
240
  >
222
241
  > | 고칠 것 | 그대로 둘 것 |
223
242
  > |---|---|
224
- > | "c: 여섯 **건**은 다듬는 정도예요" — 세는 단위 | "안 돌려본 **건** PR에 적어두셔서" — "것은"의 준말 |
225
- > | "지적해주신 **건**은 확인했습니다" — 사무투 분류사 | "제가 놓친 **건** 맞아요" — "것은"의 준말 |
243
+ > | "지적해주신 **건**은 확인했습니다" — 사무투 분류사 | "안 돌려본 **건** PR에 적어두셔서" — "것은"의 준말 |
244
+ > | "코멘트 여섯 **건**은 다듬는 정도예요" — 사물을 센다 | "제가 놓친 **건** 맞아요" — "것은"의 준말 |
245
+ > | "버그 8**건** 고쳤어요" — 사물을 센다 | "안 돌려본 **건** 확인했어요" — "것은"의 준말 |
226
246
  >
227
247
  > 준말 "건"은 구어에서 자연스러운 표현이라 늘려 쓰면("안 돌려본 것은") 오히려 딱딱해진다.
228
- > 규칙을 적용하기 전에 자리가 **수량을 세는 자리인지** 확인한다.
248
+ > 수량 자리는 **세는 사물이 바로 앞에 적혀 있을 때만** 본다. 적혀 있으면 "개"로 간다
249
+ > ("코멘트 여섯 개", "버그 8개"). 무엇을 세는지 문장에 없으면("확인이 필요한 게 2건 있습니다")
250
+ > 판정할 근거가 없으니 그대로 둔다.
251
+ >
252
+ > **이 표는 산출물 문장에만 적용된다.** 이 문서나 룰 문서가 자기 데이터를 세어 적는
253
+ > 자리("인라인 리뷰 1,321건", "표본 282건")는 대상이 아니다 — I-7이 같은 예외를 갖는 것과
254
+ > 같은 이유다.
229
255
 
230
256
  이 규칙은 산출물 문장에만 적용된다. 룰 문서나 스킬 문서가 개념을 설명할 때는 "리뷰 코멘트",
231
257
  "코멘트"라는 중립어를 쓴다 — 룰 문서가 금지 어휘를 본문에서 쓰면 산출물로 새기 때문이다.
@@ -69,7 +69,7 @@ key는 넣었는데 index 대신 id를 썼어요. 목록 순서가 바뀌는 케
69
69
  요건 이번 PR 범위를 넘어서는 것 같아서 별도 티켓으로 뺄까 싶은데 괜찮을까요?
70
70
  ```
71
71
 
72
- - 반드시 상대에게 판단을 넘기는 한 문장으로 닫는다 ("어떻게 생각하세요?", "괜찮을까요?").
72
+ - 반드시 상대에게 판단을 넘기는 한 문장을 마지막에 둔다 ("어떻게 생각하세요?", "괜찮을까요?").
73
73
  - 이견은 근거 하나만 대고 짧게 끝낸다. 방어적으로 길게 쓰면 톤이 세진다.
74
74
 
75
75
  ### 4. 질문 (clarify) — 코멘트 의도를 못 잡았다
@@ -101,7 +101,7 @@ key는 넣었는데 index 대신 id를 썼어요. 목록 순서가 바뀌는 케
101
101
 
102
102
  ### Humanize 처리
103
103
 
104
- 초안을 쓴 뒤 AI-tell을 점검한다. 기준은 [`../_shared/references/ai-tell-quick-rules.md`](../_shared/references/ai-tell-quick-rules.md)이고 답글엔 특히 아래가 자주 샌다.
104
+ 초안을 쓴 뒤 AI-tell을 점검한다. 기준은 [`../_shared/references/ai-tell-quick-rules.md`](../_shared/references/ai-tell-quick-rules.md)이고 답글엔 특히 아래가 자주 걸린다.
105
105
 
106
106
  | 패턴 | 예시 | 교정 |
107
107
  |------|------|------|
@@ -31,7 +31,7 @@ PR diff를 리뷰하고 머지 가능 여부를 판단할 수 있는 구체적
31
31
 
32
32
  ## Review Focus
33
33
 
34
- 변경 diff 리뷰할 때 세 가지 축으로 검토한다.
34
+ 변경 diff 아래 축으로 검토한다.
35
35
 
36
36
  1. **Bug** — 논리 오류, 경계값(off-by-one, empty/overflow) 처리 누락, null/undefined 역참조, 예외 미처리, race condition, 잘못된 조건 분기
37
37
  2. **Performance** — N+1 쿼리, 루프 내 불필요한 반복 연산, 중복 호출, 불필요한 메모리 할당, 캐시 미적용, 큰 객체 복사
@@ -100,6 +100,9 @@ voice 모델을 따른다. 초안 작성 후 반드시 [`../_shared/references/a
100
100
  | 음차(B-3) | "소스 오브 트루스", "룩 앤 필" 등 안 굳어진 음차 | 한글 의역 + 첫 등장만 원어 병기 |
101
101
  | 가운뎃점 나열(C-12) | "버그·성능·품질을 봅니다" | 쉼표나 구어로 풀기("버그, 성능, 품질") — 표·용어목록·합성어(입출력)는 예외 |
102
102
  | 측량·사무투 명사(I-6) | "레포 실측으로 1444개 중", "이건 오탐이에요" | 동사로 풀기("레포 뒤져보니 1444개 중", "이건 잘못 감지한 거예요") |
103
+ | 수량 예고(C-14) | "두 가지 짚을 것", "세 가지만 남길게요" | 개수를 뒤로 보내기("제가 봤을 때는 확인이 필요한 게 2건 있어요") — 개수가 대상의 고정 속성이면 그대로 |
104
+ | 명사구 종결(E-8) | "두 가지 짚을 것", "확인할 점" | 서술어를 붙여 끝내기("짚어볼 게 있어요") — 헤딩과 체크리스트는 예외 — 코멘트에서는 볼드를 씌워도 본문으로 본다 |
105
+ | 화자 소거(G-4) | "확인이 필요합니다" | 누구 판단인지 밝히기("제가 봤을 때는 확인이 필요해요") — 코드를 읽고 확인한 결함은 그대로 단정한다 |
103
106
 
104
107
  **근거를 제시하는 자리의 어휘.** 수치를 들이밀 때 "실측", "계측", "산출", "오탐" 같은 측량투
105
108
  명사를 쓰지 않는다 — 일상 대화에서 안 쓰는 말이라 그 자리만 문서 톤으로 튄다.
@@ -171,11 +174,11 @@ voice 모델을 따른다. 초안 작성 후 반드시 [`../_shared/references/a
171
174
  같은 리듬으로 나온 사례가 있다.
172
175
 
173
176
  - 한 코멘트에 "~것 같" 계열은 **1회까지**. 문제 진술과 제안에 각각 붙여 두 번 쓰지 않는다.
174
- - 리뷰 한 건에서 "~것 같"으로 닫는 코멘트는 **절반 이하**. 나머지는 "~는 건 어떨까요?",
177
+ - 리뷰 한 번에서 "~것 같"으로 끝내는 코멘트는 **절반 이하**. 나머지는 "~는 건 어떨까요?",
175
178
  "좋아보입니다", "~네요", 단정형으로 흩는다.
176
179
  - **코드를 읽고 확인한 결함은 단정한다.** 전부 헤지하면 확신도 신호가 사라져서 리뷰이가
177
180
  "이건 확실한 버그, 저건 그냥 의심"을 구분하지 못한다.
178
- - 확신이 없으면 헤지를 겹치지 말고 **질문으로 닫는다**("이 경로도 타나요?").
181
+ - 확신이 없으면 헤지를 겹치지 말고 **질문으로 끝낸다**("이 경로도 타나요?").
179
182
 
180
183
  | 헤지 몰림 | 이렇게 |
181
184
  |-----------|--------|
@@ -239,7 +242,7 @@ GitHub 마크다운은 **한 줄 개행(`\n`)을 무시하고 같은 문단으
239
242
  내놓기 전에 아래를 센다. 걸리면 초안을 그대로 내지 말고 고쳐서 낸다.
240
243
 
241
244
  1. "~것 같" 계열이 **한 코멘트에 2회 이상**인 곳 → 1회로 줄인다
242
- 2. "~것 같"으로 닫는 코멘트가 **전체의 절반을 넘는지** → 다른 종결로 분산한다
245
+ 2. "~것 같"으로 끝내는 코멘트가 **전체의 절반을 넘는지** → 다른 종결로 분산한다
243
246
  3. 코드로 확인한 결함을 헤지로 진술한 곳 → 단정으로 바꾼다
244
247
  4. 모든 코멘트가 **같은 3단 구조에 같은 분량**인지 → 사소한 건 한 줄로 줄인다
245
248
  5. 사소한 코멘트가 섞여 있는데 `a:`가 하나도 없는지 → severity를 다시 매긴다
@@ -90,7 +90,7 @@ gestalt humanize-scan --file <원문> --register <doc|chat|report>
90
90
  - **탐지기가 못 가리는 S1**: ID 목록만 나온다. 이건 직접 읽어서 판단한다
91
91
  - **그 밖의 룰**: 이번 텍스트에서 안 걸렸다. 찾아 나서지 않는다
92
92
 
93
- 룰북은 59개까지 자랐다. 매번 전부 펼치면 실제로 걸린 서너 개가 안 걸린 개에 묻힌다.
93
+ 룰북은 예순 개가 넘는다. 매번 전부 펼치면 실제로 걸린 서너 개가 안 걸린 나머지에 묻힌다.
94
94
  스캔은 이번에 볼 목록을 좁히는 장치다. 목록 밖의 룰을 굳이 뒤지면 그 자리에서 과윤문이 시작된다.
95
95
 
96
96
  **S1 0건이면 윤문하지 않는다.** 탐지기가 가리는 범위에서 걸리는 게 없고 직접 확인할 룰도
@@ -108,7 +108,7 @@ You are the Jira Writer role agent.
108
108
 
109
109
  ### 4단계 — AI-tell 제거 + 말투 통일
110
110
 
111
- 본문을 다 쓴 뒤 `ai-tell-quick-rules.md`의 S1 패턴을 기준으로 훑어 걷어낸다. 티켓 맥락에서 특히 자주 새는 것:
111
+ 본문을 다 쓴 뒤 `ai-tell-quick-rules.md`의 S1 패턴을 기준으로 훑어 걷어낸다. 티켓 맥락에서 특히 자주 걸리는 것:
112
112
 
113
113
  | 제거할 패턴 | 룰북 ID | 교정 |
114
114
  |-------------|---------|------|
@@ -128,7 +128,7 @@ Before/After나 대안을 나란히 놓아 차이를 보게 한다.
128
128
 
129
129
  ## 9. 마무리 (closing)
130
130
 
131
- 발표를 다음 행동으로 닫는다. 보고가 아니라 요청으로 끝낸다.
131
+ 발표의 마지막은 다음 행동이다. 보고가 아니라 요청으로 끝낸다.
132
132
 
133
133
  ```
134
134
  - 마무리 메시지: [청중이 가져갈 마지막 한 문장]
@@ -146,7 +146,7 @@ GESTALT_ACTOR=agent:reviewer gestalt pr edit <id> --title "고친 제목"
146
146
 
147
147
  `edit`은 `update`와 다르다. head를 안 옮기고 리뷰 판정도 라운드도 안 건드린다. 본문 오타를 고쳤다고 리뷰어가 내린 `request_changes`가 풀리면 안 되기 때문이다. 안 준 항목은 그대로 두고 빈 파일을 주면 본문을 비운다.
148
148
 
149
- ## 5단계: 머지와 닫기
149
+ ## 5단계: 머지와 종료
150
150
 
151
151
  ```bash
152
152
  gestalt pr merge <id>
@@ -162,7 +162,7 @@ gestalt pr update <id> --head "$(git rev-parse HEAD)"
162
162
  gestalt pr merge <id>
163
163
  ```
164
164
 
165
- 닫힌 PR도 head ref를 그대로 붙잡는다. 나중에 `pr diff`와 `pr checkout`이 동작한다.
165
+ 종료된 PR도 head ref를 그대로 붙잡는다. 나중에 `pr diff`와 `pr checkout`이 동작한다.
166
166
 
167
167
  ## 6단계: ref 정리
168
168
 
@@ -177,8 +177,8 @@ gestalt pr prune --checkouts # 체크아웃 자국까지
177
177
  기준은 하나다. **놓아도 커밋이 안 사라지는가.**
178
178
 
179
179
  - 머지된 PR의 base와 head를 놓는다. 놓기 전에 head가 정말 base 이력에 있는지 확인한다. 아니면 안 놓고 이유를 돌려준다.
180
- - 닫힌 PR은 아무것도 안 놓는다.
181
- - 체크아웃 자국은 기본으로 안 놓는다. 어느 이력에도 없는 커밋이라 놓으면 영영 사라진다. `--checkouts`로 뜻을 밝혀야 하고 그 PR이 이미 머지되거나 닫혔을 때만 놓는다.
180
+ - 종료된 PR은 아무것도 안 놓는다.
181
+ - 체크아웃 자국은 기본으로 안 놓는다. 어느 이력에도 없는 커밋이라 놓으면 영영 사라진다. `--checkouts`로 뜻을 밝혀야 하고 그 PR이 이미 머지되거나 종료됐을 때만 놓는다.
182
182
 
183
183
  `prune`은 CLI에만 있다. 되돌릴 수 없게 놓는 자리라 MCP 도구로는 안 뒀다.
184
184
 
@@ -197,6 +197,6 @@ gestalt pr prune --checkouts # 체크아웃 자국까지
197
197
  | --- | --- |
198
198
  | `prId` | PR id (8자 16진수) |
199
199
  | `prStatus` | `open`, `merged`, `closed` |
200
- | `unresolvedCount` | 안 닫힌 스레드 수 |
200
+ | `unresolvedCount` | 안 끝난 스레드 수 |
201
201
 
202
202
  로컬 PR에는 URL이 없다. `prUrl`을 안 돌려준다.
@@ -123,7 +123,7 @@ id를 직접 주면 아래 1번의 첫 수단이 브랜치를 안 따지고 잡
123
123
  2. **GitHub 지정** — `target`이 PR 번호나 GitHub URL이면 → `github`입니다. 사용자가 원격을 짚었으므로 아래 3번을 건너뜁니다.
124
124
  3. **안 끝난 로컬 PR** — 현재 브랜치에 안 끝난 로컬 PR이 있으면 → `local`입니다. 1번이 이미 조회했으면 그 결과를 그대로 씁니다. 1번을 안 거쳤으면 여기서 처음 조회합니다.
125
125
 
126
- 로컬 PR이 안 끝났다는 건 그 코드가 아직 안 정해졌다는 뜻입니다. 그 상태로 원격에 리뷰를 게시하면 두 자리에 서로 다른 판정이 남습니다. 로컬을 먼저 닫고 원격을 봅니다.
126
+ 로컬 PR이 안 끝났다는 건 그 코드가 아직 안 정해졌다는 뜻입니다. 그 상태로 원격에 리뷰를 게시하면 두 자리에 서로 다른 판정이 남습니다. 로컬을 먼저 종료하고 원격을 봅니다.
127
127
 
128
128
  이 갈래로 왔으면 사용자에게 한 줄 알립니다: "현재 브랜치에 안 끝난 로컬 PR {id}가 있어서 그쪽을 먼저 봐요. 원격이면 PR 번호나 URL을 주세요."
129
129
  4. `gh auth status`가 실패하거나(인증 안 됨) `git remote -v`가 비어 있으면(원격 없음) → GitHub 경로가 막혀 있습니다. → `none`입니다.
@@ -30,7 +30,7 @@ inputs:
30
30
  resolveThreads:
31
31
  type: boolean
32
32
  required: false
33
- description: "답글 게시 후 스레드를 resolved로 닫을지 여부. 기본값 false — 리뷰어가 닫는 게 원칙"
33
+ description: "답글 게시 후 스레드를 resolved로 종료할지 여부. 기본값 false — 리뷰어가 종료하는 게 원칙"
34
34
  outputs:
35
35
  - openThreads
36
36
  - responsePlan
@@ -123,7 +123,7 @@ id를 직접 주면 아래 1번의 첫 수단이 브랜치를 안 따지고 잡
123
123
  2. **GitHub 지정** — `target`이 PR 번호나 GitHub URL이면 → `github`. 사용자가 원격을 짚었으므로 아래 3번을 건너뛴다.
124
124
  3. **안 끝난 로컬 PR** — 현재 브랜치에 안 끝난 로컬 PR이 있으면 → `local`. 1번이 이미 조회했으면 그 결과를 그대로 쓴다. 1번을 안 거쳤으면 여기서 처음 조회한다.
125
125
 
126
- 로컬 PR이 안 끝났다는 건 그 코드가 아직 안 정해졌다는 뜻이다. 그 상태로 원격에 답을 달면 두 자리에 서로 다른 결론이 남는다. 로컬을 먼저 닫고 원격을 본다.
126
+ 로컬 PR이 안 끝났다는 건 그 코드가 아직 안 정해졌다는 뜻이다. 그 상태로 원격에 답을 달면 두 자리에 서로 다른 결론이 남는다. 로컬을 먼저 종료하고 원격을 본다.
127
127
 
128
128
  이 갈래로 왔으면 사용자에게 한 줄 알린다: "현재 브랜치에 안 끝난 로컬 PR {id}가 있어서 그쪽을 먼저 봐요. 원격이면 PR 번호나 URL을 주세요."
129
129
  4. `gh auth status`가 실패하거나(인증 안 됨) 원격이 없으면(`git remote -v` 비어 있음) → GitHub 경로가 막혀 있다. → `none`. **여기서 멈춘다.**
@@ -176,14 +176,14 @@ pnpm tsx bin/gestalt.ts pr --json show <판별에서 잡은 id>
176
176
  작성자는 `author` 필드다. 현재 사용자는 `gestalt pr` 명령이 쓰는 값과 같다 — 규칙은 `src/local-pr/policy.ts`의 `resolveActor`에 있다. 여기 옮겨 적으면 기본값을 바꿀 때 이 문장이 조용히 거짓이 된다.
177
177
 
178
178
  - `target`이 생략되면 현재 브랜치의 PR을 찾는다. PR이 없으면 여기서 멈추고 알린다 — 답할 코멘트가 있을 곳이 없다.
179
- - `state`가 `MERGED`/`CLOSED`(local은 `merged`/`closed`)면 사용자에게 한 줄 확인한다 ("이미 닫힌 PR인데 답글만 남길까요?").
179
+ - `state`가 `MERGED`/`CLOSED`(local은 `merged`/`closed`)면 사용자에게 한 줄 확인한다 ("이미 종료된 PR인데 답글만 남길까요?").
180
180
  - **작성자 확인**: 작성자가 현재 사용자와 다르면 이건 남의 PR이다. "이 PR은 제 것이 아닌데, 리뷰어 입장 코멘트를 다는 거라면 `/review`가 맞아요"라고 안내하고 사용자 판단을 받는다. 남의 PR에 리뷰이 어투로 답하면 어색해진다. (github·local 공통 규칙)
181
181
 
182
182
  ### 1단계: 미해결 리뷰 스레드 수집
183
183
 
184
184
  **github**:
185
185
 
186
- REST(`pulls/{n}/comments`)는 resolved 여부를 주지 않으므로 **GraphQL로 조회**한다. 이미 닫힌 스레드에 답글을 다시 붙이지 않으려면 이 단계가 필요하다.
186
+ REST(`pulls/{n}/comments`)는 resolved 여부를 주지 않으므로 **GraphQL로 조회**한다. 이미 끝난 스레드에 답글을 다시 붙이지 않으려면 이 단계가 필요하다.
187
187
 
188
188
  ```bash
189
189
  gh api graphql --paginate \
@@ -211,7 +211,7 @@ query($owner:String!, $repo:String!, $number:Int!, $endCursor:String) {
211
211
  }'
212
212
  ```
213
213
 
214
- **`comments`는 `first`가 아니라 `last`다.** 아래 필터가 스레드의 *마지막* 코멘트 작성자를 보는데 `first`는 가장 오래된 것부터 준다. 왕복이 상한을 넘은 스레드에서 중간 코멘트를 마지막으로 착각하면 판정이 양쪽으로 뒤집힌다 — 리뷰어가 기다리는 질문을 닫힌 걸로 보고 건너뛰거나, 이미 답한 스레드에 또 답글을 단다.
214
+ **`comments`는 `first`가 아니라 `last`다.** 아래 필터가 스레드의 *마지막* 코멘트 작성자를 보는데 `first`는 가장 오래된 것부터 준다. 왕복이 상한을 넘은 스레드에서 중간 코멘트를 마지막으로 착각하면 판정이 양쪽으로 뒤집힌다 — 리뷰어가 기다리는 질문을 끝난 걸로 보고 건너뛰거나, 이미 답한 스레드에 또 답글을 단다.
215
215
 
216
216
  **스레드는 `--paginate`로 전부 받는다.** AI 리뷰어가 붙으면 라인마다 스레드가 생겨 한 PR에 100개를 넘기는 일이 흔하다. 커서를 안 돌리면 101번째부터 조용히 사라지고 그 리뷰어들은 답을 못 받는다. 잘렸다는 사실조차 안 보이는 게 이 실패의 고약한 점이다.
217
217
 
@@ -219,7 +219,7 @@ query($owner:String!, $repo:String!, $number:Int!, $endCursor:String) {
219
219
 
220
220
  수집한 스레드를 아래 기준으로 걸러 `openThreads`를 만든다.
221
221
 
222
- - `isResolved: true` → 제외 (이미 닫힘)
222
+ - `isResolved: true` → 제외 (이미 종료됨)
223
223
  - 스레드의 **마지막 코멘트 작성자가 나 자신** → 제외 (내가 이미 답했고 리뷰어가 아직 안 받았다)
224
224
  - 작성자가 나 자신인 단독 스레드 → 제외 (내가 남긴 셀프 메모)
225
225
  - `isOutdated: true` → **제외하지 않고 표시만 한다.** 라인은 밀렸어도 코멘트는 유효할 수 있다. 다만 답글에 "이후 커밋에서 해당 부분이 바뀌었다"는 사실을 반영한다.
@@ -430,9 +430,9 @@ PR 전반 코멘트(원 코멘트의 `line`이 `null`)에 답할 때도 `--path`
430
430
  - 건마다 개별 호출이다. `/review`처럼 한 리뷰로 묶는 API가 아니다. 중간에 실패하면 어디까지 게시됐는지 사용자에게 알린다 — 부분 실패를 성공으로 보고하지 않는다.
431
431
  - **리뷰 상태(`APPROVE`/`REQUEST_CHANGES`)는 건드리지 않는다.** 리뷰이가 자기 PR의 리뷰 상태를 바꿀 일이 없다. github는 이 원칙을 422로도 강제한다. local(`gestalt pr review`)은 강제하지 않지만 규칙은 동일하게 지킨다.
432
432
 
433
- ### 7단계: 스레드 닫기 (opt-in, 기본 안 함)
433
+ ### 7단계: 스레드 종료 (opt-in, 기본 안 함)
434
434
 
435
- `resolveThreads`가 명시적으로 `true`거나 사용자가 요청할 때만 한다. **기본값은 닫지 않는 것이다** — 코멘트가 해결됐는지 판단하는 건 리뷰어 몫이고 리뷰이가 먼저 닫으면 확인 없이 넘어간 것처럼 보인다.
435
+ `resolveThreads`가 명시적으로 `true`거나 사용자가 요청할 때만 한다. **기본값은 종료하지 않는 것이다** — 코멘트가 해결됐는지 판단하는 건 리뷰어 몫이고 리뷰이가 먼저 종료하면 확인 없이 넘어간 것처럼 보인다.
436
436
 
437
437
  **github**:
438
438
 
@@ -449,7 +449,7 @@ mutation($threadId:ID!) {
449
449
  pnpm tsx bin/gestalt.ts pr resolve <id> <commentId>
450
450
  ```
451
451
 
452
- 닫더라도 `accept`·`alternate`만 닫는다. `defer`·`clarify`는 대화가 남아 있으므로 열어둔다. (github·local 공통)
452
+ 종료하더라도 `accept`·`alternate`만 종료한다. `defer`·`clarify`는 대화가 남아 있으므로 열어둔다. (github·local 공통)
453
453
 
454
454
  ## 결과 표시
455
455
 
@@ -52,7 +52,7 @@ outputs:
52
52
 
53
53
  | 단계 | 부르는 스킬 |
54
54
  | --- | --- |
55
- | 로컬 PR 만들기, head 옮기기, 닫기 | `local-pr` |
55
+ | 로컬 PR 만들기, head 옮기기, 종료 | `local-pr` |
56
56
  | 리뷰와 인라인 코멘트 게시 | `review` |
57
57
  | 받은 코멘트 대응과 답글 | `review-reply` |
58
58
  | PR description 짓기 | `pr` (0~4.5단계) |
@@ -173,10 +173,10 @@ Phase 1은 이 브랜치를 처음 다루는 자리라 재사용할 게 없다.
173
173
  3. <이슈 번호가 있으면 그것, 없으면 "없음">
174
174
  ```
175
175
 
176
- **Phase 3에서는 `pr` 스킬이 그보다 먼저 하나를 더 묻는다.** 그 스킬은 안 끝난 로컬 PR이 있으면 "로컬 먼저 처리할까요"라고 묻는데, 이 스킬의 로컬 PR은 Phase 5까지 열려 있는 게 정상이라 그 물음에 매번 걸린다. 첫 선택지가 루프를 `local-pr`로 되돌리므로 **그냥 두면 여기서 샌다.** 부를 때 미리 답한다.
176
+ **Phase 3에서는 `pr` 스킬이 그보다 먼저 하나를 더 묻는다.** 그 스킬은 안 끝난 로컬 PR이 있으면 "로컬 먼저 처리할까요"라고 묻는데, 이 스킬의 로컬 PR은 Phase 5까지 열려 있는 게 정상이라 그 물음에 매번 걸린다. 첫 선택지가 루프를 `local-pr`로 되돌리므로 **그냥 두면 여기서 빠져나간다.** 부를 때 미리 답한다.
177
177
 
178
178
  ```
179
- 이 로컬 PR <localPrId>은 ship이 Phase 5에서 닫습니다. 그냥 올립니다.
179
+ 이 로컬 PR <localPrId>은 ship이 Phase 5에서 종료합니다. 그냥 올립니다.
180
180
  ```
181
181
 
182
182
  Phase 3은 Phase 1에서 지은 목적을 그대로 쓰고 그 뒤 라운드에서 바뀐 것만 더한다.
@@ -413,8 +413,8 @@ verdict.overallApproved === true AND 답글이 안 달린 열린 스레드 0
413
413
 
414
414
  **`gestalt pr list`의 미해결 수를 그대로 종료 조건에 쓰지 않는다.** 그 수가 0이 되는 일은 이 루프에서 일어나지 않는다. 이유가 둘이다.
415
415
 
416
- 1. 스레드를 닫는 `review-reply`는 `resolveThreads` 기본값이 `false`다. 리뷰어가 닫는 게 원칙이라 그렇게 정해져 있다.
417
- 2. `resolveThreads: true`를 넘겨도 **`accept`와 `alternate`만 닫는다.** `defer`와 `clarify`는 대화가 안 끝났다고 보고 열어둔다.
416
+ 1. 스레드를 종료하는 `review-reply`는 `resolveThreads` 기본값이 `false`다. 리뷰어가 종료하는 게 원칙이라 그렇게 정해져 있다.
417
+ 2. `resolveThreads: true`를 넘겨도 **`accept`와 `alternate`만 종료한다.** `defer`와 `clarify`는 대화가 안 끝났다고 보고 열어둔다.
418
418
 
419
419
  **스레드 유형으로도 판정하지 않는다.** `accept`·`alternate`·`defer`·`clarify`는 `review-reply`가 도는 동안에만 있는 분류다. 로컬 PR은 그 값을 저장하지 않는다 — `Comment`에는 `threadId`와 `author`와 `resolved`만 있다. CLI에 없는 값을 조건에 쓰면 판정할 방법이 없다.
420
420
 
@@ -424,12 +424,12 @@ verdict.overallApproved === true AND 답글이 안 달린 열린 스레드 0
424
424
  gestalt pr --json show <id>
425
425
  ```
426
426
 
427
- `comments`를 `threadId`로 묶는다. 안 닫힌 스레드마다 **뿌리 말고 다른 코멘트가 있는지** 본다.
427
+ `comments`를 `threadId`로 묶는다. 안 끝난 스레드마다 **뿌리 말고 다른 코멘트가 있는지** 본다.
428
428
 
429
429
  - 답글이 있으면 처리된 스레드다. `defer`나 `clarify`로 답만 남긴 자리가 여기 온다
430
430
  - 답글이 없으면 안 끝난 것이다. 다음 라운드로 간다
431
431
 
432
- 2.3에서 `resolveThreads: true`를 넘기므로 `accept`와 `alternate`는 아예 닫혀서 목록에서 빠진다. 남는 건 답글만 달린 스레드뿐이다. 그게 이 루프가 도달할 수 있는 종점이다.
432
+ 2.3에서 `resolveThreads: true`를 넘기므로 `accept`와 `alternate`는 아예 종료돼 목록에서 빠진다. 남는 건 답글만 달린 스레드뿐이다. 그게 이 루프가 도달할 수 있는 종점이다.
433
433
 
434
434
  **이 조회는 종료를 판정하는 데만 쓴다.** 2.3의 `review-reply`는 이 목록을 못 받는다 — 그 스킬의 입력은 `target`과 `repoRoot`와 `local`과 `resolveThreads` 넷뿐이고 1단계에서 자기가 다시 모은다. 그래서 라운드마다 같은 PR을 두 번 조회한다. 없애려면 `review-reply`에 스레드 목록을 받는 입력을 새로 만들어야 하고 그건 이 스킬의 범위 밖이다. 로컬 PR 조회는 SQLite 한 번이라 그대로 둔다.
435
435
 
@@ -701,19 +701,19 @@ Copilot 리뷰 수렴 ({N}라운드)
701
701
 
702
702
  ## Phase 5 — 마무리
703
703
 
704
- **ⓒ에서 "바꾼다"를 고른 경우에만 ready로 옮긴다.** "draft로 둔다"면 이 줄을 건너뛰고 `prState`를 `draft`로 둔다. 아래 로컬 PR 닫기와 상태 정리는 어느 갈래든 그대로 한다.
704
+ **ⓒ에서 "바꾼다"를 고른 경우에만 ready로 옮긴다.** "draft로 둔다"면 이 줄을 건너뛰고 `prState`를 `draft`로 둔다. 아래 로컬 PR 종료와 상태 정리는 어느 갈래든 그대로 한다.
705
705
 
706
706
  ```bash
707
707
  gh pr ready <prNumber>
708
708
  ```
709
709
 
710
- 로컬 PR을 닫는다. **머지하지 않는다** — 실제 머지는 GitHub PR이 하고 로컬 PR은 리뷰 이력을 남기는 자리다.
710
+ 로컬 PR을 종료한다. **머지하지 않는다** — 실제 머지는 GitHub PR이 하고 로컬 PR은 리뷰 이력을 남기는 자리다.
711
711
 
712
712
  ```bash
713
713
  gestalt pr close <localPrId> --reason "GitHub #<prNumber>로 이어감"
714
714
  ```
715
715
 
716
- 닫힌 로컬 PR도 head ref를 붙잡으므로 나중에 `pr diff`와 `pr checkout`이 그대로 된다.
716
+ 종료된 로컬 PR도 head ref를 붙잡으므로 나중에 `pr diff`와 `pr checkout`이 그대로 된다.
717
717
 
718
718
  라운드 상태를 지운다. 검증 로그는 두고 갈 이유가 없다.
719
719