deel-local-cli 1.17.9 → 1.19.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.
@@ -16,7 +16,248 @@
16
16
  // 낱말과 점수. 큰 점수일수록 그 모드라는 증거가 강하다는 뜻이다.
17
17
  //
18
18
  // 한국어를 먼저 두되 영어도 같이 본다 — 오류 메시지를 그대로 붙여넣는 일이 흔하다.
19
- const 표 = {
19
+ /*
20
+ * 검사가 이 표를 그대로 읽는다 (test/자동모드.test.js).
21
+ *
22
+ * 규칙을 넣기만 하고 그게 실제로 걸리는지는 아무도 안 본다 — 안 걸리는 규칙은
23
+ * 없는 것과 같고, 그런데도 화면은 멀줦하다(다음 규칙이 받아 그럴듯한 모드를 낸다).
24
+ * 그래서 밖으로 내놓고, 규칙 하나하나가 실제 문장에 걸리는지를 재게 한다.
25
+ */
26
+ /*
27
+ * ── 「… 좀 해줘」 의 빈칸 ────────────────────────────────────────────────
28
+ *
29
+ * 낱말 뒤에 붙는 토씨를 `점검(해|좀|을|이)` 처럼 **붙여서만** 봤다. 그런데
30
+ * 한국말에서 부탁할 때는 그 사이가 거의 언제나 벌어진다 —
31
+ *
32
+ * "점검 좀 해줘" · "설명 좀 해줘" · "수정 좀 해줘" · "구현 좀 해줘"
33
+ *
34
+ * 이 꼴이 전부 **하나도 안 걸려서** 종합 모드에 그대로 남았다. 규칙이 안
35
+ * 걸리면 아무 데서도 안 터지므로(점수만 안 오른다) 여태 아무도 몰랐다.
36
+ * 자동모드.test.js 의 죽은 규칙 검사가 「이 규칙에 걸리는 실제 문장이 없다」
37
+ * 로 잡아 줬다.
38
+ *
39
+ * 그래서 '좀' **앞에만** 빈칸을 열어 둔다(`\s*좀`). 토씨 전체에 열면
40
+ * "점검 이력" 이 「점검 이」 로 걸리는 식으로 넓어진다 — 가르는 자리가
41
+ * 미묘해서, 여는 것도 좁게 연다.
42
+ */
43
+ /*
44
+ * ── 영어 시킴말 ─────────────────────────────────────────────────────────
45
+ *
46
+ * 여기 한 번만 적고 두 자리에서 쓴다 — 아래 code 점수표와, 파일 맨 아래의
47
+ * 손대라했나. 두 벌로 두면 한쪽만 늘어나고, 실제로 그렇게 어긋나 있었다.
48
+ *
49
+ * 손대라했나 는 build·create·make·develop·scaffold 를 다 알았다. 그런데
50
+ * code 점수표의 영어는 `implement|add|fix|write` 넷이 2점씩인 것과, 따로 선
51
+ * `rename` 3점이 전부였다. code 문턱은 3이라 **2점짜리 하나로는 절대 못
52
+ * 넘는다** — 무늬가 아는 동사 스무 개를 재 보니 `rename` 하나만 넘고,
53
+ * 저 넷이 2점, 나머지 열다섯이 0점이었다.
54
+ *
55
+ * "Build a complete work request and approval web application."
56
+ * 손대라했나 → 참 code 점수 → 0
57
+ *
58
+ * 그래서 영어로 시킨 일은 무슨 말이든
59
+ * 종합에 남았고 — 그것만이면 탈이 없다 — **긴 명세에서는 졌다.** 지나가던
60
+ * `error`·`failed` 가 6점이라, 만들라는 3,577자 지시문이 디버그로 갔다.
61
+ * 2차 리뷰가 「설계 낱말이 없는 명세는 그대로 디버그로 간다」 고 짚은 자리가
62
+ * 이것이고, 증상이 아니라 이쪽이 뿌리였다.
63
+ *
64
+ * 점수를 맞춰 두면 1·2등이 붙어서, 원래 있던 「비기면 안 고른다」 규칙이
65
+ * 알아서 받아 낸다. 새 울타리를 하나 더 세우는 것보다 이쪽이 낫다.
66
+ *
67
+ * 넓히되 자리는 그대로다. 첫머리에서만 본다 — 문장 가운데 낱말은 시킴말이
68
+ * 아니다. 「the build is broken」 이 code 로 가면 넓힌 것이 아니라 망가뜨린
69
+ * 것이다. 번호·목록 표시 뒤도 첫머리로 친다 — 붙여 넣는 명세가 그 꼴이다.
70
+ *
71
+ * ── 어디까지가 「첫머리」 인가 ───────────────────────────────────────────
72
+ *
73
+ * 처음엔 `[.!?
74
+ ]\s*` 였다. 마침표 뒤 **빈칸 0개**도 문장 첫머리로 친다는
75
+ * 뜻이었고, 3차 리뷰가 그 자리에서 제일 나쁜 것을 찾아냈다 —
76
+ *
77
+ * "Explain user.delete in detail." → code 모드
78
+ *
79
+ * `user.delete` 의 `delete` 가 시킴말이 되고, 설명해 달라는 말이 파일을
80
+ * 고치는 모드로 갔다. 묻기 점수는 4점이나 있었는데 「고치라는 말」 로 잡혀
81
+ * 후보에서 빠졌다 — 이 파일 맨 위가 걱정한 바로 그 모양이다.
82
+ *
83
+ * 그래서 셋을 죈다.
84
+ * · 마침표 뒤에 **빈칸이 하나는 있어야** 다음 문장이다.
85
+ * · 홑글자 뒤의 마침표는 문장 끝이 아니라 **약자**다 (`e.g. create`).
86
+ * · 시킴말 뒤에 실패말이 오면 그건 목적어가 아니라 **주어**다. 영어
87
+ * 시킴말 뒤에는 목적어가 오지 과거분사가 오지 않는다 —
88
+ * `Build failed with exit code 1.` 은 붙여 넣는 빌드 오류의 첫 줄이고,
89
+ * 그게 code 로 가면 고장 신고가 만들기 지시가 된다.
90
+ *
91
+ * 글 처음의 들여쓰기는 받아 준다(`^\s*`). 번호·목록 갈래는 처음부터
92
+ * 그랬는데 맨낱말 갈래만 안 그래서, 빈칸 두 칸으로 시작하는 지시문이
93
+ * 통째로 0점이었다.
94
+ *
95
+ * 정규식 리터럴로 적는다. 글자열을 이어 붙여 new RegExp 에 넣으면 홑따옴표
96
+ * 안에서 역빗금이 사라지고 낱말 경계가 백스페이스 글자가 된다 — 검사에서
97
+ * 잡히기 전까지 조용히 아무것도 안 맞는다. 실제로 그렇게 났다.
98
+ *
99
+ * ── 약자 목록에는 「뒤에 말이 이어지는 것」만 ───────────────────────────
100
+ *
101
+ * 8차 리뷰가 셋을 짚었고, 같은 부류를 하나 더 찾아 넷을 뺐다. 약자 목록을
102
+ * 넓히면서 **문장을 맺는 자리에 더 자주 오는 말**을 같이 넣어 버렸다.
103
+ *
104
+ * "No. Fix the bug." → `No.` 가 약자
105
+ * "Install git, node, etc. Build it." → `etc.` 가 약자
106
+ * "Ship it to Acme Inc. Create the report." → `Inc.` 가 약자
107
+ * "Sold to Acme Ltd. Build the invoice." → `Ltd.` 가 약자
108
+ *
109
+ * 넷 다 마침표가 진짜 문장 끝인데 약자로 읽혀 **뒤 문장이 통째로 죽었다.**
110
+ *
111
+ * 남길 것과 뺄 것을 가르는 것은 **그 마침표 뒤에 무엇이 오느냐**다.
112
+ * `e.g.` · `i.e.` · `Fig.` · `Dr.` · `Mr.` 는 뒤에 말이 이어지는 자리에 오는
113
+ * 약자라 마침표를 문장 끝으로 읽으면 안 된다. `No.` · `etc.` · `Inc.` ·
114
+ * `Ltd.` 는 반대로 **문장을 맺는 자리**에 훨씬 자주 온다 — 지키려던 것보다
115
+ * 잃는 것이 크면 그건 울타리가 아니라 벽이다. 그래서 뺀다.
116
+ *
117
+ * ── 공손말에 쉼표가 붙는다 ──────────────────────────────────────────────
118
+ *
119
+ * `please\s+` 는 빈칸만 받았다. 그런데 영어에서 제일 흔한 공손꼴이
120
+ * `Please, could you …` 다 — 쉼표가 하나 붙었다고 0점이 됐다.
121
+ * `please\s*,?\s+` 로 쉼표를 받아 준다. `could you` 뒤도 마찬가지다.
122
+ *
123
+ * ── 2번 갈래의 실패말은 로그꼴일 때만 막는다 ────────────────────────────
124
+ *
125
+ * 실패말 차단 목록이 두 갈래에서 달랐다. 1번 갈래(`build`·`create`…)는
126
+ * 이름씨꼴(`errors` · `failure` · `crash` · `timeout`)까지 막는데, 2번
127
+ * 갈래(`delete`·`rename`·`change`…)는 움직씨꼴만 막았다. 그래서
128
+ *
129
+ * "Delete error: permission denied" → 시킴말
130
+ *
131
+ * 같은 로그 첫 줄이 지시로 읽혔다. 그렇다고 2번 갈래에 이름씨꼴을 그냥
132
+ * 넣으면 안 된다 — `Fix errors.` · `Fix error in auth module.` 은 **진짜
133
+ * 지시**다. 1번 갈래와 달리 2번 갈래의 낱말들은 그 이름씨를 목적어로 받는다.
134
+ *
135
+ * 갈라 주는 것은 **뒤에 오는 쌍점·여는 괄호**다. 로그는 `error:` ·
136
+ * `crash (core dumped)` 꼴로 적히고, 지시문은 그렇게 안 적힌다.
137
+ * 그래서 2번 갈래의 이름씨꼴 차단은 `[:(]` 가 뒤따를 때만 건다.
138
+ * 그 목록에서 `broken` 이 빠져 있었다(9차 리뷰) — 1번 갈래는 아는 낱말인데
139
+ * 여기만 몰라서 `Rewrite broken: exit status 1` 이 지시로 읽혔다.
140
+ *
141
+ * ── 동사 뒤에 쌍점이 오면 그건 꼬리표다 ─────────────────────────────────
142
+ *
143
+ * 리뷰를 기다리는 사이에 붙여 넣을 법한 글 서른여덟 줄을 죽 재 봤다.
144
+ * 일곱이 시킴말로 읽혔고, 다섯이 한 가지 모양이었다.
145
+ *
146
+ * "fix: 값이 아닌 것을 가렸습니다" ← 이 저장소의 커밋 메시지다
147
+ * "Change-Id: I8f2c1a" git 꼬리표
148
+ * "Remove-Item : Cannot find path" 파워셸 오류
149
+ * "Update available: 1.2.3 → 1.3.0" npm 알림
150
+ * "add(a, b) { return a + b; }" 코드 한 줄
151
+ *
152
+ * 시킴말 뒤에는 **목적어**가 온다. 쌍점이 오면 그건 꼬리표고, 여는 괄호가
153
+ * 바로 붙으면 그건 부르는 짓이다. 위의 실패말 목록과 같은 생각인데,
154
+ * 저쪽은 「어떤 낱말이 오나」 를 보고 이쪽은 「어떤 글자가 오나」 를 본다.
155
+ *
156
+ * 쌍점은 **첫 낱말 바로 뒤**일 때만 꼬리표다. `Fix the bug: it is in the
157
+ * parser.` 처럼 목적어를 끼고 오는 쌍점은 그냥 지시문이다.
158
+ *
159
+ * ── 붙여 넣는 것이 로그만은 아니다 ─────────────────────────────────────
160
+ *
161
+ * SQL 도 시킴꼴로 시작한다.
162
+ *
163
+ * delete from users where id = 1;
164
+ * update accounts set balance = 0 where id = 3
165
+ *
166
+ * 「이 쿼리가 왜 이러냐」 고 물으려고 붙였는데 파일을 고치는 모드로 갔다.
167
+ * 손대라는 말로 읽히면 읽기 전용 모드가 후보에서 통째로 빠진다.
168
+ *
169
+ * 갈라 주는 것은 `from` 이 아니라 **뒤에 SQL 이 이어지느냐**다.
170
+ * `Delete from the list.` 는 그대로 지시문이고, `delete from users where`
171
+ * 는 아니다. 두 동사(`delete`·`update`)만 우리 목록과 겹치므로 그 둘에만
172
+ * 건다 — `insert`·`select` 는 애초에 여기 없다.
173
+ *
174
+ * ── 이음말 뒤도 첫머리다 ───────────────────────────────────────────────
175
+ *
176
+ * 같은 자리에서 반대쪽 구멍이 하나 나왔다.
177
+ *
178
+ * "First, set up the project. Then add tests." → 0점
179
+ *
180
+ * 붙여 넣는 명세가 딱 이 꼴인데 `First,` · `Then` 이 앞에 있다고 첫머리가
181
+ * 아니게 됐다. 번호·목록 표시를 첫머리로 치는 것과 같은 까닭으로 받는다.
182
+ * 이음말 뒤가 동사가 아니면(`Now the build is broken.`) 그대로 안 걸린다.
183
+ *
184
+ * ── 만들 것이 계획이면 그건 계획이다 ────────────────────────────────────
185
+ *
186
+ * 같은 뜻을 한국어·영어로 나란히 스물여섯 짝 재 보다 찾았다.
187
+ *
188
+ * "계획 세워 줘" → plan
189
+ * "Make a plan for this." → **code**
190
+ *
191
+ * 시킴꼴인 것은 맞다. 그런데 이 규칙이 손대라했나 의 영어 쪽이기도 해서,
192
+ * 걸리는 순간 읽기 전용 모드(plan·architect·ask·inspect)가 **후보에서
193
+ * 통째로 빠진다.** 계획을 달라는 말에 계획 모드가 남을 수가 없었다.
194
+ *
195
+ * 갈라 주는 것은 동사가 아니라 **목적어**다. 만들 것이 계획·로드맵·
196
+ * 전략이면 그건 계획 모드가 내놓는 것이지 파일을 고쳐서 되는 일이 아니다.
197
+ *
198
+ * ── 검사에 쓰던 낱말이 목록에 없었다 ────────────────────────────────────
199
+ *
200
+ * 8차 리뷰를 재 보다 찾았다. 검사 쪽이 `Rewrite what is left of the parser.`
201
+ * 를 **쓰기 지시문의 보기**로 쓰고 있는데, 정작 `rewrite` 가 목록에 없어
202
+ * 0점이었다. `write` 는 있지만 낱말 경계 때문에 `rewrite` 안에서는 안 걸린다.
203
+ *
204
+ * 0점이면 「읽기 점수가 안 붙는다」 가 언제나 참이라, 그 검사는 이 낱말에
205
+ * 대해 아무것도 안 재고 있었다. 고치는 것은 있는 자리에 넣는 일이다 —
206
+ * 다시 쓰는 것은 있는 것을 고치는 일이라
207
+ * 「고쳐 쓰는 말」 갈래다. 처음엔 손대는 갈래에 뒀는데, 그러면 계획 울타리를
208
+ * 못 받아 `Rewrite the plan.` 이 코드로 갔다(9차 리뷰) — `write` 와 짝이
209
+ * 맞아야 하는 자리다.
210
+ *
211
+ * 짓는 갈래(1번)와 고쳐 쓰는 갈래(2번)에 건다. 3번의 `implement`·`add` 는
212
+ * 반대다 — "Implement the plan we agreed on." 은 계획을 **실행**하라는
213
+ * 말이고, "Add a plan field to the schema." 의 plan 은 목적어가 아니라
214
+ * 딸린 이름씨다. 둘 다 코드가 맞다.
215
+ *
216
+ * ── 계획거리 뒤에 무엇이 와야 계획인가 ──────────────────────────────────
217
+ *
218
+ * 그 울타리를 「문장 끝 또는 전치사」 로만 열어 뒀더니, 때를 가리키는 말
219
+ * 한 마디만 붙어도 빠져나갔다(10차 리뷰).
220
+ *
221
+ * "Update the plan now." "Create a plan today." "Make a plan first."
222
+ *
223
+ * 때말 여덟과 **사이를 띄운 줄표**(`Make a plan - urgently`)를 같이 받는다.
224
+ * 줄표는 띄웠을 때만 구분자다 — `Update the plan-file.` 은 그대로 코드다.
225
+ * 계획거리 앞에 붙임표가 오는 꼴(`an action-plan`)도 계획거리로 친다.
226
+ *
227
+ * ── 실패말이 이름의 일부면 그건 로그가 아니다 ───────────────────────────
228
+ *
229
+ * 실패말 목록은 두 층이다. 움직씨꼴(`failed`·`crashed`)은 뒤에 아무 문장
230
+ * 부호나 와도 로그로 치고, 이름씨꼴(`errors`·`broken`)은 1번 갈래에서만
231
+ * 막았다. 그런데 그 이름씨 층이 마침표와 붙임표를 통째로 구분자로 쳤다.
232
+ *
233
+ * "Build errors.json" → 0점 `.json` 의 점을 문장 끝으로 읽었다
234
+ * "Create error-handler.js" → 0점 붙임표를 로그 구분자로 읽었다
235
+ * "Update crash-report.md" → 0점
236
+ *
237
+ * 이 파일 위쪽이 마침표에서 배운 것과 같다 — **점 뒤에 낱말이 붙어 있으면
238
+ * 그건 문장 끝이 아니다.** 줄표도 사이를 띄웠을 때만 구분자다.
239
+ *
240
+ * 반대쪽으로는 2·3번 갈래가 쌍점과 여는 괄호만 막고 있어서, 같은 로그가
241
+ * 어느 동사로 시작하느냐로 갈렸다.
242
+ *
243
+ * 그 자리를 줄표로만 메웠더니 마침표와 전치사꼴이 남았다(11차 리뷰).
244
+ *
245
+ * "Rewrite broken with exit code 1" "Modify broken."
246
+ *
247
+ * `broken` 은 이름씨가 아니라 **그림씨**다. `Fix errors.` 는 오류를
248
+ * 고치라는 말이지만 `Modify broken.` 은 아무 말도 아니다 — 세 갈래에서
249
+ * 다 1번 갈래와 같은 잣대를 받는다. 뒤에 이름씨가 오면(`Fix broken
250
+ * tests.`) 그건 여전히 꾸밈말이라 그대로 지시문이다.
251
+ *
252
+ * "Build broken - exit status 1" → 안 걸림 (1번 갈래)
253
+ * "Rewrite broken - exit status 1" → **걸림** (2번 갈래)
254
+ *
255
+ * 세 갈래에 같은 「띄운 줄표」 잣대를 넣어 맞춘다.
256
+ */
257
+ const 영어시킴말 =
258
+ /(?:^\s*|(?<!\b(?:e\.g|i\.e|vs|cf|approx|Fig|Dr|Mr|Mrs|Ms|St|Jr|Sr))[.!?]\s+|\n\s*|^\s*\d+[.)]\s*|^\s*[-*]\s*)(?:(?:first|then|next|after\s+that|also|now|finally|second|third|lastly|afterwards?)\s*,?\s+)?(?:please\s*,?\s+)?(?:(?:could|can|would|will)\s+(?:you|we)\s*,?\s+)?(?:please\s*,?\s+)?(?:(?:build|make|create|update|write|migrate|generate|set\s*up)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|(?:failures?|errors?|broken|crash|crashes|timeouts?)\b(?=\s*(?:[,:;!?()\[\]]|$)|\s*\.(?!\w)|\s+-\s|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)))(?!(?:[ \t]+[\w'-]+){0,3}[ \t]+(?:[\w']+-)*(?:plans?|roadmaps?|strateg(?:y|ies)|outlines?)(?=[ \t]*(?:[!?,;:)]|\.(?!\w)|$)|[ \t]+-[ \t]|[ \t]+(?:now|today|tonight|tomorrow|first|soon|asap|again)\b|[ \t]+(?:for|to|of|on|about|around|that|which|we|with|before|after|regarding|covering)\b))|(?:modify|change|develop|rewrite)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|broken\b(?=\s*(?:[,:;!?()\[\]]|$)|\s*\.(?!\w)|\s+-\s|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|(?:failures?|errors?|crash|crashes|timeouts?)\b(?:\s*[:(]|\s+-\s)))(?!(?:[ \t]+[\w'-]+){0,3}[ \t]+(?:[\w']+-)*(?:plans?|roadmaps?|strateg(?:y|ies)|outlines?)(?=[ \t]*(?:[!?,;:)]|\.(?!\w)|$)|[ \t]+-[ \t]|[ \t]+(?:now|today|tonight|tomorrow|first|soon|asap|again)\b|[ \t]+(?:for|to|of|on|about|around|that|which|we|with|before|after|regarding|covering)\b))|(?:implement|add|fix|refactor|remove|delete|rename|scaffold)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|broken\b(?=\s*(?:[,:;!?()\[\]]|$)|\s*\.(?!\w)|\s+-\s|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|(?:failures?|errors?|crash|crashes|timeouts?)\b(?:\s*[:(]|\s+-\s))))(?!\()(?![-\w]*[ \t]*:)(?![ \t]+[\w.-]+[ \t]*:[ \t])(?!(?<=\bdelete)\s+from\s+[\w."`]+\s*(?:where\b|order\s+by\b|limit\b|;|$))(?!(?<=\bupdate)\s+[\w."`]+\s+set\b)/im;
259
+
260
+ export const 표 = {
20
261
  debug: [
21
262
  // 고장은 신호가 뚜렷하다. 그리고 디버그는 파일을 고칠 수 있으므로
22
263
  // 잘못 골라도 막히지 않는다. 그래서 세게 준다.
@@ -24,6 +265,9 @@ const 표 = {
24
265
  [/작동\s*안/, 4], [/동작\s*안/, 4],
25
266
  [/에러|오류|예외|익셉션/, 4], [/버그/, 4],
26
267
  [/실패/, 3], [/터(져|졌|진다)/, 3], [/죽(어|었|는다|네)/, 3],
268
+ // 「깨지다」 는 검사·빌드가 무너졌을 때 한국어에서 제일 흔한 말인데
269
+ // 터지다·죽다만 있고 이것이 빠져 있었다(같은 뜻 짝 재기).
270
+ [/깨(져|졌|진다|지네|지는|진)/, 3],
27
271
  [/멈(춰|췄|춘다|추)/, 3], [/먹통/, 3], [/이상(해|하다|한데)/, 3],
28
272
  [/재현/, 3], [/스택\s*트레이스|stack\s*trace|traceback/i, 4],
29
273
  // 'TypeError' 처럼 앞에 글자가 붙어 오는 일이 훨씬 흔하다.
@@ -33,7 +277,7 @@ const 표 = {
33
277
  [/왜\s*(못|안)/, 3], [/뭐\s*때문(이|에)/, 3],
34
278
  // 원인을 짚으라는 말은 점검이 아니라 디버그다 — 증상이 이미 있다는 뜻이다.
35
279
  // 이게 없으면 "오류 원인 분석해줘" 가 둘 사이에서 비겨 종합에 그대로 남는다.
36
- [/원인(을|이|은)?\s*(찾|짚|파악|밝|알아|분석|살펴|봐)/, 4],
280
+ [/원인(을|이|은)?\s*(?:좀\s*)?(찾|짚|파악|밝|알아|분석|살펴|봐)/, 4],
37
281
  ],
38
282
 
39
283
  plan: [
@@ -72,10 +316,19 @@ const 표 = {
72
316
  * 파일을 못 고쳐서 사람이 막히므로, 문턱은 읽기 전용답게 높인다.
73
317
  */
74
318
  inspect: [
75
- [/점검(해|좀|을|이)/, 5], [/분석(해|좀|을|이)/, 5],
76
- [/검토(해|좀|를)/, 5], [/리뷰(해|좀)?/, 5],
319
+ [/점검(해|\s*좀|을|이)/, 5], [/분석(해|\s*좀|을|이)/, 5],
320
+ [/검토(해|\s*좀|를)/, 5], [/리뷰(해|\s*좀)?/, 5],
77
321
  // '감사합니다' 는 안 걸린다 — '합' 은 '해·하' 가 아니다.
78
322
  [/감사(를)?\s*(해|하)/, 4], [/훑어\s*(봐|보고|줘)/, 4],
323
+ /*
324
+ * 「살펴보다」 는 영어 `inspect` 와 같은 뜻인데 점수표에 없었다. 영어
325
+ * 쪽은 5점이라 "Inspect this code." 는 inspect 로 가고 "이 코드 살펴봐
326
+ * 줘" 는 종합에 남았다 — 한국어를 먼저 쓰는 도구에서 방향이 거꾸로다.
327
+ *
328
+ * 앞에 「원인」 이 붙으면 뺀다. 그건 고장을 쫓는 말이라 debug 자리고,
329
+ * 여기로 보내면 파일을 못 고치는 모드에서 원인만 듣고 끝난다.
330
+ */
331
+ [/(?<!(?:원인|까닭|이유)[을이은는]?\s{0,2}(?:좀\s{0,2})?)살펴\s*(봐|보고|보자|봐야|주)/, 5],
79
332
  [/취약(점|한|성)/, 5], [/보안\s*(점검|검토|문제|취약|구멍)/, 5],
80
333
  [/경합|레이스\s*컨디션|race\s*condition/i, 5],
81
334
  [/데이터\s*(손실|유실)|덮어쓰(기|면)|유실/, 4],
@@ -85,7 +338,36 @@ const 표 = {
85
338
  [/가능성(이|을)?\s*있는/, 3],
86
339
  [/문제(가|를|점)?\s*(있|찾|없|만)/, 3],
87
340
  [/찾아\s*(줘|주세요|봐|보)/, 2],
88
- [/\baudit\b|\breview\b|\banaly[sz]e\b|\binspect\b|\bvulnerab/i, 4],
341
+ /*
342
+ * ── 읽기 쪽 영어도 같은 무게로 ──────────────────────────────────
343
+ *
344
+ * 쓰기 쪽 낱말 구멍(위 code 표)을 메우고도 **읽기 쪽은 그대로였다.**
345
+ * 같은 뜻을 한국어로 하면 여기로 오고 영어로 하면 종합에 남았다 —
346
+ * 여덟 짝을 재 보니 다섯이 어긋났다.
347
+ *
348
+ * "이 코드 검토해 줘" → inspect
349
+ * "Review this code." → 종합
350
+ *
351
+ * 까닭은 무게였다. 한국어 '점검·분석·검토·리뷰·취약' 은 낱낱이 5점
352
+ * 규칙인데, 영어는 다섯 낱말이 **4점 한 덩이**로 묶여 있었다. 문턱에
353
+ * 하나 모자라고, 여럿이 겹쳐도 한 번만 세어진다.
354
+ *
355
+ * 그래서 한국어와 같은 모양으로 쪼개고 같은 무게를 준다. `audit` 만
356
+ * 4점인 것은 한국어 '감사' 가 4점이라 그렇다 — 짝을 맞춘 것이다.
357
+ */
358
+ /*
359
+ * 활용형까지 받는다. `\b` 로 딱 닫아 두니 `Analyzing` · `reviews` ·
360
+ * `inspection` 이 0점이었다(7차 리뷰). 한국어는 '분석해·분석을·분석이'
361
+ * 를 다 받는데 영어만 원형 하나였다.
362
+ *
363
+ * `audit` 도 5점으로 올린다. 4점으로 둔 까닭을 「한국어 '감사' 가
364
+ * 4점이라」 고 적었는데, 한국어 '감사' 가 낮은 것은 **인사말과 겹뜻**
365
+ * 이어서다. 영어 audit 에는 그 겹뜻이 없다 — 엉뚱한 근거였다.
366
+ */
367
+ [/\breview(?:s|ing|ed)?\b|\binspect(?:s|ing|ion|ions|ed)?\b/i, 5],
368
+ [/\banaly[sz]e(?:s|d)?\b|\banaly[sz]ing\b|\banalysis\b/i, 5],
369
+ [/\bvulnerab/i, 5],
370
+ [/\baudit(?:s|ing|ed)?\b/i, 5],
89
371
  [/\bdata\s*loss\b|\bdeadlock\b|\blost\s*update\b/i, 4],
90
372
  ],
91
373
 
@@ -103,12 +385,101 @@ const 표 = {
103
385
  */
104
386
  [/뭐\s*하는\s*(파일|함수|코드|모듈|클래스|녀석|건|거|것)/, 5],
105
387
  [/뭐\s*하(는|나|니|냐)/, 3], [/무슨\s*(일|역할)/, 3],
106
- [/설명(해|좀|을)/, 5], [/알려\s*(줘|주세요|줄래)/, 3],
388
+ [/설명(해|\s*좀|을)/, 5], [/알려\s*(줘|주세요|줄래)/, 3],
107
389
  [/어떻게\s*(동작|작동|돌아가)/, 5],
390
+ /*
391
+ * 「어떻게 …?」 는 영어 `how to` 와 같은 물음인데 '동작·작동·돌아가'
392
+ * 셋만 알고 있었다. 쓰는 법을 묻는 말이 통째로 0점이었다.
393
+ *
394
+ * 손대는 낱말은 안 넣는다 — "어떻게 고쳐?" 는 고쳐 달라는 말이지
395
+ * 설명해 달라는 말이 아니다.
396
+ */
397
+ [/어떻게\s*(쓰|사용|실행|돌리|켜|끄|설정|설치|연결|고르|정하|불러|읽)/, 5],
108
398
  [/무슨\s*(뜻|의미)|의미(가|는)\s*뭐/, 5],
109
399
  [/차이(가|는|점)/, 3],
110
400
  [/궁금/, 3], [/왜\s*이렇게\s*(만들|짰|되어)/, 3],
111
- [/\bwhat\s+is\b|\bexplain\b|\bhow\s+does\b/i, 4],
401
+ /*
402
+ * 여기도 마찬가지다. 한국어 '설명·뭐야·무엇·어떻게 동작' 이 5점인데
403
+ * 영어는 세 낱말이 4점 한 덩이였다. 짝을 맞춰 쪼갠다.
404
+ *
405
+ * 묻는 말꼴도 넓힌다 — `what is` 만 알고 `what does … do` 를 몰라서
406
+ * "What does this function do?" 가 0점이었다. 한국어 '뭐 하는 거야'
407
+ * 는 5점으로 아는 말이다.
408
+ */
409
+ /*
410
+ * ── 묻는 말은 **문장 첫머리**에 있어야 묻는 말이다 ────────────────
411
+ *
412
+ * 넓히자마자 반대쪽이 샜다(7차 리뷰).
413
+ *
414
+ * "Fix what is broken in route.js" → ask 5점
415
+ *
416
+ * 고치라는 말이 물음과 비겨서 종합에 떨어졌다. 한국어 '뭐야' 규칙은
417
+ * 줄 끝(`\s*\??$`)에 못박혀 있어서 이런 일이 없다 — 영어도 첫머리로
418
+ * 못박는다. 물음표로 끝나는 문장은 낱말을 안 가리고 다 받는다.
419
+ *
420
+ * `explain` 은 첫머리가 아니어도 된다 — "Explain how …" 처럼 그 자체가
421
+ * 시킴말이고, 한국어 '설명해' 도 자리를 안 가린다.
422
+ *
423
+ * ── 「말해 줘」 부류에는 첫머리 못이 있어야 한다 ──────────────────
424
+ *
425
+ * 9차 리뷰. `tell me` · `show me` · `walk me through` 를 자리 안 가리고
426
+ * 넣었더니, 쓰기 지시문의 딸린 마디가 물음이 됐다.
427
+ *
428
+ * "Rewrite this function to show me the result." → ask 5점
429
+ * "Write the docs and tell me what changed." → ask 5점
430
+ *
431
+ * `explain` 과 다르다. `explain` 은 그 자체가 문장의 시킴말이라 어디
432
+ * 있든 묻는 말인데, 이 셋은 **딸린 마디에 더 자주 온다.** 그래서 못을 박는다.
433
+ *
434
+ * 이름씨 `explanation` 은 아예 뺀다. 8차에 사소 하나(「이름씨꼴이
435
+ * 없다」)를 메우려고 넣었는데, 그 값으로 `"Add an explanation to the
436
+ * README."` 가 물음이 됐다 — 사소를 메우려다 심각을 냈다. 첫머리에
437
+ * 못을 박으면 정작 쓸모 있는 "Give an explanation of …" 가 죽고,
438
+ * 안 박으면 위가 샌다. 얻는 것보다 잃는 것이 크면 안 넣는 것이 맞다.
439
+ *
440
+ * ── 못박아 놓고 한쪽만 못박혔다 ──────────────────────────────────
441
+ *
442
+ * 8차 리뷰. `how` 규칙을 `(첫머리)how…\?|how (to|does|…)` 로 적었다.
443
+ * 세로줄은 **규칙 전체를 가른다.** 그래서 둘째 갈래에는 첫머리 못이
444
+ * 아예 안 박혔고, 바로 위 주석이 막았다는 그 자리가 그대로 열려 있었다.
445
+ *
446
+ * "Rewrite how to build it." → ask 5점, **ask 모드**
447
+ *
448
+ * 고치라는 말이 **파일을 못 고치는 모드**로 갔다. 7차에 막은 것보다
449
+ * 한 걸음 더 나쁘다 — 그때는 비겨서 종합에 떨어졌을 뿐이었다.
450
+ * 갈래를 괄호로 묶어 못을 둘 다에 박는다.
451
+ *
452
+ * 첫머리에 `^\s*` 를 준다. 쓰기 갈래는 이미 그런데 여기만 안 그래서,
453
+ * 빈칸 두 칸으로 시작하는 물음이 0점이었다.
454
+ *
455
+ * ── 이름 안의 마침표는 문장 끝이 아니다 ──────────────────────────
456
+ *
457
+ * "What parameters does route.js take?" → 0점
458
+ *
459
+ * 물음표 갈래를 `[^.!?\n]*\?` 로 적어서 `route.js` 의 마침표에서
460
+ * 끊겼다. 마침표 뒤에 낱말 글자가 붙어 있으면 그건 문장 끝이 아니라
461
+ * 이름의 일부다 — 이 파일 위쪽 영어시킴말이 이미 아는 이야기다.
462
+ *
463
+ * ── 묻는 꼴 세 가지가 더 있었다 ──────────────────────────────────
464
+ *
465
+ * · `What <이름씨> does …` 보조동사가 `what` 바로 뒤에만 오는 줄
466
+ * 알아서, 물음표가 없으면 통째로 0점이었다.
467
+ * · `How's …` `what` 에는 준 줄임꼴을 `how` 에는 안 줬다.
468
+ * · 거꾸로 `how` 에만 준 `to` · `can` · `should` 를 `what` 에는 안
469
+ * 줬다(9차 리뷰). "What to run next" · "What should I run first" 가
470
+ * 물음표 없이는 0점이었다.
471
+ * · 이름 안 마침표 예외를 `\.(?=\w)` 로 적어 유닉스 상대 경로
472
+ * (`./route.js`)가 빠졌다. 슬래시도 낱말 글자로 친다.
473
+ * · `explanation` `inspect` 는 이름씨꼴까지 받는데 여기만 안 받았다.
474
+ *
475
+ * 그리고 `Tell me how …` 는 첫머리 못 때문에 0점인데, 이건 자리
476
+ * 문제가 아니라 **낱말 문제**다. 「말해 줘」 는 `explain` 과 같은 부류의
477
+ * 물음 시킴말이라 그쪽에 넣는다 — 못을 뽑으면 위의 `Rewrite how to` 가
478
+ * 도로 열린다.
479
+ */
480
+ [/\bexplain(?:s|ing|ed)?\b|(?:^\s*|[.!?]\s+|\n\s*)(?:(?:tell|show)\s+(?:me|us)\b|walk\s+(?:me|us)\s+through\b)/im, 5],
481
+ [/(?:^\s*|[.!?]\s+|\n\s*)what\b(?:(?:[^.!?\n]|\.(?=[\w/]))*\?|(?:'s|(?:\s+\w+){0,3}\s+(?:is|are|was|were|does|do|did|can|should)|\s+to)\b)/im, 5],
482
+ [/(?:^\s*|[.!?]\s+|\n\s*)how\b(?:(?:[^.!?\n]|\.(?=[\w/]))*\?|'s\b|\s+(?:to\b|does|do|did|is|are|was|were|can|should)\b)/im, 5],
112
483
  [/읽어(만)?\s*보고\s*(설명|알려)/, 4],
113
484
  ],
114
485
 
@@ -122,22 +493,61 @@ const 표 = {
122
493
  [/끝까지/, 3], [/마무리까지/, 3],
123
494
  [/여러\s*(개|군데|파일|단계|곳)/, 3],
124
495
  [/순서대로/, 3],
125
- [/통일(해|시켜|좀)|일괄/, 2],
496
+ [/통일(해|시켜|\s*좀)|일괄/, 2],
126
497
  [/흩어진|여기저기/, 2],
127
498
  [/\bend[- ]?to[- ]?end\b/i, 3],
128
499
  ],
129
500
 
130
501
  code: [
131
- [/고쳐|고쳐줘|수정(해|좀)/, 4],
132
- [/만들어|추가(해|좀)|넣어(줘|주세요)/, 4],
133
- [/구현(해|좀)/, 5],
134
- [/바꿔(줘|주세요)?|변경(해|좀)/, 3],
135
- [/지워(줘)?|삭제(해|좀)/, 3],
136
- [/이름\s*바꿔|리네임|rename/i, 3],
502
+ [/고쳐|고쳐줘|수정(해|\s*좀)/, 4],
503
+ [/만들어|추가(해|\s*좀)|넣어(줘|주세요)/, 4],
504
+ [/구현(해|\s*좀)/, 5],
505
+ [/바꿔(줘|주세요)?|변경(해|\s*좀)/, 3],
506
+ [/지워(줘)?|삭제(해|\s*좀)/, 3],
507
+ /*
508
+ * 영어 `rename` 은 여기서 뺐다. 첫머리 갈래가 이미 5점을 주므로
509
+ * `Rename the file.` 만 8점(5+3)이 되어, 5차에서 고친 동사 어긋남이
510
+ * 여기 하나 남아 있었다. `Rename failed - file in use` 도 3점을 받아
511
+ * 로그가 code 문턱에 닿았다(6차 리뷰). 문장 가운데 갈래로 옮긴다.
512
+ */
513
+ [/이름\s*바꿔|리네임/, 3],
137
514
  [/옮겨(줘)?/, 2],
138
- [/리팩터(링)?(해|좀)/, 3],
139
- [/\bimplement\b|\badd\b|\bfix\b|\bwrite\b/i, 2],
515
+ [/리팩터(링)?(해|\s*좀)/, 3],
516
+ /*
517
+ * 첫머리 시킴말. 한국어의 '구현해'(5점)와 같은 무게다 — 같은 말을
518
+ * 어느 말로 했느냐로 모드가 갈리면 안 된다.
519
+ *
520
+ * 증거가 세서 세게 준다. 이 규칙은 낱말 하나를 보는 것이 아니라
521
+ * **문장 첫머리 + 골라 둔 동사 + 실패말이 안 따라옴**을 다 요구한다.
522
+ * `error` 같은 맨낱말(3점)보다 훨씬 좁게 잡힌 규칙이다.
523
+ *
524
+ * 4점이었을 때 남은 자리가 있었다. 설계 낱말이 하나도 없는 긴 명세에서
525
+ * 시킴말 하나(4)가 지나가는 `error`·`failed` 둘(6)에게 졌다.
526
+ * 5점이면 1·2등이 붙고, 원래 있던 「비기면 안 고른다」 규칙이 받아 낸다 —
527
+ * 새 울타리를 세우지 않고 눈금만 맞추는 것이 이 자리의 고침이다.
528
+ */
529
+ [영어시킴말, 5],
530
+ /*
531
+ * 문장 가운데의 시킴말. 첫머리 갈래(5점)와 **겹치지 않게** 앞을 막는다.
532
+ * 안 막았더니 `Fix the web app.` 은 7점(5+2)이고 `Build the web app.` 은
533
+ * 5점이었다 — 같은 뜻인데 어느 동사를 골랐느냐로 점수가 갈렸다. 긴
534
+ * 명세에서는 그 2점이 모드를 바꾼다(하나는 code, 하나는 종합).
535
+ *
536
+ * 그래서 **앞에 낱말이 있어야** 이 규칙이 돈다. `please` 는 첫머리
537
+ * 갈래가 이미 세는 말이라 따로 뺀다.
538
+ *
539
+ * 빼는 자리에도 쉼표를 받는다. 첫머리 갈래가 `Please, fix …` 를 세게
540
+ * 되자 여기가 또 2점을 얹어 `Please, build …`(5) 와 갈렸다 —
541
+ * 겹침을 막는 자리는 겹치는 쪽과 **같은 꼴**을 봐야 한다.
542
+ */
543
+ [/(?<=[a-z,;:)\]]\s{1,3})(?<!\b(?:could|can|would|will)\s{1,3}(?:you|we)[\s,]{1,4})(?<!\bplease[\s,]{1,4})(?:implement|add|fix|write|rename)\b/i, 2],
140
544
  [/써(줘|주세요)/, 3],
545
+ /*
546
+ * 「짜다」 는 코드·검사를 만들라는 한국어에서 제일 흔한 말인데
547
+ * '써 줘' 만 있었다. 계획·순서·구조를 짜는 것은 각각 plan·architect
548
+ * 규칙이 이미 더 세게 잡으므로 여기서 따로 뺄 것이 없다.
549
+ */
550
+ [/짜\s?(줘|주세요|봐|보자)/, 3],
141
551
  ],
142
552
  };
143
553
 
@@ -285,7 +695,7 @@ export function 겹친요청(text) {
285
695
  * 하나는 읽고 말하라는 말이고 하나는 고치라는 말이다. 그래서 어미가 아니라
286
696
  * **동사 목록**으로 본다. 목록에 없으면 손대라는 말이 아니다.
287
697
  */
288
- const 손대는동사 = '만들|고쳐|고치|바꿔|바꾸|추가|넣어|지워|삭제|옮겨|나눠|나누|합쳐|정리|개선|구현|작성|적용|설치|배포|리팩터링|리팩터|분리|통일|세팅|갈아|손봐|손보|수정';
698
+ export const 손대는동사 = '만들|고쳐|고치|바꿔|바꾸|추가|넣어|지워|삭제|옮겨|나눠|나누|합쳐|정리|개선|구현|작성|적용|설치|배포|리팩터링|리팩터|분리|통일|세팅|갈아|손봐|손보|수정';
289
699
  /*
290
700
  * 동사 바로 뒤에 시킴꼴이 붙어야 한다. 빈칸을 안 넘으므로 "나누는 설계만 봐줘"
291
701
  * 는 안 걸린다 — 그건 나누라는 말이 아니라 나누는 안을 보자는 말이다.
@@ -306,10 +716,34 @@ const 손대는동사 = '만들|고쳐|고치|바꿔|바꾸|추가|넣어|지워
306
716
  * 붙어 있나로 그 둘이 갈린다.
307
717
  * 「만들어라」 는 언제나 만들라는 말이다.
308
718
  */
309
- const 손대라는말 = new RegExp(`(${손대는동사})\\S{0,3}(줘|주세요|주라|해라|하라|하자|해다오|해줄래|할래|어라|아라|여라|라(?=[\s.!?~,]|$))`);
719
+ /*
720
+ * ── 여기 백슬래시 하나가 빠져 있었다 ────────────────────────────────────
721
+ *
722
+ * 이 무늬는 **템플릿 글**로 짓는다(동사 목록을 끼워 넣어야 해서). 그런데
723
+ * 템플릿 글 안에서 `\s` 는 정규식에 닿기 전에 자바스크립트가 먼저 먹는다 —
724
+ * 모르는 이스케이프라 백슬래시를 떼고 **글자 `s`** 만 남긴다.
725
+ *
726
+ * 적은 것 ...|라(?=[\s.!?~,]|$))
727
+ * 닿은 것 ...|라(?=[s.!?~,]|$)) ← 빈칸이 아니라 알파벳 s
728
+ *
729
+ * 그래서 맨 「라」 뒤에 **빈칸이나 줄바꿈이 오면 안 걸렸다.** 걸리는 것은
730
+ * 「라」 가 글 맨 끝이거나 바로 뒤에 . ! ? ~ , 가 붙을 때뿐이었다.
731
+ *
732
+ * "그것 좀 바꿔라" 걸림 (글 끝)
733
+ * "바꿔라 지금 해줘" 안 걸림 ← 여러 마디로 시키면 거의 다 이쪽이다
734
+ * "지워라 그리고 저장해" 안 걸림
735
+ *
736
+ * 위 주석이 「사람은 고쳐 달라고 세 번 적었는데 아무것도 안 바뀐 화면을
737
+ * 받는다」 고 적어 둔 바로 그 고장이, 고쳐 놓고도 백슬래시 하나 때문에
738
+ * 그대로 남아 있었다. `\\s` 로 적어야 정규식이 `\s` 를 받는다.
739
+ *
740
+ * (`\\S{0,3}` 는 처음부터 두 개라 멀쩡했다. 한 무늬 안에서 한쪽만 틀렸으니
741
+ * 눈으로는 더 안 보인다.)
742
+ */
743
+ const 손대라는말 = new RegExp(`(${손대는동사})\\S{0,3}(줘|주세요|주라|해라|하라|하자|해다오|해줄래|할래|어라|아라|여라|라(?=[\\s.!?~,]|$))`);
310
744
 
311
745
  // 파일을 못 고치는 모드. modes.js 에서 쓰기 도구를 안 주는 것들과 같아야 한다.
312
- const 읽기만하는모드 = new Set(['architect', 'plan', 'ask', 'inspect']);
746
+ export const 읽기만하는모드 = new Set(['architect', 'plan', 'ask', 'inspect']);
313
747
 
314
748
  /*
315
749
  * ── 영어로 시킨 말은 하나도 못 보고 있었다 ──────────────────────────────
@@ -334,8 +768,8 @@ const 읽기만하는모드 = new Set(['architect', 'plan', 'ask', 'inspect']);
334
768
  * 안에서 `\s` 의 역슬래시가 사라지고 `\b` 는 백스페이스 글자가 된다 —
335
769
  * 검사에서 잡히기 전까지 조용히 아무것도 안 맞는다. 실제로 그렇게 났다.
336
770
  */
337
- const 영어손대라 =
338
- /(?:^|[.!?\n]\s*|^\s*\d+[.)]\s*|^\s*[-*]\s*)(?:please\s+)?(?:build|implement|create|write|make|add|fix|refactor|remove|delete|rename|migrate|update|modify|change|generate|scaffold|set\s+up|develop)\b/im;
771
+ // 위에서 세운 공용 무늘 그대로다. 두 벌로 두면 한쪽만 늘어난다.
772
+ const 영어손대라 = 영어시킴말;
339
773
 
340
774
  /** 파일을 손대라는 말이 들었나. */
341
775
  export function 손대라했나(text) {
@@ -411,21 +845,73 @@ export function route(text) {
411
845
  const 더줘야 = 긴글 ? 2 : 0;
412
846
 
413
847
  const [으뜸, 점수] = 순위[0] ?? [null, 0];
414
- if (!으뜸 || 점수 < (문턱[으뜸] ?? 4) + 더줘야) {
848
+
849
+ /*
850
+ * ── 눈금을 올리는 것으로는 두 번째 낱말을 못 막는다 ────────────────────
851
+ *
852
+ * 위의 +2 는 **낱말 하나**를 막는다. 실제 벤치마크 지시문을 그대로 넣어
853
+ * 보니 두 개가 걸렸다 — 둘 다 증상이 아니라 요구사항 조건절이었다.
854
+ *
855
+ * "… handle duplicate requests, stale requests, unexpected server errors." +3
856
+ * "… A failed operation must not leave state silently inconsistent." +3
857
+ *
858
+ * 합이 6이라 3+2 를 넘어 디버그가 됐다. 고장 난 것이 하나도 없는 **빈
859
+ * 폴더**에서 시작하라는 글인데, 디버그 모드는 「증상을 한 문장으로 다시
860
+ * 적어라 · 재현 방법부터 확보해라」 를 시킨다. 없는 증상을 찾게 된다.
861
+ *
862
+ * 눈금을 또 올려도 세 낱말이면 그대로 뚫린다. 눈금은 글 길이만 보고
863
+ * 정하는데, 지나가는 낱말은 길이가 아니라 **글의 종류**를 따라 늘기
864
+ * 때문이다. 그래서 눈금이 아니라 견줌으로 본다.
865
+ *
866
+ * 같은 글에서 설계가 8점, 디버그가 6점이었다. 「고치라는 말이라 설계로는
867
+ * 안 보낸다」 는 그대로 맞다 — 그런데 그것은 **설계로 보내지 말라**는 말
868
+ * 이지, 그 글이 디버그라는 말이 아니다. 뺀 것이 남은 으뜸보다 세다면 이
869
+ * 글이 무엇인지는 아직 안 정해진 것이다. 종합에 둔다 — 종합은 걸음마다
870
+ * 단계를 따라가므로(agent/단계.js) 계획에서 시작해 만들기로 넘어간다.
871
+ *
872
+ * 짧은 말에는 안 건다. 짧은 말에서는 낱말 하나가 곧 뜻이다.
873
+ */
874
+ const 뺀최고 = Math.max(0, ...뺀것.map((m) => 점수들[m] ?? 0));
875
+ const 지나가는말 = 긴글 && Boolean(으뜸) && 점수 < 뺀최고;
876
+
877
+ // 골랐어야 할 만한 신호가 있었는데 일부러 안 보낸 자리인가.
878
+ const 일부러 = Boolean(지나가는말 || 뺀것.length
879
+ || (긴글 && 으뜸 && 점수 >= (문턱[으뜸] ?? 4)));
880
+
881
+ if (!으뜸 || 지나가는말 || 점수 < (문턱[으뜸] ?? 4) + 더줘야) {
415
882
  // 왜 안 바꿨는지는 화면에 그대로 뜬다. "설계로 갈 뻔했는데 고치라는 말이라
416
883
  // 안 보냈다" 와 "그냥 모르겠다" 는 사람에게 아주 다른 말이다.
417
- const 왜 = 긴글 && 으뜸 && 점수 >= (문턱[으뜸] ?? 4)
418
- ? `글이 길어 ${으뜸} 신호 하나로는 정함 — 종합에서 단계를 따라갑니다`
419
- : 뺀것.length
420
- ? `${뺀것.join('·')} 신호가 있었지만 고치라는 말이라 읽기 전용 모드로 안 보냄`
421
- : '무슨 일인지 뚜렷하지 않음';
422
- return { mode: null, score: 점수, why: 왜, 겹침: false, 점수들, 뺀것 };
884
+ const 왜 = 지나가는말
885
+ ? `글이 길고 ${뺀것.join('·')}(${뺀최고}점) ${으뜸}(${점수}점) 보다 세서 `
886
+ + `${으뜸} 로 안 봄 — 종합에서 단계를 따라갑니다`
887
+ : 긴글 && 으뜸 && 점수 >= (문턱[으뜸] ?? 4)
888
+ ? `글이 길어 ${으뜸} 신호 하나로는 안 정함 — 종합에서 단계를 따라갑니다`
889
+ : 뺀것.length
890
+ ? `${뺀것.join('·')} 신호가 있었지만 고치라는 말이라 읽기 전용 모드로 안 보냄`
891
+ : '무슨 일인지 뚜렷하지 않음';
892
+ /*
893
+ * ── 「일부러 안 골랐다」 와 「그냥 모르겠다」 는 다른 말이다 ─────────
894
+ *
895
+ * 바로 위 주석이 그 구분을 적어 뒀는데, 정작 화면에는 **둘 다 아무것도
896
+ * 안 떴다.** 부르는 쪽(repl.js · oneshot.js)이 `if (골라진.mode)` 안에서만
897
+ * 찍었기 때문이다. 여기서 지은 세 갈래 까닭은 한 번도 사람에게 안 갔다.
898
+ *
899
+ * 그렇다고 전부 찍으면 안 된다. 보통 한마디는 거의 다 여기로 오고 까닭은
900
+ * 「무슨 일인지 뚜렷하지 않음」 이다 — 그건 소음이다.
901
+ *
902
+ * 그래서 **가르는 일을 여기서 한다.** 부르는 쪽이 `뺀것.length` 니
903
+ * `글이 길` 이니를 다시 헤아리게 두면 두 자리에서 따로 어긋난다.
904
+ */
905
+ return { mode: null, score: 점수, why: 왜, 겹침: false, 점수들, 뺀것, 일부러 };
423
906
  }
424
907
 
425
908
  // 1·2등이 붙으면 고르지 않는다. 반반인 것을 억지로 정하면 절반은 틀린다.
426
909
  const 둘째 = 순위[1]?.[1] ?? 0;
427
910
  if (점수 - 둘째 < 2 && 둘째 >= (문턱[순위[1][0]] ?? 4)) {
428
- return { mode: null, score: 점수, why: `${으뜸} 과 ${순위[1][0]} 가 비슷함`, 겹침: false, 점수들 };
911
+ return {
912
+ mode: null, score: 점수, why: `${으뜸} 과 ${순위[1][0]} 가 비슷함`,
913
+ 겹침: false, 점수들, 뺀것, 일부러: true,
914
+ };
429
915
  }
430
916
 
431
917
  return {