# -*- coding: utf-8 -*- """B05 잘린 자리 윤곽(`cut-merged`) 회귀검증 — 2026-09-02. `dropCollinear`가 추적 고리의 닫힘 중복점(머리=꼬리)을 순환 이웃으로 셈해 시작 모서리를 지우던 결함(실측 63셀 구멍)의 재발 방지. Node 헬퍼(helper_b05_cut_merged_loop.cjs)가 ⚠ 도우미 확장자가 **`.cjs`** 인 이유(2026-09-07) — 루트 `package.json` 에 `"type": "module"` 이 있어 `.js` 는 Node 판·환경에 따라 ESM 으로 읽힌다. 그러면 도우미의 `require` 가 「require is not defined in ES module scope」로 죽는다(보조 창 폴더에서 실제로 9건이 그렇게 실패했고, 같은 파일이 이 폴더에서는 통과해 **환경 차이**임이 드러났다). `.cjs` 는 `type` 과 무관하게 언제나 CommonJS 라 어느 폴더·어느 Node 에서도 같게 돈다. `_Corridor_Cut.ts`를 트랜스파일해 합성 리본에 돌리고, pytest가 결과를 판정한다. """ import json import os import subprocess import pytest HERE = os.path.dirname(os.path.abspath(__file__)) @pytest.fixture(scope="module") def results(): proc = subprocess.run( ["node", os.path.join(HERE, "helper_b05_cut_merged_loop.cjs")], capture_output=True, text=True, timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_rect_every_masked_cell_inside_loop(results): """도려낸 셀은 전부 병합 고리 안 — 시작 모서리 쐐기가 빠지면 여기서 걸린다.""" r = results["rect"] assert r["masked"] > 0 assert r["uncovered"] == [], r["uncovered"] assert r["covered"] == r["masked"] def test_rect_loop_keeps_four_corners_and_closure(results): """직사각형 마스크 → 모서리 4 + 닫힘점 1. 종전에는 머리 모서리가 빠져 3+1이었다.""" loops = results["rect"]["loops"] assert len(loops) == 1 assert loops[0]["closed"] is True assert loops[0]["n"] == 5, loops[0]["points"] def test_single_cell_loop_intact(results): """한 셀짜리 고리도 4모서리 유지.""" r = results["single"] assert r["masked"] >= 1 assert r["uncovered"] == [] assert all(loop["n"] == 5 and loop["closed"] for loop in r["loops"]), r["loops"]