Commit Graph
110 Commits
Author SHA1 Message Date
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 d78f59ba5c feat(B09): 밑수 반영 재생성 + 밑수 미확보 줄 차단 + ㉡ 무대 가드 가동
B08 이 밑수(「10㎡당」 같은 기준 수량)를 본문에서 찾아 181표를 채움.
그 위에서 자원 축·일위대가를 다시 냄

- **떼채취 평떼 1,032,408 → 10,324원/㎡** — 100 배 부풀어 있던 것이 교정됨.
  「100매당일 것」이라던 의심이 실제로 `100㎡당`이었음
- 기준 미상 122 → 40, 100만원 초과 10 → 2 건. 중앙값 73,989 → 48,961
- 파생물 지문이 새 마스터(`fe454c56…`)로 따라 바뀜 — 낡음 감지 장치가
  처음으로 실제 갱신에서 동작 확인됨

밑수 미확보 표(`basis_missing` 144건 → 26 공종)
- 1 단위당으로 단정하면 곱셈이 10배·100배 틀리므로 **곱하지 않음**.
  내역서에 「밑수를 못 찾은 표입니다 — 곱하지 않았습니다. 원문 4-4. 가지정리」로 뜸

㉡ 무대 가드 가동 (B08 이 운반을 실물로 내기 시작)
- 인계에서 `haul_distance_m`·`haul_equipment` 를 받아 조판에서 실제로 호출
- 무대(20 m 이내)는 줄로 서되 금액 없음. 운반토량 합이 총 절취량을 넘는지도 검사
- 짝 시험 — 무대에 단가가 붙으면 멈추고, **암 운반·덤프 줄은 안 걸림**

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

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:11:32 +09:00
eomsangdon 612909ac39 Merge remote-tracking branch 'origin/main_desktop_1' into sub_desktop_1 2026-09-08 01:06:07 +09:00
eomsangdonandClaude Opus 5 06329e2101 fix(B09): 표 자리 맞춤을 개수 대조로 바꿔 조용한 오독 3종 차단
2단 표를 열자마자 과잉 매칭이 드러남 — 자원 축이 208 → 373 으로 뛰고
최대 단가가 2,436만원이 됨. 「한 칸 밀림」 가정이 표마다 안 맞았음

- **좌우 두 판 + 2단 머리** — 뿌리돌림 05-2 는 `근원직경 | 수량 | 근원직경 |
  수량`이라 오른쪽 판의 **직경 100 이 「특별인부 100인」**으로 읽혔음.
  첫 줄 머리가 되풀이되면 2단이라도 버림
- **라벨 칸 수가 표마다 다름** — 드론방제 08-6-2 는 라벨이 둘(`구 분 | 항 목`).
  고정 보정 대신 **숫자 칸을 순서대로** 맞추고 개수가 다르면 그 행을 버림.
  또 머리 줄 이름을 하나라도 못 풀면 표째 버림 — 넷 중 둘만 풀린 채
  숫자 둘이 **엉뚱한 직종**에 붙고 있었음
- **차원이 하나 더 있는 표** — 뭉기기 13-12-1 은 행이 공정, 숫자 칸이 토질
  3갈래인데 자원 열은 하나뿐이라 **첫 토질 값만 조용히** 서고 있었음.
  숫자 칸이 자원 열보다 많으면 버림

결과: 자원 축 231줄(갈래 88) · 일위대가 133 · 최대 5,030,954.6
(품셈대로인 값). 철근 12-3 과 콘크리트 타설 12-1 3갈래는 그대로 섬

검증: pytest 167 통과(신규 2). 갈래 표 5건 손대조 — 전부 표와 일치

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:05:11 +09:00
eomsangdonandClaude Opus 5 c12b1027f7 feat(B08): 콘크리트 타설 갈래 — 철근 유무 자동 판정
조율 창 판정 반영. 타설 공종은 타설 방식 × 구조물 종류로 갈림.

- **구조물 종류는 자동 판정** — 원단위 성분에 철근이 있으면 철근구조물.
  사람이 고르는 값이 아님. 옹벽 관측 원단위의 D13·D16 에서 그대로 나옴.
- **타설 방식은 설계 판단**이라 프로젝트 설정(`quantity.concrete_placing_method`)이
  고르고 기본은 레디믹스트(FP-12-01-01). 잠정이며 사용자 확정 대기.
  모르는 방식이면 기본으로 떨어지되 그 사실을 알림.
- 옹벽 묶음의 타설 코드를 `FP-12-01-01#철근구조물` 로 좁힘.
- ⚠ 묶음 넷 중 `FP-12-03`·`FP-12-25` 는 B09 일위대가가 아직 안 섬.
  `composite_not_ready` 로 함께 알림 — 지금 세우면 절반짜리가 됨.

검증 — 인계 48건 통과, 전체 578 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:03:55 +09:00
eomsangdonandClaude Opus 5 c357381355 fix(B08): 품셈 밑수를 원문 본문에서 읽음 — 곱셈 10배·100배 오차 자리
서브 창 제보(기준 단위 없이 도는 단가 125 중 122)의 뿌리. 밑수는 표 안이 아니라
**표 바로 위 본문**에 있음 — `### 12-2. 표면 마무리` 다음 줄의 `(단위: ㎡당)`.
표만 보면 못 찾고, 못 찾은 채 두면 「10㎡당」 표를 1㎡당으로 알아 곱셈이 10배 틀림.

- 원문 md 를 함께 열어 표 위 6줄에서 밑수를 읽음. **본문이 정본, 표 안 긁기는 보조** —
  13-3-1 이 본문 `(단위: ㎥당)` 인데 표 안 긁기가 비고의 `10㎡` 를 물어 오던 자리.
- `(단위: 인/㎡당)` 꼴은 **분모가 밑수** — 값의 단위(인)를 밑수로 읽으면 뜻이 뒤집힘.
- ⚠ 「당」도 「단위:」도 없으면 밑수가 아님. 처음에 조건을 느슨히 두어
  `(무한궤도,0.7㎥)` 를 「0.7㎥당」으로 읽어 5건이 잘못 잡혔음 — 조여서 고침.
- 위로 거슬러 보되 **다른 표에 닿으면 멈춤** — 앞 표의 밑수를 물어 오면 조용히 틀림.

밑수 확보 13 → 183 (그중 묶음 기준 36건: 떼채취 100㎡ · 큰돌쌓기 10㎡ ·
뒷채움 100㎡ · 묘목 1000본 · 헬기방제 160ha 등). 못 찾은 144건은
`basis_missing_2026-01-01.json` 으로 냄 — 곱해야 하는 형태만 담아 잡음을 줄임.
빈칸으로 두면 1단위당으로 오해되므로 목록으로 드러냄.

앞서 확인한 「밑수가 밀렸나」와는 다른 물음이었음 — 이번은 「아예 안 적혔나」.

검증 — 품셈 30건 통과, 전체 575 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:02:21 +09:00
eomsangdonandClaude Opus 5 f0608bd315 feat(B09): 2단 열 머리 표 읽기 + 「계」 열 이중계상 차단
- 자원 이름이 **둘째 줄**에 오는 표를 읽음 (철근 12-3:
  `구조별 | 가공 | 조립 | 계` 아래에 `철근공(인) | 보통인부(인)` 세 벌)
- ⚠ 「계」 열은 가공 + 조립을 이미 더한 값이라 **통째로 뺌** — 같이 읽으면
  두 번 셈(㉤ 열 방향 사고 자리). 검산: 간단 = 1.07 + 1.69 = 2.76 으로
  품셈 「계」와 일치
- 머리 줄에는 갈래 칸이 없어 자료 행과 한 칸 어긋나는 것 보정
- 열 머리 되풀이 금지는 **1단 표에만** 적용. 2단 표에서 같은 직종이
  공정마다 되풀이되는 것은 정상이라, 한 규칙으로 뭉치면 철근이 통째로 버려짐
- 내역서 후보 목록에 **규격 갈래**(`#무근구조물`)도 넣음 —
  B08 이 갈래 없는 코드를 보내면 후보로 보이고 임의로 안 고름

철근 현장가공 및 조립 4갈래 성립 (간단 919,146.7 … 매우복잡 1,278,375.3)

검증: pytest 165 통과(신규 2 — 「계」 열 제외 확인 + 되풀이 규칙 짝 시험)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:59:45 +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 8e78940b7a feat(B08): 거푸집 사용횟수 + 공종코드 잇기
- 거푸집 사용횟수는 **관측값이 아니라 법**임. 품셈 1-7-1 이 구조물 종류별로
  정해 둠(옹벽 3회 · 보호공 기초 6회). 원문 문구를 데이터에 싣고 우리 구조물이
  어느 예시에 걸리는지 적음. 걸리는 예시가 없으면 「사용횟수 미확보」.
- ⚠ 횟수별 재료 환산(품셈 12-4 합판 3회 46.1 %)은 **하지 않음**. 그 비율은
  일위대가 재료비에 걸리는 값이라 B08 이 곱하면 B09 와 겹쳐 두 번 줌.
  B08 이 내는 것은 접촉 면적 그대로 + 몇 회짜리인가까지. 시험으로 못 박음.
- 동바리는 슬래브를 떠받칠 때 쓰는 것이라 지금 서는 구조물(옹벽·집수정)은
  대상이 아님. 0 으로 적지 않고 「대상 없음 + 사유」로 냄.
- 거푸집 이름은 정확 일치로만 봄 — 부분일치면 「거푸집씻기」(공사용수)가 걸림.

공종코드 잇기
- 집수정 → FP-12-15, 물넘이포장 → FP-12-06 로 이음.
- 옹벽은 **품셈 12장에 그 이름의 공종이 없음**. 빈 코드로 두면 「매핑을 못 찾은
  줄」과 구별이 안 되므로 `composite` 로 묶음(타설+거푸집+철근+기초잡석)을 적음.
  일위대가 조립은 B09 몫이고 B08 은 물량과 묶음만 넘김.

검증 — 거푸집 8건 · 인계 45건 통과, 전체 558 passed. tsc 오류 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:45:02 +09:00
eomsangdonandClaude Opus 5 513769796f feat(B08): 콘크리트 구조물 관측 원단위 + 품셈 몫 표시
⑩ 콘크리트 구조물. 품셈에 구조물별 표준 물량표가 없어(구조물_수량.md ·
배수공_수량.md §2) 실무 설계원본 관측값을 데이터 파일로 둠.

- `resources/data_structure_unit/` — 반중력식옹벽 H=2.0(m당) · 돌집수정 ㄷ/ㄴ형 ·
  집수정 Ø800 · 콘크리트포장 T=20cm. 줄마다 출처를 실음.
- 규격 정확 일치로만 씀. 보간하지 않음 — H=1.6 을 H=2.0 에서 줄여 쓰면 틀림
  (기초·벽 두께는 높이에 비례하지 않음). 안 맞으면 「원단위 미확보」로 드러내고
  표에 있는 규격을 함께 알림.
- BOX암거·세월교는 관측값도 없고 저장 제원에 두께가 없어 전개식도 못 세움.
  `not_found` 에 사유와 함께 남기고 미확보로 냄 — 두께를 지어내면 콘크리트·
  거푸집·철근으로 번져 나감.
- 성분마다 `basis_kind`(derived/observed)를 달아 화면에 「치수 전개 / 실무 관측」
  으로 보임. 두 근거가 한 표에 섞이므로 안 적으면 되짚을 수 없음.
- 배수관의 유입부 집수정을 별도 줄로 세움. 품셈도 관부설과 집수정을 다른
  공종으로 둠 — 한 줄로 합치면 어느 쪽 물량인지 못 가름.

품셈 몫 표시 (조율 창 제보 교차 확인)
- `인력(10%)`·`장비(90%)` 처럼 딱지가 비율을 달고 오는 표 25건 확인. 형태 판정은
  정상(requirement)이었으나 **장비 몫이 시공능력 공식이라 값이 아님**을 아무도
  알 수 없었음. `resource_shares`·`partial_ratio` 를 실어 「단가가 일부만 선 것」이
  정상으로 흘러가지 않게 함. 공식 기호는 첫 표에만 있고 뒤 표가 물려받으므로
  기호 유무가 아니라 몫 유무로 판정 — 기호로 세면 절반을 놓침(9-13-2).

반영률 계약 갱신 — breakdown 을 늘 실음(`application_ratio_breakdown` ·
`quantity_breakdown`). `application_ratio_pct` 는 두 율이 같을 때만 채우는 편의값.

검증 — 관측 원단위 17건 · 인계 43건 · 품셈 23건 통과, 전체 548 passed. tsc 오류 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:38:18 +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 2b21c2ff5c merge: origin/main_desktop_1 되받기 (B08 공종 마스터 재생성 ab39c174)
로케일 충돌 1건 해소 — B08 구역 줄바꿈 차이뿐, 상대 쪽 서식 채택
(내 B09 키는 자동 병합됨).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:10:24 +09:00
eomsangdonandClaude Opus 5 ab39c174aa feat(B08): B09 인계 두 벌 + 품셈 딱지형 표 판정 보완
일감 9. 수량 결과(작업 공종 축)와 자재 총괄(자재 축)을 각각 낸다.

- 자재 줄에는 공종코드를 붙이지 않음. 붙이면 자재가 내역 줄로 오해되어
  이중계상이 됨. `verify_no_code_on_materials()` 로 코드에 못 박음.
- `in_bill` 을 실어 무대·합계 줄을 가름. 수량은 그대로 넘김 —
  무대+도자+덤프 = 총 운반토량 검산에 쓰이는 값이라 빼면 검산이 죽음.
- `ground_class_set` 동봉. 「연암」이 몇 갈래 중 하나인지 알아야 예산내역서가 섬.
- 매핑표는 데이터 파일(`resources/data_work_item_mapping/`). 못 이은 줄은
  빈 코드로 두지 않고 `unmatched_work_items` 로 냄.

품셈 형태 판정 교차 확인 — 「첫 칸이 갈래 딱지이고 이름이 둘째 칸」인 표에서
직종을 첫 세 행에서만 찾아 12장 구조물 표 8건이 미판정으로 빠져 있었음.
딱지를 알아보는 규칙을 맨 마지막에 두어 앞 판정을 흔들지 않고 해소
(미판정 85 → 77, 생산량형 16건 불변). 비율 지시를 먼저 보면 강관동바리 같은
소요량표가 참조로 넘어가므로 소요량을 먼저 보게 순서를 잡음.

검증 — 인계 22건 + 품셈 5건 통과, 전체 500 passed.
실서버 `GET /quantity/handoff` 200 (내역 10줄·제외 1·자재 4, 갈래세트 5).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 00:04:32 +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 aecea153e2 fix(B08): 석재 할증률 건설품셈 대조 — 후보와 미확보를 데이터에 명시
조율 창 지적으로 건설공사 표준품셈 1-3-1 을 대조함. 결과를 데이터 파일에
근거와 함께 남김.

- 야면석·고임돌·물구멍 — 산림·건설 두 품셈 모두 이름 없음(`not_found`).
  건설품셈이 다루는 석재는 해상 사석과 원석(마름돌용)뿐이고 제7장 돌공사에는
  재료 할증률표 자체가 없음. 확인한 범위를 `checked` 로 함께 기록.
- 막자갈 — 건설품셈 2호 노반재료에 4 % 로 있으나 우리 쓰임은 뒤채움이라
  조건이 다름. `candidates_pending_user` 에 조건과 함께 두고 엔진은 쓰지 않음
  (지식DB 는 근거 가이드이지 값을 확정하는 곳이 아님).
- 산림품셈 값에는 `pumsem: forest` 표시. 보완 출처를 섞지 않기 위함.
- 물구멍은 공제 대상이 아니라 관 자재임을 코드에 명시. 관 규격(법 Ø3~6㎝ /
  실무 Ø50)과 간격(법 2~3㎡ / 엔진 2.0)이 미확정임을 잠정으로 표시.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 23:48:28 +09:00
eomsangdon e52f18769c auto: 2026-09-07 23:47 (EOMSANGDON-HOME) 2026-09-07 23:47:47 +09:00
eomsangdonandClaude Opus 5 6a487fc6e3 feat(B08): 자재총괄 — 할증이 붙는 유일한 자리
구조물 원단위의 `destination == "material"` 성분만 모아 자재별 합산 후
할증률을 한 번만 적용. 열은 순수량·할증률·합계 + 관급구분·설치주체·비고이며
금액은 없음(B09 경계).

- 할증률은 코드가 아니라 데이터 — `resources/data_material_surcharge/`
  (품셈 1-3-1 재료 할증률 19종 + sha256 매니페스트). 실무 관측값은
  `observed_practice` 로 분리(법대로 원칙).
- 표에 없는 자재는 0 % 로 넘기지 않고 「할증률 미확보」로 표시.
  이름 조회는 정확 일치 — 부분일치면 `막자갈` 이 `자갈` 할증을 뭄.
- 이중계상 방어 ㉠ — 앞 단계 `surcharge_applied` 깃발을 실제로 읽어 경고.
  자재총괄 응답은 `True`, 원단위표는 `False` 로 어느 쪽 값인지 명시.
- 관급/사급 이름은 B09 와 동일(`owner_supplied`/`contractor_supplied`).
  관급 줄에만 설치 주체(`install_by`)를 붙이고, 미지정은 기본값으로
  때우지 않고 드러냄 — 안전관리비 대상액이 「도급자설치 관급금액」이라서임.
- 라우터 `GET /quantity/material-summary` 신설, 화면에 「구조물 원단위」·
  「자재총괄」 탭 추가. `design_owner` 가 붙은 타입(측구)은 중복 계상 방지로 제외.

검증 — 전용 테스트 23건 통과, 전체 회귀 473 passed(기존 B05 깨짐 1건 제외).
공용 브라우저 실조작으로 탭 5장·머리글·값 4줄·미확보 안내 확인.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 23:43:46 +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 4e6e588b9b feat(B09): 운전경비(연료·잡재료·조종원)를 품셈 8-4 에서 뽑아 시간당 사용료 완성
**빈 두 성분을 채움** — `mach_fuel_rate`·`mach_operator_map` 0건이라 시간당 중기사용료의
재료비·노무비가 비어 있던 자리(손료만 있으면 실제의 4분의 1). 건설품셈 **8-4 운전경비
산정** 표에서 뽑아 **92 기종** 확보.

⚠ **표가 열 단위로 뭉쳐 옴** — PDF 추출 탓에 `분류번호` 한 칸에 코드 31개,
`주연료` 한 칸에 값 31개가 공백으로 이어 붙어 있음. **위치로 짝짓되 개수가 안 맞으면
그 줄을 통째로 버림**(10건 버림, 목록으로 남김). 어긋난 채 짝지으면 **다른 기종의
연료값이 조용히 붙는** 자리라 억지로 안 맞춤.
- 코드는 앞자리를 이어받음 — `0201-0012 0020 0040` → `0201-0020`·`0201-0040`.
- ⚠ **이름 칸은 못 씀** — 표 전체 기종명이 한 덩어리로 옴. **코드로 613 기종
  카탈로그에서 이름·규격을 가져옴**(카탈로그에 없는 코드는 버리고 목록에).

**검증(굴착기 무한궤도 0.7㎥)** — 주연료 11.6 ℓ/hr · 잡재료 22 % · 조종원 1인/일.
시간당 = 재료 26,130(연료 21,418 + 잡재료 4,712) + 노무 35,412 + 경비 24,554 = **86,096**.
STC 2024 관측 96,829 과 **11 % 차** — 손료·재료는 근사하고 **노무가 갈림**
(관측 55,700/hr = 445,600/일로 어느 직종보다 높음). **맞추려 손대지 않음** — 관측값은
대조용이고 우리는 법대로 감. ⚠ 조종원 직종 확인 항목으로 올림.

- **잠정 표시** — 조종원 **직종명이 품셈 8-4 에 없어** `aliases` 기반 규칙(트럭 계열 =
  화물차운전사, 그 밖 = 건설기계운전사)으로 매김. 결과에 `operator_mapping_is_provisional`
  로 드러남. TODO(미결 9-6).
- **유가는 전국평균 잠정**, 지역 파라미터 자리(`region`)만 뚫어 둠 (품셈 8-1-7 5호).
- **파생 파일로 냄** — `resources/data_cost_machine_operating/`, 기준자료 안 건드림.
  `derived_from` 에 `mach_base` 판의 세 쪽을 적어 낡으면 드러나게 함.

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

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 20:49:50 +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
eomsangdonandClaude Opus 5 3497486bed feat(B08): 산림사업 표준품셈 476표 → 공종 마스터 정규화 (공종 축)
PLAN 8-5·8-6·8-7 의 B08 일감 1번. B09 의 ③단가산출을 여는 선행 작업임.

공종의 정체 = 품셈 절 번호
  「9-3-1. 인력」처럼 절 제목이 공종이고 표의 행은 조건별 변형(토질·암종·규격)임.
  계층·정렬은 목차표(F0001)에서 나오고 표가 그 절에 붙음. 목차 477노드,
  표 456/475 귀속(미귀속 19 는 절번호 없는 부록·경과조치).

pum_form — 뒤집히면 값이 조용히 반대가 되는 자리
  productivity(작업능력, 품=1÷값) 16 · requirement(소요량, 품=값÷밑수) 244 ·
  coefficient(시공능력 공식 K·f·E) 19 · reference(1장 적용기준·할증·참조지시) 94 ·
  undetermined 83.
  ⚠ 판정 순서가 뜻을 가짐 — 「작업능력(㎥/hr)」 표의 비고에 「보통인부 1인/일」이
  흔히 붙어 있어 직종을 먼저 보면 생산량형이 소요량형으로 뒤집힘. 생산량형 표지를
  직종보다 앞에 둠.

담당 경계 (PLAN 8-7)
  공종 축만 만들고 자원 축(resource_kind·resource_code·amount)은 안 채움 — B09 몫.
  대신 원문 셀 raw_row 를 그대로 실어 B09 가 476표를 다시 열지 않게 함.
  판정 실패분은 빈칸이 아니라 form_undetermined_*.json 목록으로 냄.

산출 (resources/data_work_item_master/)
  work_item_master_2026-01-01.json · form_undetermined_2026-01-01.json · _manifest.json.
  dataset_version 에 dataset_id·effective_date·sha256 세 쪽 기록 — 재현성.
  공종코드 FP-09-03-01 형식, sort_order 는 STmate 관례대로 256 간격.

검증 — tmp/tests/test_b08_work_item_master.py 14건 전건 통과.
  생산량형이 비고의 직종에 뒤집히지 않는 것, 직종이 둘째 열에 있어도 잡는 것,
  raw_row 보존, 자원 축 미혼입, 미판정의 목록 등재를 각각 못 박음.
  전체 회귀 382 passed (실패 3건은 B05 구조물·코리도 기존 깨짐, 본 변경과 무관).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 20:01:02 +09:00
eomsangdon 8ee858e8fa docs(knowledge): fix forest-road manual layout 2026-09-06 20:10:51 +09:00
eomsangdon 8086c57e18 auto: 2026-09-06 20:05 (ESD_LAPTOP) 2026-09-06 20:05:20 +09:00
eomsangdon 507a7cfc43 auto: 2026-09-06 20:03 (ESD_LAPTOP) 2026-09-06 20:03:36 +09:00
eomsangdon 8dab657930 auto: 2026-09-06 18:14 (ESD_LAPTOP) 2026-09-06 18:14:35 +09:00
eomsangdon 9743416301 auto: 2026-09-06 18:00 (ESD_LAPTOP) 2026-09-06 18:00:40 +09:00
eomsangdon a22886c4c9 auto: 2026-09-06 17:22 (ESD_LAPTOP) 2026-09-06 17:22:50 +09:00
eomsangdon d69d4eb6ec auto: 2026-09-06 17:07 (ESD_LAPTOP) 2026-09-06 17:07:07 +09:00
eomsangdonandClaude Opus 5 43f6325d30 knowledge(교본): 임도 교본 2~6장 수식·표 정리
산림과임업기술(임도) 2장 임도구조 · 3장 임도계획 · 4장 노선측량 ·
5장 설계 · 6장 시공에서 한 줄로 뭉개져 있던 공식을 LaTeX 수식 블록으로
분리하고 기호 설명을 목록화. 본문 값·출처 불변.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-06 16:55:41 +09:00
eomsangdon 724adf25cd Merge remote-tracking branch 'origin/sub_laptop_1' into main_laptop_1 2026-09-06 16:20:55 +09:00
eomsangdonandClaude Opus 5 6fe7004946 knowledge(교본): 산림과임업기술(임도) 그림 파일명 의미화
페이지 번호식 이름(`..._p101_1.png`)을 내용이 드러나는 이름으로 바꿨다.
예: `노선측량_그림5-2-27_중심선과영선의위치비교.png`

- 그림 120개 이름 변경(122개 신규 등록), 본문 md 12개의 링크를 새 이름으로.
- 추출 파이프라인(`_pipeline/pdf2md.py`)과 QC 리포트 갱신.

확인: 그림 127개 · md 이미지 링크 127개 · 깨진 링크 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-06 16:17:10 +09:00
eomsangdonandClaude Opus 5 d0d3f2a311 feat(B07): 자리표 마우스 크기조절·기본 도각 칸 정렬·도면명 미리보기
- 칸이 있는 글자와 그림에 모서리 그립 추가, 모서리를 끌어 칸 크기를 바꾸는 조작 신설 (다른 도면 요소에도 동일 적용)
- 기본 도각(00_template_A1)의 글자 24개에 표제란 칸을 계산해 부여 — 칸 기준 가로·세로 가운데 정렬
- 도각 편집 시 도면명·도면번호도 보던 도면 값으로 미리보기 제공
- 복제 시 미리보기 값 유지 (그립 편집 후 자리표가 토큰으로 되돌아가던 문제)
- CAD index.html 을 캐시하지 않도록 처리 — 빌드 후에도 옛 화면이 남던 문제 해소

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-06 15:52:36 +09:00
eomsangdon 54478394f4 auto: 2026-09-06 11:28 (ESD_LAPTOP) 2026-09-06 11:28:25 +09:00
eomsangdonandClaude Opus 5 698f8f0505 knowledge(임도): 유토곡선 토량배분 기술문서 신설 + 미결 20·21 등재
실무 유토곡선 원본 6건(.MASS · EARTH.DAT) 파싱 관측 수록 — 최종 누가토량 +49~+324㎥,
0선 교차 3~17회, 장비 한계거리 전 건 무대 20.0 / 도자 60.0 m. 평형선 자동 선정·극값
무시 임계·balloon 표기 관행은 현행 근거 공백임을 명시하고 미결 20 으로 등재. 도자
한계거리 60m(실무) vs 70m(현행 구현) 채택은 미결 21.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 07:53:32 +09:00
eomsangdonandClaude Opus 5 3d0215f8d8 feat(B07): 표지에 회사 로고 자리 신설
- `00_template_cover.json` 에 Image 자리 추가 — `{{회사로고}}`,
  x 57.40~137.40 · y 64.06~104.06 (폭 80 · 높이 40)
- 자리는 오른쪽 아래 `{{시행청}}`(기준점 784.35, 84.06)과 좌우로 마주 보게 잡음.
  왼쪽 여백은 `{{연도기번}}`(x 57.4)과 맞추고 세로는 시행청 글자줄에 맞춤
- 값 공급은 도각과 같은 통로 — `build_cover_drawing` 이 이미 `_fill_placeholders` 를
  태우므로 로고를 못 구하면 종전대로 엔티티째 빠짐

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 19:19:57 +09:00
eomsangdon 94883733d5 auto: 2026-09-02 19:08 (EOMSANGDON-HOME) 2026-09-02 19:08:55 +09:00
eomsangdonandClaude Opus 5 b1593bce83 feat(B07): 표제란에 로고·서명 자리 신설 + 시행청·담당자 DB 확장
사용자 지시(2026-09-02) — 로고·서명을 임의로 만들어 표제란에 넣고, 위치·크기는
도각을 고치면 따라오게 하며, 시행청·과업책임자 등은 DB를 넓혀 채울 것.

도각(표제란)
- `00_template_A1.json` 에 그림 자리 2개 추가 — 회사 로고는 용역회사 칸 왼쪽
  (316~348 × 20~36mm), 설계자 서명은 설계 칸 아래(638~680 × 17.5~25.5mm).
  자리·크기가 **템플릿 좌표로만** 정해지므로 도각을 고치면 그대로 따라옴.
- `_fill_placeholders` 가 그림 자리(`imageData`)의 `{{키}}` 도 채움. 값을 못 구하면
  빈 문자열을 남기지 않고 **엔티티째 제거** — 빈 값은 CAD 가 깨진 그림으로 그림.
- `_transform_entity` 가 `points` 배열도 옮김. 그림(로고·서명)과 띠(Hatch)가 이 키를
  쓰는데 여태 변환 대상이 아니라 도각을 옮기면 제자리에 남았음.

DB (`011_title_block.sql`, 전부 ADD COLUMN·NULL 허용)
- `projects` — `client_org`(시행청), `pm_user_id`·`field_lead_user_id`·`designer_user_id`
- `companies.logo_path` · `users.signature_path` — 그림은 파일로 두고 경로만 담음
  (기존 `storage_path`·`input_files` 와 같은 방식)
- FK 는 걸지 않음 — 사유를 파일 머리말에 적음(소프트 삭제·LEFT JOIN·4환경 공유).

배선
- `_title_block_fields` 가 시행청·과업책임자·분야별책임자·설계자(배정 없으면 소유자)와
  로고·서명 data URL 까지 실어 보냄.
- `read_stored_asset()` 신설 — `storage/` 기준 상대 경로의 **파일**을 읽음.
  `resolve_stored_project_path()` 는 폴더를 만드는 프로젝트 루트용이라 파일에 못 씀.

CAD 결함 1건 (이번 작업에서 드러남)
- `screenCanvas.drawController.drawImage` 가 `(width, height)` 를 좌표처럼 변환해
  화면 오프셋과 y 뒤집기가 섞여 들어갔음 — 그림이 제 자리를 벗어나고 비율이 무너짐.
  크기는 배율만 곱하고 자리는 세계 중심으로 잡도록 고침(SVG 컨트롤러와 같은 방식).
- 검증 창구 `__aisloCad.screen(x, y)` 추가 — 세계→화면 좌표. 그림·글자가 제 자리에
  그려졌는지 픽셀로 판정할 때 씀.

검증: `pytest tmp/tests/ -q` 135 passed / 0 failed(그림 자리 3건 신규),
`npx vitest run` 87 passed / 0 failed, `check-types`·`build` 통과.
화면 실측(5174, wdw): 표준도 API Text 24개 `{{` 잔존 0, Image 2개가 도각 좌표
(316,20)-(348,36)·(638,18)-(680,26)에 실림. 캔버스 픽셀 판정 — 두 자리 모두 배경색
외 픽셀이 그려짐(로고 88px·서명 64px), 로고 파랑(20,70,140)이 슬롯 안에서만 검출.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 08:35:25 +09:00
eomsangdonandClaude Opus 5 4cb9b15939 style: 저장소 전체 포맷터 일괄 적용 (prettier·biome·ruff)
파일마다 포맷 폭이 달라(≈80 대 100) 한 줄만 고쳐도 포맷터가 무관한 줄을 대량
재포맷했음. 사용자 지시로 전체를 한 번에 맞춤. 코드 동작 변경 없음 — 포맷만.

- 프론트엔드 `.ts/.css/.html` → 저장소 prettier (`.prettierrc`, printWidth 100)
- `B07_DesignDetail/openwebcad/**` → 자체 biome (tab 들여쓰기·single quote·lineWidth 100).
  `biome format` 만 사용 — `biome lint --write` 는 포맷 아닌 코드 수정까지 하므로 제외
- 파이썬 → `ruff format` (엔진 코드는 이미 정합, resources·scratch 스크립트 24개만 변경)

두 포맷터가 서로 되돌리지 않도록 `.prettierignore` 신규 — openwebcad 와 빌드·산출물
폴더를 prettier 대상에서 뺌. `.prettierrc` 에 `endOfLine: "auto"` 추가 — 기본값 `lf` 가
`core.autocrlf=true` 로 받은 CRLF 파일을 매번 전부 다시 써서 `--list-different` 가
실제 포맷 차이를 가리고 있었음.

검증: `tsc --noEmit` 통과(루트·openwebcad 둘 다), pytest 349 passed / 17 skipped /
0 failed, CAD vitest 87건 중 81 passed / 6 failed(laptop-sub 기준선과 동일, 회귀 없음).
포맷터 재실행 시 prettier·biome 모두 변경 0건.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 07:08:24 +09:00
eomsangdonandClaude Opus 5 44fbe480df feat(B07): 표지를 A1 전면 템플릿으로 만들고 도면 목록에 붙인다
표지는 DRAWING_GROUPS에 kind 없이 라벨만 있어 화면에서 열 수 없었다. 실무 설계도면
원본(울진 소광리, A3) 1쪽의 잉크 bbox를 pymupdf로 mm 실측해 A1로 2배 환산했다.
원본에 도각이 없다 — 좌우 테두리 없이 상·하 굵은 가로선 두 줄뿐이라, 사용자가 고른
"도각 없는 전면 디자인"이 실무 그대로였다.

- resources/template_2dDrawing/00_template_cover.json 신설. 엔티티 14개(재단 표식
  Point 4·띠 Hatch 3·글자 Text 7), bbox가 정확히 A1(840x594). 좌표계는 00_template_A1
  과 같아 도각 도면과 나란히 놓인다.
- 굵은 띠는 solid Hatch로 냈다. lineWidth는 캔버스 화면 픽셀이라(screenCanvas
  .drawController.ts:261) 확대해도 두꺼워지지 않아 실치수를 못 낸다.
- 글자 크기는 잉크 높이가 아니라 폭으로 잡았다. 원본은 장평이 좁은 CAD 글꼴이라
  높이를 그대로 옮기면 위치값이 종이 밖으로 44mm 넘치고 라벨과 겹친다.
- B07_DesignDetail_Engine_Cad_Cover.py 신설. frame_entities()를 쓰지 않는다 —
  _transform_entity()가 Hatch의 points 배열을 못 옮기고, 표지는 A1 실치수 고정이라
  애초에 변환이 필요 없다. 공용 함수는 건드리지 않았다.
- kind "cover" 배선: Schema Literal, Api_Fetch, UI_Page DRAWING_GROUPS,
  Router_Support 목록·빌드 분기·확정 캐시 매핑.

값(공사명·위치·사업량·시행청)은 아직 빈칸이다 — 메타 배선은 다음 판.

검증: tmp/tests/test_cover_template.py 6건 통과(A1 치수·Hatch 두께·잠금 레이어·
치환·lru_cache 오염 없음). 공용 브라우저에서 표지를 열어 엔티티 14개 전부
b08-frame, Ctrl+A 선택 0 확인.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 19:49:47 +09:00
eomsangdon 3f98670637 merge: AutoCAD 리본 기능 조사자료 브랜치를 합친다 2026-08-31 17:26:12 +09:00
eomsangdon 66d24fdffa merge: main의 실무문서(2026 임도 용화)를 받아들이고 코드는 최신을 유지한다
# Conflicts:
#	B07_DesignDetail/openwebcad/src/App.css
#	B07_DesignDetail/openwebcad/src/commands/command.types.ts
#	B07_DesignDetail/openwebcad/src/commands/commands.annotate.ts
#	B07_DesignDetail/openwebcad/src/commands/commands.draw.ts
#	B07_DesignDetail/openwebcad/src/commands/commands.file.ts
#	B07_DesignDetail/openwebcad/src/commands/commands.insert.ts
#	B07_DesignDetail/openwebcad/src/commands/commands.modify.ts
#	B07_DesignDetail/openwebcad/src/commands/registry.ts
#	B07_DesignDetail/openwebcad/src/commands/run-command.ts
#	B07_DesignDetail/openwebcad/src/components/CommandLine.tsx
#	B07_DesignDetail/openwebcad/src/components/InspectorPanel.tsx
#	B07_DesignDetail/openwebcad/src/components/RibbonWidgets.tsx
#	B07_DesignDetail/openwebcad/src/components/StatusBar.tsx
#	B07_DesignDetail/openwebcad/src/components/Toolbar.tsx
#	B07_DesignDetail/openwebcad/src/inputController/input-controller.ts
#	B07_DesignDetail/openwebcad/src/main.tsx
#	B07_DesignDetail/openwebcad/src/ribbon/Ribbon.tsx
#	B07_DesignDetail/openwebcad/src/ribbon/ribbon.config.ts
#	B07_DesignDetail/openwebcad/src/tools/factories/sequence-tool.ts
2026-08-31 17:07:38 +09:00
eomsangdon b012cd8003 auto: 2026-08-31 16:45 (EOMSANGDON-HOME) 2026-08-31 16:45:43 +09:00
eomsangdonandClaude Opus 5 6a2c5d9f7b feat(B07): 기본 도면층 이름을 국문으로 바꾸고 방위표 템플릿을 정리한다
도면층 17종을 프로젝트가 이미 쓰는 용어로 맞춘다 — 원지반·계획선·구조물·
암 경계선·수량 산출표·도각·등고선·계류·노선·배수유역·유역 제원·표제·
그래프 격자·측점표·유토곡선·그래프 축·운반 구간. CAD 앱의 'Default'와
'New layer'도 기본·새 도면층으로 바꾼다. layerId는 그대로다.

방위표 템플릿(00_template_compass.json)에 원본 DXF의 표제란 글자 4개가
도면 반대편에 남아 있었다. 이 때문에 템플릿 bbox가 183x262mm로 부풀어,
긴 변을 14mm에 맞추는 compass_entities()가 방위표를 1.1x1.8mm로 줄여
놓고 있었다. 글자를 지우니 bbox 20.5x32.9mm, 방위표가 8.7x14mm로 나온다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 15:07:14 +09:00
eomsangdon 8ae61af7dd auto: 2026-08-31 14:38 (ESD_LAPTOP) 2026-08-31 14:38:53 +09:00
eomsangdonandClaude Opus 5 a1dc0ee235 feat(B07): 토적도(유토곡선)·유역도(수리집수면적유역도)를 도면으로 낸다
납품 도면 2장을 B07 도면 목록에 새로 붙였다. 계산은 하지 않는다 —
유토곡선은 B06 확정 시 저장한 산출물(longitudinal_sections.data.mass_haul)을,
유역도는 B04 세부유역 GeoJSON과 도엽 등고선·세류선을 읽어 좌표만 종이 mm로 옮긴다.

- 도면 종류 확장: kind에 mass_haul·watershed 추가(Schema·Api_Fetch·openwebcad
  App.types), 12분류 라벨에 연결, 목록에 단장 도면 2건 상시 노출
- 엔진 신규: _Engine_Cad_MassHaul.py(축·곡선·평형선·띠 현·balloon·측점 테이블),
  _Engine_Cad_Basin.py(등고선·세류선 배경·노선·유역·구역별 정보표·방위표)
- 척도 상수: 유토곡선 H 1/2,000 · 세로 1mm=50㎥, 유역도 1/6,000 (A1 고정)
- 유토곡선 저장 payload에 띠·잔여의 기하 필드 추가 — 파이썬에 곡선 보간·토량 배분
  로직을 복제하지 않기 위해 값을 낳는 쪽(TS 엔진)에서 함께 남긴다
- 유역도 배경은 여러 도엽을 합쳐 받은 뒤 도곽 크기로 절취(clip_line_to_box)
- 배수규격은 소요 관경이 아니라 규격관(recommended_diameter_mm)으로 표기

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 13:01:39 +09:00
eomsangdon ea9d9685be feat(B07): CAD를 AutoCAD 명령 체계로 재구성한다 (조사표 1·2·3·5절)
저장소 사고로 잃은 4개 커밋(38eb7cd4·b8a11756·281528bf·f60b488d)의 작업물을
하나로 다시 담았다. 내용은 동일하다.

■ 구조
- commands/: 명령 정의(id·AutoCAD 별칭·글리프·도구/즉시실행)를 단일 소스로 두고
  리본·명령행·단축키가 모두 이 레지스트리를 읽는다. tools/tool.consts.ts 폐지.
- ribbon/: 탭→패널→명령 데이터(ribbon.config.ts)와 범용 렌더러 분리.
  AutoCAD 배치(홈·삽입·주석·뷰·출력)와 패널 확장(▾)을 따른다.
- tools/factories/sequence-tool.ts: 점·숫자·문자·객체·선택 단계를 선언하면
  xstate 머신을 만들어 주는 공장. 명령당 170줄 보일러플레이트 제거.
- helpers/geometry/: 3점 호·정다각형·타원·스플라인·구름형·평행이동·해치 스캔선·
  점렬 샘플링 등 상태 없는 순수 함수.
- Toolbar 483줄을 QuickAccessBar/Ribbon/InspectorPanel/StatusBar/CommandLine/
  ViewControls/PropertiesEditor/QuickProperties로 분해.

■ 명령 (조사표 기준)
- 1절 그리기 21건, 2절 수정 27건, 3절 도면층·특성·그룹·유틸리티 39건 전부 반영.
- 5절 주석 34건 중 26건 반영(문자·치수 16종·지시선·표·구름형·주석 축척).
- HatchEntity 추가(solid·pattern·cross·gradient) + JSON 왕복, Layer에 색·선가중치·
  선종류·동결·투명도 필드 추가, 그리기 루프가 동결·숨김·투명도를 반영.

■ 화면 실측에서 고친 결함
- 명령행 포커스 상태에서 ENTER가 도구로 가지 않던 문제
- 명령행 문자 입력이 접두사가 같은 명령으로 실행되던 문제
- 명령이 끝나도 입력을 계속 먹던 문제(점 입력 명령만 반복, 나머지는 선택 도구 복귀)
- 시퀀스 단계 인덱스 오사용 9건 + 단계 값 종류 검사 추가
- 해치 내부를 클릭해도 선택되지 않던 문제

미반영 8건(맞춤법 검사·꺾기 치수·치수 끊기/재연관/검사 치수·기하공차·지시선 수집·
축척 리스트 편집)은 조사표 `반영` 열과 PLAN.md에 사유를 적었다.
2026-08-30 01:34:13 +09:00
eomsangdon 487539bba1 auto: 2026-08-29 23:30 (ESD_LAPTOP) 2026-08-29 23:30:04 +09:00