feat(scripts): 놓친 8건을 코드로 막거나 검토로 보낸다
먼저 쟀다. 경고를 일괄 차단으로 올리면 채택된 편집 9건이 막힌다 — V-004 에서 고친 바로 그 9건이다. 그래서 경고는 검토로 보내고 차단은 검토가 판정할 때 일어나게 뒀다. 코드로 막은 것 셋. code[] 리비전 — check_evidence 는 리비전이 있는지만 보고 인용한 코드가 그 리비전에서 왔는지는 안 본다. 이 배치에서 실제로 났고 사람이 손으로 잡았다. 한글 수사와 그 경계 — 「다섯 개 → 여섯 개」는 결정적이다. 앵커 검사기의 오탐을 0 으로 만드는 데 시간의 절반이 갔다. 처음 판이 저장소 전체에서 401건을 냈고 전부 오탐이었다. code[] 는 한 모양이 아니다 — 심볼, 축약 경로, 줄 범위, 호스트 절대 경로, 설정 키가 섞여 있다. 축약 경로를 「없다」로 세면 있는 코드를 없다고 하는 것이고 그게 채택된 편집 아홉 건을 막았던 실패와 같은 모양이다. 판정할 수 있는 것만 판정하고 못 보는 것은 세어서 낸다. 검토로 보낸 것 다섯. D2 는 아무 계수도 안 움직이던 자리였다 — 수치도 인용도 없이 산문만 더하면 보호 구간 비교에 잡힐 것이 없다. 1인칭 표지가 늘어난 것만 보고 그 문장을 짚어 준다. 판정이 아니라 라우팅이다. 만들다 버그를 찾았다. 경고가 인용하는 문장이 파일 첫 문단에서 한 글자씩 깎이고 있었다. rfind 가 -1 을 낼 때 +2 를 해서 1 이 됐다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
This commit is contained in:
co-authored by
Claude Opus 5
parent
230ad874ca
commit
845ee89054
@@ -107,3 +107,55 @@ class PreservationTest(unittest.TestCase):
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
|
||||
class KoreanNumeralTest(unittest.TestCase):
|
||||
"""한글 수사. 아라비아 숫자만 보면 「다섯 개 → 여섯 개」가 안 보인다.
|
||||
|
||||
이 배치에서 실제로 한 번 놓쳤고 사람이 잡았다.
|
||||
"""
|
||||
|
||||
def test_a_changed_korean_numeral_is_an_error(self):
|
||||
for before, after in (("증거 다섯 개", "증거 여섯 개"),
|
||||
("문장 세 줄", "문장 네 줄"),
|
||||
("열두 건", "열세 건")):
|
||||
with self.subTest(before=before):
|
||||
self.assertTrue(cp.compare(before, after)["errors"])
|
||||
|
||||
def test_counting_words_that_are_not_numbers_are_left_alone(self):
|
||||
"""대조군. 「하나뿐」·「둘 다」는 수가 아니다. 세면 정상을 막는다."""
|
||||
for text in ("하나뿐이다", "둘 다 맞다", "한편으로는 그렇다"):
|
||||
with self.subTest(text=text):
|
||||
self.assertEqual([], cp.compare(text, text)["errors"])
|
||||
|
||||
|
||||
class UnsourcedVoiceTest(unittest.TestCase):
|
||||
"""자료에 없는 1인칭. 보호 구간 비교로는 원리적으로 안 보이던 자리다."""
|
||||
|
||||
BEFORE = "피드 아이템을 엔티티로 조회한 뒤 메모리에서 DTO로 옮기는 코드다."
|
||||
|
||||
def test_added_first_person_experience_is_surfaced_as_a_warning(self):
|
||||
after = ("처음에는 조인 한 번으로 가져올 거라고 믿었다. "
|
||||
"팀에서는 다른 의견이 많았지만 나는 조회 방식을 먼저 보자고 했다.\n\n"
|
||||
+ self.BEFORE)
|
||||
res = cp.compare(self.BEFORE, after)
|
||||
self.assertEqual([], res["errors"], "판정이 아니라 라우팅이다")
|
||||
marks = {w["value"] for w in res["warnings"] if w["kind"] == "1인칭"}
|
||||
self.assertTrue({"처음에는", "믿었다", "팀에서는"} <= marks, marks)
|
||||
|
||||
def test_the_warning_points_at_the_sentence(self):
|
||||
after = "처음에는 그렇게 믿었다.\n\n" + self.BEFORE
|
||||
w = next(x for x in cp.compare(self.BEFORE, after)["warnings"]
|
||||
if x["kind"] == "1인칭")
|
||||
self.assertIn("처음에는", w["sentence"])
|
||||
|
||||
def test_removing_first_person_is_not_reported(self):
|
||||
"""지우는 것은 이 규범에서 안전한 쪽이다."""
|
||||
after = "처음에는 그렇게 믿었다. " + self.BEFORE
|
||||
self.assertEqual([], [w for w in cp.compare(after, self.BEFORE)["warnings"]
|
||||
if w["kind"] == "1인칭"])
|
||||
|
||||
def test_an_ordinary_rewrite_raises_no_voice_warning(self):
|
||||
"""대조군."""
|
||||
self.assertEqual([], [w for w in cp.compare(self.BEFORE, self.BEFORE)["warnings"]
|
||||
if w["kind"] == "1인칭"])
|
||||
|
||||
Reference in New Issue
Block a user