@tienne/gestalt 0.69.0 → 0.70.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.
- package/CLAUDE.md +1 -0
- package/dist/package.json +1 -1
- package/dist/plugin/role-agents/humanize-monolith/AGENT.md +89 -11
- package/dist/src/cli/commands/humanize-check.d.ts +2 -0
- package/dist/src/cli/commands/humanize-check.d.ts.map +1 -1
- package/dist/src/cli/commands/humanize-check.js +11 -5
- package/dist/src/cli/commands/humanize-check.js.map +1 -1
- package/dist/src/cli/commands/humanize-scan.d.ts +23 -0
- package/dist/src/cli/commands/humanize-scan.d.ts.map +1 -0
- package/dist/src/cli/commands/humanize-scan.js +30 -0
- package/dist/src/cli/commands/humanize-scan.js.map +1 -0
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +11 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/humanize/check.d.ts +75 -7
- package/dist/src/humanize/check.d.ts.map +1 -1
- package/dist/src/humanize/check.js +241 -30
- package/dist/src/humanize/check.js.map +1 -1
- package/dist/src/humanize/detectors.d.ts.map +1 -1
- package/dist/src/humanize/detectors.js +7 -8
- package/dist/src/humanize/detectors.js.map +1 -1
- package/dist/src/humanize/index.d.ts +3 -2
- package/dist/src/humanize/index.d.ts.map +1 -1
- package/dist/src/humanize/index.js +3 -2
- package/dist/src/humanize/index.js.map +1 -1
- package/dist/src/humanize/rules.d.ts +12 -0
- package/dist/src/humanize/rules.d.ts.map +1 -1
- package/dist/src/humanize/rules.js +4 -0
- package/dist/src/humanize/rules.js.map +1 -1
- package/dist/src/humanize/scan.d.ts +24 -0
- package/dist/src/humanize/scan.d.ts.map +1 -0
- package/dist/src/humanize/scan.js +65 -0
- package/dist/src/humanize/scan.js.map +1 -0
- package/package.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/role-agents/humanize-monolith/AGENT.md +89 -11
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 윤문 전에 원문을 훑어 "이번에 볼 룰"만 추린다.
|
|
3
|
+
*
|
|
4
|
+
* 룰북은 59개까지 자랐다. 매번 전부 펼치면 모델이 나눠 쓰는 주의가 룰마다 얇아진다.
|
|
5
|
+
* 실제로 걸린 서너 개는 안 걸린 쉰 개에 묻힌다. 스캔은 그 반대로 간다 —
|
|
6
|
+
* 걸린 룰만 처방과 함께 내놓는다. 나머지는 아예 말하지 않는다.
|
|
7
|
+
*
|
|
8
|
+
* 탐지기가 없는 S1은 목록으로만 넘긴다. 코드가 못 가리는 자리를 가린다고 하면
|
|
9
|
+
* 그게 더 나쁜 거짓말이다.
|
|
10
|
+
*/
|
|
11
|
+
import { detect, DETECTABLE_RULE_IDS } from './detectors.js';
|
|
12
|
+
import { parseRuleBook, ruleLabel, s1Ids } from './rules.js';
|
|
13
|
+
export function scan(text, options = {}) {
|
|
14
|
+
const register = options.register ?? 'doc';
|
|
15
|
+
const book = options.book ?? parseRuleBook();
|
|
16
|
+
const targets = s1Ids(book, register);
|
|
17
|
+
const detectable = new Set(DETECTABLE_RULE_IDS);
|
|
18
|
+
const hits = detect(text, targets)
|
|
19
|
+
.map((found) => ({
|
|
20
|
+
ruleId: found.ruleId,
|
|
21
|
+
label: ruleLabel(book, found.ruleId),
|
|
22
|
+
count: found.count,
|
|
23
|
+
samples: found.samples,
|
|
24
|
+
prescription: book.rules.get(found.ruleId)?.prescription ?? '',
|
|
25
|
+
}))
|
|
26
|
+
.sort((a, b) => b.count - a.count || a.ruleId.localeCompare(b.ruleId));
|
|
27
|
+
const s1Total = hits.reduce((sum, hit) => sum + hit.count, 0);
|
|
28
|
+
return {
|
|
29
|
+
register,
|
|
30
|
+
s1Total,
|
|
31
|
+
hits,
|
|
32
|
+
unverifiable: targets.filter((id) => !detectable.has(id)),
|
|
33
|
+
worthHumanizing: s1Total > 0,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function formatScan(report) {
|
|
37
|
+
if (!report.worthHumanizing) {
|
|
38
|
+
// 직접 확인할 룰을 먼저 세운다. "윤문하지 않는다"를 앞에 두면 그 한 줄만 읽고
|
|
39
|
+
// 비탐지 룰 확인을 건너뛰게 된다 — 탐지기가 0건이라고 글이 깨끗한 건 아니다.
|
|
40
|
+
return [
|
|
41
|
+
`[스캔] ${report.register} 기준 S1 0건 (탐지기가 가리는 범위)`,
|
|
42
|
+
'',
|
|
43
|
+
'아래 룰은 탐지기가 못 가린다. 직접 읽어서 확인한다.',
|
|
44
|
+
` ${report.unverifiable.join(' ')}`,
|
|
45
|
+
'',
|
|
46
|
+
'여기서도 걸리는 게 없으면 윤문하지 않고 원문을 그대로 낸다.',
|
|
47
|
+
].join('\n');
|
|
48
|
+
}
|
|
49
|
+
const lines = [
|
|
50
|
+
`[스캔] ${report.register} 기준 S1 ${report.s1Total}건 (${report.hits.length}종)`,
|
|
51
|
+
'',
|
|
52
|
+
'이번에 걷어낼 룰',
|
|
53
|
+
];
|
|
54
|
+
for (const hit of report.hits) {
|
|
55
|
+
lines.push(`- ${hit.label} ${hit.count}건`);
|
|
56
|
+
for (const sample of hit.samples) {
|
|
57
|
+
lines.push(` "${sample}"`);
|
|
58
|
+
}
|
|
59
|
+
if (hit.prescription)
|
|
60
|
+
lines.push(` 처방: ${hit.prescription}`);
|
|
61
|
+
}
|
|
62
|
+
lines.push('', '탐지기가 못 가리는 S1 (직접 확인)', ` ${report.unverifiable.join(' ')}`, '', '위 목록 밖의 룰은 이번 텍스트에서 안 걸렸다. 찾아 나서지 않는다.');
|
|
63
|
+
return lines.join('\n');
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/humanize/scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAuC,MAAM,YAAY,CAAC;AAyBlG,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,UAA2B,EAAE;IAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC;IAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,aAAa,EAAE,CAAC;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAEhD,MAAM,IAAI,GAAc,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;SAC1C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACf,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QACpC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,IAAI,EAAE;KAC/D,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAEzE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAE9D,OAAO;QACL,QAAQ;QACR,OAAO;QACP,IAAI;QACJ,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzD,eAAe,EAAE,OAAO,GAAG,CAAC;KAC7B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;QAC5B,gDAAgD;QAChD,+CAA+C;QAC/C,OAAO;YACL,QAAQ,MAAM,CAAC,QAAQ,yBAAyB;YAChD,EAAE;YACF,gCAAgC;YAChC,KAAK,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YACpC,EAAE;YACF,oCAAoC;SACrC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,QAAQ,MAAM,CAAC,QAAQ,UAAU,MAAM,CAAC,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI;QAC3E,EAAE;QACF,WAAW;KACZ,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;QAC3C,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,QAAQ,MAAM,GAAG,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,GAAG,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,IAAI,CACR,EAAE,EACF,uBAAuB,EACvB,KAAK,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EACpC,EAAE,EACF,wCAAwC,CACzC,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gestalt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.0",
|
|
4
4
|
"description": "Gestalt psychology-driven AI development harness. Transforms scattered requirements into structured, validated specifications through interactive interviews.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tienne"
|
|
@@ -72,13 +72,44 @@ S2
|
|
|
72
72
|
|
|
73
73
|
## 3단계 프로세스 (윤문 모드)
|
|
74
74
|
|
|
75
|
+
### 0단계 — 스캔 (룰을 좁힌다)
|
|
76
|
+
|
|
77
|
+
원문이 파일로 있으면 먼저 스캔을 돌린다. 말투는 산문이 `doc`, 리뷰 코멘트와 슬랙이 `chat`,
|
|
78
|
+
보고서가 `report`다.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
gestalt humanize-scan --file <원문> --register <doc|chat|report>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
종료 코드로도 답한다. 걸린 게 있으면 0, 탐지기가 가리는 범위에서 0건이면 10이다.
|
|
85
|
+
파일이 없으면 3이다. 셸에서 분기할 때 stdout 을 파싱하지 않아도 된다.
|
|
86
|
+
|
|
87
|
+
스캔이 내놓는 것만 본다.
|
|
88
|
+
|
|
89
|
+
- **걸린 룰**: ID, 건수, 실제 표현, 처방이 함께 나온다. 이번 윤문의 작업 목록이다
|
|
90
|
+
- **탐지기가 못 가리는 S1**: ID 목록만 나온다. 이건 직접 읽어서 판단한다
|
|
91
|
+
- **그 밖의 룰**: 이번 텍스트에서 안 걸렸다. 찾아 나서지 않는다
|
|
92
|
+
|
|
93
|
+
룰북은 59개까지 자랐다. 매번 전부 펼치면 실제로 걸린 서너 개가 안 걸린 쉰 개에 묻힌다.
|
|
94
|
+
스캔은 이번에 볼 목록을 좁히는 장치다. 목록 밖의 룰을 굳이 뒤지면 그 자리에서 과윤문이 시작된다.
|
|
95
|
+
|
|
96
|
+
**S1 0건이면 윤문하지 않는다.** 탐지기가 가리는 범위에서 걸리는 게 없고 직접 확인할 룰도
|
|
97
|
+
안 보이면, 원문을 그대로 돌려주고 그렇게 말한다. 고칠 게 없는 글에 윤문을 돌리면 남는 건
|
|
98
|
+
과윤문뿐이다.
|
|
99
|
+
|
|
100
|
+
인라인 텍스트만 받아 스캔을 못 돌리는 경우에만 룰북을 직접 읽는다. 이때도 말투에 해당하는
|
|
101
|
+
S1부터 본다. 전 카테고리를 훑지 않는다.
|
|
102
|
+
|
|
75
103
|
### 1단계 — 탐지
|
|
76
104
|
|
|
77
|
-
|
|
105
|
+
스캔 결과에 탐지기가 못 가리는 S1을 더해 이번 작업 목록을 확정한다.
|
|
78
106
|
|
|
79
|
-
- S1(심각):
|
|
107
|
+
- S1(심각): 스캔이 짚은 룰 + 직접 확인 목록에서 실제로 걸린 것 — 반드시 제거
|
|
80
108
|
- S2(경미): 빈도, 맥락을 보고 선별 교정. 무리하게 다 고치지 않는다
|
|
81
109
|
|
|
110
|
+
스캔을 못 돌린 경우에만 룰북 자체검증 5번의 S1 목록을 기준으로 삼는다. 대화나 리뷰 말투면
|
|
111
|
+
거기 적힌 격상분까지 포함한다.
|
|
112
|
+
|
|
82
113
|
### 2단계 — 처방
|
|
83
114
|
|
|
84
115
|
탐지한 패턴마다 룰북의 처방을 적용한다. 정보와 의미, 말투는 그대로 두고 표현만 바꾼다.
|
|
@@ -98,8 +129,13 @@ S2
|
|
|
98
129
|
2. 변경률 30% 이하 (50% 초과는 작업 중단)
|
|
99
130
|
3. 장르나 말투 이탈 없음 (칼럼→에세이, 격식체→평어체 금지)
|
|
100
131
|
4. 잔존 S1 패턴 0건 (B-3 음차 표기 포함)
|
|
101
|
-
5.
|
|
102
|
-
|
|
132
|
+
5. 0단계가 짚은 S1을 절반 넘게 걷어냄. 하나도 못 줄였으면 윤문한 게 아니다
|
|
133
|
+
(잔존이 0건이라야 잔존 측면이 통과다. 남았으면 제거율이 높아도 경고가 붙는다)
|
|
134
|
+
**탐지기가 없는 룰을 고쳤으면 어느 것인지 summary에 적는다.** 코드가 못 세는 자리라
|
|
135
|
+
여기서 직접 확인한다. 댈 게 없으면 안 고친 것이다
|
|
136
|
+
6. 원문에 없던 S1을 새로 심지 않음
|
|
137
|
+
7. 원문에 없던 비유나 수사를 임의로 추가하지 않음
|
|
138
|
+
8. 삭제 처방(D-2, D-3, D-4, D-6, C-10)을 재작성으로 처리하지 않음
|
|
103
139
|
|
|
104
140
|
## Do-NOT (탐지·윤문 모두 제외)
|
|
105
141
|
|
|
@@ -115,29 +151,71 @@ S2
|
|
|
115
151
|
- **구조 라벨 접두**: 커밋과 PR 제목의 `type(scope):` — 팀이 형식으로 정한 라벨이라 C-10 콜론 부제가 아니다(룰북 C-10 예외). 라벨은 그대로 두고 콜론 뒤 본문만 다듬는다. 리뷰 코멘트의 `r:`/`c:`/`a:`도 같은 예외이고 설명은 아래 작성자 voice 항목에 있다 — 여기 두 번 적지 않는다
|
|
116
152
|
- **작성자 voice (리뷰 코멘트·PR/변경 문서)**: `author-voice.md`의 보존 패턴 — 제안형 "~것 같아요/같습니다", 물결 친근체 "~해주세요~/~할게요~", "개인적으로/제 취향이긴 한데", 이모지(코멘트당 1개 안팎). 이건 AI-tell이 아니라 작성자 voice이므로 단언, 격식으로 평탄화하지 않는다. (단 `[출처]`·"권장." 은 Claude artifact이니 보이면 제거. **`r:`/`c:`/`a:` 접두어는 예외** — 팀이 채택한 PR 리뷰 강제성 라벨이므로 코멘트 맨 앞에 있으면 보존한다. voice 시그니처 흉내가 아니라 구조적 라벨이다.)
|
|
117
153
|
|
|
118
|
-
##
|
|
154
|
+
## 윤문 가드 (양방향)
|
|
155
|
+
|
|
156
|
+
너무 많이 고치는 것과 하나도 안 고치는 것은 같은 무게로 실패다. 한쪽만 막으면 안 고치는
|
|
157
|
+
쪽이 늘 안전해져서, 결국 아무것도 안 하는 윤문이 통과한다.
|
|
158
|
+
|
|
159
|
+
과윤문 쪽
|
|
119
160
|
|
|
120
161
|
- 변경률 30% 초과 = 경고 (summary에 명시)
|
|
121
162
|
- 변경률 50% 초과 = 강제 중단, 롤백 후 D등급으로 반환
|
|
122
|
-
-
|
|
163
|
+
- 원문에 없던 S1을 새로 심으면 강제 중단. AI 티는 빼기만 하고 넣지 않는다
|
|
164
|
+
|
|
165
|
+
과소윤문 쪽
|
|
166
|
+
|
|
167
|
+
- S1을 한 건도 못 줄이고 변경도 문턱 아래면 강제 중단. 윤문을 안 한 것이다
|
|
168
|
+
- 절반도 못 줄였으면 경고. 남긴 이유를 summary에 적는다
|
|
169
|
+
- 잔존이 0건이라야 잔존 측면이 통과다. 제거율이 아무리 높아도 남은 게 있으면 경고다
|
|
170
|
+
|
|
171
|
+
**제거율은 탐지기가 있는 룰만 센다.** 0단계의 "직접 확인" 목록에 있는 룰만 고쳤으면
|
|
172
|
+
제거율은 0으로 보인다. 그때 검사 결과는 둘 중 하나다.
|
|
173
|
+
|
|
174
|
+
- 변경도 문턱 아래다 → 윤문을 안 한 것이다. 채택 금지
|
|
175
|
+
- 변경은 문턱을 넘었다 → 경고. 탐지기 밖 룰은 이 검사로 확인되지 않는다
|
|
176
|
+
|
|
177
|
+
**탐지기가 없는 S1은 코드가 판정하지 못한다.** doc 기준 A-16, B-3, C-5, C-8, C-10,
|
|
178
|
+
D-5, J-2 일곱 개다. 네가 그걸 고쳤는지는 측정할 방법이 없다. 그래서 검사는 판정 대신
|
|
179
|
+
측정값만 낸다.
|
|
180
|
+
|
|
181
|
+
그 자리는 자가검증 5번이 맡는다. 경고가 나오면 직접 확인 목록에서 무엇을 고쳤는지
|
|
182
|
+
summary에 적는다. 댈 게 없으면 그건 안 고친 것이라 원문을 그대로 낸다.
|
|
183
|
+
|
|
184
|
+
**검사를 돌렸든 안 돌렸든 기준은 같다.** 경고가 나왔다고 그걸 근거로 채택하고 끝내지
|
|
185
|
+
않는다. 인라인 텍스트라 검사를 못 돌리는 경우에도 판단은 같다 — 탐지 가능한 S1이
|
|
186
|
+
하나도 안 줄었으면 직접 확인 목록에서 무엇을 고쳤는지 댈 수 있을 때만 결과를 낸다.
|
|
187
|
+
|
|
188
|
+
윤문은 "AI 티 제거"가 목적이다. 원문을 더 멋지게 쓰는 작업도 아니고 손대는 시늉만 하는
|
|
189
|
+
작업도 아니다.
|
|
123
190
|
|
|
124
191
|
## 코드 검사 (자가검증 위)
|
|
125
192
|
|
|
126
193
|
위 3단계 자가검증은 스스로 매기는 참고값이다. 원문과 윤문본이 파일로 있으면 판단은 코드에 맡긴다.
|
|
127
194
|
|
|
128
195
|
```bash
|
|
129
|
-
gestalt humanize-check --before <원문> --after <윤문본> --register chat
|
|
196
|
+
gestalt humanize-check --before <원문> --after <윤문본> --register chat --attempt 1
|
|
130
197
|
```
|
|
131
198
|
|
|
132
|
-
변경률, S1
|
|
199
|
+
변경률, S1 제거율, 보호 토큰 생존, 구조 보존, 신규 유입을 각각 측정하고 exit code로 답한다
|
|
133
200
|
(0 통과 / 1 경고 / 2 채택 금지 / 3 판정 불가). 변경률만 보면 구조 편집이 안 보인다 —
|
|
134
201
|
변경률이 3%인데 문장 3할이 갈려나갈 수 있다.
|
|
135
202
|
코드 검사는 정규식으로 오탐 적게 잡을 수 있는 룰만 본다. 의미 판단이 필요한 룰은 모델 자가검증에서
|
|
136
203
|
따로 본다.
|
|
137
204
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
205
|
+
리포트 마지막 줄의 `[다음]`이 다음 행동을 지시한다. 그 지시를 따른다.
|
|
206
|
+
|
|
207
|
+
| 지시 | 할 일 |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `accept` | 윤문본을 채택한다 |
|
|
210
|
+
| `accept-with-warning` | 채택하되 걸린 측면을 summary에 적는다 |
|
|
211
|
+
| `retry` | 윤문본을 버리고 원문에서 다시 윤문한 뒤 `--attempt 2`로 재검사한다 |
|
|
212
|
+
| `fallback` | 재시도를 소진했다. 윤문본을 버리고 **원문을 그대로 낸다** |
|
|
213
|
+
|
|
214
|
+
`fallback`은 실패가 아니라 계약이다. 윤문이 원문보다 나아졌다고 증명하지 못했으면 남는
|
|
215
|
+
선택지는 원문뿐이다. 이때는 D등급과 함께 원문을 돌려준다. 무엇이 막았는지도 적는다.
|
|
216
|
+
|
|
217
|
+
- **판정과 변경률은 검사 출력값이다.** 자가 산출 등급이나 어림한 변경률로 덮어쓰지 않는다.
|
|
218
|
+
자가검증 2번은 검사를 못 돌리는 자리에서만 쓰는 어림값이다.
|
|
141
219
|
- 검사를 못 돌리는 상황(파일 없이 인라인 텍스트만 받은 경우)이면 자가검증만으로 진행하되,
|
|
142
220
|
변경률이 추정값임을 밝힌다.
|
|
143
221
|
|