feat(scripts): 경고를 읽는 장치가 아니라 만드는 장치를 더한다

남은 셋은 묶음 경고가 0건이라 게이트를 아무리 조여도 지나간다. 뿌리가 하나다 — 지금
검사기는 사라진 것과 새로 생긴 보호 구간을 보고, 범위가 넓어진 것과 정본을 안 거친 것을
보는 자리가 없었다.

그림이 정본을 거쳤는지 본다. SVG 는 바뀌었는데 spec.json 은 그대로면 그 그림은 정본에서
나온 것이 아니고, 화살표 뒤집기가 그 모양이다. spec 의 간선과 SVG 의 경로를 직접 견주려면
렌더러가 id 를 어떻게 붙이는지 알아야 하는데, 정본을 거쳤는지만 보면 몰라도 된다.
작업 트리와 이력 두 자리를 본다. 정본이 없는 그림은 볼 것이 아니라 세기만 한다.

적용 범위를 넓히는 말이 새로 들어왔는지 본다. 로컬에서 확인했다에 운영 환경에서도를
더하기만 하면 유보도 보호 구간도 안 바뀐다 — 지운 것이 없기 때문이다. 유보 감소의
반대편이고, 판정하지 않고 경고로 올린다.

경고 생산자를 더하는 것이 과잉 차단이 생기는 자리라 후보마다 채택 편집 100쌍을 돌렸다.
error 도 경고도 안 늘었다. 정상 편집에 경고가 붙으면 그것도 사실상 차단이다.

목록에 운영·항상 같은 흔한 말이 들어가서, 원래 있던 말을 두고 주변만 고쳐도 걸리는지
보는 대조군을 회귀에 넣었다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
This commit is contained in:
DongHyeonka
2026-09-10 16:33:47 +09:00
co-authored by Claude Opus 5
parent 16cbe141a0
commit e3230ce5ed
4 changed files with 255 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
"""그림이 정본에서 나온 것인지 보는 검사기.
`spec.json` 의 간선과 SVG 의 경로를 직접 견주려면 렌더러가 id 를 어떻게 붙이는지 알아야
한다. **정본을 거쳤는지만 보면 렌더러를 몰라도 된다** — 그리고 손으로 고친 그림이
화살표 뒤집기의 모양이다.
"""
import importlib.util
import os
import subprocess
import unittest
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
TOOL = os.path.join(ROOT, "scripts", "check-figure-provenance.py")
_spec = importlib.util.spec_from_file_location("check_figure_provenance", TOOL)
fp = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(fp)
SVG = ("docs/virtualization/final/assets/diagrams/"
"guest-memory-address-translation-path/guest-memory-address-translation-path.svg")
SPEC = ("docs/virtualization/final/.techviz/"
"guest-memory-address-translation-path/spec.json")
def _cli(*args):
return subprocess.run(["python3", TOOL, *args], cwd=ROOT,
capture_output=True, text=True)
class ProvenanceTest(unittest.TestCase):
def test_every_figure_in_this_repository_passes(self):
"""대조군. 지금 저장소의 그림에 하나라도 걸리면 정책이 과하다."""
p = _cli("--samples", "1")
self.assertEqual(0, p.returncode, p.stdout + p.stderr)
def test_a_hand_edited_svg_is_caught(self):
"""SVG 만 고치고 spec 은 그대로면 정본을 안 거친 그림이다.
고치고 나서 반드시 되돌린다 — 재현용 변경을 남기지 않는 것까지가 검증이다.
"""
svg = os.path.join(ROOT, SVG)
if not os.path.exists(svg):
self.skipTest("견줄 그림이 없다")
original = open(svg, encoding="utf-8").read()
try:
open(svg, "w", encoding="utf-8").write(
original.replace("marker-end", "marker-start", 1))
p = _cli("virtualization")
self.assertEqual(1, p.returncode, p.stdout)
self.assertIn("정본을 거치지 않고 고친 그림", p.stdout)
finally:
open(svg, "w", encoding="utf-8").write(original)
self.assertEqual(0, _cli("virtualization").returncode)
def test_a_figure_without_a_spec_is_counted_not_flagged(self):
"""정본이 없는 그림은 이 검사기가 볼 것이 아니다. 세기만 한다."""
rep = fp.verify("ca-tmpl")
self.assertEqual(0, rep.error_count)
self.assertGreater(rep.facts.get("정본이 없어 못 본 그림", 0), 0)
def test_a_missing_project_is_not_reported_as_clean(self):
self.assertEqual(2, _cli("nosuchxyz").returncode)
if __name__ == "__main__":
unittest.main()