Merge remote-tracking branch 'origin/안티그래비티' into sub_desktop_1

산출은 저쪽 것으로 다시 짓고, 내 쪽 시험 파일(열쇠 장부)은 내 것을 남김
(저쪽은 form 미판정 14 판정 전 판이라 70줄이 빠져 있었음).

- 이름표 — 산림 형태 미판정이 0 이 되어 그 표가 값 묶음으로 내려감(표 102 → 101)
- 갈래 다듬어진 줄 14 → 70(저쪽 이름 다듬기가 들어옴) · 갈래 332 그대로
- 지문·줄 수 다시 맞춤(밑수 미확보 산림 103 · 건설 439)

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:35:19 +09:00
co-authored by Claude Opus 5
22 changed files with 6933 additions and 434 deletions
@@ -13,7 +13,7 @@
장 파일 경계가 쪽 기준이라(원문 머리 경고) 앞뒤 장 제목도 받고, 파일 첫머리 표는 앞 장 파일 꼬리까지 봄.
⚠ 못 붙인 표는 조용히 버리지 않고 `orphan_tables` 목록.
⚠ 총칙·묶는 마디 덜어내기 안 함(가름만) — 총칙 뿌리는 `axis_policy.json` 건설 축(데스크탑 서브 잣대) · 미확정 둘은 안 넣음.
갈래 키 안 붙임 — B09 표 읽기가 산림 표로만 검증됨(빈칸 = 못 가름).
갈래 = 산림과 같은 B09 표 읽기로 가름(못 가른 공종은 빈칸) · 갈래 불변 열쇠는 장부(`CW-00001#01`).
"""
from __future__ import annotations
@@ -284,8 +284,11 @@ def build_const() -> tuple:
node["tables"].append(entry)
attached += 1
apply_parent_modes(nodes, {}) # 합산형은 사람이 적은 것만 — 건설은 아직 없음(전부 choose_one)
for node in nodes:
node["variant_keys"] = [] # 못 가름 — B09 표 읽기가 산림 표로만 검증됨
# 갈래 — 산림과 **같은 표 읽기 한 벌**(B09 `build_resource_axis`)로 가름 · 못 가른 공종은 빈칸.
# 갈래 불변 열쇠(`CW-00001#01`)는 `finish` 가 장부로 줌(데스크탑 서브 · 2026-09-17 브레인 ④).
from B08_Quantity.B08_Quantity_Build_WorkItemMaster_Variants import attach_variant_keys
attach_variant_keys(nodes, data["effective_date"])
return finish(
data,
source=SOURCE,
@@ -303,7 +306,7 @@ def build_const() -> tuple:
"divisions": list(DIVISIONS),
"toc_source": BOOK_NAME + " 머리 「목 차」",
"section_from_body": True,
"variant_keys_attached": False,
"variant_keys_attached": True, # 산림과 같은 표 읽기 — 못 가른 공종은 빈칸
"general_provision_roots": list(general_roots()),
},
)
@@ -180,10 +180,42 @@ def variant_match(text: str) -> str:
return "".join(_TILDES.get(ch, ch) for ch in squeezed)
_SYLLABLE = re.compile(r"^[가-힣]$")
_PIECE_GAP = re.compile(r"( [·ㆍ・›] )")
def tidy_spacing(text: str) -> str:
"""**자간 공백** 다듬기 — 「측 량」→「측량」 · 「평 규 준 틀」→「평규준틀」 · 「굴 삭 기 (무한궤도)」→「굴삭기 (무한궤도)」.
한 글자 낱말뿐인 조각이거나, 한 글자 낱말이 **셋 이상** 이어질 때만 붙임 —
「그 외 자재」·「호박돌 및 야면석」 같은 진짜 띄어쓰기는 그대로(2026-09-17 서브 훑기 175줄 · 브레인).
⚠ 보일 이름만 — 열쇠는 번호라(공종 `FW-…` · 갈래 `#01`) 다듬어도 안 흔들림.
"""
# 가운뎃점·경로 표시 사이가 한 조각 — 「메 붙 임 · 깬 돌 · 뒷길이 25㎝」 의 「깬 돌」
pieces = _PIECE_GAP.split(" ".join(str(text or "").split()))
return "".join(piece if n % 2 else _tidy_piece(piece) for n, piece in enumerate(pieces))
def _tidy_piece(text: str) -> str:
tokens = text.split(" ")
if len(tokens) >= 2 and all(_SYLLABLE.match(t) for t in tokens):
return "".join(tokens)
out: list[str] = []
run: list[str] = []
for token in [*tokens, ""]:
if token and _SYLLABLE.match(token):
run.append(token)
continue
out.extend(["".join(run)] if len(run) >= 3 else run)
run = []
if token:
out.append(token)
return " ".join(out)
def variant_display(text: str) -> str:
"""다듬은 갈래 이름 — 자간 공백을 한 칸으로, 물결표를 하나로. 원문은 따로 남긴다."""
spaced = " ".join(str(text or "").split())
return "".join(_TILDES.get(ch, ch) for ch in spaced)
"""다듬은 갈래 이름 — 자간 공백을 붙이고 물결표를 하나로. 원문은 따로 남긴다."""
return "".join(_TILDES.get(ch, ch) for ch in tidy_spacing(text))
def format_variant(serial: int) -> str:
+25 -6
View File
@@ -10,6 +10,7 @@
from __future__ import annotations
import json
import re
from datetime import date
from decimal import Decimal
from functools import lru_cache
@@ -329,15 +330,21 @@ class SortError(ValueError):
"""모르는 열로 세우라 함 — 조용히 원본 차례로 돌아가지 않음(브레인 ④)."""
#: 품셈 번호 꼴(「9-3-2」·「12-17」) — 글자로 세우면 「10-1」이 「2-1」 앞에 섬(서브 훑기 · 브레인).
_NUMBER_PATH = re.compile(r"^\d+(?:-\d+)+$")
def _order_key(value: Any) -> tuple:
"""섞인 칸도 세움 — 수 먼저, 그 뒤 글자."""
"""섞인 칸도 세움 — 수 먼저, 품셈 번호 꼴은 **마디마다 수로**, 그 뒤 글자."""
if isinstance(value, bool):
return (1, str(value))
return (2, str(value))
if isinstance(value, (int, float)):
return (0, float(value))
if isinstance(value, (dict, list)):
return (1, json.dumps(value, ensure_ascii=False, default=str))
return (1, str(value))
return (2, json.dumps(value, ensure_ascii=False, default=str))
if isinstance(value, str) and _NUMBER_PATH.match(value):
return (1, tuple(int(part) for part in value.split("-")))
return (2, str(value))
def _sorted(rows: list[dict[str, Any]], column: str, desc: bool) -> list[dict[str, Any]]:
@@ -517,6 +524,18 @@ def public(row: dict[str, Any]) -> dict[str, Any]:
return {k: v for k, v in row.items() if k not in ("@source", "@axis")}
#: 찾기만 같게 보는 글자 — 원문이 물결표·가운뎃점을 여러 벌로 씀(∼ 26 · ~ 8 · ․ · ㆍ) · 자간 공백(「굴 삭 기」).
#: ⚠ **찾기에만** 씀 — 열쇠·칸 값은 원문 그대로(손질하면 갈래 열쇠가 갈림 · 브레인 2026-09-17).
_SEARCH_SAME = str.maketrans(
{"": "~", "": "~", "": "~", "": "·", "": "·", "": "·", "": "·"}
)
def fold(text: str) -> str:
"""찾기 비교용 — 소문자 · 물결표·가운뎃점 한 벌 · 공백 없앰."""
return "".join(str(text or "").lower().translate(_SEARCH_SAME).split())
def table(
kind: str,
page: int = 1,
@@ -528,12 +547,12 @@ def table(
) -> dict[str, Any]:
all_rows = rows(kind)
columns = _columns(kind, all_rows)
needle = q.strip().lower()
needle = fold(q)
hits = (
[
r
for r in all_rows
if needle in json.dumps(public(r), ensure_ascii=False, default=str).lower()
if needle in fold(json.dumps(public(r), ensure_ascii=False, default=str))
]
if needle
else all_rows
+9 -2
View File
@@ -71,6 +71,13 @@ def _path(item: dict[str, Any] | None, by: dict[str, dict]) -> str:
return PATH_JOIN.join(reversed(names))
def _shown_path(item: dict[str, Any], by: dict[str, dict]) -> str:
"""목록에 보일 경로 — 조각마다 자간 공백 다듬기(「토목부문 › 측 량」→「측량」). 열쇠와 무관."""
from B08_Quantity.B08_Quantity_Build_WorkItemMaster_Keys import tidy_spacing
return PATH_JOIN.join(tidy_spacing(part) for part in _path(item, by).split(PATH_JOIN))
def base_rows(kind: str) -> list[dict[str, Any]]:
found = doc(kind)
if found is None:
@@ -101,7 +108,7 @@ def base_rows(kind: str) -> list[dict[str, Any]]:
"@source": name,
"work_item_code": item["work_item_code"], # 목차 코드 — 열쇠 아님, 칸으로만
"number": item["number"],
"name": _path(item, by),
"name": _shown_path(item, by), # 자간 공백만 다듬음 — 원문 이름은 마스터에
"variant": variant["name"] if variant else None, # 원문 그대로
"variant_clean": variant["name_clean"] if variant else None, # 다듬은 것
"pum_tables": [t["pum_table_id"] for t in item["tables"]],
@@ -156,7 +163,7 @@ def rules(kind: str) -> list[dict[str, Any]]:
rule = {
"@id": _key(item),
"work_item_code": item["work_item_code"],
"name": _path(item, by),
"name": _shown_path(item, by),
"mode": mode,
"children": [_key(c) for c in children.get(item["work_item_code"], [])],
}
@@ -1504,8 +1504,8 @@
"key": "step_weight",
"name_ko": "단계 무게",
"unit": "",
"visible": true,
"note": "`sum_steps` 일 때만 — 건설은 아직 합산형 선언 없."
"visible": false,
"note": "`sum_steps` 일 때만 — 건설은 아직 합산형 선언어 늘 빈칸이라 감춤(선언이 서면 보이게 할 것)."
},
{
"key": "link",
@@ -1976,8 +1976,8 @@
"merged_tables": 17,
"merged_columns": 178,
"files": 41,
"tables": 100,
"columns": 535,
"tables": 101,
"columns": 538,
"value_groups": 204,
"unknown": 0,
"value_groups_by_kind": {
@@ -6369,7 +6369,7 @@
"file_id": "form_undetermined",
"path": "resources/data_work_item_master/form_undetermined_2026-01-01.json",
"name_ko": "형태 못 정한 표",
"summary": "품·소요량·계수 어느 형태인지 못 정한 품셈 표 기록. 정본이 아니다. 2026-09-17 산림은 **비었음** — 열넷을 다 가름(다시 생기면 표가 선다).",
"summary": "품·소요량·계수 어느 형태인지 못 정한 품셈 표 기록. 정본이 아니다.",
"kind": "byproduct",
"tables": [],
"value_groups": [
@@ -7498,6 +7498,34 @@
"visible": true
}
]
},
{
"key": "variants",
"name_ko": "갈래 열쇠 장부",
"summary": "공종 열쇠 아래 갈래마다 번호를 매긴 것. 사라진 갈래의 번호는 다시 쓰지 않는다.",
"shape": "map",
"rows": 111,
"columns": [
{
"key": "@key",
"name_ko": "갈래를 지닌 건설 공종",
"unit": "",
"visible": true,
"is_row_key": true
},
{
"key": "next_serial",
"name_ko": "다음 갈래 번호",
"unit": "",
"visible": true
},
{
"key": "slots",
"name_ko": "갈래 자리→번호",
"unit": "",
"visible": true
}
]
}
],
"value_groups": [
@@ -1,7 +1,7 @@
{
"schema_version": "1.0",
"dataset_id": "data_work_item_master_manifest",
"generated_at": "2026-09-17T19:00:55+09:00",
"generated_at": "2026-09-17T22:26:44+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": "e4012dc2cbdd0dc74587eeb99dd14581c53e8457e8c678259ff91c3549a0739c",
"size_bytes": 925871
"sha256": "b73d3d9ce7c4c6de7d8c99cb2db54ce32285b4a2c37b60962b7be8beb800abce",
"size_bytes": 925751
},
{
"file": "form_undetermined_2026-01-01.json",
@@ -1,7 +1,7 @@
{
"schema_version": "1.0",
"dataset_id": "data_work_item_master_manifest",
"generated_at": "2026-09-17T19:00:56+09:00",
"generated_at": "2026-09-17T22:27:36+09:00",
"built_by": "B08_Quantity/B08_Quantity_Build_WorkItemMaster.py",
"source": {
"dataset_id": "pum_const",
@@ -12,8 +12,8 @@
"files": [
{
"file": "const_work_item_master_2026-01-01.json",
"sha256": "170abf1f23e7265415d460659b7552aa83c9136dc93b45344277c1e3c56ba6ed",
"size_bytes": 3780743
"sha256": "9bd4b0be9cf27df23781fdd9feea8ed7be2427e815db0563bc2b9eeb79a2f98b",
"size_bytes": 3839594
},
{
"file": "const_form_undetermined_2026-01-01.json",
File diff suppressed because it is too large Load Diff
@@ -10951,5 +10951,969 @@
"first_toc_number": "4-3-3",
"first_name": "배관누수 검사"
}
},
"variants": {
"CW-00063": {
"next_serial": 3,
"slots": {
"5m이하": "01",
"10m이하": "02"
}
},
"CW-00064": {
"next_serial": 3,
"slots": {
"평규준틀": "01",
"귀규준틀": "02"
}
},
"CW-00075": {
"next_serial": 3,
"slots": {
"10m이하": "01",
"10m초과∼20m이하": "02"
}
},
"CW-00077": {
"next_serial": 3,
"slots": {
"높이2m": "01",
"높이4m": "02"
}
},
"CW-00080": {
"next_serial": 3,
"slots": {
"벽용": "01",
"슬래브발코니,난간용": "02"
}
},
"CW-00087": {
"next_serial": 3,
"slots": {
"보행자출입구": "01",
"차량출입구": "02"
}
},
"CW-00116": {
"next_serial": 3,
"slots": {
"설치": "01",
"해체": "02"
}
},
"CW-00117": {
"next_serial": 3,
"slots": {
"H=3.0m이하": "01",
"4.0m이하": "02"
}
},
"CW-00118": {
"next_serial": 5,
"slots": {
"H=3.0m이하": "01",
"H=4.0m이하": "02",
"H=5.0m이하": "03",
"H=6.0m이하": "04"
}
},
"CW-00127": {
"next_serial": 3,
"slots": {
"설치": "01",
"해체": "02"
}
},
"CW-00129": {
"next_serial": 3,
"slots": {
"지상또는건물설치": "01",
"타워크레인설치": "02"
}
},
"CW-00135": {
"next_serial": 4,
"slots": {
"300600㎜": "01",
"700900㎜": "02",
"1,0001,200㎜": "03"
}
},
"CW-00151": {
"next_serial": 3,
"slots": {
"30㎝미만": "01",
"30㎝이상": "02"
}
},
"CW-00154": {
"next_serial": 3,
"slots": {
"우물통발파": "01",
"우물통발파이외": "02"
}
},
"CW-00158": {
"next_serial": 3,
"slots": {
"15cm": "01",
"30cm": "02"
}
},
"CW-00182": {
"next_serial": 4,
"slots": {
"5m미만": "01",
"5m이상∼8m미만": "02",
"8m이상": "03"
}
},
"CW-00210": {
"next_serial": 3,
"slots": {
"쌓기": "01",
"놓기": "02"
}
},
"CW-00231": {
"next_serial": 3,
"slots": {
"토사": "01",
"자갈/호박돌": "02"
}
},
"CW-00233": {
"next_serial": 3,
"slots": {
"=20m이하": "01",
"=20m35m": "02"
}
},
"CW-00236": {
"next_serial": 3,
"slots": {
"외부반입/반출": "01",
"작업구간이동": "02"
}
},
"CW-00239": {
"next_serial": 3,
"slots": {
"요동식": "01",
"전회전식": "02"
}
},
"CW-00247": {
"next_serial": 3,
"slots": {
"무근콘크리트": "01",
"철근콘크리트": "02"
}
},
"CW-00271": {
"next_serial": 3,
"slots": {
"ø12.7㎜": "01",
"ø15.2㎜": "02"
}
},
"CW-00286": {
"next_serial": 5,
"slots": {
"D900": "01",
"D1,200": "02",
"D1,500": "03",
"D1,800": "04"
}
},
"CW-00341": {
"next_serial": 3,
"slots": {
"2": "01",
"1": "02"
}
},
"CW-00342": {
"next_serial": 2,
"slots": {
"2": "01"
}
},
"CW-00343": {
"next_serial": 2,
"slots": {
"2": "01"
}
},
"CW-00371": {
"next_serial": 2,
"slots": {
"㎾": "01"
}
},
"CW-00450": {
"next_serial": 6,
"slots": {
"40㎝": "01",
"45㎝": "02",
"50㎝": "03",
"60㎝": "04",
"70㎝": "05"
}
},
"CW-00454": {
"next_serial": 3,
"slots": {
"식생매트설치": "01",
"복토": "02"
}
},
"CW-00472": {
"next_serial": 3,
"slots": {
"공동구": "01",
"바닥/인버트": "02"
}
},
"CW-00487": {
"next_serial": 3,
"slots": {
"일단": "01",
"양단": "02"
}
},
"CW-00489": {
"next_serial": 3,
"slots": {
"50㎏": "01",
"60㎏": "02"
}
},
"CW-00491": {
"next_serial": 3,
"slots": {
"레일인장법": "01",
"자연대기온도법": "02"
}
},
"CW-00494": {
"next_serial": 4,
"slots": {
"37㎏": "01",
"50㎏": "02",
"60㎏": "03"
}
},
"CW-00497": {
"next_serial": 3,
"slots": {
"조임": "01",
"해체": "02"
}
},
"CW-00527": {
"next_serial": 13,
"slots": {
"800": "01",
"900": "02",
"1,000": "03",
"1,100": "04",
"1,200": "05",
"1,350": "06",
"1,500": "07",
"1.650": "08",
"1,800": "09",
"2,000": "10",
"2,200": "11",
"2,400": "12"
}
},
"CW-00537": {
"next_serial": 7,
"slots": {
"75": "01",
"100": "02",
"150": "03",
"200": "04",
"250": "05",
"300": "06"
}
},
"CW-00547": {
"next_serial": 8,
"slots": {
"50": "01",
"75": "02",
"100": "03",
"150": "04",
"200": "05",
"250": "06",
"300": "07"
}
},
"CW-00548": {
"next_serial": 5,
"slots": {
"8001,100": "01",
"1,2001,800": "02",
"2,0002,200": "03",
"2,4003,000": "04"
}
},
"CW-00553": {
"next_serial": 3,
"slots": {
"80": "01",
"100": "02"
}
},
"CW-00564": {
"next_serial": 2,
"slots": {
"0.1㎥이상": "01"
}
},
"CW-00566": {
"next_serial": 3,
"slots": {
"0.1㎥이상": "01",
"0.03㎥이하": "02"
}
},
"CW-00567": {
"next_serial": 6,
"slots": {
"기초고르기": "01",
"피복석고르기": "02",
"피복석거친고르기": "03",
"내부사석고르기": "04",
"필터사석고르기": "05"
}
},
"CW-00586": {
"next_serial": 3,
"slots": {
"BX": "01",
"NX": "02"
}
},
"CW-00700": {
"next_serial": 7,
"slots": {
"ø16이하": "01",
"ø20이하": "02",
"ø24이하": "03",
"ø28이하": "04",
"ø32이하": "05",
"ø40이하": "06"
}
},
"CW-00703": {
"next_serial": 3,
"slots": {
"판두께1.6㎜": "01",
"판두께2.3㎜": "02"
}
},
"CW-00708": {
"next_serial": 3,
"slots": {
"자동용접": "01",
"수동용접": "02"
}
},
"CW-00715": {
"next_serial": 3,
"slots": {
"1.0B": "01",
"1.5B": "02"
}
},
"CW-00717": {
"next_serial": 5,
"slots": {
"벽돌": "01",
"치장벽돌": "02",
"블록": "03",
"ALC블록": "04"
}
},
"CW-00735": {
"next_serial": 3,
"slots": {
"주택": "01",
"일반": "02"
}
},
"CW-00782": {
"next_serial": 3,
"slots": {
"바닥": "01",
"수직부": "02"
}
},
"CW-00784": {
"next_serial": 3,
"slots": {
"바닥": "01",
"수직부": "02"
}
},
"CW-00801": {
"next_serial": 3,
"slots": {
"1층(회)": "01",
"2층(회)": "02"
}
},
"CW-00802": {
"next_serial": 3,
"slots": {
"바닥": "01",
"수직부": "02"
}
},
"CW-00831": {
"next_serial": 3,
"slots": {
"450×450": "01",
"600×600": "02"
}
},
"CW-00841": {
"next_serial": 3,
"slots": {
"일반철재": "01",
"경량철재": "02"
}
},
"CW-00844": {
"next_serial": 3,
"slots": {
"모래체가름포함": "01",
"모래체가름제외": "02"
}
},
"CW-00850": {
"next_serial": 3,
"slots": {
"3.6m이하": "01",
"3.6m초과∼7.2m이하": "02"
}
},
"CW-00861": {
"next_serial": 5,
"slots": {
"1.0㎡이하": "01",
"1.03.0㎡이하": "02",
"3.06.0㎡이하": "03",
"6.08.0㎡이하": "04"
}
},
"CW-00862": {
"next_serial": 6,
"slots": {
"1.0㎡이하": "01",
"1.03.0㎡이하": "02",
"3.06.0㎡이하": "03",
"6.09.0㎡이하": "04",
"9.012.0㎡이하": "05"
}
},
"CW-00865": {
"next_serial": 6,
"slots": {
"5㎡미만": "01",
"510㎡미만": "02",
"1015㎡미만": "03",
"1520㎡미만": "04",
"2025㎡미만": "05"
}
},
"CW-00871": {
"next_serial": 3,
"slots": {
"일반도어록": "01",
"디지털도어록": "02"
}
},
"CW-00873": {
"next_serial": 2,
"slots": {
"12mm이하": "01"
}
},
"CW-00922": {
"next_serial": 3,
"slots": {
"ø16mm": "01",
"ø20mm": "02"
}
},
"CW-00946": {
"next_serial": 10,
"slots": {
"ø50이하": "01",
"65": "02",
"80": "03",
"100": "04",
"125": "05",
"150": "06",
"200": "07",
"250": "08",
"300": "09"
}
},
"CW-00950": {
"next_serial": 3,
"slots": {
"세대내": "01",
"공용부위": "02"
}
},
"CW-00955": {
"next_serial": 13,
"slots": {
"0.75㎾이하": "01",
"1.5㎾이하": "02",
"2.2㎾이하": "03",
"3.7㎾이하": "04",
"5.5㎾이하": "05",
"7.5㎾이하": "06",
"11㎾이하": "07",
"15㎾이하": "08",
"22㎾이하": "09",
"37㎾이하": "10",
"55㎾이하": "11",
"75㎾이하": "12"
}
},
"CW-00956": {
"next_serial": 7,
"slots": {
"0.75㎾이하": "01",
"1.5㎾이하": "02",
"2.2㎾이하": "03",
"3.7㎾이하": "04",
"5.5㎾이하": "05",
"7.5㎾이하": "06"
}
},
"CW-00957": {
"next_serial": 13,
"slots": {
"0.75㎾이하": "01",
"1.5㎾이하": "02",
"2.2㎾이하": "03",
"3.7㎾이하": "04",
"5.5㎾이하": "05",
"7.5㎾이하": "06",
"11㎾이하": "07",
"15㎾이하": "08",
"22㎾이하": "09",
"37㎾이하": "10",
"55㎾이하": "11",
"75㎾이하": "12"
}
},
"CW-00963": {
"next_serial": 3,
"slots": {
"700㎜이하": "01",
"900㎜이하": "02"
}
},
"CW-00969": {
"next_serial": 7,
"slots": {
"ø15mm": "01",
"ø20mm": "02",
"ø25mm": "03",
"ø32mm": "04",
"ø40mm": "05",
"ø50mm": "06"
}
},
"CW-00972": {
"next_serial": 11,
"slots": {
"ø1525": "01",
"3250": "02",
"65": "03",
"80": "04",
"100": "05",
"125": "06",
"150": "07",
"200": "08",
"250": "09",
"300": "10"
}
},
"CW-00977": {
"next_serial": 4,
"slots": {
"ø1315": "01",
"2032": "02",
"4050": "03"
}
},
"CW-00978": {
"next_serial": 3,
"slots": {
"ø1315mm": "01",
"ø2032mm": "02"
}
},
"CW-00981": {
"next_serial": 3,
"slots": {
"ø1315mm": "01",
"ø2032mm": "02"
}
},
"CW-00982": {
"next_serial": 5,
"slots": {
"ø50mm": "01",
"ø6580mm": "02",
"ø100125mm": "03",
"ø150mm": "04"
}
},
"CW-00986": {
"next_serial": 3,
"slots": {
"거치형": "01",
"벽걸이형": "02"
}
},
"CW-01000": {
"next_serial": 4,
"slots": {
"0.5㎡미만": "01",
"1.0㎡미만": "02",
"1.5㎡미만": "03"
}
},
"CW-01002": {
"next_serial": 4,
"slots": {
"ø50㎜": "01",
"ø75㎜": "02",
"ø100㎜": "03"
}
},
"CW-01011": {
"next_serial": 17,
"slots": {
"유효길이610㎜": "01",
"762〃": "02",
"914〃": "03",
"1,067〃": "04",
"1,219〃": "05",
"1,372〃": "06",
"1,524〃": "07",
"1,676〃": "08",
"1,829〃": "09",
"1,981〃": "10",
"2,134〃": "11",
"2,286〃": "12",
"2,438〃": "13",
"2,591〃": "14",
"2,875〃": "15",
"3,048〃": "16"
}
},
"CW-01014": {
"next_serial": 3,
"slots": {
"실내기": "01",
"실외기": "02"
}
},
"CW-01018": {
"next_serial": 2,
"slots": {
"15,000Kcal/hr": "01"
}
},
"CW-01020": {
"next_serial": 6,
"slots": {
"70×1,000kcal/hr이하": "01",
"120〃": "02",
"150〃": "03",
"240〃": "04",
"360〃": "05"
}
},
"CW-01022": {
"next_serial": 10,
"slots": {
"주철재바닥설치20절이하": "01",
"21절이상": "02",
"벽걸이3절": "03",
"천장달기3절": "04",
"1m길트": "05",
"콘백터길이1m미만": "06",
"베이스보드1단형길이2m미만": "07",
"2m이상": "08",
"강판제및알루미늄제방열기1m미만": "09"
}
},
"CW-01027": {
"next_serial": 7,
"slots": {
"2구": "01",
"3구": "02",
"4구": "03",
"5구": "04",
"6구": "05",
"7구": "06"
}
},
"CW-01029": {
"next_serial": 8,
"slots": {
"100": "01",
"200": "02",
"300": "03",
"400": "04",
"500": "05",
"750": "06",
"1,000": "07"
}
},
"CW-01032": {
"next_serial": 5,
"slots": {
"건타입오일버너0.75㎾": "01",
"1.5": "02",
"(전자동방식)2.2": "03",
"3.7": "04"
}
},
"CW-01035": {
"next_serial": 11,
"slots": {
"ø50": "01",
"65": "02",
"80": "03",
"100": "04",
"125": "05",
"150": "06",
"200": "07",
"250": "08",
"300": "09",
"350": "10"
}
},
"CW-01036": {
"next_serial": 3,
"slots": {
"일반철재": "01",
"경량철재": "02"
}
},
"CW-01045": {
"next_serial": 3,
"slots": {
"지상노출관": "01",
"지하매설관": "02"
}
},
"CW-01053": {
"next_serial": 2,
"slots": {
"소화용구격납상자": "01"
}
},
"CW-01058": {
"next_serial": 2,
"slots": {
"관말시험밸브": "01"
}
},
"CW-01067": {
"next_serial": 2,
"slots": {
"압력공기탱크": "01"
}
},
"CW-01072": {
"next_serial": 2,
"slots": {
"스프링클러헤드": "01"
}
},
"CW-01083": {
"next_serial": 6,
"slots": {
"ø20": "01",
"25": "02",
"32": "03",
"40": "04",
"50": "05"
}
},
"CW-01085": {
"next_serial": 20,
"slots": {
"ø25": "01",
"32": "02",
"40": "03",
"50": "04",
"63": "05",
"75": "06",
"90": "07",
"110": "08",
"125": "09",
"140": "10",
"160": "11",
"180": "12",
"200": "13",
"225": "14",
"250": "15",
"280": "16",
"315": "17",
"355": "18",
"400": "19"
}
},
"CW-01087": {
"next_serial": 13,
"slots": {
"ø2025": "01",
"4050": "02",
"65": "03",
"80": "04",
"100": "05",
"125": "06",
"150": "07",
"200": "08",
"250": "09",
"300": "10",
"350": "11",
"400": "12"
}
},
"CW-01093": {
"next_serial": 7,
"slots": {
"분전반": "01",
"조작반": "02",
"계기반(자립개방)": "03",
"계기반(자립밀폐)": "04",
"계기반(현장)": "05",
"〃(발신기수납상)": "06"
}
},
"CW-01100": {
"next_serial": 4,
"slots": {
"유니온엘보": "01",
"공기압축기시험": "02",
"조작함(설비물)": "03"
}
},
"CW-01114": {
"next_serial": 5,
"slots": {
"ø20(90)": "01",
"25(90)": "02",
"32(110)": "03",
"40(110)": "04"
}
},
"CW-01128": {
"next_serial": 7,
"slots": {
"ø16이하": "01",
"ø20이하": "02",
"ø24이하": "03",
"ø28이하": "04",
"ø32이하": "05",
"ø40이하": "06"
}
},
"CW-01199": {
"next_serial": 4,
"slots": {
"7.5㎾": "01",
"15㎾": "02",
"30㎾": "03"
}
},
"CW-01200": {
"next_serial": 2,
"slots": {
"0.5": "01"
}
},
"CW-01201": {
"next_serial": 3,
"slots": {
"산기분기관제작": "01",
"분기관및산기장치설치": "02"
}
},
"CW-01291": {
"next_serial": 5,
"slots": {
"#8번": "01",
"#10번": "02",
"#12번": "03",
"#15번": "04"
}
},
"CW-01300": {
"next_serial": 3,
"slots": {
"3시간차단": "01",
"4시간차단": "02"
}
},
"CW-01301": {
"next_serial": 3,
"slots": {
"판넬설치(개당)": "01",
"가받침해체및설치(m당)": "02"
}
},
"CW-01302": {
"next_serial": 3,
"slots": {
"궤도정정": "01",
"궤도이설": "02"
}
},
"CW-01306": {
"next_serial": 4,
"slots": {
"A급": "01",
"B급": "02",
"C급": "03"
}
},
"CW-01358": {
"next_serial": 15,
"slots": {
"ø15": "01",
"20": "02",
"25": "03",
"32": "04",
"40": "05",
"50": "06",
"65": "07",
"80": "08",
"100": "09",
"125": "10",
"150": "11",
"200": "12",
"250": "13",
"300": "14"
}
}
}
}
@@ -4,7 +4,7 @@
"effective_date": "2026-01-01",
"pum_edition": "2026-01-01",
"toc_edition": "산림청고시제2025-82호",
"generated_at": "2026-09-17T19:00:55+09:00",
"generated_at": "2026-09-17T22:26:44+09:00",
"dataset_version": {
"dataset_id": "pum_forest",
"effective_date": "2026-01-01",
@@ -10618,12 +10618,12 @@
{
"variant_key": "01",
"name": "채 취",
"name_clean": "채 취"
"name_clean": "채취"
},
{
"variant_key": "02",
"name": "운 반",
"name_clean": "운 반"
"name_clean": "운반"
},
{
"variant_key": "03",
@@ -28953,17 +28953,17 @@
{
"variant_key": "01",
"name": "간 단",
"name_clean": "간 단"
"name_clean": "간단"
},
{
"variant_key": "02",
"name": "보 통",
"name_clean": "보 통"
"name_clean": "보통"
},
{
"variant_key": "03",
"name": "복 잡",
"name_clean": "복 잡"
"name_clean": "복잡"
},
{
"variant_key": "04",
@@ -31445,12 +31445,12 @@
{
"variant_key": "03",
"name": "설 치",
"name_clean": "설 치"
"name_clean": "설치"
},
{
"variant_key": "04",
"name": "철 거",
"name_clean": "철 거"
"name_clean": "철거"
}
],
"toc_code": "FP-12-17-01",
@@ -33774,17 +33774,17 @@
{
"variant_key": "01",
"name": "간 단",
"name_clean": "간 단"
"name_clean": "간단"
},
{
"variant_key": "02",
"name": "보 통",
"name_clean": "보 통"
"name_clean": "보통"
},
{
"variant_key": "03",
"name": "복 잡",
"name_clean": "복 잡"
"name_clean": "복잡"
}
],
"toc_code": "FP-12-38",
@@ -33952,17 +33952,17 @@
{
"variant_key": "01",
"name": "간 단",
"name_clean": "간 단"
"name_clean": "간단"
},
{
"variant_key": "02",
"name": "보 통",
"name_clean": "보 통"
"name_clean": "보통"
},
{
"variant_key": "03",
"name": "복 잡",
"name_clean": "복 잡"
"name_clean": "복잡"
}
],
"toc_code": "FP-12-38-02",
@@ -34082,17 +34082,17 @@
{
"variant_key": "01",
"name": "복 잡",
"name_clean": "복 잡"
"name_clean": "복잡"
},
{
"variant_key": "02",
"name": "보 통",
"name_clean": "보 통"
"name_clean": "보통"
},
{
"variant_key": "03",
"name": "간 단",
"name_clean": "간 단"
"name_clean": "간단"
}
],
"toc_code": "FP-12-38-03",
@@ -36558,202 +36558,202 @@
{
"variant_key": "01",
"name": "메 붙 임 · 깬 돌 · 뒷길이 25㎝",
"name_clean": "메임 · 깬 돌 · 뒷길이 25㎝"
"name_clean": "메임 · 깬돌 · 뒷길이 25㎝"
},
{
"variant_key": "02",
"name": "메 붙 임 · 깬 돌 · 뒷길이 30㎝",
"name_clean": "메임 · 깬 돌 · 뒷길이 30㎝"
"name_clean": "메임 · 깬돌 · 뒷길이 30㎝"
},
{
"variant_key": "03",
"name": "메 붙 임 · 깬 돌 · 뒷길이 35㎝",
"name_clean": "메임 · 깬 돌 · 뒷길이 35㎝"
"name_clean": "메임 · 깬돌 · 뒷길이 35㎝"
},
{
"variant_key": "04",
"name": "메 붙 임 · 깬 돌 · 뒷길이 45㎝",
"name_clean": "메임 · 깬 돌 · 뒷길이 45㎝"
"name_clean": "메임 · 깬돌 · 뒷길이 45㎝"
},
{
"variant_key": "05",
"name": "메 붙 임 · 깬 돌 · 뒷길이 55㎝",
"name_clean": "메임 · 깬 돌 · 뒷길이 55㎝"
"name_clean": "메임 · 깬돌 · 뒷길이 55㎝"
},
{
"variant_key": "06",
"name": "메 붙 임 · 깬 돌 · 뒷길이 60㎝",
"name_clean": "메임 · 깬 돌 · 뒷길이 60㎝"
"name_clean": "메임 · 깬돌 · 뒷길이 60㎝"
},
{
"variant_key": "07",
"name": "메 붙 임 · 깬 돌 · 뒷길이 70㎝",
"name_clean": "메임 · 깬 돌 · 뒷길이 70㎝"
"name_clean": "메임 · 깬돌 · 뒷길이 70㎝"
},
{
"variant_key": "08",
"name": "메 붙 임 · 깬잡석 · 뒷길이 25㎝",
"name_clean": "메임 · 깬잡석 · 뒷길이 25㎝"
"name_clean": "메임 · 깬잡석 · 뒷길이 25㎝"
},
{
"variant_key": "09",
"name": "메 붙 임 · 깬잡석 · 뒷길이 30㎝",
"name_clean": "메임 · 깬잡석 · 뒷길이 30㎝"
"name_clean": "메임 · 깬잡석 · 뒷길이 30㎝"
},
{
"variant_key": "10",
"name": "메 붙 임 · 깬잡석 · 뒷길이 35㎝",
"name_clean": "메임 · 깬잡석 · 뒷길이 35㎝"
"name_clean": "메임 · 깬잡석 · 뒷길이 35㎝"
},
{
"variant_key": "11",
"name": "메 붙 임 · 깬잡석 · 뒷길이 45㎝",
"name_clean": "메임 · 깬잡석 · 뒷길이 45㎝"
"name_clean": "메임 · 깬잡석 · 뒷길이 45㎝"
},
{
"variant_key": "12",
"name": "메 붙 임 · 깬잡석 · 뒷길이 55㎝",
"name_clean": "메임 · 깬잡석 · 뒷길이 55㎝"
"name_clean": "메임 · 깬잡석 · 뒷길이 55㎝"
},
{
"variant_key": "13",
"name": "메 붙 임 · 깬잡석 · 뒷길이 60㎝",
"name_clean": "메임 · 깬잡석 · 뒷길이 60㎝"
"name_clean": "메임 · 깬잡석 · 뒷길이 60㎝"
},
{
"variant_key": "14",
"name": "메 붙 임 · 깬잡석 · 뒷길이 70㎝",
"name_clean": "메임 · 깬잡석 · 뒷길이 70㎝"
"name_clean": "메임 · 깬잡석 · 뒷길이 70㎝"
},
{
"variant_key": "15",
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 25㎝",
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 25㎝"
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 25㎝"
},
{
"variant_key": "16",
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 30㎝",
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 30㎝"
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 30㎝"
},
{
"variant_key": "17",
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 35㎝",
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 35㎝"
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 35㎝"
},
{
"variant_key": "18",
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 45㎝",
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 45㎝"
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 45㎝"
},
{
"variant_key": "19",
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 55㎝",
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 55㎝"
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 55㎝"
},
{
"variant_key": "20",
"name": "메 붙 임 · 조약돌 및 야면석 · 뒷길이 60㎝",
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 60㎝"
"name_clean": "메임 · 조약돌 및 야면석 · 뒷길이 60㎝"
},
{
"variant_key": "21",
"name": "찰 붙 임 · 깬 돌 · 뒷길이 25㎝",
"name_clean": "찰임 · 깬 돌 · 뒷길이 25㎝"
"name_clean": "찰임 · 깬돌 · 뒷길이 25㎝"
},
{
"variant_key": "22",
"name": "찰 붙 임 · 깬 돌 · 뒷길이 30㎝",
"name_clean": "찰임 · 깬 돌 · 뒷길이 30㎝"
"name_clean": "찰임 · 깬돌 · 뒷길이 30㎝"
},
{
"variant_key": "23",
"name": "찰 붙 임 · 깬 돌 · 뒷길이 35㎝",
"name_clean": "찰임 · 깬 돌 · 뒷길이 35㎝"
"name_clean": "찰임 · 깬돌 · 뒷길이 35㎝"
},
{
"variant_key": "24",
"name": "찰 붙 임 · 깬 돌 · 뒷길이 45㎝",
"name_clean": "찰임 · 깬 돌 · 뒷길이 45㎝"
"name_clean": "찰임 · 깬돌 · 뒷길이 45㎝"
},
{
"variant_key": "25",
"name": "찰 붙 임 · 깬 돌 · 뒷길이 55㎝",
"name_clean": "찰임 · 깬 돌 · 뒷길이 55㎝"
"name_clean": "찰임 · 깬돌 · 뒷길이 55㎝"
},
{
"variant_key": "26",
"name": "찰 붙 임 · 깬 돌 · 뒷길이 60㎝",
"name_clean": "찰임 · 깬 돌 · 뒷길이 60㎝"
"name_clean": "찰임 · 깬돌 · 뒷길이 60㎝"
},
{
"variant_key": "27",
"name": "찰 붙 임 · 깬 돌 · 뒷길이 70㎝",
"name_clean": "찰임 · 깬 돌 · 뒷길이 70㎝"
"name_clean": "찰임 · 깬돌 · 뒷길이 70㎝"
},
{
"variant_key": "28",
"name": "찰 붙 임 · 깬잡석 · 뒷길이 25㎝",
"name_clean": "찰임 · 깬잡석 · 뒷길이 25㎝"
"name_clean": "찰임 · 깬잡석 · 뒷길이 25㎝"
},
{
"variant_key": "29",
"name": "찰 붙 임 · 깬잡석 · 뒷길이 30㎝",
"name_clean": "찰임 · 깬잡석 · 뒷길이 30㎝"
"name_clean": "찰임 · 깬잡석 · 뒷길이 30㎝"
},
{
"variant_key": "30",
"name": "찰 붙 임 · 깬잡석 · 뒷길이 35㎝",
"name_clean": "찰임 · 깬잡석 · 뒷길이 35㎝"
"name_clean": "찰임 · 깬잡석 · 뒷길이 35㎝"
},
{
"variant_key": "31",
"name": "찰 붙 임 · 깬잡석 · 뒷길이 45㎝",
"name_clean": "찰임 · 깬잡석 · 뒷길이 45㎝"
"name_clean": "찰임 · 깬잡석 · 뒷길이 45㎝"
},
{
"variant_key": "32",
"name": "찰 붙 임 · 깬잡석 · 뒷길이 55㎝",
"name_clean": "찰임 · 깬잡석 · 뒷길이 55㎝"
"name_clean": "찰임 · 깬잡석 · 뒷길이 55㎝"
},
{
"variant_key": "33",
"name": "찰 붙 임 · 깬잡석 · 뒷길이 60㎝",
"name_clean": "찰임 · 깬잡석 · 뒷길이 60㎝"
"name_clean": "찰임 · 깬잡석 · 뒷길이 60㎝"
},
{
"variant_key": "34",
"name": "찰 붙 임 · 깬잡석 · 뒷길이 70㎝",
"name_clean": "찰임 · 깬잡석 · 뒷길이 70㎝"
"name_clean": "찰임 · 깬잡석 · 뒷길이 70㎝"
},
{
"variant_key": "35",
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 25㎝",
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 25㎝"
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 25㎝"
},
{
"variant_key": "36",
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 30㎝",
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 30㎝"
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 30㎝"
},
{
"variant_key": "37",
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 35㎝",
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 35㎝"
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 35㎝"
},
{
"variant_key": "38",
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 45㎝",
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 45㎝"
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 45㎝"
},
{
"variant_key": "39",
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 55㎝",
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 55㎝"
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 55㎝"
},
{
"variant_key": "40",
"name": "찰 붙 임 · 호박돌 및 야면석 · 뒷길이 60㎝",
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 60㎝"
"name_clean": "찰임 · 호박돌 및 야면석 · 뒷길이 60㎝"
}
],
"toc_code": "FP-13-05-01",
@@ -39049,17 +39049,17 @@
{
"variant_key": "02",
"name": "복 토",
"name_clean": "복 토"
"name_clean": "복토"
},
{
"variant_key": "03",
"name": "간 단 구 조",
"name_clean": "간 단 구 조"
"name_clean": "간단구조"
},
{
"variant_key": "04",
"name": "보 통 구 조",
"name_clean": "보 통 구 조"
"name_clean": "보통구조"
}
],
"toc_code": "FP-13-13-02",
@@ -39132,7 +39132,7 @@
{
"variant_key": "01",
"name": "단 끊 기",
"name_clean": "단기"
"name_clean": "단기"
},
{
"variant_key": "02",
@@ -39475,7 +39475,7 @@
{
"variant_key": "01",
"name": "사 면",
"name_clean": "사 면"
"name_clean": "사면"
},
{
"variant_key": "02",
@@ -0,0 +1,95 @@
{
"audit_id": "audit_base_prices_and_work_items_integrity_2026-09-17",
"baseline_commit": "ba593281",
"head_commit": "HEAD",
"audit_date": "2026-09-17T19:39:00+09:00",
"overall_verdict": "PASSED_100_PERCENT_INTEGRITY",
"part1_base_prices_15": {
"total_tables": 15,
"total_rows": 8372,
"row_count_match": true,
"value_diff_count": 0,
"source_files_diff_bytes": 0,
"builder_code_diff_bytes": 0,
"tables_detail": {
"labor": {"rows": 261, "cols": 12, "diff": 0},
"machine": {"rows": 613, "cols": 23, "diff": 0},
"material": {"rows": 6999, "cols": 16, "diff": 0},
"oil": {"rows": 36, "cols": 10, "diff": 0},
"rate": {"rows": 218, "cols": 28, "diff": 0},
"coef": {"rows": 32, "cols": 8, "diff": 0},
"material_surcharge": {"rows": 19, "cols": 6, "diff": 0},
"formwork_reuse": {"rows": 19, "cols": 7, "diff": 0},
"rebar_complexity": {"rows": 8, "cols": 4, "diff": 0},
"timber_structure_class": {"rows": 6, "cols": 4, "diff": 0},
"masonry_slope": {"rows": 20, "cols": 4, "diff": 0},
"masonry_back_length": {"rows": 10, "cols": 4, "diff": 0},
"stone_kind": {"rows": 75, "cols": 5, "diff": 0},
"masonry_class": {"rows": 9, "cols": 5, "diff": 0},
"machine_productivity": {"rows": 47, "cols": 21, "diff": 0}
}
},
"part2_work_item_axes": {
"forest": {
"nodes_count": 477,
"leaves_count": 360,
"units_count": 620,
"tables_attached": 443,
"tables_orphan": 15,
"tables_total": 458
},
"const": {
"toc_nodes_count": 1367,
"attached_work_items": 997,
"flattened_rows": 1293,
"tables_attached": 2192
},
"toc_corrections": [
{
"toc_number": "12-17-2",
"body_number": "12-17-3",
"name": "무근콘크리트(진동기 제외)",
"source_line": 6515,
"table_id": "F0364",
"verdict": "CONFIRMED_BY_BODY_TEXT",
"effect": "F0364 복구, F0363 덮어쓰기 해소"
},
{
"toc_number": "12-24-1",
"body_number": "12-27-1",
"name": "지수판 설치",
"source_line": 6715,
"table_id": "F0375",
"verdict": "CONFIRMED_BY_BODY_TEXT",
"effect": "F0375 복구, F0371 덮어쓰기 해소"
}
],
"ghost_units_removed": [
{
"code": "FP-13-03",
"rows_count": 3,
"reason": "원문 문맥상 '[주] 13-3. 기초다짐 항을 적용한다'는 타 절의 주석 인용문구임",
"restored_tables": {
"F0405": "FP-13-04-01 메쌓기",
"F0406": "FP-13-04-01 메쌓기",
"F0418": "FP-13-05-02 찰붙임"
},
"verdict": "CONFIRMED_NON_WORK_ITEM"
},
{
"code": "FP-04-01/02",
"rows_count": 2,
"reason": "부록 설계사례 예시표 7개(F0455·F0456·F0472~F0476)가 본문 번호와 우연히 겹쳐 오부착되었던 것임",
"verdict": "CONFIRMED_NON_WORK_ITEM_APPENDIX"
}
]
},
"part3_price_impact": {
"total_unit_prices_compared": 677,
"ghost_units_removed": 3,
"anomalous_units_isolated": 1,
"unchanged_unit_prices_count": 673,
"price_change_diff_krw": 0,
"verdict": "ZERO_AMOUNT_VARIATION"
}
}
@@ -0,0 +1,161 @@
---
title: 오늘 작업 기초값 및 공종 축 원문대조 정밀 검증보고서
category: 05_원가정보
status: verified
last_updated: 2026-09-17
sources:
- resources/data_cost_input_value/
- resources/data_work_item_master/work_item_master_2026-01-01.json
- resources/data_work_item_master/const_work_item_master_2026-01-01.json
- resources/knowledge/original/행정규칙/임도 품셈 적용기준 (현 산림사업 표준품셈)/첨부/(산림청고시 제2025-82호) 산림사업 표준품셈.md
- resources/knowledge/original/원가계산/건설공사_표준품셈/2026년_건설공사_표준품셈.md
- git commit ba593281 (2026-09-16 기준선)
- git commit HEAD
---
# 오늘 작업 기초값 및 공종 축 원문대조 정밀 검증보고서
2026-09-17 진행된 **기초값 15종 및 공종 축(산림·건설) 대규모 재편 작업**에 대해, 작업 전 기준선(`ba593281`, 2026-09-16)과 현재 판(`HEAD`)을 전수 맞대어 **"자리는 바뀌어도 값과 금액은 한 원도 바뀌지 않는다"**는 약속이 지켜졌는지 원문과 소스 데이터를 전수 대조·검증한 정밀 보고서이다.
> ⚠ **사용자 지침 준수**: 본 검증은 오직 사실 확인 및 감사 결과만 보고하며, 소스코드나 데이터 파일을 임의로 수정하지 않는다.
---
## 1. 검증 총괄 요약
| 검증 영역 | 항목 수 | 줄 수 일치 여부 | 값의 변동 여부 | 원문 대조 판정 |
|---|:---:|:---:|:---:|:---:|
| **1. 기초값 열다섯** | 15개 테이블 | **8,372줄 완전 일치** | **단 1칸도 변동 없음 (0건)** | **적합 (100% 불변)** |
| **2. 공종 축 (산림·건설)** | 2개 축 | 마디 477개 / 1,367개 | 품셈표 458개 / 2,192개 제자리 부착 | **적합 (무결성 유지)** |
|  • 목차 오기 둘 정정 | 2개 절 | 12-17-3, 12-27-1 | F0364, F0375 제자리 복귀 | **적합 (원문 본문 번호 일치)** |
|  • 헛단위 5줄 제외 | 2개소 | FP-13-03 (3줄), FP-04 (2줄) | 가짜 공종 제거, 본체 귀속 | **적합 (비공종 확인)** |
| **3. 단가·금액 영향** | 677개 공종 | 헛단위 3줄 정상 소멸 | 나머지 670여 개 단가 1원도 불변 | **적합 (금액 불변 통과)** |
---
## 2. 세부 검증 내역
### 1) 기초값 열다섯 (Base Prices & Pumsem Basis) 전수 검사
노임·기계·자재·유가·요율 5종과 품셈 근거 기초데이터 10종(토량환산·자재할증·거푸집·철근·목구조·돌쌓기 4종·기계작업량)을 전수 실측하였다.
#### A. 테이블별 줄 수(`total rows`) 및 열 수(`columns`) 실측
| 번호 | 기초값 종류 (`kind`) | 역할 및 내용 | 줄 수 (`rows`) | 열 수 (`cols`) | 기준선 대비 변동 |
|:---:|---|---|---:|---:|:---:|
| 1 | `labor` | 시중노임단가 (건설 160 + 제조 101) | 261 | 12 | **일치** (변동 0) |
| 2 | `machine` | 건설기계 기초제원 및 손료 | 613 | 23 | **일치** (변동 0) |
| 3 | `material` | 조달청 공표 자재가격 | 6,999 | 16 | **일치** (변동 0) |
| 4 | `oil` | 유가 (전국 평균 및 시도별) | 36 | 10 | **일치** (변동 0) |
| 5 | `rate` | 제비율 (간접노무비·기타경비·보험료 등) | 218 | 28 | **일치** (변동 0) |
| 6 | `coef` | 토량환산계수 L, C | 32 | 8 | **일치** (변동 0) |
| 7 | `material_surcharge` | 자재 할증률 (산림·건설) | 19 | 6 | **일치** (변동 0) |
| 8 | `formwork_reuse` | 거푸집 전용 횟수 및 회수율 | 19 | 7 | **일치** (변동 0) |
| 9 | `rebar_complexity` | 철근 가공조립 복잡도 갈래 | 8 | 4 | **일치** (변동 0) |
| 10 | `timber_structure_class` | 목구조 종별 품셈 기준 | 6 | 4 | **일치** (변동 0) |
| 11 | `masonry_slope` | 돌쌓기 표준경사 (직고·성토/절토) | 20 | 4 | **일치** (변동 0) |
| 12 | `masonry_back_length` | 돌쌓기 뒷길이 기준 | 10 | 4 | **일치** (변동 0) |
| 13 | `stone_kind` | 석재 종류별 환산계수 | 75 | 5 | **일치** (변동 0) |
| 14 | `masonry_class` | 돌쌓기 구조물 형식별 종전값 | 9 | 5 | **일치** (변동 0) |
| 15 | `machine_productivity` | 불도저·로더·덤프 작업능력 제원 | 47 | 21 | **일치** (변동 0) |
| **합계** | **15개 기초값 전체** | | **8,372** | - | **100% 동일** |
#### B. 원천 데이터 파일 및 빌더 코드 무결성 검증
- 원천 JSON 데이터 파일 9종:
- `labor_const_2026-01-01.json`, `labor_mfg_2026-07-01.json`, `mach_base_2026.json`, `mat_price_public_2026-08-14.json`, `oil_2026-08-14.json`, `oil_regional_2026-09-09.json`, `rates_2026.json`, `coef_2026.json`, `pum_forest_2026.json`
- **`git diff ba593281 HEAD` 결과: 0바이트 (단 1줄의 수정도 없음)**
- 테이블 생성 빌더 코드:
- `Z01_MasterData_BasePrices_Machine.py`, `Z01_MasterData_BasePrices_Tables.py`
- **`git diff ba593281 HEAD` 결과: 0바이트 (단 1줄의 수정도 없음)**
- **결론**: 기초값 15종은 원본 데이터와 생성 로직이 완전히 동결 상태로 유지되었으며, **값이 한 칸이라도 달라진 것은 전혀 없음**.
---
### 2) 공종 축 (산림·건설) 재편 무결성 및 원문 대조
#### A. 산림 공종 축 (`work_item_forest`)
- **공종 수**: 총 477개 마디 (잎 360개, 묶는 부모 117개)
- **갈래 단위(`units`)**: 620개 (헛단위 7줄 제외 후 정규 갈래 수)
- **품셈표 부착**:
- 총 458개 표 중 부착 표 443개, orphan(고아표) 15개
- 고아표 15개는 부록 설계사례 예시표 7개(F0455·F0456·F0472~F0476)와 비공종 안내표 8개로 전수 규명됨.
#### B. 건설 공종 축 (`work_item_const`)
- **공종 수**: 총 1,367개 목차 마디 (표가 직접 붙은 공종 997개)
- **갈래 확장**: 111개 공종에서 갈래 407개 확장 $\rightarrow$ 총 1,293개 행으로 안정적 전개
- **품셈표 부착**: 2,192개 표 전수 누락 없이 제자리 부착 완료.
---
### 3) ⚠ 목차 오기 둘 정정 자리의 원문 대조 검증
품셈 고시 원문 앞부분의 목차(TOC)와 본문(Body) 간 번호가 불일치했던 2개 자리를 산림청 고시 제2025-82호 전문과 정밀 대조하였다.
```
[원문 목차의 오기]
12-17-2 철근, 펌프카 0-15m
12-17-2 무근진동기 제외 <-- 목차에 번호가 중복 기재됨!
12-24-1 뒷채움
12-24-1 지수판 설치 <-- 목차에 번호가 중복 기재됨!
[원문 본문 실사 대조]
L6503: ### 12-17-2. 철근콘크리트(펌프카 0-15m) --> F0363
L6515: ### 12-17-3. 무근콘크리트(진동기 제외) --> F0364 (본문 번호는 12-17-3!)
L6680: ### 12-24-1. 뒷채움 --> F0371
L6715: ### 12-27-1. 지수판 설치 --> F0375 (본문 번호는 12-27-1!)
```
- **검증 결과**:
1. **12-17-2 $\rightarrow$ 12-17-3 정정**:
- 원문 본문 L6515에 `12-17-3. 무근콘크리트(진동기 제외)`로 명확히 인쇄되어 있음. 목차의 `12-17-2`는 단순 오기임.
- 본문 번호로 바로잡음으로써, 뒤 공종이 앞 공종(F0363)을 덮어쓰고 F0364가 고아표(orphan)로 증발하던 버그가 완벽히 해소됨.
- `FW-00387`(12-17-2, F0363)과 `FW-00388`(12-17-3, F0364)로 독립 분리 성공.
2. **12-24-1 $\rightarrow$ 12-27-1 정정**:
- 원문 본문 L6715에 `12-27-1. 지수판 설치`로 명확히 인쇄되어 있음. 목차의 `12-24-1`은 명백한 인쇄 오기임.
- 본문 번호로 바로잡음으로써, `FW-00396`(12-24-1 뒷채움, F0371)과 `FW-00401`(12-27-1 지수판 설치, F0375)가 각자의 표를 온전히 보존함.
- **판정**: **원문 본문 번호가 100% 맞으며, 정정 조치는 완전 타당함**.
---
### 4) ⚠ 헛단위로 뺀 5줄의 비(非)공종 검증
공종 축에서 제외된 5개 줄(갈래)이 실제 공사비 견적에 들어가야 하는 공종이었는지를 원문 문맥으로 실사하였다.
#### 1. FP-13-03 (3줄) 검증
- **원문 위치**: 원문 제13장 돌쌓기 및 돌붙임 주석 문단
- **원문 텍스트**: `[주] '13-3. 기초다짐 및 뒤채움' 항을 적용한다.`
- **실사 분석**:
- 원문에서 `13-3`은 독자적인 인력·장비 품셈표를 갖는 시공 공종이 아니라, 다른 조항(13-4, 13-5)에서 설계 요령을 안내하는 **참조 인용 문장**임.
- 이전 파서가 주석 안의 `13-3. ... 항을 적용한다`라는 글자를 절 표제로 오인하여, 13-4-1의 메쌓기 표(F0405, F0406)와 13-5-2의 찰붙임 표(F0418)를 13-3에 잘못 결합시켰던 것임.
- 13-3을 헛단위로 제거함에 따라, F0405·F0406은 `13-4-1`(메쌓기)로, F0418은 `13-5-2`(찰붙임)로 **원래의 시공 공종에 완벽히 귀속**됨.
- **판정**: **공종이 아닌 인용문이 맞으며, 제거 조치는 완전 타당함**.
#### 2. FP-04-01 / FP-04-02 (부록 사례 표 7개, 2줄) 검증
- **원문 위치**: 산림품셈 고시 말미 "부록: 설계도서 작성요령 및 설계사례"
- **표 번호**: F0455, F0456, F0472, F0473, F0474, F0475, F0476
- **실사 분석**:
- 본 표들은 지자체 발주 시 설계서 작성을 돕기 위해 실어 둔 **견적서 작성 예시 샘플**임.
- 부록 사례 표의 번호가 본문 `4-1`(소나무재선충병 방제), `4-2`(솔잎혹파리 방제)와 우연히 겹쳐 본문 공종에 잘못 딸려 들어갔었음.
- 예시 견적표가 표준품셈 시공 단위로 들어가면 공종 트리가 왜곡되므로, 이를 떼어내어 `orphan_tables`로 분리함.
- **판정**: **시공 품셈 공종이 아닌 설계 참고사례가 맞으며, 제거 조치는 완전 타당함**.
---
### 5) 설계 단가 및 금액 영향 검산 (일위대가 전수 대조)
작업 전후 677개 단가산출 대상 공종의 계산 금액을 대조하였다.
1. **제외된 단가**: 헛단위였던 `B-FP-13-03` (3개) 정상 소멸.
2. **이상 단가 격리**: `B-FP-13-05-02`가 메붙임+찰붙임 품이 중복 합산되어 약 2배로 산출되던 기존 결함을 발견하여 `KnownGaps`에 "쓰면 안 됨"으로 격리(실제 설계 사용처 0).
3. **나머지 670여 개 정상 공종 단가**:
- **단 1원도 변경 없음 (전후 차액 0원, 완벽한 금액 불변 달성)**.
---
## 3. 최종 결론
> **"오늘 진행된 작업으로 변경된 공종 단가 및 기초값은 단 1원도 없으며, 원문의 인쇄 오기와 가짜 공종(인용문·부록 예시)만이 정확하게 교정되었습니다."**
1. **기초값 15종**: 원본 파일 9종과 빌더 코드 2종 모두 diff 0바이트로 8,372줄 전체가 **100% 동일하게 보존**되었습니다.
2. **목차 오기 둘**: 원문 본문 L6515(`12-17-3`) 및 L6715(`12-27-1`) 대조 결과 **원문 본문 번호가 정본임이 확인**되었으며, 증발했던 2개 표(F0364, F0375)가 제자리로 복구되었습니다.
3. **헛단위 5줄**: 주석 인용문(13-3)과 부록 설계사례(4-1, 4-2)를 공종으로 오독했던 파서 결함이 정상적으로 정제되었으며, 딸려 있던 표들도 메쌓기(13-4-1)와 찰붙임(13-5-2) 본체로 올바르게 재배치되었습니다.
4. **금액 무결성**: 헛단위 소멸 외에 실제 현장에서 쓰이는 공종 단가는 1원도 변동 없이 **"값은 그대로 두고 자리만 바로잡는다"는 약속이 완벽히 준수**되었습니다.
@@ -0,0 +1,51 @@
---
title: 품셈 실사 목차 (2026-09-17)
category: 05_원가정보
status: verified
last_updated: 2026-09-17
sources:
- resources/knowledge/technical_info/01_임도/05_원가정보/
---
# 품셈 실사 목차 (2026-09-17)
2026-09-17 산림품셈·건설품셈 및 연결고리 전수 실사에서 나온 분석 결과들을 한자리에서 찾아갈 수 있도록 정리한 **상호 참조 목차(Index) 문서**이다.
> ⚠ 본 문서는 이미 작성된 파일 내용을 다시 쓰지 않고, **어느 파일의 어느 위치에 있는지**만 가리킨다.
---
## 1. 금액에 닿는 발견 (원가 왜곡·누락 위험)
| 항목 | 가리키는 파일 및 위치 | 동반 JSON 데이터 | 가리키는 핵심 내용 |
|---|---|---|---|
| **reference 35 중 금액 직결 20** | [품셈_원문표_reference_실값_35개_목록.md](품셈_원문표_reference_실값_35개_목록.md)<br>• §1.1 종합 판정표<br>• §2. 35개 전수 목록 | `품셈_원문표_reference_실값_35개_목록.json` | 참고로 오분류되어 자원 축이 빠져 0원이 되던 35개 중 임도 핵심 공종 20개 (자재 9·소모품 5·노무 6) |
| **건설 42절 중 노무비 축소 위험** | [건설품셈_연결공종_reference_병_진단.md](건설품셈_연결공종_reference_병_진단.md)<br>• §1. 진단 총괄<br>• §2. 위험 5개 표 실측 | `건설품셈_연결공종_reference_병_진단.json` | 연결 42개 절 중 주석 내 '참고' 표기로 노무비·자재비가 0원/축소되는 5개 절 (지수판·줄눈·암발파·덤프·레미콘) |
| **산림 form 미판정 14** | [산림품셈_form_미판정_14개_원문대조_규명.md](산림품셈_form_미판정_14개_원문대조_규명.md)<br>• §1. 종합 요약표<br>• §2.A~D 세부 내역 | `산림품셈_form_미판정_14개_원문대조_규명.json` | 자동 판정이 보류되었던 산림 14개 표 전수 원문 대조 복원 (머리소실 9·혼합 3·공식 1·글값 1) |
| **밑수 못 읽은 155** | [산림품셈_결측밑수_155개_자리명세.md](산림품셈_결측밑수_155개_자리명세.md)<br>• §1. 실채움 vs 무차원<br>• §2. 소요량 79 + 생산성 11 | `산림품셈_결측밑수_155개_자리명세.json` | 결측 후보 256개 중 무차원 101개를 제외한 실질 결측 155개 (본문 위 48·표머리 107; 금액 직결 90개) |
---
## 2. 구조에서 드러난 것 (원문 왜곡·주의점)
| 항목 | 가리키는 파일 및 위치 | 가리키는 핵심 내용 |
|---|---|---|
| **목차 오기 둘** | [현재_프로그램_미판정_목록.md](현재_프로그램_미판정_목록.md) §3.1<br>• 커밋 `1de5c8ab` 기록 | 12-17-2(무근진동기 제외) $\rightarrow$ 본문 **12-17-3**, 12-24-1(지수판) $\rightarrow$ 본문 **12-27-1** 정정 및 고아표(orphan) 4줄 제자리 복원 |
| **표면마무리 100배** | [현재_프로그램_미판정_목록.md](현재_프로그램_미판정_목록.md) §2.㉰<br>[건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md) §3.2 | 산림 12-2(`0.34인/㎡`) vs 건설 공통 6-1-3(`0.34인/100㎡`) 단위 100배 불일치 $\rightarrow$ 자동 연결 확정 차단 |
| **뿌리제거 4.7배** | [현재_프로그램_미판정_목록.md](현재_프로그램_미판정_목록.md) §2.㉰ | 산림 9-21(본당) vs 건설 공통 3-9-2(1,000㎡당) 작업방식 차이 $\rightarrow$ 건설값 치환 시 4.7배 왜곡 위험, 산림 정본 유지 |
| **부문마다 장 번호 1부터** | [건설품셈_활용.md](../04_수량분석정보/건설품셈_활용.md) §3.6<br>[건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md) §3.3 | 건설 5개 부문(공통·토목·건축·기계·유지관리)마다 장 번호가 1부터 리셋 $\rightarrow$ 부문 접두어(`C_COM`, `C_CIV` 등) 필수 |
| **총칙 범위** | [건설품셈_활용.md](../04_수량분석정보/건설품셈_활용.md) §3.6<br>• `axis_policy.json` | 산림 1·2장(총칙/손료), 건설 공통 1장(37줄 46표, 순수총칙), 공통 8장(351표, 기계엔진), 유지관리 1장(40표, 실공종) 범위 |
---
## 3. 다음 판 지도 (스키마·파서 엔진 아키텍처)
| 항목 | 가리키는 파일 및 위치 | 동반 JSON 데이터 | 가리키는 핵심 내용 |
|---|---|---|---|
| **표 6유형 (산림)** | [산림품셈_표모양_6대유형_분류.md](산림품셈_표모양_6대유형_분류.md)<br>• §1. 6대 유형 총괄<br>• §2. 22개 복합표 | `산림품셈_표모양_6대유형_분류.json` | 산림 requirement 279개 표 6대 모양 분류 (세로단일 93·세로혼합 133·가로직종 20·가로매트릭스 7·병렬 4·복합 22) |
| **표 6유형 (건설 연결)** | [연결고리_건설공종_6유형_분류.md](연결고리_건설공종_6유형_분류.md)<br>• §1. 3대 기능군<br>• §2. 작업조 구조 | `연결고리_건설공종_6유형_분류.json` | 연결 확정 건설 공종 22개 절 6대 유형 분류 및 작업조 $\div$ 일당시공량 파싱 규칙 |
| **밑수 꼴 (건설 연결)** | [연결고리_건설공종_밑수꼴_분석.md](연결고리_건설공종_밑수꼴_분석.md)<br>• §1. 42개 절 밑수 꼴<br>• §2. 파서 탐색 규칙 | `연결고리_건설공종_밑수꼴_분석.json` | 소요량 22개 절 중 본문 윗줄 19개(86.4%) 집중, 표머리 2개, 소제목 1개 및 무차원 20개 |
| **밑수 꼴 (건설 전체)** | [건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md)<br>• §2. 밑수 꼴 통계 | - | 건설 2,192개 표 중 본문 윗줄 괄호 1,034개(47.2%), 표머리 446개(20.3%), 무차원 711개(32.4%) |
| **성격 집계 (산림 vs 건설)** | [건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md)<br>• §1. 성격 분류 대조표 | - | 산림 458개(req 279·coeff 47·ref 99·prod 33) vs 건설 2,192개(req 1,206·coeff 497·ref 437·prod 52) 전수 집계 |
| **미명시 7건 매핑** | [산림_건설_미명시7건_대응매핑.md](산림_건설_미명시7건_대응매핑.md)<br>• §1. 7행 대응표 | `산림_건설_미명시7건_대응매핑.json` | 건설품셈 준용 지시 7건 중 확정 6건(철근·거푸집·비탈보호 등) 및 규격 미수록 1건(1톤 방제차량) |
| **종합 총괄 보고서** | [품셈_원문_전수실사_및_원가위험_종합총괄.md](품셈_원문_전수실사_및_원가위험_종합총괄.md) | `품셈_원문_전수실사_및_원가위험_종합총괄.json` | 위 1·2·3부 분석 결과를 총괄 집약한 종합 감사 보고서 본문 |
@@ -0,0 +1,162 @@
{
"dataset_id": "pumsem_master_audit_synthesis_2026",
"title": "품셈 원문 전수실사 및 원가위험 종합총괄 데이터셋",
"generated_at": "2026-09-17T18:57:45+09:00",
"summary": {
"forest_total_tables": 458,
"const_total_tables": 2192,
"linked_cw_sections": 42,
"linked_total_links": 64
},
"part1_cost_impact_findings": {
"forest_reference_hazardous_values": {
"total_reference_tables": 99,
"actual_values_count": 35,
"direct_money_impact_count": 20,
"decision_only_count": 0,
"non_forest_road_count": 15,
"detail_doc": "품셈_원문표_reference_실값_35개_목록.md"
},
"const_linked_hazardous_sections": {
"total_linked_sections": 42,
"hazardous_sections_count": 5,
"clean_sections_count": 37,
"hazard_items": [
{
"section": "공통 6-3-9",
"name": "지수판 설치",
"risk": "자재비 0원 누락",
"missing": "PVC 지수판 1.04m, 용접봉 0.042kg, 철선 0.21kg"
},
{
"section": "토목 1-6-6",
"name": "포장줄눈 절단",
"risk": "소모품비 0원 누락",
"missing": "다이아몬드 휠 날 감모율 손료"
},
{
"section": "공통 3-3-6",
"name": "대규모 암발파",
"risk": "화약류 자재비 0원 누락",
"missing": "에멀젼폭약 0.25~0.35kg/㎥, 비전기뇌관 0.4~0.6개/㎥"
},
{
"section": "공통 1-2-7 7호",
"name": "화물차 적재량",
"risk": "덤프 운반비 0원 (계산 불가)",
"missing": "토사 9.4㎥, 깬돌 7.5㎥ 등 중량-체적 환산표"
},
{
"section": "공통 6-1-1",
"name": "레디믹스콘크리트 타설",
"risk": "노무비 축소",
"missing": "슈트타설 인력 0.05인 가산 및 소운반 10~20% 할증"
}
],
"detail_doc": "건설품셈_연결공종_reference_병_진단.md"
},
"forest_undetermined_tables": {
"total_undetermined": 14,
"resolved_count": 14,
"categories": {
"header_missing": 9,
"mixed_matrix": 3,
"formula_spec": 1,
"text_value": 1
},
"detail_doc": "산림품셈_form_미판정_14개_원문대조_규명.md"
},
"forest_missing_basis": {
"total_missing_candidates": 256,
"dimensionless_count": 101,
"recoverable_basis_count": 155,
"direct_money_impact_count": 90,
"locations": {
"text_above_table": 48,
"table_header": 107
},
"detail_doc": "산림품셈_결측밑수_155개_자리명세.md"
}
},
"part2_structural_risks": {
"toc_corrections": [
{
"wrong_toc": "12-17-2 무근진동기 제외",
"real_section": "12-17-3",
"tables_affected": ["F0363", "F0364"]
},
{
"wrong_toc": "12-24-1 지수판 설치",
"real_section": "12-27-1",
"tables_affected": ["F0371", "F0375"]
}
],
"surface_finish_scale_hazard": {
"forest": "12-2 표면마무리 (0.34인 / ㎡당)",
"const": "공통 6-1-3 표면마무리 (0.34인 / 100㎡당)",
"scale_difference": 100,
"status": "연결 확정 차단 (100배 오산 방지)"
},
"root_removal_distortion": {
"forest": "9-21 벌근 (0.80~1.22 hr / 본당)",
"const": "공통 3-9-2 뿌리뽑기 (3.76 hr / 1,000㎡당)",
"distortion_ratio": 4.7,
"status": "산림품셈 고유품 정본 유지"
},
"const_chapter_reset": {
"divisions_count": 5,
"divisions": ["공통", "토목", "건축", "기계설비", "유지관리"],
"rule": "부문 접두어(C_COM, C_CIV, C_ARC, C_MEC, C_MNT) 필수"
},
"general_provisions_scope": {
"forest": "1장(적용기준) + 2장(재료/손료)",
"const_common_ch1": "1장 적용기준 37줄·46표 (순수 총칙)",
"const_common_ch8": "8장 건설기계 351표 (계산엔진 결합)",
"const_maintenance_ch1": "유지관리 1장 40표 (실공종)"
}
},
"part3_implementation_map": {
"table_forms_distribution": {
"1_vertical_standard": 93,
"2_vertical_mixed": 133,
"3_horizontal_crafts": 20,
"4_horizontal_matrix": 7,
"5_side_by_side": 4,
"6_compound_irregular": 22
},
"basis_pattern_distribution": {
"forest": {
"text_above": 48,
"header": 107,
"dimensionless": 101,
"note_or_missing": 202
},
"const": {
"text_above": 1034,
"header": 446,
"dimensionless": 711,
"note_or_missing": 1
}
},
"pum_form_counts": {
"forest": {
"requirement": 279,
"coefficient": 47,
"reference": 99,
"productivity": 33,
"undetermined": 0
},
"const": {
"requirement": 1206,
"coefficient": 497,
"reference": 437,
"productivity": 52,
"undetermined": 881
}
},
"unspecified_7_items_resolution": {
"confirmed_mapped": 6,
"specification_missing": 1
}
}
}
@@ -0,0 +1,190 @@
---
title: 품셈 원문 전수실사 및 원가위험 종합총괄 보고서
category: 05_원가정보
status: verified
last_updated: 2026-09-17
sources:
- resources/data_work_item_master/work_item_master_2026-01-01.json
- resources/data_work_item_master/const_work_item_master_2026-01-01.json
- resources/data_work_item_link/work_item_link_2026-01-01.json
- resources/knowledge/original/행정규칙/임도 품셈 적용기준 (현 산림사업 표준품셈)/첨부/(산림청고시 제2025-82호) 산림사업 표준품셈.md
- resources/knowledge/original/원가계산/건설공사_표준품셈/2026년_건설공사_표준품셈.md
- resources/knowledge/technical_info/01_임도/05_원가정보/품셈_원문표_reference_실값_35개_목록.md
- resources/knowledge/technical_info/01_임도/05_원가정보/건설품셈_연결공종_reference_병_진단.md
- resources/knowledge/technical_info/01_임도/05_원가정보/산림품셈_form_미판정_14개_원문대조_규명.md
- resources/knowledge/technical_info/01_임도/05_원가정보/산림품셈_결측밑수_155개_자리명세.md
- resources/knowledge/technical_info/01_임도/05_원가정보/산림품셈_표모양_6대유형_분류.md
- resources/knowledge/technical_info/01_임도/05_원가정보/연결고리_건설공종_6유형_분류.md
- resources/knowledge/technical_info/01_임도/05_원가정보/연결고리_건설공종_밑수꼴_분석.md
- resources/knowledge/technical_info/01_임도/05_원가정보/건설품셈_원문표_성격_및_밑수_분석.md
- resources/knowledge/technical_info/01_임도/05_원가정보/산림_건설_미명시7건_대응매핑.md
- resources/knowledge/technical_info/01_임도/05_원가정보/현재_프로그램_미판정_목록.md
- resources/knowledge/technical_info/01_임도/04_수량분석정보/건설품셈_활용.md
---
# 품셈 원문 전수실사 및 원가위험 종합총괄 보고서
2026년 9월 17일 산림품셈(458개 표)과 건설품셈(2,192개 표), 그리고 산림↔건설 연결고리(64개 링크, 고유 건설 42개 절)를 대상으로 진행된 **원문 대조 전수 실사 및 감사 결과를 한 벌로 집대성한 종합 총괄 장부**이다.
각 세부 주제별 실사 보고서들이 상호 링크로 연결되어 있어, 본 문서를 관문(Hub)으로 삼아 모든 실사 근거와 파싱 규칙을 추적할 수 있다.
---
## 1. 금액에 닿는 핵심 발견 (원가 왜곡·누락 위험)
파서의 오분류나 밑수 결측으로 인해 **실제 설계 예산에서 금액이 0원으로 누락되거나 축소·왜곡되는 4대 위험 구역**을 전수 특정하였다.
```mermaid
flowchart TD
subgraph "금액 직결 4대 위험 구역"
A["산림 reference 99개 중<br><b>실값 35개 (금액직결 20개)</b><br>자원축 건너뛰어 0원 누락"]
B["건설 연결 42개 절 중<br><b>5개 절 위험 (노무·자재비 누락)</b><br>주석 내 참고 표기 병"]
C["산림 form 미판정 14개<br><b>전부 금액 직결 대상</b><br>머리소실9·혼합3·공식1·글값1"]
D["산림 결측 밑수 155개<br><b>금액 직결 90개</b><br>소요량 79 + 생산성 11"]
end
A --> E["Aislo 원가 계산 엔진<br>무결성 보장 및 파서 교정"]
B --> E
C --> E
D --> E
```
### 1) 산림 reference 99개 중 실은 값 35개 (금액 직결 20개)
- **상세 보고서**: [품셈_원문표_reference_실값_35개_목록.md](품셈_원문표_reference_실값_35개_목록.md) (`.json`)
- **위험 본질**: 파서가 테이블 레벨에서 `reference`(참고)로 오분류하여 자원 축 생성 대상에서 제외시킴으로써, 내역서 일위대가에서 **자재대·경비·노무비가 0원으로 빠지는 치명적 결함**.
- **3대 갈래 분류**:
1. **㉮ 금액에 바로 닿음 (임도 핵심 공종, 20개)**:
- 자재비 직결 9개: 유로폼 자재량(F0393), 찰쌓기 콘크리트(F0410), 비탈덮기 거적(F0146) 등
- 기계·소모품비 직결 5개: 삭도운반 동력(F0288), 임내차 연료(F0201), 기계톱 오일(F0175) 등
- 노무비·비율단가 직결 6개: 떼붙임 인부(F0135), 목재상하차(F0197), 기계경비 인건비비율(F0039) 등
2. **㉯ 판정·구분용 (값이나 금액 무관, 0개)**: 해당 없음.
3. **㉰ 임도 외 산림사업에 붙음 (15개)**: 벌채 목탄·신재(F0188), 방제 약제량(F0107~F0110), 묘목굴취 소요품(F0081) 등.
### 2) 건설 연결 42개 절 중 "노무비·자재비 축소 및 0원 위험" 5개 절
- **상세 보고서**: [건설품셈_연결공종_reference_병_진단.md](건설품셈_연결공종_reference_병_진단.md) (`.json`)
- **위험 본질**: 연결고리 확정 건설 공종 42개 절 중 **37개 절은 정상**이나, **5개 절에서 산림과 동일한 "주석 잠입 자재량 누락 병"이 발견**됨. 본체 표에는 노무비만 적고, 주석 `[주]`에 "참고하여 적용한다"며 자재량·손료·가산품을 분리해 두어 파서가 건너뜀.
- **5대 위험 표 명세**:
1. **공통 6-3-9 지수판**: PVC지수판 1.04m, 용접봉 0.042kg, 철선 0.21kg 누락 $\rightarrow$ **자재비 0원 위험**
2. **토목 1-6-6 포장줄눈절단**: 다이아몬드 휠 날 마모 감모율 손료 누락 $\rightarrow$ **소모품비 0원 위험**
3. **공통 3-3-6 대규모 암발파**: 에멀젼폭약(0.25~0.35kg/㎥), 뇌관 소요량 누락 $\rightarrow$ **화약대 0원 위험**
4. **공통 1-2-7 7호 화물차 적재량**: 토사(9.4㎥), 깬돌(7.5㎥) 덤프 환산표 누락 $\rightarrow$ **덤프 운반비 계산 불가(0원)**
5. **공통 6-1-1 레디믹스콘크리트**: 인력 슈트타설(0.05인 가산) 및 산악 소운반(10~20% 할증) 누락 $\rightarrow$ **노무비 축소 위험**
### 3) 산림 form 미판정 14개 표 전수 규명 (전부 금액 대상)
- **상세 보고서**: [산림품셈_form_미판정_14개_원문대조_규명.md](산림품셈_form_미판정_14개_원문대조_규명.md) (`.json`)
- **진단 결과**: 토목·임도 시공량 및 자원량에 직결되나 표 모양 신호 혼선으로 보류되었던 14개 표를 원문 대조로 완전 규명함.
- **머리 소실 9개**: 막갈이(F0140)·흙부수기(F0141)·돌자갈치우기(F0142)·VR관(F0346) 등 2단 헤더 복원, 드론운반(F0322)·인력운반(F0323) 1행 가로 룩업 테이블 복원, 한중시후카(F0333) 복합축 복원, 브레이커계수(F0248) coefficient 승격.
- **혼합 행렬 3개**: 천연림수확(F0169, L3369에서 인공림과 분기), 10종자재운반(F0304, 자재 10종×거리 10구간 피벗 정규화), 펌프카타설(F0356, 슬럼프×콘크리트 기준시공량 연동).
- **공식 1개 (F0257)**: 콘크리트 줄눈 물운반 일일량 산정식($N, Q$)과 5개 고정 변수 대입식 규명.
- **글값 1개 (F0349)**: 파형강관 관부설 비고란의 `별산`($\rightarrow$ 자재대 별도계상 플래그), `필요시적용`($\rightarrow$ 6m당 1EA 조건부 가산 플래그) 보존 처리 규칙 확정.
### 4) 산림 결측 밑수 155개 자리 명세 (금액 직결 90개)
- **상세 보고서**: [산림품셈_결측밑수_155개_자리명세.md](산림품셈_결측밑수_155개_자리명세.md) (`.json`)
- **규명 결과**: 1차 결측 후보 256개 표 중 무차원 계수·서식 101개를 제외한 실질 결측 155개의 원문 위치를 전수 특정함.
- **본문 윗줄 괄호 명시**: 48개 표 (`(100㎡당)`, `(km당)`, `(1공당)` 등 단독 행)
- **표머리 헤더 내부 명시**: 107개 표 (`단위: m`, `수량(인/100m)` 등)
- **금액 직결 우선순위**: 155개 중 **소요량(`requirement`) 79개 + 생산성(`productivity`) 11개 = 90개 표**가 직접 곱셈 밑수이므로 파서 우선 수거 대상임.
---
## 2. 구조 및 스키마 실사에서 드러난 위험·왜곡 주의점
원문 목차와 단위 체계 실사에서 확인된 5대 구조적 불일치 및 왜곡 요인이다.
### 1) 목차 오기 둘 (원문 목차와 본문 절 번호 불일치)
- **근거**: 커밋 `1de5c8ab` (`fix(b08): 공종 축 목차 오기 둘을 본문 절 번호로`)
- **오기 내역 및 정정**:
1. 목차 `12-17-2. 무근진동기 제외` $\rightarrow$ 본문 실제 절 번호는 **`12-17-3`**
2. 목차 `12-24-1. 지수판 설치` $\rightarrow$ 본문 실제 절 번호는 **`12-27-1`**
- **영향 및 조치**: 목차 번호만으로 파싱할 경우 원문 표(F0363, F0364, F0371, F0375)가 엉뚱한 부모에 붙어 orphan(고아표)이 발생하므로, 목차가 아닌 **본문 절 제목과 원문 줄(line)을 정본으로 삼아 트리를 조립**함 (`orphan 17개 $\rightarrow$ 15개`로 축소).
### 2) 표면마무리 100배 차이 (단위 스케일 불일치)
- **근거**: [건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md), [현재_프로그램_미판정_목록.md](현재_프로그램_미판정_목록.md) §2
- **비교**:
- **산림품셈 12-2**: 미장공 `0.34인 / ㎡당`
- **건설품셈 공통 6-1-3**: 미장공 `0.34인 / 100㎡당`
- **치명적 위험**: 숫자 수치(`0.34`)는 완전히 동일하지만 **밑수 단위가 100배 차이**남. 이름과 수치만 보고 산림과 건설을 자동 매핑할 경우 **노무비가 100배 과다 또는 과소 계상**되는 대형 사고가 발생함 $\rightarrow$ **확정 차단(연결 금지)** 유지.
### 3) 뿌리제거 4.7배 왜곡 (작업 방식 및 단위 차이)
- **근거**: [현재_프로그램_미판정_목록.md](현재_프로그램_미판정_목록.md) §2
- **비교**:
- **산림품셈 9-21 (벌근)**: 인력/기계 소밀도별 `0.80 / 1.01 / 1.22 hr / 본당`
- **건설품셈 공통 3-9-2 (뿌리뽑기)**: 굴착기(0.7㎥)+그래플 `3.76 hr / 1,000㎡당`
- **위험**: 산림의 본당 작업과 건설의 면적당(1,000㎡) 작업은 산림 현장의 수목 밀도 차이로 인해 직접 치환 시 **최소 4.7배 이상의 단가 왜곡**이 발생함 $\rightarrow$ 산림품셈 고유 품을 정본으로 확정.
### 4) 부문마다 장 번호 1부터 리셋 (코드 충돌 방지)
- **근거**: [건설품셈_활용.md](../04_수량분석정보/건설품셈_활용.md) §3.6, [건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md) §3
- **구조**: 산림품셈은 단일 14개 장(`FP-01` ~ `FP-14`)이나, 건설품셈은 **5개 부문(공통·토목·건축·기계·유지관리)마다 제1장부터 장 번호가 다시 시작**함.
- 예: `1-1-1` 절이 공통(적용기준), 토목(포장공사), 건축(적용범위)에 각각 독립 존재함.
- **파서 규칙**: 건설 공종 및 표 ID 생성 시 반드시 **부문 접두어(`C_COM`, `C_CIV`, `C_ARC`, `C_MEC`, `C_MNT`)**를 부여하여 코드 충돌을 방지함.
### 5) 총칙 범위와 공종 경계 (엔진 분리 원칙)
- **근거**: `axis_policy.json`, [건설품셈_활용.md](../04_수량분석정보/건설품셈_활용.md) §3.6
- **영역별 정의**:
- **산림 총칙**: 제1장(적용기준) + 제2장(소요재료 및 기계손료). 공종 목록에선 감추더라도 단위·할증·연료·손료계수는 원가 엔진이 읽어야 하므로 보존.
- **건설 공통 제1장**: 37줄·46표 전체가 순수 규정(총칙).
- **건설 공통 제8장 (351개 표)**: 건설기계 경비 표로, 시공능력 $Q$ 공식 및 기계손료 계수가 결합되어 있어 별도의 기계 계산 엔진 파이프라인으로 분리.
- **건설 유지관리 제1장 (40개 표)**: '공통'이라는 이름이 붙어 있으나 실무상 수목관리·시설물유지 공종 표이므로 이름만 보고 총칙으로 배제하지 않음.
---
## 3. 다음 판 구현 지도 (스키마·파서 엔진 아키텍처)
다음 개발 단계에서 파서 엔진이 표준품셈 전체 표를 자동 해석할 수 있도록 정리한 기술 지도이다.
### 1) 산림 requirement 279개 표의 6대 표 모양 분류
- **상세 보고서**: [산림품셈_표모양_6대유형_분류.md](산림품셈_표모양_6대유형_분류.md) (`.json`)
- **분류 통계**:
| 유형 | 명칭 | 표 수 | 비율 | 파싱 전략 및 특징 |
|---|---|---:|---:|---|
| **1형** | **세로 단일자원형** | 93개 | 33.3% | 단일 자원(보통인부 등)에 조건이 행으로 전개 $\rightarrow$ 단일 룩업 |
| **2형** | **세로 자원혼합형 (작업조형)** | 133개 | 47.7% | 직종·장비·자재가 세로로 나열 $\rightarrow$ **1형+2형 합산 226개(81%)로 전체의 주류** |
| **3형** | **가로 직종 열 전개형** | 20개 | 7.2% | 직종명이 열 헤더로 가로 전개 $\rightarrow$ 피벗 필요 |
| **4형** | **가로 조건 매트릭스형** | 7개 | 2.5% | 2축 조건 매트릭스(거리×토질 등) $\rightarrow$ 2차원 배열 매핑 |
| **5형** | **좌우 2단 병렬형** | 4개 | 1.4% | 좌우 두 표가 지면 절약형으로 병렬 결합 $\rightarrow$ 좌우 분할 파싱 |
| **6형** | **⚠ 모양이 섞인 복합 표** | 22개 | 7.9% | 다단 헤더, 조건 축 혼합 등 **가장 깨지기 쉬운 고위험군 (전용 스키마 필요)** |
### 2) 밑수 꼴 4대 패턴 통계 및 파서 규칙
- **상세 보고서**: [연결고리_건설공종_밑수꼴_분석.md](연결고리_건설공종_밑수꼴_분석.md), [건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md)
- **비교 분석**:
| 밑수 꼴 | 산림품셈 (458표) | 건설품셈 (2,192표) | 파서 수거 전략 |
|---|---:|---:|---|
| **본문 윗줄 괄호** | 48개 (10.5%) | **1,034개 (47.2%)** | 표 직전 행(`source_line - 1`)에서 `(단위: ...당)` 정규식 탐색 (건설 70% 적중) |
| **표머리 헤더 내부** | 107개 (23.4%) | **446개 (20.3%)** | 헤더 셀 내부 텍스트 `단위:`, `인/...` 정규식 탐색 |
| **무차원 / 서식** | 101개 (22.1%) | **711개 (32.4%)** | 기계손료율·할증률 등 곱셈 밑수가 없는 정상 표 (`basis = dimensionless`) |
| **주석([주]) 기재 / 결측** | 202개 (44.0%) | 1개 (0.0%) | 산림은 주석 기재 빈발, 건설은 본문 윗줄 집중 |
### 3) 산림 vs 건설 원문 표 성격(`pum_form`) 전수 집계 대조표
| 성격 (`pum_form`) | 산림품셈 (458개) | 건설품셈 (2,192개) | 스키마 취급 규칙 |
|---|---:|---:|---|
| **소요량 (`requirement`)** | 279개 (60.9%) | 1,206개 (55.0%) | 일위대가 직접 노무·자재·기계 투입량 |
| **계수·손료 (`coefficient`)** | 47개 (10.3%) | 497개 (22.7%) | 기계손료율, 할증률, 시공능력 $Q$ 계수 |
| **참고·규정 (`reference`)** | 99개 (21.6%) | 437개 (19.9%) | 일반 적용기준, 서식, 규정 안내 (단, 실값 35개 제외) |
| **시공능력 (`productivity`)** | 33개 (7.2%) | 52개 (2.4%) | 기계 및 인력 시공능력 산정 공식 |
| **미판정 (`undetermined`)** | 14개 $\rightarrow$ **0개 (완전 규명)** | 881개 (임도 대상 0개) | 산림 14개 전수 해소 완료 |
### 4) 산림-건설 미명시 7건 대응 규명
- **상세 보고서**: [산림_건설_미명시7건_대응매핑.md](산림_건설_미명시7건_대응매핑.md) (`.json`)
- **결과**: 산림 원문에서 절 번호 없이 "건설품셈에 따른다"고 한 7건 중 **확정 6건** 매핑(철근 현장가공, 거푸집 조립, 비탈면 보호 등) 및 **1건 미수록(1톤 방제차량 손료 규격 부재)** 규명 완료.
---
## 4. 상호 참조 링크 색인표 (관련 파일 11종 연결 지도)
본 종합 총괄 보고서와 연동되는 기술정보DB 세부 문서 및 원본 JSON 파일 색인표이다.
| 번호 | 문서 파일명 | JSON 데이터 파일명 | 주요 핵심 내용 |
|:---:|---|---|---|
| **1** | [품셈_원문표_reference_실값_35개_목록.md](품셈_원문표_reference_실값_35개_목록.md) | `품셈_원문표_reference_실값_35개_목록.json` | 산림 reference 99개 중 실값 35개(금액 직결 20개) 전수 명세 |
| **2** | [건설품셈_연결공종_reference_병_진단.md](건설품셈_연결공종_reference_병_진단.md) | `건설품셈_연결공종_reference_병_진단.json` | 연결 42개 절 중 5개 위험 절(지수판·줄눈·암발파·덤프·레미콘) 규명 |
| **3** | [산림품셈_form_미판정_14개_원문대조_규명.md](산림품셈_form_미판정_14개_원문대조_규명.md) | `산림품셈_form_미판정_14개_원문대조_규명.json` | 미판정 14개 표(머리소실9·혼합3·공식1·글값1) 원문 헤더 및 복원 규칙 |
| **4** | [산림품셈_결측밑수_155개_자리명세.md](산림품셈_결측밑수_155개_자리명세.md) | `산림품셈_결측밑수_155개_자리명세.json` | 결측 155개 표(본문위48·표머리107, 금액직결 90개) 자리 및 규칙 |
| **5** | [산림품셈_표모양_6대유형_분류.md](산림품셈_표모양_6대유형_분류.md) | `산림품셈_표모양_6대유형_분류.json` | 산림 requirement 279개 표 6대 모양 분류 및 복합 22개 표 명세 |
| **6** | [연결고리_건설공종_6유형_분류.md](연결고리_건설공종_6유형_분류.md) | `연결고리_건설공종_6유형_분류.json` | 연결 확정 건설 공종 22개 절 6대 유형 및 작업조/일당시공량 규칙 |
| **7** | [연결고리_건설공종_밑수꼴_분석.md](연결고리_건설공종_밑수꼴_분석.md) | `연결고리_건설공종_밑수꼴_분석.json` | 연결 확정 건설 공종 42개 절 밑수 꼴(윗줄 19개·86.4%) 실사 |
| **8** | [건설품셈_원문표_성격_및_밑수_분석.md](건설품셈_원문표_성격_및_밑수_분석.md) | - | 건설 원문 2,192개 표 전수 실사 및 산림 대비 5대 구조 차이점 |
| **9** | [산림_건설_미명시7건_대응매핑.md](산림_건설_미명시7건_대응매핑.md) | `산림_건설_미명시7건_대응매핑.json` | 미명시 7건 실측 매핑 (확정 6건, 규격 미수록 1건 정밀 사유) |
| **10** | [현재_프로그램_미판정_목록.md](현재_프로그램_미판정_목록.md) | - | 프로그램 차원의 연결고리·공종축·표판독 미판정 감사 총괄 |
| **11** | [건설품셈_활용.md](../04_수량분석정보/건설품셈_활용.md) | - | 산림 대비 건설품셈 보완 역할 및 5부문 45장 연계 총람 |
@@ -0,0 +1,159 @@
# 품셈 원문 MD ↔ 마스터 데이터 대조 정밀 검증보고서
## 1. 개요 및 감사 목적
- **감사 대상**: 산림사업 표준품셈 원문 마크다운(`(산림청고시 제2025-82호) 산림사업 표준품셈.md`, 총 9,167행)과 시스템 마스터 데이터(`work_item_master_2026-01-01.json`, `pum_forest_2026.json`, `coef_2026.json` 등 기초값 15종) 전수 대조.
- **감사 사슬**: PDF 원문 $\rightarrow$ 원문 MD (코덱스 담당) $\rightarrow$ **[원문 MD ↔ 마스터 데이터 대조 (본 일감)]**.
- **원칙**:
- 원문 MD를 Ground Truth(정본 기준)로 간주하고 마스터 데이터를 대조함.
- 마스터 데이터나 소스코드를 임의 수정하지 않고, 불일치 명세와 원인을 정밀 기록·보고함 (수정은 개발 담당 창 몫).
- B08/B09 계산 로직이 아닌, 순수 원천 데이터(테이블, 셀, 밑수, 주석, 갈래)의 일치 여부를 검증함.
---
## 2. 감사 총괄 요약표
| 검증 항목 | 점검 대상 | 일치/정상 | 불일치/결측 | 주요 영향 및 평가 |
| :--- | :--- | :---: | :---: | :--- |
| **① 표·절·갈래 누락** | 전체 476개 표 및 14개 장 | 453개 | **23개** (누락 1, 고아 22) | F0001(경과조치 1개 누락), F0455~F0476(부록 설계예시 22개 orphan) |
| **② 값이 다른 칸** | 476개 표 전체 셀 수치 | **100% 일치** | **0건** | 표 내부의 모든 셀 숫자·글자는 raw 단위에서 100% 일치 |
| **③ 밑수·단위 왜곡·결측** | 표 윗줄·표머리 밑수 규격 | 416개 | **60건** (결측 50, 왜곡 10) | 1.0 km ↔ 인/ha 왜곡, 100본 누락, 50개 표 밑수 null로 단가산출 불가 |
| **④ [주] 계수·조건 누락** | 표 아래 단가 직결 주석 | 467개 | **9건** (핵심 주석 누락) | 덤프환산, 발파가산(20%), 고철공제, 유로폼 감속(9%), 손료(3%) 누락 |
| **⑤ reference 오분류 (갈래)** | 단가 계산 대상 표 성격 | 449개 | **27건** (핵심공종 오분류) | 거푸집·PVC·채움재·고임돌·콘크리트 등 실값 표가 reference로 빠짐 |
---
## 3. 5대 항목별 상세 감사 결과
### 항목 ① md에 있는데 마스터에 없는 것 (표·절·갈래 누락)
- **원문 MD 테이블 총수**: 476개 (`F0001` ~ `F0476`)
- **마스터 공종 축 연결 (`work_items[].tables`)**: **453개 표**
- **마스터 고아 테이블 (`orphan_tables`)**: **22개 표** (`F0455` ~ `F0476`)
- **원인 분석**: 원문 MD Line 8031~9106에 위치한 "부록: 설계서 작성 예시" 표들임 (풀베기 예시, 덩굴제거 예시, 어린나무가꾸기 예시, 기계화작업 예시, 재선충병 방제 예시). 공종 축 본문(제1장~14장)의 산출 공종이 아니므로 `orphan_tables`로 분리된 상태는 데이터 구조상 정상적인 처리임.
- **마스터 완전 누락 테이블**: **1개 표** (`F0001`)
- **원인 분석**: 원문 MD Line 31의 고시 본칙 `제2조(적용에 관한 경과조치)` 부칙 표로, 공사 공종이 아닌 행정 규칙 경과조치 표이므로 공종 축 마스터에서 정상 제외됨.
- **절(Section) 매핑**: 제1장부터 제14장까지의 본문 절은 100% 공종 마디(477개 `work_items`)로 구조화되어 누락된 절은 없음.
---
### 항목 ② 값이 다른 칸 (옮겨지며 달라진 숫자)
- **표 내부 셀(Raw Cells) 전수 대조 결과**: **불일치 0건 (100% 일치)**
- 원문 MD의 476개 표 내 모든 행·열 셀 값과 `pum_forest_2026.json``rows` 데이터는 소수점 및 공백 정규화 시 100% 일치함을 확인.
- **기초값 15종 대조 결과**:
- **토량환산계수 L, C (`F0004` vs `coef_2026.json`)**:
- 경암(1.70~2.00 / 1.30~1.50), 보통암(1.55~1.70 / 1.20~1.40), 보통토사(1.20 / 0.90) 등 원문의 17개 토질별 min, max 및 대표값이 `coef_2026.json``coef_soil_L`, `coef_soil_C`에 100% 정확하게 일치 반영됨.
- **자재할증률 (`F0008`~`F0013` vs `coef_2026.json`)**:
- 원목(정치식 10%, 기타 5%), 각재(5%), 판재(10%), 붉은벽돌(3%), 합판(3~10%) 등 원문 수치와 100% 일치.
- **노임할증률 (`F0015`~`F0041` vs `coef_2026.json`)**:
- 26개 할증 기준(작업시기, 경사도, 이동거리, 작업시간 제한 등)의 퍼센트 수치 일치 확인.
---
### 항목 ③ 밑수·단위 왜곡 및 결측 (MD vs 마스터)
총 **60개 표**에서 밑수·단위 왜곡 또는 결측이 발견됨. 특히 단위가 엉뚱한 차원(면적 $\leftrightarrow$ 거리)으로 들어가거나 밑수가 null로 비어 있어 단가 산출이 원천 차단되는 심각한 오류가 존재함.
#### 1. 치명적 단위 왜곡 사례 (금액 왜곡 직결)
| 표 번호 | 원문 MD 절 및 공종 | 원문 MD 밑수·단위 | 마스터 저장 단위 | 왜곡 내용 및 위험도 |
| :---: | :--- | :--- | :--- | :--- |
| **F0076** | 제3장 3-2. 작업로 선정 | `(단위 : 인/ha)` | **1.0 km** | **[치명]** 면적 단위(`ha`)를 선형 거리(`km`)로 왜곡 저장! 견적 물량 산출 시 10,000배 단위 불일치 위험 |
| **F0223** | 제8장 8-4. 끈끈이 롤 트랩 | `(단위: 100본/ha당)` | **1.0 ha** | **[치명]** `100본` 수량이 탈락하고 단순 `ha`로 기록되어 100배 계산 오류 유발 |
| **F0408** | 제13장 13-4-3. 고임돌 소요량 | `(단위: ㎥/㎡당)` | **1.0 ㎡** | 체적/면적 복합단위(`㎥/㎡`)가 단순 면적(`㎡`)으로 축소 기록 |
| **F0410** | 제13장 13-4-4. 찰쌓기 뒷채움 콘크리트 | `(단위: ㎥/㎡당)` | **1.0 ㎡** | 뒷채움 콘크리트 타설량(`㎥/㎡`)이 면적으로 오인되어 레미콘 체적 누락 위험 |
#### 2. 주요 핵심 공종 밑수 완전 결측 사례 (`basis_quantity: null`, `basis_unit: null`)
| 표 번호 | 공종명 (절) | 원문 MD 명시 밑수 | 마스터 상태 | 비고 |
| :---: | :--- | :--- | :--- | :--- |
| **F0077** | 제3장 3-3. 작업로 설치 | `인/1일 1km당` | `null` | 선형 거리 밑수 누락 |
| **F0082** | 제3장 3-8. 드론 영상 촬영 | `인/ha` | `null` | ha 밑수 누락 |
| **F0085** | 제4장 나무베기 (벌채) | `㎥/1인/1일` | `null` | 일일 벌채능력 밑수 누락 |
| **F0240** | 제9장 9-3-2. 터파기(기계) | `㎥당` | `null` | 토공량 밑수 누락 |
| **F0251** | 제9장 9-8-1. 철근절단 | `㎥당` | `null` | 구조물 체적 밑수 누락 |
| **F0256** | 제9장 9-11-1. 포장절단 | `일당` | `null` | 장비 일당 밑수 누락 |
| **F0280** | 제9장 9-14-2. 다짐(콤펙터) | `㎥당` | `null` | 다짐 체적 밑수 누락 |
| **F0338** | 제12장 12-6. 콘크리트 포장 | `일당` | `null` | 포장 작업조 일당 누락 |
| **F0366** | 제12장 12-19. 강관비계 | `공㎥당` | `null` | 비계 체적 밑수 누락 |
| **F0379** | 제12장 12-29. 스페이셔 설치 | `개소당` | `null` | 개소 밑수 누락 |
| **F0424** | 제13장 13-8. 막돌쌓기 | `인/㎡` | `null` | 석축 면적 밑수 누락 |
| **F0430** | 제13장 13-10-2. 말뚝박기(인력) | `1일당` | `null` | 인력 작업 일당 누락 |
| **F0444** | 제13장 13-14. 식생토낭 | `인/개` | `null` | 토낭 개수 밑수 누락 |
| **F0447** | 제13장 13-15-2. 목책 설치 | `인/조` | `null` | 목책 조 밑수 누락 |
---
### 항목 ④ [주]의 계수·조건 누락 (표 아래 붙은 주석 계수)
원문 MD의 각 표 아래에는 할증, 손료, 공제, 부자재 소요량을 규정한 `[주]` 주석이 필수적으로 붙어 있음. 이 중 금액 계산에 직결되는데도 마스터의 `condition_note` 또는 산식에 누락된 핵심 9개 표:
1. **F0068 (도폭선 암발파)**:
- 원문 [주]: 덤프환산 계수(제1장 1-2-7 7호 적용) 및 대형브레이커 조합 규정.
- 마스터: `condition_note` 미반영 $\rightarrow$ 덤프 운반량 환산 계수 누락.
2. **F0146 (비탈덮기 거적)**:
- 원문 [주]: 볏짚거적 및 차광망 손율 적용 기준.
- 마스터: 손율 데이터 누락 $\rightarrow$ 자재 손료 미반영.
3. **F0242 (토공 집토)**:
- 원문 [주]: 0.7㎥ 굴착기 기준 시간당 작업량 공식 $Q = \frac{3600 \times q \times k \times f \times E}{C_m}$ 및 암질별 계수.
- 마스터: 산식 파라미터 미연결.
4. **F0245 (발파 집토)**:
- 원문 [주]: **"발파구간의 평균 횡단경사 80% 이상으로 굴진을 위한 발파 시 인건비의 20%를 가산한다."**
- 마스터: 인건비 20% 가산 조항 누락 $\rightarrow$ 급경사지 노무비 축소 발생.
5. **F0251 (구조물 헐기 철근절단)**:
- 원문 [주]: **"고철공제 : $A = 1㎥ \times 0.008 \times 7,850kg/㎥ \times 80\% = 50.24kg/㎥ \fallingdotseq 50kg/㎥$"**
- 마스터: 고철 50kg/㎥ 공제 조항 누락 $\rightarrow$ 공제액 미반영으로 견적 과다 위험.
6. **F0284 (노체다짐)**:
- 원문 [주]: 자주식 진동롤러(10ton)와 굴착기(0.7㎥) 조합 규정 및 $Q$ 공식.
- 마스터: 장비 조합 조건 누락.
7. **F0285 (살수)**:
- 원문 [주]: 물탱크 5,500L 기준, 최적함수비(13%), 자연함수비(8%), 운반시간 $T_2$ 산출식.
- 마스터: 물탱크 규격 및 살수량 계산 조건 누락.
8. **F0394 (유로폼 부자재)**:
- 원문 [주]: **"플랫 타이(Flat Tie) 대신 폼 타이(Form Tie) 사용 시 소요 수량은 12-4 합판 거푸집 자재수량을 따른다."**
- 마스터: 대체 자재 산출 기준 누락.
9. **F0395 (유로폼 설치 및 해체)**:
- 원문 [주]: **"공구손료 및 경장비 기계경비는 인력품의 3%로 계상한다.", "수직고가 7m를 초과하는 경우 매 3m마다 시공량을 9%까지 감한다."**
- 마스터: 공구손료 3% 및 고소작업 감속율(9%) 미반영 $\rightarrow$ 노무비/경비 왜곡.
---
### 항목 ⑤ 갈래(variants) 및 `pum_form: reference` 오분류
마스터 데이터에서 `pum_form``reference`(단순 참고)로 지정되면 자동 견적 엔진이 해당 표를 자원 집계 대상에서 제외함. 그러나 조사 결과, **철근콘크리트(제12장)와 구조물(제13장)의 실제 공사비 산출 핵심 자재·인력 표 27개가 `reference`로 오분류**되어 있어 자원 축에서 탈락하고 있음!
#### 금액 직결 핵심 오분류 표 명세 (27개 중 대표 15개)
| 표 번호 | 원문 절 및 공종명 | 단위 | 원문 표 내용 (실제 비용 성격) | 마스터 현 분류 | 정상 분류 및 조치 요구 |
| :---: | :--- | :---: | :--- | :---: | :---: |
| **F0369** | 12-22. P.V.C 파이프 설치(50mm) | 개소당 | 아스팔트 4kg, 방수공 0.034인, 보통인부 0.04인 | `reference` | **`requirement`** (배수관 필수자재) |
| **F0380** | 12-30-1. 다웰바 신축이음부 | 개소당 | D32 다웰바 필요수량, 설치비 재료비의 5% | `reference` | **`requirement`** (도로줄눈 필수공종) |
| **F0381** | 12-30-2. 다웰바 접속스라브부 | 개소당 | D29 다웰바, PVC파이프, 특별인부 0.1인 | `reference` | **`requirement`** (도로줄눈 필수공종) |
| **F0382** | 12-31. 물끊기 홈(NOTCH) 설치 | 개소당 | 특별인부 0.1인, 보통인부 0.001인 | `reference` | **`requirement`** (옹벽 상단 필수) |
| **F0383** | 12-32. 전선관 설치(P.V.C ø54) | 개소당 | 주재료비 및 설치비(주재료비의 5%) | `reference` | **`requirement`** (전기/통신 배관) |
| **F0386** | 12-34-2. 합판거푸집(3회 0~7m) | ㎡당 | 보통인부 0.29인, 콘크리트 진동기 2대 | `reference` | **`requirement`** (콘크리트 타설 필수) |
| **F0388** | 12-34-4. 채움재(T=20mm) | ㎡당 | 채움재 자재비, 고철대 감(3%) | `reference` | **`requirement`** (신축이음 채움재) |
| **F0390** | 12-36. P.C BOX 설치 | 식 | 미장공 0.14인, 보통인부 0.05인 | `reference` | **`requirement`** (암거 설치 필수) |
| **F0391** | 12-37. 콘크리트 타설(무근) | ㎥당 | 레미콘 자재비, 콘크리트공 0.15인, 인부 0.27인 | `reference` | **`requirement`** (타설 필수 노무) |
| **F0393** | 12-38-2. 유로폼 사용수량 | 10㎡당 | 웨지핀, 플랫타이, 박리제(주재료비 24~79%) | `reference` | **`requirement`** (유로폼 부자재) |
| **F0400** | 13-2-3. 야면석 채집(운반) | 100개당 | 화물자동차 운반 품 (소형트럭 등) | `reference` | **`requirement`** (석재 운반비) |
| **F0406** | 13-3. 돌붙이기 뒷채움자갈 | ㎡당 | 조약돌/자갈 소요량(0.15~0.30㎥/㎡) | `reference` | **`requirement`** (석축 뒷채움 필수) |
| **F0408** | 13-4-3. 고임돌 소요량 | ㎥/㎡ | 석축 높이별 고임돌 소요 체적 기준표 | `reference` | **`requirement`** (석축 자재량 산출) |
| **F0410** | 13-4-4. 찰쌓기 뒷채움 콘크리트 | ㎥/㎡ | 높이별 레미콘 소요량(0.20~0.55㎥/㎡) | `reference` | **`requirement`** (찰쌓기 핵심 레미콘비) |
| **F0446** | 13-15-2. 목책 설치(목재) | m당 | 통나무 원목 및 부자재 소요량 | `reference` | **`requirement`** (목책 필수자재) |
---
## 4. 종합 평가 및 후속 개선 권고사항
1. **원문 데이터(표 셀 수치)는 100% 무결점 보존됨**:
- 파서가 추출한 476개 표의 내부 셀 값과 기초값 15종의 기본 수치는 원문 MD와 완벽히 일치함.
2. **가장 시급한 조치 사항 (금액 직결 3대 과제)**:
- **과제 1 (단위 왜곡 교정)**: `F0076`(작업로 선정)의 단위 `1.0 km` $\rightarrow$ `1.0 ha` 즉시 교정 (면적-거리 불일치 해소).
- **과제 2 (`reference` $\rightarrow$ `requirement` 전환)**: F0369(PVC), F0380/F0381(다웰바), F0391(타설 노무), F0410(뒷채움 레미콘) 등 27개 핵심 표의 성격을 `requirement`로 전환하여 자원 축 생성.
- **과제 3 (밑수 50개 결측 보완)**: F0077, F0240, F0251, F0366, F0424 등 주요 공종의 `basis_quantity``basis_unit` 복원.
3. **[주] 주석 계수 구조화**:
- F0245(급경사 발파 20% 가산), F0251(고철 50kg 공제), F0395(유로폼 공구손료 3%, 감속 9%) 등 누락된 9개 핵심 주석 계수를 견적 엔진 파라미터로 연결 필요.
---
*보고서 작성일: 2026-09-17*
*작성자: Antigravity (보조 AI)*
*기반 파일: `scratch/audit_results.json`*
+5 -1
View File
@@ -10,7 +10,7 @@
| 트리 | 그룹 | 상태 |
|---|---|---|
| 01_임도/ | 01_계획노선 · 02_상세설계 · 03_계산정보 · 04_수량분석정보 · 05_원가정보 | 61문서(목록 기준, draft) |
| 01_임도/ | 01_계획노선 · 02_상세설계 · 03_계산정보 · 04_수량분석정보 · 05_원가정보 | 65문서(목록 기준, draft) |
| 02_사방댐/ | 01_대상지_타당성평가 · 02_상세설계 · 03_계산정보 · 04_수량분석정보 · 05_원가정보 | 15문서 draft (2026-08-11) |
## 01_임도/01_계획노선 — 임도망·노선계획 영역 (프로그램 반영 2027 예정, 문서 수립은 현재 진행)
@@ -125,6 +125,10 @@
| 01_임도/05_원가정보/연결고리_건설공종_밑수꼴_분석.md | 임도 연결 확정 건설 공종 42개 절 밑수 꼴 전수 실사 — 소요량 22개 절 중 본문 윗줄 19개(86.4%)·표머리 2개·소제목 1개 및 무차원 20개 분류, 작업조 일당시공량 나눗셈 및 윗줄 단독행 탐색 파서 규칙 명세 | 국토부 건설공사 표준품셈 2026년판 및 연결고리 마스터 실사 (2026-09-17) | draft |
| 01_임도/05_원가정보/건설품셈_연결공종_reference_병_진단.md | 임도 연결 확정 건설 공종 42개 절 내 reference 표 전수 진단 — 산림과 동일한 '주석 내 참고 표기 자재량 누락 병' 5개 절(지수판 6-3-9 자재량·줄눈 1-6-6 날손료·암발파 3-3-6 화약량·적재량 1-2-7 7호 덤프환산·레미콘 6-1-1 가산율) 규명 및 파서 대응책 명세 | 국토부 건설공사 표준품셈 2026년판 및 연결고리 마스터 실사 (2026-09-17) | draft |
| 01_임도/05_원가정보/산림품셈_form_미판정_14개_원문대조_규명.md | 산림품셈 form 미판정(undetermined) 14개 표 전수 원문 실사 규명 — 머리 소실 9개(막갈이 등 2단헤더/1행 룩업 복원)·혼합 행렬 3개(천연림 수확/10종자재 피벗/펌프카)·공식 1개(물운반 파라미터)·글값 1개(파형강관 별산/필요시적용 플래그) 명세 | 산림사업 표준품셈 2025-82호 (2026-09-17) | verified |
| 01_임도/05_원가정보/품셈_원문_전수실사_및_원가위험_종합총괄.md | 2026-09-17 산림·건설 품셈 및 연결고리 전수 실사 종합 총괄 보고서 — 금액 직결 4대 위험(reference 실값 20·건설 노무비 위험 5·미판정 14·밑수 155), 5대 구조 왜곡(목차오기·표면마무리 100배·뿌리 4.7배 등), 6유형·밑수 지도 및 관련 11문서 상호 연결 총괄 | 산림사업 표준품셈 & 건설공사 표준품셈 2026 전수 실사 집약 (2026-09-17) | verified |
| 01_임도/05_원가정보/품셈_실사_목차.md | 2026-09-17 품셈 실사 상호 참조 목차(Index) 문서 — 금액에 닿는 발견(4건)·구조에서 드러난 것(5건)·다음 판 지도(6건)의 파일 위치·동반 JSON·핵심 요약만 간결하게 가리키는 관문 장부 | 기술정보DB 원가정보 실사 문서 11종 색인 (2026-09-17) | verified |
| 01_임도/05_원가정보/오늘_작업_기초값_공종축_원문대조_검증보고서.md | 2026-09-17 기초값 15종(8,372줄 100% 불변) 및 공종 축(목차오기 둘 원문본문 일치·헛단위 5줄 정상 제외·단가 0원 변동) 원문대조 정밀 감사 검증보고서 | 원천 JSON 9종 및 산림·건설 품셈 원문 정밀 대조 (2026-09-17) | verified |
| 01_임도/05_원가정보/품셈_원문md_마스터데이터_대조_검증보고서.md | 산림사업 표준품셈 원문 MD(9,167행 476개 표) ↔ 마스터 데이터(477개 공종) 전수 대조 검증보고서 — 5대 항목(누락 23개·수치 100% 일치·밑수 결측/왜곡 60개·[주] 핵심 계수 누락 9개·금액 직결 reference 오분류 27개) 정밀 명세 | 산림사업 표준품셈 2025-82호 & 공종/기초값 마스터 전수 대조 (2026-09-17) | verified |
## 02_사방댐 — 사방댐 설계자동화 기술문서
@@ -289,7 +289,7 @@ def test_갈래에도_불변_열쇠가_있다(master: dict) -> None:
# 이름 칸 둘 — 원문은 손대지 않고, 다듬은 것이 따로
raw = [it.get("variant_keys") or [] for it in items]
assert [n for it in items for n in (it.get("variant_keys") or [])] == [p[0] for p in pairs]
assert sum(1 for a, b in pairs if a != b) == 14 # 자간·물결표가 다듬어진 줄
assert sum(1 for a, b in pairs if a != b) == 70 # 자간·물결표가 다듬어진 줄
assert raw # 원문 목록은 그대로 남아 있다
@@ -38,6 +38,7 @@ def _same_except_time(fresh: dict, saved: dict) -> None:
for doc in (fresh, saved):
doc.pop("generated_at")
doc["stats"].pop("keys_newly_issued") # 첫 뽑기만 발급 · 다시 뽑으면 0
doc["stats"].pop("variant_keys_newly_issued", None) # 갈래 열쇠도 같음
assert fresh == saved
@@ -149,3 +150,42 @@ def test_산림을_고르는_쪽이_건설_파일을_안_집음() -> None:
assert load_master()["dataset_id"] == "work_item_master_forest"
assert not list(OUT.glob("work_item_master_*const*.json"))
def test_건설_갈래도_이름을_다듬어도_같은_열쇠(master: dict) -> None:
"""④ 건설 갈래 펴기(2026-09-17) — 갈래 열쇠는 번호(`CW-00063#01`) · 자간·물결표를 손질해도 새로 안 남."""
import copy
from B08_Quantity.B08_Quantity_Build_WorkItemMaster_Keys import (
assign_variant_keys,
load_registry,
)
items = master["work_items"]
spread = [it for it in items if it.get("variants")]
assert len(spread) > 100 and sum(len(it["variants"]) for it in spread) > 400
registry = load_registry(const.CONST_KEY_REGISTRY, const.KEY_PREFIX)
nodes = copy.deepcopy(spread)
for node in nodes: # 사람이 이름을 다듬은 날 — 자간 한 칸 · 물결표 다른 벌
node["variant_keys"] = [
" ".join(k.split()).replace("", "") for k in node["variant_keys"]
]
assert assign_variant_keys(nodes, registry) == [] # 새 번호 0
for before, after in zip(spread, nodes):
assert [v["variant_key"] for v in after["variants"]] == [
v["variant_key"] for v in before["variants"]
]
def test_자간_다듬기는_진짜_띄어쓰기를_안_붙임() -> None:
from B08_Quantity.B08_Quantity_Build_WorkItemMaster_Keys import tidy_spacing
assert tidy_spacing("측 량") == "측량"
assert tidy_spacing("평 규 준 틀") == "평규준틀"
assert tidy_spacing("굴 삭 기 (무한궤도)") == "굴삭기 (무한궤도)"
assert tidy_spacing("메 붙 임 · 깬 돌 · 뒷길이 25㎝") == "메붙임 · 깬돌 · 뒷길이 25㎝"
assert tidy_spacing("토목부문 측 량 기준점 측량") == "토목부문 측량 기준점 측량"
assert (
tidy_spacing("그 외 자재의 운반품셈") == "그 외 자재의 운반품셈"
) # 한 글자 낱말 둘은 진짜 띄어쓰기
assert tidy_spacing("호박돌 및 야면석 · 뒷길이 25㎝") == "호박돌 및 야면석 · 뒷길이 25㎝"
+4 -2
View File
@@ -84,8 +84,10 @@ def test_트리_표_id_와_이름표_표_id_는_양쪽으로_같음(client: Test
label_only += [f"{entry['file_id']}::{i}" for i in sorted(label_ids - tree_ids)]
assert not_labelled == [], not_labelled
assert label_only == [], label_only
# 2026-09-17 92 → 100 — 공종 축 산출 일곱 + 갈래 열쇠 장부 표, 형태 미판정 표는 비어 빠짐.
assert sum(len(t) for t in files.values()) == LABELS["counts"]["tables"] == 100
# 2026-09-17 92 → 101 — 공종 축 산출 일곱 + 갈래 열쇠 장부 표.
# 2026-09-17 101 → 102 — 건설 열쇠 장부에도 갈래 표(건설 갈래 펴기 ④).
# 2026-09-17 102 → 101 — 산림 형태 미판정이 0 이 되어 그 표가 빠짐(값 묶음으로 내려감).
assert sum(len(t) for t in files.values()) == LABELS["counts"]["tables"] == 101
for entry in LABELS["files"]: # 이름이 실제로 붙음 · 줄 수도 이름표 셈과 같음
named = {t["key"]: t for t in entry["tables"]}
for t in files[entry["file_id"]]:
+60 -3
View File
@@ -76,9 +76,11 @@ def test_산림_평평한_잎_목록과_계산_규칙(client: TestClient) -> Non
def test_건설_공종_축도_같은_길(client: TestClient) -> None:
"""건설(2026-09-17 뽑음) — 부문이 뿌리라 경로가 부문부터 · 열쇠 CW- · 계산 규칙은 전부 choose_one."""
"""건설(2026-09-17 뽑음) — 부문이 뿌리라 경로가 부문부터 · 열쇠 CW- · 계산 규칙은 전부 choose_one.
갈래도 산림과 같은 읽기로 ( · 공종 997 1,293 · 갈래 열쇠 `CW-00063#01`)."""
table = _get(client, "work_item_const", size=500, axis_role="")
assert table["total"] == table["stats"]["work_items"] > 900
assert table["stats"] == {"work_items": 997, "units": 1293} and table["total"] == 1293
assert sum(1 for r in table["rows"] if "#" in r["@id"]) > 0
rows = table["rows"]
assert all(r["@id"].startswith("CW-") for r in rows)
assert all(r["name"].split(" ")[0].endswith("부문") for r in rows)
@@ -200,7 +202,11 @@ def test_연결고리_표가_이은_줄에_연결됨_감추지_않고_표시만(
} - confirmed
for kind, prefix in (("work_item_const", "CW-"), ("work_item_forest", "FW-")):
every = _get(client, kind, size=500, axis_role="")
rows = every["rows"] + _get(client, kind, size=500, page=2, axis_role="")["rows"]
rows = [
row
for page in range(1, every["total"] // 500 + 2)
for row in _get(client, kind, size=500, page=page, axis_role="")["rows"]
]
assert len(rows) == every["total"] # 연결 거르기 기본은 「전부」 — 다 보임
marked = {r["@key"] for r in rows if r["link"] == "연결됨"} # 갈래 줄은 공종 열쇠로
listed = {r["@key"] for r in rows} # 표가 안 붙은 묶는 마디(CW-01329 따위)는 목록 밖
@@ -250,3 +256,54 @@ def test_총칙_줄은_기본_감춤_전부를_고르면_보임(client: TestClie
_get(client, kind, size=1, axis_role="general_provision")["total"]
== (counts["general_provision"])
)
def test_찾기는_물결표_가운뎃점_띄어쓰기를_같게_봄(client: TestClient) -> None:
"""원문이 물결표를 둘(∼·~)로 쓰고 자간 공백이 들쭉날쭉 — 사람이 친 「~」·붙여 쓴 이름으로도 찾힘.
찾기만 ·열쇠는 원문 그대로(서브 훑기 · 브레인 2026-09-17)."""
wavy = _get(client, "work_item_forest", size=50, q="2.12.5")["total"]
assert wavy >= 1
assert _get(client, "work_item_forest", size=50, q="2.1~2.5")["total"] == wavy
assert _get(client, "work_item_forest", size=50, q="2.12.5")["total"] == wavy
rows = _get(client, "work_item_forest", size=50, q="2.1~2.5")["rows"]
assert all("~" not in r["@id"] for r in rows) # 열쇠는 손질 안 함
spaced = _get(client, "work_item_forest", size=50, q="토사 깍기", axis_role="")["total"]
assert (
spaced == _get(client, "work_item_forest", size=50, q="토사깍기", axis_role="")["total"] > 0
)
def test_이름_다듬기는_보일_이름만_열쇠는_그대로(
client: TestClient, monkeypatch: pytest.MonkeyPatch
) -> None:
"""⭐ 갈래 불변 열쇠를 세운 까닭(브레인 2026-09-17) — 자간 공백(「측 량」·「평 규 준 틀」)을 다듬어도
열쇠(`FW-#01`)가 한 글자도 안 흔들림. 다듬기를 끈 목록과 켠 목록의 열쇠를 맞댐."""
from B08_Quantity import B08_Quantity_Build_WorkItemMaster_Keys as keys
from Z01_MasterData import Z01_MasterData_WorkItems as work_items
for kind in work_items.KINDS:
tidy = work_items.base_rows(kind)
with monkeypatch.context() as patch:
patch.setattr(keys, "tidy_spacing", lambda text: " ".join(str(text or "").split()))
raw = work_items.base_rows(kind)
assert [r["@id"] for r in tidy] == [r["@id"] for r in raw]
if kind == "work_item_const":
assert (
sum(a["name"] != b["name"] for a, b in zip(tidy, raw)) > 0
) # 실제로 다듬어진 줄이 있음
shown = _get(client, "work_item_const", size=50, q="기준점 측량", axis_role="")["rows"]
assert shown and all("측 량" not in r["name"] and " 측량 " in r["name"] for r in shown)
def test_품셈_번호는_마디마다_수로_세움(client: TestClient) -> None:
"""글자로 세우면 「10-1」이 「2-1」 앞에 섬(서브 훑기) — 마디마다 수로."""
rows = _get(client, "work_item_forest", size=500, sort="number", axis_role="")["rows"]
numbers = [tuple(int(x) for x in r["number"].split("-")) for r in rows if "-" in r["number"]]
assert len(numbers) > 300 and numbers == sorted(numbers)
def test_건설_늘_빈_칸은_감춤(client: TestClient) -> None:
"""건설은 합산형 선언이 없어 「단계 무게」가 늘 빈칸 — 감춤(산림은 보임)."""
hidden = lambda kind: {c["key"]: c["hidden"] for c in _get(client, kind, size=1)["columns"]} # noqa: E731
assert hidden("work_item_const")["step_weight"] is True
assert hidden("work_item_forest")["step_weight"] is False