@tienne/gestalt 0.67.0 → 0.69.0

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 (163) hide show
  1. package/CLAUDE.md +12 -5
  2. package/README.ko.md +9 -5
  3. package/README.md +10 -5
  4. package/dist/package.json +2 -1
  5. package/dist/plugin/review-agents/comment-reviewer/AGENT.md +2 -0
  6. package/dist/plugin/review-agents/quality-reviewer/AGENT.md +1 -1
  7. package/dist/plugin/review-agents/writing-reviewer/AGENT.md +123 -0
  8. package/dist/plugin/role-agents/_shared/references/ai-tell-quick-rules.md +1 -1
  9. package/dist/plugin/role-agents/_shared/references/comment-rules.md +14 -0
  10. package/dist/plugin/skills/_shared/agent-model.md +15 -0
  11. package/dist/plugin/skills/blast-radius/SKILL.md +31 -0
  12. package/dist/plugin/skills/diff-radius/SKILL.md +1 -1
  13. package/dist/plugin/skills/execute/SKILL.md +15 -0
  14. package/dist/plugin/skills/local-pr/SKILL.md +201 -0
  15. package/dist/plugin/skills/pr/SKILL.md +73 -4
  16. package/dist/plugin/skills/review/SKILL.md +236 -22
  17. package/dist/plugin/skills/review-reply/SKILL.md +160 -7
  18. package/dist/src/agent/role-match-engine.d.ts +8 -0
  19. package/dist/src/agent/role-match-engine.d.ts.map +1 -1
  20. package/dist/src/agent/role-match-engine.js +1 -1
  21. package/dist/src/agent/role-match-engine.js.map +1 -1
  22. package/dist/src/cli/commands/interview.js +2 -2
  23. package/dist/src/cli/commands/interview.js.map +1 -1
  24. package/dist/src/cli/commands/pr.d.ts +133 -0
  25. package/dist/src/cli/commands/pr.d.ts.map +1 -0
  26. package/dist/src/cli/commands/pr.js +489 -0
  27. package/dist/src/cli/commands/pr.js.map +1 -0
  28. package/dist/src/cli/commands/spec.js +2 -2
  29. package/dist/src/cli/commands/spec.js.map +1 -1
  30. package/dist/src/cli/index.d.ts.map +1 -1
  31. package/dist/src/cli/index.js +85 -0
  32. package/dist/src/cli/index.js.map +1 -1
  33. package/dist/src/core/config.d.ts.map +1 -1
  34. package/dist/src/core/config.js +4 -3
  35. package/dist/src/core/config.js.map +1 -1
  36. package/dist/src/core/home.d.ts +20 -0
  37. package/dist/src/core/home.d.ts.map +1 -0
  38. package/dist/src/core/home.js +52 -0
  39. package/dist/src/core/home.js.map +1 -0
  40. package/dist/src/core/types.d.ts +38 -0
  41. package/dist/src/core/types.d.ts.map +1 -1
  42. package/dist/src/core/version.d.ts.map +1 -1
  43. package/dist/src/core/version.js +4 -7
  44. package/dist/src/core/version.js.map +1 -1
  45. package/dist/src/events/store.d.ts +32 -0
  46. package/dist/src/events/store.d.ts.map +1 -1
  47. package/dist/src/events/store.js +68 -3
  48. package/dist/src/events/store.js.map +1 -1
  49. package/dist/src/humanize/detectors.d.ts.map +1 -1
  50. package/dist/src/humanize/detectors.js +3 -1
  51. package/dist/src/humanize/detectors.js.map +1 -1
  52. package/dist/src/interview/engine.d.ts +6 -1
  53. package/dist/src/interview/engine.d.ts.map +1 -1
  54. package/dist/src/interview/engine.js +7 -2
  55. package/dist/src/interview/engine.js.map +1 -1
  56. package/dist/src/knowledge-base/summarizer.d.ts +22 -0
  57. package/dist/src/knowledge-base/summarizer.d.ts.map +1 -0
  58. package/dist/src/knowledge-base/summarizer.js +179 -0
  59. package/dist/src/knowledge-base/summarizer.js.map +1 -0
  60. package/dist/src/llm/factory.d.ts +9 -0
  61. package/dist/src/llm/factory.d.ts.map +1 -1
  62. package/dist/src/llm/factory.js +13 -0
  63. package/dist/src/llm/factory.js.map +1 -1
  64. package/dist/src/local-pr/engine.d.ts +176 -0
  65. package/dist/src/local-pr/engine.d.ts.map +1 -0
  66. package/dist/src/local-pr/engine.js +373 -0
  67. package/dist/src/local-pr/engine.js.map +1 -0
  68. package/dist/src/local-pr/git.d.ts +190 -0
  69. package/dist/src/local-pr/git.d.ts.map +1 -0
  70. package/dist/src/local-pr/git.js +580 -0
  71. package/dist/src/local-pr/git.js.map +1 -0
  72. package/dist/src/local-pr/index.d.ts +6 -0
  73. package/dist/src/local-pr/index.d.ts.map +1 -0
  74. package/dist/src/local-pr/index.js +8 -0
  75. package/dist/src/local-pr/index.js.map +1 -0
  76. package/dist/src/local-pr/policy.d.ts +77 -0
  77. package/dist/src/local-pr/policy.d.ts.map +1 -0
  78. package/dist/src/local-pr/policy.js +80 -0
  79. package/dist/src/local-pr/policy.js.map +1 -0
  80. package/dist/src/local-pr/registry.d.ts +79 -0
  81. package/dist/src/local-pr/registry.d.ts.map +1 -0
  82. package/dist/src/local-pr/registry.js +307 -0
  83. package/dist/src/local-pr/registry.js.map +1 -0
  84. package/dist/src/local-pr/repository.d.ts +67 -0
  85. package/dist/src/local-pr/repository.d.ts.map +1 -0
  86. package/dist/src/local-pr/repository.js +251 -0
  87. package/dist/src/local-pr/repository.js.map +1 -0
  88. package/dist/src/local-pr/types.d.ts +151 -0
  89. package/dist/src/local-pr/types.d.ts.map +1 -0
  90. package/dist/src/local-pr/types.js +9 -0
  91. package/dist/src/local-pr/types.js.map +1 -0
  92. package/dist/src/local-pr-web/engine.d.ts +24 -0
  93. package/dist/src/local-pr-web/engine.d.ts.map +1 -0
  94. package/dist/src/local-pr-web/engine.js +112 -0
  95. package/dist/src/local-pr-web/engine.js.map +1 -0
  96. package/dist/src/local-pr-web/html-generator.d.ts +24 -0
  97. package/dist/src/local-pr-web/html-generator.d.ts.map +1 -0
  98. package/dist/src/local-pr-web/html-generator.js +385 -0
  99. package/dist/src/local-pr-web/html-generator.js.map +1 -0
  100. package/dist/src/local-pr-web/index.d.ts +5 -0
  101. package/dist/src/local-pr-web/index.d.ts.map +1 -0
  102. package/dist/src/local-pr-web/index.js +5 -0
  103. package/dist/src/local-pr-web/index.js.map +1 -0
  104. package/dist/src/local-pr-web/server.d.ts +126 -0
  105. package/dist/src/local-pr-web/server.d.ts.map +1 -0
  106. package/dist/src/local-pr-web/server.js +394 -0
  107. package/dist/src/local-pr-web/server.js.map +1 -0
  108. package/dist/src/local-pr-web/types.d.ts +11 -0
  109. package/dist/src/local-pr-web/types.d.ts.map +1 -0
  110. package/dist/src/local-pr-web/types.js +2 -0
  111. package/dist/src/local-pr-web/types.js.map +1 -0
  112. package/dist/src/mcp/schemas.d.ts +79 -4
  113. package/dist/src/mcp/schemas.d.ts.map +1 -1
  114. package/dist/src/mcp/schemas.js +80 -2
  115. package/dist/src/mcp/schemas.js.map +1 -1
  116. package/dist/src/mcp/server.d.ts.map +1 -1
  117. package/dist/src/mcp/server.js +23 -10
  118. package/dist/src/mcp/server.js.map +1 -1
  119. package/dist/src/mcp/tools/generate-kb.d.ts +10 -1
  120. package/dist/src/mcp/tools/generate-kb.d.ts.map +1 -1
  121. package/dist/src/mcp/tools/generate-kb.js +17 -1
  122. package/dist/src/mcp/tools/generate-kb.js.map +1 -1
  123. package/dist/src/mcp/tools/pr.d.ts +5 -0
  124. package/dist/src/mcp/tools/pr.d.ts.map +1 -0
  125. package/dist/src/mcp/tools/pr.js +165 -0
  126. package/dist/src/mcp/tools/pr.js.map +1 -0
  127. package/dist/src/mcp/tools/review-passthrough.d.ts.map +1 -1
  128. package/dist/src/mcp/tools/review-passthrough.js +264 -15
  129. package/dist/src/mcp/tools/review-passthrough.js.map +1 -1
  130. package/dist/src/mcp/tools/search-kb.d.ts.map +1 -1
  131. package/dist/src/mcp/tools/search-kb.js +5 -0
  132. package/dist/src/mcp/tools/search-kb.js.map +1 -1
  133. package/dist/src/mcp/tools/status.d.ts +16 -0
  134. package/dist/src/mcp/tools/status.d.ts.map +1 -1
  135. package/dist/src/mcp/tools/status.js +19 -4
  136. package/dist/src/mcp/tools/status.js.map +1 -1
  137. package/dist/src/memory/user-profile-store.d.ts.map +1 -1
  138. package/dist/src/memory/user-profile-store.js +3 -4
  139. package/dist/src/memory/user-profile-store.js.map +1 -1
  140. package/dist/src/review/context-collector.d.ts +1 -1
  141. package/dist/src/review/context-collector.js +1 -1
  142. package/dist/src/review/passthrough-engine.d.ts +1 -0
  143. package/dist/src/review/passthrough-engine.d.ts.map +1 -1
  144. package/dist/src/review/passthrough-engine.js +7 -2
  145. package/dist/src/review/passthrough-engine.js.map +1 -1
  146. package/dist/src/spec/text-based-spec-generator.d.ts.map +1 -1
  147. package/dist/src/spec/text-based-spec-generator.js +5 -2
  148. package/dist/src/spec/text-based-spec-generator.js.map +1 -1
  149. package/package.json +2 -1
  150. package/plugin/.codex-plugin/plugin.json +1 -1
  151. package/plugin/review-agents/comment-reviewer/AGENT.md +2 -0
  152. package/plugin/review-agents/quality-reviewer/AGENT.md +1 -1
  153. package/plugin/review-agents/writing-reviewer/AGENT.md +123 -0
  154. package/plugin/role-agents/_shared/references/ai-tell-quick-rules.md +1 -1
  155. package/plugin/role-agents/_shared/references/comment-rules.md +14 -0
  156. package/plugin/skills/_shared/agent-model.md +15 -0
  157. package/plugin/skills/blast-radius/SKILL.md +31 -0
  158. package/plugin/skills/diff-radius/SKILL.md +1 -1
  159. package/plugin/skills/execute/SKILL.md +15 -0
  160. package/plugin/skills/local-pr/SKILL.md +201 -0
  161. package/plugin/skills/pr/SKILL.md +73 -4
  162. package/plugin/skills/review/SKILL.md +236 -22
  163. package/plugin/skills/review-reply/SKILL.md +160 -7
@@ -0,0 +1,489 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { LocalPrEngine, PrError } from '../../local-pr/engine.js';
4
+ import { openThreads, resolveActor, unresolvedComments, unresolvedCount, } from '../../local-pr/policy.js';
5
+ import { listRepos, repoKey, unregisterRepo } from '../../local-pr/registry.js';
6
+ import { PrWebEngine } from '../../local-pr-web/engine.js';
7
+ /**
8
+ * 본문을 파일이나 stdin에서 읽는다.
9
+ *
10
+ * 인자로 받지 않는 이유는 셸을 타면 한글과 백틱, 줄바꿈이 깨지기 때문이다.
11
+ * `-`면 stdin이다 — gh가 --body-file에 쓰는 방식과 같다.
12
+ */
13
+ function readBody(bodyFile) {
14
+ if (bodyFile === undefined)
15
+ return '';
16
+ // 빈 문자열은 "안 줬다"가 아니라 "빈 경로를 줬다"다. 안 갈라 두면 셸에서 안 풀린
17
+ // `--body-file "$F"`가 본문을 조용히 지운다 — 없는 경로는 ENOENT로 죽는데
18
+ // 이 자리만 성공으로 끝난다
19
+ if (bodyFile === '')
20
+ throw new PrError('--body-file에 경로가 비어 있어요', 1);
21
+ return readFileSync(bodyFile === '-' ? 0 : bodyFile, 'utf-8');
22
+ }
23
+ function actorOf(opts) {
24
+ return resolveActor(opts.author);
25
+ }
26
+ function engineOf(opts) {
27
+ return new LocalPrEngine(resolve(opts.repoRoot ?? process.cwd()));
28
+ }
29
+ /** 에이전트가 파싱할 자리라 --json이면 객체만 내보낸다 */
30
+ function emit(value, json, human) {
31
+ if (json) {
32
+ console.log(JSON.stringify(value, null, 2));
33
+ }
34
+ else {
35
+ human();
36
+ }
37
+ }
38
+ function summarize(pr) {
39
+ const unresolved = unresolvedCount(pr);
40
+ const round = pr.rounds[pr.rounds.length - 1].number;
41
+ return `${pr.id} [${pr.status}] ${pr.title} (라운드 ${round}, 미해결 ${unresolved})`;
42
+ }
43
+ /** 오류를 종료 코드로 옮긴다. 에이전트가 stdout을 안 읽고도 갈래를 탄다 */
44
+ function run(fn) {
45
+ try {
46
+ fn();
47
+ }
48
+ catch (e) {
49
+ // `process.exit`이 여기서 흐름을 끊는 건 런타임의 성질이지 이 갈래가 한 약속이
50
+ // 아니다. 갈라 두지 않으면 테스트가 exit을 가로챌 때 두 번 나간다
51
+ if (e instanceof PrError) {
52
+ console.error(e.message);
53
+ process.exit(e.exitCode);
54
+ }
55
+ else {
56
+ console.error(e instanceof Error ? e.message : String(e));
57
+ process.exit(1);
58
+ }
59
+ }
60
+ }
61
+ export function prCreateCommand(opts) {
62
+ run(() => {
63
+ const engine = engineOf(opts);
64
+ try {
65
+ const pr = engine.create({
66
+ title: opts.title,
67
+ body: readBody(opts.bodyFile),
68
+ author: actorOf(opts),
69
+ base: opts.base,
70
+ head: opts.head,
71
+ });
72
+ emit(pr, opts.json, () => {
73
+ console.log(`PR을 만들었어요: ${pr.id}`);
74
+ console.log(` base ${pr.baseSha.slice(0, 8)} → head ${pr.headSha.slice(0, 8)}`);
75
+ console.log(` 리뷰: gestalt pr show ${pr.id}`);
76
+ });
77
+ }
78
+ finally {
79
+ engine.dispose();
80
+ }
81
+ });
82
+ }
83
+ export function prListCommand(opts) {
84
+ run(() => {
85
+ const engine = engineOf(opts);
86
+ try {
87
+ const prs = engine.list(opts.status);
88
+ emit(prs, opts.json, () => {
89
+ if (prs.length === 0) {
90
+ console.log('PR이 없어요');
91
+ return;
92
+ }
93
+ for (const pr of prs)
94
+ console.log(summarize(pr));
95
+ });
96
+ }
97
+ finally {
98
+ engine.dispose();
99
+ }
100
+ });
101
+ }
102
+ export function prShowCommand(opts) {
103
+ run(() => {
104
+ const engine = engineOf(opts);
105
+ try {
106
+ const pr = engine.get(opts.id);
107
+ if (!pr)
108
+ throw new PrError(`PR을 못 찾았어요: ${opts.id}`, 3);
109
+ emit(pr, opts.json, () => {
110
+ console.log(summarize(pr));
111
+ console.log(` 작성 ${pr.author}`);
112
+ if (pr.body)
113
+ console.log(`\n${pr.body}\n`);
114
+ for (const round of pr.rounds) {
115
+ const verdict = round.verdict ?? '진행 중';
116
+ console.log(`\n라운드 ${round.number} — ${verdict} (코멘트 ${round.commentCount})`);
117
+ for (const review of pr.reviews.filter((r) => r.round === round.number)) {
118
+ console.log(` ${review.reviewer}: ${review.verdict} — ${review.summary}`);
119
+ }
120
+ }
121
+ // 머리글의 "미해결 N"과 이 목록이 같은 함수에서 나온다. 따로 세면 머리글은
122
+ // 스레드를, 목록은 코멘트를 세어 한 화면에서 수가 갈린다
123
+ const threads = openThreads(pr);
124
+ if (threads.length > 0) {
125
+ console.log('\n미해결 스레드');
126
+ for (const { root, comments } of threads) {
127
+ const at = root.line === null ? root.path : `${root.path}:${root.line}`;
128
+ const replies = comments.length - 1;
129
+ const tail = replies > 0 ? ` (답글 ${replies}개)` : '';
130
+ console.log(` [${root.id}] ${at} (${root.author})${tail}`);
131
+ console.log(` ${root.body.split('\n')[0]}`);
132
+ }
133
+ }
134
+ });
135
+ }
136
+ finally {
137
+ engine.dispose();
138
+ }
139
+ });
140
+ }
141
+ export function prDiffCommand(opts) {
142
+ run(() => {
143
+ const engine = engineOf(opts);
144
+ try {
145
+ const diff = engine.diff(opts.id);
146
+ emit({ diff }, opts.json, () => console.log(diff));
147
+ }
148
+ finally {
149
+ engine.dispose();
150
+ }
151
+ });
152
+ }
153
+ /**
154
+ * `gestalt pr checkout <id>` — PR head를 임시 워크트리로 떼어낸다.
155
+ *
156
+ * `--remove`면 지운다. 붙였다 뗐다를 한 명령에 둔 이유는 경로 규칙이 하나라서다.
157
+ * 리뷰어는 id만 알면 되고 경로를 적어둘 필요가 없다.
158
+ */
159
+ export function prCheckoutCommand(opts) {
160
+ run(() => {
161
+ const engine = engineOf(opts);
162
+ try {
163
+ if (opts.remove) {
164
+ const result = engine.removeCheckout(opts.id, { force: opts.force });
165
+ emit(result, opts.json, () => {
166
+ if (result.removed) {
167
+ console.log(`워크트리를 지웠어요: ${result.path}`);
168
+ if (result.savedRef) {
169
+ console.log(` 여기서 커밋한 변경은 ${result.savedRef}로 붙잡아 뒀어요`);
170
+ }
171
+ }
172
+ else {
173
+ console.log(`안 지웠어요 — ${result.reason}`);
174
+ console.log(` ${result.path}`);
175
+ }
176
+ });
177
+ // 안 지운 건 실패가 아니라 판단을 되돌려준 것이다. 에이전트가 종료 코드로
178
+ // 갈래를 타게 4(상태 충돌)를 준다. 지킨 갈래는 `dirty`, `diverged`, `stale`
179
+ // 셋이고 앞으로 늘 수 있다. 그 셋을 나열하는 대신 "지운 두 갈래가 아니면"으로
180
+ // 적는다. `absent`를 뺀 이유는 지울 자리가 없는 게 정리의 목표가 이미 이뤄진
181
+ // 상태여서다. 4로 주면 `--remove`를 두 번 부르는 `set -e` 스크립트가 두 번째에
182
+ // 죽는다. 이 갈림은 --json의 status로도 읽을 수 있다 — 산문 reason을 부분
183
+ // 문자열로 긁을 필요가 없다
184
+ if (result.status !== 'removed' && result.status !== 'absent')
185
+ process.exit(4);
186
+ return;
187
+ }
188
+ const checkout = engine.checkout(opts.id);
189
+ emit(checkout, opts.json, () => {
190
+ console.log(checkout.created ? '워크트리를 뗐어요' : '이미 떼어둔 워크트리가 있어요');
191
+ console.log(` ${checkout.path}`);
192
+ console.log(` head ${checkout.headSha.slice(0, 8)}`);
193
+ console.log(` 정리: gestalt pr checkout ${opts.id} --remove`);
194
+ });
195
+ }
196
+ finally {
197
+ engine.dispose();
198
+ }
199
+ });
200
+ }
201
+ export function prCommentCommand(opts) {
202
+ run(() => {
203
+ const engine = engineOf(opts);
204
+ try {
205
+ const body = readBody(opts.bodyFile);
206
+ if (!body.trim())
207
+ throw new PrError('본문이 비었어요. --body-file로 넘겨주세요', 1);
208
+ const pr = engine.comment(opts.id, {
209
+ author: actorOf(opts),
210
+ path: opts.path,
211
+ line: opts.line ? Number(opts.line) : undefined,
212
+ body,
213
+ replyTo: opts.replyTo,
214
+ });
215
+ const added = pr.comments[pr.comments.length - 1];
216
+ emit(added, opts.json, () => console.log(`코멘트 ${added.id} 추가`));
217
+ }
218
+ finally {
219
+ engine.dispose();
220
+ }
221
+ });
222
+ }
223
+ export function prCommentsCommand(opts) {
224
+ run(() => {
225
+ const engine = engineOf(opts);
226
+ try {
227
+ const pr = engine.get(opts.id);
228
+ if (!pr)
229
+ throw new PrError(`PR을 못 찾았어요: ${opts.id}`, 3);
230
+ const comments = opts.unresolved ? unresolvedComments(pr) : pr.comments;
231
+ emit(comments, opts.json, () => {
232
+ for (const c of comments) {
233
+ const at = c.line === null ? c.path : `${c.path}:${c.line}`;
234
+ const mark = c.resolved ? '해결' : '열림';
235
+ console.log(`[${c.id}] ${at} (${c.author}, ${mark})`);
236
+ console.log(c.body);
237
+ console.log('');
238
+ }
239
+ });
240
+ }
241
+ finally {
242
+ engine.dispose();
243
+ }
244
+ });
245
+ }
246
+ export function prResolveCommand(opts) {
247
+ run(() => {
248
+ const engine = engineOf(opts);
249
+ try {
250
+ const pr = engine.resolve(opts.id, opts.commentId, actorOf(opts));
251
+ emit(pr, opts.json, () => console.log(`코멘트 ${opts.commentId} 스레드를 닫았어요`));
252
+ }
253
+ finally {
254
+ engine.dispose();
255
+ }
256
+ });
257
+ }
258
+ const VERDICTS = {
259
+ approve: 'approve',
260
+ 'request-changes': 'request_changes',
261
+ comment: 'comment',
262
+ };
263
+ export function prReviewCommand(opts) {
264
+ run(() => {
265
+ const verdict = VERDICTS[opts.verdict];
266
+ if (!verdict) {
267
+ throw new PrError('판정은 approve, request-changes, comment 중 하나예요', 1);
268
+ }
269
+ const engine = engineOf(opts);
270
+ try {
271
+ const pr = engine.review(opts.id, {
272
+ reviewer: actorOf(opts),
273
+ verdict,
274
+ summary: readBody(opts.bodyFile).trim(),
275
+ });
276
+ emit(pr, opts.json, () => {
277
+ console.log(`판정을 남겼어요: ${opts.verdict} — 상태 ${pr.status}`);
278
+ console.log(` 라운드 ${pr.rounds[pr.rounds.length - 1].number}`);
279
+ });
280
+ }
281
+ finally {
282
+ engine.dispose();
283
+ }
284
+ });
285
+ }
286
+ export function prUpdateCommand(opts) {
287
+ run(() => {
288
+ const engine = engineOf(opts);
289
+ try {
290
+ const pr = engine.update(opts.id, opts.head);
291
+ emit(pr, opts.json, () => {
292
+ console.log(`head를 ${pr.headSha.slice(0, 8)}로 옮겼어요 — 상태 ${pr.status}`);
293
+ });
294
+ }
295
+ finally {
296
+ engine.dispose();
297
+ }
298
+ });
299
+ }
300
+ /**
301
+ * `gestalt pr edit <id>` — 제목과 본문을 고친다.
302
+ *
303
+ * 본문은 `--body-file`로만 받는다. `pr create`와 `pr comment`가 같은 이유로 그렇게
304
+ * 받는다 — 인자로 넘기면 셸이 한글과 백틱과 줄바꿈을 건드린다. 제목은 원래 인자로
305
+ * 받던 값이라 `--title` 그대로다.
306
+ *
307
+ * `--body-file`을 준 순간 본문은 그 파일 내용이다. 빈 파일이면 본문을 비운다 —
308
+ * 코멘트와 달리 여기서 빈 본문을 막지 않는 건 "잘못 쓴 본문을 지운다"가 실제로
309
+ * 있는 쓰임이어서다.
310
+ */
311
+ export function prEditCommand(opts) {
312
+ run(() => {
313
+ if (opts.title === undefined && opts.bodyFile === undefined) {
314
+ throw new PrError('고칠 것을 주세요 — --title이나 --body-file 중 하나는 있어야 해요', 1);
315
+ }
316
+ const engine = engineOf(opts);
317
+ try {
318
+ const pr = engine.edit(opts.id, {
319
+ ...(opts.title !== undefined ? { title: opts.title } : {}),
320
+ ...(opts.bodyFile !== undefined ? { body: readBody(opts.bodyFile) } : {}),
321
+ }, actorOf(opts));
322
+ emit(pr, opts.json, () => {
323
+ console.log(`PR ${pr.id}을 고쳤어요 — 상태 ${pr.status}`);
324
+ console.log(` ${pr.title}`);
325
+ });
326
+ }
327
+ finally {
328
+ engine.dispose();
329
+ }
330
+ });
331
+ }
332
+ export function prMergeCommand(opts) {
333
+ run(() => {
334
+ const engine = engineOf(opts);
335
+ try {
336
+ const before = engine.get(opts.id);
337
+ const unresolved = before ? unresolvedCount(before) : 0;
338
+ const pr = engine.merge(opts.id, actorOf(opts), { deleteBranch: opts.deleteBranch });
339
+ emit(pr, opts.json, () => {
340
+ console.log(`PR을 머지했어요: ${pr.id}`);
341
+ if (unresolved > 0)
342
+ console.log(` 미해결 스레드 ${unresolved}개가 남은 채로 머지했어요`);
343
+ });
344
+ }
345
+ finally {
346
+ engine.dispose();
347
+ }
348
+ });
349
+ }
350
+ export function prCloseCommand(opts) {
351
+ run(() => {
352
+ const engine = engineOf(opts);
353
+ try {
354
+ const pr = engine.closePr(opts.id, actorOf(opts), opts.reason ?? '');
355
+ emit(pr, opts.json, () => console.log(`PR을 닫았어요: ${opts.id}`));
356
+ }
357
+ finally {
358
+ engine.dispose();
359
+ }
360
+ });
361
+ }
362
+ /**
363
+ * `gestalt pr prune` — 붙잡아 둘 이유가 끝난 ref를 놓는다.
364
+ *
365
+ * `refs/gestalt/` 아래는 지금까지 늘기만 했다. 무엇을 언제 놓는지는 엔진의 `prune`
366
+ * 주석에 있다. 되돌릴 수 없는 갈래(체크아웃 자국)는 `--checkouts`로 뜻을 밝혀야 놓는다.
367
+ */
368
+ export function prPruneCommand(opts) {
369
+ run(() => {
370
+ const engine = engineOf(opts);
371
+ try {
372
+ const result = engine.prune({ checkouts: opts.checkouts, dryRun: opts.dryRun });
373
+ emit(result, opts.json, () => {
374
+ const verb = result.dryRun ? '놓을 참이에요' : '놓았어요';
375
+ console.log(`ref ${result.released.length}개를 ${verb}`);
376
+ for (const ref of result.released)
377
+ console.log(` ${ref}`);
378
+ for (const k of result.kept)
379
+ console.log(` 남김 ${k.prId} — ${k.reason}`);
380
+ if (!opts.checkouts) {
381
+ console.log(' 체크아웃 자국은 그대로예요. 놓으려면 --checkouts를 붙여주세요');
382
+ }
383
+ });
384
+ }
385
+ finally {
386
+ engine.dispose();
387
+ }
388
+ });
389
+ }
390
+ /**
391
+ * `--repo-root`가 지금 자리와 다른 레포를 가리키면 막는다.
392
+ *
393
+ * `pr serve`는 뜨면서 그 경로를 뷰어 목록에 영구히 넣는다. 목록에 넣는 문을 좁게
394
+ * 둔 근거가 "사람이 그 레포에서 웹 UI를 직접 띄운 순간"인데, `--repo-root`를 그대로
395
+ * 받으면 그 전제가 깨진다 — 에이전트가 셸로 `pr serve --repo-root /남의/레포
396
+ * --no-browser`를 한 번 돌리면 그 레포가 인증 없는 뷰어 목록에 들어간다. 이후 전혀
397
+ * 다른 레포에서 serve를 띄워도 그 레포의 diff와 코멘트가 계속 나간다.
398
+ *
399
+ * 그래서 `--repo-root`는 지금 자리와 같은 레포를 가리킬 때만 받는다. 워크트리나
400
+ * 하위 디렉토리를 가리키는 쓰임은 그대로 살고(키가 같다), 남의 레포를 넣는 쓰임만
401
+ * 닫힌다. 다른 레포를 보려면 거기서 한 번 띄우면 된다.
402
+ *
403
+ * 목록에 넣는 호출 자체는 `local-pr-web/engine.ts`에 있다. 거기서 "cwd만 등록하고
404
+ * 나머지는 조회만"으로 가르는 게 더 좁은 문이지만 그건 이 파일 밖이다.
405
+ *
406
+ * 서버를 안 띄우고 이 판단만 볼 수 있게 내보낸다. 통과 갈래를 `prServeCommand`로
407
+ * 확인하려면 진짜 서버가 떠 버린다.
408
+ */
409
+ export function assertServeRoot(repoRoot) {
410
+ const cwd = process.cwd();
411
+ if (resolve(repoRoot) === resolve(cwd))
412
+ return;
413
+ let same;
414
+ try {
415
+ same = repoKey(repoRoot) === repoKey(cwd);
416
+ }
417
+ catch {
418
+ same = false;
419
+ }
420
+ if (same)
421
+ return;
422
+ throw new PrError(`--repo-root가 지금 자리와 다른 레포를 가리켜요: ${repoRoot}\n` +
423
+ '웹 UI는 띄우는 순간 그 레포를 인증 없는 뷰어 목록에 넣어요. 그 레포로 옮겨가서 띄워주세요', 4);
424
+ }
425
+ /** `gestalt pr serve` — 브라우저에서 PR을 읽는 읽기 전용 웹 UI. 코멘트 작성은 CLI 몫으로 남긴다 */
426
+ export async function prServeCommand(opts) {
427
+ const repoRoot = resolve(opts.repoRoot ?? process.cwd());
428
+ if (opts.repoRoot !== undefined) {
429
+ try {
430
+ assertServeRoot(repoRoot);
431
+ }
432
+ catch (e) {
433
+ console.error(e instanceof Error ? e.message : String(e));
434
+ process.exit(e instanceof PrError ? e.exitCode : 1);
435
+ return;
436
+ }
437
+ }
438
+ const engine = new PrWebEngine();
439
+ try {
440
+ const result = await engine.start({
441
+ repoRoot,
442
+ port: opts.port,
443
+ openBrowser: !opts.noBrowser,
444
+ });
445
+ console.log(`\n로컬 PR 웹 UI: ${result.url}`);
446
+ console.log(result.message);
447
+ console.log('\nCtrl+C로 멈춥니다.\n');
448
+ // 서버의 SIGINT 핸들러가 프로세스를 끝낼 때까지 살려둔다
449
+ await new Promise(() => {
450
+ /* Ctrl+C까지 대기 */
451
+ });
452
+ }
453
+ catch (err) {
454
+ const msg = err instanceof Error ? err.message : String(err);
455
+ console.error(`웹 UI를 못 띄웠어요: ${msg}`);
456
+ process.exit(1);
457
+ }
458
+ }
459
+ /**
460
+ * `gestalt pr repos` — 웹 UI가 열어 주는 레포 목록.
461
+ *
462
+ * `unregister`가 키를 받으므로 그 키를 어디선가 볼 수 있어야 한다. 무엇이 인증 없는
463
+ * 뷰어에 실려 있는지 확인하는 자리이기도 하다.
464
+ */
465
+ export function prReposCommand(opts) {
466
+ run(() => {
467
+ const repos = listRepos();
468
+ emit(repos, opts.json, () => {
469
+ if (repos.length === 0) {
470
+ console.log('등록된 레포가 없어요');
471
+ return;
472
+ }
473
+ for (const r of repos)
474
+ console.log(`${r.key} ${r.name} ${r.path}`);
475
+ });
476
+ });
477
+ }
478
+ /** `gestalt pr unregister <key>` — 그 레포를 웹 UI 목록에서 뺀다. 레포 자체는 안 건드린다 */
479
+ export function prUnregisterCommand(opts) {
480
+ run(() => {
481
+ const gone = unregisterRepo(opts.key);
482
+ if (!gone)
483
+ throw new PrError(`목록에 없는 키예요: ${opts.key}`, 3);
484
+ emit({ key: opts.key, removed: true }, opts.json, () => {
485
+ console.log(`목록에서 뺐어요: ${opts.key}`);
486
+ });
487
+ });
488
+ }
489
+ //# sourceMappingURL=pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { loadConfig } from '../../core/config.js';
2
2
  import { EventStore } from '../../events/store.js';
3
- import { createAdapter } from '../../llm/factory.js';
3
+ import { createAdapter, createTierAdapter } from '../../llm/factory.js';
4
4
  import { InterviewEngine } from '../../interview/engine.js';
5
5
  import { SpecGenerator } from '../../spec/generator.js';
6
6
  import { logger } from '../../core/logger.js';
@@ -13,7 +13,7 @@ export async function specCommand(sessionId, options) {
13
13
  }
14
14
  const eventStore = new EventStore(config.dbPath);
15
15
  const llm = createAdapter(config.llm);
16
- const engine = new InterviewEngine(llm, eventStore);
16
+ const engine = new InterviewEngine(llm, eventStore, createTierAdapter(config.llm, 'frugal'));
17
17
  const generator = new SpecGenerator(llm, eventStore);
18
18
  try {
19
19
  const session = engine.getSession(sessionId);
@@ -1 +1 @@
1
- {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../../../src/cli/commands/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB,EAAE,OAA4B;IAC/E,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC;IAE1F,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CACX,+FAA+F,CAChG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,qCAAqC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;QAEzE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;YAAS,CAAC;QACT,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../../../src/cli/commands/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB,EAAE,OAA4B;IAC/E,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC;IAE1F,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CACX,+FAA+F,CAChG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,GAAG,EAAE,UAAU,EAAE,iBAAiB,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC7F,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,qCAAqC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;QAEzE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;YAAS,CAAC;QACT,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,SAAS,IAAI,OAAO,CAiGnC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgCpC,wBAAgB,SAAS,IAAI,OAAO,CAiNnC"}
@@ -10,6 +10,7 @@ import { updateCommand } from './commands/update.js';
10
10
  import { usageReportCommand } from './commands/usage-report.js';
11
11
  import { humanizeCheckCommand } from './commands/humanize-check.js';
12
12
  import { getVersion } from '../core/version.js';
13
+ import { prCheckoutCommand, prCloseCommand, prCommentCommand, prCommentsCommand, prCreateCommand, prDiffCommand, prEditCommand, prListCommand, prMergeCommand, prReposCommand, prResolveCommand, prReviewCommand, prPruneCommand, prServeCommand, prShowCommand, prUnregisterCommand, prUpdateCommand, } from './commands/pr.js';
13
14
  export function createCli() {
14
15
  const program = new Command();
15
16
  program
@@ -74,6 +75,90 @@ export function createCli() {
74
75
  noBrowser: options.browser === false,
75
76
  });
76
77
  });
78
+ const pr = program
79
+ .command('pr')
80
+ .description('로컬 PR 리뷰 — 에이전트끼리 주고받는 자리')
81
+ .option('--repo-root <path>', 'Repository root (defaults to cwd)')
82
+ .option('--author <actor>', '누가 하는지 (예: codex:worker-2). 없으면 GESTALT_ACTOR')
83
+ .option('--json', '에이전트가 파싱할 JSON으로');
84
+ const inherited = (cmd) => (cmd.parent?.opts() ?? {});
85
+ pr.command('create')
86
+ .description('현재 HEAD로 PR을 만든다')
87
+ .requiredOption('--title <title>', 'PR 제목')
88
+ .option('--base <ref>', '갈라져 나온 기준 (기본 main)')
89
+ .option('--head <ref>', '리뷰 대상 (기본 HEAD)')
90
+ .option('--body-file <path>', '본문 파일. -면 stdin')
91
+ .action((o, cmd) => prCreateCommand({ ...inherited(cmd), ...o }));
92
+ pr.command('list')
93
+ .description('PR 목록')
94
+ .option('--status <status>', 'open | changes_requested | merged | closed')
95
+ .action((o, cmd) => prListCommand({ ...inherited(cmd), ...o }));
96
+ pr.command('show <id>')
97
+ .description('PR 상세 — 라운드와 미해결 스레드')
98
+ .action((id, o, cmd) => prShowCommand({ ...inherited(cmd), ...o, id }));
99
+ pr.command('diff <id>')
100
+ .description('PR의 diff')
101
+ .action((id, o, cmd) => prDiffCommand({ ...inherited(cmd), ...o, id }));
102
+ pr.command('checkout <id>')
103
+ .description('PR head를 임시 워크트리로 떼어낸다 — 코드를 일부러 깨고 돌려볼 자리')
104
+ .option('--remove', '떼어둔 워크트리를 지운다')
105
+ .option('--force', '--remove와 함께: 커밋 안 된 변경이 있어도 지운다')
106
+ .action((id, o, cmd) => prCheckoutCommand({ ...inherited(cmd), ...o, id }));
107
+ pr.command('comment <id>')
108
+ .description('인라인 코멘트를 단다')
109
+ .requiredOption('--path <path>', '파일 경로')
110
+ .option('--line <number>', '라인 번호. 없으면 파일 전반')
111
+ .requiredOption('--body-file <path>', '본문 파일. -면 stdin')
112
+ .option('--reply-to <commentId>', '스레드에 답글')
113
+ .action((id, o, cmd) => prCommentCommand({ ...inherited(cmd), ...o, id }));
114
+ pr.command('comments <id>')
115
+ .description('코멘트 목록')
116
+ .option('--unresolved', '안 닫힌 것만')
117
+ .action((id, o, cmd) => prCommentsCommand({ ...inherited(cmd), ...o, id }));
118
+ pr.command('resolve <id> <commentId>')
119
+ .description('코멘트 스레드를 닫는다')
120
+ .action((id, commentId, o, cmd) => prResolveCommand({ ...inherited(cmd), ...o, id, commentId }));
121
+ pr.command('review <id>')
122
+ .description('판정을 남긴다')
123
+ .requiredOption('--verdict <verdict>', 'approve | request-changes | comment')
124
+ .option('--body-file <path>', '요약 파일. -면 stdin')
125
+ .action((id, o, cmd) => prReviewCommand({ ...inherited(cmd), ...o, id }));
126
+ pr.command('update <id>')
127
+ .description('head를 지금 커밋으로 옮긴다')
128
+ .option('--head <ref>', '옮길 대상')
129
+ .action((id, o, cmd) => prUpdateCommand({ ...inherited(cmd), ...o, id }));
130
+ pr.command('edit <id>')
131
+ .description('제목과 본문을 고친다. 리뷰 판정도 라운드도 안 건드린다')
132
+ .option('--title <title>', '새 제목')
133
+ .option('--body-file <path>', '새 본문 파일. -면 stdin')
134
+ .action((id, o, cmd) => prEditCommand({ ...inherited(cmd), ...o, id }));
135
+ pr.command('merge <id>')
136
+ .description('머지한다. 승인이 없어도 막지 않는다')
137
+ .option('--delete-branch', '머지 뒤 브랜치를 지운다')
138
+ .action((id, o, cmd) => prMergeCommand({ ...inherited(cmd), ...o, id }));
139
+ pr.command('close <id>')
140
+ .description('PR을 닫는다')
141
+ .option('--reason <text>', '닫는 이유')
142
+ .action((id, o, cmd) => prCloseCommand({ ...inherited(cmd), ...o, id }));
143
+ pr.command('prune')
144
+ .description('붙잡아 둘 이유가 끝난 ref를 놓는다 — 머지된 PR의 base·head')
145
+ .option('--checkouts', '체크아웃 자국도 놓는다. 되돌릴 수 없어 기본은 남긴다')
146
+ .option('--dry-run', '무엇을 놓을지만 보여준다')
147
+ .action((o, cmd) => prPruneCommand({ ...inherited(cmd), ...o }));
148
+ pr.command('serve')
149
+ .description('브라우저에서 PR을 읽는 웹 UI를 띄운다 (읽기 전용)')
150
+ .option('--port <number>', '서버 포트 (기본 7892)', parseInt)
151
+ .option('--no-browser', '브라우저를 자동으로 열지 않는다')
152
+ .action(async (o, cmd) => {
153
+ const opts = { ...inherited(cmd), ...o };
154
+ await prServeCommand({ ...opts, noBrowser: opts.browser === false });
155
+ });
156
+ pr.command('repos')
157
+ .description('웹 UI가 열어 주는 레포 목록')
158
+ .action((o, cmd) => prReposCommand({ ...inherited(cmd), ...o }));
159
+ pr.command('unregister <key>')
160
+ .description('그 레포를 웹 UI 목록에서 뺀다. 레포 자체는 안 건드린다')
161
+ .action((key, o, cmd) => prUnregisterCommand({ ...inherited(cmd), ...o, key }));
77
162
  program
78
163
  .command('humanize-check')
79
164
  .description('Judge a humanized draft against the rulebook (exit 0 pass / 1 warn / 2 abort)')