feat(b08): 원문 대조 밑수 60건 반영 — 16 채움 · 왜곡 1 고침 · 나머지는 사유로 남김

브레인 일감 ①. 안티그래비티 전수 대조 보고(02544795)의 `item3_basis` 60건을
**하나씩 원문 줄을 열어 확인**한 뒤 반영. 값(숫자)은 한 칸도 안 건드림(원문 셀 453/453 그대로).

- **채움 16** — 원문 괄호가 분명하고 **분모가 하나**인 것만
  (3-8 드론 영상 ha · 10-7-4·10-8 기·일 · 12-7·12-8 일 · 13-8 ㎡ · 13-14 개 …)
- **왜곡 고침 1** — 13-10-2 윈치말뚝 박기: 원문 L7489 가 「(단위: 1일당)」인데 「개」로 서 있었음
- **거절 27 + 확인 뒤 기각** — 사유를 코드 주석에 남김
  · ⚠ 보고가 「인」을 밑수로 적은 셋(F0228·F0229·F0230)은 **2026-09-09 에 오독으로 판정된
    바로 그 표**(8-6-2 드론방제·8-6-3 지상방제) — 안 넣음
  · 분모가 둘인 자리(3-2 작업로 선정 「인/1일 1km당」 · 8-11 「1대 1조, 시간당」) — 반쪽은 안 적음
  · `coefficient`·`reference` 표는 밑수가 없음 · 「%」·「회」·「분/1회」·「공㎥」·「인/조」는 단위가 아님
- **보고가 틀린 자리 둘** — F0223 은 원문이 「100본/ha당」이라 마스터(ha)가 맞고,
  F0235 는 표머리가 「소요인력(인/본당)」이라 마스터(본)가 맞음. 보고대로 고쳤으면 뒤집힐 뻔했음

밑수 확보 227 → 243(미확보 103 → 92) · 지문 한 번 갱신(더하기 16 + 왜곡 고침 1)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsGw1Dz9HmhuAxGisxmDPF
This commit is contained in:
2026-09-17 22:44:29 +09:00
co-authored by Claude Opus 5
parent b1db01bf9b
commit 6bd45b0cb4
8 changed files with 114 additions and 131 deletions
@@ -203,6 +203,29 @@ BASIS_JUDGMENTS: dict[str, tuple[str, float, str, str]] = {
"F0323": ("10-13-2", 1000.0, "", "위와 같음"),
"F0333": ("12-1-3", 1.0, "", "원문 「㎥당」"),
"F0346": ("12-11-1", 1.0, "m", "원문 「m당」"),
# ── 원문 md ↔ 마스터 전수 대조 60건 중 **원문 괄호가 분명하고 분모가 하나인 것만** ────
# 안티그래비티 보고(02544795) · 원문 줄을 직접 열어 괄호 글을 확인한 것만 싣는다.
# ⚠ 보고가 적은 단위를 그대로 믿지 않는다 — 「인」을 밑수로 적은 자리가 셋 있었고
# 그 자리(8-6-2 드론방제·8-6-3 지상방제)는 **2026-09-09 에 오독으로 판정된 바로 그 표**다.
"F0082": ("3-8", 1.0, "ha", "드론 영상 촬영 — 원문 「(단위 : 인/ha)」"),
"F0256": ("9-11-1", 1.0, "", "원문 「(단위: 일당)」"),
"F0310": ("10-7-4", 1.0, "", "원문 「(단위: 인/1일당)」"),
"F0311": ("10-7-4", 1.0, "", "원문 「(단위: 1기당)」"),
"F0312": ("10-7-4", 1.0, "", "원문 「(단위: 1일당)」"),
"F0313": ("10-8-1", 1.0, "", "원문 「(단위: 인/1일당)」"),
"F0314": ("10-8-2", 1.0, "", "원문 「(단위: 1기당)」"),
"F0315": ("10-8-3", 1.0, "", "원문 「(단위: 1일당)」"),
"F0339": ("12-7-1", 1.0, "", "원문 「(단위: 일당)」"),
"F0340": ("12-7-2", 1.0, "", "원문 「(단위: 일당)」"),
"F0341": ("12-8", 1.0, "", "원문 「(단위: 일당)」"),
"F0356": ("12-17-1", 1.0, "", "원문 「(단위: ㎥/일 당)」"),
"F0395": ("12-38-3", 1.0, "", "원문 「(단위: 일 당)」"),
"F0424": ("13-8", 1.0, "", "원문 「(단위: 인/㎡)」"),
"F0444": ("13-14", 1.0, "", "원문 「(단위: 인/개)」"),
"F0449": ("13-16-2", 1.0, "", "원문 「(단위: 일 당)」"),
# ⚠ **왜곡 고침 하나** — 값이 아니라 **밑수 단위**가 틀려 있던 자리.
# 원문 L7489 가 「(단위: 1일당)」인데 마스터가 「개」로 서 있었다(13-10-2 윈치말뚝 박기).
"F0430": ("13-10-2", 1.0, "", "왜곡 고침 — 원문 「(단위: 1일당)」인데 「개」로 서 있었음"),
}
@@ -6327,7 +6327,7 @@
"name_ko": "밑수 못 찾은 표",
"summary": "기준 수량을 못 읽은 품셈 표. 1 단위당으로 단정하면 곱셈이 틀린다.",
"shape": "list",
"rows": 103,
"rows": 92,
"columns": [
{
"key": "pum_table_id",
@@ -1,7 +1,7 @@
{
"schema_version": "1.0",
"dataset_id": "data_work_item_master_manifest",
"generated_at": "2026-09-17T22:26:44+09:00",
"generated_at": "2026-09-17T22:38:16+09:00",
"built_by": "B08_Quantity/B08_Quantity_Build_WorkItemMaster.py",
"source": {
"dataset_id": "pum_forest",
@@ -12,8 +12,8 @@
"files": [
{
"file": "work_item_master_2026-01-01.json",
"sha256": "b73d3d9ce7c4c6de7d8c99cb2db54ce32285b4a2c37b60962b7be8beb800abce",
"size_bytes": 925751
"sha256": "094c56c75dfa76e2acf2904cea7e6959a1998ceccaa46bf9f83bcdf9c9f3fdd4",
"size_bytes": 926610
},
{
"file": "form_undetermined_2026-01-01.json",
@@ -22,8 +22,8 @@
},
{
"file": "basis_missing_2026-01-01.json",
"sha256": "13b663780bca6143a126a2a873ff31b0a9eeb2aa41ea89e928b9c6a23537b164",
"size_bytes": 14212
"sha256": "e68975380e77d3f2d016cc264c22382335019220ad16ac9c3ad16cfb82e5769d",
"size_bytes": 12739
}
]
}
@@ -1,7 +1,7 @@
{
"schema_version": "1.0",
"dataset_id": "data_work_item_master_manifest",
"generated_at": "2026-09-17T22:27:36+09:00",
"generated_at": "2026-09-17T22:39:08+09:00",
"built_by": "B08_Quantity/B08_Quantity_Build_WorkItemMaster.py",
"source": {
"dataset_id": "pum_const",
@@ -12,7 +12,7 @@
"files": [
{
"file": "const_work_item_master_2026-01-01.json",
"sha256": "9bd4b0be9cf27df23781fdd9feea8ed7be2427e815db0563bc2b9eeb79a2f98b",
"sha256": "4e1d7fe8080913d17730395da18d4c039c432bca7b92e38a62d765a0b098314e",
"size_bytes": 3839594
},
{
@@ -52,12 +52,6 @@
"pum_form": "requirement",
"line": 1815
},
{
"pum_table_id": "F0082",
"section": "3-8. 드론 영상 촬영",
"pum_form": "requirement",
"line": 1901
},
{
"pum_table_id": "F0083",
"section": "4-1-1. 임업용 동력기계톱",
@@ -472,12 +466,6 @@
"pum_form": "requirement",
"line": 4860
},
{
"pum_table_id": "F0256",
"section": "9-11-1. 콘크리트(기계)",
"pum_form": "requirement",
"line": 4946
},
{
"pum_table_id": "F0294",
"section": "9-21. 제근",
@@ -490,42 +478,6 @@
"pum_form": "requirement",
"line": 5669
},
{
"pum_table_id": "F0310",
"section": "10-7-4. 모노레일 운반",
"pum_form": "requirement",
"line": 5770
},
{
"pum_table_id": "F0311",
"section": "10-7-4. 모노레일 운반",
"pum_form": "requirement",
"line": 5779
},
{
"pum_table_id": "F0312",
"section": "10-7-4. 모노레일 운반",
"pum_form": "requirement",
"line": 5795
},
{
"pum_table_id": "F0313",
"section": "10-8-1. 짐내리기",
"pum_form": "requirement",
"line": 5813
},
{
"pum_table_id": "F0314",
"section": "10-8-2. 운반대 설치",
"pum_form": "requirement",
"line": 5829
},
{
"pum_table_id": "F0315",
"section": "10-8-3. 케이블 크레인 운전",
"pum_form": "requirement",
"line": 5840
},
{
"pum_table_id": "F0317",
"section": "10-10-1. 콘크리트 및 골재운반(지상)",
@@ -556,12 +508,6 @@
"pum_form": "requirement",
"line": 6499
},
{
"pum_table_id": "F0356",
"section": "12-2 표면 마무리를 따른다.",
"pum_form": "productivity",
"line": 6520
},
{
"pum_table_id": "F0362",
"section": "12-2 표면 마무리를 따른다.",
@@ -592,12 +538,6 @@
"pum_form": "requirement",
"line": 7087
},
{
"pum_table_id": "F0424",
"section": "13-8. 막돌쌓기",
"pum_form": "requirement",
"line": 7415
},
{
"pum_table_id": "F0437",
"section": "13-12-1. 뭉기기",
@@ -610,12 +550,6 @@
"pum_form": "requirement",
"line": 7625
},
{
"pum_table_id": "F0444",
"section": "13-14. 식생토낭 및 포트",
"pum_form": "requirement",
"line": 7715
},
{
"pum_table_id": "F0447",
"section": "13-15-2. 목책 설치",
@@ -4,7 +4,7 @@
"effective_date": "2026-01-01",
"pum_edition": "2026-01-01",
"toc_edition": "2026-01-01",
"generated_at": "2026-09-17T22:27:36+09:00",
"generated_at": "2026-09-17T22:39:08+09:00",
"dataset_version": {
"dataset_id": "pum_const",
"effective_date": "2026-01-01",
@@ -4,7 +4,7 @@
"effective_date": "2026-01-01",
"pum_edition": "2026-01-01",
"toc_edition": "산림청고시제2025-82호",
"generated_at": "2026-09-17T22:26:44+09:00",
"generated_at": "2026-09-17T22:38:16+09:00",
"dataset_version": {
"dataset_id": "pum_forest",
"effective_date": "2026-01-01",
@@ -25,8 +25,8 @@
"tables_attached": 453,
"tables_orphan": 22,
"form_undetermined": 0,
"basis_found": 227,
"basis_missing": 103,
"basis_found": 243,
"basis_missing": 92,
"basis_grouped": 54,
"axis_roles": {
"general_provision": 78,
@@ -6732,9 +6732,9 @@
"source_line": 1901,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "ha",
"basis_source": "사람 판정 — 드론 영상 촬영 — 원문 「(단위 : 인/ha)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -22238,9 +22238,9 @@
"source_line": 4946,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -26773,9 +26773,9 @@
"source_line": 5770,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 인/1일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -26806,9 +26806,9 @@
"source_line": 5779,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "기",
"basis_source": "사람 판정 — 원문 「(단위: 1기당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -26890,9 +26890,9 @@
"source_line": 5795,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 1일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -26967,9 +26967,9 @@
"source_line": 5813,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 인/1일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -27049,9 +27049,9 @@
"source_line": 5829,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "기",
"basis_source": "사람 판정 — 원문 「(단위: 1기당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -27106,9 +27106,9 @@
"source_line": 5840,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 1일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -29361,9 +29361,9 @@
"source_line": 6254,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -29431,9 +29431,9 @@
"source_line": 6269,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -29484,9 +29484,9 @@
"source_line": 6280,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 일당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -31131,9 +31131,9 @@
"source_line": 6520,
"pum_form": "productivity",
"form_basis": "사람 판정 — 혼합 — 값이 「㎥/일」이라 생산량형",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: ㎥/일 당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -33982,9 +33982,9 @@
"source_line": 6943,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 일 당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -37556,9 +37556,9 @@
"source_line": 7415,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "㎡",
"basis_source": "사람 판정 — 원문 「(단위: 인/㎡)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -37896,8 +37896,8 @@
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": 1.0,
"basis_unit": "",
"basis_source": "표 안",
"basis_unit": "",
"basis_source": "사람 판정 — 왜곡 고침 — 원문 「(단위: 1일당)」인데 「개」로 서 있었음",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -39079,9 +39079,9 @@
"source_line": 7715,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "개",
"basis_source": "사람 판정 — 원문 「(단위: 인/개)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -39500,9 +39500,9 @@
"source_line": 7788,
"pum_form": "requirement",
"form_basis": "직종 표기((인)·인부·공)",
"basis_quantity": null,
"basis_unit": null,
"basis_source": null,
"basis_quantity": 1.0,
"basis_unit": "일",
"basis_source": "사람 판정 — 원문 「(단위: 일 당)」",
"resource_shares": {},
"partial_ratio": false,
"expression_cells": [],
@@ -45,6 +45,8 @@ MASTER = OUT_DIR / "work_item_master_2026-01-01.json"
#: 2026-09-17 두 번 갱신 — 둘 다 **더하기만**(덮어쓴 것 0 · 사라진 것 0):
#: ① 표머리 몫꼴(`인/ha`·`인/100kg`)에서 밑수 18개를 새로 읽음
#: ② 형태 미판정 14표를 사람 판정으로 가름(안티그래비티 원문 대조) · 그중 5표는 밑수도 확인
#: ③ 원문 전수 대조 60건 중 **원문 괄호가 분명한 16표**의 밑수를 채움
#: ⚠ 그 가운데 **하나(F0430)만 값이 바뀜** — 원문이 「1일당」인데 「개」로 서 있던 왜곡을 고침
#: ⇒ 곱하면 안 되던 줄이 곱할 수 있게 된 것이지, 있던 값이 바뀐 것이 아니다.
#: 2026-09-17 랩탑 메인 — 목차 오기 둘을 본문 번호로 바로잡아(브레인 지시) **네 줄만** 바뀌어 새로 뜸
#: (옛 f8b8fba1…). 네 줄 모습은 `test_목차_오기는_본문_번호로_바로잡고_열쇠는_그대로` 가 잼 ·
@@ -52,7 +54,7 @@ MASTER = OUT_DIR / "work_item_master_2026-01-01.json"
#: 2026-09-17 랩탑 메인 둘째 — 헛단위 뺌(인용을 제목으로 읽은 13-3 표 셋 · 부록 사례 번호 겹침 일곱)으로 다시 뜸
#: (옛 be88f730…). 바뀐 줄은 13-3·4-1·4-2·2-1·2-2·3-1·3-2·3-3·13-4-1·13-5-2 의 표 귀속뿐 —
#: `test_work_item_master_toc` 가 자리를 잼 · 단가표 대조는 그 파일 머리.
BASELINE_WORK_ITEMS_SHA = "cd9a0e755249fb408c01499e980afed02a7b882b36ae7029a5bd35ab63f5c5da"
BASELINE_WORK_ITEMS_SHA = "4c97958865d1779eacff4696ea77d35534044b8f81b2ef3033935ead2aadb6bc"
#: 열쇠 작업이 새로 얹은 칸. 지문을 잴 때만 떼어낸다.
ADDED_FIELDS = (
@@ -354,13 +356,37 @@ def test_산림_형태_미판정이_없다(master: dict) -> None:
for table_id, form in 가른것.items():
assert by_id[table_id]["pum_form"] == form, table_id
assert by_id[table_id]["form_basis"].startswith("사람 판정"), table_id
# 머리가 소실돼 자동으로는 못 읽는 표의 밑수 손으로 적
assert set(BASIS_JUDGMENTS) <= set(가른것)
# 미판정 열넷 가운데 머리가 소실돼 자동으로는 못 읽는 표의 밑수 손으로 적
# (그 뒤 원문 전수 대조로 다른 표들도 들어와 `BASIS_JUDGMENTS` 는 더 넓다)
assert {"F0140", "F0322", "F0333", "F0346"} <= set(BASIS_JUDGMENTS)
assert by_id["F0140"]["basis_quantity"] == 100.0 and by_id["F0140"]["basis_unit"] == ""
assert by_id["F0322"]["basis_quantity"] == 1000.0 and by_id["F0322"]["basis_unit"] == ""
assert judged_form("F0140", "5-26-1")[0] == "requirement"
def test_원문_대조_밑수_판정(master: dict) -> None:
"""원문 md ↔ 마스터 전수 대조(안티그래비티 02544795)에서 나온 밑수를 반영했는가.
⚠ **보고가 적은 단위를 그대로 믿지 않는다.** 보고는 「인」을 밑수로 적은 자리가 셋 있었고
그 자리(8-6-2 드론방제·8-6-3 지상방제)는 2026-09-09 에 오독으로 판정된 바로 그 표다.
원문 줄을 열어 괄호 글을 확인한 것만, 그것도 **분모가 하나일 때만** 싣는다.
"""
by_id = {t["pum_table_id"]: t for it in master["work_items"] for t in it["tables"]}
for table_id, quantity, unit in (
("F0082", 1.0, "ha"), # (단위 : 인/ha)
("F0311", 1.0, ""), # (단위: 1기당)
("F0424", 1.0, ""), # (단위: 인/㎡)
("F0430", 1.0, ""), # ⚠ 왜곡 고침 — 「개」로 서 있었음
):
assert by_id[table_id]["basis_quantity"] == quantity, table_id
assert by_id[table_id]["basis_unit"] == unit, table_id
# 「인」은 밑수가 아니다 — 보고가 그렇게 적었어도 안 넣는다
for table_id in ("F0228", "F0229", "F0230"):
assert by_id[table_id]["basis_unit"] != "", table_id
# 분모가 둘인 자리도 안 넣는다 — 3-2 작업로 선정은 원문이 「인/1일 1km당」이다
assert by_id["F0076"]["basis_unit"] != "ha"
def test_표머리_몫꼴_밑수_읽기() -> None:
"""「당」 없이 몫으로만 적힌 표머리에서 밑수를 읽는다 — 분모가 밑수다(명세 꼴 B).