Commit Graph
17 Commits
Author SHA1 Message Date
eomsangdonandClaude Opus 5 cdbc932717 feat(B09): 새 인계 칸 둘 수용 + 예시 서식 우회 제거(원천이 이김)
- 계약 시험이 **제 일을 했음** — 「인계가 보내는데 안 읽는 칸: spec_class,
  spec_class_basis」로 깨짐. 둘 다 읽고, 갈래 판정 근거(`spec_class_basis`)는
  **B08 문구 그대로** 줄 비고에 이음
- 예시 서식 거르기를 뺌 — B08 이 **마스터 원천에서** 거름(8건).
  두 곳에서 같은 것을 거르면 나중에 한쪽만 고쳐짐
- 짝 시험은 남기되 모양을 바꿈 — 인공 표 대신 **실물 마스터에서 그 8공종이
  자원으로 서지 않는지**. 원천이 바뀌면 이 시험이 알려 줌

검증: pytest 211 통과. 못 맞춘 자원 497(원천 필터 뒤 값과 일치)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 06:17:29 +09:00
eomsangdonandClaude Opus 5 b98dee3a06 fix(B09): 예시 서식 표 건너뜀 + 정규식 문자클래스 범위 오독 수정
⑤ 구간 표기 37줄을 살피다 둘이 나옴

- 그 줄들은 **살릴 값이 아니었음** — 품셈이 실어 둔 **단가산출서 예시(빈 서식)**
  안의 셀이었음(「ha당 참나무시들음병방제 단가산출서(예시)」).
  읽으려 들면 구간 라벨(「12~14㎝」)과 항목명이 자원 이름으로 오해됨
  ⇒ 머리글에 「단가산출서」·「예시」가 있으면 **표째 건너뜀**.
  못 맞춤 882 → 497, 성분 빠짐 84 → 78. 자원 축·일위대가·분포는 그대로
  (값이 없던 표라 당연함)
- ⚠ **진짜 결함** — `RANGE_DASHES` 를 정규식 문자클래스에 그대로 넣어
  `~-–` 이 **범위 연산자**로 읽히고 있었음. 「0.7㎥」·「15톤」까지 구간으로 잡힐
  자리였음. `re.escape` 한 `RANGE_DASH_CLASS` 를 두고 세 파일이 그것을 씀
  (「한 곳으로 모으라」는 지적이 없었으면 못 봤을 자리)
- 구간 셀에 **단위 꼬리**(「51~100m」)를 허용하되 **수~수+단위 전체가 맞을 때만** —
  단위가 붙었다고 다 구간은 아님(「굴착기 0.7㎥」는 규격)

계획서 — 석재 할증률 물음을 「몇 %인가」가 아니라
「붙일까 말까, 붙인다면 근거를 어디서」로 고침(메인 지적)

검증: pytest 211 통과(신규 2 — 예시 서식 건너뜀 + 정상 표는 안 걸림)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 05:54:18 +09:00
eomsangdonandClaude Opus 5 52d76a9286 fix(B09): 제잡비 밑수 = 직접노무비 + 안 불리던 가드 잇기 + 700줄 분리
메인 창이 B09 를 읽기 전용으로 교차검토해 낸 지적을 처리

제잡비 밑수 — **사람 품(직접노무비)만**으로 바꿈. 기계 안의 조종원 노임은 안 셈
- 근거 셋을 주석에 인용: 산림품셈 13-6-2 [주]③ 「노무비의 합계액」 ·
  건설품셈 제8장 「잡재료 등 손료 : **직접노무비**에 …」 ·
  같은 장에서 기계를 넣을 때는 「노무비, 기계손료 및 운전경비의 합」이라 **따로 적음**
- 뜻으로도 그쪽 — 제잡비는 **본 자원에 안 선 잔 기계 손료**를 사람 품에 비례해
  얹는 자리인데 그 표엔 굴착기가 이미 본 자원으로 서 있음
- 찰쌓기 60~80 기준 ㎡당 2,565.90 → **2,098.46** (제잡비 붙는 17줄 전부 걸림)
- ⚠ 잠정 — 사용자 확정 대기. 조종원 포함이면 약 +22 %

안 불리던 가드 둘 (「있다」와 「돈다」는 다름)
- ㉥ 물빼기 파이프 — **조판에서 실제로 부름**. 지금은 늘 아랫단이라 안 걸리되
  설계 조건이 실리는 날 그 값만 바꾸면 바로 걸림
- ㉢ 배합 분해 — 부를 자리가 아직 없음. **그 사실과 부를 위치를 코드에 적음**

700줄 제한 (CLAUDE.md 4장) — 셋을 나눔
- `_UnitPrice_View`(화면용 조회) · `_ResourceAxis_Sources`(자료 적재·셀 파싱) ·
  `_BillOfQuantities_Rows`(줄 만들기). 가르는 금을 각 파일 머리말에 적음
- 부르는 쪽이 어디서 오는지 신경 쓰지 않게 재수출

물결표 목록을 `RANGE_DASHES` 한 곳으로 모음 — 네 파일에 따로 적혀 서로 달랐음
(지금 물리는 것은 없었으나 같은 목록이 네 벌이면 언젠가 하나만 고쳐짐)

검증: pytest 206 통과, 700줄 초과 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 05:39:47 +09:00
eomsangdonandClaude Opus 5 c2a8f7cc41 feat(B09): 제잡비를 경비로 붙임 + ㉥ 물빼기 파이프 가드 + 성분 빠짐 차단 확대
제잡비 (품셈 13-6-1·13-7-1 [주]③, 원문은 메인이 찾아 줌)
- **노무비 합계 × 비율이 경비(J)로** 붙음. 재료·노무가 아님
- 기본은 **아랫단**(물빼기 파이프 미설치). 「상한」이라 산출근거에 그 사실을 적음
- `PriceDetail.percent_of_labor` 신설 — 밑수가 3분할 전체인 `percent_of_parent` 와
  다름. 비율 줄은 참조를 풀기 전에 처리(자기 자신을 가리켜 순환으로 잡혔음)
- 표시 합계에도 넣음 — 안 넣으면 화면 합계와 실제 단가가 어긋남

㉥ 가드 신설 — 제잡비 윗단(파이프 설치)을 쓰면서 물구멍을 자재로 또 실으면 멈춤
  (원문이 「상단에는 파이프 설치의 노무비·재료비를 포함한다」고 명시).
  짝 시험 4건 — 아랫단·파이프 없음·비슷한 이름은 안 걸림

성분 빠짐 차단 확대
- 시간·대수로 세는 줄(장비 몫)을 못 맞추면 그 공종 금액을 안 만듦.
  초본류 시비가 「트럭(2.5t) 2.6시간」을 빼고 33.1원/㎡ 로 서 있었음
- 자재 줄(kg·매)은 이미 알려진 미결이라 막지 않고 드러내기만 함
- 요약의 「의심 저가」에서 막아 둔 공종은 제외 — 새로 살펴야 할 것과 섞이지 않게

뭉친 표 두 곳 수정
- 칸 전체를 한 이름으로 먼저 시도 — 「굴착기 (무한궤도)」가 안 풀려 찰쌓기 13-6-2 의
  장비 몫이 빠지고 공종이 막혀 있었음
- ⚠ 라벨 줄 판정에 **순수 숫자 칸** 검사 추가 — 「자재 | 종자 | kg | 0.025」를
  라벨 줄로 오해해 씨앗뿜어붙이기 표를 가로챘음(회귀, 시험이 잡음)

결과: 자원 축 354 → 418, 일위대가 176 → 203, 막힌 공종 32
  찰쌓기 13-6-2 = 118,794.9원/㎡ (노무 + 굴착기 0.48h + 제잡비 3 %)

검증: pytest 190 통과(신규 6)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 04:22:56 +09:00
eomsangdonandClaude Opus 5 15bdf6bd64 feat(B09): 뭉친 이름+갈래 열 표 읽기 — 돌쌓기 계열 성립
메인이 `reference` 오판 41건을 되살려(bc4b6837) 돌쌓기(장비)가 마스터에
들어왔으나, 그 표는 **이름도 값도 뭉쳐 오고 열이 규격 갈래**인 또 다른 모양이라
여전히 안 섰음 (「석공 보통인부 | 0.09 0.05 | 0.08 0.04 | 0.07 0.03」)

- 뭉친 이름·값을 갈래 열에 짝지어 읽음. 개수가 어긋나면 표째 버림
- 「굴착기+부착용 집게」는 **두 기종 조합**으로 보아 같은 시간을 둘 다 붙임
  (TODO(미결) 해석 잠정 — 사용자 확인 대기)
- 규격이 **옆 칸**에 있고 갈래(무한궤도)가 안 적힌 기종은 규격 일치 + 무한궤도
  우선으로 잠정 채택. 카탈로그 규격이 범위(0.6∼0.8)면 그 안에 드는지로 판정
- ⚠ 「1.04(1.17)」 괄호값은 **조건 시공 시 대안값**임이 원문에서 확인됨
  (13-6-1 [주]② 흡출방지재 시공 시 ( ) 값). 기본은 괄호 밖, 대안값은
  `alternative_amount` 로 남겨 화면에 「시공 시 다름」으로 보이게 함
- 라벨 줄 판정을 **모든 칸**으로 — 첫 칸만 보면 기초잡석 12-25 를 라벨 줄로
  오해해 표째 가로챘음(그 탓에 기초잡석이 한때 다시 막혔음)
- 갈래 키를 **공백 없는 것**으로 통일(`#보통`), 원문 문구는 이름에 보존
  (두 창 합의)

결과: 자원 축 259 → 354, 일위대가 145 → 176
  돌쌓기(찰) 35cm이하 58,166.7 / 55cm이하 52,938.7 / 75cm이하 46,892.7 원/㎡
  메쌓기·찰쌓기·붙이기 계열도 직경 3갈래로 섬

검증: pytest 184 통과(신규 1). 화면 실측 — 지금 인계 자료에 구조물 줄이 없어
표에는 아직 안 뜸(B08 이 갈래를 골라 보내면 그대로 금액이 섬)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 02:04:42 +09:00
eomsangdonandClaude Opus 5 0728e4bae7 fix(B09): 기종 이름 표기 맞춤 + 공식 계수 줄을 자원으로 안 셈
석재 할증률을 찾으러 12·13장 본문을 훑다 발견한 둘

- 품셈은 같은 기종을 「굴 삭 기」·「굴착기」·「유압식백호우」로 섞어 적음.
  메쌓기 13-6-1 의 「굴 삭 기 (무한궤도)」가 안 붙어 **장비 몫이 통째로
  빠져 있었음**. 이름 안 공백 제거 + 기종 별칭만 맞춤(규격은 안 건드림)
- ⚠ 그 정규화가 새 오독을 열었음 — 측구터파기의 「유압식백호우 … | k | 0.9」
  줄이 자원으로 잡혀 **버킷계수 0.9 를 소요량으로** 읽었음(사용료 0.9시간분
  이중). 공식 기호(K·f·E)를 단 줄은 자원으로 세지 않음 — 그 줄은 시공능력
  공식 쪽에서 씀

결과: 자원 축 256 → 259, 일위대가 145 유지, 최소 233.4 / 최대 5,030,954.6

석재 할증률은 **품셈에 없음을 확인** — 1-3-1 재료 할증률표에 야면석·막자갈·
고임돌이 없고, 13-4~13-7 돌쌓기 본문 [주]에도 할증 문구 없음. 사용자 확정 대기

검증: pytest 183 통과(신규 2 — 공식 줄 제외 + 공백 이름 매칭 짝 시험)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:48:47 +09:00
eomsangdonandClaude Opus 5 a8f0248bf7 feat(B09): 작업조+시공량 표 읽기 — 유로폼 노무 성립
품셈에는 소요량 대신 **「작업조 몇 인이 하루 몇 ㎡」**로 주는 표가 11건 있음.
1단위당 품 = 인원 ÷ 시공량. 행-자원으로 읽으면 **인원 4를 소요량 4로** 오해해
35배 부풀어, 형태 판정보다 **먼저** 가름
(유로폼 12-38-3 은 마스터에서 `reference` 로 찍혀 형태 필터에 버려지고 있었음)

- 유로폼 설치·해체: 형틀목공 4 ÷ 35 = 0.1143인/㎡, 보통인부 1 ÷ 35 = 0.0286인/㎡
  → 유형별 갈래로 세움 (복잡 51,009.1 · 보통 36,435.0 · 간단 31,880.7 원/㎡)
- 유형은 우리가 안 고름 — 품셈 12-38-3 [유형] 이 「보통: 측구·수로·옹벽」으로
  정해 두었으므로 갈래로 세우고 고르는 것은 B08 (철근 12-3 [주]① 과 같은 모양)
- ⚠ 못 푼 작업조 줄이 있으면 **표째 버림** — 평떼 시비에서 「트럭 2.5ton 1대」가
  조용히 빠지고 노무만으로 28.6원/㎡ 이 서 있었음(분포 최소값이 233 → 28.5 로
  떨어진 것으로 발견)
- 이름 안에 공백이 든 줄(「비 계 공」)은 한 이름으로 먼저 시도 — 공백을 구분자로만
  보면 그런 표가 통째로 버려짐

결과: 자원 축 246 → 256, 일위대가 139 → 145, 최소값 233.4 유지

검증: pytest 181 통과(신규 6 — 손계산 대조 + 오탐 짝 시험 포함)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:42:20 +09:00
eomsangdonandClaude Opus 5 50f3ab70d3 fix(B09): 「값 못 읽음」 오탐 좁히고 「값 × 비율%」 표기 읽기
- ⚠ 앞 커밋의 「값 못 읽은 줄」 판정이 **머리 줄까지 잡고 있었음** —
  「특별인부 | 벌목부 | 보통인부」처럼 자원 이름만 나열된 줄. 28 공종 중
  대부분이 오탐이었음. **숫자가 있는데** 못 읽은 줄만 성분 빠짐으로 봄 (28 → 12)
- 「0.2 × 30%」꼴을 0.06 으로 읽음. ⚠ 딱지의 30 % 를 **또 곱하지 않음** —
  두 번 곱하면 0.018. 그 밖의 식(「5인/km」)은 기준이 달라 안 읽고 막은 채 둠

기초잡석 12-25 성립 (121,661.1원/㎥)
  소할 할석공 0.06 + 부설다짐 보통인부 0.6 + 적사 굴착기 0.04535hr
  (Q = 3600 ÷ 22 × 0.7 × 0.55 × 1.0 × 0.35 = 22.05㎥/hr)
  운반(덤프)은 품셈이 10장에서 따로 내므로 여기 안 붙음

⇒ 옹벽 묶음 4조각이 모두 섬 — 타설 65,826.4 · 거푸집 81,321.9 ·
   철근 1,032,497.4 · 기초잡석 121,661.1

검증: pytest 174 통과(신규 4 — 오탐 짝 시험 포함:
머리 줄은 안 걸리고, 숫자 있는 미해독 줄은 걸림)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:20:48 +09:00
eomsangdonandClaude Opus 5 7591670e93 fix(B09): 값 못 읽은 자원 줄이 있는 공종은 금액을 막음
기초잡석 12-25 를 붙이다 발견 — `소할(30%) | 할석공(인) | 0.2 × 30%` 를
못 읽어 **부설다짐 0.6인만으로 107,145원**이 서고 있었음. 값이 그럴듯해
어떤 검사에도 안 걸림(「부분 성공이 가장 위험」)

- 이름 칸 판정을 **낱말 목록이 아니라 「풀리는지」**로 바꿈 — 첫 칸이 공정 이름인
  표(기초잡석)가 딱지 목록에 없어 통째로 못 맞추고 있었음. 자원 축 231 → 243
- **자원은 알아봤는데 값을 못 읽은 줄**이 있으면 그 공종을 `partial_items` 로
  표시하고 일위대가 금액을 만들지 않음. 그런 공종이 **28건** 있었고,
  그중 23건이 조용히 성분 빠진 단가로 서 있었음
- 못 읽은 줄은 `unmatched` 에 사유째 남김

검증: pytest 172 통과(신규 2 — 표시되는지 + 실제로 막는지 짝)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:14:47 +09:00
eomsangdonandClaude Opus 5 2ad66dce5d feat(B09): 열이 자원인 표(전치형) 읽기 + 오독 3종 차단
품셈에는 자원이 행이 아니라 **열 머리**에 오는 표가 39건 있음
(「구 분 | 콘크리트공(인) | 보통인부(인)」, 행은 무근·철근·소형구조물).
행-자원으로 읽어 콘크리트 타설(12-1)이 하나도 안 서고 있었음

- 갈래(variant)마다 따로 세움 — 품이 달라 뭉치면 어느 것도 안 맞음.
  코드는 `B-FP-12-01-01#무근구조물`, 이름에 갈래를 적어 사람이 고를 수 있음
- 레디믹스트콘크리트 타설: 무근 58,635.0 / 철근 65,826.4 / 소형 117,270.0 원

읽다가 잡은 오독 3종 — 전부 **고쳐 읽지 않고 버림** (자리를 단정할 수 없음)
- 병합 셀로 한 칸 밀린 행: 목재틀흙막이가 등급 글자를 건축목공 자리에 두어
  단가 503만원으로 섰음
- 좌우 두 판이 붙은 표: 소운반에서 거리값 60 이 「보통인부 60인」으로 읽혀
  1,553만원이 섰음. 열 머리가 되풀이되면 표째 버림
- 같은 갈래 이름 중복: 목재틀흙막이 「상」이 8.760 + 13.767 로 합산돼
  667만원이 섰음. 그 줄들을 버림
- 갈래 이름에 자원용 머리글 필터를 쓰던 것도 고침 — 「중」·「상」 등급이
  통째로 지워지고 있었음. 합계 줄만 걸러 냄

기준 단위 미상 드러내기 (막지 않음 — 막으면 125 중 122 가 멈춤)
- `unknown_basis` 122건, 그중 100만원 넘는 10건을 목록으로 냄
  (떼채취 평떼 1,032,408원 등 — 「100매당」류 묶음 기준 의심)
- 내역서 줄 비고에도 「기준 단위가 표에 없습니다 — 수량 단위와 같다고 보고
  곱했습니다」를 적음. 반영률 문구를 덮지 않고 이어 붙임

700줄 제한으로 전치형 처리를 `_Transposed.py` 로 분리 (647 + 138줄)

검증: pytest 163 통과(신규 5). 자원 축 198줄·갈래 54,
일위대가 85 → 125, 분포 최소 233.4 · 중앙 72,268.5 · 최대 5,030,954.6

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:53:58 +09:00
eomsangdonandClaude Opus 5 a71031b1f0 feat(B09): ④ 예산내역서 조판 + 배분율 표 오독 차단
조판
- B08 인계 응답을 계층 선 내역서로 접음. 계층·정렬은 공종 마스터의
  `parent_code`·`sort_order`(256 간격)에서 옴 — 코드 글자수로 깊이 안 셈
- ITEM NO. 를 가지치기 나무에서 매김. 머리글 줄은 수량·금액 없음
- `in_bill=false`(보정량계)는 수량만 보이고 금액 안 붙임.
  `check_excluded_rows_not_priced()` 가 수치로 막음 (㉡ 확장)
- 단가 없는 줄·공급 구분 미정 자재는 0 으로 안 때우고 `missing` 에 이름째 남김
- 잎에 일위대가가 없고 하위에 있으면 **후보만 보임** — 임의로 고르지 않음
- 반영률은 적기만 함(B08 이 이미 곱함) — 여기서 또 곱하면 두 배

배분율 표 오독 차단 (2026-09-08 실측으로 발견)
- 분류 딱지가 「인력(10%)」처럼 비율을 달고 오면 판정이 빗나가 자원이 통째로
  빠지고 있었음. 측구터파기(FP-09-12-01)는 자원 줄이 0 개였음
- 비율 꼬리표만 떼고 정확 일치 유지 — 「보통인부(인)」·「인력운반공」은 안 걸림
- 자원 축 119 → 144 줄, 일위대가 73 → 85. 기존 줄 변경 0·삭제 0
- ⚠ 그 표들은 인력 몫만 붙음(장비 몫은 시공능력 공식). 그대로 두면
  인력 10 % 몫 단가가 전량에 곱해져 **조용히 틀림** — 25 공종을
  `partial_ratio` 로 표시하고 내역서에서 금액을 안 붙임

검증: pytest 146 통과(신규 10). 가드는 일부러 어겨 멈추는 것까지 확인,
오탐 짝 시험 포함. 실물 인계자료(프로젝트 5cff3920)로 조판 실행 —
14 줄·검산줄 1·미확보 14 건이 이름째 뜸

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:31:17 +09:00
eomsangdonandClaude Opus 5 01691d4c14 feat(B09): 자원 축 재생성 + 마스터 파일 지문 기록
- B08 공종 마스터 재생성(ab39c174) 반영 — 자원 축 116 → 119 줄,
  미판정 83 → 76. 새로 붙은 것: 강관동바리(형틀목공·보통인부) ·
  신구 BOX접합(미장공)
- 기존 119 줄 중 **수치가 바뀐 줄 0건** — 밑수 판정 교정이 기존 소요량을
  건드리지 않았음. 일위대가 총액 분포도 그대로
  (최소 233.4 · 중앙 86,034.0 · 최대 1,916,466.0, 의심 저가 0건)
- 산출물에 `source_master_file`(마스터 파일 sha256) 추가 — 기존
  `source_dataset_version` 은 품셈 원판 지문이라 마스터를 다시 생성해도
  안 움직여, 낡은 파생물을 드러내지 못했음

검증: pytest 136 통과, 새 공종 2건 일위대가 적층 확인
(강관동바리 27,908.7 · 신구 BOX접합 33,273.1)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:14:02 +09:00
eomsangdonandClaude Opus 5 991f7e31b1 fix(B09): 분류 딱지 행에서 이름을 둘째 칸으로 읽음 — 자재·장비가 통째로 빠지던 자리
배분 창이 「초류종자살포 배합이 네 일위대가에 있나」를 물어 확인하다 **구멍을 찾음.**

- 품셈 표 중 **첫 칸이 분류 딱지**(「자재」·「장비」)이고 **이름이 둘째 칸**인 것이 있음:
  `['자재', '종      자', '', 'kg', '0.025']` · `['장비', '종자살포기', '2,500-3,000ℓ', …]`.
  첫 칸만 보고 읽어 **그 표의 자재·장비가 통째로 빠지고 있었음** — 씨앗뿜어붙이기에서
  종자·비료·피복제·침식안정제·색소·장비 3종이 다 빠지고 **보통인부 한 줄만** 남았음.
- 첫 칸이 분류 딱지면 이름을 둘째 칸에서 읽고, 값도 그 뒤 칸에서 찾게 고침.
- **매칭 106 → 116**(노무 100 → 110). 산출 파일 다시 냄.

**⚠ 그래도 배합은 아직 못 실림 — 원인은 사급 자재 단가 미결임**
- 종자·복합비료·화이버·합성접착제·색소가 **관급 카탈로그에 없음**(임도 자재가 관급에
  없다는 앞선 발견과 같은 자리). 장비 3종(종자살포기·트럭·물탱크)도 기종 카탈로그에 없음.
- **다만 이제 못 맞춘 목록에는 남음** — 구멍을 목록으로 드러내는 규칙 그대로.
  시험으로 못 박음(`test_seeding_materials_are_listed_not_dropped`).
- ⇒ 사면 4계열의 배합이 **B09 일위대가 몫**인 것은 맞으나, **사급 단가가 들어오기 전에는
  못 세움.** 「자재총괄에 이을 것이 없다」는 메인 판정은 유지되고, 그 자재는
  **㉡ 6번 슬롯 수동 입력 목록**으로 감(야면석·막자갈·고임돌·물구멍에 이어).

자체검증 — 신규 2건 포함 `pytest tmp/tests/ -q` **136 passed** · ruff 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 23:55:09 +09:00
eomsangdonandClaude Opus 5 0df6acb57d feat(B09): 자재 카탈로그 — 관급/사급 분리, 그리고 ⚠ 임도 자재가 관급에 없다는 발견
**`B09_Estimation_MaterialCatalog.py` 신설** — 두 창이 맞춘 이름을 그대로 씀:
`supply_type` = `owner_supplied` / `contractor_supplied` ·
`owner_supplied_install_by` = `contractor` / `owner` / `None`.

- 관급 = 나라장터 **6,999건**(`vat_basis: 부가가치세별도` → 부가세 제외 단가).
- **설치 주체는 지어내지 않음** — 원천에 없으므로 전부 `None`(미지정)으로 두고 **세어서
  알림**. 안전관리비 대상액이 관급 전액이 아니라 **도급자설치분**을 쓰므로(8-10)
  잘못 찍으면 금액이 조용히 틀리는 자리임.
- **규격 필수** — 같은 품명에 규격이 수백 개(「연돌」 410 · 「육각볼트」 323). 이름만
  맞추면 엉뚱한 규격 단가가 붙음.
- 매칭 카탈로그에 자재를 붙이면서 **이름 색인**을 넣음(7,700건이라 매번 훑으면 느림).

**⚠ 붙여 보고 알아낸 것 — 관급 목록에 임도 자재가 거의 없음**
- 나라장터 목록이 **건축·설비 자재 중심**(덕트·밸브·복공판·스피커…)이고,
  **시멘트·모래·자갈·레미콘·철근·파형강관이 한 건도 없음**.
- 까닭 둘 — ① 철근·레미콘·아스콘은 그 파일이 `excluded_named_groups` 로 **명시적으로
  빼 둠**(쇼핑몰 스냅샷 미보관) ② **시멘트·모래·자갈은 애초에 사급**임. 실무 울진에서
  관급은 **파형강관 Ø800/Ø1000 뿐**이었음.
- ⇒ **자재 매칭 0건.** 억지로 이름을 느슨하게 맞추지 않음 — 그렇게 하면 엉뚱한
  건축 자재 단가가 임도 공종에 붙음.
- **이 사실을 시험으로 못 박음**(`test_forest_road_materials_are_absent_from_owner_catalog`)
  — 나중에 「자재가 왜 안 붙나」를 다시 파는 일이 없도록.

**화면 요약 문구를 실측대로 갈아 끼움** — 「자재 카탈로그가 없어서」가 아니라
「관급 6,999건을 붙였으나 임도 자재가 거의 없고, **사급 단가가 미결**이라 구조물 계열이
안 섬」으로. 설치 주체 미지정 건수도 함께 냄.

자체검증 — 신규 6건 포함 `pytest tmp/tests/ -q` **129 passed** · ruff 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 23:40:02 +09:00
eomsangdonandClaude Opus 5 3762a06b25 fix(B09): 넓은 필터가 정상 자원 70건을 지우고 있었음 — 조회 우선으로 바꿈
메인의 `막자갈`→배합 `자갈` 오탐 사례를 전해 듣고 내 필터를 재 봤더니 **같은 병이 있었음.**

- **실측** — `is_non_resource_label()` 이 머리글 낱말을 **부분일치**로 보고 있어
  `건설기계운전사`·`일반기계운전사`·`작업반장`·`인력운반공`·`비계공`·`계장공` 등
  **정상 자원 70 / 745** 를 「자원 아님」으로 지우고 있었음(「계」·「작업」·「인력」에 걸림).
  그 탓에 **매칭 14건이 조용히 없어졌음**.
- **고침 둘**
  ① 머리글 판정을 **정확 일치 + 머리글 낱말 조합**(「단위작업별」·「위치및면적」)으로 좁힘.
  ② **카탈로그 조회를 필터보다 먼저** 함 — 카탈로그에 있는 이름은 **정의상 자원**이라,
     필터가 넓어져도 정상 자원이 안 사라지는 구조가 됨.
- **결과** — 매칭 91 → **106**(노무 100 · 기종 6). 산출 파일 다시 냄.

**오탐 짝 시험을 함께 넣음** (「걸려야 한다」 + **「걸리면 안 된다」**)
- 머리글 필터 — 정상 자원 8종은 안 먹고 머리글 7종은 잡는지.
- ㉡ 무대 — 이름에 「운반」이 든 `도자운반`·`덤프운반` 줄은 **안 걸리는지**
  (판정을 이름이 아니라 `equipment` 정확 일치로 하는 근거).
- ㉣ 효율 — 손료계수 0.0002085·조종원 0.125 처럼 **0~1 이지만 효율이 아닌 값**은
  안 걸리는지(효율 자리로 들어올 때만 막는 근거).

**덤으로 잡은 것** — 상세가 하나도 안 붙는 일위대가가 **제목만 서서** 「상세 줄이 없어
단가를 못 조립」하는 상태가 있었음. **붙을 상세를 먼저 모으고 없으면 제목도 안 세움**
(일위대가 67 · 건너뜀 1). 전수 시험(`모든 일위대가 총액 > 0`)이 이걸 잡았음.

PLAN 9-6 에 ㉤(열 방향 검사, 이중계상 규칙이 아니라 표 정합 검사)과 이번 필터 교훈 기록.

자체검증 — `pytest tmp/tests/ -q` **123 passed** · ruff 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 23:33:42 +09:00
eomsangdonandClaude Opus 5 34d90a14d1 feat(B09): 기계경비(S→X) + 기종 카탈로그 매칭 (PLAN 9-3)
**`B09_Estimation_MachineCost.py` 신설 — 취득가 → 시간당 사용료 두 단계**
- `mach_base_2026.json` 실사: `mach_price` **613 기종**(`machine_code`+`specification`),
  `mach_loss_coef` 387건(시간당 손료계수·내용시간·연간표준시간).
- **시간당 손료 = 취득가 × 손료계수.** 취득가가 **천원 단위**라 환산을 놓치면 1,000배
  틀리는 자리 — 테스트로 박음. 굴착기(무한궤도) 0.7㎥ → **24,554원/hr**
  (STC 2024 관측 23,128 과 같은 자릿수, 취득가 판 차이로 설명됨).
- ⚠ **빠진 성분을 0 으로 안 때움** — `mach_fuel_rate`·`mach_operator_map` 이 **0건**이라
  연료(재료비)·운전사(노무비)를 못 채움. `HourlyMachineCost.gaps` 로 **공백을 알림**.
  실측 비중이 노무 53·재료 20·경비 27 % 라 손료만 쓰면 **4분의 1**이 됨 — 조용히
  총액에 섞이면 안 되는 자리.
- 손료계수 없는 기종 **230건**도 0 으로 안 때우고 멈춤.

**자원 축에 기종 매칭 추가**
- 기종 셀은 괄호 안에 **형식과 규격이 섞여** 있음 — 「굴착기(무한궤도, 0.7㎥)」는
  이름 `굴착기(무한궤도)` + 규격 `0.7`. 형식은 이름의 일부이고 숫자 조각만 규격임.
- **규격이 옆 칸에 있는 표**가 많아(`['굴착기 (무한궤도)','굴착기(무한궤도,0.2㎥)','hr',…])
  뒷 칸에서 규격 후보를 찾아 고름. 규격 없이 매칭 성공으로 치지 않는 규칙은 그대로.
- 산출 갱신 — 매칭 86 → **91행**(노무 86 + 기종 5), 미매칭 274 → **269건**.

자체검증 — 신규 7건 포함 `pytest tmp/tests/ -q` **104 passed** · ruff 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 20:43:19 +09:00
eomsangdonandClaude Opus 5 6e7570eba6 feat(B09): 자원 축 매칭 — 공종 축에 자원을 붙여 별도 파일로 냄 (PLAN 8-6·9-3)
메인 창의 공종 축(`resources/data_work_item_master/`)은 **읽기만** 하고, 결과는
**내 소관 경로** `resources/data_cost_resource_axis/` 에 냄 — 메인이 품셈을 다시
돌리면 그 폴더가 덮이므로 안에 섞으면 사라짐.

- ⚠ **`pum_form` 을 먼저 봄** — `productivity` = 1 ÷ 값 · `requirement` = 값 ÷ 기준수량.
  **뒤집으면 20배 틀림.** 형태를 모르는 표(`undetermined`)는 **값을 안 씀**, 한쪽으로
  단정하지 않고 멈춤. 테스트가 뒤집힘을 자릿수로 잡음.
- `coefficient`(19)·`reference`(94)는 공종이 아니므로 **일위대가 항목으로 안 세움**.
- **규격이 없으면 매칭 성공으로 안 침** — 「굴착기」와 「굴착기 0.7㎥」는 단가가 다름.
  이름이 여럿이면 규격 없이는 못 고르고 `unmatched` 로 감.
- **못 맞춘 것은 빈칸이 아니라 목록** — 다만 표 머리글·소계·기호(`f`·`E`)·규격 구간
  (`10∼12`·`50이상`)·절번호는 자원이 아니므로 먼저 걷어냄. 안 걸렀을 때 1,550건이던
  목록이 **274건의 실제 공백**으로 줄어 쓸 수 있는 목록이 됨.

산출 — 매칭 **86행**(노무, 7직종: 보통인부 59·특별인부 19·조경공 4 등) ·
못 맞춘 **274건**(상위: 치즐소모량·자재·굴착기(무한궤도) 등).
⚠ **노임 카탈로그만 있어 노무만 맞음** — 기계·자재 카탈로그가 아직 없어 그 계열은
전부 못 맞춘 목록으로 감. 사유 문구에 그 사실을 적어 「이름이 틀림」과 구분함.

자체검증 — 신규 12건 포함 `pytest tmp/tests/ -q` **97 passed** · ruff 통과 · 409줄.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 20:36:59 +09:00