feat: block Korean prose contract violations

This commit is contained in:
DongHyeonka
2026-07-29 18:30:10 +09:00
parent 4b7f1a90d2
commit d333e265b9
2 changed files with 72 additions and 0 deletions
+35
View File
@@ -39,6 +39,7 @@ Write Korean reader-facing prose as a supported first-person experience, not as
"""
_PLAIN_FORM_ENDING = re.compile(r"(?<!니)다(?=[.!?](?:\s|$))")
_FIRST_PERSON = re.compile(r"(?:저는|제가)")
_FENCE = re.compile(r"^\s*(?:```|~~~)")
_HEADING = re.compile(r"^\s{0,3}(#{1,6})\s+(.+?)\s*$")
_IMAGE_ONLY = re.compile(r"^\s*!\[[^\]]*\]\([^)]*\)\s*$")
@@ -159,3 +160,37 @@ def plain_form_ending_locations(markdown: str) -> list[int]:
for segment in reader_prose_segments(markdown):
locations.extend(segment.line for _ in _PLAIN_FORM_ENDING.finditer(segment.text))
return locations
def first_person_metrics(markdown: str) -> dict[str, int | float | bool]:
segments = reader_prose_segments(markdown)
first_person_marker_count = sum(
len(_FIRST_PERSON.findall(segment.text))
for segment in segments
)
opening_has_first_person = bool(
segments and _FIRST_PERSON.search(segments[0].text)
)
section_markers: dict[str, bool] = {}
for segment in segments:
if segment.h2_title is None:
continue
section_markers.setdefault(segment.h2_title, False)
if _FIRST_PERSON.search(segment.text):
section_markers[segment.h2_title] = True
experience_section_count = len(section_markers)
marked_experience_section_count = sum(section_markers.values())
experience_section_coverage = (
marked_experience_section_count / experience_section_count
if experience_section_count
else 0.0
)
return {
"first_person_marker_count": first_person_marker_count,
"opening_has_first_person": opening_has_first_person,
"experience_section_count": experience_section_count,
"marked_experience_section_count": marked_experience_section_count,
"experience_section_coverage": round(experience_section_coverage, 3),
}