chore: 네 창 작업 269건 main 반영 (2026-09-09) #13

Merged
eomsangdon merged 269 commits from main_desktop_1 into main 2026-09-09 18:21:28 +09:00
Owner

네 환경 브랜치가 모두 같은 내용으로 수렴한 상태에서 main 으로 올림.

주요 — 지침·계획서 정리 · docs git 전환 · 시험 resources/tester 이관 · B07 표준도 일곱 종류 · B08/B09 결함 열셋 정정

🤖 Generated with Claude Code

네 환경 브랜치가 모두 같은 내용으로 수렴한 상태에서 main 으로 올림. 주요 — 지침·계획서 정리 · docs git 전환 · 시험 resources/tester 이관 · B07 표준도 일곱 종류 · B08/B09 결함 열셋 정정 🤖 Generated with [Claude Code](https://claude.com/claude-code)
eomsangdon added 269 commits 2026-09-09 18:21:13 +09:00
사용자 지적 — 창을 줄이면 내용이 밖으로 나가고 글자를 못 읽었음.

원인은 세 자리의 **고정 최소폭**과 flex 기본값이었음.
- 계획노선|지형 2열이 `repeat(2, minmax(0,1fr))` 로 **고정**이라, 좁아지면 각 열이
  카드 하나도 못 담고 넘쳤음 → `auto-fit` + `min(360px,100%)` 로 바꿔 스스로 1열로 접힘.
- 카드 격자 `minmax(260px,…)` · 고르는 줄 `minmax(200px,…)` 는 그 폭 아래에서 넘침
  → `min(…, 100%)` 로 컨테이너까지만 줄어들게 함.
- 카드 머리줄에 min-width/max-width 를 주어 배지·[선택]·[×] 가 안 밀려 나가게 함.
- 페이지 몸통(flex)에 min-width: 0 — 안 주면 안쪽 격자가 넘칠 때 몸통이 통째로
  가로로 밀렸음.

실측(공용 브라우저): 폭 1400·1000·760·620·480 에서 여섯 컨테이너 모두 **넘침 0px**,
페이지 가로 스크롤 없음(scrollWidth = clientWidth). 트랙 폭도 확인 —
1400/1200 은 580·580(남는 트랙 0px), 1000·820 은 2열, 700 이하 1열.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
창 넷이 DB·저장소를 함께 써 겹침이 실제로 생기는 자리다. 청크·임시배치 갈래에만
있던 보호막 둘이 직행 `/files` 갈래에는 빠져 있었다.

- `is_analysis_running` 가드: 분석 중 업로드를 409 로 막는다. 없으면 분석 2개가
  같은 산출물 경로에서 부딪힌다.
- `supersede_previous_input_files`: 같은 이름 옛 행을 SUPERSEDED 로 내린다.
  없으면 같은 파일이 두 줄로 활성이라 어느 것으로 도는지 순서에 달린다.

세 갈래가 같은 보호막을 쓰는지 지키는 시험을 `tmp/tests` 에 남김.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B08 의 「확정 없이 다음으로」 단추가 B08 화면 안에 있어, 상세설계(B07)에서
B08 로 못 넘어가면 그 단추에 닿을 길이 없었음(닫힌 문 안에 열쇠).

- 단계 표시줄이 NOT_STARTED·STALE 을 막던 것을 개발환경에서만 품
- 열어 둔 단계는 「확정 전이라 값이 비어 보일 수 있음」을 툴팁으로 알림
- 잠금을 푸는 것이 아니라 가기만 하는 것 — 실제 우회는 B08 의 그 단추가
  서버(common_util_dev_unlock)로 하고, 운영에서는 ENVIRONMENT 로 거절

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
무한 로딩으로 보이던 자리가 둘이었음.

1) 미리받기가 클릭 앞을 막음 (진짜 원인)
   진입 직후 도면 31 장을 순서대로 미리 받는데, 한 장이 0.3~1.0초라
   그 사이 클릭한 도면이 앞의 여러 장 뒤에 줄을 서서 30초 넘게 안 열렸음.
   화면은 「불러오는 중」 그대로였음.
   - 클릭이 도는 동안 미리받기가 쉬게 함
   - 클릭이 이미 받아 둔 장은 건너뜀

2) CAD 가 아무 말도 안 하면 끝이 없었음
   끝을 알리는 것이 drawing-loaded · drawing-error 두 통지뿐이라,
   iframe 이 안 뜨거나(ready 없음) 도면을 여는 중에 멈추면 영원히 돎.
   - 지켜보는 시계 추가 (ready 20초 · 도면 15초)
   - iframe 자체가 못 뜨면 기다리지 않고 바로 끊음
   - 화면 표시만 끊고 요청은 살려 둠 — 늦게 오면 그대로 받음

곁들여 B07 의 「모든 도면 확정 뒤에 이동」 가드를 개발환경에서만 품
(B09 로 가는 길. 운영에서는 그대로 막음).

확인: 단계 표시줄 B08·B09 가 눌리고 B07 → B08 이동됨. tsc 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실측(창 620) — .b09-main 이 1,190px 밀려 나감. 원인이 세 겹이었음.

- .b09-main · 표를 감싸는 body 칸에 min-width: 0 이 없었음. flex 자식 기본 최소폭이
  auto 라 안쪽 표의 최소폭(칸이 nowrap)을 그대로 물었음.
- ⚠ 진짜 원인은 그 아래였음 — .b09-sheet 가 **감싸는 칸(div)에 붙는 자리와 표(table)에
  바로 붙는 자리**가 둘 다 있음(내역서·자재대는 표에 직접). 표에는 overflow 가 안 먹어
  표 폭만큼 바깥이 밀렸음. table.b09-sheet 를 블록으로 바꿔 제 안에서 가로로 넘어가게 함.
- 주석에 백틱을 쓰면 템플릿 문자열이 끊김 — 그 사실을 주석에 남김(한 번 겪음).

실측: 다섯 탭(공사원가계산서·설계내역서·일위대가·단가산출근거·관급·사급) × 창 1400·620
전부 몸통 가로밀림 없음·넘침 0px, 표만 제 안에서 스크롤.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
업로드 하나가 그 프로젝트의 설계 산출물·초기값 스냅숏을 되돌릴 수 없게 지운다.
창 넷이 한 프로젝트를 볼 수 있어 말없이 지우면 남의 작업이 사라진다.

- `describe_existing_outputs`: 지워질 것을 사람 말로 낸다(전처리·노선·횡단·도면·
  수량·원가·초기값). 빈 폴더는 세지 않는다.
- 지울 것이 있는데 확인이 없으면 409 `confirm_required` — 무엇이 지워지는지 함께 준다.
- 세 갈래(직행·청크·보관함 연결) 전부에 `confirm_replace` 를 붙임.
- ⚠ 기본값은 확인 켬(True) — 자동 절차(체인·스크립트)는 물음에 안 걸린다.
  사람이 올리는 라우터만 False 로 불러 확인을 받는다.
- 화면: 409 를 받으면 「되돌릴 수 없습니다」와 지워질 목록을 보이고 한 번 묻는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실사용 확인에서 청크 세션 생성이 NameError 로 500 이 났다. 세 갈래가 확인
단계 이름을 다 들고 있는지 지키는 시험을 추가.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ 「넘침은 0 인데 못 읽는」 자리였음. 표가 자기 스크롤 안에서 잘려 넘침 수치로는
안 잡히고, 실제로는 좌측 패널(320 고정)과 진행단계 패널(fixed)이 화면을 덮고 있었음.

실측(B08, 본문에 남는 폭)
  860px  348 → 388     760px  248 → 288
  620px  108 → 175     500px    4 → 194
  1400·1000 은 그대로 (넓은 화면 배치 안 건드림)

방법 — 패널을 비율(vw)로 줄이면 좁아질수록 본문도 같이 줄어 결국 못 읽음.
그래서 **본문에 남길 폭**(--wf-min-content-width: 320px)을 정하고 패널이 그만큼
물러나게 함. 좁은 폭 전용 패널 폭(--wf-left-panel-narrow-width: 280px)도 따로 둠.
진행단계 패널은 폭을 줄이고 아래로 내려 본문 윗부분(탭·표 머리)을 안 가리게 함.

확인 — B03·B05·B06·B07·B08·B09 를 1400·760 두 폭에서 훑음. 문서 넘침 전부 0,
넓은 폭 배치 변화 없음(좌측 320 유지).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
공용 오버레이가 좁은 폭에서 좌측 패널을 320 에서 280·227·182 로 물리면서(ef4cdb66)
2열 칸이 128.8 에서 108.8·82.4·60px 까지 줄어 도면 이름이 말줄임으로 잘렸음.
문서 넘침은 0 이라 수치로는 안 잡히는 자리 — 잘린 것이 `overflow: hidden` 안이라서.

실측 (도면 31장, 잘린 이름 수 · 고치기 전 → 뒤)
  1400·1000    0 → 0   (2열 128.8px 그대로 — 넓은 폭 배치 안 건드림)
  860·760·620  1 → 0   (1열 221.6px)
  560         16 → 0   (1열 168.8px)
  500         19 → 2   (1열 124px)

남은 2건은 횡단도 격자 밖(「계획평면도(노선배치도)」 등)이고 폭 500 에서만 남음 —
그 폭에서 패널이 182px 까지 물러난 결과라 공용 오버레이 몫.

`repeat(auto-fit, minmax(120px, 1fr))` — 가장 긴 이름 107px + 단추 안여백·테두리
20px 를 문턱으로 잡음. 넓은 폭에서는 두 칸이 들어가 배치가 그대로임.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ 인라인 좌표는 미디어 규칙보다 세다. 넓은 화면에서 끌어 둔 자리가 좁은 화면에도
그대로 남아 본문을 덮었음(앞 커밋으로 폭은 줄였으나 자리는 그대로였음).

- 좁아지면 인라인 좌표를 **떼어** CSS 자리로 보냄. ⚠ **저장값은 안 지움** —
  지우면 사용자가 맞춰 둔 자리가 사라져 더 나쁨.
- 넓어지면 **끌어 둔 자리를 되찾음.**
- ⚠ 좁은 폭에서 사용자가 직접 끌면 **그 뜻이 이김** — 규칙이 다시 덮지 않음.
  그 자리는 **저장하지 않아** 넓은 화면 자리를 밀어내지도 않음.

실측(진행단계 패널, 저장값 {left:420, top:300} 을 심어 두고)
  1400  420/300 (끌어 둔 자리)        저장값 유지
   760  물러남 · 본문 남음 288px      저장값 유지
   500  물러남 · 본문 남음 194px      저장값 유지
   620 에서 직접 끌기 → 410/309 로 붙고, 폭을 600 으로 바꿔도 그 자리 유지
  다시 1400 → 420/300 되찾음 · 저장값 안 바뀜

곁들여 — 좁은 폭 진행단계 규칙에서 `top: auto; bottom: …` 을 뺌. 위·아래가 함께
잡혀 패널이 화면 높이만큼 늘어났음(실측 717px). 폭만 줄이고 자리는 그대로 둠.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
접었을 때 머리·본문만 감추고 요약줄은 남아, 폭 0 인 패널에서 글자가 64px 밖으로
새어 나왔다(폭과 무관하게 늘 같은 값 — 좁은 폭 문제가 아니라 그 자리 결함).
감추는 목록에 요약줄을 더한다.

확인: 접힘에서 display:none·넘침 0, 펼침에서 이전과 같음(넘침 0).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ 앞 커밋의 「본문에 320 을 남긴다」가 폭 500 에서 패널을 **180px 로 눌러** 목록
이름이 잘렸음(랩탑 보조 실측: 잘린 이름 2건). 폭을 반씩 나누면 **둘 다 못 쓰는
화면**이 됨.

- CSS ≤560 — 패널을 **안 줄임**(280px 유지). 본문 밀기는 이미 ≤860 에서 꺼져 있어
  패널이 **본문 위에 겹쳐** 뜨고, 읽을 때는 손잡이로 접음. 폭 500 에서 잘린 글자 0.
- TS — 정한 적이 없고 화면이 아주 좁으면(≤560) **접은 채로 시작**함. 펼친 채로 열면
  본문이 가려진 화면부터 보게 되기 때문임.
- ⚠ **사용자가 정한 적이 있으면 그 뜻이 이김** — 저장값이 있으면 그대로 따름.
- ⚠ **처음 앉힐 때는 저장하지 않음** — 좁아서 접은 것을 「사용자가 접었다」로 적으면
  넓은 화면으로 돌아와도 접힌 채로 남음.

실측
  정한 적 없음 + 500  → 접힘 true · 저장값 null (기록 안 남김)
  정한 적 없음 + 1400 → 접힘 false · 저장값 null
  「펼침」 정해 둠 + 500 → 접힘 false (사용자 뜻이 이김)
  잘린 글자 860·620·560·500 전부 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
창폭 480 에서 좌측 패널이 237 까지 물러나면 「횡단 반폭(m)」 라벨이 안 줄어
`.ui-field` 가 2px 넘쳤다(공용 `.ui-field` 는 안 건드리고 내 행에서 처리).

- `@media (max-width: 560px)` 에서만 라벨을 윗줄로 접는다.
- ⚠ 폭 제한 없이 `flex-wrap` 을 주면 넓은 폭에서도 라벨이 윗줄로 올라간다 —
  실제로 재 보고 되돌린 뒤 폭 조건을 붙였다.

확인(1400·760·620·480): 넘침 0 · 잘린 라벨 0 · 가로 스크롤 0,
넓은 폭 높이 42(한 줄) 유지, 480 에서만 68(두 줄).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 재확인(2026-09-09)으로 값 확인. `EARTHWORK_HAUL_EQUIPMENT_LIMITS_M` 의
dozer 는 2026-09-08 에 이미 60 으로 바뀌었는데 바로 위 설명만 70 으로 남아 있었음.
읽는 사람이 설명을 믿고 70 으로 오해할 자리라 맞춤. 동작 변화 없음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ 빠뜨리고 있던 줄임 — 지식DB `구조물_기초_토공.md` [구현] 이 「구조물 토공 수량 항목:
터파기·**버림콘크리트**·되메우기·뒤채움·잔토처리」로 이미 지목해 두었고, 실무 시트도
같은 공종에서 버림 유무로 0.30 ↔ 0.20 ㎥/㎡ 로 갈렸음.

근거(원문 열어 확인)
  두께 KDS 44 90 00 「구조물 시공이 원활하도록 **100 mm 두께**의 버림콘크리트를 타설」
  폭   KCS 34 50 05 「두께는 설계도서에 따르며, **폭은 잡석다짐의 폭과 동일**하게 한다」

⚠ 잡석다짐 폭이 아직 없어(기초잡석은 품셈에 공종만 있고 치수가 없음) **터파기 폭을
잠정**으로 쓰고 근거 문구에 그 사실을 적음 — 정해지면 상수 한 줄만 바꾸면 됨.

- 기본은 **넣음**, 저장 제원에서 「안 넣음」이면 뺌(확정 ⑭ 「기본 보이게, 뺄 수도 있게」).
  ⚠ 빈 칸을 「빼기」로 읽지 않음 — 정한 적 없는 프로젝트에서 줄이 사라지면 안 됨.
- 돌쌓기·큰돌쌓기 둘 다. 옹벽은 관측 원단위에 이미 0.15㎥/m 로 있었음.
- 타설 줄은 **버림 몫만** 셈 — 채움 콘크리트는 그 공종 품에 들어 있을 수 있어 제외 유지.

시험 743 통과(새 6건 포함).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정(2026-09-09): 층따기 단위는 ㎡. 대신 그 면적이 B06 설계에서 나와야 한다.

- `_bench_cut_length`: 성토(diff<0) 구간에서 원지반 횡단기울기가 **1:4 보다 급한**
  조각만 골라 지표면을 따라간 길이(빗변)를 더한다. 절·성토 경계는 영교점까지만 센다.
  근거는 별표2·교본 6장 4절, 지식DB 성토_비탈면 §4 [구현].
- 결과에 `bench_cut_length_m` 을 실어 B08 이 측점 사이를 평균단면적법으로 이어 ㎡ 를 낸다.
  ⚠ 여기서 ㎥ 로 바꾸지 않는다 — 단의 높이·폭은 설계도서 값이라 지어낼 수 없다.
- 파이썬·TS 짝을 함께 고침(`common_util_cross_design_areas.ts`). 거울 테스트 통과.
- ⚠ 성토 비탈면 길이가 아니라 **원지반 표면**을 센다 — 층따기 대상 면이 그쪽이다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
법이 요구하는데 우리가 안 내던 줄들임 — 국가지점번호판·안내판·차단기·가설창고·수방자재.

⚠ 개소를 **지어내지 않음.** 임도규정 제26조제5항이 「500미터 마다 설치·관리하되
**필요시 거리를 조정**할 수 있으며」라 하고 기점 포함·종점 잔여·갈림길 중복을 원문이
정하지 않음 ⇒ `연장÷500` 을 산식으로 쓰지 않고 설정 `ancillary_counts` 로 **개소를 받음**.

⚠ 사유를 **갈라 적음** — 「품셈에 그 이름의 공종이 없음」과 「개소 미입력」은 다음에 할 일이
다름. 법정 의무인 둘(번호판 제26조5항 · 안내판 제26조6항)은 그 사실을 사유에 적어
화면에서 왜 채워야 하는지 보이게 함. 차단기는 교본에만 있어 「법정」이라 적지 않음.

⚠ 다섯 중 **품셈에 공종이 있는 것은 가설창고(FP-11-01) 하나뿐**(마스터 전수 확인).
나머지 넷은 금액이 못 서지만 **줄은 세움** — 빼면 빠진 줄을 아무도 못 봄.
개소를 안 넣어도 줄이 서고 사유가 함께 감(준비공 표 · 인계 양쪽).

시험 749 통과(새 6건 포함).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 12번 「내야 할 표 16개 전체」. 안 내던 일곱 중 넷을 냄.

- 서식은 지어내지 않고 실무 내역서(영월 기번6·봉화 기번41) 같은 이름 시트를 그대로
  옮김 — 코드번호·명칭·규격·단위·단가·비고. 중기목록표만 합계 + 3분할(노무·재료·경비).
- ⚠ 경비목록표는 취득가(천원)이지 시간당 손료가 아님. 실무 실측
  「S00104 불도저(무한궤도) 19톤 천원 184,499」와 자릿수를 맞춤 — 손료를 실으면
  세 자리 어긋난 채 「경비」로 읽힘.
- 자원 집계표(역집계)도 함께 냄. 일위대가 안쪽을 한 겹만 폄 — 기계 사용료를 다시
  손료·연료로 쪼개면 중기 집계표와 이중계상이 됨. 비율 줄(제잡비)은 자원으로 안 셈.
- 집계표는 반올림, 내역서 본체는 절사 — 어긋나는 것이 정상임을 문구로 함께 냄.
- 새 계산 없음. PriceBook 자료를 접기만 함.

실무 대조(2024 대 2026 자료): 보통인부 165,545→172,068 · 불도저19 취득가
184,499→198,150 · 시간당 126,029→124,842. 연도 차이 범위 안.

라우터 조회 하나 추가(GET .../estimation/base-data). 시험 8건, 262건 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 5번(2026-09-09 「진행해줘」)의 1단계. 실무 원본 `07-구조도-소광리.xlsx`
53탭을 펴서 표 짜임을 확정한 뒤, B08 원단위 전개를 그 모양으로 접는 통로를 냄.

⚠ 계산은 새로 만들지 않음 — `build_unit_table` 결과를 제원 조합으로 묶고 단위당으로
나눌 뿐임(계산 자리는 한 곳, CLAUDE.md 5장).

장 나눔 축 = 제원 조합(`type_id` + 높이 + 제원 전부). 확정 ⑨ 대로 기울기가 바뀌면 장이
갈림 — 기울기가 제원의 한 칸이라 저절로 지켜짐. 측점·방향처럼 개소마다 다를 뿐인 칸은
장을 안 가름(`PER_PLACE_OPTION_KEYS`).

선행 확인 두 건도 끝냄
  · 8-3 틈메우기돌 — 53탭 전수에서 `틈메우기`·`틈막이`·`사춤` 0건 ⇒ 넣지 않음
  · 8-2 버림 콘크리트 — 실무에 있음(「바닥 10㎝ 이상 콘크리트(버림)」 · 옹벽 버림CON'C),
    KDS 44 90 00 의 100㎜ 와 같음

⚠ 만들다 잡음 — `billing_unit` 이 비어 있으면 「단위 미정」이 아니라 「m·연장」이라는
계약이 있었음(`StructureQuantity`). 미정으로 읽어 돌쌓기가 전부 단위 없는 장이 됐음.

⚠ 실무 시트와 어긋나는 줄 일곱은 PLAN 4-12 에 표로 남기고 확정 대기로 둠 —
임의로 맞추지 않음(터파기 0.35 대 2.30 이 가장 큼).

자체검증 — 새 시험 11건 통과, 회귀 562 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ **면이 달랐음.** 층따기는 성토부 **아래 원지반**을 계단으로 깎는 일인데(교본 6장 4절)
우리는 **성토 비탈면 길이**를 밑수로 쓰고 있었음. 값이 나오므로 아무 시험도 안 잡던 자리.

B06 설계가 측점마다 내는 `design.bench_cut_length_m`(원지반 표면의 경사길이, 원지반
횡단기울기 1:4 보다 급한 조각만)를 그대로 밑수로 씀. 면적은 종전대로 **평균단면적법**.
⚠ 값이 없는 측점은 **0** — 성토 사면길이로 대신 채우지 않음(다른 면을 세게 됨).

⚠ 단위는 **㎡ 그대로**(사용자 확정 ⑦). ㎥ 로 바꾸지 않음 — 단의 높이·폭은 설계도서 값이라
지어낼 수 없음. 앞서 「품셈 밑수가 ㎥ 라 못 곱함」으로 막아 둔 자리는 이 확정으로 풀림.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 에는 「품셈 공식이 ㎥ 인데 우리는 ㎡」라 막아 두었음(410만원 자리).
사용자가 **㎡(실무 관행)**로 확정했으므로 매핑 밑수를 ㎡ 로 바꾸고 막힘을 풂.

⚠ 어긋남 자체는 사라지지 않았으므로 매핑에 **그 사실과 까닭을 적어 둠** —
품셈 9-18 [주]는 `Q1 = … = ㎥/시간` 이라 공식은 체적 기준이고, 단의 높이·폭이
설계도서 값이라 체적을 지어낼 수 없어 면적으로 감. ⇒ **받는 쪽이 ㎡ 단가를 세워야 함**
(㎥ 단가를 그대로 곱하면 금액이 틀림).

옛 시험 둘이 「층따기는 막힌다」를 계약으로 못 박고 있어 정정.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
돌은 기본 「캔다」(별표2 「야면석 등은 **가급적 현장에서 채취·사용**하도록 운반거리를
조사한다」 · 실무 견적 다섯 권에 야면석 구입 단가 0건). 구조물마다 「구입」으로 바꿀 수 있음.

⚠⚠ **채집석 공제는 사토에서 한 번만 뺀다.**
B08 은 소요량(`collected_stone_deduction_m3`, ㎥ **양수**)을 내기만 하고 공제하지 않으며,
빼는 자리는 유토곡선의 사토뿐임 — 실어 내는 몫(spoil_m3 − natural_spoil_m3)에서 먼저 빼고
모자라면 자연방토에서 뺌. (랩탑 메인의 통로에도 같은 문장을 박아 둠 — 두 곳이 같은 말이라야
나중에 누가 봐도 안 갈림.)

⚠ **부호를 넘기지 않음.** 실무 시트가 `−274.66` 이라 그대로 넘기면 두 번 뒤집힘.

밑수 — 면석 몸통(면적×뒷길이×몫) + 고임돌 + 막자갈. **이미 우리 식 안에 있는 값들**이라
새 수치를 지어내지 않음. 목적지는 `haul_deduction` 이라 자재총괄(`material` 만 모음)에
안 섞임. 인계 맨 위에 구조물 합산 한 값으로 실림.

시험 754 통과(새 6건 포함).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
네 창 합의 문구 그대로 못 박음:

    채집석 공제는 사토에서 한 번만 뺀다.
    B08 은 소요량(collected_stone_deduction_m3, ㎥ 양수)을 내기만 하고 공제하지 않으며,
    빼는 자리는 유토곡선의 사토뿐이다 —
    실어 내는 몫(spoil_m3 − natural_spoil_m3)에서 먼저 빼고 모자라면 자연방토에서 뺀다.

- `computeHaulPlan` 이 공제를 받아 **잔량 하나하나**를 줄인다 — 총량만 줄이면 사토
  balloon·운반거리가 안 따라간다. 지반유형 안분도 같은 비율로 줄인다.
- ⚠ `null`(아직 안 옴)과 `0`(공제 없음)을 가른다. 결과에 받은 값과 실제로 뺀 값을 함께 싣는다.
- 서버 진입점·파이썬 context 를 통로로 이어 둠. B08 이 값을 내면 실어 주기만 하면 됨.

시험 3건(공제 반영·잔량 동반 감소·사토 초과 시 사토까지만·자연방토는 나중) 을
TS 를 실제로 돌려 확인.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실무 내역이 「레미콘타설(장비) **무근,버림**」으로 갈라 적음(봉화 제50호표,
2026-09-09 데스크탑 보조 확인). 같은 공종·같은 단가라 **금액은 안 움직이고 이름만 맞춤** —
받는 쪽이 그 갈래로 일위대가를 그대로 세울 수 있게.

⚠ 버림은 늘 무근이라 구조물 종류(무근/철근)를 따라가지 않음. 그래서 버림 몫만 따로
모아 갈래 이름을 「무근,버림」으로 냄. 나머지 콘크리트는 종전대로 구조물 종류로 갈림.

검증 프로젝트 실측 — 돌쌓기 셋·큰돌쌓기 하나의 버림이 한 줄로 모여 4.700㎥.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
별표2 Ⅰ.1.나.(5) 「측구터파기 단면적」이 횡단도 표의 법정 칸인데 한 값뿐이라
「측구 토사 / 측구 암석」 두 칸이 반만 채워졌다.

- 가르는 근거는 **절토 분리와 같은 것**(지반 유형 + 암반 경계선). 새 입력을 만들지 않았다.
- 측구 상단에서 암반 경계선까지의 깊이로 공칭 도형(사다리꼴·L형)을 가로로 가른다.
- ⚠ 근거가 없으면 **나누지 않는다.** 사유를 `ditch_split_basis` 로 함께 냄:
  rock_boundary / soil_ground / rock_ground_no_boundary / no_ditch.
- 기존 `ditch_area_m2` 는 **합계로 그대로** 두고 갈래를 덧붙였다 — B08 이 순서대로 옮겨 갈 수 있게.
- 파이썬·TS 짝을 함께 고침. 거울 테스트 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
별표2 Ⅰ.1.나.(5) 가 요구하는 여덟(지반고·계획고·절토고·성토고·단면적·지장목 제거·
측구터파기 단면적·사면보호공) 중 뒤 넷이 빈칸으로 나가던 자리.

빈칸의 까닭은 「값이 없어서」가 아니라 **통로가 없어서**였음 — 표가 `source["quantities"]`
를 보는데 그 키가 원본 파일에 아예 없음(실측: 횡단 원본 15키에 `samples`·`center_z`·
`chainage_m` 은 있고 `quantities` 는 없음). 반면 저장된 설계에는 단면적이 그대로 있고
사면길이도 설계선에서 유도됨.

⚠ 계산을 새로 짜지 않음 — 단면적은 B06 저장값을 그대로 읽고, 사면 계열은 B08 이 쓰는
`station_slope` 를 그대로 부름. 계열 이름·어느 면을 쓰나도 `SlopeArea` 정의를 빌림
(거기서 밑수가 바뀌면 이 표도 같이 움직여야 함).

채운 열 칸
  단면적 3   깍기 토사 · 깍기 암석 · 쌓기
  사면   7   층따기 · 면고르기(성·절) · 지장목제거(성·절) · 성토파종 · 절토살포

⚠ 사면 칸의 단위 — B08 은 측점 사이를 적분해 ㎡ 를 내나 그것은 두 측점이 있어야 나옴.
한 장짜리 횡단도에 들어가는 것은 그 측점의 **사면길이(m)** 이고 1m 폭 조각의 ㎡/m 와
수치가 같음. 표기를 m 로 볼지 ㎡/m 로 볼지는 표기 문제이고 값은 하나임.

안 채운 칸 — 근거가 없어 임의로 안 넣음
  측구 토사/암석(저장값이 `ditch_area_m2` 한 값뿐) · 표토제거(두께 칸 없음) ·
  편책(별도 일위대가 제작 뒤 연결로 확정) · 제근(입목 본수 안 듦) · 노면다짐

자체검증 — 새 시험 8건(사면길이는 손으로 잰 √5 · √(2.4²+2²) 와 대조, `is not None`
만 보면 0 이어도 통과하므로 실수치로 맞춤), 회귀 570 통과 · 0 실패.
실프로젝트 936be972 세 측점에서 **21칸 중 14칸**에 값이 찍힘(앞서 4칸).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「표가 났는데 안 보이면 낸 것이 아님」. 꺼져 있던 탭 둘을 켜고 표를 붙임.

- 새 파일 B09_Estimation_UI_BaseData.ts — 화면 조립부가 이미 1,200줄을 넘어 분리.
  상태를 안 들고 그리기만 함.
- 기초자료 탭: 노무비(118)·재료비(1)·경비(613) 목록표. 중기 탭: 중기목록표(5).
- ⚠ 빈 표를 그냥 두지 않음 — 재료비목록표가 한 줄뿐인 사유를 표에 띄움.
  「다 채운 것」으로 읽히면 안 됨.
- ⚠ 계산 과정을 감추지 않음(8-13) — 조종원 환산이 실무·교본과 다르다는 사실과
  그 영향(기계 든 공종 +19~24%)을 중기 탭에 적음. 잡재료가 연료에 접혀 있다는 것도.
- 경비목록표는 취득가(천원), 시간당 사용료는 중기 탭이라는 안내를 달았음.

실측(공용 브라우저): 기초자료 표 3장 732줄 · 중기 5줄, 사유 문구 넷 다 뜸.
⚠ 백엔드 재시작이 있어야 새 조회가 붙음(재시작 전 404 → 후 200).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
랩탑 메인이 측구를 갈라 냈으므로(`6a7c339f`) 그 값을 그대로 옮김.
여기서 다시 가르지 않음 — 근거가 없는 측점은 B06 이 나누지 않고 사유를 함께 냄.

`split_basis()` 를 함께 둠 — `ditch_split_basis` 를 사람이 읽는 말로 바꿔 준다.
⚠ 표 칸은 숫자만 담으므로 이 말은 표 밖(주기·화면)에 실어야 함.
「전량 암」이 경계선을 못 찾아서인지 정말 암 지반이어서인지 숫자만으로는 구별 안 됨.

⚠ 층따기 밑수가 바뀐 것이 이 표에도 그대로 왔음 — 랩탑 메인이 「성토 사면길이」에서
「B06 이 낸 원지반 깎는 길이(`bench_cut_length_m`)」로 고쳤고, 이 모듈이 B08 `_length_of`
를 빌려 쓰므로 **같이 움직였음**. 값이 없는 옛 저장분에서는 0 으로 섬 —
성토 사면길이로 대신 채우지 않는 것이 맞음(다른 면을 세게 됨).

실측(936be972, 옛 저장분) — 여전히 **14칸**. `ditch_split_basis`·`bench_cut_length_m`
둘 다 저장된 설계에 없음(B06 확정 전 자료). 새 키가 있는 자료에서 16칸이 되는 것은
시험으로 확인함.

자체검증 — 시험 11건(측구 두 칸 · 못 가른 측점 사유 · 층따기 밑수 따라가기 추가),
회귀 573 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
엔진(`B08_Quantity_Engine_UnitQuantity.STONE_SUPPLY_KEYS`)은 이미 `stone_supply` 를
읽는데 저장 칸이 없어 저장이 거부됐다(`정의되지 않은 옵션입니다: stone_supply`).
`back_len_cm` 때와 같은 계열 — 읽는 키와 저장 칸이 어긋난 자리.

- 붙인 곳: 돌쌓기(찰·메) · 큰돌쌓기 · 골막이 · 바닥막이 · 기슭막이 여섯.
- 기본 「채집」 — 사용자 확정 ②(2026-09-09) 「기본은 캔다, 구조물마다 바꿀 수 있게」.
  별표2 「석축 등에 필요한 야면석 등은 가급적 현장에서 채취·사용」이 근거.
- 저장 왕복을 실제로 해 봄: PUT 200 → 되읽기에서 `stone_supply="구입"` 그대로 나옴.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ 어제 넣은 `ancillary_counts` 를 **엔진은 읽는데 저장 요청 모양에는 없었음** — 화면에서
넣을 길이 없어 스크립트로만 넣히던 자리였음(`stone_supply` 가 레지스트리에 없어 저장이
거부되던 것과 같은 계열 — **읽는 자리와 넣는 자리가 안 맞는 것**).

`QuantitySettingsBody` 에 칸을 두고, 「통째로 갈아 끼우는 칸」 목록에 넣음 — 병합이면
개소를 **지울 수가 없음**(0 으로 되돌리려면 통째 교체라야 함).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ 앞 커밋(`bfd10b57`)이 `variant_value` 까지 「무근,버림」으로 바꿔 **금액이 통째로
빠졌음**(B09 실측 275,584원 · 본체 합계 9,587,677 → 9,312,093). 품셈 12-1-1 의 갈래는
**무근구조물·소형구조물·철근구조물 셋뿐**이라 「무근,버림」은 **없는 갈래**였음.

⇒ 갈래(`variant_value`·`structure_kind`)는 **무근구조물**로 되돌리고, 실무 줄 이름은
**표시 문구(`spec`·`spec_detail`)에만** 둠. 근거 — 봉화 제50호표가 줄 이름은
「레미콘타설(장비) 무근,버림」인데 **단가는 「무근」과 같음**. 실무도 줄만 가르고 품은
무근 것을 씀.

⚠ 받는 쪽이 문자열을 눅여 읽는 방식은 쓰지 않기로 함 — 그러면 다음 갈래가 조용히
잘못 붙음. **보내는 쪽에서 바로잡는 것**이 맞음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「표준도」를 누르면 도각만 실린 빈 장이 뜨던 것을, 제원 조합마다 표 한 벌을
CAD 표 객체로 그려 낸다. 도각은 두르지 않음(2026-09-08 사용자 지시).

값은 여기서 셈하지 않음 — `build_standard_sheets` 가 낸 것을 글자로 옮길 뿐임.
셈이 두 벌이 되면 도면과 수량서가 갈림(CLAUDE.md 5장).

실화면 확인 (프로젝트 936be972, 구조물 5기를 심고 확인)
  장 4개 · 개소 5 — ①③ 이 같은 제원이라 한 장에 2개소로 모임(장 나눔 실물 증명)
  돌쌓기(찰) H=2.5 뒷길이 45㎝ 깬돌   12줄  2개소·합 20.00m
  돌쌓기(메) H=2.0 뒷길이 35㎝ 야면석 10줄  1개소
  옹벽 H=2.0                          7줄  1개소 (관측 원단위 사유 1줄)
  큰돌쌓기 H=2.5                       5줄  1개소 (막힌 사유 4줄이 표에 그대로 뜸)

⚠ 만들다 잡은 것 — 표 폭을 176㎜ 로 냈더니 단서가 붙은 근거 문구(물구멍관·버림
콘크리트)가 칸을 넘어 수량 칸을 덮었음. 표는 글자를 안 접음. A1 작도 영역
739 × 499㎜ 에 맞춰 735㎜ 로 넓히고 줄 높이 9㎜ 로 잡음 —
**네 장까지** 한 면에 듦(47줄 × 9 + 간격 = 465㎜). 더 늘면 장 나눔(㉢)이 필요함.

⚠ 못 낸 값은 0 이 아니라 「-」 로 적음. 도면에 0 이 찍히면 「없다」로 읽힘.
⚠ 구조물이 없으면 빈 격자 대신 사유 한 줄이 뜸 — 빈 표는 「만들다 만 것」으로 보임.

자체검증 — 회귀 573 통과 · 0 실패. 공용 브라우저에서 표준도를 눌러 실제로 열고
확대해 글자·수치를 읽어 확인함(스크린샷 `tmp/browser/shots/standard_fit.png`).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 12번의 마지막 둘. ③(자재값 출처 둘 다)·⑮(유가 전국/지역)와 한 벌.

- 서식은 실무 시트(영월 기번6) 그대로 — 원천 5칸(단가+쪽수) + 적용(단가+출처) + 비고.
  원천 이름은 코드에 안 박고 PriceBook.slot_names 를 씀(사무소마다 다름, 9-4 미결).
- ⚠ 확정 ③ — 슬롯마다 출처를 남길 자리를 둠(쪽수·업체명·날짜). 값이 없는 원천은
  0 이 아니라 빈칸. 0 이면 「0원짜리 견적」으로 읽힘.
  견적이 국계법 시행령 §9 의 4순위라는 사실을 표가 스스로 밝힘.
- ⚠ 확정 ⑮ — 유가 전국/지역 고르는 칸을 냄. 다만 지역값이 아직 자료에 없어
  「고를 수 없음 + 까닭」으로 드러냄. 없는 값을 지어내지 않음.
- ⚠ 환율및기초자료 인건비 칸은 운전사 셋만. 직종 118개를 다 실으면 노무비목록표와
  같은 표가 두 벌이 됨 — 실무 시트도 셋뿐임.
- 조종원 시간당이 실무·교본과 다른 사실(× 16/12 × 25/20)을 표 비고에 그대로 냄.

라우터 조회 추가(GET .../estimation/price-sources). 시험 5건 추가, 267건 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ 확정 ⑨ 가 통째로 미구현이었음 — 레지스트리에 `face_slope_ratio` 칸이 없어 **늘 1:0.3**
으로 돌았고, 찰 H=2.5 와 메 H=2.0 이 같은 기울기로 나왔음. 우리 0.3 은 실은
**「메쌓기·성토·직고 1.5m 이하」 한 칸**이었음.

품셈 13-4-4 [주]⑪ <표준경사>를 데이터로 두고 **직고 · 메/찰 · 성토/절토** 셋으로 고름.
  메 성토 0.30 0.35 0.40 0.45 0.50 · 메 절토 0.25 0.30 0.35 0.40 0.45
  찰 성토 0.25 0.30 0.35 0.40 0.45 · 찰 절토 0.20 0.25 0.30 0.35 0.40

⚠ 경계값은 **앞 칸** — 원문 표기가 `∼1.5 · ∼3` 이라 이하로 읽음(직고 3.0m → `~3` 칸).
   7.0m 은 `~7`, 그보다 커야 마지막 칸. 해석을 데이터·주석·시험에 함께 박음.
⚠ **성토/절토가 저장에 아직 없음** — 레지스트리에 없는 키를 읽지 않고 **성토 열로 잠정**
   적용하며 **근거 문구에 그 사실을 적음**. 값이 생기면 한 줄만 바꾸면 됨.
⚠ 저장 제원에 값이 있으면 **그 값이 이김**(확정 ⑨). 자동으로 고른 값은 **저장에 안 박음** —
   「정한 적 없음」과 「0.3 으로 정함」이 구별돼야 함.
⚠ 큰돌쌓기는 이 표 대상이 아님 — 교본이 「1:0.3 **이상**」으로만 둠. 그대로 둠.

검증 프로젝트 실측 — 돌쌓기(메) H=2.0 면적 **20.881 → 21.190㎡(+1.5%)**, 찰 H=2.5 는
1:0.3 그대로. 옛 시험 셋이 「늘 1:0.3」을 계약으로 못 박고 있어 기울기를 명시하도록 정정.

시험 761 통과(새 7건 포함).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
표를 냈는데 화면에 없으면 낸 것이 아니라 붙임. 목록표 넷 아래에 A9·A10 두 장 추가.

- 자재단가대비표: 원천마다 「단가·페이지」 두 칸으로 머리글 두 줄, 채택 원천 굵게
- 슬롯 6 이 곧 「적용 단가」라 「적 용」 칸을 따로 세우지 않음 (같은 값 두 번 서는 것 방지)
- 환율및기초자료: 환율·인건비(운전사 3)·단가 및 재료비 세 구획
- 유가 적용 범위 고르는 칸 — 지역 공시가는 자료가 없어 고를 수 없게 두고 까닭 표시 (확정 ⑮)
- 두 표는 목록표와 따로 받아 옴 — 못 받아도 목록표 넷은 그대로 남음
- 시간당 노임이 소수로 남는 까닭을 화면에 밝힘 (여기서 자르면 기계 사용료가 어긋남)

검증: tsc 통과 · pytest 267 통과 · 공용 브라우저 5174 에서 표 6장·줄 737 확인,
body.scrollWidth 1696 < innerWidth 1704 (가로 넘침 없음)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실무 탭이 「위 치수조서 + 아래 수량산출서」인데 1단계에서 아래 표가 섰고 이번이 위 그림.
그림이 붙으면서 한 면에 넉 장을 쌓을 수 없게 돼 **장 나눔(㉢)도 같이** 했음.

장 나눔 — 계획평면도가 쓰는 본 그대로
  `standard_sheet` / `standard_sheet_2` … 제원 조합 하나가 한 장.
  좌측 목록은 `idPrefix` 묶음(계획평면도와 같은 짜임)이고 kind 는 새로 `standard`.
  구조물이 없어도 한 장은 남김 — 단추가 사라지면 「없어진 것」처럼 보이고 사유를 읽을
  자리도 없어짐.

그림 — `B07_DesignDetail_Engine_Cad_StandardFigure.py`
  ⚠ **기울기를 값으로 받음. 0.3 을 그림에 박지 않았음.** `face_slope_ratio` 가 오면 그
  값으로 기울고, 비어 있으면 교본 7-3 기본 0.3 으로 그리되 **「자동 판정 전」이라고 그림에
  적음**. 자동 판정이 붙는 대로 그림이 따라감.
  ⚠ 치수는 수량이 쓰는 그 상수(`STONE_MASONRY`)를 직접 읽음 — 여기서 다시 적으면 그림과
  표가 갈림. 상부 0.45+0.10H · 하부 0.45+0.40H · 터파기 폭 평균두께+0.2 · 되메우기 0.2.
  ⓘ 그 상수는 **뒷면이 수직인 1:0.3 벽**을 뜻함(하부−상부 = 0.30H = 전면이 기우는 양).
    기울기가 0.3 이 아니면 그 차이만큼 뒷면이 기욺 — 상수에서 따라 나오는 결과라 그대로 그림.
  ⚠ 치수가 없는 것은 그리되 치수를 안 적음 — 막자갈은 「입적 − 몸통 − 고임돌」이라 폭·높이로
    정의된 도형이 아님. 자리만 보이고 값은 표를 가리킴.

죽은 길 걷어냄 — `BLANK_DRAWINGS` 가 「표준도」 하나뿐이었는데 그것이 내용 있는 장이 되어
빈 도각 경로가 통째로 안 쓰이게 됨. 상수·목록 루프·분기·import 를 지움(700줄 제한도 걸렸음).

자체검증 — 회귀 573 통과 · 0 실패, `tsc --noEmit` 0.
⚠ 병합 뒤 깨진 시험 둘을 고침(내 폴더 `tmp/tests`, 랩탑 메인 `11394d40` 의 여파)
  · `stone_supply='채집'` 기본값을 확정 ② 근거와 함께 허용 목록에 등록
  · 바닥막이 「모든 옵션이 b05」 단정 → 조달이 detail 로 들어와 B05 셋만 보게 좁힘

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
데스크탑 메인이 넣은 품셈 표준경사 판정(13-4-4 [주]⑪)이 **근거 문구 안에만** 있었고
표준도는 못 읽고 있었음. 판정 함수 `face_slope_ratio()` 를 그대로 부르게 바꿈 —
판정을 두 벌로 짜면 그림과 수량이 갈림(CLAUDE.md 5장).

실측 (프로젝트 936be972 구조물 5기)
  돌쌓기(찰) H=2.5 1:0.3  뒷길이 45㎝ 깬돌       단면 (0,0)(0.75,2.5)(1.45,2.5)(1.45,0)
  돌쌓기(메) H=2.0 1:0.35 뒷길이 35㎝ 야면석     단면 (0,0)(0.70,2.0)(1.35,2.0)(1.25,0)
  큰돌쌓기  H=2.5 1:0.3
  옹벽                                          판정 대상 아님 — 안 적음
⇒ **메쌓기가 찰쌓기와 다른 값으로 갈림**(0.35 대 0.3). 장 제목에 그대로 뜸.

메/찰은 종류에서 옴. 큰돌쌓기는 `bond` 칸이 그것이고 안 고르면 찰쌓기로 봄 —
품셈 13-6 은 둘 다 「1:0.3 이상」이라 그림 기울기가 갈리지 않음.

기울기 근거 문구를 그림 아래 한 줄로 실음 — 「사용자 지정」인지 「품셈 표준경사」인지,
그리고 「성토/절토가 저장에 없어 성토 열로 잠정」인지가 도면에서 보여야 함.

⚠ 시험 제원에서 `face_slope_ratio` 를 뺐음 — 실제 구조물 제원에 그 칸이 없는데 시험만
갖고 있어 **판정 경로가 한 번도 안 돌았음**(늘 「사용자 지정」으로 빠짐). 빼고 나니
메/찰이 갈리는 것이 시험으로 잡힘. 사용자 지정이 이기는 것도 따로 검사함.

자체검증 — 회귀 573 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`bond` 는 레지스트리에 이미 있는 칸인데 사유를 **조건 없이 붙이고** 있어, 메쌓기·찰쌓기를
고른 구조물에도 「메/찰 구분이 없어 못 고름」이 그대로 떴음.

⚠ 얻는 것은 **노무 품 갈래뿐**이고 재료 원단위는 13-6 [주]⑦ 때문에 여전히 안 섬 —
그래도 고치는 까닭은 **사유가 거짓이면 사유 칸 전체를 못 믿게 되기 때문**임.
재료 미확보 사유는 아직 참이라 그대로 둠.

시험 762 통과(새 1건 포함).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`Router_Support_Io.BLANK_DRAWINGS` 일곱 줄(계획평면도 3종·라이다·표준 횡단면도·표준도·
용지도)이 **어느 모듈도 import 하지 않는 죽은 목록**이었음. 일곱 전부 실제 도면이 되면서
차례로 빠졌고 표준도가 마지막이었음(2026-09-09).

남겨 두면 「계획평면도가 빈 도각으로 열리나?」로 읽히는 덫임.

확인 — 실제 파일로 도면 목록을 만들어 봄(프로젝트 936be972)
  도면 36장 · kind 별 longitudinal 3 · cross 20 · plan 3 · plan_lidar 1 · landuse 1 ·
  cover 1 · cross_standard 1 · mass_haul 1 · watershed 1 · **standard 4**
  **blank 0** — 빈-도각 경로를 타는 도면이 하나도 없음.
  표준도 넉 장 제목에 판정된 기울기가 뜸(메 1:0.35 · 찰 1:0.3).

`build_blank_drawing` 자체는 남김 — 도각 표제란 시험이 쓰고, 다음에 또 「목록엔 있는데
아직 안 그리는」 도면이 생기면 그 함수가 쓰임.

자체검증 — 회귀 573 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
재생성이 `cross_sections` 행을 지우고 다시 쓰면 `data.design` 에 면적 4키만 남는다.
`get_cross_section_designs` 는 `ground_type` 있는 줄만 담으므로 그 상태는 「설계 없음」이고,
B08 토적표가 통째로 0 이 됐다(창 셋에서 같은 증상).

원인은 결함이 아니라 분담이었다 — 체인은 재생성 뒤 [확정]을 불러 그 자리를 채웠고,
재생성만 따로 도는 길에는 그 단계가 없었다. 그래서 [확정] 없이도 정본이 서게 한다.

- [저장]이 확정과 **같은 조회**(`get_cross_sections_missing_design_chainages`)로
  빈 측점을 골라 기본 설계로 채운다.
- ⚠ **값이 있는 행은 안 건드린다** — 사용자 조작값·이월분이 거기 있다. 시험으로 잠금.
- 실측(route 184): 저장 뒤 DB 설계 62행·38키 복구, 층따기 13,696.8 ㎡,
  측구 토사 0.173 / 암 8.886 ㎡ — 파일 기반 값과 일치.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 ⑨(2026-09-09) 「품셈 표준경사 표대로 자동 + 사용자가 바꿀 수 있게」.
지금은 칸이 없어 코드가 늘 0.3 으로 돌아 찰 H=2.5 와 메 H=2.0 이 같은 값으로 나왔다.

- `face_slope_ratio`(1:n 의 n) — 돌쌓기(찰·메)·큰돌쌓기·골막이·바닥막이·기슭막이 여섯.
- ⚠ **기본값 없음(빈 값)** — 빈 값이 「자동 판정」의 뜻이다. 기본값을 박으면
  「정한 적 없음」과 「그 값으로 정함」이 구별되지 않는다. 읽는 쪽이
  「비어 있으면 표대로 자동, 값이 있으면 그 값」으로 가른다.
- 그래서 「기본값 없으면 필수」 정책의 예외로 두고, 까닭을 시험 주석에 남김.
- 엔진이 읽는 이름과 글자까지 대조(`B08_Quantity_Engine_UnitQuantity` 의
  `options.get("face_slope_ratio")`), 저장 왕복도 실제로 확인(PUT 200 → 0.5 되읽음).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
품셈 표준경사 표가 높이 × 메/찰 × **성토/절토** 로 갈리는데 성절토만 없었다.
새 입력을 만들지 않고 이미 저장되는 두 값으로 가린다 —
`design.section_mode` + 구조물 `options.side`.

- `common_util_structure_face_role.structure_face_role()` — ("성토"|"절토"|None, 까닭 문구).
  ⚠ 못 가르면 **None**. 성토로 눅이지 않는다 — 받는 쪽이 근거 없음을 알아야 한다.
  예외 하나: `both_cut` + 「자동(성토 쪽)」은 세울 성토면이 없어 근거 없음.
  판정을 두 벌로 짜면 그 예외에서 갈리므로 여기 하나만 둔다(CLAUDE.md 5장).
  파이썬 단독 — 읽는 쪽이 B08 뿐이다. 화면이 쓰게 되면 그때 TS 짝·거울 시험을 붙일 것.
- 전면 기울기 칸: 표 범위(0.20~0.50) 밖이면 **막지 않고 알리기만** 한다.
  실무 도면이 S0.7·S0.8 을 쓴다 — 막으면 실물이 안 들어간다.

시험 14건(네 단면유형 × 좌/우 여덟 · 자동 셋 · 모르는 값 · 옛 영문 표기 · 문구).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B07 409 는 워크플로 단계가 아니라 **종단 레코드 상태**(`longitudinal_sections.status`)를
보는 가드라 `dev/unlock` 으로 안 풀렸음. 읽는 쪽만 우회함.

지킨 것 넷
  1. **문은 서버가 막음** — 화면 표시로 여는 것이 아님. 운영에서는 그대로 409
     (`is_dev_environment()` 가 거짓이면 우회가 아예 없음).
  2. **표식이 실제로 있을 때만 엶** — 개발환경이라고 무조건 열지 않음. `dev/unlock` 이
     4단계를 풀어 둔 프로젝트만. 그래야 되돌리기(DELETE)로 다시 닫힘.
  3. **레코드는 안 건드림** — `status` 는 `DRAFT` 그대로. 상태를 올리면 그것이 곧
     「확정 흉내」라 `common_util_dev_unlock` 이 스스로 금지한 자리와 같아짐.
  4. **열렸다는 것이 화면에 뜸** — 좌측 목록 머리 아래 「확정을 건너뛴 상태입니다 —
     개발 전용. 값이 비어 보일 수 있습니다.」 조용히 열면 다음 사람이 헤맴.

실화면 확인 (프로젝트 936be972)
  목록 200 · `dev_bypass: true` · 도면 34장 · 안내 문구 뜸
  표준도 4장 제목에 판정된 기울기 — 「표준도 2장 (돌쌓기(메) H=2 **1:0.35** 뒷길이 35㎝
  야면석·호박돌)」 · 찰은 1:0.3

자체검증 — 회귀 573 통과 · 0 실패, `tsc --noEmit` 0, prettier 는 바꾼 파일만.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
앞서 「성토 열로 잠정」 딱지를 달아 두었던 자리를 채움. 랩탑 메인이 낸 공용 함수
`common_util_structure_face_role(section_mode, side)` 를 **그대로** 부름 —
판정을 두 벌로 짜면 `both_cut` + 「자동」 예외에서 갈리므로 우리 쪽에 다시 안 짬.

- 새 저장 키 없음 — 이미 저장되는 `design.section_mode` 와 구조물 `options.side` 만 씀.
  라우터가 측점별 단면유형을 모아 넘기고, 구조물은 **가장 가까운 측점** 값을 씀.
- ⚠ 못 가르면 `None` 을 **성토로 눅이지 않음** — 종전값 1:0.3 으로 서되 **왜 못 갈랐는지**를
  근거 줄에 적음. 임의값이 금액으로 굳으면 안 됨.
- 근거 줄에 판정 문구가 그대로 실림 — 「… 1:0.35 · right_cut · 자동(성토 쪽) → 성토면」.

곁들여 — 전면 기울기 칸이 레지스트리에 생겨(`ebdf2988`) 「아직 칸이 없음」 문구와
없는-키 목록에서 뺌. ⚠ 표 밖 값(실무 도면의 S0.7·0.8)은 **막지 않고 그대로** 씀 —
접으면 사용자가 넣은 값이 조용히 다른 값이 됨. 시험으로 잠금.

검증 프로젝트 실측 — 62측점 전부 `right_cut`, 돌쌓기 「자동(성토 쪽)」 → 성토면.
잠정으로 쓰던 열과 **결과는 같고 근거가 값에 생김**. 돌쌓기(메) 21.190㎡(1:0.35) 유지.

시험 747 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`phase: "detail"` 칸(돌 종류·조달·뒷길이·전면 기울기)을 **그리는 화면이 없었음**
(2026-09-09 실측: B06 구조물 폼은 b05 phase 열 칸만 그림. 화면 글자 전수에서 「조달」·
「뒷길이」·「돌 종류」 0건). 그 자리를 표준도가 맡음 — PLAN 4-5b 「표준도는 입력 화면이기도 함」.
B06 은 「어디에·몇 m」(배치), 표준도는 「어떤 제원」.

**장 하나 = 제원 조합 하나**라 한 번 고치면 그 조합의 개소 전부에 걸림.

지킨 것
  · **자동값을 저장에 박지 않음** — 빈 칸이 「정한 적 없음」의 뜻(확정 ⑨). 비우면 그 키를
    지움. 판정된 기울기는 칸이 아니라 **회색 도움말**로만 비춤.
  · **막지 않음** — 실무 도면에 1:0.7·1:0.8 이 실재(구조물도 53장). 품셈 범위(0.20~0.50)
    밖이어도 값은 받고 안내만.
  · **값을 여기서 셈하지 않음** — 정본에 적기만 하고 표·그림은 다음 조회에서 그 정본으로
    다시 섬. 표준도가 두 번째 정본이 되면 안 됨.

⚠ 만들다 잡은 것 셋
  ① `face_slope_ratio` 가 **구조물 등록부에 없어** 저장이 통째로 거절됐음
     (`ValueError: 돌쌓기(찰)에 정의되지 않은 옵션입니다`). 한 칸 때문에 전부 못 저장되는
     것은 나쁨 — 등록부에 없는 칸은 **빼고 이름으로 알림**(조용히 버리면 저장된 줄 앎).
     그 칸 신설은 랩탑 메인 몫.
  ② 저장 뒤 표·그림을 다시 받으면서 **폼이 새로 그려져 안내가 지워졌음.** 밖에서 들고
     있다가 다시 넣음.
  ③ **장 제목에 제원이 들어 있는데 좌측 단추 글자가 안 따라왔음.** 목록을 통째로 다시
     받지 않고 표준도 줄만 갈아 끼움.

실화면 확인 (프로젝트 936be972, 개발 우회로로 열어서)
  「표준도 2장」에서 돌 종류 견치돌·뒷길이 55 로 저장 →
    단추 글자가 「…뒷길이 35㎝ 야면석·호박돌」 → 「…뒷길이 55㎝ 견치돌」로 **즉시 바뀜**
  기울기 0.7 저장 → 안내 셋: 「1개소에 반영했습니다」 · 「1:0.7 는 품셈 표준경사 표
    범위(1:0.2~1:0.5) 밖입니다 — 값은 그대로 씁니다」 · 「「전면 기울기」 칸이 masonry_dry
    등록부에 아직 없어 저장하지 못했습니다」
  조달 「구입」 저장 → 그 장의 **2개소에만** 들어가고 다른 장은 그대로(정본 실측)
  확인 뒤 **지정받은 제원으로 되돌리고 우회로도 닫음**(목록 409 복귀).

700줄 제한으로 표준도 라우터를 `B07_DesignDetail_Router_Standard.py` 로 뗌(579 + 153).

자체검증 — 새 시험 7건 + 회귀 580 통과 · 0 실패, `tsc --noEmit` 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
기울기 판정이 `section_mode` 를 받아야 도는데, 그 표를 만드는 코드가 B08 라우터 안에만
있었음. B07 표준도는 `build_table` 을 직접 부르면서 그 인자를 못 줘 **늘 「가를 근거 없음」**
으로 떨어졌음(랩탑 보조 실측).

⇒ `section_modes_from_designs(designs)` 를 엔진에 두어 **부르는 쪽마다 다시 짜지 않게** 함.
B07 은 저장된 횡단 설계 목록을 이 함수에 넣어 `build_table(..., section_modes=…)` 로 주면 됨.

⚠ 동작은 그대로 — `section_mode` 가 없는 측점은 담지 않고, 못 가르면 여전히
「가를 근거 없음 + 종전값 1:0.3」으로 섬(성토로 눅이지 않음).

내 프로젝트 실측 유지 — 돌쌓기(메) H=2.0 **1:0.35 · 21.190㎡**,
근거 「… right_cut · 자동(성토 쪽) → 성토면」.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
표준도가 `build_table` 을 직접 부르면서 `section_modes` 를 안 넘겨, 성절토를 가를 근거가
없다며 **전 구조물이 종전값 1:0.3** 으로 섰음. 값이 없는 게 아니라 **안 넘긴 것**이었음.

`section_modes_from_designs` 한 벌을 그대로 씀(부르는 쪽마다 다시 짜면 B08 과 갈림).
노선은 `get_workflow_route_context` 로 찾고, 못 찾으면 빈 표 — 성토로 눅이지 않음.

⚠ 고치고 나니 **제목·그림이 표와 갈렸음** — 표는 판정된 1:0.35, 제목은 다시 판정하며
근거를 못 받아 1:0.3. 실측으로 잡았음. 그래서 **표를 만든 그 판정을 시트에 실어**
제목·그림이 같은 값을 쓰게 함(`face`·`face_reason`). 자리를 고르는 것도 B08 이 쓰는
`_section_mode_at` 과 판정 한 벌 `structure_face_role` 을 그대로 부름.

실측 (프로젝트 936be972) — 제목과 표가 **같은 값**
```
큰돌쌓기  H=2.5  제목 1:0.3   표 0.3    면적 2.6101
돌쌓기(메) H=2.0  제목 1:0.35  표 0.35   면적 2.1190   ← 메쌓기가 갈림
돌쌓기(찰) H=2.5  제목 1:0.3   표 0.3    면적 2.6101
옹벽      H=2.0  기울기 없음(판정 대상 아님)
```
표 산출근거에 판정 경로가 그대로 뜸 — 「품셈 13-4-4 [주]⑪ 표준경사 · 메쌓기 성토 ·
직고 2m ≤3m → 1:0.35 · right_cut · 자동(성토 쪽) → 성토면」.

앞서 `face_slope_ratio({}, wet=…)` 로 확인한 「근거 없음」은 `face` 를 안 준 호출이라
**정상 동작**이었음 — 함수가 성토로 안 눅이게 짠 결과.

자체검증 — 회귀 580 통과 · 0 실패. 세 라우터 모두 700줄 안(588 · 190 · 692).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
 사용자 확정 2차 ① — 「㎡ 유지. 부피는 **사용자가 지정한 길이값을 곱해** 쓴다」.
그러면 품셈 ㎥ 단가를 그대로 쓸 수 있어 **단위 불일치가 풀림**(2,124만원 자리).

- 설정 `quantity.bench_cut_depth_m` 신설. [저장]으로도 넣을 수 있게 요청 모양에 칸을 두고,
  「안 정함」으로 되돌릴 수 있게 nullable 목록에도 넣음.
- 인계 줄: 길이가 있으면 **면적 × 길이 = ㎥** 로 내고, 규격 칸에 「면적 13,696.75㎡ ×
  길이 0.5m」로 **어디서 온 값인지** 남김.
- ⚠ **면적을 없애지 않음** — 횡단도 하단 표가 면적을 씀. ㎥ 를 덧붙이는 것.
- ⚠ **길이 기본값을 임의로 박지 않음** — 없으면 종전처럼 막고 사유를 냄
  (교본 「층따기 높이·폭은 **설계도서에 명시**」라 설계 입력임).
- 매핑 밑수를 ㎥ 로 되돌리고 그 까닭을 적음(공식이 체적 기준).

실측 — 길이 0.5m 를 넣으면 13,696.75㎡ → **6,848.375㎥** 로 서고 in_bill True.
안 넣으면 0 · input_missing · 「길이를 넣으면 면적 × 길이로 물량이 섭니다」.

시험 748 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 ④ 「터파기를 횡단도에서 표현 → 노티스 → 사용자가 선택」의 밑감.
근거의 급이 달라 갈라 둔다.

- 관: `KCS 44 40 10 배수관 §3.2(4) 그림 3.2-1` 표 그대로(Ø800→1.6 · 1000→1.8 ·
  1200→2.1 · 1500→2.5 m). ⚠ 관경+2b 로 계산하지 않는다 — 표가 관 두께·여유를 담고 있다.
  표에 없는 관경은 `None` — 지어내지 않는다.
- 벽: 법정 근거 없음(교본은 「설계도서 지시」까지). 실무 정본 xls 7탭 식 —
  기초 0.5×0.9(기초버림이면 0.1×0.7) + H×(평균두께+0.2). ⚠ **비탈 없음(수직)**.
- 레지스트리에 「기초」 칸(기초유/기초버림) 신설 — 정본 탭 제목 그대로. 그림·물량이 같은 축.
- 파이썬·TS 짝 + 거울 시험. 실무 수치(H=1·2·3 → 1.48·2.51·3.54)와 맞는지도 잠금.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 상부 = 뒷길이(ℓ3) + 0.30 · 하부 = 상부 + 0.30 × (H − 1.0) · 평균이 두께
- 옛 식(0.45 + 0.10H / 0.45 + 0.40H)에는 뒷길이가 없어 35↔45 를 바꿔도
  돌 부피·막자갈·터파기가 같은 값으로 섰음
- H ≤ 1.0 은 (H−1) 몫을 0 으로 눅여 하부가 상부보다 얇아지지 않게 함
- 산출근거 문구에 식을 남김 — 막자갈·터파기 두 줄
- tmp/tests/test_b08_wall_thickness.py 신설(7건), 옛 두께를 못 박던
  test_b08_stone_kind.py 의 막자갈 밑값 15.130 → 12.630 정정

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 2차 ③ — 기술문서 DB 를 먼저 뒤지고, 계수 원문이 없으면 실무 기준 + 노티스.

근거 (원문 확인분)
- 대한건설협회 임금적용요령 4-나 (재경원 회계45101-45, 1995.1.13): 공표 노임은
  **기본급여액**이며 제수당·상여금·퇴직급여충당금은 예정가격작성기준에 따라 별도 계상
- 기재부 「(계약예규) 정부 입찰·계약 집행기준」 제76조의3(노무비의 계상):
  노임 + 제수당 + 상여금(연 400% 한도) + 퇴직급여충당금
- 품셈 8-1-2 5.6호가 운전사 노임을 그 예규로 넘김

미확인 (노티스로 드러냄)
- 예규 원문 자체는 저장소에 없음 — 위 둘은 인용 문서
- 16/12 는 상여 연 400% 와 산술이 일치하나 25/20 은 원문 근거 못 찾음
- 실물 셋이 같은 계수 사용: 실무 두 공사지·임도교본 예제·다산 ESTX 기준계수 0.20833

구현
- `OPERATOR_ALLOWANCE_FACTOR` = 16/12 × 25/20, 근거·한계 주석을 이 한 곳에 모음
- 나눗수 8시간은 그대로 두고 **곱셈으로만** 적용 — 나눗수를 줄이면 작업효율을
  시간당 사용료에 넣은 것이 되어 ㉣ 위반. 검사(`check_operator_hours_basis`)에도
  계수를 넘겨 곱셈 자리를 드러냄
- 일위대가 조종원 줄·A10 인건비·중기 탭 노티스를 같은 문구로 맞춤

검증 (79da822d 기준)
- 굴착기 0.7  86,096.4 → 109,704.5 (+27.4%) · 불도저 19t 124,842.3 → 148,450.4 (+18.9%)
- 조종원 수량 0.20833 = 다산 ESTX 기준계수와 일치
- 실무 시트 재현: 267,360 ÷ 8 × 계수 = 55,700 (시트 값과 일원까지 일치)
- 본체 11,356,910 → 12,141,903 (+784,993, +6.9%)
- pytest 267 통과 · tsc 통과

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 ④ 「터파기가 횡단도에서 표현이 안 된다 → 교본·실무문서로 구현 →
노티스 → 사용자가 선택」.

- 관: 관 위에서 관 바닥까지 **표값 폭**으로 수직(KCS 44 40 10 그림 3.2-1).
  표에 없는 관경이면 **안 그린다** — 폭을 지어내지 않는다.
- 벽: 벽 바닥선 아래로 **수직**(정본 식에 기울기 항 없음). 폭 = 바닥폭 + 여유 0.2,
  깊이 = 기초유 0.5 / 기초버림 0.1.
- ⚠ `foundation` 이 비어 있으면 **안 그린다** — 고르기 전에는 근거가 없다.
- 말풍선에 **근거의 급을 갈라** 적는다: 관은 「법정 표」, 벽은 「품셈에 규정이 없어
  실무 관행으로 정한 값」.
- 파선(`.b06-chart__excavation`)으로 구조물보다 먼저 그려 벽 밑에 깔린다.

화면 확인: 관 터파기 5개소, Φ1000 → 1.80m · Φ800 → 1.60m (표값 그대로).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 터파기·되메우기·잔토를 `common_util_excavation.wall_trench_area_m2` 한 벌로
  옮김(화면 B06 과 짝인 TS 가 같은 값을 냄) — 돌쌓기·큰돌쌓기 공용 `_trench_components`
- `options.foundation` 「기초유」 = 기초분 0.45㎥/m · 「기초버림」 = 0.07㎥/m
- 안 고른 프로젝트는 비탈분만 세우고 사유를 냄 — 한쪽으로 찍으면 0.45 가 임의로 굳음
- 되메우기 = (기초깊이 + H) × 0.2 × 연장 · 잔토 = 터파기 − 되메우기
- 터파기 여유폭·되메우기 두께 상수를 엔진에서 지우고 공용 모듈을 가리키게 함
- tmp/tests/test_b08_wall_trench.py 신설(7건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 입적 = 정면적 × 평균두께 · 단위 ㎥ · destination `reference`
- 값을 새로 내는 것이 아니라 이미 쓰던 밑수를 화면에 드러내는 줄
- 자재총괄·토공·일위대가 어디에도 안 섞임
- 「석적」은 정본에 없어(소광리 시트에만) 내지 않음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
**기초 칸**(`foundation` — 기초유 / 기초버림, 정본 xls 탭 제목 그대로)
터파기 기초 몫이 0.5×(0.7+0.2)=0.45 대 0.1×(0.7+0.0)=0.07 ㎥/m 로 갈리고, 횡단도
터파기 선도 같은 칸을 봄. 고를 자리가 어디에도 없어 비어 있던 값임.
정본에 없는 갈래를 넣으면 **막지 않고 알림**(기존 네 칸과 같은 결). 비우면 키를 지움.

**그림을 새 두께 식에 맞춤** — 데스크탑 메인이 `STONE_MASONRY` 를 갈면서
`thickness_base_m`·`thickness_top_coeff`·`thickness_bottom_coeff` 가 사라져
그림이 `KeyError` 로 죽었음(도면이 「읽지 못했습니다」로 뜸). 실화면에서 잡았음.
  상부 = 뒷길이 + 0.30 · 하부 = 상부 + 0.30 × (H − 1.0)
  H=1.0 ℓ45 → 0.75/0.75 · H=1.5 ℓ35 → 0.65/0.80 · H=2.0 ℓ35 → 0.65/0.95 ·
  H=2.0 ℓ45 → 0.75/1.05 · H=3.0 ℓ45 → 0.75/1.35   ← 실무 원본과 전부 일치

⚠ **뒷길이를 안 정한 장은 두께를 못 내므로 그리지 않음** — 0 으로 때우면 거짓 그림이 됨.

⚠ 배운 것 — 「그림이 상수를 직접 읽으니 저절로 따라온다」가 **키 이름이 바뀌면 깨진다**는
   것으로 드러남. 값은 한 벌이 맞으나 **이름이 바뀌는 것은 예고가 필요함.**

실화면 확인 — 「표준도 3장」에서 기초 「기초유」 저장 → 「2개소에 반영했습니다」,
정본 실측 `[기초유, null, 기초유, null, null]`(그 장의 두 개소에만).

자체검증 — 새 시험 3건 + 회귀 583 통과 · 0 실패, `tsc --noEmit` 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 확정 ⑪ 「기준 구조물에서 유도 — 기슭막이면 하단 길이」 ⇒ 벽에서 하단 길이 = 하부 두께
- 버림 콘크리트 폭이 옛 잠정(터파기 폭 = 평균두께 + 0.2)에서 하부 두께로 바뀜
  (H2.5·45 → 1.175 → 1.20㎥ / H1.5·45 → 1.025 → 0.90㎥ / 10m 기준)
- 큰돌쌓기는 직경 위끝을 하단 길이로 준용
- ⚠ 기초잡석(12-25)은 폭이 생겨도 **두께가 원문에 없어** 물량을 안 세우고 사유를 냄
  (실무 관측은 관보호공 날개벽 T=0.2 하나뿐 — 다른 구조물 값을 옮겨 쓰지 않음)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- `pipe.revet_foundation`(기슭막이 기초) 신설 — **유입·유출 한 칸**. 한 공사에서 한쪽만
  기초유로 하는 일이 드물어 폼을 둘로 안 늘렸다. 실무가 갈라 쓰면 그때 나눌 것.
- 독립 기슭막이·돌쌓기 갈래도 이음: 구조물 정본 `foundation` → `RevetmentSpec` →
  `RevetmentLayout.foundation` → 터파기 그림. ⚠ 이름을 저장 칸과 **같은 글자**로 뒀다.
- ⑨ `stone_coeff_basis`(품셈/실무 관행) · ⑩ `fill_concrete_mpa`(180/210) 칸 신설.
  ⚠ **기본값 없음** — 「비어 있음 = 아직 안 정함」이고 기본값(⑨ 품셈 · ⑩ 210)은 계산 쪽이 갖는다.
- 저장 왕복 확인: PUT 200 → 되읽기에서 "실무 관행"·"180"·"기초유" 그대로.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⑤ 돌 중량 — 지식DB 전수 확인 결과 품셈·교본에 돌중량표 없음. 값(0.88 계열)은
   그대로 두고 출처(울진 소광 원단위 라이브러리)를 산출근거·source 에 남김
⑨ `stone_coeff_basis` — 빈 값이면 품셈 열(야면석 0.11·0.15)이 기본, 「실무 관행」이면
   건설품셈 참고자료 열(0.15·0.20)로 덮이고 그 사실이 사유로 뜸
⑩ `fill_concrete_mpa` — 빈 값이면 210, 180 을 고르면 그 값이 이김. 아는 값이 아니면
   기본으로 서되 사유에 저장값을 적음
- Component 에 `spec` 칸 추가 — 같은 이름이라도 단가가 갈리는 값을 받는 쪽에 넘김
- 기본값은 등록부가 아니라 계산 쪽이 가짐(등록부 default 는 비어 있음 = 「안 정함」)
- tmp/tests/test_b08_coeff_and_strength.py 신설(6건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⑨ `stone_coeff_basis`(품셈 / 실무 관행) · ⑩ `fill_concrete_mpa`(180 / 210) 를 폼에 붙임.
둘 다 **빈 값이 기본**(품셈 열 · 210) — 값을 미리 적어 두면 「안 정함」이 사라짐.
없는 갈래는 막지 않고 알림. ⇒ 칸 일곱: 돌 종류 · 조달 · 뒷길이 · 기초 · 전면 기울기 ·
야면석 계수 · 채움 강도.

⚠ **그림이 또 죽어 있었음** — `STONE_MASONRY["excavation_extra_m"]` 이 사라져 `KeyError`.
터파기 수가 `common_util_excavation` 으로 옮겨 갔음(내가 정본 xls 에서 낸 값들).
그림도 **그 한 벌**을 읽게 바꿈 — 횡단도와 같은 상수라야 두 도면이 같은 터파기를 그림.
```
WALL_TRENCH_CLEARANCE_M 0.2 · WALL_FOUNDATION_WIDTH_M 0.9 · WALL_FOUNDATION_DEPTH_M 0.5
WALL_BLINDING_WIDTH_M 0.7 · WALL_BLINDING_DEPTH_M 0.1
```
그림에 **기초 칸을 그림** — 「기초유」 0.9×0.5 · 「기초버림」 0.7×0.1.
**안 정한 장은 기초를 안 그림**(지어내지 않음).

⚠ 오늘 두 번째임 — 공용 상수 **이름이 바뀌면 그림이 죽음**. 값이 한 벌인 것과 별개로
이름 변경은 서로 알려야 함.

실화면 확인 — 칸 일곱이 다 서고, 야면석 계수 「실무 관행」·채움 강도 「180」 저장 →
「2개소에 반영했습니다」, 정본에 그 장의 두 개소만 들어감.

자체검증 — 새 시험 3건 + 회귀 586 통과 · 0 실패, `tsc --noEmit` 0.
⚠ 병합 여파로 깨진 등록부 규정 시험을 고침 — 「빈 칸이 곧 기본」인 칸 셋
(`face_slope_ratio`·`stone_coeff_basis`·`fill_concrete_mpa`)을 규정에서 뺌.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
값 한 칸에 세로축 값이 공백으로 뭉쳐 든 표를 행-자원으로도 열-자원으로도 못 읽어
두 표가 한 줄도 안 서고 있었음.

- 11-1 콘테이너형 가설건축물 F0325: 0 → 40 줄 (길이 4 × 폭 5 × 직종 2)
  `reference` 로 찍혀 형태 필터에 걸려 버려지고 있었음
- 13-5-1 돌붙임(인력) F0416: 0 → 80 줄 (메·찰 × 돌 3종 × 뒷길이 7 × 직종 2)
  「뭉친 자원 줄의 이름을 못 풀었습니다」로 버려지고 있었음

읽는 법 — 맨 아랫줄이 값, 그 위가 자원 이름, 더 위가 묶음 이름. 칸 수와 숫자 개수가
딱 나뉘지 않으면 한 줄도 세우지 않고 unmatched 로 보냄.

짓다 잡은 함정 넷
- 꼬리의 「비고」 칸(「H=2.6M 기준 …」)을 값으로 세면 표 전체를 못 읽음 — 꼬리만 떼어 냄
- 자원 줄에 줄머리가 있는 표와 없는 표가 섞여 있음 — 무조건 앞칸을 버리면 자원 하나가
  통째로 사라짐(11-1 이 7 대 8 로 어긋났음). 있는 그대로 세고 안 맞으면 앞칸을 떼어 봄
- 묶음 줄은 반대로 앞칸(축 이름)을 먼저 떼야 함 — 안 떼면 「구 분」이 묶음으로 서서
  메·찰이 통째로 사라짐
- 「구 분」·「종 별」은 자간을 벌린 한 낱말임 — 축 둘로 읽으면 갈래가 「구 메 붙 임」이 됨
- 「-」 는 그 규격이 없다는 뜻 — 0 으로 세우면 공짜 공종이 됨(야면석 70㎝ 넷)

가로채기 방지 — 값줄 위가 단위 줄인 4축 표(10-6-3)는 자원 이름이 하나도 안 풀리므로
내 표가 아니라고 보고 손대지 않음. 전체 대조로 늘어난 표가 F0325·F0416 둘뿐이고
줄이 줄어든 표는 없음을 시험으로 못 박음.

검증: 자원 축 419 → 539 줄 · 일위대가 갈래 60개 신설 · pytest 272 통과

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「구조물을 놓아도 횡단도에 아무것도 안 보인다」가 창 둘에서 같은 증상이었다.
화면에 표식을 심어 재 보니 **브라우저 쪽 단면에 `revetment` 자체가 없었다**.

- 원인: `withDraftWalls` 가 미저장 초안 목록이 **빈 배열**일 때도 「초안 있음」으로 읽고
  **서버 저장분(`revetment`)을 통째로 지운 뒤** 아무것도 안 얹었다.
  ⇒ `!drafts || !drafts.length` 로 고쳤다 — 빈 목록도 「초안 없음」이다.
- 초안 경로가 `foundation` 을 안 실어 터파기가 안 그려지던 것도 함께 고침
  (`WallSpec.foundation` 추가, 거울 시험도 같이 갱신).
- 겹침 방지 가드를 **좁혔다** — 링크가 있기만 하면 막던 것을, 그 링크의 벽이
  **이 카드에 실제로 설 때만** 막게 했다(`culvertWallsStandAt`). 관이 아홉·열하나인
  노선에서는 링크가 거의 모든 측점을 덮어 독립 벽 경로가 통째로 죽어 있었다.

화면 확인: 벽 터파기 「기초유 · 폭 1.62m · 깊이 0.50m (수직)」, 관 터파기 Φ1000 1.80m ·
Φ800 1.60m, 그려진 선 전부 좌우 변이 수직.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 구조물 전개가 destination `earthwork` 로 내던 셋을 아무도 받지 않아 내역서에
  한 줄도 안 나갔음(두께 식·기초 몫을 맞춰도 금액 0원). 실무 토적집계에는 서는 줄
  (울진 대흥 1공구 D12~D14 구조물터파기 토사 1,248/암 30 · 되메우기 739㎥)
- 새 파일 `Engine_Handoff_Trench.py` — 700줄 제한 탓에 Rows 에 안 넣음
- 구조물터파기: 심도(직고 + 기초 깊이)로 갈라 냄. 토질·용수 칸이 없어 품셈 9-13 의
  18구분 중 하나를 못 골라 상위 코드 + `input_missing` 사유로 둠
- 되메우기: FP-09-14-01 로 붙어 금액이 섬
- 잔토처리: 사토로 갈 몫이라 in_bill=False, ⚠ 그 통로가 아직 없다는 사실을 사유에 적음
- 매핑에 구조물터파기 줄 추가(FP-09-13 · 원문 L5022~5241)
- tmp/tests/test_b08_structure_trench_rows.py 신설(6건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 우리 갈래는 「리핑암」인데 일위대가는 「파쇄암」으로 서 있어 도자 운반 금액이
  이름만 못 이어 안 붙던 자리(≒30만원)
- 근거: 품셈 10-11 f 표 「파쇄암 1/1.35」 = 10-12 [주]③ 환산계수 「암절취 1.35」
- ⚠ 갈래 이름 자체는 안 바꿈 — 흙깎기(FP-09-04)가 「리핑암」으로 서 있음
- 매핑에 `ground_aliases` 절 신설, 인계본에 `ground_class_aliases` 로 실음
- tmp/tests/test_b08_ground_alias.py 신설(4건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 실무 내역 셋에 「노체포설·노체다짐」으로 가른 줄이 없음 — 영월은 「암성토
  BACK-HOE(0.7㎥)」 한 줄이고 그 단가산출 안에 적사→성토→다짐 3단계가 들어감,
  울진은 「유용성토」·「사토 및 다짐공」, 봉화는 성토사면다짐만 따로
- ⇒ 성토 본체 한 줄(포설) + 성토면다짐(㎡) 따로가 실무 양식. 다짐은 그 단가 안 단계
- 매핑에 적어 둔 「내역 양식이 정해지면 내린다」 조건이 채워진 것

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 새 저장 칸을 만들지 않음. 측점마다 이미 있는 `design.ground_type`
  (soil·ripping_rock·blasting_rock)이 품셈 9-13 토질 3구분과 그대로 맞물림
- 판정 규칙: 구조물이 **걸친 측점 전부**를 보고 갈래가 하나일 때만 값을 냄.
  섞이면 다수결로 고르지 않고 갈래별 측점 수를 사유에 적음(암 단가가 몇 배라
  임의 선택이 금액으로 굳음). 걸친 측점이 없으면 가장 가까운 측점 + 그 사실을 근거에
- 터파기 줄이 토질·심도로 갈려 서고, 막힌 사유가 「용수 유무」 하나로 좁혀짐
- tmp/tests 2건 추가(측점값 반영·섞임 판정)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
데스크탑 메인이 구조물 터파기·되메우기·잔토를 인계에 실었는데, **잔토 126.625㎥ 가
어디에도 안 실렸다**. 사토로 실어 내는 몫이라 유토곡선이 세야 겹치지 않는다.

    구조물 잔토는 사토에 한 번만 더한다.
    B08 은 소요량(structure_spoil_m3, ㎥ 양수)을 내기만 하고,
    더하는 자리는 유토곡선의 사토뿐이다.

- ⚠ **잔량 하나하나를 늘린다** — 총량만 늘리면 사토는 늘고 운반이 안 는다(공제 때와 같은 자리).
- ⚠ 나누는 법: 지금은 총량 하나만 오므로 **남은 사토 잔량 크기에 비례**해 나눈다.
  한 곳에 몰면 운반거리가 틀린다. 측점별 값이 오면 이 함수만 고치면 된다.
- ⚠ 자연방토·지반유형 안분은 안 건드린다 — 실어 내는 흙이고, 어느 지반에서 나온지 모른다.
- `null`(아직 안 옴) ≠ `0`(없음), 받은 값과 **실제로 더한 값**을 따로 싣는다.

시험 5건(더해짐·잔량 동반 증가·자연방토 불변·토취 불변·공제와 함께 와도 한 번씩).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- `B08_Quantity_Engine_HaulInputs.haul_inputs(unit_table)` — 둘 다 양수 ㎥,
  빼고 더하는 것은 받는 쪽(B06) 몫
- ⚠ 측점별로도 냄(`structure_spoil_points`) — 총량만 주면 잔량 비례로 흩어져
  운반거리가 틀어짐. 구조물은 구간이라 가운데 측점을 자리로 봄
- ⚠ 「아직 안 옴(None)」과 「없음(0)」을 가름
- 라우터에 `project_haul_inputs(project_id)` + `GET .../quantity/haul-inputs`
  — B06 이 이 함수를 부르면 됨(같은 계산을 두 벌로 짜지 않게)
- tmp/tests/test_b08_haul_inputs.py 신설(5건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
통로는 났는데 `_mass_haul_context()` 를 **인자 없이** 불러 값이 늘 `None` 이었다
(`Router_HaulPlan.py:64` · `Server_Calc_Prebuild.py:170`). 오늘 세 번째로 나온
「받는 곳은 있는데 넣는 곳이 없던」 자리다.

- `haul_inputs_for()` 로 B08 의 `project_haul_inputs` 를 받아 두 자리 모두에 넘긴다.
  ⚠ 여기서 다시 세지 않는다 — 두 값 다 B08 전개에서 나온다(CLAUDE.md 5장).
- 측점별 잔토(`structure_spoil_points`)를 받으면 **그 자리 잔량에 얹는다** —
  총량 비례로 흩으면 운반거리가 틀린다. 총량만 오면 종전대로 비례 분배(차선).
- 저장 payload 에 받은 값·실제로 먹은 값 넷을 남긴다 — 「값이 흐르는지」를 저장분에서
  바로 가릴 수 있어야 한다.

실측(route 184): 공제 0(구입이라 채집 없음) · 구조물 잔토 12.875㎥ 가 **실제로 전달됨**.
⚠ 그 노선은 사토가 0(전 구간 토취)이라 더할 잔량이 없어 `added=0` — 아래 물음 참조.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사토가 0 인 노선(전 구간 토취)에서는 잔토를 더할 자리가 없어 **물량이 그냥 사라졌다**.
파낸 흙은 어디로든 가므로 그것이 가장 나쁘다.

- 담을 사토 잔량이 없으면 **그 측점에 사토를 새로 세워** 담는다. 물량이 보존되고
  운반비가 붙는다(금액이 느는 방향 — 안전측).
- ⚠ 토취를 줄이는 길(㉯)은 「그 잔토를 성토재로 쓸 수 있다」는 근거가 있어야 한다.
  구조물 터파기 흙은 암이 섞일 수 있고 우리가 그 판정을 안 하므로, **근거 없이 금액을
  내리지 않는다.** 확정되면 이 함수 한 곳만 바꾸면 된다 — 그 문장을 주석에 남겼다.
- 새로 세운 사토는 자연방토 0 · 지반유형 안분 0 — 실어 내는 흙이고 지반을 모른다.
- 측점별 잔토를 Node 진입점까지 이어 붙임(빠져 있어 총량 갈래로 떨어지고 있었다).

실측(route 184): 사토 0 → **12.88㎥**, 잔량이 **측점 5m 자리에 섬**(전에는 노선 전체 구간).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 키가 (심도, 토질, 근거문구)라 같은 「암절취 · 심도 2~3m」이 측점 문구가 다르다는
  이유로 두 줄로 갈렸음(실화면 121.75 + 33.875)
- 키를 (심도, 토질)로 좁히고 근거 문구는 모아서 한 줄에 적음
- tmp/tests 1건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
두 창 저장분에서 **공제가 한 톨도 안 빠졌다**(`deducted 0`). 두 노선 다 원래 사토가 0
(전 구간 토취)이라, 공제가 잔토 가산보다 **먼저** 돌아 뺄 대상이 없었다.

- 유토곡선의 사토는 「현장에 남는 흙 총량」이고 출처를 안 가린다 — 공제는 그 총량에서
  빼는 것이라 **잔토가 담긴 뒤라야** 뺄 대상이 있다.
- ⚠ 모자라면 `collected_stone_deducted_m3` 가 작게 나와 「덜 뺐다」가 값으로 드러난다 —
  그 장치는 그대로 살려 뒀다.
- ⚠ 토취는 계속 안 건드린다. 「채집석을 캐 가면 성토에 쓸 흙이 줄어 토취가 는다」는
  갈래가 있으나 근거가 없다 — 그 여지를 주석에 적어 뒀다.

시험 7건(순서 시험 추가: 잔토 100 더한 뒤 공제 40 이 실제로 빠짐).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 운반 줄이 띠(bands)·이동(transfers)에서만 만들어져 사토는 잔량(residuals)으로 남아
  어디에도 안 실렸음. 그래서 구조물 잔토 126.63㎥ 를 얹어도 덤프가 안 늘었고,
  채집석 공제도 사토를 줄이는 값이라 끝까지 금액에 안 나타났음
- 실무에는 서는 줄(울진 대흥 1공구 토적집계 D32 사토 1,281㎥)
- 운반표에 `spoil`(물량·거리·근거)을 실어 인계가 「사토 운반」 한 줄을 세움
- 물량은 유토곡선 결과 그대로 — 공제·가산이 끝난 값이라 여기서 또 만지지 않음.
  자연방토는 실어 내지 않으므로 뺌
- 거리는 설계 입력 `spoil_site_distance_m` 신설 — 안 정했으면 막고 사유
  (품셈이 정하는 값이 아니라 임의 거리가 그대로 금액이 됨)
- 지반 갈래는 유토곡선이 안분하지 않아 갈래 없이 한 줄, 그 사실을 근거에
- tmp/tests/test_b08_spoil_haul.py 신설(6건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B08 이 사토 운반을 덤프 단가로 가르려면 토사/암 갈래가 필요하다. 잔량에는 이미
`ea/rr/br` 이 실려 있으나(절토에서 남은 흙이라 구성비를 안다), **구조물 잔토로 생긴
몫만은 근거가 없다**(어느 지반에서 파낸 흙인지 판정하지 않는다).

- `ground_unknown_m3 = volume − (ea+rr+br)` 을 잔량마다 함께 낸다.
- ⚠ 안 내면 받는 쪽이 **0 으로 눅여 토사로 세기 쉽다** — 그래서 값으로 드러낸다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 새 판정이 아니라 구조물터파기가 쓰는 그 값(`design.ground_type` 판정) 그대로 —
  그 터파기에서 나온 흙이 곧 이 잔토라 두 자리가 같은 판정을 씀
- 섞여서 못 고른 구조물은 「모름」(None)으로 보냄 — 터파기에서 다수결로 안 고른 규칙 그대로
- 한계도 그대로 넘어감(터파기 깊이가 암반 경계보다 깊은지는 안 봄) — 사유에 적음
- 받는 쪽(B06)이 사토 잔량 ea/rr/br 에 넣으면 「모르는 몫」이 사라짐
- tmp/tests 2건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B08 이 구조물터파기에서 이미 판정한 토질(`design.ground_type`, 품셈 9-13 3구분)을
잔토 측점값에 함께 실어 준다. **새 근거를 만드는 것이 아니라 이어받는 것**이라
두 자리가 같은 판정을 쓴다(두 벌로 짜면 갈린다).

- `structure_spoil_points[].ground_type` (soil→ea · ripping_rock→rr · blasting_rock→br).
  옛 이름(`ground`)·라벨(`ground_label`)도 함께 받는다.
- ⚠ **섞여서 못 고른 구조물은 `null`** 로 오고 그 몫은 갈래 없이 담겨
  `ground_unknown_m3` 로 드러난다 — 임의로 토사로 몰지 않는다.
- ⚠ 한계는 그대로 넘어온다: 「터파기 깊이가 암반 경계선보다 깊은지」는 안 본다
  (터파기 토질에 이미 있던 한계이고 새로 생기는 것이 아니다).

시험 8건(갈래별로 담김·못 고른 몫은 「모름」으로 남음 포함).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 유토곡선 잔량이 갈래별 물량(ea/rr/br)을 들고 오므로 갈래마다 한 줄로 세움
  (덤프 단가가 토사·암으로 갈려 합쳐 세우면 한쪽 단가로 다 물림)
- 갈래를 못 붙인 몫(ground_unknown_m3)은 따로 한 줄로 세우고 막음 — 토사로 눅이면
  임의 단가가 됨
- 갈래가 안 오는 옛 저장분에서는 종전처럼 한 줄
- tmp/tests 3건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
기초잡석(②)
- 두께 0.2m(사용자 확정). 폭은 버림 폭과 같아(KCS 34 50 05) **버림 × 두께 비**로 나옴
  ⇒ 관측 원단위로 오는 옹벽에도 값이 섬(버림 0.15㎥/m ⇒ 잡석 0.30㎥/m)
- destination `unit_price` — 운반·부설·다짐 품이 붙는 공종이라 자재총괄에 안 섞임
- 인계에 FP-12-25 줄로 섬. 묶음 구조물(옹벽)은 조각이 이미 세므로 건너뜀
- 두께는 설정 `rubble_base_thickness_m` 로 화면에서 바꿀 수 있음

용수 축(④)
- 품셈 9-13 의 18구분을 토질 × 육상/용수 × 심도로 골라 자식 코드로 내려감
- ⚠ 기본 「육상」은 **통상값이고 사용자 확정이 아님** — 그 사실을 줄 사유에 적음
- 3m 초과 칸은 원문에 없어 상위 코드 + 사유

- 설정 신설: rubble_base_thickness_m(0.2) · structure_trench_water(육상)
- tmp/tests 신설 test_b08_rubble_base.py(7건) + 터파기 시험 6건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 타설 줄(품셈 12-1)은 품만 주고 재료를 안 줌(서브 일위대가도 재료 0원) — 콘크리트를
  자재 축에 안 보내면 재료비가 통째로 빠짐. destination 을 material 로 옮김
- 배합 분해 금지(㉢)는 그대로 — 「콘크리트 ㎥」에서 멈춤
- 할증 이름 잇기(값은 그대로, 찾을 때만 다른 이름):
  · 이형철근 D13·D16 → 「이형철근」 (품셈 1-3-1, 규격 안 가림)
  · 콘크리트 셋 → 「레미콘」 **레미콘 타설일 때만**. 비빔은 시멘트·골재가 각각 할증되는
    자리라 붙이지 않고 사유를 냄
- 할증률 미확보 사유를 비고에 적음 — 「표에 이름 없음」과 「이 방식엔 안 붙임」은 할 일이 다름
- tmp/tests/test_b08_material_concrete.py 신설(6건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 ① — 작업효율 0.50(두 끝의 평균). 딸림 지시 「값을 코드에 박고 끝내지 말 것 ·
화면에 칸으로 세우고 근거를 보이고 바꿀 수 있게」를 그대로 구현.

막혔던 자리 둘
- 품셈 9-3-2 가 작업효율을 「0.55∼0.45」 범위로 줌 → 확정값이 아니라 계수가 안 섬
- 그 표에 장비가 없음 → [주]① 「무한궤도 굴착기(0.7㎥)」가 마스터에 안 실려 기종을 못 고름
⇒ 두 자리를 채워 흙깎기 단가가 처음으로 섬: 2,515.1원/㎥ × 2,355.84㎥ ≒ 592만원

구현
- `B09_Estimation_FactorChoices` 신설 — 범위 칸을 품셈에서 훑어 모으고(코드 안 박음),
  고를 수 있는 것은 원문 두 끝과 그 평균 셋뿐. 기본은 평균
- 장비 규격도 같은 결로: 흙깎기는 [주] 에만 있는 값을 채우는 칸, 층따기는 원문 0.7㎥ 를
  기본으로 두고 실무(영월 0.2㎥)로 바꿀 수 있는 칸
- 고른 값은 프로젝트 설정 `estimation` 구획에 저장 — 프로젝트마다 갈림
- `cached_build` 를 고른 값별로 캐시 (전역 한 벌이면 한 프로젝트가 남의 금액을 흔듦)
- `GET/PUT /{project_id}/estimation/factors` · 기초자료 탭 맨 위에 칸과 근거 표시

⚠ 짓다 잡은 것 — 「0.45-0.05」를 범위로 잘못 읽고 있었음. 그건 뺄셈(=0.40)이라
품셈이 이미 정한 값인데 「고를 것」으로 둔갑했음. 물결(∼) 일 때만 범위로 봄

검증: pytest 279 통과(신규 7) · tsc 통과 · 평균 2,515.1 / 하한 2,794.6 으로
고른 값이 단가에 실제로 닿는 것 확인
⚠ 화면 확인은 못 함 — 내 창 브라우저 세션이 만료됐고 자격 파일이 이 폴더에 없음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지시(2026-09-09): 「값을 코드에 박고 끝내지 말 것 · 대신 페이지에 남길 것」

- 층따기 길이(확정 2차 ①) — 비면 층따기 줄이 막힘. 칸이 없어 값이 안 들어가던 자리
- 기초잡석 두께(확정 3차 ②, 0.2m) — 근거: 폭은 버림 폭과 같음(KCS 34 50 05),
  두께는 품셈 12-25 가 안 정해 사용자 확정값
- 사토장까지 거리(확정 3차 ③ 미정) — 비어 있고, 비면 사토 운반 줄이 막힘
- 구조물터파기 용수(확정 3차 ④) — 기본 「육상」이 **통상값이고 사용자 확정 아님**을
  칸 밑 근거 줄에 적음. 품셈 9-13 의 18구분이 이 값으로 갈림
- 칸마다 근거 한 줄(`b08-quantity__hint`)을 붙임 — 왜 그 값인지 화면에서 보이게

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
일위대가가 선 141 공종 중 **70 공종**이 「품셈 표에 있는데 못 붙은 줄」을 갖고 있었음.
막지 않는 것은 맞으나(막으면 정상 공종이 무더기로 멈춤) 화면이 말하지 않아
**조용히 싼 단가**가 내역서에 그대로 들 수 있었음.

실례 — 초류종자살포(FP-05-24-01, 수량 17,873.80㎡)
  품셈 5-24-1 은 자재 5(종자·비료·피복제·침식안정제·색소) + 장비 3(종자살포기·트럭·
  물탱크) + 인력 2 인데, 우리 단가는 **인력 둘만**으로 233.4원/㎡ 였음.

- `UnitPriceBuild.unattached` 신설 — 공종별로 못 붙은 줄 이름을 들고 있음
- 본표(`detail_of`)가 `unattached`·`unattached_note` 를 함께 냄
- 일위대가 상세 화면이 그 문구를 굵게 띄움. 다 붙은 단가는 아무 말도 안 함
  (늘 경고가 뜨면 아무도 안 읽음)
- 품셈이 자간을 벌려 적은 이름(「종      자」)은 눌러서 보임

⚠ 지역 이름 충돌 하나 잡음 — `names` 가 공종 이름표라 같은 이름을 쓰니 조립이 통째로
터졌음. 주석으로 못 박음.

검증: pytest 282 통과(신규 3) · tsc 통과

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 안 정하면 타설 줄은 기본값(레디믹스트)으로 도는데 할증만 미확보로 두어 같은
  프로젝트에서 두 값이 어긋났음(실화면). 안 정함 = 기본값으로 보고 사유를 적음
- 비빔은 그대로 미확보 + 사유(시멘트·골재가 각각 할증되는 자리)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실무 정본이 근거임 — `구조물도/기슭막이/04.구조도(기슭막이).xls` 탭 제목이
「돌기슭막이(H=2.0m, **찰쌓기**, 기초유)」이고 그 안의 계산이 돌쌓기와 **같은 식**임.
⇒ 기슭막이는 새 식이 아니라 **「형태가 돌쌓기면 돌쌓기 식」**. 여기서 다시 짜면
같은 계산이 두 벌이 되어 돌쌓기와 갈림(CLAUDE.md 5장).

형태별 갈래
  돌쌓기(찰) → `stone_masonry(..., wet=True)`    12줄
  돌쌓기(메) → `stone_masonry(..., wet=False)`   11줄
  콘크리트 · 돌망태 · 통나무/목재틀 · 바자 → **식 없음 + 왜 없는지 한 줄**
     콘크리트   돌쌓기(13-4)가 아니라 콘크리트 구조물 — 벽 두께·저판이 정본에 없음
     돌망태     품셈 13-8, 규격 축이 망태 치수라 돌쌓기 표를 못 씀 — 원단위 미확보
     통나무틀   품셈 13-13, 밑수가 ㎥당 목공 품 — 각재·판재가 카탈로그에 없음
     바자       바자얽기(5-15) 별도 일위대가로 잇기로 확정(2026-09-09 ⑧-4)
  형태 미정 → 「형태를 골라야 물량이 섭니다」

⚠ **뒷길이·돌 종류 칸이 기슭막이 등록부에 없음** — 돌쌓기 식은 그 둘로 계수가 갈리는데
없으면 `_back_length` 가 **조용히 45㎝ 로 돎**. 값이 나오므로 아무도 못 알아채는 자리라
**「돌쌓기 기본값으로 섰음」을 줄로 드러냄.** 칸 신설은 등록부 담당 창 몫.

⚠ 확정 대기가 남은 자리(막자갈 식 · 돌 중량 · 체적/석적 줄)는 **지금 값 그대로** 둠 —
`stone_masonry` 를 부르므로 그쪽이 갈리면 기슭막이도 같이 따라감.

자체검증 — 여섯 형태를 다 돌려 봄(찰 12줄 · 메 11줄 · 나머지 0줄 + 사유).
회귀 586 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 유토곡선 잔량은 다짐상태인데 이 값은 자연상태(제자리 기하 부피)라 그냥 더하면 섞임
  (2026-09-09 랩탑 메인 지적). `volume_basis: "natural"` 을 총량·측점마다 실음
- ⚠ 엄밀히는 되메움에 쓰이는 흙이 다짐부피 ÷ C 라 조금 더 들지만, 실무 정본 시트도
  그냥 빼므로(터파기 1.55 − 되메우기 0.30 = 잔토 1.25) 값은 그대로 두고 사실만 적음
- tmp/tests 1건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 유토곡선 잔량이 되돌린 값(natural_m3_by_ground)을 들고 오면 **그것을 씀**.
  없으면 다짐값으로 서되 「품셈 운반 밑수는 자연상태」라는 사실을 근거에 적음
  (조용히 쓰면 상태가 어긋난 물량이 단가에 물림). 우리가 환산하지 않음 — 계수는 저쪽에 있음
- 갈래를 못 붙인 몫은 상태도 못 되돌리므로 그 사실을 함께 적음
- `haul.spoil.volume_basis` 신설 — 받는 쪽이 단가와 맞는지 스스로 보게
- 범위를 줄 사유에 적음: 「사토장 정지」는 실무가 사토 운반 단가 안 조각(1/3)으로 넣으므로
  수량 줄을 따로 안 세움 · 사토장 사면 보호공은 실무 집계표에 행이 없어 안 셈
  (교본 6장 3절은 요구 — 뒤집으면 그때)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 「사토장 정지」는 실무가 사토 운반 단가 안 조각(1/3)으로 넣으므로 수량 줄을 안 세움
  (세우면 같은 품을 두 번 셈)
- 사토장 사면 보호공은 실무 내역·사방공 집계표에 행이 없어 안 셈. 교본 6장 3절은
  요구하나 프로젝트 규칙상 실무가 안 세면 안 세는 쪽이 기본 — 뒤집히면 이 문장만 지움

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 코드 주석에만 두면 화면에서 안 보임(오늘 여러 번 나온 자리)
- 「제자리 기하 부피(자연상태) · 되메움에 쓰이는 흙은 다짐부피 ÷ C 라 조금 더 들지만
  실무 정본도 그냥 빼므로 그대로 둠」을 두 줄의 spec_detail 에 실음
- 잔토 사유를 지금 동작으로 고침 — 「통로가 없어 안 실림」 → 「유토곡선이 사토에 얹어
  사토 운반 줄로 섬」(2026-09-09 통로가 생김)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
구조물터파기 여덟 갈래가 「단가가 일부만 섰습니다 — 붙은 몫 10%」로 서 있던 자리.
값이 없어서가 아니라 품셈이 「육상토사(0~1m)와 동일」처럼 **다른 절을 가리키는데**
그 참조를 안 따라가서였음.

- `B09_Estimation_MachineProductivity_Reference` 신설 — 참조를 따라가 계수를 이음.
  값을 옮겨 적지 않고 가리키는 절을 그때그때 읽음. 사슬·순환도 처리(순환은 멈춤)
- 열 갈래가 풀림: 09-13-02·03·05·06·08·09·11·12·17·18
- 빌려 온 계수는 **출처를 줄 비고에 적음** — 「계수 출처: 「…와 동일」 → 육상토사(0~1m)」

⚠ 짓다 잡은 것 셋
- 「육상과동일」은 「육상」이라는 절이 아니라 **제 이름에서 용수를 육상으로 바꾸라**는 뜻.
  이름 규칙을 먼저 태우면 없는 절을 찾다가 네 갈래를 놓쳤음
- 한 표에 참조가 둘이고 **가리키는 곳이 다름**. 9-13-11 은 치즐 줄이 「육상과동일」,
  백호우 줄이 「용수 암절취(0~1m)와 동일」임. 아무 줄에서나 주우면 용수 자리에 육상
  계수가 붙어 작업효율이 0.375 대신 0.50 으로 서고 **금액이 조용히 틀림**.
  ⇒ **기계 줄에 붙은 참조만** 보게 함
-  **묶음 배분율이 첫 줄에만 붙고 있었음** — 품셈이 「인력(10%)」 머리를 병합해 적어
  다음 줄엔 딱지가 없음. 그래서 「보통인부 1.0」이 100%로 서 **조용히 열 배**가 됐음
  (구조물터파기 단가가 224,305원/㎥ 이었음). 묶음 머리를 만날 때까지 이어 주게 고침

막힌 채로 두는 것 — 암·발파암 갈래는 **깨기(대형브레이커)·치즐**이 그대로 빠져 있어
금액을 세우지 않음. 다만 **사유를 남은 줄로 고쳐 적음**(백호우 이야기는 이미 풀렸음).
9-13-14 는 자기 자신을 가리키는 원문 오기라 **고쳐 읽지 않고** 사유로 남김.

검증: pytest 288 통과(신규 6) · 토사 갈래 단가가 처음 섬(1~2m 7,218.5원/㎥)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 잔토 「그 통로가 없다」 → 2026-09-09 에 생김(HaulInputs → 사토 가산 → 사토 운반 줄)
- `face_slope_ratio` 「레지스트리에 없는 키」 → 칸이 생김(돌쌓기 계열 여섯 · 표준도 폼).
  빈 값이 「자동」의 뜻
- 성토/절토 「저장이 아직 안 갖고 있다」 → 측점 단면유형 + 설치 측으로 판정 중.
  못 가르는 자리만 남고 그때도 눅이지 않고 사유를 적음 (masonry_slope 정책 문구도 함께)
- 품셈 9-13 「토질·용수 칸이 없다」 → 셋 다 서면 자식 코드로 내려감

⚠ 사유가 거짓이면 사유 칸 전체를 못 믿게 됨 — 오늘 통로가 여럿 생겨 낡은 자리를 훑음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 2026-09-09 사용자 확정: 사토장은 **이미 있는 측점 위에만** 놓임 ⇒ 거리는 「발생점 →
  사토장 측점」 누가거리로 저절로 나옴. 가정할 것이 없어짐
- 잔량이 `spoil_haul_distance_m` 을 들고 오면 갈래별 **가중평균**을 내어 그 거리로 줄이 섬
  (실무 내역이 운반수단 × 지반별 평균 하나를 올리는 서식)
- 없는 갈래만 산출 조건의 대체 거리로 서고, 거리 출처를 값 옆에 적음
- 사유·화면 도움말을 「거리가 없음」 → 「사토장을 아직 안 놓았음」으로 고침
  (사토장이 서면 낡을 문구였음)
- tmp/tests 2건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「운반거리의 산정 시에 모든 수량은 다짐상태로 환산하여 계산하고, 내역서에
적용하는 수량은 자연상태로 한다」(설계실무 요령, config 5-4-3 인용문) 인데
유토곡선이 쌓은 다짐 물량이 그대로 내역 줄로 서 있었음.

- HaulSummary: 줄마다 `natural_m3`(÷C)·`volume_basis`·`conversion_c` 를 함께 냄.
  환산은 이 파일 한 곳에서 한 번만. 거리·검산은 다짐 기준 그대로.
  `L`(1.3·1.35·1.625) 은 안 씀 — 품셈 10-11·10-12 가 `f = 1/L` 을 스스로 곱함.
- 토공집계표: 운반 줄을 자연상태로 실음. 갈래를 모르면 다짐 그대로 두고 사유 표기.
- 사토 줄: `natural_m3_by_ground`·`volume_basis` 신설. 갈래 없는 몫은 환산 안 함.
- 구조물 잔토(자연상태)를 곡선에 담기 전 ×C — 왕복이 맞게 됨. 갈래 모르면 그대로.

실측 변화(내역 4줄): 도자 토사 15.65→17.39 · 리핑암 70.30→61.13 ·
덤프 토사 33.76→37.51 · 리핑암 140.78→122.42 (합 260.49→238.45, −8.5%).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	B08_Quantity/B08_Quantity_Router_Earthwork.py
- 유토곡선은 다짐상태로 쌓고(운반거리를 그 기준으로 재야 맞음) 내역서 수량은 자연상태임
  (config_system_design 5-4-3). 인계 줄이 다짐값을 그대로 읽고 있었음
- 되돌린 값(natural_m3)이 오면 그 값으로 서고, 쓴 계수(÷C)를 근거에 적음
- ⚠ 되돌릴 계수가 없으면(갈래 못 붙임) 다짐 그대로 두고 사유를 냄 — 토사 계수로 눅이면
  근거 없이 금액이 움직임
- 거리는 안 바뀜(다짐 기준이 맞음)
- tmp/tests/test_b08_haul_state.py 신설(4건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
칸이 없어 `_back_length` 가 조용히 45㎝ 기본값으로 돌던 자리임.

- `back_len_cm` 25·30·35·45·55·60·75㎝ / `stone_kind` 야면석·호박돌·깬잡석·깬돌·견치돌
- 기본값 없음 — 값이 없으면 「기본값으로 섰음」이 드러나야 함
- 돌쌓기(찰·메)와 같은 키·같은 글자 (품셈표 `stone_kind` 데이터셋과 대조)
- 기슭막이는 돌이 아닌 형태(콘크리트·돌망태·바자)도 있어 필수로 두지 않음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 되돌린 값(natural_m3_by_ground)이 오면 그 값으로 서고 상태를 사유에 적음
- 안 오면 다짐 그대로 두고 「내역 수량은 자연상태여야 함」을 사유로 냄
- tmp/tests 2건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 축이 다른 값을 그냥 빼면 암에서 15% 어긋남(우리가 만드는 어긋남). 갈래를 실어 보내
  유토곡선이 ×C 로 다짐 축에 맞춰 빼게 함
- 갈래를 못 가른 구조물 몫은 계수가 없어 따로 냄(환산 안 함)
- ⚠ 벽 입적 ↔ 원바닥 암 부피의 관계를 정한 원문이 없음(캐면 부풀고 쌓으면 공극) —
  그 가정은 어느 쪽으로 가도 남으므로 가정은 그대로 두고 축만 맞춤.
  실무 시트가 그냥 뺀다는 사실까지 값과 함께 보냄
- tmp/tests 3건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
유용토운반작업장(구 사토장) — 노선 옆에 남는 흙을 쌓는 성토 단면.

- `common_util_spoil_fill.{ts,py}` 신설(한 벌, 거울 시험) — 평상(노면 끝 높이) →
  1:n 비탈 → 지반과 만나는 데까지. 단면적은 적분으로 정확히 셈.
  폭 시작점 = **노면 끝**(사용자 확정) ⇒ 그 구간 노견도 이 성토 안에 듦.
  폭 상한 = **지반 샘플이 있는 데까지**. 상한에서도 모자라면 그 폭을 냄(임의로 안 넓힘).
  용량에서 폭을 되풀이로 역산하는 `solveSpoilWidthM` 함께 냄.
- 등록부 `spoil_bank` 를 넓힘 — 새 종류를 만들지 않음(지식DB 상 같은 시설임).
  이름 「유용토운반작업장(구 사토장)」 · 구간형 · 횡단도에 그림 ·
  칸 `side`(자동=성토 쪽) · `fill_slope_ratio`(비면 노선 성토 기울기) · `extra_distance_m`.
- 기울기·적치높이 기본값은 지어내지 않음 — 지식DB §4 가 근거 없음을 못 박음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
채집석은 **벽 입적(제자리 부피)**이라 자연 축이고 유토곡선은 다짐 축임.
축이 다른 값을 그냥 빼고 있었음(리핑암이면 13% 어긋남).

- 갈래별 값(`collected_stone_by_ground_m3`)이 오면 갈래마다 ×C 해서 뺌
- 갈래를 못 가른 몫은 계수가 없어 **환산하지 않고** 그대로 뺌
- 갈래가 아예 안 오면 종전처럼 총량을 그대로 뺌 (안 온 것과 0 은 다름)
- 통로 정리 — `_mass_haul_context` 가 B08 입력 dict 를 통째로 받게 함
  (칸이 늘 때마다 인자를 늘리다 빠뜨리던 자리)

⚠ 벽 입적과 원바닥 암 부피의 관계를 정한 원문이 없음 — 그 가정은 그대로 두고
**축만** 맞춘 것임(세 창 합의, 근거 문구는 B08 이 값과 함께 보냄).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 관 허용오차 두 값이 우연히 다른 것처럼 보였음. `LENGTH_MATCH_TOLERANCE_M`(0.5m,
  「길이를 어디서 가져오나」)과 `SECTION_MATCH_TOLERANCE_M`(0.05m, 「횡단이 있나」)을
  한 자리에 이름 붙여 모으고 **맞추면 둘 다 나빠지는 까닭**을 적음
  ⚠ 두 값의 차이는 증상이고 병은 「관 자리에 측점이 없는 것」(계획서 3-14, B06 자리)
- 채집석 축 맞춤 검산을 값과 함께 보냄 — 더하는 쪽·빼는 쪽에 같은 계수가 걸려
  사토 총량이 그대로임(61.88 → 61.887)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「단가가 일부만 섰습니다 — 붙은 몫 0%」 만으로는 어디를 손볼지 알 수 없었음.
구조물터파기가 그 자리였는데, 참조는 이미 풀렸고 실제로 막는 것은 깨기(대형브레이커)·
치즐이었음.

- 사유에 `component_gaps`·`unattached` 를 이어 붙임
  「붙은 몫 0% · 깨기, 치즐소모량(본/hr) 줄이 아직 안 붙었습니다 (계수 참조는 풀렸습니다).」

검증: pytest 288 통과

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사토장이 선 측점은 **노면 끝 바깥이 사토장 몫**이라 노선 성토에서 빼야 함.
안 빼면 같은 흙을 두 번 셈(2026-09-09 확정 ㉠).

- `compute_cross_design(spoil_fill=…)` / `computeCrossDesign({spoilFill})` 신설(짝)
- 새 칸: `spoil_fill_area_m2` · `spoil_fill_side` · `spoil_fill_width_m` ·
  `spoil_fill_max_width_m` · `spoil_fill_line` · `spoil_fill_unclosed` ·
  `spoil_fill_replaced_fill_m2`(노선 성토에서 뺀 몫 — 되짚기용)
- **합쳐서 하나로 내지 않음** — 받는 쪽이 갈라 볼 수 있어야 함
- 기울기가 비면 그 측점의 노선 성토 기울기를 그대로 씀(새 값 안 만듦)
- `fillAreaBeyond`/`_fill_area_beyond` — 경계 종거를 보간해 자름(한 칸도 안 흘림)
- 거울 시험에 사토장 사례 둘 추가 + 값이 0 이면 잡히는 가드

⚠ `B06_Section_Engine_Design.py` 가 924줄 — 700줄 제한 초과 상태임(이번 전에도 881줄).
  기능이 다 선 뒤 분리할 자리.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
표토 운반(법이 요구하는데 제거만 세고 있던 자리)
- 시행규칙 별표2 「표토는 전량 제거한 후 … 최고 홍수위보다 높은 장소로 운반하고
  쌓아두어야 한다」 — 제거(9-15)만 세면 운반이 빠짐
- 물량은 제거 물량 그대로(다시 안 셈), 거리는 설계 입력 `topsoil_haul_distance_m`
- 거리가 없으면 막고 사유 · 제거가 안 서면 운반도 안 섬(밑수가 그 줄) · 법 문구를 사유에

화면 칸(사용자 지시 「대신 페이지에 남길 것」)
- 부대시설 개소 다섯(국가지점번호판·안내판·차단기·가설창고·수방자재) — 서버가 받고
  있었는데 넣을 칸이 없던 자리. 산식으로 만들지 않는다는 사유를 칸 밑에 적음
- 표토 운반거리 칸 + 별표2 근거 한 줄

- tmp/tests/test_b08_topsoil_haul.py 신설(5건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 「입목 본수를 들고 있지 않음」이 원문과 달랐음. 품셈 9-21 [주]① 은
  **소림(30~60㎥/㏊)·중림(60~90)·밀림(90 이상)** 으로 가름 — 본수가 아니라 **축적**
- ⚠⚠ 그리고 **9-21 표에 밑수 단위 열이 없음**(9-20 은 「10주당」이라 적혀 있음).
  등급을 넣어도 「무엇당 값」인지 모르면 못 셈 — 원문 확인이 필요한 자리로 사유에 적음
- 임목축적 등급 설정·화면 칸 신설(`stand_volume_class`) + 근거 한 줄
  (산림조사부·영림계획에서 옮겨 적는 값이라 프로그램이 만들 수 없음)
- 대상 면적(벌개제근 연동, 지장목제거와 같은 자리)을 참고값으로 실음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 9-20 가. 「벌개·제근 → 뿌리다듬기 → 적재 → 운반」이 시공 과정 표준이고 [주] 가
  「제근 후 뿌리다듬기와 적재항목에 적용」이라 두 항목을 줌. 별표2 도 「그 뿌리…를 전량
  제거한 후 운반하고 쌓아두어야」로 뒤 단계를 요구 — 우리는 제거 한 줄만 세고 있었음
  (표토와 같은 병: 법·품셈이 두 동작을 묶는데 앞 동작만 셈)
- 적재는 FP-09-20-02(「10주당」) · ⚠ 운반은 그 장에 공종이 없어 코드를 못 붙임 —
  지어내지 않고 사유로 냄
- 둘 다 제근과 같은 밑수(본수)가 서야 값이 남. 대상 면적은 참고값으로 실음
- tmp/tests 3건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
품셈 제8장 [주]⑤ 「불도저 및 굴착기에 리퍼, 브레이커, 부착용집게를 조합하여 사용할
때는 …잡재료비율을 16%로 계상하고, 리퍼, 브레이커, 부착용 집게의 손료 및 치즐
소모율을 추가하는 것이다」 를 따라감.

세 자리를 이었음
1. **뭉개진 카탈로그 줄을 원문으로 되살림** — `mach_base_2026.json` 의 대형 브레이커
   여섯 줄이 이름 칸에 표 전체가 뭉쳐 규격·손료계수가 없었음. 건설품셈 제8장 (0230)
   표에서 읽어 채움. ⚠ **두 번 검증** — 계수 합 3,000+2,833+768=6,601 이 표의 「계」와
   같고, 같은 방식으로 읽은 굴착기 「계 2,085」가 카탈로그 0.0002085 와 정확히 일치
2. **부착용 장비는 손료만으로 층을 세움** — 제 엔진이 없어 운전경비표에 줄이 없음.
   없다고 버리면 깨기 몫이 영영 안 붙음. ⚠ 리퍼·브레이커·집게에만 여는 길
3. **작업량을 직접 준 기계 줄을 읽음** — 「대형브레이커(㎥/hr) 3.5」. 공식이 아니라
   시간당 작업량을 표가 바로 주는 모양. 단위가 붙은 칸만 읽음(짐작 금지)

결과
- 구조물터파기(암절취·육상·2~3m) 155.625㎥ × 72,378.4 = **11,263,899원** — 처음 섬
- 돌쌓기 단가에 **부착용 집게 손료**가 더해짐(메 76,607.9 → 78,864.5) — [주]⑤ 그대로
- 본체 19,444,626 → **30,892,279원**
- 남은 것은 **치즐(자재) 하나** — 기계가 빠지면 막고 자재 소모품이 빠지면 드러내기만
  하는 규칙대로, 금액을 세우고 본표가 「치즐소모량 줄이 아직 안 붙었습니다」를 말함

⚠ 아직 안 한 것 — 같은 [주]⑤ 의 **「잡재료비율 16%」**. 조합 사용 시 굴착기 잡재료가
22% 가 아니라 16% 임. 그 자리는 운전경비 층이라 따로 손봐야 함.

검증: pytest 290 통과(신규 3)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 갈라 내라는 원문이 없고 실무도 한 덩이로 셈. 별표2 타.(1) 이 「노출되는 면은
  전체면적 녹화」라 소단도 녹화 대상이므로 섞여 있는 것이 틀린 것이 아님
- 가르면 「그 몫으로 무엇을 세나」를 우리가 정하게 되어 근거 없는 줄이 섬 —
  대신 근거 문구에 「소단면 포함」을 적어 가르지 않고 보이게 함

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
① 수량 산식이 확정 대기인 줄에 그 사실을 함께 실음 (계획서 4-12 3단계)
   구조물터파기가 내역서에서 가장 큰 줄(11,263,899원)이 됐는데 그 밑수가 사용자
   확정을 기다리는 식 위에 서 있음. 값은 그대로 두고 **드러내기만** 함.
     「⚠ 터파기 수량 산식이 확정 대기입니다 — 실무 시트는 기초만(기초폭 × 깊이 0.3)
       세고 우리는 벽 전체를 셉니다(m당 실무 0.35 vs 우리 2.30, 약 6.6배).
       실무 식으로 확정되면 이 줄 금액이 약 1/6.6 로 줄어듭니다.」
   되메우기·잔토처리도 같은 뿌리라 함께 표시. ⚠ 측구터파기는 다른 뿌리라 대상 아님

② `VARIANT_ALIASES` — 축이 달라 다르게 불리는 갈래를 **이름을 갈지 않고** 이음
   우리 「리핑암」은 B05·B06 지반유형(캘 수 있는가), 품셈 「파쇄암」은 운반 상태
   (부서졌는가)라 일반적으로 같은 말이 아님 — 발파암도 캐고 나면 파쇄암 상태임.
    다만 산림품셈 10-11 f 표가 토사·파쇄암·발파암을 따로 두어 그 표의 파쇄암은
   발파를 뺀 나머지이고, 10-12 [주]③ 「토사 1.3, **암절취 1.35**, 발파암 1.625」가
   10-11 의 파쇄암 1/1.35 와 **같은 값**이라 그 표 안에서는 암절취(리핑) = 파쇄암임.
   그 문장을 주석에 그대로 남김

검증: pytest 290 통과 · `find_variant_code("FP-10-11","리핑암")` → `B-FP-10-11#파쇄암`

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 운반 단가가 지반 갈래로 갈리는데 `variant_value` 가 비어 있어 받는 쪽이 갈래를 못 골랐음
  (「버림」에서 275,584원이 사라졌던 자리와 같은 병)
- `variant_axis: "ground_class"` · `variant_value: 리핑암` 으로 실음. 갈래가 없는 줄은 None
- ⚠ 이름은 우리 갈래 그대로 — 일위대가의 「파쇄암」과는 인계본 `ground_class_aliases` 가 이음
- tmp/tests 2건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠⚠ 조사 중 큰 것이 나옴 — **우리가 「틀렸다」고 버린 옛 두께식이 실은 「골막이 식」이었음.**
소광리 숨김탭 「골막이(찰)(치수조서연결)」 원문:
```
C26  평 균 두 께 = {( 0.45 + 0.1 × H ) + ( 0.45 + 0.4 × H )} ÷ 2
```
우리 옛 식과 글자까지 같음. ⇒ **실무는 구조물 종류마다 두께식이 다름.**
확정 ②(뒷길이 기반)는 **기슭막이에 맞고**, 골막이에는 이 식이 맞음.
⇒ 골막이에 `stone_masonry` 를 그대로 부르면 **틀어짐.** 그래서 안 부름.

골막이가 돌쌓기와 다른 자리 셋 (정본 실측)
  · 두께식 위와 같음
  · 밑수가 **「돌쌓기 + 돌붙임」** (19.62 + 2.625 = 22.245) — 기슭막이는 돌쌓기만
  · 단위가 **개소당** — 기슭막이는 m당
  · 정면적이 사다리꼴 ((상장+하장)÷2×높이) − 파형강관(0.4×0.4×3.14)
  ⚠ **상장·하장 칸이 등록부에 없어** 정면적을 못 냄 — 칸 신설이 선행

바닥막이는 형태가 **돌붙임**(품셈 13-5)이라 돌쌓기(13-4) 표를 못 씀. 밑수도 면적(㎡)이라
축이 다름 — 돌붙임 원단위 미확보.

⚠ **일부러 안 부름** — 돌 계열이라 `stone_masonry` 를 부르면 **값이 나오므로 아무 시험도
안 잡음.** 오늘 큰돌쌓기에서 같은 일이 있었음(직경 60~80㎝ 가 뒷길이 45㎝ 계수로 돌던 자리).

자체검증 — 골막이 0줄 + 사유 · 바닥막이 0줄 + 사유 · 기슭막이 13줄(그대로).
회귀 586 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「같은 돌쌓기니 한 함수로」가 되기 쉬운 자리라, 두 정본을 나란히 잰 결과를 코드에 남김.

다른 것 넷 (소광리 「골막이(찰)(치수조서연결)」 ↔ 「돌기슭막이」)
  두께식   골막이 (0.45+0.1H)/(0.45+0.4H)   ↔ 기슭막이 뒷길이 기반(ℓ3+0.30 …)
  밑수     골막이 **돌쌓기 + 돌붙임**        ↔ 기슭막이 돌쌓기만
  단위     골막이 **개소당**                ↔ 기슭막이 m당 (확정 ⑦ 「통일 안 함」)
  정면적   골막이 **사다리꼴**(상장·하장)    ↔ 기슭막이 직사각(H × 1)

같은 것 여섯 — 막자갈 2/3 · 야면석 0.88 ton/㎡ · 물구멍 2㎡/개소 · 기울기 몫 1.04 ·
고임돌 0.15 · 채움콘크리트 0.2. **우리 기본값이 어디서 왔는지의 답**이기도 함.

`STONE_MASONRY` 상수 머리에도 한 줄 — 「**기슭막이 계열 전용**. 골막이는 두께식이 다름
(정본 C26)」. 상수만 보고 가져다 쓰면 **값이 나오므로 아무 시험도 안 잡는** 자리임.

자체검증 — 회귀 586 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 소광리 숨김탭 「골막이(찰)(치수조서연결)」 C26 이 우리가 확정 ② 로 버린 옛 식과
  글자까지 같음 — 그 식은 틀린 식이 아니라 **골막이 식**이었음. 기슭막이에 쓰던 것이
  어긋남의 정체였음
- 골막이는 두께식 말고도 셋이 더 다름(밑수 = 돌쌓기+돌붙임 · 단위 = 개소당 ·
  정면적 = 사다리꼴) — 상수만 보고 가져다 쓰지 못하게 적음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
① 품셈 제8장 [주]⑤ 의 마지막 조각 — 「…조합하여 사용할 때는 …**잡재료비율을 16%로
   계상**하고, 리퍼·브레이커·집게의 손료 및 치즐 소모율을 추가」. 손료·치즐만 넣고
   이 줄을 빠뜨리면 본체 재료비가 22% 로 남아 조금씩 비싸짐.
   - 기계마다 「#조합」 층을 함께 세움(손료·조종원 같음, 잡재료만 16%)
   - 조립 **끝에 한 번** 조합 공종의 본체 줄을 그 층으로 바꿔 닮 — 도중에는 어느 공종이
     조합인지 아직 모름. 바꾼 줄 24
   - 부착 장비는 **이름이 아니라 분류번호**로 잡음(0103 리퍼 · 0230 브레이커 ·
     0240 진동콤팩터 · 7206 집게) — 이름은 원천이 뭉개 놓는 일이 있음(0230 이 그랬음)
   - 결과: 구조물터파기 72,378.3 → 72,333.2 · 돌쌓기(메) 78,864.5 → 78,423.8 ·
     돌쌓기(찰) 61,757.3 → 61,418.0 · 본체 30,892,279 → **30,849,376원**

② 터파기 노티스 문구 정정 — 「실무는 기초만 세고 우리는 벽 전체를 셈(6.6배)」이
   **틀렸음**. 우리 식은 정본(기초 0.45 + 비탈) 그대로이고, 6.6배는 소광리 시트가
   비탈 줄을 안 적어서 난 것임. ⇒ 「비탈 터파기를 셀지 확정 대기 — 안 세면 약 1/7」로
   고침. 값·금액은 그대로

검증: pytest 290 통과(신규 1)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자는 「이 구간에 ○㎥」를 정하는데 단면은 폭을 알아야 그려짐.
그 구간 측점을 한꺼번에 보고 **폭 하나**를 이분법으로 찾음(작업장은 폭이 일정함).

- `enforce_spoil_fills` 신설 — `enforce_ford_surface_drops` 와 같은 자리·같은 방식.
  자동설계 체인·[저장] 뒤 **맨 마지막**에 돎(앞 보정이 다시 계산하면 사토장 칸이 지워짐)
- 「자동」이면 그 측점의 **성토 쪽**에 섬 (`structure_face_role` 재사용)
- 상한(지반 샘플이 있는 데까지)에서 멈추고 못 담은 몫은 `spoil_fill_unplaced_m3` 로 냄
- 구간 안 측점만 씀 — **새 측점을 만들지 않음**(사용자 확정 ③)
- 용량이 없으면 아무것도 안 세움(폭을 정할 근거가 없음)

실측 — 용량 200㎥·800㎥ 를 넣으면 각각 그만큼 담기고(오차 2% 안), 100만㎥ 를 넣으면
상한 폭에서 멈추고 남은 몫이 값으로 남음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ **정정** — 어제 「돌붙임 원단위 미확보」로 사유를 냈으나 **소광리 정본에 식이 셋 있었음.**
안 찾아본 것을 「없다」고 적은 자리였음. 53탭 전수에서 드러남.

붙인 원단위 (정본 「돌붙임L3=45(사방)」 · 「돌붙임L3=30(야면석메붙임)」)
```
돌붙임(찰)  두께 0.45 · 돌 30×30×45㎝ **0.918 ton/㎡**(= 0.45 × 0.77 × 2.65) ·
            고임돌 0.15 · 모르타르 0.009 · 채움 0.2 + **버림 0.1** · 터파기 0.45   8줄
돌붙임(메)  두께 0.30 · 야면석 20×20×30㎝ **0.42 ton/㎡**(원문 직접값) ·
            고임돌 0.07 · 터파기 0.30                                          5줄
            ⚠ 모르타르·채움·버림은 **줄 자체가 없음** — 0 으로 만들지 않고 뺌
```
밑수는 **면적(㎡)** — 등록부 `area_m2` 와 축이 그대로 맞음. **기울기 몫을 안 곱함**(평면).

⚠⚠ **돌쌓기 표(13-4)와 합치지 못하게 못 박음** — 값이 겹쳐 보여 합치고 싶어지는 자리:
```
돌쌓기(13-4)  밑수 비탈면적 · 뒷길이 일곱 규격 · 기울기 몫 √(1+n²)
돌붙임(13-5)  밑수 **평면적** · 뒷길이 **넷** · **기울기 몫 없음** · 메는 모르타르·채움 없음
⚠ 45㎝ 에서 고임돌 0.15·채움 0.20 이 **우연히 같음** — 합치면 25·30·60·75 에서 조용히 틀림
```

ⓘ **돌중량이 관측값이 아니라 유도값임** — `뒷길이 × 0.77(채움률) × 2.65(비중)`.
   두 원본에서 같은 모양이 나왔음. 다만 **야면석은 그 식이 안 맞아**(공극이 커 ㎥당 무게가
   다름) 원문 직접값 0.42 를 그대로 옮김. ⇒ 확정 ⑤ 가 「값 고르기」가 아니라
   **「채움률·비중 두 인자 정하기」**로 바뀔 수 있음 — 우리 0.88 은 안 건드렸음.

⚠ 뒷길이가 **붙박이**(찰 0.45 · 메 0.30) — 정본 탭이 그 둘뿐이고 등록부에 칸이 없음.
   그 사실을 줄로 냄. 칸이 생기면 표를 열면 됨.

자체검증 — 새 시험 5건(정본 값 대조 · 메는 세 줄이 빠지는지 · 기울기 몫 없음),
회귀 591 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 토공집계표는 실무 토적집계 모양이라 무대·도자운반·덤프운반을 함께 싣는데, 인계본에는
  운반표(FP-10-11·FP-10-12)가 같은 물량으로 또 실렸음 — 둘 다 in_bill 이었음
  (실측: 도자 17.389·61.130 · 덤프 37.511·122.417 이 두 축에 각각)
- 집계 쪽 운반 줄을 in_bill=False 로 두고 사유를 적음. 값은 남김 — 검산
  (무대+도자+덤프 = 총 운반토량)이 그 값을 씀(무대를 그렇게 둔 것과 같은 규칙)
- 성토 같은 다른 집계 줄은 안 건드림
- tmp/tests/test_b08_haul_double_count.py 신설(5건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
품셈 9-21 제근은 장비 규격 두 갈래(0.2㎥·0.7㎥)를 **고르라고** 둔 표인데 둘 다 붙고
보통인부도 두 번 붙어 단가가 **128,039원**으로 서 있었음. 밑수가 원문에 없어 아직
금액이 안 서 있었을 뿐, **밑수가 정해지는 날 조용히 두 배로 설 자리**였음.

- `B09_Estimation_ResourceAxis_ChooseOne` 신설 — 블록마다 갈래 하나, 열마다 갈래 하나.
  장비 2 × 임목밀도 3 = **여섯 갈래**로 세움 (55,625.9 ~ 111,161.4원)
- ⚠ **「고르는 표」를 좁게 가름** — 기계 줄이 둘이라고 다 그런 표가 아님. 9-13 암절취는
  깨기(브레이커)와 들어내기(백호우)가 **함께 듦**. 자국은 **같은 이름에 규격만 다른 것**.
  품셈도 그렇게 말함 — 9-20-1 [주]④ 「0.2㎥ 또는 0.4㎥ … 계수를 달리 적용」
- ⚠ 밑수는 만들지 않음 — 9-21 은 표 머리·제목·[주] 어디에도 밑수 표기가 없음
  (앞 절 9-20-1 「(10주당)」·9-20-2 「(단위: 10주당)」과 대비되는 자리)

⚠ 짓다 잡은 것 — 기종 해석이 **넘겨받은 카탈로그를 무시**하고 기계 카탈로그를 직접 봐서,
노무만 든 카탈로그로 돌릴 때도 기계 줄이 나왔음. 카탈로그에 기계가 없으면 이 표를
안 읽게 막음(시험이 그것을 잡았음).

⚠ 시험 하나가 **버그를 맞는 것으로 적어 두고 있었음** — 「제근은 보통인부 줄이 둘이다」.
그것이 곧 이중계상이었음. 뒤집어 다시 적었음.

검증: pytest 295 통과(신규 4) · 자원 축 539 → 547 줄, 늘어난 8 줄은 전부 제근

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「반쪽 단가」 표시가 여태 **이름을 카탈로그에서 못 찾은 줄**만 잡고 있었음. 그물 밖에 둘이
더 있었고, 둘 다 **금액이 서 있는 줄**이라 표시가 없으면 완성된 값으로 읽혔음.

- 기초잡석 12-25 — 원문에 「운반 | 덤프트럭(15ton)」 줄이 있는데 우리 단가에 없음.
  ⚠ 사유를 「원문이 값을 안 줌」으로 뭉뚱그리지 않음 — 그 값은 품셈 10-12(덤프운반)가
  **운반거리로** 내는 것이라 **거리가 정해지면 풀림**. 「영영 막힘」과 「곧 풀림」은
  사용자가 보는 뜻이 다름
- 기초잡석 소할 — 원문이 「**브레이커 사용할 때 제외**」라 한 줄인데 지금은 무조건 붙음.
  ⚠ 조건부 열두 줄 중 **이것만 금액이 서 있음**(다른 열한 줄은 붙는 쪽, 이것은 빠지는 쪽)
- 규준틀 11-2·11-3 — 지금 값은 **인력 품만**. 손율은 원문에 있음(비탈 50% · 수평 80%)

⚠ 앞 보고를 정정함 — 규준틀은 「표시가 아무것도 없다」고 했으나 **B08 인계가 이미
「재료량은 [주]④ 설계수량에 따른다라 미확보」를 싣고 있었음.** 화면 문구 뒤쪽이 잘려
안 보였던 것임. 그래서 그 말은 되풀이하지 않고 **B09 쪽에서만 아는 것**만 보탬.
「잘린 자리를 사유가 없는 자리로 읽지 말 것」을 주석에 남김

검증: pytest 300 통과(신규 5)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
소광리 정본 「개거(150-200) (2)」·「L형수로-(201)」 — **둘 다 m당**.

⚠⚠ **두 표가 담는 것이 다름.** 값이 비슷해 보여 합치고 싶어지는 자리라 못 박음:
```
콘크리트 개거 150×200   터파기 · 유로폼 · 면목  **세 줄뿐** — **콘크리트 본체 줄이 없음**
콘크리트 L형수로 H=0.2  터파기 · 되메우기 · 잔토 · **콘크리트** · PVC Φ50 · 이형철근 D13 ·
                       거푸집 · 면목  **여덟 줄**
ⓘ 같은 것 — 둘 다 m당이고 거푸집 계열(유로폼·거푸집)과 면목이 있음
```
⚠ 개거에 콘크리트가 없는 것은 **빠뜨린 것이 아니라 원문 그대로**임. 0 으로 때우거나
L형수로 값을 옮겨 채우지 않음 — 돌붙임(메)에서 세 줄을 안 만든 그 판단과 같음.
⚠ **PVC Φ50 은 줄만 있고 수량 칸이 빔** — 안 세우고 그 사실을 줄로 냄.

⚠ 규격이 **붙박이**(「콘크리트 개거 150×200」) — `open_ditch` 등록부에 **옵션이 하나도 없음**.
   `ditch_spec` 을 주면 L형수로로 갈림. 칸이 생기면 열면 됨.

**측구(`ditch_side`)는 안 건드림** — `design_owner: 횡단 설계` 라 B06 소관이고 `enabled: False`.
정본 「측구수로400/500」은 **「터파기 계산서」**라 터파기·잔토·되메우기 셋뿐임(본체 없음) —
그쪽이 쓸 때를 위해 적어 둠.

실전개 (연장 10m)
  개거   터파기 0.3㎥ · 유로폼 5.5㎡ · 면목 20m
  L형수로 터파기 3.1645 · 되메우기 1.2997 · 잔토 1.8647 · 콘크리트 1.508 ·
         이형철근 3.98㎏ · 거푸집 7.38㎡ · 면목 10m

자체검증 — 새 시험 5건(정본 값 대조 · 개거에 콘크리트가 없는지 · 잔토 = 터파기−되메우기 ·
빈 수량 줄 · 없는 규격), 회귀 596 통과 · 0 실패.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
교본 6장 3절이 운반처리 위치를 평면도·횡단도에 표시하도록 요구함.

- 긴 파선+점(9 3 2 3) · 사토장 색 — **터파기 짧은 점선과 선 종류를 가름**
- 이름표 「유용토운반작업장 ○㎡」 를 평상 위에 얹음
- 말풍선에 단면·폭·구간 용량·못 담은 몫·잘림 경고와 **근거 두 줄**
  (「폭은 노면 끝에서 잼」·「교본 6장 3절이 표시를 요구함」)
- 지반을 못 만나 잘린 사토장은 붉게 — 사면 미폐합 경고와 같은 결
- 계획선을 만져도 사토장이 안 사라지게 저장분 폭·구간값을 이어 붙임
  (폭은 구간 용량에서 서버가 정한 값이라 브라우저가 다시 풀지 않음)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 「재료량은 설계수량에 따른다」는 값을 안 준다는 뜻이지 안 센다는 뜻이 아님.
  근주이식·임목파쇄(셀지 말지가 설계 판단)와 성격이 다름 — 확정 ⑨·⑩ 과 같은 틀로 감
- 제안값(울진 소광 §8 관측): 각재 50×50 0.0044㎥ · 판재 T12 0.0029㎥ · 못 0.03㎏/개소
- ⚠ 「실무 관측값이지 법정 기준 아님」과 손율 원문값(비탈 50% · 수평 80%)을 줄 사유와
  화면 칸 밑에 함께 적음 — 값만 박으면 「대신 페이지에 남길 것」 지시를 어기는 것
- 개소가 안 서면 재료도 안 섬(밑수가 그 줄) · 자재 축으로 감(할증은 자재총괄에서 한 번)
- 설정 `frame_material` + 화면 칸 셋
- tmp/tests/test_b08_frame_material.py 신설(7건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사토장이 **측점 위에만** 서므로(사용자 확정 ③) 거리는 「발생점 → 사토장 측점」
누가거리로 그냥 나옴. 가정할 것이 없어짐.

- `_spoil_sites` — 측점 설계에 실려 온 사토장 구간값을 구조물 단위로 접음(다시 안 셈)
- 거리 = 발생점별 물량 가중평균 + `extra_distance_m`(항상 더함)
- 사토장이 없으면 종전대로 설계 입력값 · 그것도 없으면 막힘(임의 거리 안 넣음)
- 사유에 사토장 측점·수용량·**못 담는 몫**을 실어 화면이 드러내게 함
- `distance_basis` 칸 신설 — 받는 쪽이 「측점 기준」과 「설계 입력값」을 갈라 봄

⚠ 사토장에 쌓아도 **유토곡선 사토는 줄지 않음** — 그 흙은 여전히 실어 내야 하는 흙이고
  사토장은 목적지임. 줄이면 운반비가 사라짐. (네 창에 확인 요청함)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사토장
- 카드 면적표에 「사토장」 줄을 따로 세움 — 성토와 **합치지 않음**(확정 ㉠).
  사토장이 없는 측점에는 줄을 세우지 않음(어느 측점에 있는지 표에서 보이게)
- 성토와 다른 색으로 둠 — 같은 색이면 한 덩어리로 읽힘

등록부(다른 창 요청, 기본값 없음 — 현장 치수라 지어내지 않음)
- `erosion_check.top_length_m`·`bottom_length_m` — 골막이 정면적이 사다리꼴이라
  두 변이 있어야 셈. 실무 정본 산출식이 상장ⓐ·하장ⓑ를 씀
- `soil_guard.form` 에 「떼」 추가 — 실무 정본에 떼흙막이 산출식이 있는데 붙일 칸이 없었음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	B08_Quantity/B08_Quantity_Engine_UnitQuantity.py
① 마스터가 본문·표에서 밑수를 「인」으로 읽어 온 자리가 여섯 있음(드론방제 둘·지상방제·
   야면석 채집·휘발유·천공기). 「인」은 **사람 수**이지 공종 단위가 아니라, 그대로 두면
   「몇 인짜리 공종」이 되어 **단위 불일치 검사가 엉뚱하게 통과**함.
   ⚠ 원문 쪽 고치기는 마스터 몫(데스크탑 메인) — 여기서는 **받는 쪽에서 막음**.
   같은 규칙이 `WorkItemUnit` 머리말에 이미 있어 짝을 맞춤

② 규준틀 사유 갱신 — 데스크탑 메인이 각재·판재·못을 자재 축에 세워(`e100d311`)
   「인력 품만」의 뜻이 바뀜. 재료가 오되 관급·사급이 안 갈려 아직 금액 0 임을 적음

⚠ 계획서 9장 재판정(미체크 27 → 21 · 크기 딱지)은 `docs/` 가 git 밖이라 커밋에 안 실림 —
  파일에는 반영돼 있음.

검증: pytest 300 통과 · 밑수가 「인」인 자원 줄 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「인」 오독 넷(원문 대조)
- 8-6-2 드론방제·8-6-3 지상방제 「(단위 : 인)」은 **소요인력**이지 공종 밑수가 아님
- 13-2-4 야면석 채집 「(단위: 인 당)」은 표 안이 ㎡당·㎥당 두 줄이라 하나로 못 정함
- ⚠ 넓게 「인」을 버리면 2-2-5 천공기가 사라짐(「천공인부 1인당 1대」) — 숫자가 붙었나로 좁게 가름

칸 이어붙임 — 앞 칸 값 + 뒤 칸 단위로 **원문에 없는 밑수**가 서던 자리
- 13-2-4 「0.36 ㎥당」(0.36 은 뒷길이 60 의 ㎡당 값)
- 5-19-2 「30 ㎥당」(30 은 표토두께 ㎝)
- ⇒ detect_basis 가 **칸 하나 안에서만** 봄. 「100㎥당」처럼 한 칸에 다 있는 것은 그대로

- 마스터 재생성: 밑수 확보 182 → 180 (없는 값 둘이 빠지고 넷이 미확보로 정직해짐)
- tmp/tests/test_b08_master_basis_person.py 신설(5건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
돌골막이(erosion_check)
- 소광리 정본 「골막이(찰)(치수조서연결)」 식을 개소당으로 전개.
  정면적 사다리꼴 − 방수로 파형강관 → 돌쌓기 → 평균두께 → 입적 →
  야면석·고임돌·막자갈·채움콘크리트·물구멍관 → 바닥파기·잔토·되메우기 11줄.
- 거울 시험이 정본 W열과 소수점까지 일치(19.62 / 2.625 / 20.56 / 19.58 /
  3.34 / 10.54 / 4.45 / 4.91 / 8.61 / 2.74 / 5.87).
- 엑셀의 줄별 INT(x*100)/100 자름을 그대로 옮김 — 다음 줄이 잘린 값을 받음.
- 두께식 주석 정정: 「0.45 + 0.1H」의 0.45 는 상수가 아니라 뒷길이 ℓ3
  (정본 C26 이 P6/100 을 읽음). 골막이도 뒷길이 기반임.
- 등록부에 없는 칸 셋(뒷길이·돌 종류·방수로 유무)은 붙박이로 돌되 사유를 냄.

떼흙막이(soil_guard)
- 형식 「떼」가 들어와 정본 「떼흙막이」 표가 섬 — 떼 1.39㎡ · 터파기 0.17㎥.
- 사용자 확정 4차대로 그림·옵션은 기슭막이와 한 벌, 수량 데이터는 분리.
  나머지 일곱 형식은 원단위 미확보 사유로 뜸.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
정본이 줄마다 INT(x*100)/100 으로 자르고 다음 줄이 그 잘린 값을 받으므로
표시용이 아니라 계산의 일부임. 안 자르면 막자갈 10.55 · 잔토 2.75 로
정본과 갈림. round(4.905) 가 짝수 반올림으로 4.90 이 되는 자리(물구멍관)도
함께 적음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 소광리 C26 이 `P6/100`(뒷길이 45㎝)을 읽는 것이라 골막이도 **뒷길이 기반**임.
  둘은 「더하는 몫」만 다름 — 골막이 ℓ3 + 0.1H/0.4H · 기슭막이 ℓ3 + 0.30 / +0.30(H−1)
- 앞서 상수처럼 적어 두었는데 그렇게 굳으면 **뒷길이를 바꿔도 골막이 값이 안 움직이는**
  결함이 조용히 남음(랩탑 보조가 셀 참조로 확인해 알려 옴)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠⚠ **진단이 뒤집힌 자리임.** 계획서 3-14 는 「관을 나중에 놓으면 측점이 안 생긴다」로
적혀 있었으나 실측하니 **측점은 이미 있었음** — 구조물 이름표까지 달고.

진짜 원인 — **관 자리와 측점 자리는 최대 0.5m 어긋나고 그것이 설계임.**
측점을 만들 때 정수 미터가 같은 격자 측점이 있으면 그리로 스냅함
(`B05_Profile_Engine_Sections_Core` — 횡단 파일명이 정수 미터라 두 측점이 한 파일을
덮어쓰는 것을 막는 가드). 관 440.241 은 **측점 440.0** 위에 섬.
그런데 붙이는 쪽이 **0.02m** 로만 봐서 그런 관은 어느 측점에도 안 붙었음
⇒ 횡단도에 안 서고 길이도 안 실려 B08 이 「연장 없음」으로 막음.

- `attach_culvert_sets` / `attachCulvertSets`(짝) — **가장 가까운 측점 하나**를 그 관의
  자리로 봄. 거리로 자르지 않아 스냅 폭이 바뀌어도 따라가고, 하나만 고르므로 두 번 안 셈
- `pipeOwnerChainage` 신설 — 길이를 싣는 주인도 같은 규칙
- `SECTION_MATCH_TOLERANCE_M` 0.05 → 0.5 — 좁게 보면 「횡단 자체가 없습니다」라는
  **거짓 사유**가 뜸(반대 방향의 거짓). 옛 판단 근거를 주석에 남기고 뒤집은 까닭도 적음

실측 — 관 9개 중 **5개만** 길이가 있던 것이 **9개 전부**로 (440·620·720·900 복구).

곁들여
- 「측점 없는 구조물 N개」 알림 + [측점 만들기] 단추(3-14 ㉯) — **진짜로 측점이 없는**
  경우를 위해 남김. 판정은 스냅을 셈에 넣어 0.5m.
  샘플링 조건은 확정 때 남긴 `sampling.json` → 없으면 1단계 저장값. 둘 다 없으면 막고 사유
- 등록부 `retaining_wall.form` 에 「식생옹벽블럭」 추가(다른 창 요청)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B08 이 율을 이미 곱해 보내고, 율이 갈리는 줄은 `pct` 를 비운 채 갈래로만 보냄.
받는 쪽은 **곱하지도 100% 로 채우지도 않아** 값은 맞았는데, **왜 그 수량인지**가
화면에 아무 데도 없었음 — 값이 맞아도 그것은 반쪽임.

- `application_ratio_breakdown` 을 읽어 사유로 적음
  「반영률이 갈래마다 다릅니다 — fill 80%, cut 100% (적용 후 수량)」
- ⚠ **「율 없음」이라 쓰지 않음** — 사실이 아님. 오늘 가장 위험하다고 본 오독과 같은 말임
- 율이 안 걸린 줄은 아무 말도 안 함

검증: pytest 303 통과(신규 3) · 율을 어긋나게 넣어 실제로 돌려 봄
  (quantity 1300 · gross 1500 · pct None → 1300 그대로 · gross 안 씀 · 두 번 안 곱함)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
랩탑 보조가 산출식을 손에 들고 기다리던 칸들. **기본값은 안 넣음**(현장 값이라
지어내면 안 되고, 비어 있으면 사유가 뜨는 것이 맞음).

- 골막이 `back_len_cm`(뒷길이 ℓ3) · `stone_kind`(돌 종류) · `spillway`(방수로)
  ⚠ 뒷길이 하나에 두께식·고임돌·야면석·채움콘 네 성분이 걸림
  ⚠ 방수로는 지금 **늘 빼고** 있었음 — 「없음」을 고를 칸이 없었음
- 개거 `ditch_spec` — 콘크리트 개거 150×200 / L형수로 H=0.2. 비우면 실무 붙박이(개거)
- 물빼기 구멍 덮어쓰기 `weep_hole_diameter_mm` · `weep_hole_area_m2` (여섯 종류)
  비우면 **국가기준**(Ø50 · 2㎡당) — 사용자 확정 「국가기준 + 숫자 변경 가능하게」
  ⚠ 바닥막이는 뺌 — 바닥에 눕는 시설이라 벽면이 없음

칸 이름·글자는 기슭막이·돌쌓기와 같은 벌을 씀(엔진이 읽는 이름 그대로).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1번 비탈 터파기 「지금 이대로」 — `BASIS_WALL` 에서 「확인 후 쓸 것」을 걷고 확정 표시로 바꿈
  (「법정 근거 없음」은 사실이라 그대로 둠)
6번 제근 밑수 **면적 축** — 산림품셈 9-21 에 밑수 표기가 없어 **건설품셈 3-9-2 「1,000㎡당」**
  을 ⚠ **교차 참조**로 빌려 씀. 제근·뿌리 적재가 같은 면적으로 섬(㎡)
  ⚠ 임목축적 등급은 **단가 갈래**이지 물량 밑수가 아님 — 비어도 값은 서고 사유만 남음
4번 뿌리 운반 **덤프**(FP-10-12) — ⚠ 운반 밑수는 부피(㎥)인데 뿌리 부피를 든 곳이 없어
  물량은 안 섬. 사용자 관찰(실무에서 운반품이 안 붙기도 함)도 사유에 적음

곁들여 — 준비공 인계 줄이 **값이 서는 순간 근거를 잃던 자리**를 고침(대분류 이름만 싣고
  있었음). 제근이 확정으로 값이 서자 「교차 참조」 표시가 사라진 것에서 드러남

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
막자갈 (작은 것 3)
- 옛 식(입적 − 몸통 − 고임돌)에서 (뒷채움 상 + 하) ÷ 2 × H 로 갈아탐.
- 상·하는 벽 두께가 아니라 뒷채움 폭임. 정본 04.구조도(기슭막이).xls
  여섯 탭(H=1.0~3.0 · 메/찰 · 기초유/버림) 전부 상 0.30 · 하 0.45 로 같음.
  소광리는 같은 식에 0.30/0.60 을 써서 0.900 이 나옴 — 그 사실을 사유로 냄.
- H=2.0 에서 정본 0.75 와 일치(옛 식은 1.66 쪽으로 튀던 자리).

석적 (작은 것 4)
- 정면적 × 뒷길이 × 0.77 로 새 줄. 정본에 없고 소광리에만 있는 줄임을 사유에 적음.
- 「체적」은 이미 「입적」 이름으로 내고 있어 이름만 맞음 — 새로 만들지 않음.

돌 무게 (큰 것 7)
- 뒷길이 × 0.77(채움률) × 2.65(비중) 계산식이 기본. H=2.0 에서 정본 1.92 톤과 일치.
- 야면석만 관측표(35→0.575 · 45→0.880 · 55→1.100) — 공극이 커 계산식이 안 맞음.
- 종류를 안 고르면 정본 줄 이름 그대로 「돌」로 서고 그 사실이 사유로 뜸.
- 잠정임(실무자 협의 후 명확히)을 화면 근거에 적음.

터파기 (큰 것 1) — 기초 + 비탈 그대로. 코드 변경 없음.

채집석 밑수도 새 줄을 따라감 — 석적 + 고임돌 + 막자갈.
거울 시험 신설: 정본 H=2.0 여섯 줄 일치, 일부러 다른 두 줄(입적·물구멍관)의
차이까지 못박음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	B08_Quantity/B08_Quantity_Engine_Pipe.py
# Conflicts:
#	B08_Quantity/B08_Quantity_Engine_UnitQuantity.py
- 실무(영월 1.9)가 한 면적에 두 작업을 얹음 — 뿌리뽑기 @475 · 잡관목제거 @882 가
  같은 11,035㎡. ⚠ 이중계상이 아니라 서식이 그러함(사유에 적음)
- 잡관목제거는 품셈에 이름이 없음(실무 D00033 별도 단가) — 공종 보류(확정 5차 3번)라
  코드 없이 서고 사유가 붙음
- ⚠ 곁들여 잡은 것: `item` 칸을 **늘 지반 갈래로 읽고 있었음** — 지장목제거의 작업 갈래에
  「시공법 미지정으로 공종을 못 고름」이라는 틀린 사유가 붙었음. 갈래로 읽는 공종을
  GROUND_SPLIT_GROUPS 로 한정하고 나머지는 규격 칸으로 보냄
- tmp/tests/test_b08_tree_removal_split.py 신설(5건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 5차 「비탈 터파기, 지금 이대로」 ⇒ 구조물터파기·되메우기·잔토처리 세 줄의
「확정 대기」 문구를 걷음. **값은 안 바뀜** — 11,256,879원이 확정된 값이 됨.

⚠ 표는 지우지 않고 **비워** 둠 — 같은 성격의 자리가 또 생기면 여기 적으면 됨.
적을 때 「왜 대기인지」와 「정해지면 얼마나 움직이는지」를 함께 적으라는 규칙을 주석에 남김.

검증: pytest 303 통과 · 본체 31,118,251원 그대로

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 「기본 안 셈」이되 「현장에 따라 파쇄가 적용될 필요 있음」이라 **임목파쇄만** 켤 수 있게 둠
- ⚠ 안 켠 프로젝트에는 **줄 자체가 없음** — 빈 칸이 「세야 함」으로 읽히지 않게
  (부대시설은 법정 의무라 늘 서는 것과 다른 자리)
- 켜도 부피는 지어내지 않음 — 넣어야 값이 서고 FP-08-11(이동식 임목 파쇄)이 붙음
- 근주이식(FP-14-02)은 **칸도 안 만듦** — 켤 자리가 없으면 물을 일도 없음
- 설정 `wood_chipping_enabled`·`wood_chipping_volume_m3` + 화면 칸 둘
- tmp/tests/test_b08_wood_chipping.py 신설(5건)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
골막이 (erosion_check)
- spillway 「있음/없음」 — 「없음」이면 파형강관 0.5024㎡ 를 안 뺌. 정면적이 밑수라
  일곱 줄이 +2.1~3.1 % 움직임. 「있음」이 정본과 같은 값(정본은 방수로 치수 0 인
  개소에서도 뺐음). 안 고르면 정본 쪽으로 서고 사유가 뜸.
- stone_kind · back_len_cm 를 읽음. 「칸이 없다」던 사유가 「안 골랐다」로 바뀜.

돌 무게 헬퍼 한 벌 (stone_weight_per_m2)
- 확정 5차 큰 것 7 규칙을 돌쌓기·골막이가 같이 씀. 계산식이 기본, 야면석만 관측표.
  두 벌로 두면 같은 확정이 구조물마다 갈림.

물구멍 헬퍼 한 벌 (weep_hole_spec)
- weep_hole_diameter_mm · weep_hole_area_m2 를 읽고 비우면 Ø50 · 2㎡당.
  지름은 규격(spec)으로 실어 단가가 갈리게 함.
- 정본이 개소당 관 길이를 평균두께(0.83m)로 잡는 것을 주석에 남김 — 우리 상수 0.5m
  와 갈리는 자리이고 미결임.

개거 — ditch_spec 칸이 와서 두 규격을 고를 수 있음.

시험 — 등록부 정책 예외에 새 칸 넷(ditch_spec · weep_hole 둘 · fill_slope_ratio)과
사토장 둘을 넣음. 613 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 4차 원문 — 「흙막이는 횡단도에서 **표현방식들과 옵션들은 동일하게** 반영하면
될거야. **형상은 동일해.** 물론 **데이터는 분리하여 계산**되어야함.」

- 그리기 경로는 **이미 같음** — C군 벽은 `attachWallSpecs` 로 `section.revetment` 에 붙어
  기슭막이와 같은 기하를 탐(따로 그리지 않음). 형태 이름도 「찰/콘크리트」 글자로 갈려
  흙막이 선택지(돌(찰)·돌(메)·떼…)가 그대로 먹힘
- 빠져 있던 것은 **옵션 칸**이라 기슭막이 열두 칸을 **같은 글자 그대로** 옮김 —
  단 수 · 올림 · 이동 · 뒷길이 · 돌 종류 · 조달 · 야면석 계수 · 채움 강도 ·
  전면 기울기 · 기초 · 물빼기 구멍 둘
  ⚠ 흙막이 수량이 안 쓰는 칸도 **숨기지 않음**(사용자가 「동일하게」라 함) — 수량 쪽에서
    조용히 무시되면 됨
- ⚠ 코드에 **「형상 동일 ≠ 수량 동일」**을 못 박음. 원단위·공종코드·성분 줄은 흙막이 자기 것.
  반대 사례가 골막이임(그림도 수량도 다르고 두께식마저 다른 식) — **계열이 다르면 상수를
  나눠 쓸 것**

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실무 원본 횡단도에는 그 자리가 **아예 없음**(400dpi 실측, 다른 창 확인) —
납품 양식을 늘리는 것이 아니라 **안 쓰던 빈 줄을 쓰는 것**임.

- 우측 그룹의 빈 줄 자리에 「사토장」 신설 (`spoil_fill`)
- 값은 B06 이 낸 `spoil_fill_area_m2` 를 그대로 옮김 — 여기서 더하거나 빼지 않음
  (`fill_area_m2` 에서 이미 빠져 있음 · 확정 ㉠ 같은 흙을 두 번 세지 않기)
- 사토장이 없는 측점은 값이 안 실려 종전처럼 빈칸

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 채움콘크리트 계수가 돌 종류로 갈리는데(깬돌 0.2 · 야면석 0.15) 근거 문구에
  종류가 안 적히던 자리 — 값은 바뀌는데 왜 바뀌었는지가 화면에 안 보였음.
  고임돌은 이미 적고 있었으므로 같은 규칙으로 맞춤.
- 병합 해결 과정에서 골막이 두께식 주석 두 줄이 한 줄로 붙은 것 복구.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠⚠ **차단인지는 `blocked_kind` 가 정한다 — 문구가 아니다.**
배수관 다섯 줄이 `blocked_kind=None · in_bill=True` 인데도 **사유가 있다는 것만으로**
막혀 금액이 안 서고 있었음. 그 사유는 차단이 아니라 **주의 문구**였음 —
「관종을 안 정해 기본값(파형강관)으로 섰습니다」.
⇒ 사유만 온 줄은 **금액을 세우고 그 문구를 곁말(ⓘ)로** 닮. 차단 표시가 붙은 줄은 그대로 막음.
ⓘ 오늘 두 번째 같은 병임 — 아침엔 겹침 설명을 `blocked_reason` 에 넣었더니 막힌 줄로 읽혔음.

⚠ 그리고 막힘이 풀리자 **다음 벽**이 드러남 — 관부설 12-11 표를 한 줄도 못 읽고 있었음.
그 표는 **규격이 열**(∅800·∅1000·∅1200)이고 값이 **나눗셈 식**(「0.62/2.5」 = 관 2.5m
한 개당 0.62시간 ⇒ m 당 환산값)임.
- `match_spec_column_table` 신설 — 첫 줄이 규격 이름만 늘어선 표일 때만 내 표로 봄
- 「0.016/2.5/2」처럼 겹친 나눗셈도 읽음 · 값이 빈 칸(기초콘크리트·거푸집)은 건너뜀
- 관경마다 갈래가 섬. B08 이 「Ø800」으로 보내도 「∅800mm」 갈래에 붙음

결과 — 배수관 네 줄이 처음으로 금액이 섬
  Ø1000 10m × 10,903.7 = 109,037 · Ø800 11m × 10,973.0 = 120,703 ·
  Ø800 9m ×2 = 197,514  ⇒ 합 **427,254원**
  본체 31,118,251 → **31,545,505원**
  ⚠ Ø1500 은 품셈 표에 그 관경이 없어(800·1000·1200) 그대로 막힘 — 후보만 보임

검증: pytest 307 통과(신규 4) · 자원 축 547 → 565 줄

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠⚠ **깨진 시험의 뿌리는 칸이 아니라 자리였음.** 정책 시험은 `tmp/tests` 라 **git 밖**이라
정본(추적됨)만 다른 창에 가고 예외 목록(추적 안 됨)은 안 따라감 ⇒ **다른 창에서만 깨짐.**
오늘 그 일이 두 번 났음. ⇒ **까닭을 값 옆(정본)에 두어 함께 움직이게 함.**

- 스키마에 칸 둘 신설
  · `empty_means` — **「비워 두는 것이 뜻인 칸」**(세 번째 갈래). 비면 계산 쪽이 기준값으로
    돌고 그 사실이 화면에 뜸. 값을 넣으면 그 값이 이김
  · `default_basis` — 기본값이 **도메인 확정값이 아닐 때** 그 뜻(「다단 없음」·「안 더함」).
    법정·확정 수치면 비워 둠 — 비어 있는 것이 「확정값」이라는 뜻
- 56곳에 까닭을 적음 — 전면 기울기 · 야면석 계수 · 채움 강도 · 비탈 기울기 · 물빼기 둘 ·
  개거 규격 · 뒷길이 · 돌 종류 / 단 수 · 올림 · 이동 · 조달 · 설치 측 · 추가 운반거리
- 정책 시험이 그 칸을 읽게 바꿈 + 까닭이 한 낱말이면 잡는 시험 둘 추가

⇒ 앞으로 등록부에 칸을 열 때 **예외 목록을 고치지 말고 까닭을 값 옆에 적을 것.**

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
정본 여섯 탭 전수 확인 구간이 H=1.0~3.0 인데 코드가 높이를 막지 않고
표준경사표는 직고 7m 까지 칸을 준다 — 높은 벽이 실제로 설 수 있음.
그 구간에서 막자갈 두께(= 물량 ÷ 비탈면적)가 0.375 ÷ √(1+경사²) 로 거의
붙박이라, 직고와 함께 두꺼워지는 품셈 13-4-4 [주]⑨ 범위보다 얇아짐
(H 3.0 0.359 안 · H 3.5 0.354 아래). 방향이 반대라 값만 보면 안 드러남.

값은 정본 식대로 세우고 막지도 눅이지도 않음 — 근거 구간 밖이라는 사실만
사유로 냄. 큰돌쌓기는 막자갈 줄 자체가 없어 이 갈림이 안 번짐.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
TS 짝이 2026-09-04 에 이미 이 선으로 갈라 두었음(`common_util_cross_design_geometry.ts`).
**새로 긋는 선이 아니라 TS 에 있던 선을 파이썬에도 그은 것**이라 거울이 안 깨짐.

- `_SectionGeometry` + `_side_role`(TS `sideRole`) → `…_Engine_Design_Geometry.py`
- 안 옮긴 것 — 측구 방향 해석 · 지반 보간 · 사면 폐합 허용오차. **TS 도 본체에 둔 것들**
- 계산은 **한 줄도 안 바꿈**. 옮기기만 함

검증 — 거울 시험(횡단 설계선·단면적 두 쪽 대조) 통과. 전체 610 통과 / 22 건너뜀.
남은 것 — ② 표준값 해석·저장분 읽기 도우미 분리(522줄이라 급하진 않음).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 표토제거: 대상 면적 0 ㎡ 에 0 ㎥ 를 「값 있음」으로 내고 있었음. 0 은 「없음」과
  구별이 안 되고 받는 쪽이 「표토가 없는 노선」으로 읽음. 두께 미입력은 이미
  막고 있었는데 면적 0 만 통과하던 자리. 운반 줄은 제거를 밑수로 삼아 함께 막힘.
- 표토 대상 면적이 별표2 문언과 두 방향으로 어긋남 — 법은 「노면·절토대상지」인데
  우리는 절토·성토 사면적을 다 더하고 노면(연장 × 노폭)은 안 셈. 성토대상지는
  별표2 (7) 이 「제거·정리」로만 두어 운반·적치 의무를 안 검. 값은 그대로 두고
  사유로만 드러냄 — 실무 확인 사항이라 임의로 확정하지 않음.
- 비탈 규준틀 재료량이 「수평 값 준용」인 사실이 상수 주석에만 있고 화면 근거에는
  없었음 — 값이 서면 어디서 온 값인지 안 보이던 자리.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
「품셈 표에 그 관경이 없음」만 적으면 사용자가 **엉뚱한 것을 정하러 감** — 정할 것이
단가가 아니라 **시설 선택**일 수 있음.

- 관부설 품셈 표가 다루는 관경은 ∅800·∅1000·∅1200 뿐임을 사유에 적음
- Ø1,500 이상이면 임도기술교본 3장을 가리킴 — 「BOX암거 적용 — 수리계산상 배수관
  **Ø1,500㎜ 이상** 적용 유역」(`횡단배수관_암거 §5`)
- ⚠ **단정하지 않음** — 그 §5 는 **교본 기준이지 법령·행정규칙이 아님**. 프로젝트 규칙이
  「기본값은 현행 법령·행정규칙, 교본은 과거 참조」라 **가리키기만** 하고 사유에 그 사실을
  함께 적음

검증: pytest 307 통과 · Ø1500 두 줄에 그 문구가 뜸

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
배수관 네 줄이 금액으로 섰으나 그 값은 **인력 품만**임 — 파형강관·커플링밴드·
크레인(5ton)·모래부설이 아직 안 붙음. 까닭이 둘로 갈림:
  · 관·모래 — 원문이 「별산」·「설계수량」이라 한 자리
  · 크레인 — 기계 카탈로그에 없음(9-9 목록에 올림)

 원문을 대조하다 **숨은 값** 하나 나옴 — 커플링밴드는 표가 비었으나 [주]① 이
「**1EA/6m**」를 줌. 자재가 서면 m 당 1/6 EA 로 셀 수 있음(「필요시 별도 산정」 조건 하나 더).

ⓘ 원문 특이점도 계획서에 적어 둠 — 배관공이 ∅800 0.25 · ∅1000 **0.22** · ∅1200 0.41 로
**가운데만 작음**. 크레인·보통인부는 관경이 커질수록 늘어남. **원문 그대로라 손대지 않음.**

검증: pytest 307 통과 · ∅800 0.25/8.0 = 0.03125 로 열 순서가 맞음을 원문과 대조

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ **시험만으로는 안 잡히던 자리임.** 실제 프로젝트에 사토장을 놓고 눈으로 본 뒤 잡음.

① **사토장을 지워도 값이 남음** — `enforce_spoil_fills` 가 **얹기만** 해서, 구조물을
   지운 뒤에도 저장분의 `spoil_fill_*` 가 그대로 남아 횡단도에 계속 그려지고 면적표에도
   섰음. ⇒ 사토장이 덮지 않는 측점에 **값이 남아 있으면** 사토장 없이 다시 계산해 지움.
   노선 성토도 그때 원래 값으로 돌아옴(사토장 몫을 빼 두었던 것이 복구됨).
   ⚠ **칸이 있는 것과 값이 있는 것은 다름** — 설계 결과는 사토장이 없어도 `0.0` 을 늘
     실으므로 「값이 남은」 측점만 되돌림(`_has_spoil_value`)
② **말풍선에 늘 뜨던 가짜 경고** — 「⚠ 0.0㎥ 는 못 담음」. 폭을 이분법으로 찾아
   400 − 399.9937 = 0.0063 이 남는 것이라, 표시 자릿수에서 안 보이는 몫은 경고 안 함

실측(프로젝트 fa76c162) — 지운 뒤 사토장 0 · 용량 null · 노선 성토가 정확히
「지우기 전 + 옮겨 갔던 몫」으로 복구됨(100m 1.7563+4.9217=6.678 …).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
원문·실무 대조에서 나온 것:
- 품셈 9-15-2(답외구간) 원문에 T(표토두께) 0.2m · L(운반거리) 20m 가 적용값으로
  박혀 있음. 종전 사유 「품셈이 정하는 값이 아닙니다」가 반쪽이라 정정 — 값을
  자동으로 넣지는 않되 원문에 있는 값을 없다고 말하지도 않음.
- 그 품에 20m 압토가 이미 들어 있음. 실무 내역서(영월 2024)도 「표토제거 답외구간
  / M2 · 도자 19Ton · D=20」 한 줄뿐이고 운반 줄이 따로 없음. 우리 운반 줄은
  20m 를 넘는 몫일 때만 새 줄인데 그 가름을 아직 안 함 — 사유로 남김.
- FP-10-12(덤프 운반)은 부모 코드라 품이 없음. 잎은 토사/암절취/발파암이고
  갈래를 안 보내면 B09 가 후보만 보이고 금액이 안 섬. 표토는 토사이므로
  variant_axis=ground_class · variant_value=토사 로 실어 보냄. 준비공 줄이
  갈래를 넘길 통로도 함께 엶(종전에는 늘 None).

파일 분리(700줄 제한):
- 부대시설 다섯 줄을 _Preparation_Ancillary 로, 상태 낱말을 _Preparation_Status 로
  가름. 상태 문자열은 받는 쪽 판정에 쓰이므로 두 벌이 되지 않게 한 벌만 둠.
  710줄 → 622 + 113 + 16.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
777줄이던 _Handoff_Rows 를 565 + 255 로 가름. 줄의 모양은 안 바뀜 —
갈라낸 넷을 본체에서 다시 내보내 부르는 쪽 import 도 그대로임.
상태 낱말은 _Preparation_Status 한 벌에서 읽음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 레지스트리 이름이 없으면 내역 줄 이름에 코드값이 그대로 떴음(`retaining_wall`).
  _Wording.type_label 이 이미 대비표를 들고 있으므로 그것을 씀 — 이제 「옹벽」으로 섬.
- 관측 원단위로 가는 구조물은 표에 터파기 줄이 없으면 그 구조물만 조용히 빠졌음.
  옹벽이 터파기 0 줄인데 사유도 안 났음(돌쌓기는 세 줄이 섬). 값을 지어내지 않고
  「터파기가 안 선 구조물」 줄을 in_bill False · blocked_kind unit_data_missing 로
  세워 빠졌다는 사실이 보이게 함.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
랩탑 메인이 화면에서 잡음: 「측구터파기 · 굴삭기+브레카」가 work_item_code null
인데 blocked_kind 도 null 이라 아무 말 없이 금액만 빠졌음.

인계본의 bill_flag_warnings·unmatched_work_items 에는 이미 실려 있었음 —
목록은 있는데 줄에 표시가 없었던 것. 줄 단위로 보는 쪽(B09·화면)은 목록을 안 봄.
같은 모양이 여덟 줄이었음(흙깎기·측구터파기·도자운반 둘·덤프운반 둘·지장목제거·큰돌쌓기).

- 토공 줄: 코드가 없으면 시공법 미지정이면 input_missing, 매핑을 못 이었으면
  unit_data_missing 으로 갈라 답. 다음에 할 일이 다름(사용자 입력 vs 매핑 작업).
- 운반 줄: 같은 규칙. 무대(free_haul)는 품에 포함이라 안 세우는 것이지 막힌 게
  아니므로 표시를 안 답.
- 불변식 시험을 세움 — 코드도 막힘 표시도 없이 내역에 서는 줄이 하나라도 있으면 깨짐.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠⚠ 한 칸(`ditch_enabled`)에 **두 뜻**이 담겨 있었음.
결과(실제 섰나)를 그대로 다시 입력으로 넣어 읽었으므로 **한 번 저장되면 자동 판정이
영영 다시 안 돌았음.** 계획고를 내려 절토가 생겨도 측구가 안 서고 **아무 말도 안 나왔음.**

- **선택** `ditch_choice` (없음 = 자동) · **결과** `ditch_enabled` (실제 섰나)로 가름
- 자동 판정을 **먼저** 하고 선택을 그 위에 얹음. 양성 단면은 선택보다 기하가 먼저
- ⚠ **옛 저장분은 자동값과 다를 때만 선택으로 살림** — 같으면 자동이 그렇게 냈던 것이고
  다르면 사용자가 일부러 바꾼 것임. 설계 의도를 잃지 않으면서 굳은 값을 푼 것
  (오늘 `length_m` 에서 겪은 「저장분이 걸린 자리」를 같은 방식으로 처리)
- 화면 카드는 이제 **선택**을 읽어 상태를 세우고, 표시는 **결과**를 보임
- 파이썬·TS 짝 양쪽 + 호출부 여섯 곳(재계산·저장·확정·사토장·요청 스키마)

시험 다섯 추가 — 「결과를 다시 넣어도 자동이 계속 돎」이 그 잠금. 전체 616 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
물넘이포장이 면적을 못 받아 「0.0 ㎡」로 내역에 서고 있었음. 코드가 붙어 있어
0 원 줄이 만들어지고 화면에는 값이 있는 줄로 보임 — 0 은 「없음」과 구별이 안 됨.
줄은 그대로 넘기되 in_bill False + 까닭(원단위 사유 그대로) + input_missing 로 둠.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
화면 토글이 **2단**이라 「자동으로 되돌리기」 단추가 없음. 되돌리려면 원래 값으로 다시
누르는 수밖에 없는데, 그것을 선택으로 굳히면 **방금 고친 병이 그대로 되돌아옴**
(지형이 바뀌어도 안 따라감).

⇒ 선택이 자동값과 같으면 **선택 없음(자동)** 으로 본다. 파이썬·TS 짝 양쪽.
시험 하나 추가 — 「자동과 같은 선택은 자동으로 푼다」. 전체 617 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정 5차 6번 「제근 밑수 — 면적 축. 건설품셈 3-9-2 「1,000㎡당」을 빌려 씀」.

- `WorkItemUnit.BORROWED_UNITS` 신설 — **사용자가 정한 자리만** 담음. 우리가 골라 채우는
  표가 아님. 값과 **근거 문구를 한 자리에** 둠(⚠ 교차 참조 표시 — 임도 전용 품이 있는데
  건설품셈을 쓰는 것이라 화면이 그 사실을 밝혀야 함)
- ⚠⚠ `BORROWED_BASIS_PER` — **「1,000㎡당」이라 ÷1,000 환산**. 단위만 「㎡」로 달고 값을
  그대로 두면 **금액이 천 배**가 됨. 단위와 배수를 한 자리에 두고 시험으로 못 박음
- ⇒ 제근 여섯 갈래에 밑수가 붙어 단가가 섬 — 굴착기 0.7㎥·소림 **55.4원/㎡**

⚠ **자릿수가 견준 값과 어긋남을 사유에 함께 적음** — 실무 영월 「뿌리뽑기」는 475원/㎡ 이고,
빌려 온 3-9-2 는 같은 1,000㎡당에 굴착기(0.2㎥) 3.76hr 로 산림품셈 9-21 의 0.80hr 보다
4.7배 큼. **100㎡당으로 보면 실무와 자릿수가 맞음.** 값은 확정대로 두고 **어긋남을 보임** —
지어내지도, 조용히 넘기지도 않음.

검증: pytest 311 통과(신규 4)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
⚠ **뿌리** — `tmp/` 는 창 사이에 안 건너감(실측 확인: 상대 창이 놓은 `tmp/_sync_probe.txt`
가 시간을 두고 두 번 봐도 안 보임). 그래서 **정본(등록부 스키마)만 건너가고 그것을 읽는
시험은 안 건너가** 오늘 두 번, 같은 시험이 **연 창은 통과·받은 창은 실패**가 됐음.

- `tmp/tests/*` 를 `resources/tester/` 로 **복사**(127 파일). 내용은 **한 줄도 안 고침**
- `tmp/tests` 는 **남겨 둠** — 되돌릴 자리(사용자 지시)
- 실행: `./venv/Scripts/python.exe -m pytest resources/tester/ -q`
  옮기기 전과 **같은 수**: 617 통과 / 22 건너뜀 / 실패 0

⇒ 이제 시험·예외·까닭이 **정본과 함께** 움직임. 오늘 세운 「예외는 정본 스키마에」와 짝임.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
tmp/ 가 창끼리 안 건너가는 것이 확정돼(랩탑이 시간 두고 두 번 확인) 시험·예외가
저절로 건너가도록 git 안으로 옮김. 사용자 확정.

- 내용은 하나도 안 고침 — 자리만 옮김. tmp/tests 는 남겨 둠.
- 같은 이름이 이미 있던 64 개는 랩탑 것을 그대로 두고 건너뜀.
- helper_b05_*.js 둘은 랩탑이 .cjs 로 이미 올린 것과 **줄바꿈만 다른 같은 내용**이라
  복사본을 도로 뺌(시험이 .cjs 를 부름).
- resources/tester/ 에서 전체 1176 통과 · 29 건너뜀 · 실패 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- `docs/` 를 .gitignore 에서 빼 git 추적 대상으로 전환 (위키·완료 이력·검증 기록)
- `docs/raw/PLAN.md` · `docs/raw/OWNERS.md` 를 저장소 최상위로 이동 후 .gitignore 에 등록
  — 창끼리 공유하되 저장소에는 안 올리는 장부
- 살아 있는 경로 참조 7개 파일 정정 (아카이브 107건은 그때 사실이라 그대로 둠)
- graphify 날짜별 산출물(`docs/wiki/graphify-out/20*/`) 제외 — `graphify update` 가 다시 만듦

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
eomsangdon merged commit 46795d1f18 into main 2026-09-09 18:21:28 +09:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: eomsangdon/Aislo#13