계획서 0-2 「재계산 중간 취소」 재판정. **취소는 만들지 않기로 닫음.**
· 잰 값 — 서버 계측 네 번 87.3 · 90.0 · 93.9 · 95.4초(평균 91.7). 293초에서 이미 3분의 1.
· 취소가 「반쯤 부순 상태」를 만드는 단추가 됨 — 관 지점은 체인 **전에** 이미 지워지고,
체인이 끊기면 노선만 새것·종횡단은 옛것으로 어긋남(2026-09-06 실측 사고와 같은 자리).
· 시간의 90 %가 배수·관·측점 재생성 한 곳이라, 급하면 취소보다 그 자리를 줄이는 것이 이득.
대신 대기 안내를 고침 — 「몇 분 걸립니다」 → 「1분 반쯤 걸립니다 (N초 지남)」로
**경과 시간이 1초마다 돎**. 멈춘 것인지 도는 것인지 사람이 알 수 있어야 함.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
계획서 4-13. 소광리 `07-구조도-소광리.xlsx` 다섯 탭의 **개소당 소계를 그대로** 옮김
(Ø800 A·C · Ø1000 A·C · Ø800 A+집수정). 비례로 늘리지 않음 — 그 규격에서만 맞는 값임.
- 원단위표에 다섯 줄 추가. 거푸집 종류가 탭마다 갈려 이름을 뭉개지 않음 —
Ø800 A·C 는 **유로폼**, Ø1000 과 A+집수정은 **합판거푸집(4회)**.
- ⚠ 철근·면목 줄은 원본 날개벽 탭에 **없음**(집수정구조도 탭에만 있음). 지어내지 않음.
- 등록부·배치 폼에 「관보호공 날개벽」 칸(A-TYPE·C-TYPE·A-TYPE+집수정). 비우면 안 셈.
- ⚠ 겹쳐 세는 자리 — 「A-TYPE+집수정」은 집수정을 품은 형식이라 집수정 형식도 차 있으면
**사유로 알림**(값은 안 고침). 원단위표 `double_count_rules` 와 짝.
ⓘ 집수정 Ø800 은 **이미 표에 있었음**(`pipe_inlet_basin` □형·콘크리트·800) — 다시 만들지 않음.
화면 실측 — 배수관 폼에 칸이 뜨고 선택지 셋 확인. 엔진 실행으로 날개벽 줄이 따로 서고
터파기 13.104 · 콘크리트 2.0595 · 유로폼 12.5376 이 나오는 것까지 봄.
시험 일곱 추가, 전체 1218 통과·실패 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
확정 2차 ② 후반 「사용자가 값을 바꿀 수 있게」. 식은 이미 있었고 없던 것은 덮어쓸 칸이었음.
- 등록부(돌쌓기 계열 다섯 종류)에 `thickness_top_m`·`thickness_bottom_m` 칸을 둠.
큰돌쌓기는 두께 식이 달라 뺐고 화면에서도 그 장에는 안 뜸.
- 빈 칸은 「안 정함」 — 자동값을 저장에 박지 않음. 상부만 넣으면 하부는 그 위에서 식을 이음.
- 근거 문구가 어디서 온 값인지 적음(「사용자 입력」 / 「뒷길이 45㎝ + 0.3」).
화면 실측(랩탑_보조, 표준도 3장 돌쌓기(찰)) — 0.60 넣고 저장하니 2개소 반영,
입적 24.375 → 20.625㎥ 로 움직였고 칸을 비워 되돌리니 24.375 로 복귀함.
시험 다섯 추가, 전체 1203 통과·실패 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>
⚠⚠ 한 칸(`ditch_enabled`)에 **두 뜻**이 담겨 있었음.
결과(실제 섰나)를 그대로 다시 입력으로 넣어 읽었으므로 **한 번 저장되면 자동 판정이
영영 다시 안 돌았음.** 계획고를 내려 절토가 생겨도 측구가 안 서고 **아무 말도 안 나왔음.**
- **선택** `ditch_choice` (없음 = 자동) · **결과** `ditch_enabled` (실제 섰나)로 가름
- 자동 판정을 **먼저** 하고 선택을 그 위에 얹음. 양성 단면은 선택보다 기하가 먼저
- ⚠ **옛 저장분은 자동값과 다를 때만 선택으로 살림** — 같으면 자동이 그렇게 냈던 것이고
다르면 사용자가 일부러 바꾼 것임. 설계 의도를 잃지 않으면서 굳은 값을 푼 것
(오늘 `length_m` 에서 겪은 「저장분이 걸린 자리」를 같은 방식으로 처리)
- 화면 카드는 이제 **선택**을 읽어 상태를 세우고, 표시는 **결과**를 보임
- 파이썬·TS 짝 양쪽 + 호출부 여섯 곳(재계산·저장·확정·사토장·요청 스키마)
시험 다섯 추가 — 「결과를 다시 넣어도 자동이 계속 돎」이 그 잠금. 전체 616 통과.
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>
사용자 확정 4차 원문 — 「흙막이는 횡단도에서 **표현방식들과 옵션들은 동일하게** 반영하면
될거야. **형상은 동일해.** 물론 **데이터는 분리하여 계산**되어야함.」
- 그리기 경로는 **이미 같음** — C군 벽은 `attachWallSpecs` 로 `section.revetment` 에 붙어
기슭막이와 같은 기하를 탐(따로 그리지 않음). 형태 이름도 「찰/콘크리트」 글자로 갈려
흙막이 선택지(돌(찰)·돌(메)·떼…)가 그대로 먹힘
- 빠져 있던 것은 **옵션 칸**이라 기슭막이 열두 칸을 **같은 글자 그대로** 옮김 —
단 수 · 올림 · 이동 · 뒷길이 · 돌 종류 · 조달 · 야면석 계수 · 채움 강도 ·
전면 기울기 · 기초 · 물빼기 구멍 둘
⚠ 흙막이 수량이 안 쓰는 칸도 **숨기지 않음**(사용자가 「동일하게」라 함) — 수량 쪽에서
조용히 무시되면 됨
- ⚠ 코드에 **「형상 동일 ≠ 수량 동일」**을 못 박음. 원단위·공종코드·성분 줄은 흙막이 자기 것.
반대 사례가 골막이임(그림도 수량도 다르고 두께식마저 다른 식) — **계열이 다르면 상수를
나눠 쓸 것**
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>
⚠⚠ **진단이 뒤집힌 자리임.** 계획서 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>
사토장
- 카드 면적표에 「사토장」 줄을 따로 세움 — 성토와 **합치지 않음**(확정 ㉠).
사토장이 없는 측점에는 줄을 세우지 않음(어느 측점에 있는지 표에서 보이게)
- 성토와 다른 색으로 둠 — 같은 색이면 한 덩어리로 읽힘
등록부(다른 창 요청, 기본값 없음 — 현장 치수라 지어내지 않음)
- `erosion_check.top_length_m`·`bottom_length_m` — 골막이 정면적이 사다리꼴이라
두 변이 있어야 셈. 실무 정본 산출식이 상장ⓐ·하장ⓑ를 씀
- `soil_guard.form` 에 「떼」 추가 — 실무 정본에 떼흙막이 산출식이 있는데 붙일 칸이 없었음
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>
칸이 없어 `_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>
- `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>
품셈 표준경사 표가 높이 × 메/찰 × **성토/절토** 로 갈리는데 성절토만 없었다.
새 입력을 만들지 않고 이미 저장되는 두 값으로 가린다 —
`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>
사용자 확정 ⑨(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>
엔진(`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>
접었을 때 머리·본문만 감추고 요약줄은 남아, 폭 0 인 패널에서 글자가 64px 밖으로
새어 나왔다(폭과 무관하게 늘 같은 값 — 좁은 폭 문제가 아니라 그 자리 결함).
감추는 목록에 요약줄을 더한다.
확인: 접힘에서 display:none·넘침 0, 펼침에서 이전과 같음(넘침 0).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- masonry_wet·masonry_dry 에 `stone_kind` 옵션 추가 (야면석·호박돌 / 깬잡석 /
깬돌 / 견치돌). 기본값 없음·required·phase detail — 품셈 13-4-3(고임돌)·
13-4-4(채움 콘크리트) 가 돌 종류로 갈리므로 B08 이 계수 축을 하나로 고를 수 있게 함.
- 값 선정은 설계 판단이라 기본값을 두지 않음 — 미지정이면 B08 이 드러냄.
- 지식DB 미결 22 등재: 옆도랑 저폭 0.3m 근거 공백(별표2 는 너비·깊이만) +
현행 45° 단면이 통수단면 경제 단면 60° 와 어긋남.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
데스크탑 창 보고(2026-09-08): 실무 프로젝트 구조물의 **상세 옵션이 통째로 비어 있음** —
`back_len_cm`(뒷길이) · `stone_cm`(돌규격) · `form`(옹벽 형식). 그래서 B08 수량이 품셈 갈래를
못 골라 **금액이 0 으로 남음**(13-4 돌쌓기 뒷길이 · 13-6 큰돌쌓기 직경 · 12-3 옹벽 형식).
**까닭 — 아무도 안 받고 있었음.** 레지스트리가 그 칸들을 `phase: "detail"` 로 두고
「B05 는 유무·종류·위치만, **상세 치수는 B06/B07 에서**」(2026-08-17 사용자 확정)로 갈라 놨는데,
**그 화면이 아직 안 그리고 있었음**. 폼은 한 벌인데 필터(`isB05Option`)가 늘 상세를 숨겼음.
고침 — 폼이 `includeDetail` 을 받아 **B06 에서만** 상세 칸까지 그림(B05 는 종전 그대로).
새 결정이 아니라 **2026-08-17 확정을 이제 구현한 것**임.
⚠ **기본값 없는 필수 항목은 빈 칸(「— 선택 —」)으로 연다** — 첫 항목을 슬쩍 고르면 근거 없는
값(뒷길이 25㎝ 같은)이 수량·단가로 흘러감. 설계자가 고르게 둠.
**큰돌쌓기에 「쌓기 방식」(메쌓기·찰쌓기) 옵션 신설** — 품셈이 13-6-1 메 / 13-6-2 찰로 갈라
두는데 구분 칸이 없었음(돌쌓기는 이미 타입이 갈려 있음). 기본값 없음·필수·상세.
실화면 확인(용화 5601e828 · B06) — C군 → 큰돌쌓기 고르면 **돌규격·쌓기 방식** 칸이 빈 채로 뜸.
돌규격 `60~80` · 쌓기 방식 `찰쌓기` 로 한 건 넣고 [저장] → 정본 `structures.json` 에
`{"stone_cm": "60~80", "bond": "찰쌓기", …}` 로 남는 것 확인. 시험분은 지우고 저장해
**원래 7건**으로 되돌림.
시험 5건 — B06 만 상세를 받는지 · B05 는 종전대로인지 · 기본값 없는 필수는 빈 칸인지 ·
큰돌쌓기 메/찰 구분 · **규격 축이 타입마다 다른지**(큰돌쌓기=직경, 돌쌓기=뒷길이 — 데스크탑이
섞여 있던 결함을 잡은 자리). 전체 501 passed · 17 skipped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지시(2026-09-07). 계획서 3-6 마지막 항목 — 산마루측구·도수로·옹벽처럼 **구간**으로
놓이는 시설이 종단에는 띠로 보이는데 **평면(배수유역도)에는 아무 표시가 없었음**.
**「부품이 없어 새로 짜야 함」이 사실이 아니었음** — 계획선 표본(`strengthSamples`)이 **1m 간격**
이라 **배열 인덱스가 곧 누가거리**임(`resampleRoute`). 구간 → 화면 선은 그 토막을 잘라 굵게
긋기만 하면 됨. 새 파일 하나(88줄)로 끝남.
- `B05_Profile_UI_Drainage_Spans.ts` — 띠 그리기(`drawRouteSpans`)와 자료 만들기
(`routeSpansFromStructures`). 구간형만 띠가 되고, 색은 **레지스트리 표시색**을 그대로 씀.
- 그리는 자리 — **계획선 바로 위, 강도 색칠·마커 아래**. 굵기 7px·투명도 0.45 라 계획선을
덮지 않음. 이름은 안 적음(종단에 이미 있고, 지도 글자는 눈금·유역 번호와 겹침).
- 목록이 바뀌면 따라옴 — `setStructures`·`setStructureTypes` 가 띠를 다시 넘김.
- 저장분에 노선보다 긴 구간이 남아 있어도 잘라서 그리고, 시작=끝인 구간도 한 칸은 보임.
⚠ 프로필 패널이 이미 700줄을 넘겨 있어(843) **매핑 로직은 띠 모듈로 뺐음** — 패널에는 3줄만
남김(827줄). 그 파일의 초과는 이전부터임.
시험 5건 — 부품 존재 · 범위 밖 구간 안전 · **쌓는 순서**(계획선 → 띠 → 강도 색칠) ·
종단과 같은 자료에서 뽑는지 · 목록 변화가 따라오는지.
⚠ 실화면 확인은 아직임 — 공용 브라우저가 소단 무한루프(별건, `80db17d4` 로 고침) 로 멈춰 있어
사용자 새로고침 대기 중임.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지시 5건. ⚠ **화면 검증은 아직 못 함** — 다른 창의 분배 조율로 git sync 를 먼저
하게 되어 미커밋으로 두지 않으려고 먼저 커밋함. 타입 검사·시험은 통과 상태임.
- **1. 패널을 화면으로** — `document.body` 에 `position: fixed` 로 띄움. 모달이
`overflow: hidden` 이라 안에 두면 가장자리에서 잘렸음. 이제 모달 밖으로도 넘어감.
- **2. 너무 가까움 + 위치 제어** — 여백 14 → 40px 로 넓히고 방위별 상자 반지름만큼 더 밀어냄.
**머리를 잡아 손으로 옮길 수 있음**. 옮긴 자리는 꺾임점 기준으로 기억해 지도를 옮기거나
확대해도 따라오고, 다른 꺾임점을 고르면 자동 자리로 돌아감.
- **3. 자동 위치를 16방위로** — 4방위는 대각 자리에서 곡선을 물었음. 곡선 중심의 반대 방향을
22.5° 단위로 맞춤.
- **4. 「법정 하한」 삭제**, 「칸을 비우면 자동」을 **다음 줄**로 뺌. 대신 무엇을 붙들고
있는지(고정 없음 / 반지름 고정 / 곡선 길이 고정)를 그 줄에 냄.
- **5. 반지름·곡선 길이 고정 단추** — 노드를 옮기면 교각이 바뀌어 R 과 길이 중 하나는 반드시
따라 움직임. 그래서 **셋 중 하나**임: 자동 / R 고정(길이가 따라감) / 길이 고정(R 을 L/Δ 로
다시 잡음). 붙들어 둔 곡선은 **손잡이로도 안 바뀜**(끌면 R 이 바뀌므로 집기에서 제외).
잠금·길이는 되돌리기 사진에도 담김.
- 새 모듈 `_Edits.ts` — 잠금 반영·상태줄 요약·서버 응답 펴기. 본체 692줄로 700줄 유지.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지적 3건 반영.
- **접선점 표기 복구** — 손잡이를 「고른 곡선만」으로 줄이면서 직선↔R 만나는 자리의
**표기까지 없앴음**. 접선점은 손잡이이기 이전에 읽을 정보라 **늘 그림**(고른 곡선은
속을 채워 도드라지게). 노드를 못 집던 문제는 집기 우선순위로 이미 풀려 겹치지 않음.
- **라벨을 반지름 + 곡선 길이 두 칸으로, [자동] 단추 삭제** — 교각 Δ 는 앞뒤 직선이
정하므로 L = R·Δ 로 묶임. 길이를 받으면 R 로 바꿔 한 값만 보관. 칸을 비우면 자동.
- **라벨 자리를 곡선 중심의 반대쪽으로**(상하좌우) — 중심 쪽에 두면 곡선을 가림.
중심 방향은 접선점 두 방향 단위벡터의 합(각 이등분선)으로 구함.
- ⚠ 라벨 글자가 안 읽히던 것 — `--color-surface-2` 가 이 테마에 없어 밝은 기본값으로
떨어졌음. 모달 본체와 같은 토큰으로 교체(실측 배경 rgb(37,31,56)·글자 rgb(228,224,240)).
- 상자 높이가 늦게 자라 자리가 11px 어긋나던 것도 다음 프레임에 다시 맞추게 함.
- 700줄 유지 — 교각·중심방향은 `_Label`, 등고선 띠는 `_Input` 으로 옮겨 본체 687줄.
실화면 검증 — 접선점이 고르기 전에도 보임 / 곡선 길이 40 → 반지름 203.7m 로 따라옴 /
라벨이 중심 반대쪽(위)에 붙음 / [자동] 없음. 554 passed · 18 skipped, tsc 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지적 ③④⑤⑥ 과 추가 지시(되돌리기)를 한 묶음으로 처리.
- **③ R 라벨** — 모달 맨 아랫줄이던 곡선 편집칸을 걷고, 고른 꺾임점 **옆에 뜨는 라벨**로
바꿈(`_Label.ts` 신설). 캔버스 밖으로 나가면 반대쪽으로 접어 넣음. 확대·이동·창 크기가
바뀌어도 고른 노드를 따라감.
- **④ 노드가 손잡이보다 먼저 잡히게** — 반대였던 탓에 헤어핀처럼 곡선이 몰린 데서는
노드를 아예 못 집었음. 손잡이는 **고른 곡선에만** 그림. 머리말 안내에 조작 여섯을 적음.
- **⑤ 줌·팬을 배수유역도와 동일하게**(`_Input.ts` 신설) — 휠은 **당기면 확대**(반대였음),
계수 1.15/0.87, 상한은 화면 폭 16m 기준, 하한 0.5, **팬은 가운데 버튼 전용**.
⚠ 커서 고정 계산이 좌상단 기준이라 확대할수록 지점이 밀리던 것도 중심 기준으로 고침.
- **⑥ 등고선을 노선 ±300m 띠로** — 창 크기와 무관한 고정 띠라 창을 늘려도 안 깨짐.
화면 밖 걸러내기는 종전대로 `drawPreparedLayer` 가 함.
- **되돌리기·다시하기·초기화**(`_History.ts` 신설) — [확인]이 무거워 되돌릴 길이 없으므로
창 안에서 물릴 수 있게 함. **끌기 한 번이 한 걸음**이고 클릭만으로는 걸음이 안 생김.
[초기화]는 **이 창을 연 상태**로 (≠ [예상노선으로]). Ctrl+Z / Ctrl+Y · Ctrl+Shift+Z.
- 700줄 제한 — 집기(hit test)를 `_Input.ts` 로 옮겨 본체 695줄.
실화면 검증(5174) — 라벨이 노드 오른쪽 [+18,−38]px 에 뜸 / 휠 당기니 중심에서 373.1 →
428.1px 로 확대 / 왼쪽 끌기로는 지도 안 움직임 / 가운데 버튼 끌기는 [60,40] 그대로 따라옴 /
단추 켜짐이 여섯 단계 모두 맞음. 전체 554 passed · 18 skipped, tsc 통과. 정본 안 건드림.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지적 ①② 의 뿌리 하나를 고침. 곡선을 서버만 그려서, 노드를 끌거나 손잡이를
살짝 건드리기만 해도 그려 둔 선·손잡이·노드 요약을 통째로 비웠음. 그 결과 화면에서
곡선이 전부 사라져 「R 이 지워졌다」로 보였음(값 자체는 남아 [확인] 때 반영됐음).
- `buildEditedPolyline` 신설 — `build_planned_polyline` 의 **편집 갈래**
(simplify=False + curve_flags/radii) 파이썬·TS 짝. 단순화·IP 추출·반지름 피팅은
초기 변환 전용이라 안 옮김.
- `markEdited` 가 비우는 대신 **같은 규칙으로 다시 그림**. 나머지 곡선은 안 사라짐.
- 손잡이는 곡선 목록 자리가 아니라 **노드 번호**로 잡음 — 다시 그릴 때마다 목록이
새로 나므로 자리로 들면 엉뚱한 곡선을 가리킴.
- 접선 자리가 모자라 R 이 눌리는 것이 끄는 즉시 보임(상태줄 「기준 미달 N곳」).
- 끌기 중에도 상태줄을 갱신 — 예전에는 아무 말이 없어 사라진 인상만 남았음.
- 서버가 곡선을 안 둔 자리(내각 179° 이상)는 **곡선 없음으로 열게** 고침. 전부 켬으로
열면 아무것도 안 만지고 [확인]만 눌러도 곡선이 새로 생겨 노선이 조용히 바뀌었음.
거울 시험 `tmp/tests/test_route_polyline_browser_mirror.py` 10건 추가.
원호 표본 개수는 `math.sin` 의 마지막 자리 차이로 90° 처럼 딱 떨어지는 자리에서 하나
갈릴 수 있어(같은 원 위의 같은 호), 개수가 같을 때는 1e-9 로 자리까지, 갈릴 때는
현 하나분 안쪽으로 모양을 맞춤. 일부러 공식을 틀어 시험이 잡는 것도 확인함.
실화면(5174) — 노드/손잡이를 끈 뒤에도 상태줄이 「곡선 22곳(하한 R 12m)」 유지,
「기준 미달 2곳」이 그 자리에서 뜸. 종전에는 「곡선 기준 R 12m」로 바뀌며 다 사라졌음.
전체 554 passed · 18 skipped, tsc 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정(2026-09-07) — 소단은 좌측 별도 폼이 아니라 **다른 옹벽·기슭막이와 같은 자리**
(구조물 배치)에서 놓는 것으로 바뀜. 기하는 그대로 두고 **입구만 옮겼음.**
· 레지스트리에 **C군(사면안정) 「소단」** 신설. 옵션은 다른 C군 구간형과 같은 꼴 —
길이·기준측점 전·후 + 폭·간격(사면길이)·안쪽 기울기.
· ⚠ **소단은 C군 구간형이지만 벽이 아님** — 기슭막이 제원 자리에 얹히지 않게 파이썬·TS
양쪽 벽 필터에서 뺐음. 안 뺐으면 소단을 놓는 순간 「독립 기슭막이」로 그려졌을 것임.
· 구조물 목록이 바뀌면 소단 구간을 세션 사본(`berm`)으로 펴고, 달라졌을 때만 재계산함.
계산 계통(브라우저·서버·`USER_TOUCHED_KEYS`·옹벽 의무 판정)은 **한 줄도 안 바꿨음**.
· ④에서 만든 좌측 별도 「소단」 패널은 걷어냈음(모듈 삭제).
**안쪽 기울기 기본값 2° → 0°** (사용자 재확정). 기울이는 것은 실무이나 법령·교본 근거가
없어 기본으로 넣지 않고 폼에서 받음. 주석·지식DB 방침도 그에 맞춰 고침.
**소단측구**(B군 종단배수)도 같은 꼴로 옵션을 붙였음 — 소단 위에 놓이는 시설이라 폭·간격이
소단을 따르고, 기울기만 **사면 쪽**(소단과 반대). 소단이 실제로 서면서
`PENDING_TYPE_IDS` 빈 칸이 풀려 연장 수량이 다른 구조물과 같은 길로 나옴.
자체검증 — 「근거 없는 기본값 금지」 시험에 두 타입 12개 기본값을 근거와 함께 등재.
소단측구 연장 시험을 「빈 칸」에서 「연장 100m」로 뒤집음. 전체 544 passed · 18 skipped.
TS 타입 검사·ruff 통과. 화면 확인은 다음 단계.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B군(측구·맹암거 등)을 넣어도 **어디에 놓였는지 안 보였음**. 알약은 기준점 한 곳에만 찍히고,
시~종점 띠는 **고른 동안만** 폈기 때문. 측구처럼 길게 이어지는 시설은 「어디부터 어디까지」가
곧 그 시설의 내용이라 늘 보여야 함(2026-09-07 사용자 지시).
- 구간형이면 **늘** 띠를 그림. 고른 것은 두껍고 진하게(4px·0.55), 나머지는 얇고 옅게(3px·0.45).
- **레인 높이는 42px 그대로** — 2-5b 에서 줄여 둔 것을 안 부풀림.
- B05 가 레지스트리를 **한 번만 받아 쓰는 자리에 따라 나눔** — 추가 메뉴는 켜진 종류만
(종전대로 여섯 군), **알약 레인·군 판정은 전부**. B06 에서 넣은 B군은 레지스트리에서
꺼져 있어, 켜진 것만 주면 종단에 이름·색 없이 「?」 회색 알약으로 떴을 자리였음.
실측(용화, 구간형 7건) — 띠 **0 → 7개**, 높이 3px, 레인 42px 그대로, 알약 18개 그대로.
B군 6종은 전부 `interval` 이라 확인한 C군과 같은 경로를 탐. 타입 응답 36종에 B군 6종 포함 확인.
평면(지도)은 손대지 않음 — 노선 위에 구간을 얹는 방법이 지금 없어 **별건**으로 둠.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 결정 두 가지를 반영함(2026-09-07).
① 측구(옆도랑) — 목록에 두되 표시만.
레지스트리에 `design_owner` 를 새로 두고 측구에 「횡단 설계」를 적음. 구조물 배치 폼에서
그 종류를 고르면 「횡단 설계에서 관리 — 여기서 넣어도 제원·수량은 그쪽 값을 씁니다.」가
뜸. `managed_by` 와 달리 저장은 그대로 되므로 배치는 계속 가능함.
까닭 — 횡단 설계가 측구 켬/끔·형식·터파기 단면적(`ditch_area_m2`)을 파이썬·TS 짝으로
이미 셈함. 구조물로 또 세면 같은 것을 두 번 계상함.
목록 항목에 안 붙이고 폼에 붙인 것은 「한 항목 = [측점][이름]만」이 2026-08-18 사용자
지시이기 때문임.
② B군 수량 1단계 — 구조물 정본에서 시설별 연장(m)을 냄.
`common_util_structure_lengths.py` 하나. B군 수량 단위가 전부 m 이라 단면 기하가 필요
없음(맹암거 12-10 · L형 측구 12-9-1 · 산마루측구 12-9-2). 수량서 양식에 안 묶이므로
B08 을 실무 xlsx 양식으로 다시 짜도 그대로 씀.
빼는 것 셋 — 관 정본 소관(`managed_by`), 횡단 소관(`design_owner`), 그리고 소단측구
(놓일 소단이 아직 없음 — 계획서 3-9 뒤에 채움).
겹친 구간은 합쳐서 셈함. 같은 시설을 겹치게 두 번 넣으면 단순 합이 그 구간을 두 번
세기 때문임. 원래 합(`raw_length_m`)도 함께 내보내 겹침이 숨지 않게 함.
자체검증
- 새 시험 7건 `tmp/tests/test_structure_lengths.py` — 종류별 합산 / 겹침 제거(80m 인데
단순 합 110m) / 측구 제외 / 소단측구 제외 / 배관 제외 / 구간 없는 항목은 스키마가 막음
/ 빈 프로젝트.
- 화면 확인(8001·5174, `/api/health` `stale:false`) — 구조물군 B → 종류 측구 선택 시
안내가 254×44px 로 뜨고 문구가 맞음. 리셋으로 폼 되돌림.
- 전체 521 passed · 18 skipped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- `B05_Profile_UI_RouteEdit_Curve.ts` 신설(68줄) — 손잡이 끌기 역셈
(`dragHandleTo`)·직선 교점(`intersect`)·내각(`innerAngleDeg`) 순수 기하만.
- 모달은 740 → 692줄. 화면 배선·동작 불변, 셈 식 그대로 옮김.
- 서버 정셈과 짝임을 새 파일 머리에 명시. 거울 시험은 새 자리를 보게 갱신.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실화면에서 잡음 — 곡선 하나만 지워도 나머지 반지름이 **R 12~199m → 전부 12m**
로 되돌아갔음.
원인은 편집 모델과 저장 모델이 다른 것이었음. 서버는 처음 만들 때 이어진
꺾임을 한 곡선으로 묶는데, 그 곡선의 교각점은 앞뒤 직선을 늘려 만나는 자리라
**원본 꺾임점 중 어느 것도 아님**. 편집은 「꺾임점 하나 = 곡선 하나」로
표현되므로, 묶인 채로 두면 한 번만 손대도 묶음이 낱개로 흩어지고 각 자리가
하한으로 떨어졌음.
모달이 자료를 읽을 때 **묶인 구간을 그 교각점 하나로 갈아 끼우게** 함 —
안쪽 꺾임점은 그 곡선이 대신하므로 뺌. 앞뒤 직선과 반지름이 그대로라
그려지는 선은 똑같고, 이제 손대도 안 흩어짐. 서버가 고른 반지름도 함께
들고 가 [확인] 때 되돌려 보냄.
시험 tmp/tests/test_route_polyline_apex_roundtrip.py 2건 — 갈아 끼워도 곡선
수·반지름이 같고 선이 **1mm 안**에서 일치, 그리고 안 갈아 끼우면 실제로
하한으로 눌리는 것(왜 필요한지)도 못박음.
실화면 확인(용화) — 되돌린 뒤 곡선 26곳 R 최대 198.9m → 곡선 하나 지우고
[확인] → 곡선 25곳, **R 42.5·51·198.9m 그대로**.
tsc --noEmit 통과 · pytest 432 passed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정(2026-09-07) — 「직선과 곡선 교차점 이동 시에는 직선의 각도와
반지름 값 변경이 되」. 되물어 확정: 끄는 점은 **곡선 시작·끝점**.
셈은 서버의 반대 방향임 — 서버는 교각점·R 에서 접선점을 내고, 화면은 끈
접선점에서 교각점·R 을 구함. 끈 쪽 직선만 돌리고 반대쪽은 옛 교각점을 지나는
그대로 두어, 두 직선이 만나는 자리가 새 교각점이 되고
R = |새 교각점 − 끈 자리| / tan(교각/2) 로 나옴.
**두 벌이 아니라 짝임** — 왕복이 제자리인지를
tmp/tests/test_route_polyline_handle_drag.py 3건이 지킴. 화면이 낸 (교각점, R)
을 서버 셈에 넣으면 끈 자리가 **1µm 안**으로 되돌아옴. 접선점을 직선 위에서만
밀면 교각점이 안 움직이고 R 만 커지는 것도 확인.
손잡이를 **속 빈 네모(5px)** 로 키움 — 3.5px 채운 네모는 선·노드와 색이 같아
눈에도 안 띄고 집기도 어려웠음(실화면). 곡선을 지운 자리에는 손잡이도 없음.
실화면 확인(용화) — 손잡이를 끌자 「14번째 꺾임점 · R 16.6 · 값 지정」으로
바뀜. 서버가 곡선 성분 22개(예: R 44.3m, 노드 1~3을 한 곡선으로)를 내려줌.
⚠ 그 확인 도중 **서버가 또 옛 코드로 돌고 있었음**(응답에 `curves` 키 자체가
없었음). 오늘 두 번째임 — 화면 검증 전에 응답에 새 필드가 있는지부터 볼 것.
tsc --noEmit 통과 · pytest 430 passed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PLAN 2-5 (2026-09-07 사용자 지시 4 「구조물 표시 통일」). B06 종단에는 구조물 마크가
아예 없었고 배수관·세월교만 다른 계통으로 그려졌음.
- B05 가 쓰는 **같은 부품**(`buildStructureLane`)을 B06 종단 그래프 아래에 붙임.
이름·중복 번호·툴팁·약호가 전부 B05 규칙 그대로 따라옴.
- 종단 차트가 `toX`(누가거리 → px)를 내보내 레인이 그래프와 같은 자리를 씀.
- 좌측 「구조물 배치」가 목록을 받을 때마다 `setStructureMarks` 로 넘김(구조물 정본 +
관 정본). 관을 가상 구조물로 바꾸는 `pipesToStructureMarks` 는 B05 안에 있던 것을
공용 자리(`B05_Profile_Api_Structures`)로 올려 **한 벌만** 둠.
- 알약을 누르면 그 자리에 가장 가까운 측점 카드를 고름(좌측 목록 클릭과 같은 규칙).
끌기는 B05 몫이라 여기서는 자리만 보임(배수유역 재분할이 걸림).
- 검증 훅 `window.__b06Marks` 추가(`__corridorBuild` 등과 같은 용도).
자체검증 — 실화면 B06 종단에 레인 1줄·알약 10개(「배수관 1~8 · 세월교 1~2」)가 B05 와
같은 표기로 뜸. 훅 값 `{structures:10, types:36}`. tsc 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
실화면에서 [곡선 지우기] 클릭이 캔버스에 가로채였음 —
「<canvas …> subtree intercepts pointer events」.
원인은 세로 배치임. 상자가 세로 flex 이고 캔버스 자리가 `flex: 1 1 auto` 라
공간을 다 먹는데, 새로 넣은 편집줄에 `flex: none` 이 없어 눌려 없어지고
캔버스가 그 위를 덮었음. 바닥 단추줄과 같이 `flex: none` 을 주고
`z-index: 1` 로 올림.
실화면 재확인(용화, 20번째 꺾임점) — 네 조작 모두 동작:
고름 → 「자동 · 내각 155° · 법정 하한 12m」
곡선끔 → 「곡선 없음 — 직선이 그대로 꺾입니다」 · 상태줄 「곡선 지움 1곳」
곡선켬 → 「자동」으로 복귀
R 40 → 「값 지정」 · 상태줄 「R 지정 1곳」
자동 → 값 비고 「자동」으로 복귀
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지시(2026-09-07) — 「r과 직선 삭제나 추가가 있어야 하지 않을까?」
서버 쪽(f59932de)에 이어 화면을 붙임.
- **곡선 시작·끝점을 네모로 표시** — 어디부터 어디까지가 한 곡선인지 눈으로 봄.
- 꺾임점을 누르면 **고른 자리**가 되고 아래 편집줄이 그 곡선을 만짐.
- **R 입력칸** — 값을 넣으면 그 반지름으로 못박고, [반지름 자동]으로 되돌리면
서버가 예정노선에 맞춰 다시 고름.
- **[곡선 지우기] / [곡선 넣기]** — 지운 자리는 가운데가 빈 동그라미로 보이고
직선이 그대로 꺾임.
- 직선 삭제·추가는 원래 있던 조작 그대로(오른쪽 클릭 삭제 · 두 번 클릭 삽입).
다만 그때 **편집값 목록도 같은 자리에서 밀어 준다** — 안 그러면 뒤 노드의
R·켬끔이 한 칸씩 어긋남.
- [확인]이 정점마다 `curve`·`radius_m` 을 함께 보냄.
상태줄에 「곡선 N곳(하한 R m) · 곡선 지움 N곳 · R 지정 N곳」을 보임.
tsc --noEmit 통과 · pytest 427 passed.
남은 것 — **곡선 시작·끝점을 끌어 직선 각도와 R 을 함께 바꾸는 조작**은 다음 단계.
지금은 표시까지이고, 자리 옮기기는 꺾임점 끌기로 함.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지시(2026-09-07) — 「r과 직선 삭제나 추가가 있어야 하지 않을까?」
편집을 **꺾임점 목록 + 자리마다 곡선 켬끔 + 반지름** 셋으로 표현함.
· 직선 삭제·추가 = 목록에서 점을 빼거나 더하기(빼면 앞뒤 직선이 하나로
합쳐지고, 직선 위에 더하면 둘로 갈리며 그 자리에 곡선이 생김)
· 곡선 삭제·추가 = `curve` 를 끄고 켜기(끄면 직선이 그대로 꺾임)
· 반지름 변경 = `radius_m` 못박기(없으면 서버가 고름)
`POST /route/replan` 의 정점마다 `curve`·`radius_m` 을 받게 함.
편집값이 오면 **묶지 않음** — 사용자가 곡선 하나로 본 것을 임의로 합치면
손잡이가 사라지기 때문. 편집값은 점과 짝이라 중복 제거도 함께 함.
시험 tmp/tests/test_route_polyline_edit.py 7건 — 곡선 삭제·추가, 반지름
못박기, **반지름을 바꿔도 교각점은 안 움직임**(「주변 직선 각도 구속」),
직선 삭제·추가. pytest 427 passed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PLAN 3-6 「설치 측을 사용자가 고르게 할지(폼에 칸 추가) 뒤에 정할 것」 — 2026-09-07
사용자 확정 「폼 선택은 가능하게 반영하고 나중에 선택 비활성화로 하자」.
- 레지스트리 C군 5종(옹벽·돌쌓기(찰)·돌쌓기(메)·흙막이·큰돌쌓기)에 `side` 선택 칸.
선택지 「자동(성토 쪽)·좌·우」, 기본은 자동 — 종전 동작(성토 나는 쪽 자동)과 같음.
- 기하는 이미 그 값을 봄 — `B06_Section_UI_Cross_Revetment.ts:168` 이 "좌"/"우" 면 그쪽,
아니면 `fillSide()`. 배관(`common_util_structure_walls.ts:80`)·파이썬 짝도 `options.side`
를 이미 나름. 즉 배선은 있고 **칸만 없었음**.
- 옵션 칸에 `enabled` 를 둠(기본 참). 거짓이면 폼에 **회색으로 남고** 못 고르며 필수 검사
에서도 빠짐 — 칸을 지우지 않고 잠그는 자리(사용자 「나중에 비활성화」).
자체검증 — 레지스트리 5종 모두 `(['자동(성토 쪽)','좌','우'], 기본 '자동(성토 쪽)', enabled True)`
로 읽힘. 실화면 B06 C군 폼에 「설치 측」 칸이 그 세 선택지로 뜸(값 자동). tsc 통과.
시험 499 통과 — 실패 1·오류 8 은 모두 `require is not defined in ES module scope` 인
JS 도우미 건으로 내 변경과 무관(도우미 파일 날짜 8/27·9/2, 다른 환경에서 만든 것).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PLAN 3-6 (2026-09-07 사용자 지시 5 「A군뿐 아니라 구조물 전체를 넣을 수 있어야 함」).
원인은 「B06 이 A군만 받는다」가 아니라 **레지스트리의 `enabled:false`** 였음 — B군 6종·
F군 2종·G군 1종이 목록에서 통째로 빠져 있었고, 두 화면이 같은 목록을 쓰므로 B05·B06 이
똑같이 A/C/D/E/G/기타 여섯 군만 보였음. 레지스트리 주석(2026-08-17)이 그 셋을 「B05
선택지에서 빼고 **B06 개별 횡단도 옵션으로 재사용**」이라 적어 둔 자리임.
- `fetchStructureTypes(includeDisabled)` 로 갈래를 둠. B06 만 참으로 부름 — B05 는 종전대로.
- 함께: 3-5 ⓑ 되돌릴 자리 주석(단 2개 이상일 때만 이어 붙이는 한 줄) 표시.
자체검증 — 공용 브라우저에서 두 화면 군 목록 대조:
B06 A·**B**·C·D·E·**F**·G·기타 (8) / B05 A·C·D·E·G·기타 (6, 그대로)
B06 에서 B군 6종(측구·산마루측구·소단측구·도수로·절토사면 배수로·맹암거)과
F군 2종(야생동물 이동통로·비탈면 녹화)이 실제로 목록에 뜸. tsc 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 확정(2026-09-07) — 사용자가 잡는 것은 **곡선 시작·끝점**이고 필요하면
반지름을 직접 바꿈. 정점 목록만으로는 어디부터 어디까지가 한 곡선인지,
그 반지름이 얼마인지 알 수 없어 편집·도면이 같은 값을 못 봄.
- RouteCurve 신설 — 교각점(apex) · 반지름 · 접선길이 · 내각 ·
곡선 시작점 · 끝점 · 그 곡선이 대신하는 꺾임점 구간 · 위반.
반지름을 바꿔도 apex 는 안 움직임(「곡선 반지름 변경 시 주변 직선 각도
구속」이 그 뜻 — 직선이 고정이라 접선점만 미끄러짐).
- `planned_route_curves.json` 으로 저장(노드 CSV 옆).
- `GET /route/plan` 이 `curves` 를 함께 돌려줌.
곁들여 고친 것 — 묶음을 도로 쪼갤 때 **별표2 의 155° 를 다시 안 봐서**
펴진 자리(내각 159°)에도 곡선이 생기고 있었음. 쪼갤 때 다시 검사함.
그 결과 용화 노선이 곡선 24 → 13곳, 정점 179 → 145 로 제자리를 찾음.
실측(용화, 예상노선 331점) — 노드 28 · 곡선 13 · 정점 145 · 위반 0 ·
벗어남 최대 3.57m 평균 1.081m(고치기 전 1.077m). 반지름은 12~28m 로
자리마다 갈림(전에는 전부 12m).
pytest 420 passed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
같은 노선으로 [확인]을 되풀이하면 계획노선 정점이 136 → 134 → 119, 노드가
22 → 21 로 계속 줄었음(보조 창 실측). 사용자가 아무것도 안 옮겨도 누를
때마다 자기 노선이 뭉개졌음.
원인은 **이미 폴리라인인 것을 다시 단순화**한 것. 두 자리 모두 그랬음 —
- read_route_plan 이 노드를 계획노선(원호 점이 섞인 폴리라인)에서 되뽑음
- replan_route 가 화면이 보낸 노드를 또 한 번 단순화해서 씀
단순화(Douglas-Peucker)는 원본 점군에서 한 번만 돌아야 함.
고친 것:
- build_planned_polyline 에 simplify 갈래 신설. False 면 받은 점을
꺾임점으로 그대로 씀(중복 제거만).
- 폴리라인을 쓸 때 그것을 낳은 **노드도 함께 저장**
(planned_route_nodes.csv · planned_route_initial_nodes.csv).
노드는 폴리라인에서 되뽑을 수 없으므로 낳은 값을 보관함.
- read_route_plan 은 저장된 노드를 그대로 씀(없는 옛 프로젝트만 뽑음).
- replan_route 는 simplify=False 로 씀.
실측(용화 b269ea34 실제 노선 파일, 4회 왕복)
옛 방식 노드21/정점115 → 20/115 → 20/113 → 20/115 (깎이고 흔들림)
고친 방식 노드21/정점115 → 이후 매 회차 **완전히 동일**
시험 tmp/tests/test_route_polyline_idempotent.py 2건 신설 — 노드 왕복이
제자리인지, 그리고 옛 방식이 실제로 깎이는지(갈래가 필요한 이유) 못박음.
pytest 414 passed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
자동 체인 2.7 단계 추가 — 초기 폴리라인을 세운 뒤 노선을 다시 읽어
그것을 BP·경유점·EP 로 세우고 algorithm=as_planned 로 넘김.
전에는 폴리라인 파일만 만들고 노선은 원본 점군으로 풀었음. 그래서
종횡단 측점·유토곡선·3D 코리도가 곡선 없는 점군 위에 섰음.
실측(용화 3건): DB 노선 정점 331·323 vs 초기 폴리라인 145.
노선을 한 번이라도 편집한 프로젝트만 145 로 맞아 있었음.
자체검증 — 2.7 재판독이 145 정점을 돌려주고 BP·EP 좌표가
expected_route.csv 첫·끝 줄과 같음. pytest 409 passed.
계측 로그(_log_steps) 동봉 — 재확정 체인 단계별 경과시간용.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PLAN 0-10. 그동안은 화면이 route/plan 을 처음 부를 때 만들어져, 화면을 안 열면 값이
없었음 — 초기값은 서버가 낸다는 0-4 원칙과 어긋났음.
- 파일입력 자동설계 체인이 예상노선 정본을 남긴 직후(2.6단계) 초기 폴리라인도 세움.
실패는 비치명적 — 없으면 화면이 처음 열릴 때 만들어짐.
- _ensure_planned_initial 이 **낡음도 본다** — 예상노선 파일이 더 나중에 쓰였으면 다시
만듦. 파일을 다시 올리면 예상노선이 새로 깔리는데 초기본이 옛 노선인 채로 남으면
노선 초기화가 옛 자리로 돌아갔음.
자체검증 — 예상노선 파일 시각을 최신으로 만든 뒤 route/plan 을 부르니 초기 폴리라인이
다시 만들어짐(노드 28 · 곡선 13 그대로). 시험 409 통과·17 건너뜀.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
보조 창 지적 — [3D 업데이트]를 눌러도 브라우저가 만들기만 하고 PUT 이 없었음.
저장 시점이 B05->B06 이동뿐이라(2026-08-23 확정), 누른 뒤 새로고침하면 저장본이 낡은
채라 다음 사람이 또 만들어야 했음.
- 버튼 경로 끝에서 saveCorridorIfDirty 를 부름.
- saveCorridorIfDirty 가 PUT 성공 뒤 그 봉투를 브라우저 보관함에도 담음(옛 열쇠 자리는
치움). 그러지 않으면 다음 진입이 새 열쇠 주소로 16.9MB 를 한 번 더 받았음.
typecheck 통과. 실측 확인은 보조 창이 자기 프로젝트에서(저장본이 최신인 자리) 진행.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PLAN 0-2 항목 9 / 0-3. 노선 편집 [확인]이 재확정 체인을 타는데 그 체인이 solve_route 로
BP·CP·EP 사이를 격자에서 다시 풀었음. 사용자가 노드를 조금만 비틀어도 탐색 제약에 걸려
체인이 통째로 멈췄음(보조 창 로그: 세그먼트 1 (BP -> CP1) 경로 탐색 실패 — 종단경사
한계 26% · 최소곡선반지름 12m · 회피지역 제약).
- B05_Profile_Engine_AsPlanned.solve_as_planned 신설 — 제어점 목록이 곧 노선이고 표고만
지표면 격자에서 뜸. 반환 꼴은 솔버와 같아 아래 단계가 그대로 이어짐.
종단기울기·곡선반지름 위반은 **세되 막지 않음**(사용자 확정: 자동 보정·차단 없이 경고만).
- run_route_design 에 algorithm=as_planned 갈래 추가. 스키마 검증에도 허용.
- 재확정 체인이 그 갈래를 씀 — 자동탐색은 이제 초기 업로드에서만 돎.
솔버와 지표 계산이 겹치지만 합치지 않음 — 솔버는 0-3 으로 접히는 코드라 리팩터링해
두 곳을 얽을 값어치가 없음.
시험 409 통과·17 건너뜀, main import 스모크 통과.
실화면 [확인] 재검증은 보조 창이 자기 프로젝트에서 진행.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
보조 창 실측 — [확인] 이 체인 중간에 400 으로 끊겨도 route/replan 은 success 를 돌려주고
계획노선 CSV 는 이미 새 노선으로 바뀐 뒤였음. 그 결과 배수유역·관은 새 노선, 종횡단은
옛 노선으로 어긋난 채 굳고(배수관 측점 9 -> 0), 다시 누를수록 어긋남이 쌓였음
(1,097.4 -> 1,079.4 -> 1,064.7m).
- run_redesign_chain 이 중단 사유를 문자열로 돌려줌(성공은 None). 중단 지점 넷 모두.
- replan 이 쓰기 전에 이전 수정본을 쥐고 있다가 실패하면 되돌림. 처음 고치는 경우였으면
파일을 지워 초기 폴리라인으로 돌아감.
- 실패는 409 + 사유로 응답 — 화면이 성공으로 보이던 것을 막음.
원인 자체(자동탐색이 사용자 노선을 다시 풀다 실패)는 별건으로 남음 — 로그 사유
「세그먼트 1 (BP -> CP1) 경로 탐색 실패: 종단경사 한계(26%)·최소곡선반지름(12m)·회피지역
제약으로 통과 경로가 없습니다」. 고친 노선을 그대로 받아 쓰는 입구가 필요함(PLAN 0-2 항목 9).
시험 409 통과·17 건너뜀.
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>
손 안 댄 프로젝트를 열면 저장본 열쇠가 맞아 매번 16.9MB 를 받았고, 브라우저 보관이
모듈 Map 이라 새로고침 한 번에 날아가 또 받았음(보조 창 실측: 첫 로그인~B05 도달 29MB
중 16.9MB 가 이것). 해시 질의(0b30f5b0)는 낡았을 때만 막았지 맞을 때는 그대로였음.
- b_asset_cache 에 readCachedBytes / writeCachedBytes / purgeAssetsWithPrefix 추가.
앞 둘은 네트워크를 안 타는 순수 보관함 접근이고, 마지막은 주소 앞머리가 같은 옛
보관본을 지움 — 코리도는 주소에 열쇠가 박혀 정본이 바뀌면 새 주소가 되므로 17MB 짜리가
쌓이지 않게 담기 전에 치움.
- 코리도 조회가 보관함을 먼저 봄. 주소에 열쇠가 있어 정본이 바뀌면 저절로 다른 주소가
되므로 옛 보관본을 잘못 쓸 일이 없음.
자체검증(공용 브라우저) — 담기·읽기 왕복 정상(44바이트 왕복, 해시 보존), 열쇠만 다른 두 벌을
담은 뒤 앞머리 지우기로 둘 다 제거 확인. typecheck 통과.
※ 실제 16.9MB 절감은 저장본이 최신인 프로젝트에서 확인해야 함 — 이 프로젝트는 검증 중
계획고를 만져 저장본이 낡은 상태라 코리도 자체가 안 실림(__corridorSource null).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
사용자 지시(2026-09-06) — 노드를 제어해 계획노선을 고친다. 그동안 모달은 서버가 준
폴리라인 정점을 그대로 잡았는데, 거기에는 원호 위 점이 섞여 있어 편집 대상이 아님.
- 그려 보이는 선(폴리라인, 원호 포함)과 잡는 점(노드)을 나눔. 선은 plannedLine,
노드는 서버가 내려 준 nodes.
- 노드에 붙은 반지름·내각·법정 위반을 화면에 실음 — 위반 노드는 붉게, 상태줄에
곡선 수와 기준 R, 미달 개수.
- 노드를 옮기면 폴리라인은 낡은 값이므로 지우고 직선으로 미리 보임. 곡선은 [확인] 때
서버가 같은 R 규칙으로 다시 끼움(계산을 두 벌로 짜지 않음).
- API 타입에 nodes·min_radius_m·curve_count·violation_count 추가.
자체검증(공용 브라우저, 용화) — 모달이 노드 28개로 열리고 상태줄에
「노드 28개 · 초기 폴리라인 · 곡선 13곳(R 12m)」. 전에는 폴리라인 정점 142개를 잡았음.
typecheck 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
계획서 2-2. 3D 픽·사이드 목록에는 structure-pick 기록이 있는데 종단 그래프 알약 경로에만
빠져 있었음 — 세션 키가 아예 안 써져 B06 이 잡을 값이 없었음(보조 창 추적).
- 구조물 브리지에 markChainage 추가 — 알약 id 의 누가거리를 구조물 정본·관 정본 양쪽에서
되읽음.
- Page 의 onStructureSelect 가 writeStructurePick 으로 그 자리를 남김(사이드 목록 경로와
같은 창구).
자체검증(공용 브라우저, 용화) — 알약 18개 중 셋을 눌러 세션 키가
찰쌓기 1 -> {at:40} · 찰쌓기 3 -> {at:80} · 옹벽 -> {at:120} 으로 써짐(전에는 null).
그 상태로 B06 진입 시 측점 6+0.0(120m) 카드가 선택된 채로 뜸. typecheck 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>