서버 Node 가 기준벽 역할별 넓이를 design.wall_fill_overlap 에 남기고 B08 이 다단 목록 통(base 표시 칸)으로 읽어 기준벽 줄 비고에 붙임 · 호출부(Router_Material) 안 늘림 · 936be972 빈 저장: 관 9 곳 유출 벽 258.12 1.417 · 720 1.403 · 804.18 1.166 · 982.64 0.807 · 620 0.136 · 440 0.046 · 533.98 0.004 · 85.05/900 0㎡ · 이 프로젝트 기준벽은 모두 미확정(금액 밖)이라 비고 안 뜸 · 벽 칸을 적으면 「1.42㎡ × 10m ≈ 14.2㎥」 · 금액 변화 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
유토곡선 장비 경계의 도자 한계거리가 config 붙박이였고 설정 칸 haul_limits_m_override 는 아무도 안 읽었음.
dozer_haul_limit_m 칸으로 갈음해 B06 유토곡선 문맥·배분·B08 산출 조건이 같은 값을 읽음(common_util 한 곳).
화면에 기본값 60 m · 근거(품셈 8-1-1 · 산림과임업기술 5장 · 실무 EARTH.DAT 전수)를 보이고, 종무대 20 m 는 규정이라 값만 보임.
종무대 이하 값은 저장에서 막음 · 비우면 기본값.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
무슨 일이 있었나
랩탑 줄의 병합 `20ba886c`(Merge origin/main_desktop_1·main_laptop_1·sub_desktop_1 into
sub_laptop_1)가 우리 파일 22개를 떨구고 35개 파일의 내용을 옛것으로 되돌림. 손으로 지운
커밋은 없고 **병합 자체가 떨군 것**임. 그것이 `origin/dev`·`main_laptop_1`·`sub_laptop_1`·
`CODEX` 까지 퍼졌고(데스크탑 둘만 무사), 이 창의 병합 `d92c1f2b` 로 들어옴.
잃었던 것
- 공용 — `common_util_provenance.py` · `ui_template_provenance.ts`
- B08 — 근거 사전 · 좌측 패널 상자 모듈 · 토량환산계수 칸
- B09 — 근거 사전 셋
- B05 — 계획노선 편집 모듈 아홉 · 지형 라우터 · B04 지도 모듈
- 시험 셋과, 35개 파일 안의 최근 작업(환산계수 고르기 · 근거 호버 배선 등)
어떻게 되살렸나
`611a2b40`(병합 직전, 전부 온전)에서 `git show <커밋>:<경로>` 로 내용만 꺼내 되돌림.
이력은 안 건드림. ⚠ HEAD 에만 있던 「추가 816줄」은 랩탑의 새 작업이 아니라 **되살아난
옛 코드**였음(B05 편집은 모듈로 쪼개기 전 덩어리 · B08 라우터는 환산계수 고르기 전 옛
상수판). 되돌릴 시점 이후의 **진짜 새 커밋은 둘뿐**이라 그 둘만 패치로 다시 얹음 —
`9f827bf6`(리로드 빌드 고리 끊기, 데스크탑 보조) · `b9bca6b3`(B06 조정창 1px, 랩탑).
위키 여덟은 코덱스 몫이라 손대지 않음.
자체검증 — 양쪽 작업이 다 살아 있음을 짚어 확인: `main.py` 의 「개발 서버는 살려 둔다」 ·
`B05_Profile_Engine_Grade.py` 의 `plan_curve_length_limit_m` · `B08_..._EarthworkGrid.ts` 의
`attachProvenance`. `tsc --noEmit` 통과 · `pytest -q` **1317 passed, 28 skipped**
(되살리기 전에는 시험 둘이 수집 단계에서 깨져 있었음).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RANEBHns1S4tkmsYwewtk
사용자는 「이 구간에 ○㎥」를 정하는데 단면은 폭을 알아야 그려짐.
그 구간 측점을 한꺼번에 보고 **폭 하나**를 이분법으로 찾음(작업장은 폭이 일정함).
- `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>
채집석은 **벽 입적(제자리 부피)**이라 자연 축이고 유토곡선은 다짐 축임.
축이 다른 값을 그냥 빼고 있었음(리핑암이면 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>
통로는 났는데 `_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>
데스크탑 메인이 구조물 터파기·되메우기·잔토를 인계에 실었는데, **잔토 126.625㎥ 가
어디에도 안 실렸다**. 사토로 실어 내는 몫이라 유토곡선이 세야 겹치지 않는다.
구조물 잔토는 사토에 한 번만 더한다.
B08 은 소요량(structure_spoil_m3, ㎥ 양수)을 내기만 하고,
더하는 자리는 유토곡선의 사토뿐이다.
- ⚠ **잔량 하나하나를 늘린다** — 총량만 늘리면 사토는 늘고 운반이 안 는다(공제 때와 같은 자리).
- ⚠ 나누는 법: 지금은 총량 하나만 오므로 **남은 사토 잔량 크기에 비례**해 나눈다.
한 곳에 몰면 운반거리가 틀린다. 측점별 값이 오면 이 함수만 고치면 된다.
- ⚠ 자연방토·지반유형 안분은 안 건드린다 — 실어 내는 흙이고, 어느 지반에서 나온지 모른다.
- `null`(아직 안 옴) ≠ `0`(없음), 받은 값과 **실제로 더한 값**을 따로 싣는다.
시험 5건(더해짐·잔량 동반 증가·자연방토 불변·토취 불변·공제와 함께 와도 한 번씩).
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>
B08 창 보고(2026-09-08): 관 11개가 `pipe_points.json` 에 있고 품셈 공종도 있는데 **연장(m)이
없어** 배수관 물량이 막혀 있었음. 관 길이는 횡단 기하가 **m 단위 올림까지** 끝낸 값
(`CulvertLayout.pipe.lengthM`)인데 **정본(`design`)에 안 실렸음**.
**옮기거나 새로 짜지 않았음** — 그 계산은 **이미 서버가 Node 로 그대로 실행**하고 있었음
(`B06_Section_Server_Calc_Node` ← `Server_Calc_Prebuild.recompute_server_side`, [저장]·[확정]).
구조물 폐회로 면적이 실리는 **그 다리에 값 한 줄만** 더 실었음 — 계산을 두 벌로 짜지 않음
(CLAUDE.md 5장). B08 창이 낸 갈래 둘(서버로 이관 / 저장 때 남기기)은 둘 다 불필요했음.
- `STRUCTURE_AREA_KEYS` → **`STRUCTURE_ROW_KEYS`** 로 이름을 고치고 `pipe_length_m` 추가.
이름이 「면적」이라 길이를 담으면 거짓말이 됨.
- **면적을 못 내는 측점에서도 길이는 냄** — 설계선이 모자라 폐회로가 안 닫히는 자리에도
관은 서 있고 수량은 그 길이가 필요함(`return pipeRow`).
- ⚠ **서버에 화이트리스트가 하나 더 있었음** — `_AREA_KEYS`(「Node 가 다른 키를 내도 안 흘림」).
거기 안 넣으면 Node 가 값을 내도 **조용히 버려짐**. 넣고, **두 목록을 대조하는 시험**을 둠.
- 키 이름은 `pipe_length_m` 으로 **B08 창과 미리 못 박음** — 오늘 `back_len_cm` 이 엔진에서
`stone_back_length_cm` 로 읽혀 저장값이 영영 안 닿던 사고가 있었음.
⚠ 값이 정본에 실리려면 그 프로젝트에서 **[저장] 한 번**이 필요하고, **번들 재빌드**
(`npm run build:server-calc`)도 필요함 — 번들은 git 밖이라 창마다 각자 돌려야 함.
시험 6건 — 패치로 받는지 · 음수 거부 · 면적과 **같은 목록**으로 실리는지 · 면적 실패 시에도
길이는 나오는지 · 이름을 두 번 적지 않는지 · **서버 화이트리스트와 TS 목록이 짝인지**.
전체 507 passed · 17 skipped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PLAN 0-10. 8000 에서 1회 실측 결과 재확정 체인 292.9s 중 배수유역 분석이 285.0s(97%)로
나와, 그 안쪽을 가르기 위한 마크만 추가. 로직 불변.
- B06 확정: 조회 / 기본설계 계산 / 확정 저장 / 서버 재계산 / 측구 역반영
- 서버 재계산 내부: 상세+DB 병렬 조회 / 포장·세월교 보정 / Node 번들 / 정본 저장
- 배수유역 분석 내부: _prepare(도엽 읽기·좌표변환) / preview_stages / 응답 만들기·저장
- preview_stages: 1차 영역 / 격자 확장·흐름 판정 / 흐름 강도 / 외곽선·기본 관·화살표
`_log_steps` 는 체인 모듈 것을 그대로 씀(지연 임포트로 순환 회피).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
보조 창이 노선 편집 [확인] 실측에서 둘을 잡음.
1. projects 에 design_speed_kph / terrain_type 컬럼이 없음(있는 것은 road_type 뿐).
매 요청마다 OperationalError(1054) 가 ERROR 로그로 남고 기본값 폴백으로 넘어갔음.
- 임도 종류는 projects.road_type, 설계속도·지형은 워크플로 stage 2 params 에서 읽음.
- 산식은 이미 있던 B05_Profile_Engine_Grade.legal_plan_radius_min_m 를 씀 —
내가 같은 표를 다시 짜 두었던 것을 지움(중복 제거).
2. 재확정 체인이 solve_route 400 으로 끊길 때 상태 코드만 남겨 원인을 못 짚었음.
본문(사유)까지 로그에 남김. 노선 편집 [확인]이 조용히 끊겨 배수유역·관은 새 노선으로
가고 종횡단만 옛 노선에 남는 어긋남이 굳었던 자리임.
recompute 의 상세 조회와 DB 두 건도 asyncio.gather 로 묶음(원격 DB 왕복 약 12ms/질의).
시험 409 통과·17 건너뜀.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
측점마다 SELECT+UPDATE 두 왕복을 냈고 DB 가 원격이라 왕복 하나가 약 12ms.
22행이면 670ms 이고 측점 수에 선형으로 늘었음(보조 창 서버 내부 측정).
- B06_Section_Repository_Bulk.merge_cross_section_designs 신설 — 노선 측점을 한 번에
읽고, 파이썬에서 chainage 를 맞춰 JSON 을 합친 뒤
`UPDATE ... SET data = CASE id ...` 한 문장으로 되돌려 씀(없는 행은 다중 INSERT).
행 수와 무관하게 왕복 두 번. Repository 가 685줄이라 파일을 나눔(700줄 한계).
- 부르는 자리 셋을 묶음으로 바꿈 — _apply_section_edits 의 기본설계·측점 patch 두 루프,
_recompute 의 보정·면적 두 루프.
자체검증(공용 브라우저 [저장] 3회) — sections/save 3,593ms -> 2,205 / 1,870 / 2,547ms.
버튼 전체 대기 4,137ms -> 2,624~3,415ms. 진행 표시는 2~3ms 만에 뜸.
시험 tmp/tests/test_b06_bulk_designs.py 5건(같은 JSON 결과·왕복 두 번·1cm 허용오차·
행 없을 때 INSERT·빈 목록은 왕복 0). 전체 400 통과·17 건너뜀.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-06 저녁 사용자 확정. 이유는 속도가 아니라 보안 — 저장 경로가 브라우저 계산이면
유토 배분·운반거리 코드(_balance 523 + _settle 235 = 758줄)가 번들에 남아야 해서
화면에서 안 그려도 뺄 수 없음. 서버가 정본을 내면 그 몫이 번들에서 빠짐.
대가는 저장 대기 850ms -> 약 980ms(Node 131ms) — 기다리는 조작이라 허용.
- 저장·확정이 편집을 커밋한 **뒤** recompute_server_side 를 부름(전에는 편집 앞에서
Node 없이 보정만). 바뀐 벽·측점이 면적·유토곡선에 실림.
- run_node 갈래 제거 — 이제 부르는 자리가 둘 다 Node 를 돎(체인·저장).
쓰이지 않게 된 enforce_stored_designs 래퍼 삭제.
- 코리도 열쇠 질의: hash 를 isinstance 로 좁힘. 파이썬에서 곧바로 부르면 Query 기본값
객체가 들어오는데 truthy 라 열쇠 없는 호출이 통째로 stale 로 떨어졌음(보조 창 지적).
시험 395 통과·17 건너뜀.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정(2026-09-06): 조작 중과 [저장]·[확정]의 계산은 브라우저 몫이고,
서버는 초기값을 만들 때만 같은 코드를 Node 로 돌린다.
- 면적 산출을 B06_Section_Structure_Layouts 로 빼 Node 진입점과 브라우저가
같은 한 벌을 쓰게 함(structureAreaRows / applyStructureAreaRows).
- [저장]·[확정]이 카드를 그리지 않은 측점까지 면적을 계산해 cross_patch 로
보냄. 유토곡선도 그 위에서 쌓음.
- 서버는 저장 때 Node 를 돌리지 않음 — 포장 구간·세월교 노면 하강 보정만
남기고, 그 보정은 편집분을 얹기 전에 돌게 순서를 바꿈.
검증: tsc --noEmit 통과, pytest 387 passed, Node 진입점 스모크 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정(2026-09-06): 읽을 때는 영구저장소에서 가져오기만 하고, 계산은
화면(캐시)에서 하며, 저장·확정에서만 영구저장소에 쓴다.
- get_section_detail 이 조회할 때마다 돌리던 포장 구간 보정·세월교 노면 하강
보정을 제거. 조회는 저장분을 그대로 싣는다.
- 두 보정을 recompute_server_side 로 옮겨 [저장]·[확정]·자동설계 체인에서
정본에 남긴다. 보정된 설계 위에서 구조물 면적·유토곡선이 나오도록 순서를
잡았다.
- 설계 미지정 측점 폴백(attach_default_designs)만 조회에 남긴다 — 저장분이
있으면 아무 일도 하지 않는다.
검증: pytest 387 passed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
feat(B06): 구조물 면적·유토곡선 서버 계산 자리 마련 + 상단측 저장 누락 수정
계산 자리 일원화(CLAUDE.md 5장) — 브라우저에서만 돌던 두 계산을 서버가 같은 TS 로
한 번 더 돌려 정본에 얹음. 파이썬 포팅 금지(기하가 두 벌이 되면 그림과 수량이 갈림).
- B06_Section_Server_Calc_Node.ts 신설 — 구조물 폐회로 면적 계산 후 그 위에서
유토곡선을 쌓음(화면과 같은 순서). balloon 위치는 서버가 만들지 않음.
- B06_Section_Structure_Layouts.ts 신설 — 정본만 읽는 제어기 흉내를 B07 도면에서
떼어 공용화. B07·서버가 같은 한 벌을 씀.
- common_util_node_bundle.py 신설 — 번들 빌드·실행 배관 공용화(코리도도 이걸 씀).
- 전처리 체인(초기값 스냅샷 앞)·[저장]·[확정]에서 서버 재계산 호출.
- 상단측(측구 방향) 변경이 B05 [임시저장]에만 실리던 것을 B06 [저장]·[확정]에도
실음 — flushUphillOverrides.
- 죽은 세션 등록 항목 pipes 제거(읽는 곳도 쓰는 곳도 없었음).
검증: tsc --noEmit 통과, pytest 386 passed, tmp/tests/test_b06_server_calc_node.mjs 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@