hanlint 0.0.17 → 0.0.19
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/README.md +23 -20
- package/data/calqueFrame.json +60 -0
- package/data/cliches.json +39 -29
- package/data/collocationStops.txt +28 -0
- package/data/confusable.json +20 -20
- package/data/easyWords.json +12 -246
- package/data/exemplars.json +50 -29
- package/data/hiddenDeps.txt +11 -11
- package/data/japaneseLoan.json +27 -27
- package/data/koreanProse.txt +64 -0
- package/data/patterns.json +26 -26
- package/data/phraseRepeat.json +11 -0
- package/data/platformApis.txt +11 -11
- package/data/redundantPair.json +16 -16
- package/data/ruleCategories.json +2 -0
- package/data/ruleDocs.json +56 -54
- package/data/ruleMechanisms.json +2 -0
- package/data/screenNarration.json +10 -10
- package/data/screenSentence.json +60 -12
- package/data/screenTone.json +6 -6
- package/data/screenWord.json +70 -110
- package/data/spacing.json +12 -12
- package/data/spelling.json +29 -29
- package/data/translationese.json +23 -24
- package/data/usageCounts.report.json +1676 -0
- package/data/version.json +1 -1
- package/package.json +1 -1
- package/src/analysis/grammar/ending.js +1 -1
- package/src/analysis/grammar/hangul.js +4 -4
- package/src/analysis/grammar/josa.js +1 -1
- package/src/analysis/grammar/register.js +1 -1
- package/src/analysis/grammar/voice.js +1 -1
- package/src/analysis/index.js +3 -3
- package/src/analysis/josa.js +1 -1
- package/src/analysis/splitSentences.js +1 -1
- package/src/analysis/tokenize.js +41 -26
- package/src/baseline/store.js +8 -8
- package/src/cli/help.js +11 -10
- package/src/cli/main.js +332 -182
- package/src/cli/walk.js +2 -2
- package/src/cli/welcome.js +8 -8
- package/src/config/loadConfig.js +3 -3
- package/src/config/patch.js +6 -6
- package/src/config/readerContract.js +26 -26
- package/src/config/settings.js +44 -25
- package/src/config/toml.js +9 -9
- package/src/data/exemplars.js +21 -21
- package/src/data/load.js +6 -6
- package/src/data/operations.js +14 -14
- package/src/data/patches.js +10 -10
- package/src/data/patterns.js +5 -5
- package/src/data/profiles.js +6 -6
- package/src/data/prose.js +27 -0
- package/src/document/model.js +4 -4
- package/src/document/parseMarkdown.js +7 -7
- package/src/document/plainText.js +3 -3
- package/src/document/sourceText.js +117 -19
- package/src/edit/applyFixes.js +0 -0
- package/src/fingerprint/build.js +18 -9
- package/src/fingerprint/codeBlocks.js +3 -3
- package/src/fingerprint/codeMarkers.js +4 -4
- package/src/fingerprint/dictionaries.js +34 -7
- package/src/fingerprint/markers.js +27 -5
- package/src/fingerprint/readerState.js +9 -9
- package/src/fingerprint/sourceSentence.js +1 -1
- package/src/fingerprint/topics.js +1 -1
- package/src/guard/contract.js +6 -6
- package/src/guard/editLocality.js +1 -1
- package/src/guard/outline.js +1 -1
- package/src/guard/receipt.js +13 -13
- package/src/guard/surface.js +4 -4
- package/src/index.js +9 -7
- package/src/learn/edits.js +2 -2
- package/src/learn/operations.js +1 -1
- package/src/regex.js +2 -2
- package/src/report/compactReport.js +7 -3
- package/src/report/fingerprintJson.js +2 -2
- package/src/report/githubReport.js +1 -1
- package/src/report/jsonReport.js +3 -3
- package/src/report/registerMatch.js +2 -2
- package/src/report/sheet.js +0 -0
- package/src/report/textReport.js +35 -16
- package/src/report/writingSpec.js +17 -17
- package/src/rules/code/inputFileSource.js +1 -1
- package/src/rules/code/installImport.js +2 -2
- package/src/rules/code/platformApi.js +1 -1
- package/src/rules/document/countMismatch.js +2 -1
- package/src/rules/document/enoughOnce.js +2 -1
- package/src/rules/document/fieldEcho.js +10 -6
- package/src/rules/document/keywordHeading.js +1 -1
- package/src/rules/document/keywordMissing.js +1 -1
- package/src/rules/document/noQuestion.js +2 -2
- package/src/rules/document/promiseRecall.js +1 -1
- package/src/rules/document/tableOddCell.js +1 -1
- package/src/rules/finding.js +4 -4
- package/src/rules/paragraph/factListParagraph.js +1 -1
- package/src/rules/paragraph/paraFragment.js +1 -1
- package/src/rules/readerDebt.js +1 -1
- package/src/rules/registry.js +30 -26
- package/src/rules/screen/screenWord.js +2 -1
- package/src/rules/sentence/calqueFrame.js +11 -0
- package/src/rules/sentence/cliche.js +7 -3
- package/src/rules/sentence/connectorRepeat.js +2 -1
- package/src/rules/sentence/danglingDeixis.js +1 -1
- package/src/rules/sentence/dash.js +1 -1
- package/src/rules/sentence/deixis.js +1 -1
- package/src/rules/sentence/doubleNegative.js +2 -1
- package/src/rules/sentence/doublePassive.js +2 -1
- package/src/rules/sentence/draftHistory.js +2 -1
- package/src/rules/sentence/endingRepeat.js +3 -2
- package/src/rules/sentence/euiChain.js +1 -1
- package/src/rules/sentence/fillerOpener.js +1 -1
- package/src/rules/sentence/hardWord.js +6 -3
- package/src/rules/sentence/imperativePeriod.js +1 -1
- package/src/rules/sentence/japaneseLoan.js +7 -3
- package/src/rules/sentence/longSentence.js +1 -1
- package/src/rules/sentence/negationRedefine.js +1 -1
- package/src/rules/sentence/nounPile.js +10 -4
- package/src/rules/sentence/numberOrphan.js +1 -1
- package/src/rules/sentence/outsideProfile.js +8 -3
- package/src/rules/sentence/phraseRepeat.js +54 -0
- package/src/rules/sentence/redundantPair.js +7 -3
- package/src/rules/sentence/translationese.js +7 -3
- package/src/rules/shared/candidates.js +2 -2
- package/src/rules/shared/dictionaryRule.js +46 -8
- package/src/rules/shared/repeat.js +2 -2
- package/src/rules/structure/bridgeRepeat.js +3 -3
- package/src/rules/structure/emojiBullet.js +1 -1
- package/src/rules/structure/headingSkip.js +1 -1
- package/src/rules/structure/headingUniform.js +2 -1
- package/src/rules/structure/loneSubheading.js +1 -1
- package/src/rules/structure/moreLater.js +1 -1
- package/src/text.js +2 -2
- package/src/usage/counts.js +54 -0
- package/src/usage/index.js +8 -0
- package/src/usage/sentences.js +681 -0
package/data/ruleDocs.json
CHANGED
|
@@ -1,56 +1,58 @@
|
|
|
1
1
|
{
|
|
2
|
-
"blockUnread": "코드 블록 바로 뒤에 붙인 출력을 읽어 주는 설명글이 없는
|
|
3
|
-
"bridgeRepeat": "절을 닫는 문장이
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
2
|
+
"blockUnread": "코드 블록 바로 뒤에 붙인 출력을 읽어 주는 설명글이 없는 곳.\n\n왜: 출력을 붙였으면 그 출력을 읽어 준다. 숫자와 기호를 그대로 두면 독자는 어느 부분이 무엇인지 모른 채\n 다음으로 넘어가고, 방금 실행한 것이 제대로 된 것인지도 확인하지 못한다.\n어디서: 출력을 붙였으면 어느 부분이 무엇인지 짚어 읽어 준다는 블로그 쓰기 방식에서 왔다. 실제 블로그 글 하나의\n 출력 블록에서, 서른 줄 가운데 다른 것이 한 줄뿐인데 아무도 그것을 짚어 주지 않는다고 평가자가 지적했다.\n고치기: 출력 바로 아래에 그 출력을 읽는 문장을 한 줄 붙인다. 어느 숫자가 무엇인지, 무엇을 확인하면\n 되는지 말한다.\n안 잡는 것: 언어를 밝힌 코드 블록(실행할 것이지 읽을 것이 아니다)은 잡지 않는다. 앞이 코드 블록이 아닌 text\n 펜스도 잡지 않는다. 그것은 출력이 아니라 그림이다. 실제 운영 문서 하나가 폴더 구조를 text 펜스로 그렸는데\n 그것을 출력으로 보아 오탐이 났다. 출력 바로 뒤에 산문 문단이 오는 곳도 잡지 않는다. 블록 종류로 어림하는\n 규칙이라 경고로만 낸다.",
|
|
3
|
+
"bridgeRepeat": "절을 닫는 문장이 접속사(`이번에는`, `이제`, `다음으로`)로 시작하는 절이 3개 이상인 글.\n\n왜: 절 끝에서 다음 절을 예고하는 문장은 한 번이면 두 절을 잇지만, 절마다 되풀이되면 틀에 박힌 글이 된다.\n 독자는 절이 남긴 결과가 아니라 `이번에는`이라는 말만 거듭 읽게 되고, 절 사이에 실제 순서가 있는지 없는지가\n 그 말에 가려진다.\n어디서: 실제 강의 글 여섯 편에서 `앞에서 A 를 확인했습니다. 이번에는 B 를 확인합니다`가 53번 나왔고, 그중 한\n 편은 14절 가운데 12절이 이 말로 끝났다. 기준 말뭉치 390편에서 문장 첫머리의 `이번에는`은 1건이었다. 강의\n 글은 `앞에서 ... 이번에는 ...`을 되풀이해 없는 순서를 만들지 않는다는 쓰기 방식에서 왔다. 접속사 목록은\n data/bridgeOpeners.txt에 있고, 기준값은 설정 bridgeRepeatMin(기본 3)이다.\n고치기: 절이 방금 만든 결과를 이름으로 부르고 그것이 아직 못 하는 일을 한 문장으로 적는다. 그 못 하는 일이\n 다음 절의 제목이 된다. 나란히 놓인 사례라면 억지로 잇지 말고 같은 기준 아래의 사례라고 밝힌다.\n안 잡는 것: 접속사로 끝나는 절이 기준값보다 적은 글, 문장 중간의 `이번에는`, 절의 마지막 산문 문단이 아닌 곳,\n 도입 절은 잡지 않는다. 절 끝이 코드나 표라도 그 앞 산문 문단의 마지막 문장을 본다.",
|
|
4
|
+
"calqueFrame": "단어는 한국어인데 한국 사람이 그 뜻으로 쓰지 않는 동사와 앞말의 짝. `글에 잇지 못했어요`, `그 팀에 닿는 줄`.\n\n왜: 영어의 link, reach, render를 한국어 동사 하나로 옮기면 단어마다 사전에 있는데 문장은 한국 사람이 쓰지 않는\n 말이 된다. 독자는 단어를 다 알아도 무슨 일이 있었는지 다시 묻는다. 실측: AI가 쓴 `캐스팅 장갑과 가는\n 합사는 아직 원투 글에 잇지 못했어요.`를 읽은 사람이 `잇지`가 이상하다고 되물었다. `맡겼습니다`를 읽고는\n 누구에게 맡겼는지 물었다.\n어디서: 실제 대화 기록에서 사람이 지적한 조어 48건과 사람이 받아들인 문장 53건. 사전은 data/calqueFrame.toml이고\n 항목마다 동사와 그 앞말(`잇다`와 `글에`, `닿다`와 `팀에`)을 정규식으로 적는다. 받는 이, 장소, 관용구가 같은\n 문장에 있으면 바른 말이 되는 항목은 unless로 그 문장을 넘긴다. 실측: 지적 48건 가운데 11건을 잡고, 받아들인\n 53건과 공개된 글 7,123문장에서는 하나도 잡지 않는다. 기준 말뭉치 1,600편 225,350문장에서는 6건이 났다(이야기\n 글의 `맡기다` 4건, 옛 글의 `-어 봄` 2건).\n고치기: 그 일에 한국 사람이 쓰는 말로 바꾼다. `글에 잇다`는 `글에 연결하다`로, `그 팀에 닿는 줄`은 `그 팀에\n 해당하는 규칙`으로, `숫자가 그려지기 전`은 `숫자가 화면에 뜨기 전`으로 쓴다. `맡겼습니다`에는 누구에게 무엇을\n 맡겼는지 쓴다. 기본 사전은 경고라 문맥을 보고 정한다. 프로젝트가 설정의 dictionary.calqueFrame으로 더한\n 짝은 오류로 낸다.\n안 잡는 것: 처음 쓴 조어 전부. 말뭉치에 있는지만으로는 새로 지은 말과 자연스러운 한국어를 가려낼 수 없었다.\n 줄과 대를 잇는 것(`원줄 아래에 카드채비를 잇고`, `끼워 잇는 낚싯대`), 몸이나 물건이 닿는 것(`바닥에 닿은\n 봉돌`), 받는 이나 장소가 같은 문장에 있는 `맡기다`(`네이버에 맡겼습니다`). 앞 문장에만 받는 이가 있는\n `맡기다`는 잡는다. 백틱과 따옴표 안의 인용. 설정의 protectedTerms와 겹치는 곳.",
|
|
5
|
+
"cliche": "`핵심은`, `결국 중요한 것은`, `단순히 A를 넘어`, `살펴보겠습니다` 같은 상투어.\n\n왜: 문장이 하는 일 없이 매끈하기만 한 표현이다. 독자는 그 문장에서 정보를 받지 못하고 광고를 읽는\n 기분이 든다. `살펴보겠습니다` 뒤에 실제 행동이 없으면 문장째 지운다.\n어디서: AI 문체 신호 조사(Wikipedia Signs of AI writing, gist 패턴4). 사전은 data/cliches.toml이고 설정의\n dictionary.cliches로 더한다.\n고치기: 그 표현이 맡은 일이 있으면 그 일을 직접 쓴다. `핵심은 X다`는 `X다`로, `살펴보겠습니다`는 살펴본\n 결과로 바꾼다.\n안 잡는 것: 사전에 없는 표현. 사전에 없어도 목적어가 흐린 문장은 나쁘지만 그것은 사람 평가자가 본다.\n 그 종류의 글이 거의 다 쓰는 항목은 짚지 않는다. report 프리셋에서는 사업보고서 문서의 90% 이상(설정\n usageShare)에 나온 항목이다.",
|
|
6
|
+
"confusable": "`학생으로써`, `정답을 맞추다`, `나와 틀리다`, `감기가 낳다`처럼 뜻이 다른 말을 바꿔 쓴 곳.\n\n왜: `로서`와 `로써`, `맞히다`와 `맞추다`, `틀리다`와 `다르다`, `낫다`와 `낳다`는 소리가 같거나 비슷해서 뜻이\n 바뀐 줄 모르고 쓴다. 독자는 뜻으로 읽다가 걸린다.\n어디서: 국립국어원 한글 맞춤법 제57항(구별하여 적는 말), 온라인가나다 298340, 표준국어대사전 뜻풀이. 앞뒤\n 단어로 뜻이 정해지는 경우만 사전(data/confusable.toml)에 넣었다.\n고치기: 항목마다 바른 말로 고친 글을 낸다. 활용이 바뀌는 것(`틀려`→`달라`, `낳은`→`나은`)은 활용까지 바꾼다.\n안 잡는 것: 앞뒤 단어로 뜻이 정해지지 않는 경우, `이로써`나 `그것과 다르다`처럼 이미 맞는 것, 백틱과 따옴표\n 안의 인용은 잡지 않는다.",
|
|
7
|
+
"connectorRepeat": "같은 접속부사로 시작하는 문장이 한 문단 안에 연달아 오는 곳.\n\n왜: `그리고`, `그래서`를 연달아 붙이면 문장 사이의 관계가 전부 같은 것으로 읽히고 글이 단조로워진다.\n어디서: 같은 접속사를 연달아 쓰지 않는다는 글쓰기 원칙. 이태준 문장강화, 유시민 글쓰기 특강. 접속부사\n 목록은 data/connectors.txt에 있다.\n고치기: 앞 문장에서 만든 파일이나 값의 이름을 다시 불러 잇는다. 그렇게 이어지지 않을 때만 접속사를 쓴다.\n안 잡는 것: 문단이 바뀌면 다시 센다. 다른 접속사가 이어지는 것은 잡지 않는다.",
|
|
8
|
+
"countMismatch": "같은 단위로 서로 다른 수를 약속하는 글. 여섯 가지를 소개한다고 열고 다섯 가지라고 닫는 것.\n\n왜: 독자는 어느 쪽을 믿어야 할지 모른다. 약속과 이행이 어긋난 글은 나머지도 의심받는다.\n어디서: 실제 블로그 글 하나가 도입에서 여섯 방식을 약속하고 결말에서 다섯 가지라고 적었고, 사람 평가자가\n 네 차례 검토에서 모두 짚었다. 이런 검사를 하는 다른 도구는 찾지 못했다. 단위 목록은 data/countUnits.txt에 있다.\n고치기: 수를 맞추거나, 서로 다른 것을 세는 문장이면 무엇을 세는지 이름을 붙인다.\n안 잡는 것: 단위가 다른 수(`여섯 가지`와 `다섯 열`)와 같은 수의 반복은 잡지 않는다. 본문 절 안의 수도 잡지\n 않는다. 둘째 절의 `두 가지`와 넷째 절의 `네 가지`는 다른 목록이다. 같은 절 안의 두 수까지 비교하자 백과사전과\n 수필에서 표본 20건 가운데 11건이 오탐이었다. 그래서 도입의 약속과 마지막 절의 결산만 비교하고, 절이 없는 글은\n 글 전체가 60줄 안일 때만 비교한다(설정 countMismatchSpan). `3단계`처럼 숫자가 붙은 단계는 서수라 세지 않는다.",
|
|
9
|
+
"danglingDeixis": "지시어가 든 문장인데 바로 앞 문장과 화제어가 하나도 겹치지 않는 경우.\n\n왜: `이것`이 가리킬 것이 앞 문장에 없다. 독자는 되돌아가도 찾지 못한다. 지시어 가운데 가장 나쁜 경우다.\n어디서: 독자가 바로 앞에서 읽은 화제어와 이 문장의 화제어를 비교해 겹치는 것이 하나도 없으면 짚는다. 실제\n 블로그 글을 사람 평가자가 네 차례 검토했는데 네 번 모두 지시어를 지적했다.\n고치기: 가리키는 대상의 이름을 쓴다. 앞 문장에 그 이름이 없다면 앞 문장에 먼저 세운다.\n안 잡는 것: 앞 문장과 화제어가 겹치는 지시어는 deixis가 짚는다. 글의 첫 문장은 앞이 없으므로 여기서\n 잡는다. 앞 문장이 물음이나 감탄이면 그 문장을 가리키는 것이라 단어가 안 겹쳐도 잡지 않는다.",
|
|
10
|
+
"dash": "긴 줄표(U+2014)와 짧은 줄표(U+2013). 코드 블록까지 글 전체를 본다.\n\n왜: AI가 매끄럽게 고친다면서 새로 넣는 대표적인 부호다. 한국어 문장 부호가 아니라 독자가 멈춘다.\n GPT-4.1이 사람보다 3.28배 많이 쓴다는 조사가 있다.\n어디서: Wikipedia Signs of AI writing 4.6. Freeburg 조사.\n고치기: 덧붙이는 말은 마침표로 끊거나 괄호에 넣고, 범위는 물결표로 쓴다(`2020~2024`).\n안 잡는 것: 하이픈(-)과 물결표. 코드 안의 줄표도 잡고, 설정 ignoreFences가 검사에서 뺀 펜스 안도 잡는다.\n 렌더러가 지우는 펜스라도 파일에 있는 글자다. 코드에 줄표가 꼭 필요하면 그 파일에서 이 규칙을 끈다.",
|
|
11
|
+
"deixis": "`이것`, `해당 값`, `위의 코드`, `이러한` 같은 지시어. 앞 문장에 가리킬 것이 있는 경우.\n\n왜: 독자가 스크롤을 되돌려 무엇을 가리키는지 찾아야 한다. 되돌아가야 하는 곳마다 독자가 글을 떠날 수 있다.\n어디서: 설명을 풀어 쓴다는 글쓰기 원칙. 지시어 목록은 data/deixis.txt에 있다. 독자가 바로 앞에서 읽은\n 화제어와 이 문장의 화제어가 겹치면 여기서 짚는다.\n고치기: 가리키는 파일, 값, 코드의 이름을 쓴다. `이것으로 파일이 만들어집니다`는 `save로 link.png가\n 만들어집니다`로 바꾼다.\n안 잡는 것: 앞 문장과 화제어가 하나도 겹치지 않는 지시어. 그것은 danglingDeixis가 따로 짚는다.\n `앞서 말한 X`처럼 이름을 다시 쓰는 말.",
|
|
12
|
+
"doubleNegative": "`하지 않으면 안 된다`, `하지 않을 수 없다` 같은 이중 부정.\n\n왜: 부정을 두 번 겹쳐 긍정을 만들면 독자가 한 번 더 뒤집어 읽는다. 일본어를 그대로 옮긴 표현이다.\n어디서: urimal.org 김민지 2020 번역 투, 나무위키 이중 부정.\n고치기: 긍정으로 쓴다. `노력하지 않으면 안 된다`는 `노력해야 한다`로, `잊지 않을 수 없다`는 `잊는다`로\n 쓴다. `하다` 동사는 `hanlint fix`가 고친다.\n안 잡는 것: 뜻을 일부러 약하게 하는 이중 부정(`나쁘지 않다`). 그것은 다른 구문이다.",
|
|
13
|
+
"doublePassive": "`되어지다`, `보여지다`, `잊혀지다`처럼 피동에 `-어지다`를 또 붙인 이중 피동.\n\n왜: 피동이 두 번 겹치면 누가 하는지 한 번 더 흐려진다. 독자는 주어를 찾아 되돌아간다.\n어디서: 국립국어원 어문 규범. im-not-ai A-8(오경순 2010, 김은일 2015, 서보현 2018). 피동 어간 사전은\n data/passiveStems.txt에 있다.\n고치기: 하나만 남긴다. `되어진다`는 `된다`로, `보여진다`는 `보인다`로, `잊혀진`은 `잊힌`으로 쓴다. 고칠\n 말이 하나로 정해지고 바뀌는 부분이 인용 밖에 한 번만 있으면 `hanlint fix`가 고친다.\n안 잡는 것: `만들어진다` 같은 단순 피동. 어간이 피동사가 아니면 지적하지 않는다. 따옴표와 인라인 코드\n 안은 글쓴이가 쓴 말이 아니라 인용이므로 지적하지 않는다.",
|
|
14
|
+
"draftHistory": "글쓴이의 수정 이력과 자기 검증 기록. `처음에는 ~라고 썼습니다`, `~것을 확인했습니다`.\n\n왜: 독자는 초고를 본 적이 없다. 무엇을 어떻게 고쳤는지는 독자가 지금 하려는 일과 아무 관계가 없고,\n 글쓴이가 직접 확인했다는 보고도 독자가 자기 화면에서 할 일을 대신해 주지 못한다. 알아낸 사실만\n 결과 문장으로 남기고 알아낸 과정은 뺀다.\n어디서: 블로그 글에서 반드시 빼는 것의 첫 항목이라는 글쓰기 원칙. 실제 블로그 글의 `ibis-framework[duckdb]만\n 설치한 환경에서 아래 코드가 그대로 도는 것을 확인했습니다`를 평가자가 세 번째 검토에서 글쓴이의 자기 검증\n 기록으로 읽힌다고 지적했다. 찾는 표현 목록은 data/draftHistory.txt에 있다.\n고치기: 알아낸 사실만 남긴다. `확인했습니다`를 지우고 그 사실을 바로 쓴다. 독자가 할 일이면 `확인해\n 보세요`로 권한다. 과정을 남기고 싶으면 회고 글로 따로 뺀다.\n안 잡는 것: 수치의 출처를 밝히는 문장(`일곱 번씩 재서 가운데 값을 적었습니다`). 사실 확인은 글쓰기\n 규칙이 요구하는 것이라 재는 방법은 남긴다. 인용 안의 같은 표현.",
|
|
15
|
+
"duplicateBlock": "앞선 코드나 출력 블록과 거의 같은 블록.\n\n왜: 서른 줄 가운데 한 줄만 다른 블록을 두 번 읽으면 독자는 다른 한 줄을 찾느라 블록 전체를 훑는다. 다른 줄만\n 보이거나 앞 블록을 가리키는 것이 낫다.\n어디서: 실제 블로그 글 하나에서 두 엔진의 출력 서른 줄 가운데 다른 것이 한 줄이었고 사람 평가자가 짚었다.\n 줄이 90% 이상 겹치면 잡는다(설정 duplicateBlockRatio, 기본 0.9). 블록은 넉 줄 이상이어야 한다.\n고치기: 다른 줄만 남기고 나머지는 앞 블록을 가리킨다. 정말 둘 다 필요하면 무엇이 다른지 산문에서 먼저 말한다.\n안 잡는 것: 넉 줄 미만인 블록, 종류가 다른 두 블록(코드와 출력), 겹친 줄이 기준값보다 적은 블록은 잡지 않는다.\n 경고로만 낸다.",
|
|
16
|
+
"emojiBullet": "이모지로 시작하는 목록 항목.\n\n왜: 목록 항목마다 이모지를 달면 장식이 정보를 가리고 AI가 쓴 홍보 글처럼 읽힌다.\n어디서: Wikipedia Signs of AI writing 4.7(Emoji as formatting), Bloomberg 2026-01(LinkedIn AI 게시물).\n고치기: 이모지를 지우고 항목의 첫 단어가 내용을 말하게 한다.\n안 잡는 것: 본문 문장 안의 이모지는 잡지 않는다. 목록 항목의 맨 앞만 본다.",
|
|
17
|
+
"endingRepeat": "같은 종결어미로 끝나는 문장 4개가 인과 접속사도 질문도 독자를 부르는 말도 없이 이어지는 곳.\n\n왜: `습니다`가 네 번 이어지고 그 사이에 인과 접속사도 독자를 부르는 말도 없으면 글이 단조로워지고 사실이\n 나란히 놓이기만 한다. 서너 문장에 한 번은 앞뒤를 까닭으로 잇는 문장이 있어야 읽힌다.\n어디서: AI 문체 신호 조사(im-not-ai E-2 동일 종결어미 4문장 이상, gist 패턴35), 경희대 글쓰기 교육의\n `것이다` 반복. 짧은 문장만 늘어놓지 않는다는 글쓰기 원칙. 몇 문장부터 잡을지는 설정 endingRun(기본 4)이\n 정한다.\n고치기: 하나를 질문으로 바꾸거나, 두 문장을 까닭으로 잇거나, 독자가 할 행동을 동사로 끝낸다.\n안 잡는 것: 인과 접속사(`그래서`, `때문에`)이나 독자를 부르는 말이 든 문장. 그 문장이 연속을 끊는다.\n 어미가 같아도 까닭으로 이어져 있으면 단조롭지 않다. 실측: 이 조건을 넣기 전에는 발행한 글 다섯 편에서\n 56건이 나왔고 그중 대부분이 합니다체 자체를 센 것이었다. 명령형과 의문형의 연속. 종결어미를 정하지 못한\n 문장. 글쓰기 규칙을 어긴 것이 아니라 리듬을 살펴볼 곳이라 경고로 낸다.",
|
|
18
|
+
"enoughOnce": "`여기까지면 충분합니다`로 끊는 문장이 한 글에 두 번 이상 나오는 것.\n\n왜: 기본 사용법이 끝나는 곳에서 한 번 끊어 주면 독자는 여기서 멈춰도 된다는 것을 안다. 그 문장이 절마다\n 나오면 끝난다고 해 놓고 글이 계속 이어져서, 독자는 어디가 진짜 끝인지 알 수 없다.\n어디서: 절은 앞 절이 못 한 일에서 시작한다는 블로그 쓰기 방식에서 왔다. `여기까지면 만들어 쓰는 데\n 충분합니다. 아래부터는 ~할 때 봅니다.` 같은 문장은 글 전체에 한 번만 쓴다. 찾는 말 목록은\n data/enoughMarkers.txt에 있다.\n고치기: 기본 사용법이 정말로 끝나는 곳 하나만 남기고 나머지는 지운다. 지운 곳은 앞 절이 만든 것을 이름으로\n 부르고 다음에 할 일을 붙이는 문장으로 잇는다.\n안 잡는 것: 한 번만 쓴 글은 잡지 않는다. 인용 안의 같은 문장은 검사하기 전에 인용으로 걸러 둔다.",
|
|
19
|
+
"euiChain": "한 문장에 조사 `의`가 세 번 이상 나오거나 `의`로 끝나는 어절 둘이 붙어 있는 곳(`회사의 팀의 결정`).\n\n왜: 명사를 `의`로 쌓으면 무엇이 무엇의 목적어인지 표시되지 않아 독자가 조사를 머릿속에서 끼워 넣는다.\n어디서: `의`가 이어지면 문장으로 편다는 글쓰기 원칙. 쿠버네티스 한국어 현지화 가이드(일본어 の 직역).\n고치기: 동사로 편다. `회사의 팀의 결정`은 `회사에서 팀이 정한 것`으로 쓴다.\n안 잡는 것: 단어 안의 `의`(`의미`, `의사`)와 `의`로 끝나는 단어(`정의`, `회의`. 목록은 data/euiNouns.txt).\n 떨어져 있는 `의` 둘(`글쓰기 규칙의 기준은 사용자 저장소의 스킬이다`)은 자연스러운 한국어라 잡지 않는다.\n 실측: `의` 두 번을 기준으로 삼았더니 문서에서 오탐이 4건 났다.",
|
|
20
|
+
"factListParagraph": "짧은 평서문 셋 이상이 접속사 없이 이어지는 문단.\n\n왜: 쉬운 단어를 골라도 사실만 나란히 놓으면 읽히지 않는다. 독자는 단어가 아니라 문장 사이의 까닭을 못\n 따라가서 멈춘다. `병합 셀은 첫 칸에만 값이 있습니다. 나머지 칸은 빈값입니다. 정렬하면 순서가 깨집니다.`는\n 세 문장의 관계를 독자가 세워야 한다.\n어디서: 설명을 풀어 쓴다는 블로그 쓰기 방식에서 왔다. 인과 접속사 목록은 data/causalMarkers.txt, 문장\n 첫머리 접속사 목록은 data/connectors.txt에 있다. 최소 문장 수는 설정 factListMinSentences(기본 3), 평균\n 어절 수의 상한은 설정 factListMaxMeanLength(기본 8)다.\n고치기: 문장 사이에 `그래서`, `때문에`, `그러면`을 넣어 잇는다. 풀어 쓰면 글이 길어지는 것이 정상이다.\n안 잡는 것: 두 문장 이하인 문단은 잡지 않는다. 인과 접속사, `하지만`이나 `그런데` 같은 문장 첫머리 접속사,\n 질문, 독자에게 말을 거는 문장이 하나라도 든 문단도 잡지 않는다. 평균 어절 수가 상한을 넘는 문단도 잡지\n 않는다(긴 문장은 조건과 이유를 안에 품고 있다). 실제 글 하나에서 접속사만 보자 문단의 40%가 잡혔고, 읽어\n 보니 대부분 긴 설명문이었다. 그래서 짧은 문장이 끊겨 이어지는 문단만 잡는다. 그래도 나열이 아닐 수 있어\n 경고로만 낸다.",
|
|
21
|
+
"fieldEcho": "frontmatter가 약속한 것을 도입이나 마지막 절이 하나도 언급하지 않는 글.\n\n왜: frontmatter에 독자의 질문과 독자가 얻을 것을 적어 두고 본문이 다른 말을 하면, 검색해 들어온 독자는\n 미리보기에서 본 약속과 다른 글을 읽는다. 도입은 그 질문에 답하기 시작해야 하고, 마지막 절은 독자가 얻을\n 것을 다시 말해야 한다.\n어디서: 도입은 독자가 막힌 데서 시작하고 결말은 독자가 얻을 것으로 닫는다는 블로그 쓰기 방식에서 왔다. 실제\n 블로그의 frontmatter에 readerQuestion과 readerTakeaway를 적어 두었는데 어떤 검사기도 본문과 맞춰 보지\n 않았다. 볼 필드는 설정 introFields와 endingFields가 정한다. 둘 다 비어 있으면 이 규칙은 돌지 않는다.\n고치기: 도입 첫 문단에서 그 질문의 말을 그대로 쓰고, 마지막 절에서 얻을 것을 그 이름으로 다시 언급한다.\n 본문이 맞고 frontmatter가 낡았으면 frontmatter를 고친다.\n안 잡는 것: 설정에 필드를 적지 않은 글, frontmatter에 그 필드가 없거나 빈 글, 화제어가 없는 값은 잡지 않는다.\n 글의 끝은 마지막 절 하나가 아니라 결말과 그 뒤 목록을 아우르므로 마지막 두 절을 함께 본다. 실제 글 두 편의\n 마지막 절이 `더 해 볼 것`이라 결말이 한 칸 앞에 있었고, 마지막 절만 보았을 때 그것이 오탐이었다. 화제어가\n 겹치는지로 어림하는 규칙이라 경고로만 낸다.",
|
|
22
|
+
"fillerOpener": "`다음으로`, `이어서`, `마지막에는`으로만 잇는 문장.\n\n왜: 앞에서 무엇을 만들었는지 밝히지 않고 순서를 나타내는 말만 붙이면 독자는 무엇을 이어받는지 모른 채 다음\n 행동을 읽는다.\n어디서: 쉬운 말로 바로 쓴다는 글쓰기 원칙.\n고치기: 앞 절에서 만든 파일이나 확인한 값을 이름으로 다시 언급하고 다음 행동을 붙인다. 예: `link.png는\n 33픽셀입니다. 명함에 넣기에는 너무 작습니다.`\n안 잡는 것: 문장 중간의 `이어서`. 목록 항목.",
|
|
23
|
+
"firstResultDistance": "첫 코드나 표나 그림이 나오기 전에 산문 문단이 4개를 넘는 글.\n\n왜: 따라 하러 온 독자는 실행할 것이 나올 때까지 배경을 읽는다. 문단이 넷을 넘으면 읽다가 떠난다.\n어디서: 실제 블로그 글 하나에서 셋째 문단까지 숫자가 하나도 없어 사람 평가자가 짚었다. 도입은 독자가 막힌 데서\n 시작하고 첫 코드 블록이 도입 안에 온다는 쓰기 방식에서 왔다. 기준값은 설정 firstResultMaxParagraphs(기본 4)다.\n고치기: 첫 실행할 것을 앞으로 당기거나 그 앞의 문단을 뒤로 보낸다.\n안 잡는 것: 코드도 표도 그림도 없는 글(참고 문서)은 잡지 않는다. introLong이 도입만 보는 것과 달리 이 규칙은 절을\n 넘어 센다. 경고로만 낸다.",
|
|
24
|
+
"hardWord": "`금일`, `익월`, `금회`처럼 행정 한자어를 더 익숙한 말로 바꿀 수 있는지 살펴볼 곳.\n\n왜: 평소에 쓰지 않는 말은 독자가 머릿속에서 한 번 번역한다. 같은 뜻이면 더 자주 쓰는 말로 바로 쓴다.\n어디서: 국립국어원 다듬은 말(korean.go.kr 개선 > 다듬은 말)과 표준국어대사전의 동의어 정보. 사전은\n data/easyWords.toml이고 항목마다 출처가 있다. 자료에 대신 쓸 말이 있어도 분야 용어와 외래어는\n 문맥에 따라 뜻이 달라져 기본 사전에서 뺐다. 사용자는 설정의 dictionary.easyWords로 더한다.\n고치기: 제안이 독자에게 더 익숙하고 원문의 뜻도 지킬 때만 고른다. 널리 쓰는 기술 용어는 남기고 필요한\n 뜻을 문장으로 설명한다. 단어를 직역해 새 이름을 만들지 않는다. `hanlint fix`는 고치지 않는다.\n안 잡는 것: 사전에 없는 말. 고유명사와 제품 이름. 백틱과 따옴표 안의 인용. 제안이라 경고로만 낸다.\n 그 종류의 글이 거의 다 쓰는 말은 짚지 않는다. 프리셋이 정한 종류의 문서 90% 이상(설정 usageShare)에\n 나온 사전 항목이다.",
|
|
25
|
+
"headingSentence": "본문 문장을 그대로 복사한 절 제목.\n\n왜: 절 제목은 간단명료하게 쓴다. `합니다`, `하세요`로 끝나는 제목은 목차에서 대상이 안 보이고 본문과 같은\n 문장이 두 번 읽힌다.\n어디서: 절 제목은 간단명료하게 쓴다는, 글을 검토한 사람이 정한 규칙이다.\n고치기: 대상이나 질문을 짧게 쓴다. `파일을 엽니다`는 `파일 열기`나 `왜 파일이 열리지 않을까`로 쓴다.\n안 잡는 것: 물음표로 끝나는 질문 제목과 명사로 끝나는 제목은 잡지 않는다. 설정 headingSentenceMaxLevel(기본 6)보다\n 깊은 제목도 잡지 않는다. 절 제목 아래에 문장형 부제를 두는 형식(강의 교안의 H3 부제는 정한 형식에 따라 행동과\n 결과를 말하는 문장이다)은 그 값을 2로 두어 H2까지만 본다. 실제 강의 글 여섯 편에서 이 부제 62개가 모두\n 걸렸다.",
|
|
26
|
+
"headingSkip": "제목 수준을 건너뛴 곳. H2 다음에 바로 H4 제목이 오거나 글이 H3 제목으로 시작하는 것.\n\n왜: 목차가 계층을 잃는다. 화면 낭독 프로그램과 목차 생성기가 건너뛴 수준을 제대로 다루지 못하고, 독자는 어느\n 절 아래인지 모른다.\n어디서: markdownlint 계열의 제목 수준 검사, Wikipedia Signs of AI writing 4.10(헤더 남용).\n고치기: 한 수준씩 내려간다. frontmatter의 title이 H1이므로 본문은 H2부터 시작한다.\n안 잡는 것: 올라가는 것(H4 다음 H2)은 잡지 않는다. 절이 끝나고 새 절이 시작하는 정상 흐름이다.",
|
|
27
|
+
"headingUniform": "H2가 셋 이상인 목차에서 75% 이상이 같은 글자로 끝나는 것.\n\n왜: 목차 전체가 `기`로 끝나면 순서가 있는 과정이 아니라 같은 항목의 나열로 읽힌다.\n어디서: 실제 블로그 글 하나에서 H2 여덟 개 가운데 일곱 개가 `기`로 끝나 목차가 같은 항목의 나열처럼 읽혔다.\n 예시 제목의 어미를 그대로 따라 쓰지 않는다는 절 제목 쓰기 방식에서 왔다. 기준값은 설정\n headingUniformRatio(기본 0.75)다.\n고치기: 형태를 섞는다. `오류 원인 찾기`, `왜 파일이 열리지 않을까`, `pandas가 멈추는 곳`처럼 쓴다. 제목을 바꾸기\n 전에 그 제목을 가리키는 곳이 있는지 본다. 실제 블로그 하나는 media.json이 절 제목으로 이미지를 묶고 있어\n 제목만 고치자 이미지 연결이 깨졌다.\n안 잡는 것: H2가 둘 이하인 글과 H3 이하는 잡지 않는다. 한글 음절로 끝나지 않는 제목도 세지 않는다. 어미는\n 한글이기 때문이다. 버전과 날짜(`[0.0.2] - 2026-08-27` 같은 CHANGELOG 절), 한자 독음 괄호로 닫은 수필 제목\n (`約婚[약혼]까지의 來歷[내력]`은 `]`로 끝난다), 라틴 약어로 닫은 제목(`소스 IP`)이 여기 든다. 셋 다 기준\n 말뭉치에서 오탐이었다.\n경고로 내는 까닭: 제대로 잡은 목차와 잘못 잡은 목차가 겉으로 똑같다. `구현하기 / 사용하기 / 같이 보기`\n (제대로 잡은 것)와 `생성하기 / 적용하기 / 검증하기 / 정리하기`(쿠버네티스 태스크 문서의 관례)를 글자 모양으로는\n 가르지 못한다. 그 목차가 순서 있는 과정인지 관례인지는 사람이 본다. 표본 20건 가운데 제대로 잡은 것은\n 하나였다.",
|
|
28
|
+
"imperativePeriod": "명령형과 청유형 뒤의 마침표.\n\n왜: 한글 맞춤법은 명령·청유 문장 끝에도 마침표를 쓴다. 이 규칙은 `세요`, `십시오`, `합시다`, `해라`를 마침표\n 없이 끝내는 블로그 표기 방침이다. 한 글 안에서 기준이 갈리면 독자가 부호를 읽느라 멈춘다. blog와 guide\n 프리셋에서만 켜고, 다른 종류의 글은 enforceStyle에 넣어 켠다.\n어디서: 블로그 글쓰기 방침. eddmpython의 발행 검사가 같은 규칙을 정규식으로 막는다.\n고치기: 마침표를 지운다. `hanlint fix`가 고친다.\n안 잡는 것: 평서형 뒤의 마침표. 따옴표 안의 명령문은 문장 부호 규칙이 달라 보지 않는다.",
|
|
29
|
+
"inputFileSource": "코드가 읽는 파일과 쓰는 폴더를 글 어디에서도 만들지 않은 곳.\n\n왜: 위에서 아래로 따라 하는 독자는 그 줄에서 파일 없음 오류로 멈춘다. 글쓴이 컴퓨터에는 파일이 있어서 글쓴이는\n 모른다.\n어디서: 실제 블로그 글 하나에서 `read_excel(\"sales_small.xlsx\")`가 읽는 파일을 만드는 코드가 없었고, data 폴더도\n 어디에서도 만들지 않았다. 사람 평가자가 두 차례 검토에서 모두 짚었다. 앞선 코드가 만든 파일은 글을 위에서부터\n 읽으며 쌓은 목록에서 찾는다.\n고치기: 파일을 만드는 코드 블록을 앞에 두거나, 산문에서 그 파일을 어떻게 준비하는지 이름을 들어 말한다.\n안 잡는 것: 앞선 코드가 쓴 파일과 앞선 산문이 이름을 든 파일(독자가 준비하는 것으로 본다)은 잡지 않는다. 별표,\n URL, 서식 자리표시자가 든 경로도 잡지 않는다. 폴더는 오류가 아니라 경고로 낸다.",
|
|
30
|
+
"installImport": "설치 줄에 없는 패키지를 import하는 코드와, 코드 한 줄이 요구하는데 설치 줄에 없는 의존성.\n\n왜: 독자는 글이 시킨 설치 줄만 실행한다. 목록에 없는 패키지는 ModuleNotFoundError로 끝나고, extra가 빠진\n 백엔드는 실행 중에 멈춘다.\n어디서: 실제 블로그 글 하나가 ibis-framework[duckdb]만 설치하고 sqlite 엔진에 붙었고 사람 평가자가 짚었다.\n 모듈과 패키지 이름의 대응은 data/pythonPackages.txt, 표준 라이브러리 목록은 data/pythonStdlib.txt, 숨은\n 의존성 목록은 data/hiddenDeps.txt에 있다.\n고치기: 설치 줄에 그 패키지를 더한다. 필요하면 extra까지 적는다.\n안 잡는 것: 설치 줄이 하나도 없는 글(판단할 수 없다), 표준 라이브러리, 글이 만드는 .py 파일, 상대 import는\n 잡지 않는다. 숨은 의존성은 경고로 낸다.",
|
|
31
|
+
"introImage": "도입에 그림이 한 장을 넘는 글.\n\n왜: 도입은 독자를 첫 결과로 데려가는 부분이다. 그림이 쌓이면 스크롤이 길어지고, 실행할 수 있는 것이 첫 화면\n 밖으로 밀려난다. 도입에서 첫 결과를 보지 못한 독자는 본문을 읽지 않고 떠난다.\n어디서: 도입은 독자가 막힌 데서 시작하고 문단 넷과 그림 한 장을 넘지 않는다는 블로그 쓰기 방식에서 왔다.\n introLong이 문단만 세므로 그림은 이 규칙이 센다. 기준값은 설정 introMaxImages(기본 1)다.\n고치기: 넘치는 그림을 그것이 설명하는 본문 절로 내린다. 대표 그림 한 장만 도입에 둔다.\n안 잡는 것: H2가 없는 글(전체가 도입이라 셀 수 없다)은 잡지 않는다. 본문 절의 그림 수는 세지 않는다.",
|
|
32
|
+
"introLong": "첫 H2 앞의 산문 문단이 4개를 넘는 도입.\n\n왜: 도입은 문단 넷과 그림 한 장을 넘지 않는다. 첫 코드 블록이나 실행할 수 있는 것이 그 안에 와야 한다. 독자가\n 막힌 곳을 말하는 문단이 길어지면 그것이 다시 뒤로 미룬 배경 설명이 된다.\n어디서: 도입은 독자가 막힌 데서 시작한다는 블로그 쓰기 방식에서 왔다. 기준값은 설정 introMaxParagraphs(기본 4)다.\n고치기: 넘치는 문단을 첫 절로 내리거나 지운다. 정의 문단이면 지운다. 검색해 들어온 독자는 그것이\n 무엇인지 이미 안다.\n안 잡는 것: H2가 없는 글(전체가 도입이라 셀 수 없다)은 잡지 않는다. 본문 절이 하나뿐인 글과 도입이 전체 문단의\n 절반을 넘는 글도 잡지 않는다. 둘 다 절 구조가 없는 글이지 도입이 긴 글이 아니다. 위키뉴스 단신은 본문이\n 문단 나열이고 끝에 `## 출처` 하나가 붙어, H2가 하나 있다는 이유로 기사 전체가 도입으로 세어졌다. 제목 구조가\n 없는 수필은 도입 문단이 78개였다. 표본 20건의 오탐 11건이 모두 이런 글이었다.",
|
|
33
|
+
"japaneseLoan": "`구좌`, `익일`, `잔고`, `고참`, `망년회` 같은 일본어투 단어.\n\n왜: 순화어가 이미 자리 잡아 일본어투가 낡고 딱딱하게 읽힌다.\n어디서: 국립국어원 일본어 투 용어 순화 자료집 2005, 꼭 가려 써야 할 일본어 투 용어 50개 2019.\n 사전은 data/japaneseLoan.toml에 있다.\n고치기: 순화어로 바꾼다. `구좌`는 `계좌`로, `익일`은 `다음 날`로 쓴다.\n안 잡는 것: 앞에 한글이 붙은 경우. `최고참`의 `고참`처럼 다른 단어의 일부일 수 있어 단어가 시작하는 곳을\n 본다. 굳어진 한자어(`견적` 등)는 사전에 넣지 않았다.\n 그 종류의 글이 거의 다 쓰는 항목은 짚지 않는다. report 프리셋에서는 사업보고서 문서의 90% 이상(설정\n usageShare)에 나온 항목이다.",
|
|
34
|
+
"keywordHeading": "제목이 약속한 대표 검색어의 말이 절 제목 어디에도 없는 글.\n\n왜: 검색해 들어온 독자는 본문을 읽기 전에 목차를 훑는다. 제목에서 본 말이 목차에 한 번도 없으면 이 글이\n 자기 질문을 다루는지 확신하지 못한 채 뒤로 간다. 제목은 한 번 약속하고, 목차는 그 약속을 어디에서\n 지키는지 보여 준다.\n어디서: 실제 블로그 글 하나를 평가자 다섯이 역할을 나눠 네 차례 읽었고, 둘째 차례에 검색 독자 역할이 짚었다.\n `절 제목만 위에서 아래로 훑으면 목차 전체에 파이썬 이라는 말이 한 번도 안 나온다. 나는 브라우저\n 안에서 만드는 도구가 아니라 파이썬 코드를 찾아 들어온 사람이다.` 검색어를 읽을 필드는 설정\n keywordField가 정한다.\n고치기: 그 말이 실제로 하는 일을 맡은 절의 제목에 넣는다. 위 글이라면 `파이썬으로 QR코드 파일 만들기`다.\n 억지로 모든 제목에 넣지 않는다. 한 번이면 된다.\n안 잡는 것: keywordField를 설정하지 않은 글, 검색어가 제목에도 첫 문단에도 없는 글(그것은 keywordMissing이\n 먼저 짚는다), H2가 셋 미만인 글, 한 글자 단어는 잡지 않는다. 뜻이 같은 다른 말로 목차를 쓴 경우는 가려내지\n 못하므로 경고로만 낸다. 다른 글 하나에서는 `시작`이 목차에 없었지만 `프로젝트 폴더 열기`가 그 일을 했다.\n제목만 보지 않는 까닭: 제목에만 있는지 보면 제목에는 없고 첫 문단에만 있는 검색어가 두 규칙 사이에서\n 빠진다. keywordMissing은 제목과 첫 문단을 함께 보므로 통과시키고, 이 규칙은 제목에 없다고 건너뛴다.\n 그래서 이 규칙도 keywordMissing과 같은 곳(제목과 첫 문단)을 본다.",
|
|
35
|
+
"keywordMissing": "대표 검색어가 제목에도 첫 문단에도 없는 글.\n\n왜: 검색해서 들어온 독자는 자기가 검색창에 친 이름을 첫 화면에서 찾는다. 그 이름이 안 보이면 본문을\n 읽기 전에 뒤로 간다.\n어디서: 독자가 검색창에 친 이름과 글이 쓰는 이름이 다르면 첫 문단에서 그 차이를 말한다는 블로그 쓰기 방식에서\n 왔다. 검색어를 읽을 필드는 설정 keywordField가 정한다.\n고치기: 제목이나 첫 문단에 그 이름을 그대로 쓴다. 이름이 다르면 첫 문단에서 그 차이를 한 문장으로 말한다.\n안 잡는 것: keywordField를 설정하지 않은 글과 그 필드가 비어 있는 글은 잡지 않는다.",
|
|
36
|
+
"loneSubheading": "H2 아래 소제목이 하나뿐이고 그 제목이 절 제목의 말을 되풀이하는 곳.\n\n왜: 소제목은 절 안을 나누려고 둔다. 하나뿐이면 나눈 것이 없고, 그 하나가 절 제목과 같은 말이면\n 독자는 같은 제목을 두 번 읽는다. 목차만 길어지고 얻는 것이 없다.\n어디서: 한 절 아래에 소제목이 하나뿐이고 같은 뜻을 되풀이하면 소제목을 지운다는 블로그 쓰기 방식에서 왔다.\n고치기: 소제목을 지우고 본문을 절 제목 아래로 올린다. 정말 둘로 나뉘면 소제목을 하나 더 만든다.\n안 잡는 것: 소제목이 둘 이상인 절과 H4 이하는 잡지 않는다. 절 제목에 없는 말이 소제목에 하나라도 있으면 새\n 이야기를 여는 것이므로 하나뿐이어도 잡지 않는다. 실제 글 하나에서 `AI에게 원문과 이 페이지 주소 보내기` 아래의\n `AI에게 보낼 요청 예시`는 `AI` 하나만 겹치고 `요청`과 `예시`를 새로 꺼내므로 오탐이었다. 화제어로 어림하는\n 규칙이라 경고로만 낸다.",
|
|
37
|
+
"longSentence": "30어절을 넘는 문장.\n\n왜: 문장이 길면 독자가 주어와 서술어를 잇느라 되돌아간다. 짧은 문장과 긴 문장을 섞으라는 규칙의 상한이다.\n어디서: 실측. 블로그 다섯 편의 가장 긴 문장이 23, 33, 23, 26, 45어절이었고 30어절을 넘는 둘은 읽어 보니 한\n 문장에 목록 넷을 넣은 것이었다. 상한은 설정 longSentenceMax(기본 30)로 바꾼다.\n고치기: 마침표로 끊는다. 나열이면 목록으로 꺼낸다.\n안 잡는 것: 상한 이하의 문장. 코드와 표. 글쓰기 규칙을 어긴 것이 아니라 살펴볼 곳이라 경고로 낸다.",
|
|
38
|
+
"moreLater": "마지막 절의 목록 항목이 150자를 넘어 본문만큼 설명하는 것.\n\n왜: 글 끝의 목록은 본문에서 뺀 것을 모아 두는 곳이다. 무엇을 할 수 있는지 한 줄과 링크나 코드 한 줄이면 된다.\n 항목이 본문 문단만큼 길어지면 미룬 것이 아니라 옮겨 적은 것이고, 결말에서 끝난 글이 다시 이어진다.\n어디서: 글 끝의 목록 항목은 본문만큼 설명하지 않는다는 블로그 쓰기 방식에서 왔다. 기준값은\n 설정 moreLaterMaxChars(기본 150)이고, 실제 글 다섯 편의 마지막 절 항목 24개를 재서 정했다. 항목은 17자에서\n 196자였고 149자부터가 문장 셋 이상이었다.\n고치기: 항목을 한 줄로 줄이고 자세한 것은 링크나 코드 한 줄로 넘긴다. 정말 본문에 있어야 하면 본문 절로 올린다.\n안 잡는 것: 마지막 절이 아닌 곳의 목록(본문 목록은 설명의 일부다)과 목록이 없는 마지막 절은 잡지 않는다. 한\n 글에 한 번만 낸다. 길이로 어림하는 규칙이라 경고로만 낸다.",
|
|
39
|
+
"negationRedefine": "`단순한 X가 아닙니다` 뒤에 `Y입니다`로 다시 정의하는 두 문장 공식.\n\n왜: 부정하고 다시 정의하는 대구는 AI가 즐겨 쓰는 수사다. 독자는 X가 아니라는 말에서 정보를 얻지 못하고\n Y만 읽으면 된다.\n어디서: AI 문체 신호 조사(gist 패턴7 부정 후 재정의, im-not-ai C-8 대칭 대구).\n고치기: 앞 문장을 지우고 Y를 바로 쓴다. 필요하면 Y가 무엇을 하는지 한 문장을 더한다.\n안 잡는 것: 뒤 문장이 정의하는 문장이 아닌 경우. `단순한 도구가 아닙니다. 그래서 설치가 어렵습니다.`는 잡지\n 않는다.",
|
|
40
|
+
"noQuestion": "절이 둘 이상인데 물음표가 한 번도 없는 글.\n\n왜: 물음표가 없다는 것은 관찰한 사실일 뿐 잘못이라는 뜻이 아니다. 질문 없이 설명하는 글도 바른 글이므로 기본은\n 경고다. 질문을 요구하는 사용자가 설정 enforceStyle에 이 규칙을 넣었을 때만 오류로 낸다.\n어디서: 독자가 품을 물음을 글이 먼저 묻고 답한다는 쓰기 방식에서 왔다.\n고치기: 설명만으로 충분하면 그대로 둔다. 질문이 필요한 곳에서만 독자의 의문을 묻고 다음 문장으로 답한다.\n 물음표를 넣으려고 이미 분명한 문장을 바꾸지 않는다.\n안 잡는 것: 절이 하나뿐인 짧은 참고 문서는 잡지 않는다. 제목의 물음표도 센다. 물음은 없는데 독자에게 말을 거는\n 문장은 있는 글도 잡는다(질문을 쓸지는 사람이 판단한다). 독자에게 말을 거는 문장만 세던 규칙 readerAbsent는 이\n 규칙이 잡는 것에 모두 들어 있어 이 규칙으로 합쳤다.",
|
|
41
|
+
"nounPile": "명사 5개 이상이 조사 없이 이어진 곳. 그 종류의 글에서 관용으로 쓰는 연쇄는 짚지 않는다.\n\n왜: `가상환경 생성 후 패키지 설치 확인`은 무엇이 무엇의 목적어인지 표시되어 있지 않다. 독자가 조사를\n 끼워 넣어야 읽힌다. 글자 모양으로 어림하는 규칙이라 기본은 경고이고, 설정 enforceStyle에 넣으면\n 오류로 낸다.\n어디서: 명사를 쌓지 말고 동사로 되돌린다는 글쓰기 원칙. im-not-ai A-13, F-4. 몇 개부터 잡을지는 설정\n nounPileMin(기본 5)이 정한다. `파이썬 데이터프레임 라이브러리`처럼 넷까지는 흔해서 다섯부터 짚는다.\n고치기: 기술 용어는 그대로 두고 명사 사이의 관계를 조사와 동사로 밝힌다. 예: `가상환경을 만든 뒤\n 패키지가 설치됐는지 확인한다.`\n안 잡는 것: 쉼표로 나열한 고유명사(pandas, Polars, DuckDB). 쉼표가 연속을 끊는다. 기준보다 짧은 복합어.\n 용례가 있는 연쇄: 문장의 긴 연쇄가 전부 그 종류의 빈도표(data/usageCounts.<종류>.json)에 문서 3편(설정\n usageMin) 이상으로 있으면 관용이다. `정관상 배당절차 개선방안 이행 가부`는 사업보고서가 쓰는 말이지 쌓은\n 것이 아니다. 종류는 프리셋이 정하고 지금은 report 프리셋만 있다. 실측: 사업보고서 961편 747,583문장에서\n 관용 연쇄를 빼기 전에는 1,000문장당 6.2건, 뺀 뒤에는 4.8건이다(22.6% 감소). 빠진 것은 양식의 항목\n 이름(`정관상 배당절차 개선방안 이행 가부`, 661편)과 관용 용어(`무기명식 이권부 무보증 사모 전환사채`,\n 17편)이고 남은 것은 한 회사의 사업 이름처럼 그 글에서만 쌓은 명사다.",
|
|
42
|
+
"numberOrphan": "`A에서 B로`라고 비교하는데 A가 글 앞에 한 번도 나온 적 없는 경우.\n\n왜: 독자는 앞에서 본 값을 기준으로 변화를 읽는다. 기준값이 그 문장에서 처음 나오면 무엇에서 무엇으로\n 움직인 것인지 알 수 없고, 앞으로 되돌아가 찾다가 없다는 것을 확인하고 멈춘다.\n어디서: 실측. 실제 블로그 글의 `이 5백만 줄 표를 넘길 때 파이썬이 잡은 메모리 최대치는 453MB에서 700MB로\n 올라갔습니다`를 평가자가 지적했다. 453MB가 앞의 어떤 실행에도 없었다. 새로 나온 값과 옵션은 무엇인지,\n 왜 그 값인지, 독자가 지금 무엇을 하면 되는지를 그 자리에서 알려 준다는 글쓰기 원칙.\n고치기: 기준값이 어디서 나온 것인지 한 문장으로 밝히거나, 그 값을 만든 실행을 앞에 둔다.\n안 잡는 것: 한 자리 수(재는 값이 아니라 세는 말이다). 앞선 문장, 코드 블록, 출력, 표, 목록, 제목에 이미\n 나온 값. 같은 문장 안에서 앞서 나온 값. 값 바로 앞에서 그 값의 출처를 밝힌 경우(`1년 전 26.14%에서\n 18.53%로`는 어디서 온 값인지 이미 말했다. 실측에서 오탐이었고 data/baselineAnchors.txt로 걸렀다).\n 겉으로 보이는 글자로 어림해 세는 규칙이라 경고로만 낸다.",
|
|
43
|
+
"outsideProfile": "같은 종류의 글에서 백 문장에 하나도 안 되는 값(문장 길이, 쉼표, 처음 나온 화제어, 얼버무리는 말)을 가진 문장.\n\n왜: 독자는 그 종류의 글에서 늘 보던 만큼을 기대한다. 편집된 글 수천 문장 가운데 1%도 안 되는 길이나 새 화제어\n 수는 그 독자가 그 종류에서 겪지 않던 부담이다. 좋다 나쁘다가 아니라 어디가 다른지를 말한다.\n어디서: 실측. 기준 말뭉치 390편에서 30어절을 넘는 문장이 안내서 0.16%, 기술 문서 0.87%, 뉴스 6.7%, 1930년대\n 수필 8.3%였다. 기준값 하나로는 종류마다 열 배씩 다르게 잡힌다. 종류별 분포를 백분위로 보이는 것은\n Coh-Metrix가 영어에서 한 방식이고 한국어에는 없었다. 프로파일은 data/profiles.json에 있고 말뭉치에서\n 만든다. 몇 백분위부터 잡을지는 설정 profilePercentile(기본 99)이 정한다. 처음 나온 화제어는 독자가 앞\n 문장들에서 읽지 않은 화제어로 센다.\n고치기: 문장을 나누거나 쉼표 절을 문장으로 세운다. 처음 나온 화제어가 많으면 앞 문장에서 하나씩 먼저 세운다.\n 얼버무리는 말은 수치나 조건으로 바꾼다.\n안 잡는 것: 프리셋에 프로파일이 없는 종류. 99% 값이 0인 지표(거의 나오지 않는 지표라 하나만 있어도 상위 1%에\n 들어 가려낼 것이 없다). 상위 1%는 정의상 백 문장에 하나라 경고로만 낸다. `--profile`이 가리키는 사용자\n 프로파일이 있으면 종류 대신 그것과 비교한다.",
|
|
44
|
+
"paraFragment": "한두 문장짜리 산문 문단이 3개 이상 연달아 오는 곳.\n\n왜: 설명글에 줄바꿈을 마구 넣으면 이유로 이어야 할 문장 사이가 모두 끊긴다. 독자는 조각 사이의 관계를 다시\n 세워야 한다.\n어디서: 설명글에는 줄바꿈을 함부로 넣지 않는다는, 글을 검토한 사람이 정한 규칙이다. 설명을 풀어 쓴다는 블로그\n 쓰기 방식도 같은 것을 요구한다. 기준값은 설정 fragmentRun(기본 3)이다.\n고치기: 화제가 같으면 한 문단으로 묶는다. 줄바꿈은 화제가 바뀌는 곳에만 둔다.\n안 잡는 것: 사이에 코드 블록이나 표가 끼면 처음부터 다시 센다. 코드 앞뒤에 한 문장씩 놓는 것은 글을 조각낸 것이\n 아니라 설명이다. 목록은 세지 않는다.",
|
|
45
|
+
"phraseRepeat": "한 글이 같은 문형을 되풀이해 쓰는 경우. 문장 하나하나가 아니라 글 안의 비율로 짚는다.\n\n왜: `X가 아니라 Y다`는 한 번은 멀쩡한 한국어다. 되풀이하면 글이 같은 소리로 읽힌다. 그래서 한 번 쓴\n 것까지 잡으면 바르게 쓴 문장도 잡힌다.\n어디서: 실측. 사람 글 4,021편(위키백과 본문 1,642, 지침 931, 토론 1,304, 사업보고서 144)과 기계 글 360편에서\n 문서마다 비율을 재서, 사람 글 100편 가운데 99편이 넘지 않는 값보다 높게 기준값을 잡았다. 사람 글은\n 100편 가운데 99편이 3.4% 이하이고(두 번 이상 나온 것만 셀 때), 기준값 8%에서는 사람 글 0.17%, 기계 글 20%가\n 걸린다. 사전과 기준값은 data/phraseRepeat.toml에 있다. 문형은 두 말뭉치를 비교해 찾았다(1,000문장당 사람\n 7.05, 기계 65.55). `~하는 편이 낫다`는 후보였다가 두 번 이상 나온 글로 세면 기계 글이 1%만 걸려 뺐다.\n고치기: 되풀이된 문장 가운데 덜 필요한 것을 바로 말하는 문장으로 바꾼다. 한 편에 한 번은 남겨도 된다.\n 걸린 문장은 전부 센다. 지적은 하나지만 이유에 줄 번호를 모두 적는다. 하나만 인용하면 고치는 쪽이\n 나머지를 정규식으로 다시 찾아야 한다. 한 줄에 여러 문장이 있으면 그 줄은 한 번만 적는다.\n안 잡는 것: 산문 문장이 8개보다 적은 글. 종결어미가 없는 줄(제목, 항목명, 표의 칸). 기준값 이하의 되풀이.\n 두 번보다 적게 나온 문형: 한 번 쓴 글은 비율이 기준값을 넘어도 잡지 않는다. 겉으로 보이는 글자로\n 어림하는 규칙이라 경고로 낸다.",
|
|
46
|
+
"platformApi": "한 운영체제에서만 도는 API나 경로를 쓴 코드.\n\n왜: 다른 운영체제의 독자는 앞을 다 따라 하고도 그 줄에서 AttributeError로 멈춘다. 글쓴이 컴퓨터에서는 돌아서\n 글쓴이는 모른다.\n어디서: 실제 블로그 글 하나에서 peak_wset이 윈도우에서만 나와 사람 평가자가 짚었다. 목록은 data/platformApis.txt에\n 있다.\n고치기: 그 줄이 어느 운영체제 전용인지 적고 대안을 준다. 또는 여러 운영체제에서 도는 API로 바꾼다.\n안 잡는 것: 목록에 없는 API와 산문 안의 언급은 잡지 않는다. 경고로만 낸다.",
|
|
47
|
+
"promiseRecall": "`뒤에서 다루겠습니다`라고 미뤄 놓고, 미룬 이야기를 다시 언급하는 말이 글 어디에도 없는 것.\n\n왜: `뒤에서 다루겠습니다`를 써 놓고 끝까지 안 나오면 나눠 설명한 것이 아니라 빠뜨린 것이다. 미룬 이야기를\n 다시 다룰 때는 미뤘다는 사실을 밝히고 앞에서 쓴 이름을 다시 쓴다.\n어디서: 미룬 이야기는 같은 글 안에서 다시 다룬다는 블로그 쓰기 방식에서 왔다. 이런 검사를 하는 다른 도구는\n 찾지 못했다. 찾는 말 목록은 data/promiseMarkers.txt와 data/recallMarkers.txt에 있다. 미루는 말과 다시\n 언급하는 말은 글을 문장 순서대로 읽으며 모으고, 글을 끝까지 읽은 뒤에 따진다.\n고치기: 뒤 절에서 `앞에서 미룬 X`라고 밝히며 다룬다. 다시 다루지 못할 것은 처음부터 미루지 말고 지운다.\n안 잡는 것: 다시 언급하는 말이 하나라도 있는 글은 잡지 않는다. 어느 약속을 어느 말이 다시 다뤘는지는 맞춰 보지\n 않는다. 찾는 말 목록으로 어림하는 규칙이라 경고로만 낸다.",
|
|
48
|
+
"redundantPair": "`역전 앞`, `그때 당시`, `매 시간마다` 같은 겹말.\n\n왜: 뜻이 같은 두 말을 겹쳐 쓴 것이라 한쪽이 군더더기다.\n어디서: 국립국어원 새국어생활 2005 한규희 「겹말은 가능한 한 줄이자」, 법조신문 「넘쳐나는 겹말들」.\n 사전은 data/redundantPair.toml에 있다.\n고치기: 하나만 남긴다. `역전 앞`은 `역 앞`으로, `그때 당시`는 `그때`로 쓴다.\n안 잡는 것: 뜻을 강조하려고 일부러 겹친 말. 사전에 없는 겹말.\n 그 종류의 글이 거의 다 쓰는 항목은 짚지 않는다. report 프리셋에서는 사업보고서 문서의 90% 이상(설정\n usageShare)에 나온 항목이다.",
|
|
49
|
+
"screenNarration": "화면이 자기를 설명하는 말. 빈 상태의 예고, `이 화면은`, `잠시 뒤 다시`, `할 수 있습니다`.\n\n왜: 빈 상태에 \"오면 여기에 표시됩니다\"를 두면 사용자는 없는 것을 읽는다. \"이 화면은 비밀번호로 엽니다\"는 제목이\n 이미 한 말이다. \"잠시 뒤 다시 시도해 주세요\"는 실패를 감싸는 위로이고, 다시 시도는 버튼이 한다. \"볼 수\n 있습니다\"는 버튼과 입력란이 이미 보여 주는 기능을 글로 되풀이한다. 넷 다 정보가 아니라 해설이다.\n어디서: 실제 운영 중인 앱의 화면 글을 검토해 정한 규칙이다.\n실측: 운영 화면 \"계약 신청이 도착하면 여기에 표시됩니다\",\n \"내려받기 페이지에서 요청이 오면 여기에 표시됩니다\", \"이 화면은 비밀번호로 엽니다. 비밀번호는 이 탭에서만 기억합니다\",\n 수집 화면 \"진행 상태를 갱신하지 못했습니다. 저장된 자료는 유지되며 잠시 뒤 다시 확인합니다\".\n 사전은 data/screenNarration.toml에 있고 설정 dictionary.screenNarration으로 항목을 더한다.\n고치기: 빈 상태는 `<대상> 없음`(요청 없음, 계약 없음)으로 쓴다. 화면이 자기를 설명하거나 기능을 설명하는 말은\n 지운다. 다시 시도하라는 문장은 `<대상> <동작> 실패`로 줄이고 다시 시도 버튼을 둔다. 문장이 허용된 글에서도\n 같은 말은 군더더기라서 enforceStyle에 넣어 켜고 검사한다.\n안 잡는 것: 사전에 없는 해설, \"이 컴퓨터\"나 \"이 회사\"처럼 화면이 아닌 것을 가리키는 지시어는 잡지 않는다. screen\n 프리셋이 아니면 enforceStyle에 넣어야 돈다.",
|
|
50
|
+
"screenSentence": "단어를 써야 할 곳에 놓인 문장. 진행, 실패, 요구, 완료를 종결어미로 쓴 화면 글.\n\n왜: 화면 글은 데이터의 이름과 사용자가 하는 동작의 이름이다. 빈 상태는 `<대상> 없음`, 진행은 `<동작> 중`, 실패는\n `<대상> <동작> 실패`, 요구는 `<대상> 필요`, 끝난 일은 상태를 나타내는 단어 하나(`승인됨`)로 쓴다. 문장은\n 제목이 이미 말한 것을 되풀이하거나 화면을 해설하고, 사용자는 단어만 읽고 문장은 건너뛴다.\n어디서: 실제 운영 중인 앱의 화면 글을 검토해 정한 규칙이다.\n실측: 운영 화면 \"요청을 완료하지 못했습니다\", 설치 페이지\n \"상태를 확인하지 못했습니다.\", 온보딩 \"대시보드를 열고 있습니다\", 진단 화면 \"자료 갱신을 위한 로그인이 필요합니다\".\n 사전은 data/screenSentence.toml에 있고 설정 dictionary.screenSentence로 항목을 더한다.\n고치기: 종결어미를 떼고 단어로 만든다. `요청을 완료하지 못했습니다`는 `요청 실패`, `대시보드를 열고 있습니다`는\n `대시보드 여는 중`, `로그인이 필요합니다`는 `로그인 필요`, `변경을 완료했습니다`는 `변경됨`으로 쓴다. 문장이\n 꼭 필요한 글(장표, 고지, 실패 원인)은 문장이 허용된 글 모듈로 옮기고 chat 프리셋으로 검사한다.\n안 잡는 것: 종결어미가 없는 글은 잡지 않는다. screen 프리셋에서만 켜지고, 산문 프리셋에서는 문장이 정상이라\n 꺼진다. 문장 하나에 걸리는 형태가 여럿이면 가장 앞의 것 하나만 짚는다.",
|
|
51
|
+
"screenTone": "손님을 대하듯 높이는 말투. `언제든`, `안심`, `살펴보세요`, `하시면`, `보여드립니다`.\n\n왜: 화면은 손님을 맞는 점원이 아니다. 안심시키는 말(`언제든 바꿀 수 있습니다`)에는 정보가 없고, 권하는 말(`준비된\n 회사부터 살펴보세요`)은 버튼이 할 일을 글로 대신하며, 높이는 말(`로그인하시면 보여드립니다`)은 단어로 쓸 곳을\n 문장으로 늘린다. 사용자는 그 말을 읽지 않고 건너뛰거나, 읽고 나서 화면을 믿지 못한다.\n어디서: 실제 운영 중인 앱의 화면 글을 검토해 정한 규칙이다.\n실측: 온보딩 \"설정에서 언제든 지울 수 있습니다\",\n \"위하고에 로그인하시면 담당 수임처를 찾아 보여드립니다\", \"이렇게 부르겠습니다\", 수집 화면 \"준비된 회사부터 바로\n 살펴보세요\". 사전은 data/screenTone.toml에 있고 설정 dictionary.screenTone으로 항목을 더한다.\n고치기: 지운다. 그곳에 정보가 있었으면 단어로 남긴다(`적지 않으셔도 됩니다`는 `선택`, `이렇게 부르겠습니다`는\n `호칭 미리보기`). 문장이 허용된 글에서도 같은 말은 군더더기라서 enforceStyle에 넣어 켜고 검사한다.\n안 잡는 것: 사전에 없는 말투는 잡지 않는다. 보고서와 장표의 권고(`받으십시오`)는 권하는 말이 아니라 해야 할 조치라서\n 사전에 없다. screen 프리셋이 아니면 enforceStyle에 넣어야 돈다.",
|
|
52
|
+
"screenWord": "화면의 단어. 개발 용어(메타데이터, 컴포넌트, 트랜잭션)와, 프로젝트가 한 이름으로 정한 단어를 다른 이름으로 쓴 곳.\n\n왜: 화면 글은 데이터의 이름과 사용자가 하는 동작의 이름이다. 용어에 설명이 필요한지는 독자와 문맥에 달려 있다.\n 프로젝트가 같은 대상을 두 이름으로 부르면 사용자는 둘이 다른 것인지 묻는다. 프로젝트에서 한 이름으로 정한\n 규약은 사전으로 확인하고, 일반 기술 용어는 이름을 바꾸지 않고 뜻을 설명한다.\n어디서: 실제 운영 중인 앱의 화면 글을 검토해 정한 규칙이다.\n실측: 화면 글 4,177개를 검토해 용어 불일치 224건과\n 개발 용어 77건을 찾았는데 산문 규칙은 하나도 짚지 못했다. 설명이 필요한지 검토할 기본 용어는\n data/screenWord.toml에 있고, 프로젝트가 정한 단어는 설정 dictionary.screenWord로 더한다. 같은 곳에 기본 항목과\n 설정 항목이 함께 걸리면 설정 항목을 따른다.\n고치기: 기본 사전은 용어 설명이 필요한지 검토해 달라는 경고만 내고 바꿀 말을 제안하지 않는다. 기술 용어를\n 설명하는 화면에서는 이름을 그대로 두고 정의와 예시를 붙인다. 프로젝트가 직접 정한 dictionary.screenWord의\n 용어 규약만 오류와 고친 글을 낸다. 강의 자료를 검토할 때 `쿼리`를 `조회`로, `원자적`을 `한 번에`로 바꾸는\n 기본 사전 항목이 뜻을 바꾼 일이 있었다. 낯선 용어라는 이유로 다른 명사를 만들지 않는다.\n안 잡는 것: 사전에 없는 말, 다른 단어 안에 든 말(`온라인`에 든 `라인`, `파이프라인`), 백틱과 따옴표로 감싼 인용은\n 잡지 않는다. screen 프리셋이 아니면 enforceStyle에 넣어야 돈다.",
|
|
53
|
+
"sectionNoProse": "설명글 없이 코드, 표, 이미지만 있는 절.\n\n왜: 절은 제목, 시각 자료, 설명글, 그리고 설명을 돕는 예시로 짠다. 코드와 표만 쌓인 절에서는 독자가 무엇을\n 보는지 모른다.\n어디서: 절은 제목, 소제목, 시각 자료, 설명글, 예시로 짠다는, 글을 검토한 사람이 정한 규칙이다.\n고치기: 코드가 하는 일을 한 문장으로 먼저 말하고 그다음에 이름을 하나씩 푼다.\n안 잡는 것: 목록만 있는 절(`더 해 볼 것`)은 목록 안에 설명이 들어 있으므로 잡지 않는다. 빈 절도 잡지 않는다.",
|
|
54
|
+
"spacing": "`할수 있다`, `것같다`, `떠난지 3년`, `한번도`, `두번`, `수 밖에`, `뿐만아니라`처럼 자주 틀리는 띄어쓰기.\n\n왜: 의존 명사와 단위 명사는 띄어 쓰고 조사는 붙여 쓴다는 규칙이 가장 자주 틀리는 곳이다. 틀리면 독자가 단어의\n 경계를 다시 찾는다.\n어디서: 국립국어원 한글 맞춤법 제5장 띄어쓰기(제41항 조사, 제42항 의존 명사, 제43항 단위 명사). 항목마다 근거가\n 붙어 있다(data/spacing.toml). 관형형 `ㄹ` 뒤의 의존 명사는 받침을 묶어 쓰는 표기 `{ㄹ}`로 잡는다.\n고치기: 항목마다 띄어 쓰거나 붙여 쓴 글을 낸다. hanlint fix가 적용한다.\n안 잡는 것: `뿐`, `만큼`, `대로`는 잡지 않는다(체언 뒤 조사와 관형형 뒤 의존 명사를 글자 모양으로 가르지 못한다).\n `못하다`와 `못 하다`, `안되다`와 `안 되다`도 뜻에 따라 둘 다 맞아서 잡지 않는다. `실수`, `술수`처럼 `ㄹ` 받침\n 명사 뒤의 `수`와, `물때`, `밀물때`, `썰물때`처럼 한 단어인 `때`도 잡지 않는다(`물 때`와 글자 모양이 같아 그곳은\n 둘 다 짚지 않는다). 백틱과 따옴표 안의 인용, 설정 protectedTerms와 겹치는 곳도 잡지 않는다.",
|
|
55
|
+
"spelling": "`됬`, `돼고`, `않 해`, `왠일`, `몇일`, `금새`, `오랫만`, `어떻해`, `할께`, `바램`처럼 자주 틀리는 표기.\n\n왜: 틀린 표기는 독자가 먼저 알아채고, 그 순간 글보다 글쓴이를 본다. 사람 작가가 가장 자주 지적받는 곳이고\n 모두 규칙으로 잡을 수 있다.\n어디서: 국립국어원 한글 맞춤법(제27항 붙임 2 며칠, 제35항 붙임 2 되어→돼, 제53항 -ㄹ게, 제56항 -든지),\n 온라인가나다 답변, 표준국어대사전 표제어. 항목마다 근거가 붙어 있다(data/spelling.toml).\n고치기: 항목마다 고친 표기를 낸다. hanlint fix가 적용한다.\n안 잡는 것: 뜻에 따라 둘 다 맞는 경우(`데`/`대`, `이따가`/`있다가`, `못하다`/`못 하다`, `한번`/`한 번`,\n `안되다`/`안 되다`), 백틱과 따옴표 안의 인용, 사전에 없는 표기는 잡지 않는다.",
|
|
56
|
+
"tableOddCell": "한 열이 모두 같은 단위로 잰 값인데 한 칸만 다른 것을 담은 표.\n\n왜: 독자는 표의 한 열을 같은 잣대로 훑는다. 그 가운데 한 칸만 다른 것을 재고 있으면 훑던 눈이 그 칸에서\n 멈추고, 그 칸이 다른 뜻이라는 것을 본문에서 다시 찾아야 한다.\n어디서: 실제 블로그 글 하나의 라이브러리 여섯 개 비교표에서, 시간 열의 아홉 칸 가운데 여덟 칸이 초 단위인데\n 한 칸이 `직접 부르지 않음`이었다. 메모리 열도 여덟 칸이 MB 단위인데 한 칸이 `넘길 때 453MB 에서 700MB`였다.\n 평가자가 표를 훑다가 열의 뜻이 바뀌는 칸에서 멈춘다고 짚었다. 한 열에 값이 네 칸 이상일 때만 본다(설정\n tableOddCellMinRows, 기본 4).\n고치기: 그 칸을 같은 단위로 다시 재거나, 그 줄을 표에서 빼서 본문 문장으로 옮긴다. 표에 남겨야 하면 열을\n 나눠 다른 단위라는 것을 열 제목으로 보인다.\n안 잡는 것: 값이 네 칸보다 적은 열, 첫 열(이름 열이라 잰 값이 아니다), 빈 칸과 `-`는 잡지 않는다. 다른 칸이\n 둘 이상인 열도 잡지 않는다(그 열은 원래 자유롭게 적는 열이다). 단위로 어림하는 규칙이라 경고로만 낸다.",
|
|
57
|
+
"translationese": "`~에 있어서`, `~에 의해`, `~을 통해`, `~로부터`, `~에도 불구하고` 같은 번역투.\n\n왜: 영어와 일본어 구문을 그대로 옮긴 표현이라 한국어로 읽을 때 매끄럽지 않다. 독자가 머릿속에서\n 다시 번역한다.\n어디서: 국립국어원 새국어생활 1990과 2012, urimal.org 김민지 2020, egowriting 번역투 고치기,\n kubernetes.io 한국어 현지화 가이드. 사전은 data/translationese.toml에 있다.\n고치기: 항목마다 고친 예가 있다. `에 있어서`는 `에서`로, `음에도 불구하고`는 `지만`으로 쓴다. 기계가\n 바꿀 수 있는 것은 `hanlint fix`가 고친다. `로부터`는 받는 사람이면 `에게`, 출발점이면 `에서`라 기계가\n 고르지 않는다.\n안 잡는 것: 사전에 없는 번역투. 무생물 주어 타동사 구문처럼 구문 분석이 필요한 것은 잡지 않는다. 그 종류의\n 글이 거의 다 쓰는 항목은 그 종류의 말이라 짚지 않는다. report 프리셋에서는 사업보고서 문서의 90%\n 이상(설정 usageShare)에 나온 항목(`에 대한`, `을 통해`, `로부터`, `에 관한`, `로 인해`, `을 위해`, `에 대해`,\n `에 의해`)이다. 실측: 사업보고서 200편 171,276문장에서 번역투 지적은 1,000문장당 289.8건이었고 그중\n 254건이 이 여덟 항목이었다."
|
|
56
58
|
}
|