@tienne/gestalt 0.72.0 → 0.72.1

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.
package/CLAUDE.md CHANGED
@@ -108,7 +108,7 @@ plugin/.mcp.json Grok MCP (plugin/mcp.json과 동일)
108
108
  ```
109
109
 
110
110
  - Codex는 마켓플레이스 매니페스트를 `.agents/plugins/marketplace.json`에서만 찾는다. `.codex-plugin/marketplace.json`은 인식하지 않는다.
111
- - Grok은 `.grok-plugin/marketplace.json`이 정본이다. source는 반드시 `./plugin`이다. Claude 매니페스트(`source: "./"`)를 바꾸지 말 것.
111
+ - Grok은 `.grok-plugin/marketplace.json`만 읽는다. 마켓플레이스를 고칠 일이 있으면 여기를 고친다. source는 반드시 `./plugin`이다. Claude 매니페스트(`source: "./"`)를 바꾸지 말 것.
112
112
  - Grok은 `plugin/.mcp.json`(점 파일)을 읽는다. `plugin/mcp.json`과 내용을 같게 유지한다.
113
113
  - Codex는 `path`가 가리킨 디렉토리를 통째로 복사한다. 레포 루트를 가리키면 `.git`과 `node_modules`까지 딸려가 1.6GB가 되므로 반드시 `plugin/`으로 좁힌다.
114
114
  - Codex는 심링크를 따라가지 않는다. 자산은 실물 파일로 `plugin/` 안에 있어야 한다.
package/README.ko.md CHANGED
@@ -246,7 +246,7 @@ Codex는 호스트 패스스루로 동작해요 — Gestalt가 프롬프트와
246
246
 
247
247
  ### 옵션 6: Grok Build 플러그인
248
248
 
249
- Grok Build TUI/CLI용으로 MCP 서버랑 워크플로 스킬을 한 번에 받아요. 마켓플레이스는 `.grok-plugin/marketplace.json`이 정본이에요. Claude 마켓플레이스는 레포 루트를 복사하니 여기서 쓰지 마세요.
249
+ Grok Build TUI/CLI용으로 MCP 서버랑 워크플로 스킬을 한 번에 받아요. Grok은 `.grok-plugin/marketplace.json`을 읽어요. Claude 마켓플레이스는 레포 루트를 복사하니 여기서 쓰지 마세요.
250
250
 
251
251
  ```bash
252
252
  grok plugin marketplace add tienne/gestalt
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tienne/gestalt",
3
- "version": "0.72.0",
3
+ "version": "0.72.1",
4
4
  "description": "TypeScript AI Development Harness - Gestalt psychology-driven requirement clarification",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -72,7 +72,6 @@
72
72
  |---|---|
73
73
  | 규칙·정의가 적힌 문서 | 기준 문서 |
74
74
  | 비교 대상이 되는 수치 | 기준값 (목표 대비, 전기 대비 등 — impact-writer 용법) |
75
- | 여러 사본 중 원본 하나 | 정본 |
76
75
  | 조회·대조용 참조 자료 | 참조 기준 |
77
76
  | 데이터가 처음 만들어지는 곳 | 원천 데이터 |
78
77
  | 값을 담고 있는 데이터 자체 | 기준 데이터 |
@@ -85,6 +84,8 @@
85
84
  "룰북과 에이전트 문서가 갈라졌는지 본다"가 "룰북 기준 문서와…"보다 낫다.
86
85
  명사를 고르기 전에 동사로 풀 수 있는지 먼저 본다 — "A가 기준이다", "A를 기준으로 삼는다".
87
86
 
87
+ **여러 사본 중 원본 하나를 가리킬 때가 특히 그렇다.** 이 자리에 명사를 붙이면 뭉개진다. "이 파일만 읽는다", "고칠 일이 있으면 여기를 고친다", "표와 본문이 어긋나 보이면 본문을 따른다"처럼 적는다.
88
+
88
89
  ### 음차를 옮길 때 — 한 단어로 정하지 않는다
89
90
 
90
91
  같은 영어 단어라도 가리키는 게 다르면 다른 말이 된다. 대체어 하나를 정해놓고 전부 치환하면
@@ -98,6 +99,23 @@
98
99
  | layer | 동시에 처리되는 한 덩어리 | 묶음 |
99
100
  | layer | 순서대로 밟는 구간 | 단계 |
100
101
  | layer | 책임이 갈리는 구분 | 역할 |
102
+ | surface | 에이전트나 사람이 접근하는 창구 | 그 이름을 부른다 (CLI, MCP, 웹) |
103
+ | surface | 그 셋을 아울러야 할 때 | 호출하는 쪽 |
104
+ | surface | 이름 붙이기 애매한 접근 지점 | 자리 |
105
+ | surface | 값이 찍히는 화면 | 화면 |
106
+ | surface | 사용자에게 나가는 응답 | 사용자에게 보이는 / 나가는 |
107
+ | surface | 노출 영역 전체를 개념으로 부를 때 | 사용자 노출 |
108
+ | surface | 탐지기가 걸리는 넓이 | 걸리는 범위 |
109
+ | deep | 게슈탈트 용어를 써도 되는 곳 | 게슈탈트 내부 |
110
+ | deep | LLM 지시 프롬프트를 가리킬 때 | LLM에게만 가는 프롬프트 |
111
+
112
+ **이 표는 한국어 산문에서 음차로 쓴 자리만 다룬다.** 세 가지는 대상이 아니다.
113
+
114
+ - **코드 식별자.** `sanitizeSurfaceContext`, `DEEP_PROMPT_KEYS`, `gateway`는 그대로 둔다. 심볼을 바꾸면 호출부가 전부 딸려 온다.
115
+ - **그 도메인의 정착 용어.** 디자인 시스템의 `surface`와 `onSurface`(Material Design 색 토큰), CI의 gate, API gateway가 그렇다. **이 파일은 플러그인으로 배포돼 다른 레포에서도 읽히므로** 프론트엔드 레포에서 색 토큰을 "표면"으로 옮기라는 말이 되지 않게 조심한다.
116
+ - **이미 나간 CHANGELOG와 릴리즈 노트.** 그때 낸 문장이 아니게 된다.
117
+
118
+ **대비쌍은 짝을 함께 옮긴다.** `surface`와 `deep`처럼 둘이 맞물려 뜻을 이루는 말은 한쪽만 풀면 남은 쪽이 무엇의 반대인지 가리킬 데를 잃는다. 실제로 "표면"만 걷었다가 "심층"이 짝 없이 남아 한 문단 안에서 이름이 둘로 갈렸다.
101
119
 
102
120
  **일괄 치환은 조사를 깨뜨린다.** 받침 유무가 바뀌면 뒤따르는 조사도 바뀐다.
103
121
  `레이어라면` → `계층이라면`, `레이어(…)는` → `계층(…)은`. 실제로 이 자리에서 두 번 깨졌다.
@@ -180,7 +180,7 @@ gestalt pr prune --checkouts # 체크아웃 자국까지
180
180
  - 닫힌 PR은 아무것도 안 놓는다.
181
181
  - 체크아웃 자국은 기본으로 안 놓는다. 어느 이력에도 없는 커밋이라 놓으면 영영 사라진다. `--checkouts`로 뜻을 밝혀야 하고 그 PR이 이미 머지되거나 닫혔을 때만 놓는다.
182
182
 
183
- `prune`은 CLI에만 있다. 되돌릴 수 없게 놓는 자리라 도구 표면에 안 뒀다.
183
+ `prune`은 CLI에만 있다. 되돌릴 수 없게 놓는 자리라 MCP 도구로는 안 뒀다.
184
184
 
185
185
  ## 여러 워커로 나눌 때
186
186
 
@@ -134,7 +134,7 @@ id를 직접 주면 아래 1번의 첫 수단이 브랜치를 안 따지고 잡
134
134
  5. `gh pr view <target>`이 성공하면(GitHub PR이 실제로 존재) → `github`입니다.
135
135
  6. 여기까지 아무 데도 안 걸렸으면(GitHub에도 로컬에도 대응하는 PR이 없는 브랜치나 커밋 범위 리뷰) → `none`입니다. 4.7단계 전체를 건너뜁니다.
136
136
 
137
- **갈리는 건 본문이 정본입니다.** 아래 표는 본문 1~6번을 그대로 펼친 것뿐입니다. 표와 본문이 어긋나 보이면 본문을 따르고 표를 고칩니다. 각 행은 자기 위의 행에 안 걸린 경우입니다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻입니다.
137
+ **아래 표는 본문 1~6번을 그대로 펼친 것뿐입니다.** 표와 본문이 어긋나 보이면 본문을 따르고 표를 고칩니다. 각 행은 자기 위의 행에 안 걸린 경우입니다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻입니다.
138
138
 
139
139
  "로컬 PR 조회" 열은 1번의 두 수단(`show <id>` 또는 위의 가리는 법)이 대상 PR을 찾았는지입니다. 앞쪽은 브랜치를 안 따지고 뒤쪽만 따집니다. `안 봄`은 1번도 3번도 조회할 일이 없어 CLI를 아예 안 부른 경우입니다.
140
140
 
@@ -133,7 +133,7 @@ id를 직접 주면 아래 1번의 첫 수단이 브랜치를 안 따지고 잡
133
133
 
134
134
  gh 인증이 되고 원격도 있는데 로컬 PR을 지정했으면 1번이 먼저 잡는다. 로컬 PR id 형식이 아닌 값(PR 번호, URL, 브랜치명)은 1번을 그냥 지나친다.
135
135
 
136
- **갈리는 건 본문이 정본이다.** 아래 표는 본문 1~5번을 그대로 펼친 것뿐이다. 표와 본문이 어긋나 보이면 본문을 따르고 표를 고친다. 각 행은 자기 위의 행에 안 걸린 경우다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻이다.
136
+ **아래 표는 본문 1~5번을 그대로 펼친 것뿐이다.** 표와 본문이 어긋나 보이면 본문을 따르고 표를 고친다. 각 행은 자기 위의 행에 안 걸린 경우다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻이다.
137
137
 
138
138
  "로컬 PR 조회" 열은 1번의 두 수단(`show <id>` 또는 위의 가리는 법)이 대상 PR을 찾았는지다. 앞쪽은 브랜치를 안 따지고 뒤쪽만 따진다. `안 봄`은 1번도 3번도 조회할 일이 없어 CLI를 아예 안 부른 경우다.
139
139
 
@@ -2,7 +2,7 @@ import type { PullRequest } from '../../local-pr/types.js';
2
2
  /**
3
3
  * `gestalt pr` — 로컬 PR CLI.
4
4
  *
5
- * 에이전트가 부르는 정본 표면이다. MCP가 없거나 끊긴 런타임에서도 돌아야 해서
5
+ * MCP가 없거나 끊긴 런타임에서도 에이전트가 부를 수 있는 자리다.
6
6
  * 셸만 있으면 되는 이 경로를 먼저 만든다.
7
7
  */
8
8
  export interface PrCommonOptions {
@@ -1,18 +1,18 @@
1
1
  import { GestaltPrinciple } from '../core/types.js';
2
2
  /**
3
- * 표면/심층 분리 (Figure-Ground)에서 표면 문자열을 정의하는 단 한 곳.
3
+ * 사용자에게 보이는 문자열을 정의하는 단 한 곳. 게슈탈트 내부와의 경계다 (Figure-Ground).
4
4
  *
5
5
  * 코드 내부는 게슈탈트 원리(GestaltPrinciple enum)와 에이전트 식별자를 그대로 쓰지만,
6
- * 사용자에게 돌려주는 표면 문자열에는 게슈탈트 용어가 새어 나가면 안 된다.
6
+ * 사용자에게 돌려주는 문자열에는 게슈탈트 용어가 새어 나가면 안 된다.
7
7
  * 이 모듈이 내부 식별자를 평범한 한국어·영어 문구로 잇는 유일한 매핑 지점이다.
8
8
  *
9
- * 심층 (README, docs, LLM 시스템 프롬프트, 내부 타입) 이 모듈을 거치지 않고
10
- * 게슈탈트 어휘를 그대로 유지한다.
9
+ * 게슈탈트 내부(README, docs, LLM 시스템 프롬프트, 내부 타입) 이 모듈을 거치지 않고
10
+ * 어휘를 그대로 유지한다.
11
11
  */
12
12
  export type SurfaceLang = 'ko' | 'en';
13
13
  /**
14
14
  * 원리가 담당하는 단계를 평범한 말로 설명한 문구를 돌려준다.
15
- * currentPrinciple/principleStrategy/gestaltFocus 등 표면 노출 자리에 사용한다.
15
+ * currentPrinciple/principleStrategy/gestaltFocus 등 사용자에게 나가는 자리에 쓴다.
16
16
  * 알 수 없는 값('next' 등)은 중립적 기본 문구로 대체한다.
17
17
  */
18
18
  export declare function getStageLabel(principle: GestaltPrinciple | string, lang?: SurfaceLang): string;
@@ -27,27 +27,27 @@ export declare function getAgentDisplayName(agentName: string, lang?: SurfaceLan
27
27
  export declare function toDisplayAgentNames(agentNames: string[], lang?: SurfaceLang): string[];
28
28
  export declare function getConsistencyHint(lang?: SurfaceLang): string;
29
29
  /**
30
- * 표면 문자열에 절대 나타나면 안 되는 게슈탈트 금지어.
31
- * 회귀 테스트(LeakTest)가 이 목록으로 사용자 표면 응답을 검사한다.
30
+ * 사용자에게 나가는 문자열에 절대 나타나면 안 되는 게슈탈트 금지어.
31
+ * 회귀 테스트(LeakTest)가 이 목록으로 사용자에게 나가는 응답을 검사한다.
32
32
  * 원리 이름 6종(figure-ground는 두 표기 모두)만 담는다 — 에이전트 접미사(completer 등)는
33
33
  * 게슈탈트 용어가 아니므로 중립 표시 이름에 그대로 쓸 수 있어 제외한다.
34
34
  */
35
35
  export declare const BANNED_SURFACE_TERMS: readonly string[];
36
36
  /**
37
- * MCP 도구 응답에서 심층 쪽(LLM 지시 프롬프트) 필드 키.
38
- * 이 필드들은 게슈탈트 어휘를 담은 채 유지되므로 표면 누수 검사 대상에서 제외한다.
37
+ * MCP 도구 응답에서 LLM에게만 가는 프롬프트 필드 키.
38
+ * 이 필드들은 게슈탈트 어휘를 담은 채 유지되므로 누수 검사 대상에서 제외한다.
39
39
  */
40
40
  export declare const DEEP_PROMPT_KEYS: readonly string[];
41
41
  /**
42
42
  * 도구 응답에 통째로 실리는 컨텍스트 객체(gestaltContext/specContext/executeContext)에서
43
- * 게슈탈트 용어가 새는 메타 필드를 중립적 표면 값으로 치환한다.
43
+ * 게슈탈트 용어가 새는 메타 필드를 중립적인 값으로 치환한다.
44
44
  *
45
45
  * - currentPrinciple(원리 enum 값) → currentStage(평범한 단계 설명)
46
- * - principleStrategy(원리 용어가 박힌 전략 문구) → 표면에서 제거 (프롬프트에 이미 포함)
46
+ * - principleStrategy(원리 용어가 박힌 전략 문구) → 사용자 응답에서 제거 (프롬프트에 이미 포함)
47
47
  * - activeAgents(에이전트 식별자) → 중립적 표시 이름
48
48
  * - allRounds[].gestaltFocus(원리 enum 값) → stage(평범한 단계 설명)
49
49
  *
50
- * 심층 프롬프트 필드(systemPrompt 등)와 나머지 필드는 그대로 둔다.
50
+ * LLM에게만 가는 프롬프트 필드(systemPrompt 등)와 나머지 필드는 그대로 둔다.
51
51
  */
52
52
  export declare function sanitizeSurfaceContext<T>(ctx: T, lang?: SurfaceLang): T;
53
53
  //# sourceMappingURL=surface-labels.d.ts.map
@@ -39,7 +39,7 @@ const AGENT_DISPLAY_NAMES = {
39
39
  };
40
40
  /**
41
41
  * 원리가 담당하는 단계를 평범한 말로 설명한 문구를 돌려준다.
42
- * currentPrinciple/principleStrategy/gestaltFocus 등 표면 노출 자리에 사용한다.
42
+ * currentPrinciple/principleStrategy/gestaltFocus 등 사용자에게 나가는 자리에 쓴다.
43
43
  * 알 수 없는 값('next' 등)은 중립적 기본 문구로 대체한다.
44
44
  */
45
45
  export function getStageLabel(principle, lang = 'ko') {
@@ -62,7 +62,7 @@ export function toDisplayAgentNames(agentNames, lang = 'ko') {
62
62
  return agentNames.map((name) => getAgentDisplayName(name, lang));
63
63
  }
64
64
  /**
65
- * 실행 단계에서 caller에게 주는 "일관성 유지" 힌트의 평범한 표면 문구.
65
+ * 실행 단계에서 caller에게 주는 "일관성 유지" 힌트로 사용자에게 보이는 평범한 문구.
66
66
  * Similarity 원리를 노출하던 similarityStrategy 필드를 이 문구로 치환한다.
67
67
  */
68
68
  const CONSISTENCY_HINT = {
@@ -73,8 +73,8 @@ export function getConsistencyHint(lang = 'ko') {
73
73
  return CONSISTENCY_HINT[lang];
74
74
  }
75
75
  /**
76
- * 표면 문자열에 절대 나타나면 안 되는 게슈탈트 금지어.
77
- * 회귀 테스트(LeakTest)가 이 목록으로 사용자 표면 응답을 검사한다.
76
+ * 사용자에게 나가는 문자열에 절대 나타나면 안 되는 게슈탈트 금지어.
77
+ * 회귀 테스트(LeakTest)가 이 목록으로 사용자에게 나가는 응답을 검사한다.
78
78
  * 원리 이름 6종(figure-ground는 두 표기 모두)만 담는다 — 에이전트 접미사(completer 등)는
79
79
  * 게슈탈트 용어가 아니므로 중립 표시 이름에 그대로 쓸 수 있어 제외한다.
80
80
  */
@@ -88,8 +88,8 @@ export const BANNED_SURFACE_TERMS = [
88
88
  'gestalt',
89
89
  ];
90
90
  /**
91
- * MCP 도구 응답에서 심층 쪽(LLM 지시 프롬프트) 필드 키.
92
- * 이 필드들은 게슈탈트 어휘를 담은 채 유지되므로 표면 누수 검사 대상에서 제외한다.
91
+ * MCP 도구 응답에서 LLM에게만 가는 프롬프트 필드 키.
92
+ * 이 필드들은 게슈탈트 어휘를 담은 채 유지되므로 누수 검사 대상에서 제외한다.
93
93
  */
94
94
  export const DEEP_PROMPT_KEYS = [
95
95
  'systemPrompt',
@@ -102,14 +102,14 @@ export const DEEP_PROMPT_KEYS = [
102
102
  ];
103
103
  /**
104
104
  * 도구 응답에 통째로 실리는 컨텍스트 객체(gestaltContext/specContext/executeContext)에서
105
- * 게슈탈트 용어가 새는 메타 필드를 중립적 표면 값으로 치환한다.
105
+ * 게슈탈트 용어가 새는 메타 필드를 중립적인 값으로 치환한다.
106
106
  *
107
107
  * - currentPrinciple(원리 enum 값) → currentStage(평범한 단계 설명)
108
- * - principleStrategy(원리 용어가 박힌 전략 문구) → 표면에서 제거 (프롬프트에 이미 포함)
108
+ * - principleStrategy(원리 용어가 박힌 전략 문구) → 사용자 응답에서 제거 (프롬프트에 이미 포함)
109
109
  * - activeAgents(에이전트 식별자) → 중립적 표시 이름
110
110
  * - allRounds[].gestaltFocus(원리 enum 값) → stage(평범한 단계 설명)
111
111
  *
112
- * 심층 프롬프트 필드(systemPrompt 등)와 나머지 필드는 그대로 둔다.
112
+ * LLM에게만 가는 프롬프트 필드(systemPrompt 등)와 나머지 필드는 그대로 둔다.
113
113
  */
114
114
  export function sanitizeSurfaceContext(ctx, lang = 'ko') {
115
115
  if (!ctx || typeof ctx !== 'object')
@@ -58,7 +58,7 @@ function proseOnly(text, options = {}) {
58
58
  * 길이도 자른다 — D-9의 (?:\S+\s+)? 처럼 임의 토큰을 삼키는 탐지기가 있어서
59
59
  * 매치 하나가 수백 자로 늘어날 수 있다.
60
60
  *
61
- * 어투 탐지기와 맞춤법 검사가 같이 지나는 자리에 둔다. 한쪽만 누르면 표면이 넓은
61
+ * 어투 탐지기와 맞춤법 검사가 같이 지나는 자리에 둔다. 한쪽만 누르면 걸리는 범위가 넓은
62
62
  * 쪽이 그대로 새는데, 실제로 맞춤법만 누른 판이 그랬다.
63
63
  */
64
64
  function clampSample(sample) {
@@ -3,16 +3,16 @@ import type { Actor, Comment, PullRequest, ReviewVerdict } from './types.js';
3
3
  /**
4
4
  * 로컬 PR의 판단 규칙.
5
5
  *
6
- * 표면이 셋(CLI, MCP,)이고 이 규칙을 산문으로 옮겨 적는 스킬 문서가 셋 더 있다.
7
- * 규칙을 표면마다 다시 구현하면 하나가 반드시 뒤처진다 — 실제로 미해결 수를 스레드로
6
+ * CLI MCP셋이 이 규칙을 쓴다. 산문으로 옮겨 적는 스킬 문서도 셋 더 있다.
7
+ * 규칙을 호출하는 쪽마다 다시 구현하면 하나가 반드시 뒤처진다 — 실제로 미해결 수를 스레드로
8
8
  * 고친 뒤에도 웹 UI만 옛 계산으로 남아 같은 PR이 CLI에서 2, 웹에서 4로 보였다.
9
- * 표면은 여기서 값을 가져다 쓰고 스스로 세지 않는다.
9
+ * 호출하는 쪽은 여기서 값을 가져다 쓰고 스스로 세지 않는다.
10
10
  */
11
11
  /**
12
12
  * 아직 안 닫힌 코멘트.
13
13
  *
14
14
  * 미해결을 가르는 술어가 여기 하나뿐이다. 아래 두 함수도 이 목록에서 나온다 —
15
- * 표면이 헤아릴 때와 늘어놓을 때를 따로 계산하면 같은 화면에서 수가 갈린다.
15
+ * 호출하는 쪽이 헤아릴 때와 늘어놓을 때를 따로 계산하면 같은 화면에서 수가 갈린다.
16
16
  * 실제로 `pr show`가 머리글에 스레드 수를, 바로 아래 목록에 코멘트 수를 찍어
17
17
  * "미해결 1"이라고 해놓고 세 줄을 늘어놓았다.
18
18
  */
@@ -24,7 +24,7 @@ export interface Thread {
24
24
  /** 그중 안 닫힌 것만. 전부 닫혔으면 빈 배열이다 */
25
25
  unresolved: Comment[];
26
26
  /**
27
- * 표면이 한 줄로 접을 때 보여줄 코멘트. 안 닫힌 것 중 첫 번째다.
27
+ * 한 줄로 접을 때 보여줄 코멘트. 안 닫힌 것 중 첫 번째다.
28
28
  * 전부 닫혔으면 맨 처음 코멘트가 온다.
29
29
  */
30
30
  head: Comment;
@@ -43,7 +43,7 @@ export declare function threadsOf(pr: PullRequest): Thread[];
43
43
  /** 안 닫힌 스레드 하나 */
44
44
  export interface OpenThread {
45
45
  /**
46
- * 표면이 한 줄로 접을 때 보여줄 코멘트. 스레드에서 아직 안 닫힌 것 중 첫 번째다.
46
+ * 한 줄로 접을 때 보여줄 코멘트. 스레드에서 아직 안 닫힌 것 중 첫 번째다.
47
47
  * 뿌리가 닫히고 답글만 열려 있으면 그 답글이 여기 온다.
48
48
  */
49
49
  root: Comment;
@@ -51,7 +51,7 @@ export interface OpenThread {
51
51
  comments: Comment[];
52
52
  }
53
53
  export declare function openThreads(pr: PullRequest): OpenThread[];
54
- /** 안 닫힌 스레드 수. 표면의 "미해결 N"이 전부 이 값이다 */
54
+ /** 안 닫힌 스레드 수. 화면에 찍히는 "미해결 N"이 전부 이 값이다 */
55
55
  export declare function unresolvedCount(pr: PullRequest): number;
56
56
  /**
57
57
  * 누가 했는지.
@@ -1 +1 @@
1
- {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/local-pr/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,EAAE,CAE7D;AAED,0BAA0B;AAC1B,MAAM,WAAW,MAAM;IACrB,gCAAgC;IAChC,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,iCAAiC;IACjC,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB;;;OAGG;IACH,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,EAAE,CAYnD;AAED,kBAAkB;AAClB,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,IAAI,EAAE,OAAO,CAAC;IACd,oCAAoC;IACpC,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,UAAU,EAAE,CAIzD;AAED,wCAAwC;AACxC,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAE,KAAqB,GAAG,KAAK,CAEtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,WAAW,EAAE,EACrB,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAIT;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EAAE,EACrB,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAAC,aAAa,EAAE,SAAS,GAAG,iBAAiB,CAAC,CAEvD"}
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/local-pr/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,EAAE,CAE7D;AAED,0BAA0B;AAC1B,MAAM,WAAW,MAAM;IACrB,gCAAgC;IAChC,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,iCAAiC;IACjC,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB;;;OAGG;IACH,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,EAAE,CAYnD;AAED,kBAAkB;AAClB,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,IAAI,EAAE,OAAO,CAAC;IACd,oCAAoC;IACpC,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,UAAU,EAAE,CAIzD;AAED,4CAA4C;AAC5C,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAE,KAAqB,GAAG,KAAK,CAEtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,WAAW,EAAE,EACrB,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAIT;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EAAE,EACrB,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAAC,aAAa,EAAE,SAAS,GAAG,iBAAiB,CAAC,CAEvD"}
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * 로컬 PR의 판단 규칙.
3
3
  *
4
- * 표면이 셋(CLI, MCP,)이고 이 규칙을 산문으로 옮겨 적는 스킬 문서가 셋 더 있다.
5
- * 규칙을 표면마다 다시 구현하면 하나가 반드시 뒤처진다 — 실제로 미해결 수를 스레드로
4
+ * CLI MCP셋이 이 규칙을 쓴다. 산문으로 옮겨 적는 스킬 문서도 셋 더 있다.
5
+ * 규칙을 호출하는 쪽마다 다시 구현하면 하나가 반드시 뒤처진다 — 실제로 미해결 수를 스레드로
6
6
  * 고친 뒤에도 웹 UI만 옛 계산으로 남아 같은 PR이 CLI에서 2, 웹에서 4로 보였다.
7
- * 표면은 여기서 값을 가져다 쓰고 스스로 세지 않는다.
7
+ * 호출하는 쪽은 여기서 값을 가져다 쓰고 스스로 세지 않는다.
8
8
  */
9
9
  /**
10
10
  * 아직 안 닫힌 코멘트.
11
11
  *
12
12
  * 미해결을 가르는 술어가 여기 하나뿐이다. 아래 두 함수도 이 목록에서 나온다 —
13
- * 표면이 헤아릴 때와 늘어놓을 때를 따로 계산하면 같은 화면에서 수가 갈린다.
13
+ * 호출하는 쪽이 헤아릴 때와 늘어놓을 때를 따로 계산하면 같은 화면에서 수가 갈린다.
14
14
  * 실제로 `pr show`가 머리글에 스레드 수를, 바로 아래 목록에 코멘트 수를 찍어
15
15
  * "미해결 1"이라고 해놓고 세 줄을 늘어놓았다.
16
16
  */
@@ -44,7 +44,7 @@ export function openThreads(pr) {
44
44
  .filter((t) => t.open)
45
45
  .map((t) => ({ root: t.head, comments: t.unresolved }));
46
46
  }
47
- /** 안 닫힌 스레드 수. 표면의 "미해결 N"이 전부 이 값이다 */
47
+ /** 안 닫힌 스레드 수. 화면에 찍히는 "미해결 N"이 전부 이 값이다 */
48
48
  export function unresolvedCount(pr) {
49
49
  return openThreads(pr).length;
50
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/local-pr/policy.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAe;IAChD,OAAO,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAChD,CAAC;AAiBD;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,EAAe;IACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC9C,KAAK,MAAM,OAAO,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;YAC5B,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACxC,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAClD,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;IAC1F,CAAC,CAAC,CAAC;AACL,CAAC;AAaD,MAAM,UAAU,WAAW,CAAC,EAAe;IACzC,OAAO,SAAS,CAAC,EAAE,CAAC;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,eAAe,CAAC,EAAe;IAC7C,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,QAAiB,EAAE,WAAkB,aAAa;IAC7E,OAAO,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC;AAC9D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAqB,EACrB,iBAAqC;IAErC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzF,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IACjF,OAAO,CAAC,SAAS,IAAI,CAAC,gBAAgB,CAAC;AACzC,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,gBAAgB,CAC9B,MAAqB,EACrB,iBAAqC;IAErC,OAAO,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC;AACxF,CAAC"}
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/local-pr/policy.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAe;IAChD,OAAO,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAChD,CAAC;AAiBD;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,EAAe;IACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC9C,KAAK,MAAM,OAAO,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;YAC5B,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACxC,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAClD,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;IAC1F,CAAC,CAAC,CAAC;AACL,CAAC;AAaD,MAAM,UAAU,WAAW,CAAC,EAAe;IACzC,OAAO,SAAS,CAAC,EAAE,CAAC;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,eAAe,CAAC,EAAe;IAC7C,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,QAAiB,EAAE,WAAkB,aAAa;IAC7E,OAAO,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC;AAC9D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAqB,EACrB,iBAAqC;IAErC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzF,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IACjF,OAAO,CAAC,SAAS,IAAI,CAAC,gBAAgB,CAAC;AACzC,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,gBAAgB,CAC9B,MAAqB,EACrB,iBAAqC;IAErC,OAAO,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC;AACxF,CAAC"}
@@ -18,7 +18,7 @@ export declare class PrWebEngine {
18
18
  * 프로세스 하나가 서버를 하나만 띄우도록 공유하는 인스턴스.
19
19
  *
20
20
  * 아직 부르는 자리가 없다. `pr serve`는 `new PrWebEngine()`으로 직접 만들고 MCP는
21
- * 이 모듈을 안 가져간다. 여러 표면이 서버를 공유해야 할 때를 위해 남겨 둔 진입점이다.
21
+ * 이 모듈을 안 가져간다. CLI와 MCP가 같은 서버 인스턴스를 공유해야 할 때를 위해 남겨 둔 진입점이다.
22
22
  */
23
23
  export declare function getPrWebEngine(): PrWebEngine;
24
24
  //# sourceMappingURL=engine.d.ts.map
@@ -93,7 +93,7 @@ let _instance = null;
93
93
  * 프로세스 하나가 서버를 하나만 띄우도록 공유하는 인스턴스.
94
94
  *
95
95
  * 아직 부르는 자리가 없다. `pr serve`는 `new PrWebEngine()`으로 직접 만들고 MCP는
96
- * 이 모듈을 안 가져간다. 여러 표면이 서버를 공유해야 할 때를 위해 남겨 둔 진입점이다.
96
+ * 이 모듈을 안 가져간다. CLI와 MCP가 같은 서버 인스턴스를 공유해야 할 때를 위해 남겨 둔 진입점이다.
97
97
  */
98
98
  export function getPrWebEngine() {
99
99
  if (!_instance)
@@ -111,7 +111,7 @@ export function errorKind(exitCode) {
111
111
  * update-ref를 쓰고 워크트리를 만든다. `close`는 ref를 지운다. `checkout_remove --force`는
112
112
  * 경로를 재귀로 지운다. 인자 하나를 바꿔 부르면 이 머신의 아무 git 레포나 그 대상이
113
113
  * 된다. 레지스트리가 `pr create`의 등록 경로를 막은 것과 같은 축인데, 정작 git을
114
- * 변형하는 표면이 열려 있었다.
114
+ * 변형하는 자리가 열려 있었다.
115
115
  *
116
116
  * 그래서 지금 자리와 **같은 레포**일 때만 받는다. 판정은 공용 git 디렉토리로 하므로
117
117
  * 워크트리와 하위 디렉토리는 그대로 통과한다 — 이 인자가 원래 있는 이유가 그거다.
@@ -257,7 +257,7 @@ function actorOfAgent(name) {
257
257
  * PR은 이벤트 소싱이라 그렇게 붙은 중복은 지울 수 없고 사람이 손으로 닫아야 한다.
258
258
  * 그래서 어디까지 썼는지를 PR 자신에게도 남긴다 — 재기동해도 여기서 되짚는다.
259
259
  *
260
- * 코멘트의 `marker` 필드에 넣는다. 본문에 실었더니 어느 표면에서도 보이지 않았다
260
+ * 코멘트의 `marker` 필드에 넣는다. 본문에 실었더니 CLI에서도 웹에서도 그대로 보였다
261
261
  * 웹은 본문을 이스케이프해서 `<!-- ... -->`를 화면에 그대로 찍고 CLI는 평문으로
262
262
  * 내보낸다. 사람이 읽을 이유가 없는 해시 줄이 리뷰 코멘트마다 붙었다.
263
263
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tienne/gestalt",
3
- "version": "0.72.0",
3
+ "version": "0.72.1",
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.0",
3
+ "version": "0.72.1",
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"
@@ -72,7 +72,6 @@
72
72
  |---|---|
73
73
  | 규칙·정의가 적힌 문서 | 기준 문서 |
74
74
  | 비교 대상이 되는 수치 | 기준값 (목표 대비, 전기 대비 등 — impact-writer 용법) |
75
- | 여러 사본 중 원본 하나 | 정본 |
76
75
  | 조회·대조용 참조 자료 | 참조 기준 |
77
76
  | 데이터가 처음 만들어지는 곳 | 원천 데이터 |
78
77
  | 값을 담고 있는 데이터 자체 | 기준 데이터 |
@@ -85,6 +84,8 @@
85
84
  "룰북과 에이전트 문서가 갈라졌는지 본다"가 "룰북 기준 문서와…"보다 낫다.
86
85
  명사를 고르기 전에 동사로 풀 수 있는지 먼저 본다 — "A가 기준이다", "A를 기준으로 삼는다".
87
86
 
87
+ **여러 사본 중 원본 하나를 가리킬 때가 특히 그렇다.** 이 자리에 명사를 붙이면 뭉개진다. "이 파일만 읽는다", "고칠 일이 있으면 여기를 고친다", "표와 본문이 어긋나 보이면 본문을 따른다"처럼 적는다.
88
+
88
89
  ### 음차를 옮길 때 — 한 단어로 정하지 않는다
89
90
 
90
91
  같은 영어 단어라도 가리키는 게 다르면 다른 말이 된다. 대체어 하나를 정해놓고 전부 치환하면
@@ -98,6 +99,23 @@
98
99
  | layer | 동시에 처리되는 한 덩어리 | 묶음 |
99
100
  | layer | 순서대로 밟는 구간 | 단계 |
100
101
  | layer | 책임이 갈리는 구분 | 역할 |
102
+ | surface | 에이전트나 사람이 접근하는 창구 | 그 이름을 부른다 (CLI, MCP, 웹) |
103
+ | surface | 그 셋을 아울러야 할 때 | 호출하는 쪽 |
104
+ | surface | 이름 붙이기 애매한 접근 지점 | 자리 |
105
+ | surface | 값이 찍히는 화면 | 화면 |
106
+ | surface | 사용자에게 나가는 응답 | 사용자에게 보이는 / 나가는 |
107
+ | surface | 노출 영역 전체를 개념으로 부를 때 | 사용자 노출 |
108
+ | surface | 탐지기가 걸리는 넓이 | 걸리는 범위 |
109
+ | deep | 게슈탈트 용어를 써도 되는 곳 | 게슈탈트 내부 |
110
+ | deep | LLM 지시 프롬프트를 가리킬 때 | LLM에게만 가는 프롬프트 |
111
+
112
+ **이 표는 한국어 산문에서 음차로 쓴 자리만 다룬다.** 세 가지는 대상이 아니다.
113
+
114
+ - **코드 식별자.** `sanitizeSurfaceContext`, `DEEP_PROMPT_KEYS`, `gateway`는 그대로 둔다. 심볼을 바꾸면 호출부가 전부 딸려 온다.
115
+ - **그 도메인의 정착 용어.** 디자인 시스템의 `surface`와 `onSurface`(Material Design 색 토큰), CI의 gate, API gateway가 그렇다. **이 파일은 플러그인으로 배포돼 다른 레포에서도 읽히므로** 프론트엔드 레포에서 색 토큰을 "표면"으로 옮기라는 말이 되지 않게 조심한다.
116
+ - **이미 나간 CHANGELOG와 릴리즈 노트.** 그때 낸 문장이 아니게 된다.
117
+
118
+ **대비쌍은 짝을 함께 옮긴다.** `surface`와 `deep`처럼 둘이 맞물려 뜻을 이루는 말은 한쪽만 풀면 남은 쪽이 무엇의 반대인지 가리킬 데를 잃는다. 실제로 "표면"만 걷었다가 "심층"이 짝 없이 남아 한 문단 안에서 이름이 둘로 갈렸다.
101
119
 
102
120
  **일괄 치환은 조사를 깨뜨린다.** 받침 유무가 바뀌면 뒤따르는 조사도 바뀐다.
103
121
  `레이어라면` → `계층이라면`, `레이어(…)는` → `계층(…)은`. 실제로 이 자리에서 두 번 깨졌다.
@@ -180,7 +180,7 @@ gestalt pr prune --checkouts # 체크아웃 자국까지
180
180
  - 닫힌 PR은 아무것도 안 놓는다.
181
181
  - 체크아웃 자국은 기본으로 안 놓는다. 어느 이력에도 없는 커밋이라 놓으면 영영 사라진다. `--checkouts`로 뜻을 밝혀야 하고 그 PR이 이미 머지되거나 닫혔을 때만 놓는다.
182
182
 
183
- `prune`은 CLI에만 있다. 되돌릴 수 없게 놓는 자리라 도구 표면에 안 뒀다.
183
+ `prune`은 CLI에만 있다. 되돌릴 수 없게 놓는 자리라 MCP 도구로는 안 뒀다.
184
184
 
185
185
  ## 여러 워커로 나눌 때
186
186
 
@@ -134,7 +134,7 @@ id를 직접 주면 아래 1번의 첫 수단이 브랜치를 안 따지고 잡
134
134
  5. `gh pr view <target>`이 성공하면(GitHub PR이 실제로 존재) → `github`입니다.
135
135
  6. 여기까지 아무 데도 안 걸렸으면(GitHub에도 로컬에도 대응하는 PR이 없는 브랜치나 커밋 범위 리뷰) → `none`입니다. 4.7단계 전체를 건너뜁니다.
136
136
 
137
- **갈리는 건 본문이 정본입니다.** 아래 표는 본문 1~6번을 그대로 펼친 것뿐입니다. 표와 본문이 어긋나 보이면 본문을 따르고 표를 고칩니다. 각 행은 자기 위의 행에 안 걸린 경우입니다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻입니다.
137
+ **아래 표는 본문 1~6번을 그대로 펼친 것뿐입니다.** 표와 본문이 어긋나 보이면 본문을 따르고 표를 고칩니다. 각 행은 자기 위의 행에 안 걸린 경우입니다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻입니다.
138
138
 
139
139
  "로컬 PR 조회" 열은 1번의 두 수단(`show <id>` 또는 위의 가리는 법)이 대상 PR을 찾았는지입니다. 앞쪽은 브랜치를 안 따지고 뒤쪽만 따집니다. `안 봄`은 1번도 3번도 조회할 일이 없어 CLI를 아예 안 부른 경우입니다.
140
140
 
@@ -133,7 +133,7 @@ id를 직접 주면 아래 1번의 첫 수단이 브랜치를 안 따지고 잡
133
133
 
134
134
  gh 인증이 되고 원격도 있는데 로컬 PR을 지정했으면 1번이 먼저 잡는다. 로컬 PR id 형식이 아닌 값(PR 번호, URL, 브랜치명)은 1번을 그냥 지나친다.
135
135
 
136
- **갈리는 건 본문이 정본이다.** 아래 표는 본문 1~5번을 그대로 펼친 것뿐이다. 표와 본문이 어긋나 보이면 본문을 따르고 표를 고친다. 각 행은 자기 위의 행에 안 걸린 경우다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻이다.
136
+ **아래 표는 본문 1~5번을 그대로 펼친 것뿐이다.** 표와 본문이 어긋나 보이면 본문을 따르고 표를 고친다. 각 행은 자기 위의 행에 안 걸린 경우다. "—"는 앞 행에서 이미 갈려 볼 필요가 없다는 뜻이다.
137
137
 
138
138
  "로컬 PR 조회" 열은 1번의 두 수단(`show <id>` 또는 위의 가리는 법)이 대상 PR을 찾았는지다. 앞쪽은 브랜치를 안 따지고 뒤쪽만 따진다. `안 봄`은 1번도 3번도 조회할 일이 없어 CLI를 아예 안 부른 경우다.
139
139