feat(safety): B-1 PR① — law_monitor 스케줄 제거 + statute KR poll_changes + fixture 박제 (mig 356)
plan safety-library-1 B-1 PR① (fixture-first): - law.go.kr 라이브 fixture 5종 박제 (OC 새니타이즈 검증 — 응답 법령상세링크에 키 포함 함정) - R7-M3 판정: 전문 1콜 XML = 조문 853+별표 23 전체 스냅샷(부분 실패 개념 없음) + 별표번호/가지번호 = 구조화 필드 — 조문 취득 = 전문 1콜+로컬 파싱 확정(R2-m1) - legal_acts KR 시드 26행(법령ID 라이브 실측, watch=26 전부, FK 계열 9그룹) ★ '유해ㆍ위험작업...' 정식명 = 가운뎃점 — law_monitor 하드코딩(점 없음)은 영구 미매칭 잠복 - statute_adapters/kr.py: poll_changes(lawSearch MST diff) — 순수 파서 분리, fixture 테스트 8/8 - statute_collector.py: 관찰 전용 코어(워터마크 영속 0 — ingest=PR②), 스케줄 미등록(R8-B1) - main.py: law_monitor 스케줄 제거 — 버전 체인 밖 레거시 매일 증식의 유일 경로 차단 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+46
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<법령 법령키="0017662026021921374">
|
||||
<기본정보>
|
||||
<법령ID>001766</법령ID>
|
||||
<공포일자>20260219</공포일자>
|
||||
<공포번호>21374</공포번호>
|
||||
<언어>한글</언어>
|
||||
<법종구분 법종구분코드="A0002">법률</법종구분>
|
||||
<법령명_한글><![CDATA[산업안전보건법]]></법령명_한글>
|
||||
<법령명_한자><![CDATA[산업안전보건법]]></법령명_한자>
|
||||
<제명변경여부>N</제명변경여부>
|
||||
<한글법령여부>Y</한글법령여부>
|
||||
<편장절관>40040000</편장절관>
|
||||
<소관부처 소관부처코드="1492000">고용노동부</소관부처>
|
||||
<전화번호>044-202-8810, 8813, 8815, 8997</전화번호>
|
||||
<시행일자>20260601</시행일자>
|
||||
<제개정구분>일부개정</제개정구분>
|
||||
<조문별시행일자>20260601</조문별시행일자>
|
||||
<조문시행일자문자열>20260801:제10조의2, 제23조, 제175조제4항제1호의2</조문시행일자문자열>
|
||||
<별표편집여부>N</별표편집여부>
|
||||
<공포법령여부>Y</공포법령여부>
|
||||
<시행일기준편집여부>Y</시행일기준편집여부>
|
||||
</기본정보>
|
||||
<조문>
|
||||
<조문단위 조문키="0001000">
|
||||
<조문번호>1</조문번호>
|
||||
<조문여부>전문</조문여부>
|
||||
<조문시행일자>20260601</조문시행일자>
|
||||
<조문이동이전></조문이동이전>
|
||||
<조문이동이후></조문이동이후>
|
||||
<조문변경여부>N</조문변경여부>
|
||||
</조문단위>
|
||||
<조문단위 조문키="0001001">
|
||||
<조문번호>1</조문번호>
|
||||
<조문여부>조문</조문여부>
|
||||
<조문제목><![CDATA[목적]]></조문제목>
|
||||
<조문시행일자>20260601</조문시행일자>
|
||||
<조문이동이전></조문이동이전>
|
||||
<조문이동이후></조문이동이후>
|
||||
<조문변경여부>N</조문변경여부>
|
||||
<조문내용>
|
||||
<![CDATA[제1조(목적) 이 법은 산업 안전 및 보건에 관한 기준을 확립하고 그 책임의 소재를 명확하게 하여 산업재해를 예방하고 쾌적한 작업환경을 조성함으로써 노무를 제공하는 사람의 안전 및 보건을 유지ㆍ증진함을 목적으로 한다. <개정 2020.5.26>]]>
|
||||
</조문내용>
|
||||
</조문단위>
|
||||
</조문>
|
||||
</법령>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><LawSearch><target>law</target><키워드>산업안전보건기준에 관한 규칙</키워드><section>lawNm</section><totalCnt>1</totalCnt><page>1</page><numOfRows>1</numOfRows><resultCode>00</resultCode><resultMsg>success</resultMsg><law id="1"><법령일련번호>273603</법령일련번호><현행연혁코드>현행</현행연혁코드><법령명한글><![CDATA[산업안전보건기준에 관한 규칙]]></법령명한글><법령약칭명><![CDATA[안전보건규칙]]></법령약칭명><법령ID>007363</법령ID><공포일자>20250901</공포일자><공포번호>00450</공포번호><제개정구분명>일부개정</제개정구분명><소관부처코드>1492000</소관부처코드><소관부처명>고용노동부</소관부처명><법령구분명>고용노동부령</법령구분명><공동부령정보></공동부령정보><시행일자>20260302</시행일자><자법타법여부></자법타법여부><법령상세링크>/DRF/lawService.do?OC=__OC_REDACTED__&target=law&MST=273603&type=HTML&mobileYn=&efYd=20260302</법령상세링크></law></LawSearch>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><LawSearch><target>law</target><키워드>산업안전보건법</키워드><section>lawNm</section><totalCnt>3</totalCnt><page>1</page><numOfRows>3</numOfRows><resultCode>00</resultCode><resultMsg>success</resultMsg><law id="1"><법령일련번호>283449</법령일련번호><현행연혁코드>현행</현행연혁코드><법령명한글><![CDATA[산업안전보건법]]></법령명한글><법령약칭명><![CDATA[]]></법령약칭명><법령ID>001766</법령ID><공포일자>20260219</공포일자><공포번호>21374</공포번호><제개정구분명>일부개정</제개정구분명><소관부처코드>1492000</소관부처코드><소관부처명>고용노동부</소관부처명><법령구분명>법률</법령구분명><공동부령정보></공동부령정보><시행일자>20260601</시행일자><자법타법여부></자법타법여부><법령상세링크>/DRF/lawService.do?OC=__OC_REDACTED__&target=law&MST=283449&type=HTML&mobileYn=&efYd=20260601</법령상세링크></law><law id="2"><법령일련번호>284771</법령일련번호><현행연혁코드>현행</현행연혁코드><법령명한글><![CDATA[산업안전보건법 시행령]]></법령명한글><법령약칭명><![CDATA[]]></법령약칭명><법령ID>003786</법령ID><공포일자>20260324</공포일자><공포번호>36220</공포번호><제개정구분명>타법개정</제개정구분명><소관부처코드>1492000</소관부처코드><소관부처명>고용노동부</소관부처명><법령구분명>대통령령</법령구분명><공동부령정보></공동부령정보><시행일자>20260324</시행일자><자법타법여부></자법타법여부><법령상세링크>/DRF/lawService.do?OC=__OC_REDACTED__&target=law&MST=284771&type=HTML&mobileYn=&efYd=20260324</법령상세링크></law><law id="3"><법령일련번호>286657</법령일련번호><현행연혁코드>현행</현행연혁코드><법령명한글><![CDATA[산업안전보건법 시행규칙]]></법령명한글><법령약칭명><![CDATA[]]></법령약칭명><법령ID>007364</법령ID><공포일자>20260529</공포일자><공포번호>00470</공포번호><제개정구분명>일부개정</제개정구분명><소관부처코드>1492000</소관부처코드><소관부처명>고용노동부</소관부처명><법령구분명>고용노동부령</법령구분명><공동부령정보></공동부령정보><시행일자>20260601</시행일자><자법타법여부></자법타법여부><법령상세링크>/DRF/lawService.do?OC=__OC_REDACTED__&target=law&MST=286657&type=HTML&mobileYn=&efYd=20260601</법령상세링크></law></LawSearch>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+26
@@ -0,0 +1,26 @@
|
||||
산업안전보건법 001766 283449 20260219 20260601 법률
|
||||
산업안전보건법 시행령 003786 284771 20260324 20260324 대통령령
|
||||
산업안전보건법 시행규칙 007364 286657 20260529 20260601 고용노동부령
|
||||
산업안전보건기준에 관한 규칙 007363 273603 20250901 20260302 고용노동부령
|
||||
유해위험작업의 취업 제한에 관한 규칙 MISS
|
||||
중대재해 처벌 등에 관한 법률 013993 228817 20210126 20220127 법률
|
||||
중대재해 처벌 등에 관한 법률 시행령 014159 277417 20251001 20251001 대통령령
|
||||
건설기술 진흥법 001807 276921 20251001 20251001 법률
|
||||
건설기술 진흥법 시행령 002111 286847 20260609 20260609 대통령령
|
||||
건설기술 진흥법 시행규칙 006175 286885 20260611 20260611 국토교통부령
|
||||
시설물의 안전 및 유지관리에 관한 특별법 000237 266683 20241203 20251204 법률
|
||||
위험물안전관리법 009502 259933 20240206 20250807 법률
|
||||
위험물안전관리법 시행령 009707 273077 20250805 20250807 대통령령
|
||||
위험물안전관리법 시행규칙 009732 262765 20240520 20250521 행정안전부령
|
||||
화학물질관리법 000162 276815 20251001 20251001 법률
|
||||
화학물질관리법 시행령 004390 280507 20251223 20251223 대통령령
|
||||
화학물질의 등록 및 평가 등에 관한 법률 011857 279805 20251111 20260512 법률
|
||||
소방시설 설치 및 관리에 관한 법률 009503 236977 20211130 20241201 법률
|
||||
소방시설 설치 및 관리에 관한 법률 시행령 009694 284781 20260324 20260324 대통령령
|
||||
전기사업법 001854 283981 20260310 20260310 법률
|
||||
전기안전관리법 013718 268805 20250131 20260201 법률
|
||||
고압가스 안전관리법 001850 283919 20260310 20260310 법률
|
||||
고압가스 안전관리법 시행령 002246 286839 20260609 20260609 대통령령
|
||||
액화석유가스의 안전관리 및 사업법 001849 276549 20251001 20251128 법률
|
||||
근로기준법 001872 265959 20241022 20251023 법률
|
||||
환경영향평가법 002016 276833 20251001 20251023 법률
|
||||
|
@@ -0,0 +1,89 @@
|
||||
"""B-1 PR① — KR 어댑터 순수 파서 fixture 테스트 (plan safety-library-1).
|
||||
|
||||
fixture = 2026-06-13 law.go.kr 라이브 박제 (OC 새니타이즈, tests/fixtures/statute_kr/).
|
||||
파서는 순수 함수라 httpx/DB 불요 — 컨테이너 밖 로컬 실행.
|
||||
"""
|
||||
|
||||
import gzip
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent / "app"))
|
||||
|
||||
from workers.statute_adapters import ChangeEvent # noqa: E402
|
||||
from workers.statute_adapters.kr import detect_change, parse_search_hit # noqa: E402
|
||||
|
||||
FIX = Path(__file__).parent / "fixtures" / "statute_kr"
|
||||
|
||||
|
||||
def _read(name: str) -> str:
|
||||
p = FIX / name
|
||||
if name.endswith(".gz"):
|
||||
return gzip.decompress(p.read_bytes()).decode("utf-8")
|
||||
return p.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_parse_search_hit_exact_match():
|
||||
hit = parse_search_hit(_read("lawsearch_sanab.xml"), "산업안전보건법")
|
||||
assert hit is not None
|
||||
assert hit["law_id"] == "001766"
|
||||
assert hit["mst"] == "283449"
|
||||
assert hit["promulgation_date"] == "20260219"
|
||||
assert hit["effective_date"] == "20260601"
|
||||
assert hit["status_code"] == "현행"
|
||||
|
||||
|
||||
def test_parse_search_hit_rejects_partial_name():
|
||||
# totalCnt 3 인 응답에서 '산업안전보건법 시행령' 등 부분 일치는 비매칭이어야 함
|
||||
hit = parse_search_hit(_read("lawsearch_sanab.xml"), "산업안전보건")
|
||||
assert hit is None
|
||||
|
||||
|
||||
def test_detect_change_same_watermark_is_silent():
|
||||
hit = parse_search_hit(_read("lawsearch_sanab.xml"), "산업안전보건법")
|
||||
assert detect_change(hit, "kr-law:001766", "산업안전보건법", watermark="283449") is None
|
||||
|
||||
|
||||
def test_detect_change_new_mst_is_amend():
|
||||
hit = parse_search_hit(_read("lawsearch_sanab.xml"), "산업안전보건법")
|
||||
ev = detect_change(hit, "kr-law:001766", "산업안전보건법", watermark="283448")
|
||||
assert isinstance(ev, ChangeEvent)
|
||||
assert ev.kind == "amend"
|
||||
assert ev.new_version_key == "283449"
|
||||
assert ev.effective_date == "20260601"
|
||||
|
||||
|
||||
def test_detect_change_empty_watermark_is_amend():
|
||||
# 첫 폴링(워터마크 부재) = 변경으로 감지 — PR② 부트스트랩 전 관찰 모드의 기대 동작
|
||||
hit = parse_search_hit(_read("lawsearch_sanab.xml"), "산업안전보건법")
|
||||
ev = detect_change(hit, "kr-law:001766", "산업안전보건법", watermark=None)
|
||||
assert ev is not None and ev.kind == "amend"
|
||||
|
||||
|
||||
def test_detect_change_repeal_keyword():
|
||||
hit = {"mst": "9", "revision_type": "폐지", "promulgation_date": None,
|
||||
"effective_date": None, "law_id": "x", "status_code": None}
|
||||
ev = detect_change(hit, "kr-law:x", "x", watermark="1")
|
||||
assert ev is not None and ev.kind == "repeal"
|
||||
|
||||
|
||||
def test_lawservice_snapshot_semantics_rule():
|
||||
"""R7-M3 판정 박제: 전문 1콜 XML = 조문+별표 전체 스냅샷 (PR② payload 계약의 전제)."""
|
||||
root = ET.fromstring(_read("lawservice_rule.xml.gz"))
|
||||
articles = root.findall(".//조문단위")
|
||||
annexes = root.findall(".//별표단위")
|
||||
assert len(articles) >= 800, "산안기준규칙 조문 853 기대 — 전문 1콜 판정 근거"
|
||||
assert len(annexes) == 23, "별표 23 전부 본문 XML 포함 = 스냅샷 의미론"
|
||||
# R7-M3 ②: 별표 식별 = 구조화 필드 (suffix 문자열 파싱 불요)
|
||||
first = annexes[0]
|
||||
assert first.findtext("별표번호") is not None
|
||||
assert first.findtext("별표가지번호") is not None
|
||||
|
||||
|
||||
def test_lawservice_sanab_basic_info():
|
||||
root = ET.fromstring(_read("lawservice_sanab.xml.gz"))
|
||||
assert root.findtext(".//법령ID") == "001766"
|
||||
assert len(root.findall(".//조문단위")) >= 200
|
||||
# 별표 없는 법령 = 별표단위 0 (스냅샷 의미론의 반대쪽 케이스)
|
||||
assert len(root.findall(".//별표단위")) == 0
|
||||
Reference in New Issue
Block a user