auto: 2026-10-01 08:46 (ESD_LAPTOP)

This commit is contained in:
2026-10-01 08:46:34 +09:00
parent bcb1c725c4
commit 6387fb8167
@@ -0,0 +1,732 @@
# 지난 계획 — 20~31장 (2026-09-29 ~ 09-30)
초기 계획노선 갈래 · 구조물 조합 항목 연결 · 계획노선 편집 · 노선 추천 · B05/B06 한 페이지 · 선택 입력 · 폴더 구조 · 구조물마다 복사본 · 마스터 템플릿 재구성(라이브러리 한 화면 · 일위대가 이동 · 대시보드 설정) · M01 원문 대조 흠 고침 · 회사 알약 · 여러 개 고르기 · 층 사이 복사 · 카드 공용 틀.
## 20. 초기 계획노선 갈래 (담당 sub3 서버 · dmain 화면)
- 사용자 확정: 초기값 = 예상노선 추종(필수 · 늘 켜짐) · 로직 단추 셋 = 토공 최소 · 기울기 순한 노선 · 비중 계산(예상 · 토공 · 기울기 슬라이더 합 100 · 기본 50/25/25) · 단추를 누르면 그 결과가 적용되고 새 초기값 · [초기화](옛 「예상노선으로」) = 마지막 적용 결과 · 화면에 「현재 초기값: ○○」 · 종단 · 배수유역 · 횡단 다시 계산은 노선이 바뀐 뒤 [확인]에서만 · [저장]에서 작업본 · 공통 제약(종단기울기 상한 · 최소 곡선반경 · 계류 이격) 모든 로직이 지킴.
- 사용자 확정(9-29): 공통 제약 기준값 확정 — 후보 표 임시값(종단기울기 상한 = 프로젝트 설계속도 · 지형 표값 · 최소 곡선반지름 = 프로젝트 표값 · 계류 이격 100 m · 토공 가늠 폭 4 m · 탐색 복도 100 m · 기울기 잴 지반 5 m) 그대로 기본값 · 로직 단추 옆 제약 칸(종단기울기 % · 최소 반지름 m · 계류 이격 m · 지반 고름 m)에서 프로젝트마다 숫자를 바꿀 수 있음(비우면 기본값).
- API(sub3 정함 · dmain 맞춤): `POST /api/projects/{id}/route/initial` 받음 `{logic(또는 mode): "follow"|"earthwork"|"gentle"|"weighted", weights?: {expected, earthwork, grade}}`(weighted 만 · 합 100 · 기본 50/25/25) → 줌 `{status, mode, weights, planned: [[x,y]…], nodes: [/route/plan 의 nodes 와 같은 모양], curves: [/route/plan 의 curves 와 같은 모양], metrics: {length_m, max_grade_pct, avg_grade_pct, cut_m3, fill_m3, over_limit: {grade, radius, stream, total}, offset_avg_m, offset_max_m}, criteria: {max_grade_pct, min_radius_m, stream_offset_m, road_width_m, corridor_m, pending: [확정 대기 칸 이름]}}` · 파일 안 씀(캐시용) · 적용 = 받은 nodes 로 기존 `POST /route/replan`([확인])
- 현재 초기값: `POST /route/replan` 에 `initial: {logic, weights}` 을 함께 보내면 성공 때만 `B05_Profile/route/initial_choice.json` 에 적음(자동저장 없음) · `GET /route/plan` · `POST /route/initial` · `POST /route/replan` 응답에 `current_initial: {logic, weights}`(없으면 follow 100/0/0) · 응답에 `logic` 칸도 줌(`mode` 와 같음)
- 공통 제약 넘지 못함(sub3 · 응답 칸 더함): 응답에 `relaxed`(제약 다 지키는 길이 없었나) · `terrain_bound_pct`(그때만 — 복도 안 어떤 길도 넘어야 하는 기울기 · 그 위는 막음) · `metrics.violations: [{kind: "grade"|"radius"|"stream", from_m, to_m, station: "No.9+0.0", value, limit, reason}]` · `metrics.over_limit.total` = 목록 수 · `metrics.raw_max_grade_pct`(참고 · 고르지 않은 DEM) · `criteria.grade_smooth_m` — 종단기울기 = 측점 20 m 사이 · DEM 을 5 m 로 고른 지반(도상 가늠) · dmain 화면은 목록 표시 한 줄만 더함
- [x] 서버: 초기노선 생성 길 하나에 갈래 인자(추종 · 토공 최소 · 기울기 순한 · 비중{예상,토공,기울기}) · 공통 제약 적용 · 결과 비교값(연장 · 최대/평균 종단기울기 · 절성토량 · 기준 초과 구간 수 · 예상노선 이격) 함께 반환 · 지식DB 기준값 후보 표(sub3) — 검증완료(test_route_initial 10 · 랩탑_보조 ORCA 네 갈래 200 · 비중 반응 · 400 · 422 · 노선 파일 안 씀)
- 자리: `B05_Profile/B05_Profile_Engine_RouteInitial.py`(엔진) · `B05_Profile_Router_Replan.py` `initial_route`(길) · 추종 = 지금 `_ensure_planned_initial` → `build_planned_polyline`
- 기준값 확정 · 화면에서 변경 가능(코드 머리 상수 = 기본값, 비운 칸에만 씀):
| 항목 | 원문 | 실무 | 출처 | 임시값 |
| --- | --- | --- | --- | --- |
| 종단기울기 상한 | 간선 · 산불 설계속도 40/30/20: 일반 7/8/9 % · 특수 10/12/14 % · 특수+포장 18 % · 작업임도 20 % | 평균 3~8 % 만점(타당성평가) · 능선 4 % 이내(교본) | 별표2 Ⅰ.2.라 · 타당성평가 · 교본 3장 | 프로젝트 설계속도 · 지형 표값(비포장) |
| 최소 곡선반지름 | 40/30/20: 일반 60/30/15 · 특수 40/20/12 m · 배향곡선 10 m · 작업임도 규정 없음 | 계곡 · 능선 진입 때 반지름 먼저 확보(교본) | 별표2 Ⅰ.2.다 · 교본 3장 | 프로젝트 표값(`_plan_criteria`) |
| 계류 이격 | 법정 이격 수치 없음 | 산지계류 100 m 이내 구간 비율 5 % 미만 만점(1/25,000 주요 수계) · 계류 버퍼 경고(교본 표 2-4) | 타당성평가 · 교본 2장 | 100 m · 소하천 이상(세류 · 연결선 뺌) · 건너기 봐줌 |
| 토공 가늠 폭 | 유효너비 3 m + 길어깨 0.5~1 m(간선) | — | 별표2 횡단구성 | 4 m |
| 탐색 복도 | 법령 값 아님 | — | — | 예상노선 좌우 100 m |
| 기울기 잴 지반 | 도상 측정(1/5,000 · 20 m 간격) | 지반 잔굴곡은 계획고가 흡수 | 타당성평가 GIS 측정 규칙 | DEM 을 5 m 로 고름 · 측점 20 m |
- [x] 화면(B04 계획노선 편집 창): 「예상노선으로」→「초기화」 · 로직 단추 셋 · 비중 슬라이더 셋(합 100 · 기본 50/25/25) · 「현재 초기값: ○○」 · 결과 비교값 한 줄 · 다시 계산은 [확인]에서만(dmain) — 화면 틀 검증완료(자리 = B05 계획노선 편집 창 · 옛 「초기화」는 「연 상태로」 · API 줄 모양에 맞춤(`normalizeRouteInitial`) · [확인] 몸통에 `initial{mode,weights}` 실음 · 실서버(데스크탑_메인) 토공 최소 1078.0→1141.6m 노드 34 · 기울기 순한 1140.8m · 비중 70/15/15 1118.8m · 각 0.7초 · 기준 초과 6/7/11구간 · 기준값 확정(꼬리표 없음) · 가짜 답으로 토공 최소 1078.0→1091.4m · 비중 70/15/15 합 100 · 되돌리기 뒤 [초기화] = 비중 결과 · 노선 그대로 [확인] = 재계산 0회 · [취소] 뒤 초기값 되돌아옴 · 열 때 서버 `current_initial` 로 「현재 초기값」(원본 follow → 예상노선 추종 · 비중 70/15/15 끼워 넣으면 그 이름 · 슬라이더 70/15/15 · [초기화] = 그 갈래 서버에 물어 1118.8m · 캐시가 서버와 다르면 서버가 이김) · 사본 왕복(원본 폴더 사본 · DB 읽기만 · 재계산 체인 가짜) 추종 · 토공 최소 · 기울기 순한 · 비중 50/25/25 마다 [확인] → 다시 열기 현재 초기값 = 보낸 것 · 다시 연 노드 = 보낸 노드 · [초기화] = 마지막(비중) 노드 · 캐시 없으면 서버가 같은 노드 · 비교값 다 있음 · test_b05_routeedit_initial_roundtrip 5 · 제약 못 지킨 구간 한 줄(없으면 「모두 지킴」 · 5곳 넘으면 「외 N곳」 · 풍선에 전부) · 상한 풂 안내 · 「기울기 잴 지반 5m 고름」 — 사본 네 갈래 모두 4곳 · 상한 29.1% 로 풂 · 화면 끼워 넣기 7곳 · 외 2곳 · 풍선 7줄 · 없음이면 풂 줄 숨김 · test_b05_routeedit_initial_roundtrip 6 · 검증 대기)
- [x] 화면 공통 제약 칸(종단기울기 % · 최소 반지름 m · 계류 이격 m · 지반 고름 m — 「기울기 잴 지반 고름 칸」과 한 줄에, dmain): 로직 단추 옆 · 비우면 기본값(placeholder 로 보임) · 채운 칸만 `POST /route/initial` 몸통 `criteria{max_grade_pct,min_radius_m,stream_offset_m,grade_smooth_m}` 로 · [확인]의 `initial.criteria` 에도 실어 성공하면 `initial_choice.json` 에 같이 남음(빈 칸은 안 담김) · 다시 열 때 `current_initial.criteria` 에서 그 칸만 복원(나머지는 그 자리 기본값 placeholder) · 서버 B05_Profile_Engine_RouteInitial · Router_Replan 이 criteria 를 받으면 그 값으로, 없으면 기본값 · 응답 `criteria.pending` 은 이제 늘 빈 목록 — 화면 「후보 · 사용자 확정 대기」 글 삭제 — 검증완료(엔진 test_route_initial 17: stream_offset_m 30 · grade_smooth_m 2 override 시 응답 그 값 그대로 · max_grade_pct 는 그대로 · initial_choice 왕복에 criteria 칸 · 라우터 model_validate 로 criteria 파싱 · 사본 왕복 test_b05_routeedit_initial_roundtrip 7: 계류 이격 30m 만 겹쳐 물음 → 답에 30 · [확인] 뒤 `current_initial.criteria == {stream_offset_m: 30}` · `/route/plan` 다시 읽어도 그대로 · [초기화] 캐시 일치 · 화면 단위시험 test_b05_routeedit_initial 9: criteria 줄에 「확정 대기」 없음 · serverBase/sameBase 가 제약 겹침도 견줌 · 타입검사 0 · prettier·ruff 적용)
- 사용자 확정(9-29): 관 · 구조물 자리에는 그 소수 측점의 횡단을 따로 둠(지금 정수 m 격자로 붙는 것을 풂) · 화면 표기는 「측점 + 거리」에서 거리를 정수로 반올림해 보임(예 119.8 → No.5+20) · 백엔드 · 파일 · 저장값은 소수 그대로
- [x] 소수 측점 횡단(sub6): 구조물 · 관 측점의 횡단을 소수 자리 그대로 만들고 파일 이름 소수 2자리(`cross_00119.80m`) · `Engine_Sections_Core:348` 격자 붙임 풂 · B06(찾기 · 패치 · 저장) · B07(횡단 도면) · `M02_Table_Fill`(관연장) 찾기 규칙을 같은 이름 규칙으로 · 옛 프로젝트(정수 이름) 열기 호환 · 화면 표기 「No.N+정수」는 보이기만(B05 · B06 목록 · 폼 · 툴팁 · 종단 표시) · 시험 test_b06_patch_station · test_b05_b06_save_roundtrip 에 소수 측점 한 건씩 — 검증완료(08e493f1 · 시험 108 · ORCA 사본 sub6_검증 119.8 → cross_00119.80m · B06 「5+20」 · 사본 지움 · 검증 대기)
- [x] 왕복 남은 차이: 관 측점 4개가 정수 m 로 붙음(440.24→440 등 · Engine_Sections_Core:348) — 관 · 구조물 자체 측점은 소수 그대로 · 횡단 측점만 격자(sub6) · B06 [저장] 때 옮긴 관 측점의 횡단 수정이 버려짐(Persist:452 · Router_Confirm:136)(sub5) — 검증완료(sub6 867c4650 · sub5 548daa6f) · 고친 뒤 왕복 재검(sub8) — 검증완료(af1b419d · 7dbae140 · 재검 차이 0 · ORCA 사본 B05→B06→B05 그대로)
- 검증완료(18 · 브레인 · 메인 5173 · 랩탑_메인 · 랩탑_보조 프로젝트 · 사진 w1~w12): 편집 창 단추(1m 등고선 · 거리 재기 · 초기화 · 로직 셋) · 확대 뒤 기울기 라벨(−34.1% · +21.5% · +30.7%) · 1m 등고선 켬(선 385KB→1153KB · 5m 짙게) · 측점 눈금 이름표 · 눈금 클릭 → 횡단 40+0.0 미리보기 + 지도 반폭 선 · 남김: 회전 저장은 dmain 수치(6.12px/m · 30°)로 갈음
- 검증완료(20 · 브레인 · 5173 · 랩탑_보조 · 확인 안 누름): 토공 최소 → 1078.0→1165.4m · 현재 초기값 토공 최소 · 비교값(최대 18.1% · 평균 7.1% · 절토 1,999 · 성토 1,946 · 기준 초과 4구간 · 이격 19.4m) · 공통 제약 14.0%/R12/100m 후보 표시 · [초기화] = 마지막 초기값 유지 · [취소] 무기록 · 남김: 위반 목록 표시(dmain 진행 중)
- 검증완료(17~20 최종 · 브레인): 전역 12곳 f6fb384f · 아티팩트 보고 · 남은 결정: 공통 제약 기준값 · 소수 측점 횡단 이름
---
## 21. 구조물 집계표 항목 연결 — 세 그룹(마스터 · 회사 · 개인) · B05/B06 좌측 패널 단순화 · 저장 스냅샷 (담당 아래 표)
사용자 방향(9-29) — 구조물 원가·자재는 구조물집계표 항목(SS 한 줄 = 일위대가 UA · 자재조합 UM · 도면 SD · 면적산출 SA · 재료산출 SM)으로만 연결 · B05/B06 좌측 패널은 2D 형상·위치 값만 남기고 상세 옵션은 지움 · 항목은 모달로 고름(마스터 · 회사 · 개인 세 그룹을 폴더처럼) · 적용은 캐시 → [저장]에서 프로젝트 영구저장소로 항목 내용을 복사(지난 공사 값이 돌아가지 않게) · 지정이 바뀌면 옛 복사본 삭제 · 세 그룹 관리 화면은 공용 양식 하나 · 일반 사용자 대시보드에 「구조물 관리」 · 회사 관리자는 회사용 · 개인용 구분 · 회사용은 관리자만 고치고 모두 가져다 씀 · 회사용을 고쳐 쓰려면 개인용으로 복사.
조사 결론(브레인 · 9-29):
- 층 넷 서버 뼈대 있음 — `M02_Template_Layers.py`(system `resources/master_template/` · company `storage/{회사}/templates/` · personal `storage/{회사}/{사용자}/templates/` · project `…/{프로젝트}/templates/` + `_initial/` · manifest · copy · reset · save-as) · 권한 규칙 `Router_Layers.py:130-194`(회사 쓰기 = ADMIN · SYSTEM_ADMIN · is_master · 개인 = 본인만 쓰기 · 같은 회사 읽기).
- 구조물집계표 편집(`M02_MasterTemplete_Store.py` · `Matset.py` · `Branch.py`)은 시스템 층 폴더에 박혀 있음(`FOLDER` :21) · SS 대장 · 자재조합은 회사 · 개인 층에 없음 · M02 화면 `layer="system"` 고정(`UI_Side.ts:90`).
- 구조물 기록(`B05_Profile/route/structures.json` · `B04_PreProcess/drainage/edits/pipe_points.json`)에 집계 항목 칸 없음 · 지금은 `M02_Table_Fill.py` 가 종류 + 옵션값 바인딩으로 열을 맞춤 · 저장 종점은 `PUT /route/structures`(B05 임시저장 · B06 저장 · 확정 모두) 와 `PUT /drainage/pipe-points`.
- 좌측 패널은 B05 · B06 한 코드(`B05_Profile_UI_Structures_*` · B06 은 `includeDetail`) · 옵션 정의 = `B05_Profile_Structure_Types.json`(모르는 키는 저장 거절 `Structures_Repository.py:188-200`) · 옵션 분류: 형상(G · 측점 · 길이 · 높이 · 폭 · 좌우 · 각도 · 관경) · 그림에도 쓰는 값(H · form · foundation · face_slope_ratio · pipe_kind · inlet_structure · tiers 등 — B06 · B07 횡단 그림이 읽음) · 원가 전용(D · stone_kind · stone_supply · fill_concrete_mpa · weep_hole · blinding · bond · stone_cm · spillway · wing_wall_type · inlet_basin_material · joint_spacing · separation_sheet · wire_mesh · ditch_spec · material · extra_distance · capacity 등).
- 공용 부품: 모달 `ui_template_modal.ts`(폭은 `dialogClass` 로) · 접기 카드 `ui-sidebar-card` · 폭 손잡이 `ui_template_resizer` · 나무 보기는 M01 에만(`M01_MasterData_UI_Tree.ts`) → 공용으로 올림 · 「B02 항목선택 상세」는 없음 — 가장 가까운 것 = M02 카드 셋(도면 정보 · 면적산출 · 재료산출 `M02_MasterTemplete_Structure.ts:250`).
- 흠 발견: B05 에서 일반 구조물 [수정] 때 B06 상세 값이 통째로 지워짐(`Panel_Commit.ts:307` 옵션 덮어쓰기 · `readOptions` 는 보이는 칸만).
- B08 · B09 는 빈 페이지 — 이번 장은 연결 자리(항목 · 스냅샷)까지 · 수량 · 원가 계산 화면은 다음 장.
### 21-0. 사용자 확정(9-29)
- 옵션 숨김은 Claude 가 형상 · 원가로 가르지 않음 — **구조물 종류마다 어떤 옵션을 보일지 사용자가 체크**(M02 「구조물 옵션 보이기」 화면 · 시스템 층 · 기본 = 모두 보임) · B05/B06 폼은 체크된 옵션만 보임 · 정의 · 옛 값은 그대로.
- 집계표 항목은 사용자가 지정해야 함 — 자동 맞춤 없음 · 미지정 = 집계표에 안 들어감.
- 모달의 「변경」 = 다른 항목으로 바꾸기 · 해제 · 개인용으로 복사 · [관리 화면에서 고치기] — 모달 안 시트 편집 없음.
- 프로젝트 안에서는 키(SS · UA · SD …)를 앞에 내세우지 않음 — **폴더 모양**(그룹 → 종류 → 분류 → 항목 → 그 항목의 도면 · 면적산출 · 재료산출 · 자재조합 · 일위대가 이름)으로 보임 · 키는 툴팁 · 작은 글.
- 회사 없는 사용자는 없음 — 회사 없이 개인 집계표를 만들려 하면 「회사부터 등록」 안내 · 개인 층 = `storage/{회사}/{사용자}/templates/`.
- 시스템 관리자 대시보드 = 마스터 템플릿 + 구조물 관리(회사용 · 개인용).
- 스냅샷 범위 = SS 줄 + 도면 SD + 면적 SA + 재료 SM + 자재조합 UM + 일위대가 UA 줄 + UA 가 담은 로직 줄(일위대가는 M01 시스템 것 참조).
### 21-1. 약속(모든 창 공통)
- 항목 참조 = `summary_item: {layer: "system"|"company"|"personal", owner: null|"{회사}"|"{회사}/{사용자}", key: "SS000004", name: "돌기슭막이 메쌓기 1.2m"}` — `StructureInstance` 새 칸(스키마) · pipe_points 점 기록의 같은 이름 칸(options 밖) · 없으면 null.
- 항목 목록 API = `GET /api/m02/items?layer=…&owner=…` → `[{key, 열, 종류, 분류1, 분류2, 분류3, 단위, 일위대가, 자재조합, 도번, 면적번, 재료번, names: {일위대가, 자재조합, 도번, 면적번, 재료번}}]`(names = 화면에 보일 이름 · 없으면 null) · `?all=1` → `[{layer, owner, items}]` · 세 그룹 나무 = 그룹 → 종류 → 분류1 → 항목(잎).
- 항목 스냅샷 자리 = `{프로젝트}/templates/items/{layer}_{owner 슬러그}_{key}/` 안 `집계.json`(SS 줄) · `도면.json` · `면적.json` · `재료.json` · `자재조합.json` · `일위대가.json`(UA 줄 + 담은 로직 줄) · `manifest.json`(원본 층 · 판 sha16 · 적용일 · 쓰는 구조물 id 목록).
- 층 폴더 구성(회사 · 개인) = 시스템과 같은 모양 — `table/구조물집계표.json` · `구조물집계표조합.json` · `structure/` · `area/` · `material/` · `자재조합.json`.
- 화면 색 = 목록 줄 `.is-assigned`(`--color-success` 계열) · 미지정은 지금 그대로 · 모든 색은 `var(--color-*)`.
### 21-2. 서버 — 층 인식 집계표 저장소 (sub4 · opus high)
- [x] `M02_MasterTemplete_Store.py` · `Matset.py` · `Branch.py` 의 `FOLDER` 고정을 층 폴더 인자로(`layer_root(layer, owner)` = `M02_Template_Layers` 경로 재사용) · 시스템 층 동작 · 시험 그대로
- [x] 회사 · 개인 층 첫 진입 때 빈 집계표 뼈대 생성(열 0 · SS 대장 `다음 1` · 자재조합 빈 판)
- [x] 라우트: 지금 `/api/m02/structures/…` · `/structure-combos` · `/material-combos` · `/templates/{kind}/{name}` 을 `/api/m02/layers/{layer}/…` 로도 열고 권한은 `Router_Layers._layer_dir` 규칙(시스템 = SYSTEM_ADMIN 쓰기 · 회사 = 회사 관리자 쓰기 · 개인 = 본인) · 옛 경로는 시스템 층 별칭
- [x] `GET /api/m02/items` 목록(21-1) — 세 층 한 번에(`?all=1` · 회사 · 개인은 세션으로)
- [x] 개인 층 쓰기에 회사 없음 → 409 「회사부터 등록」
- [x] 회사 항목 → 개인 복사 `POST /api/m02/layers/personal/items/copy {from_layer, from_owner, key}` — 열 하나 + SD · SA · SM 파일 + UM 줄 복사 · 새 SS 키 · `본뜬` 표시
- [x] 시험 `resources/tester/test_m02_layers_store.py`(층별 읽기 · 쓰기 · 권한 403 · 복사 · 시스템 회귀)
- 검증완료 — test_m02_layers_store 4 · M02 시험 88 통과 · 층 폴더는 `store.at(층 폴더)`(ContextVar) · 층 길 `Router_Items` · 일위대가(UA) 갈라 내기는 층 길에서도 SYSTEM_ADMIN 만(M01 마스터에 씀)
### 21-3. 스키마 · 저장 스냅샷 · 채움 (sub5 · opus high)
- [x] `B05_Profile_Structures_Schema.py` `summary_item` 칸 · `pipe_points` 점 기록 칸 · 검증(층 · 키 모양)
- [x] `PUT /route/structures` · `PUT /drainage/pipe-points` 뒤 — 지정 항목마다 스냅샷 복사(21-1 자리 · 이미 있고 판 같으면 안 씀) · 아무 구조물도 안 쓰는 스냅샷 폴더 삭제(지정 바뀜 · 구조물 삭제) · manifest 갱신
- [x] `M02_Table_Fill.py` — 프로젝트 모드는 항목 지정 우선(스냅샷의 열 정의 사용) · 옵션 바인딩 자동 맞춤은 끔(미지정 = 빈칸)
- [x] `[초기화]` 는 스냅샷 폴더를 건드리지 않음(초기값 정책 그대로) · 프로젝트 복제 도구가 `templates/items/` 도 복사
- [x] 시험 `resources/tester/test_structures_summary_snapshot.py`(지정 → 저장 → 폴더 생김 · 마스터 바꿔도 프로젝트 값 그대로 · 지정 바꿈 → 옛 폴더 삭제 · 해제 → 삭제 · 채움이 지정 열로)
- 검증완료 — 스냅샷 시험 17 · 관련 시험 168 통과 · 폴더 이름 `{layer}_{owner 슬러그(없으면 none · / → -)}_{key}` · `집계.json` = `{줄, 열}` · 관 id = `pipe@측점` · 회사 · 개인 항목 열 id = `열id@폴더` · 관 `summary_item` 은 화면(21-4)이 되보내야 유지
### 21-4. B05/B06 좌측 패널 (sub3 · sonnet high)
- [x] 폼은 `GET /api/projects/structure-types` 옵션의 `visible`(21-8) 이 false 면 숨김 · 정의 · 값은 그대로(모두 true 면 지금과 같음)
- [x] [수정] 때 옵션 덮어쓰기 → 보이는 칸만 바꾸고 나머지 보존(`Panel_Commit.ts:307` · 관 계열의 merge 와 같은 길) — 흠 고침
- [x] 폼 옵션 아래 「집계 항목」 줄: 이름(없으면 「미지정」) · [고르기](모달 21-5) · [해제] · 관 계열 하위 폼도 같은 줄
- [x] 목록 줄 `.is-assigned` 색 · 툴팁에 항목 이름 · B05 · B06 둘 다(한 코드)
- [x] 캐시 = 지금 초안 키(`aislo:draft:structures` · `pipes`) 안의 기록 칸 — 새 키 없음 · [저장] 흐름 변경 없음
- [x] 700줄: `B05_Profile_UI_Structures_Panel.ts` 707 · `B05_Profile_UI_Panel.ts` 714 — 이번 손대는 파일은 기능별로 나눔
- [x] 시험 `resources/tester/test_b05_structures_form_summary.spec`(폼 숨김 · 보존 · 지정 · 해제 · 색) + 자체 ORCA
- 검증완료(9-29 sub3): 시험 `test_b05_structures_form_summary.py` 11(폼 숨김 · 옵션 보존 · 줄 · 관 merge · 목록 색 · 저장 기록) · 자체 ORCA(랩탑_보조 · 5178 · 밝음 · 어두움 · 대비 5.75~7.43) — B05 구조물 지정 · 해제 · 새로고침 뒤 초안 유지 · 관(B05 · B06) 지정 · 해제 · B06 구조물 지정 · 초안 `aislo:draft:structures|pipes` 안 `summary_item` · 미지정은 칸을 안 실음
- 화면 쪽 이음(sub3): `B05_Profile_UI_Structures_Summary_Picker.ts` = **가짜 모달** — 21-5 가 오면 이 파일을 지우고 `Panel.ts` 의 import 한 줄만 `@ui/ui_template_item_picker` 로 바꿈 · 맞춰 둔 모양 = `openItemPicker({current: SummaryItem|null}) → Promise<{item: SummaryItem} | {clear: true} | null>`(null = 닫음) · 목록은 `GET /api/m02/items?all=1` 을 읽고 404 면 21-1 모양의 가짜 세 줄
- 서버 의존(sub5 · sub7): `visible`(21-8)은 서버가 채우면 그때부터 폼이 숨김(없으면 모두 보임 — 시험은 fake 로 확인) · `summary_item` 은 **미지정이면 칸을 안 실음**(서버 모델이 모르는 칸을 거절하는 동안에도 저장 · 계산이 안 깨짐) — 지정한 채 저장 · 재계산하려면 21-3 스키마(구조물 · 관 지점)와 응답에 칸이 있어야 함(관은 응답에 칸이 없으면 화면이 같은 측점에서 이어받음)
- 흠 고침: [수정] 옵션 덮어쓰기 — 폼이 그린 칸만 갈아 끼우고 안 그린 칸(상세 · 숨긴 칸)은 옛 값 보존(`mergeStructureOptions`) · B05 에서 관 옵션 · 집계 항목만 바꿔도 세션 초안에 담음(B06 이 같은 값을 봄)
### 21-5. 항목 고르기 모달 · 공용 나무 보기 (sub1 · sonnet high) — 키는 숨기고 이름으로(21-0)
- [x] `ui_template/ui_template_tree.ts` — M01 `renderTree` 를 공용으로 올림(M01 은 그대로 부름) · 접기 · 깊이 들임 · 잎 고름
- [x] `ui_template/ui_template_item_picker.ts` — `openModal`(넓은 `dialogClass`) 왼쪽 나무(마스터 · 회사 · 개인 → 종류 → 분류1 → 항목 · 검색 칸) · 오른쪽 = 고른 항목의 폴더 모양(도면 · 면적산출 · 재료산출 · 자재조합 · 일위대가 이름 · 키는 툴팁) · 아래 단추 [적용] · [해제] · [개인용으로 복사](회사 · 마스터 항목일 때) · [관리 화면에서 고치기](개인 항목 · 21-6 으로 이동) · 밝음 · 어두움
- [x] `GET /api/m02/items?all=1` 한 번 읽고 나무 만듦 · 고른 항목 = 21-1 `summary_item` 으로 돌려줌
- [x] 시험(폼 열기 · 나무 펼침 · 검색 · 적용 · 해제 · 복사 호출) + 자체 ORCA
- 검증완료(9-29 · 사용자 주소 5174 · 밝음 · 어두움): 시험 `resources/tester/ui/item-picker-data.test.ts` 통과 · ORCA 수치 — 나무 펼침 · 접기 · 찾기(4 · 없음) · 고르면 오른쪽 폴더 5줄(키는 툴팁) · 적용 = summary_item · 해제 · 복사 호출 뒤 개인 줄 고름 · 관리 화면 이동 · 닫기 · Esc · 바깥 = 취소 · 항목 400 · 긴 이름 · 빈 목록 · 서버 오류 글 그대로 · M01 왼쪽 목록 이상 없음 · 서버 `GET /api/m02/items` · 복사 `POST /api/m02/layers/personal/items/copy` 는 아직 없어 404 일 때 가짜 응답(`ui_template_item_picker_fake.ts` — 실서버 오면 지움) · 검증 대기
### 21-6. 구조물 관리 화면 · 대시보드 (sub2 · sonnet high)
- [x] M02 페이지에 층 인자(`#/m02-master-template?layer=personal|company`) — `UI_Side.ts:90` 고정 풂 · `UI_Main` 구조물 패널 · 오른쪽 조합 패널 · [돌아가기] 를 층 무관하게 · 제목 「구조물 관리(개인)」 · 「구조물 관리(회사)」 · 「마스터 템플릿」
- [x] 편집 권한 = 시스템 층 SYSTEM_ADMIN · 회사 층 회사 관리자(role ADMIN 또는 is_master) · 개인 층 본인 · 읽기만이면 단추 숨김 + 「회사용은 복사해서 씀」 안내와 [개인용으로 복사]
- [x] 대시보드 카드 「구조물 관리」 — USER 개인용 단추 하나 · ADMIN 회사용 · 개인용 둘 · SYSTEM_ADMIN 21-0 답대로 · 라벨 `ui_template_locale_*`
- [x] 라우트 보호: `config_frontend.ts` `PROTECTED_ROUTES` · 서버는 21-2 권한
- [x] 시험 + 자체 ORCA(세 역할 계정 · 회사용 읽기만 · 복사 뒤 개인용 편집)
- 검증완료(9-29) — `test_m02_layer_screen.py` 5 + `test_m02_structure_panel.py` 19 통과 · 5177 ORCA: 시스템 층 그대로 · 개인 층(제목 · 도면 양식 없음 · 구조물집계표 · 면적산출 조합 패널 · 돌아가기) · 회사 층 읽기만(저장 숨김 · 안내 막대 · 열 고른 뒤 [개인용으로 복사] 요청 `{from_layer:"company", from_owner:"1", key:"SS000001"}`) · 회사 없음 안내 → 대시보드 · 카드 USER 개인용 · ADMIN · SYSTEM_ADMIN 회사용 + 개인용 · 회사용 단추 → `?layer=company`. 층 라우트(`/api/m02/layers/{layer}/structures…` · `items/copy`)는 sub4 서버 도착 전이라 화면 쪽에서 옛 길로 바꿔 확인 — 실서버 도착 뒤 한 번 더(검증 대기).
### 21-8. 구조물 옵션 보이기 (sub7 · sonnet high)
- [x] `resources/master_template/구조물옵션표시.json` = `{type_id: {option_key: true|false}}`(없는 종류 · 키 = 보임) · `GET /api/projects/structure-types` 응답 옵션마다 `visible` 칸(서버가 채움)
- [x] M02 시스템 층 좌측 「구조물 옵션 보이기」 줄(구조물 집계 양식 아래 별도) → 메인 = 종류 목록 · 종류 고르면 옵션 체크 목록(라벨 · 키 작은 글 · B06 전용 표시) · [저장] · [모두 보임]
- [x] 라우트 `GET/PUT /api/m02/structure-options`(SYSTEM_ADMIN 쓰기)
- [x] 시험(파일 없음 = 모두 true · 저장 → 응답 visible 반영) + 자체 ORCA
- 검증완료(sub7 21-8): 표 `구조물옵션표시.json`(숨김만 저장 · 파일 없음 · `{}` = 모두 보임) · `GET /api/projects/structure-types` 옵션마다 `visible` · `GET/PUT /api/m02/structure-options`({판, 표시, 종류} · 낡은 판 409 · 없는 종류 · 키 422) · M02 좌측 「구조물 옵션 보이기」 줄(구조물 집계 양식 아래) → 메인 종류(군별) → 옵션 체크(키 작은 글 · B06 전용 · 필수 표시) · [저장] · [모두 보임] · 시험 test_m02_structure_options · ORCA 메인 폴더 탭 저장 → B05 응답 visible 반영 · 낡은 판 복구 · 고름 한 줄 · 페이지 스크롤 0 · 만든 것 되돌림(`{}`)
### 21-9. 통합(9-29 12:30 · 여섯 창 1차 끝 뒤)
- 브레인 결정: 숨긴(visible=false) 옵션은 서버 · 화면 모두 「필수 아님」 — 숨김이 저장을 막지 않음(sub7) · 일위대가 갈라 내기는 SYSTEM_ADMIN 만(sub4 ①) · 회사 · 개인 층 첫 진입 뒤 같은 이름 새로 만들기 409(sub4 ②)
- 남은 결정(사용자 · 수량 화면 때): 지정 바꿈이 B06 이후 단계를 「다시 계산 필요」로 되돌리지 않음 · 같은 묶음 열(관 매설 · 커플링)은 항목 하나로 함께 채움(sub5 ②③)
- [x] sub2: origin/dev 되받기 충돌(M02_MasterTemplete_UI_Style.css · ui_template_locale_m2.ts) 풂 → push · 실서버 층 라우트로 21-6 재확인
- 검증완료(sub2) — 충돌 다섯(M02 Side · Style · locale · B05 List · Panel_Types)을 양쪽 살려 풂(옵션 보이기 · 도면 양식은 시스템 층만) · 타입검사 · 시험 30 통과(layer_screen · structure_panel · structure_options) · 9aa07fda push · 실서버 5177: 세 층 화면(시스템 · 개인 · 회사) 열림 · 세 역할(SYSTEM_ADMIN 실계정 · USER 세션 흉내로 회사용 읽기만) · 회사 열 rv 복사 → 개인 SS000001 · SD01010101 생김 · 개인 층 면적산출 조합 패널 · 돌아가기 · 옛 길 대체는 ORCA 시험에만 있었고 코드는 처음부터 층 길(`/layers/{층}/…`) · 시험으로 만든 회사 · 개인 층 파일 열두 개는 지워 원래대로
- [x] sub3: origin/dev 되받기 충돌(B05_Profile_UI_Structures_List.ts · _Panel_Types.ts) 풂 → push · 임시 모달 파일 지우고 sub1 `openItemPicker`(apply · clear · cancel) 로 이음 · 관 summary_item 을 시설 보관소(FacilityAttributes · attach) 가 되보내게(sub5 ①)
- 검증완료(sub3 9-29): 충돌 둘 양쪽 살려 풂(dev 측점 import + 집계 항목 import · Panel_Types) · 임시 모달 파일 · 전용 CSS 삭제 → `@ui/ui_template_item_picker`(apply · clear · cancel · canCopy 는 true 고정 — 개인 층 쓰기 불가 사용자의 복사는 서버 까닭을 모달이 보임) · 시험 23 통과 · 타입검사 통과 · 사본 격 ORCA(랩탑_보조 · 파일 백업 뒤 복원): 옹벽 · 배수관 3 지정 → [저장] PUT 관 · 구조물 모두 summary_item 실림 · 저장 뒤 pipe_points.json · structures.json 에 기록 · 스냅샷 폴더 `templates/items/system_none_SS000002·3` 생김 · 초안 지우고 새로고침 → B05 · B06 목록 색 · 툴팁 유지. ⚠ 실서버 `?all=1` 은 `[{layer, owner, items}]` 묶음인데 sub1 모달이 아직 납작한 줄로만 읽어 잎 이름이 빈 나무로 나옴(sub1 몫) — 이 검증은 화면에서 응답을 납작하게 펴는 임시 덮개로 진행
- [x] sub1: 가짜 파일 지우고 실서버 `?all=1` 모양 `[{layer, owner, items}]` · `names` · 복사 응답 `{key}` 바로 고름 — 검증완료(9-29 · 5174 ORCA 실서버: 세 층 나무 마스터 51 · 회사 0 · 개인 0 · 폴더 줄 이름(키 툴팁) · 복사 → 개인 항목 바로 고름 → 적용 summary_item{personal · 1/3 · SS000001} · 다시 열면 그 항목 고른 채 · 시험 만든 개인 폴더는 원래대로 · 시험 `resources/tester/ui/item-picker-data.test.ts` · 되받기 충돌 sub2 · sub3 · sub4 · sub7 양쪽 살려 풂 10cc5dd3 · 5cb65dff · 검증 대기)
- [x] sub4: items 줄에 `names` 다섯 이름 · 복사 응답 `{key}` 확인 — 검증완료(test_m02_layers_store · 되받기 충돌 다섯 파일 양쪽 살려 풂)
- [x] sub7: 되받기 · push · 숨긴 옵션 = 필수 아님(서버 검증 · 화면 표시) — 검증완료(sub_laptop_2 · 3 를 내 가지에 merge 로 풂 · 서버 `_validate_options` 가 숨긴 옵션 건너뜀 · 화면 폼은 visible 만 그림 · test_m02_structure_options 관련 71개 통과 · ORCA 메인 폴더 탭 확인)
- [ ] sub6: 되받기 · push(가지에만 있는 커밋 11)
### 21-7. 검증 (sub8 · sonnet medium → 브레인 최종)
- [x] 사본 프로젝트에서 사용자 길: 개인용에 항목 만들기 → B05 구조물에 지정(색) → B06 에서도 같은 색 → [저장] → 스냅샷 폴더 · manifest → 마스터 항목 값 바꿔도 프로젝트 채움 그대로 → 지정 바꿈 → 옛 폴더 삭제 → 해제 → 삭제 → 회사용 복사 → 개인용 편집
- [x] 예외: 항목 없이 저장 · 같은 항목 두 구조물 · 저장 안 하고 페이지 옮김(캐시 유지) · 권한 없는 층 쓰기 403 · 옛 프로젝트(칸 없음) 열기
- 검증완료(21-7 1차 · sub8 · 사본 sub8_검증 · 확인 약 45): 스냅샷 폴더 · manifest · 마스터 바꿔도 채움 같음 · 지정 바꿈 · 해제 폴더 삭제 · 같은 항목 두 구조물 · 숨김이 저장 안 막음 · 403 · 흠 7 → 21-10
- [x] 재검(흠 고친 뒤 · 세 창 · sub8 층 담당 · sub7 B05/B06 사본 sub7_검증 · sub6 모달 · 테마 · 예외 사본 sub6_검증)
- [x] 브레인 최종(진짜 마우스 · 사진 · 아티팩트)
- 검증완료(21-7 재검 · 트리 99b83d9d): sub7 24건 흠 0(지정 · 저장 · 스냅샷 · 흠 2 · 3) · sub6 약 45곳 흠 1(B05 종단 구조물 표지 글 대비 — 21장 밖 · 옛 화면 · 사용자 결정 대기) · sub8 약 40건 흠 1(옵션 숨김이 관 계열 하위 폼에 안 먹음 → 21-10)
### 21-10. 흠 고침(sub8 1차 검증 · 9-29)
- [x] 흠 1 빈 개인 · 회사 층에서 첫 항목 만들 길 없음(열 0 이라 단추 모두 꺼짐) → 열 0 에서도 [열 더하기](종류 · 분류 · 단위 입력)가 켜짐(sub2)
- [x] 흠 4 회사용 읽기만 화면에 [분류 더하기] · [열 지우기] · 카드 [수정] 이 보임 → 읽기만이면 편집 단추 모두 숨김(sub2)
- 검증완료(sub2 · 22f3df94) — 시험 26 통과(layer_screen 7 + structure_panel 19) · 실서버 5177: 열 0 개인 · 회사 층 [열 더하기](on) → 머리 글 입력 → [저장] → 번호 SD01010101 · SS000001 생김 · 다시 열어도 유지 · 읽기만(회사 층 USER 세션): 단추 줄 · 안내 글 없음 · 카드 수정 · 더하기 · 지우기 단추 0 · 머리 더블클릭 · 칸 입력 · 글자 입력 뒤 입력칸 0 · [개인용으로 복사] 켜짐 · 시험으로 만든 개인 · 회사 층 파일 열 개 지워 처음 상태(파일 셋)로
- [x] 흠 2 [고르기] 열었다 닫고 다시 [적용] 하면 초안(aislo:draft:structures)에 안 들어가 저장에 안 실림(sub3)
- [x] 흠 3 관 지정을 저장 전 B05→B06→B05 오가면 화면 · 저장이 옛 지정(초안 pipes 엔 새 값)(sub3)
- 검증완료(sub3 21-10 흠 2·3 · 사본 sub3_검증 2fb68626 · 5f43ef85): 흠 2 원인 = 필수 옵션이 비면 폼 검증이 조용히 멈춰 지정이 초안에 안 감(폼 줄엔 새 값이 보임) → 고치는 구조물은 집계 항목만 기록에 바로 반영(필수 옵션 전부 비운 뒤 지정 SS000001 · 해제 모두 초안 반영) · 흠 3 원인 = B05 진입이 세션 초안 관을 안 읽고 정본만 불러 옛값으로 덮음 → 초안이 있으면 그 관 목록으로 세움(배수관 2 지정 → B06 → B05 · 해제 → B06 → B05 모두 유지 · 새로고침도 유지) · [저장] 관 1 · 구조물 5 지정이 pipe_points.json · structures.json 에 기록 · 초안 지우고 다시 열면 목록 색 6줄 유지 · 시험 13 + 관련 25 통과 · 타입검사 통과
- [x] 흠 5 다크 테마 ui-btn--ghost 글자 대비 1.06(헤더 메뉴 · 모달 단추 안 보임 · 공용) · 흠 6 밝은 테마 ui-tree__caret · ui-tree__count 대비 3.08 → 4.5 이상(sub1) · 흠 7 모달 잎 툴팁 · 관리 단추 · 자리표(아래 줄) — 검증완료(9-30 5174 · 흠 5 색 변경 없음: 다크 1.06 은 ORCA 가 색 전환을 멈춘 측정값 — 다시 불러온 뒤 ghost 헤더 6.85 · 모달 6.85 · 카드 6.85 · 밝음 16.65 · 전환 끄고 토글하면 6.85 · 흠 6 밝음 나무 6.3 · M01 줄 수 5.41 · 다크 7.35 · 7.04)
- [x] 흠 7 모달: 잎 툴팁 = 층 이름 + 키 · [관리 화면에서 고치기] 는 개인 항목만 · 이름에 「새 분류N」 자리표는 빼고 보임(sub1) — 검증완료(층별 툴팁 「마스터 · SS000001」 · 관리 단추 개인만 켜짐 · 자리표 이름 「분류 없음」 · 커밋 5b04f453 · 시험 자료 1파일 통과 · 검증 대기)
- [x] 흠 7 서버: 같은 이름 자재 조합 오류 글에서 파일명 · 키를 빼고 쉬운 말 한 줄 · 긴 이름 자름(sub4) — 검증완료(9-29 · 자재 조합 만들기 · 고치기가 이름 겹침 · 60자 넘음을 틀 검사 앞에서 「이름」 한 줄로 막음 · 파일명 · 키 없음 · 긴 이름 30자에서 …)
차례 — 21-2 · 21-3 · 21-8 서버가 먼저(21-1 약속 고정 뒤 화면 창은 가짜 응답으로 동시 진행) → 21-4 · 21-5 · 21-6 → 21-7.
- [x] 흠 8 옵션 숨김(visible=false)이 관 계열 하위 폼(배수관 · BOX · 세월교 · 기슭막이 — `B05_Profile_UI_Drainage_Facility*`)에 안 먹음 → 하위 폼도 visible 을 거름 · 값은 보존(sub3 · 자기 검증까지)
- 검증완료(sub3 21-10 흠 8 · 사본 sub3_검증 · eb387d5f): 시설 폼 칸에 옵션 키 표식 · 끈 키 칸 가림 · 숨긴 칸은 폼이 받은 옛 값을 저장에 그대로(제안값 채우기도 안 바꿈) · 이 폼엔 필수 검사 없음 · 시험 16 + 관련 12 통과 · 타입검사 통과 · ORCA(마스터 표시 파일에 네 종류 옵션 하나씩 끔): 배수관 관경 · 세월교 수량 · BOX 높이 · 기슭막이 높이(유입 · 유출)가 B05 · B06 폼에서 사라지고(유입 · 유출 각 줄 · 본체 규격은 키 둘 다 꺼질 때만) 관종 · 날개벽 · 설치 측을 고쳐도 숨긴 값 1200 · 2 · 2.5 · 3 / 3.5 그대로 · 값 없던 칸은 안 생김 · 저장 PUT 200 두 번 · 파일에 값 유지 · B05→B06→B05 유지 · 밝음 · 어두움 숨김 4~1곳 display none · 가로 넘침 없음 · [모두 보임]({}) 뒤 네 칸이 옛 값으로 되돌아옴 · 마스터 표시 파일 {} 로 되돌림 · 탭 닫음
- 검증완료(21장 코더 몫 전부 · 9-29 14:26): 흠 8 sub3 eb387d5f(관 계열 하위 폼 숨김 · 값 보존 · 자기 검증) · 전역 12곳 트리 31a1c92e · CAD · 스프레드시트 소스 변경 없음(빌드 불필요) · 남은 것: 브레인 실제 검증 · 아티팩트(사용자 요청 때) · 사용자 결정(B05 종단 구조물 표지 글 대비 · 지정 바꿈 뒤 「다시 계산 필요」 · 같은 묶음 열 함께 채움)
- 검증완료(21 · 브레인 · 5173 · 사본 sub7_검증 · 진짜 마우스 · 사진 a3~d2): 일곱 흐름 통과 · 아쉬운 점 셋(항목이 있으면 새 종류 더할 길 없음 · 마지막 열 못 지움 · 대시보드 카드가 아래쪽) — 사용자 결정 대기 · 검증 흔적 정리(지정 해제 · 복사본 0 · 개인 층 시험 파일 tmp/브레인검증_개인층_0929)
---
## 22. 계획노선 편집 창 — 반폭 선 · 고르기 · 고정 (담당 sub4 · sub5 · sub6)
사용자 지시(9-29 저녁) — 측점을 고르면 나오는 파란 선 = 우측 패널 「횡단 반폭」 기준 양쪽 · 측점 라벨로도 측점 고름 · 호를 눌러도 그 곡선이 골라짐 · 고정된 선 · 호는 색으로 표시 · 시점 · 종점도 고정. 다음 대화 = 초기노선 계산(토공 최소 · 기울기 순한 · 비중).
브레인 판정: 파란 선은 평면 거리 ±반폭(횡단 미리보기의 원지반 선 범위와 같음) · 곧은 선은 양 끝이 모두 고정일 때 · 호는 교각점과 앞뒤 점이 모두 고정일 때 「고정 색」 · 시점 · 종점은 기본 고정(지금 동작) · 풀면 끌어 옮김 · 고정 정보는 초기노선 계산에 넘길 수 있게 상태로 둠(서버 반영은 다음 대화).
- [x] 22-1 파란 반폭 선 길이 = 우측 패널 「횡단 반폭」(cross_half_width_m · 지금 적용값) 양쪽 — 지금은 설계 단면 끝(designHalfWidths)(sub4 · `RouteEdit_Cross.ts` · `RouteEdit_Render.ts` 의 `drawCrossWidth` 만)
- 검증완료(22-1 · sub4 · 5179 · 랩탑_보조 열어 보기만): 적용 안 함 → 파란 선 40.0m(좌 20.0 · 우 20.0) = 원지반 선 40.0m · B06 반폭 15 적용 → 30.0m(15.0 · 15.0) = 원지반 선 30.0m · 확대 · 축소(4.6 · 6.1 · 8.1 px/m) · 노드 끌기 · 되돌리기 · 창 닫고 다시 열기 모두 30.0m · 어두움에서 하늘색 선 보임 · 시험 test_b05_routeedit_cross_width.py 5건 · 값 = B06 「횡단 반폭」[적용] 세션값 · 없으면 서버 기본 20m(B06 입력칸 기본 12 와 다름)
- 22-1 브레인 판정: 기본 = 계산 반폭 20m(파란 선 40m) · B06 「횡단 반폭」 입력칸 기본 12 는 횡단 카드 **표시** 폭(8-19 사용자 지시)이라 그대로 · B06 에서 [적용]한 값이 있으면 그 값을 따름
- [x] 22-2 측점 라벨을 눌러도 그 측점이 골라짐(지금은 작은 수직 눈금만)(sub5 · `RouteEdit_Input.ts` · 라벨 자리 계산) — 검증완료(sub5 · 5180 · 사본 없이 열어 보기만 · 진짜 마우스: 라벨 셋 10+0·11+0·13+0 각각 눈금과 같은 횡단 측점 · 라벨 가로 +12px 안 잡힘/+21px 밖 안 잡힘 · 지도 30° 회전에서도 넷 통과 · 어두움 통과 · 솎여 안 보이는 눈금은 이제 안 잡힘(호 가로채기 막음) · 시험 test_b05_routeedit_pick.py)
- [x] 22-3 호(곡선)를 눌러도 그 곡선이 골라짐 — 교각점을 누른 것과 같은 동작(sub5 · `RouteEdit_Input.ts` · `RouteEdit_Curve.ts` 점-호 거리) — 검증완료(sub5 · 5180 · 호 셋 노드 2·5·9 호 위 누름 = 교각점 누름과 같은 곡선 번호 · 같은 패널(R·L 칸 값 동일) · 확대 5단계 · 30° 회전 · 어두움 · 창 닫고 다시 열기 · 노드 끌고 되돌리기 뒤에도 같음 · 호 위에서 끌어도 노선 안 움직이고 되돌리기 안 켜짐 · 호 밖 12px 빈 곳은 -1 · 눈금이 호 위면 눈금 우선(횡단 열림) · B04 지도 라벨 22개 정상)
- [x] 22-4 고정 표시 — 곧은 선은 양 끝 고정 · 호는 교각점과 앞뒤 점 고정일 때 「고정 색」(새 색 토큰 · 밝음 · 어두움)(sub6 · `RouteEdit_Render.ts` 노선 · 호 그리기)
- [x] 22-5 시점 · 종점 고정 — 기본 고정 · 시점 · 종점을 고르면 고정 단추 · 풀면 끌어 옮김 · 고정이면 끌기 막힘 · 되돌리기 · 다시 열기에 유지(sub6 · `RouteEdit.ts`(697줄 · 먼저 나눔) · `RouteEdit_Label.ts`)
- 검증완료(sub6 · sub6_검증 · 교각점 3·4번째 고정 → 그 사이 선만 고정 색 · 앞뒤 선 주황 · 세 점 고정 → 가운데 호 고정 색 · 시점 고정 끌기 막힘(1078.0m 그대로 · 커서 not-allowed) · 풀고 끌기 1092.2m · 되돌리기 1078.0m · 다시 고정 · [취소] 뒤 다시 열어 시점 풀림 · 교각점 고정 유지 · 종점 고정 단추 · 고정 점 지우기 막힘 · 확대 3.06 · 축소 1.00 px/m 판정 유지 · 고정 색 #db2777 대비 4.29(밝음) · #f472b6 6.41(어두움) · 시점 26.13m 옮겨 [확인] 재계산 성공(1053.6m) · 다시 열어 고정 좌표 되짚음 · 고정 한 벌 읽기 = `_RouteEdit_Lock.ts` readRouteLocks · 시험 test_b05_routeedit_lock 5건) · 검증 대기
## 23. 계획노선 추천 — 기본값(예상노선 추적)과 같은 층 · 별도 창 · 갈래가 실제로 다르게 (담당 sub3 서버 · sub7 화면)
사용자 확정(9-29 저녁) — 전처리가 만드는 기본 계획노선 = 예상노선 추적 · 토공 최소 · 기울기 순한 · 비중 계산은 그와 같은 층의 「추천」 · 알약에 기본값(예상노선 추적) 항목 · [초기화] = 예상노선 추적으로 돌아감 · 「연 상태로」는 뜻이 애매 · 추천 기능이 차지하는 자리가 넓음 → 「1m 등고선」 왼쪽에 구분선 + 새 단추 → 별도 모달.
브레인 판정: [초기화] = 전처리 때 만든 초기값 노선을 다시 놓음(재계산 없음 · 데이터 3층 규칙) · 「연 상태로」 단추는 뺌([취소] · 되돌리기가 같은 일) · 새 단추 이름 「노선 추천」.
브레인 실측(9-29 19:40 · 랩탑_보조 · 랩탑_메인 같은 결과): 네 갈래 모두 노드 301 · 연장 1164.65~1165.42m · 최대 기울기 18.1~19.5% · 절토 1,986~2,021 · relaxed=true · 상한 29.06% · 위반 4 — 선은 조금씩 다르나 눈으로는 같은 노선 · 추적(follow)도 전처리 초기값(1078m)과 다름 · 공통 제약을 hard 로 바꾼 뒤(258a3512) 갈래가 모임(그 전 dmain 실측: 추적 1078 · 토공 1141.6 · 기울기 1140.8 · 비중 1118.8m).
- [x] 23-1 서버: 갈래가 같은 노선으로 모이는 원인을 찾아 고침 — 제약 풂(relaxed) 뒤 목적 함수가 묻히는지 · 탐색 복도 · 무게 크기 · 노드 301 조밀 샘플링 확인 · 갈래마다 목적이 드러나게(토공 최소 = 절성토 합 최소 · 기울기 순한 = 최대 · 평균 기울기 최소 · 비중 = 가중합) · 추적(follow) = 전처리 초기값과 같은 노선 · 갈래별 비교값 표를 PLAN 에 · 시험(sub3 · `B05_Profile_Engine_RouteInitial*.py` · `Router_Replan.py` 의 initial_route 만)
- 원인(sub3): 지형이 가파름(노선 옆경사 평균 67 % · 복도 안 4 m 링크의 14 %만 상한 14 % 안) → 반지름 규칙까지 지키는 길이 없어 풂(상한 29.1 %) → 풂 탐색 벌점(1 m 당 500 × 넘은 비율)이 목표(1 m 당 평균 1)의 수십~수백 배라 네 갈래 모두 「넘은 기울기 합 최소」 한 길 · 벌점만 낮춰도 탐색 목표(4 m 링크 기울기 · 옆경사)와 비교값(측점 20 m 기울기 · 절성토)이 어긋나 순서가 안 맞음 · follow 는 예상노선 이격 최소 탐색이라 초기값과 다름 · 복도 · 격자는 원인 아님(풂 구역만 좁혀도 그대로 모임)
- 고침: 후보 묶음(목표 비중 셋 × 벌점 50 · 5 + 센 벌점 기준 길 · 제약을 지킬 수 있으면 비중마다 상한 단계)을 한 번 짜고 갈래는 **비교값으로** 고름 — 토공 최소 = 절성토 합 최소 · 기울기 순한 = 최대(같으면 평균) 최소 · 비중 = 이격 · 절성토 · 기울기(최대+평균)를 후보 범위로 0~1 맞춘 가중합 · 기준 길보다 못 지킨 곳 많은 후보는 뺌 · follow = 전처리 초기값 규칙(`build_planned_polyline(예상노선)`) 그대로 · 넘은 곳은 「예상노선 추적」 사유로 목록 · 응답 모양 그대로
- 비교값(랩탑_보조 = 랩탑_메인 · 같은 입력 · 기준 14 % · R12):
| 갈래 | 연장 m | 최대 % | 평균 % | 절토 ㎥ | 성토 ㎥ | 절성토 합 | 이격 평균/최대 m | 못 지킨 곳 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 예상노선 추적 | 1078.01 | 32.4 | 13.72 | 3,479 | 4,056 | 7,535 | 1.1 / 3.5 | 12 |
| 토공 최소 | 1156.68 | 20.09 | 6.68 | 1,949 | 1,945 | **3,893** | 18.1 / 39.5 | 4 |
| 기울기 순한 | 1153.20 | **16.83** | 7.23 | 2,081 | 1,959 | 4,039 | 19.0 / 43.8 | 2 |
| 비중 50/25/25 | 1153.26 | 17.96 | 6.92 | 2,123 | 2,001 | 4,124 | **16.1** / 35.4 | 3 |
노선 차이(두 선 사이 최대 거리): 토공–기울기 6.1 m · 토공–비중 9.6 m · 기울기–비중 13.5 m · 추적–나머지 41~47 m. 비중은 최대 기울기가 둘 사이(16.8 < 18.0 < 20.1) · 이격이 가장 가까움 · 절성토 합은 둘보다 큼(예상 50 % 가 이격을 먼저 당김)
- 검증완료(sub3 77d3ffee · test_route_initial 20 · test_b05_routeedit_initial_roundtrip 7 · API 8005 두 프로젝트 네 갈래 200 · 첫 요청 약 1.3~1.6초 · 같은 입력 다음부터 0.25~0.55초 · 추적 = planned_route_initial.csv 거리 < 0.01 m · 추적 노드+반지름으로 [확인] 재구성 = 초기값 그대로 · 비중 합 90 → 400 · 없는 갈래 → 422 · 없는 프로젝트 500 → 404 · 기울기 30 % 겹침 → 풂 없음 · 토공 1026.4m/절성토 2,989 · 기울기 22.9 % · 비중 이격 4.4m · 갈래 차이 39~52 m · ORCA 5178 랩탑_보조 편집 창 토공 최소 1,156.7m/20.1% · 기울기 순한 1,153.2m/16.8% · 비중 1,153.3m/18.0% · [취소] · 노선 파일 안 씀 · 검증 대기) · 남김: `_project_paths` 가 없는 프로젝트에 500 인 흠은 replan · plan · reset 에도 있음(이번엔 initial 만)
- [x] 23-2 화면: 「1m 등고선」 왼쪽에 구분선 + [노선 추천] 단추 → 모달(알약 넷: 예상노선 추적(기본) · 토공 최소 · 기울기 순한 · 비중 계산 · 비중 슬라이더 · 제약 칸 · 비교값 · 못 지킨 구간 · [적용] · [닫기]) · 편집 창 도구 막대에서 추천 묶음 빼냄 · [초기화] = 초기값(예상노선 추적) 노선 · 「연 상태로」 뺌(sub7 · `RouteEdit_Initial*.ts` · `RouteEdit_Chrome.ts` · 새 모달 파일 · 새 CSS 파일)
- 검증완료(sub7 23-2 · ORCA 8009·5182 · 랩탑_보조 읽기만): 도구 막대 = [노선 추천] 하나(구분선 뒤 · 1m 등고선 앞) · 추천 묶음 · 「연 상태로」 없음 · 알약 넷 각각 서버 미리 보기(연장 1,164.7 · 1,165.4 · 1,165.4 · 1,164.7m · 최대 기울기 19.5 · 18.1 · 18.1 · 19.5% · 절토 1,986 · 1,999 · 2,021 · 2,000㎥ · 지도 선 63점) · 비중 50/25/25 → 70/15/15 → 33/7/60 합 100 · 바꾸면 [적용] 잠김 · [다시 셈] · 제약 칸 기울기 10 → 상한 10.0% · 풂 29.1% · [닫기] 뒤 노드 28 · 해시 그대로 · [적용] 토공 최소 → 노드 63 · 1165.4m · 「현재 추천: 토공 최소」 · [초기화] → 노드 28 · 1078.0m · 좌표 해시 처음과 같음(재계산 POST 없음 · GET plan initial_route) · 되돌리기 63 · 다시하기 28 · 모달 안 Ctrl+Z 는 뒤 노선 안 건드림 · 서버 오류 시 토스트 · [적용] 잠김 · 취소 뒤 다시 열면 현재 추천 예상노선 추적 · 밝음 · 어두움 · 폭 597px 한 열 · 시험 25 통과 · 타입검사 통과 · 남은 것: 되돌리기는 「현재 추천」 글을 함께 되돌리지 않음(RouteEdit.ts 에 알림 이음 필요) · 지도 미리 보기는 모달 안 지도(편집 창 캔버스 위 겹침은 RouteEdit_Render 몫)
- 검증완료(sub7 23-2 되돌리기 짝 · ORCA 5182): 걸음(사진)마다 「현재 추천」을 실어 되돌리기 · 다시하기가 함께 되살림 · 토공 적용 63점 「토공 최소」 → 되돌리기 28점 「예상노선 추적」 → 다시하기 63점 「토공 최소」 → [초기화] 28점 → 되돌리기 63점 「토공 최소」 → 되돌리기 28점 → 다시하기 63 · 28 짝 유지 · 취소 뒤 재열기 예상노선 추적 · 시험 19 통과 · 타입검사 통과
## 24. B05 · B06 한 페이지 두 보기 — 좌측 패널 · 종단도(유토곡선 · 배수유역도) · 저장 한 벌
사용자 확정(9-29 저녁) — 방향 「가」: B05 · B06 을 한 페이지로 · 가운데만 「종단 보기(3D + 종단도) ↔ 횡단 보기(종단도 + 횡단 카드)」 · 좌측 패널 · 아래 단추 · 저장 · 캐시 · **종단도(유토곡선 · 배수유역도 포함)** 한 벌 · 유토곡선 · 배수유역도는 종단도에 끼우는 떼었다 붙이는 판(나중에 떼기 쉽게).
조사 결론(9-29 · 코드 읽기): 공용은 구조물 폼 · 목록 · 페이지 틀 · 종단 그리기 부품뿐 · 좌측 패널 틀 · 아래 단추 · 저장 흐름 · 종단도 조립 · 확대 · 선택 연동은 두 벌 · 종단 계획고 초안은 **같은 저장 키를 두 가게가 따로** 고침 · 관 목록 주인이 둘(B05 배수유역도 · B06 자체 목록) · B06 은 계획고 고칠 때 최소 흙덮기 · 기울기 막기가 없음 · 오갈 때마다 화면 전체를 지우고 새로 만듦 · 3D 화면은 닫는 길이 없어 오갈 때마다 옛 화면이 뒤에서 계속 돎 · B06 횡단 카드에서 구조물을 누르면 폼이 못 찾음(찾는 거리 0.05 vs 0.51 m) → 「집계 항목」 줄이 숨음 · 700줄 넘은 파일 다섯(Profile_Panel 827 · Viewer 771 · B05 Page 766 · Cross_View 756 · B05 Panel 714).
### 24-0. 사용자 확정(9-29 밤)
- 종단도 + 유토곡선 + 표 + 배수유역도 = 두 보기에서 **같은 자리 · 같은 기능**(코드 혼선 줄임).
- 브레인 판정: 같은 자리 = 가운데 아래쪽(지금 B05 자리 · 크기 손잡이 · 접기) · 위쪽 칸만 보기마다 다름(종단 보기 3D · 횡단 보기 횡단 카드 · 카드 칸은 그 안에서 스크롤) · 배수유역도 = 종단도 오른쪽 판 · 유토곡선 · 표 = 종단도 위 겹침 판(지금 B05 그대로).
- 진행 단계 「종단설계」 「횡단설계」 두 칸 그대로(누르면 보기만 바뀜).
- 관 · 옹벽 · 세월교 고치는 칸 = 좌측 폼 하나로(3단계).
- 합치는 동안 B05 · B06 새 기능 멈춤(계획노선 편집 창 일은 계속).
- 아래 단추 = [초기화] [저장] [확정] [보기 전환] 한 줄([임시저장] → [저장]).
### 24-1. 약속(모든 창 공통 · 바꾸려면 ask)
- 공용 자리 = `A00_Common/design/` 새 폴더 · 보기 이름 `DesignView = "profile" | "cross"`.
- 상태 한 곳 `design_store.ts` — `useDesignStore(projectId, routeId)` → `get(key)` · `set(key, value)` · `subscribe(key, fn)` · 키 = structures · pipes · alignmentDraft · sectionDetail · selection({chainageM, structureId}) · 밑은 지금 캐시(`b_page_state` 등록 키 · 새 키는 등록부에 먼저).
- 좌측 칸 등록부 `design_panel.ts` — `registerPanelSection({id, title, views, order, build(ctx)})` · `createDesignPanel(ctx, view)` → `{root, setView}` · 칸마다 한 번만 정의 · 보일 보기만 적음.
- 아래 단추 `design_dock.ts` · 저장 한 줄기 `design_save.ts` — `saveDesign(ctx, {confirm})` (관 → 구조물 → 계획고 → 암거 옵션 → 오르막 → 횡단) · [확정] = 저장 + 단계 2 · 3 닫기(지금 서버 그대로).
- 종단도 한 벌 `design_profile.ts` — `createDesignProfile(ctx)` → `{root, setView, dispose}` · 판 자리 `side`(배수유역도) · `overlay`(유토곡선 · 표) · 두 보기 모두 같은 도구(되돌리기 · 직선화 · 옮기기 · 확대 · 막기 규칙).
- 관 찾는 거리 한 값 `PIPE_MATCH_M = 0.51`(한 곳) · 페이지 파일은 좌측 칸 · 단추 · 저장을 직접 만들지 않음(시험으로 막음).
### 24-2. 1단계 — 공용 틀(아직 두 주소 · 동시에 넷)
- [x] 24-2a 상태 한 곳 · 저장 한 줄기 — `design_store` · `design_save` · 계획고 초안 가게 하나로(B05 `Profile_Edit` 가게가 주인 · B06 `Page_Grade_Edit` 는 그 가게를 씀) · 관 주인 하나로(B05 배수유역도 쪽 · B06 자체 목록은 가게를 읽기만) · B05 [임시저장] · B06 [저장] 을 `saveDesign` 으로(sub4 · opus high · `B05_Profile_UI_Page_Actions.ts` · `B06_Section_UI_Page_Persist.ts` · `B05_Profile_UI_Profile_Edit.ts` · `B06_Section_UI_Page_Grade_Edit.ts` · `B05_Profile_Api_Pipes_Draft.ts`)
- 검증완료(24-2a · sub4 · 5179 · 사본 sub4_검증 · 커밋 7760dcd7): 시험 96건 초록(16파일)(save_roundtrip B05·B06 새 차례 0 차이 · save_channels · save_recompute · design_store_save 5 · 24-5 목록) · B05 ▲40 +0.3 → B06 866.71 · B06 ▼80 −0.2 → B05 864.49 · B05 [저장] 요청 차례 관→구조물→계획고→확정(오르막)→횡단 · 파일 edits {40:0.370 · 80:−0.233} = 초안 · 구조물 메모 반영 · 관 11개 그대로 · B06 ▲60 [저장] 계획고→횡단 2건만 · 파일 = B05 화면(866.74 · 865.70 · 864.50) · [확정] 단계 2·3 COMPLETE · B07 이동 · 초안 비움 · 어두움 정상
- 덧붙임(브레인 · 커밋 dd806627): ① 옛 B06 계획선 편집 껍데기 걷음(Page_Grade_Edit 삭제 · setGradeEdit · LegacyGradeEdit · useProfileEditStore) — ▲▼ 는 종단도 한 벌 · B06 ▼200 편집 정상
- 덧붙임 ② 유토 뱃지 한 계산 — 구조물 폐회로 면적을 재계산 창구(refreshCrossDesigns) 한 자리에서 얹음 · 전 B05 −14,144.5 · B06 −12,533.2 → 후 B05 · B06 · B05 모두 −12,993.7 · B06 편집 뒤 두 보기 −12,952.9 · test_masshaul_single_source 잠금 추가
- 덧붙임 ③ 계획고 초안 등록부 키(alignment-draft) — sub6 가 옮김(acd30ba3) · 가게가 그 키를 봄 확인 · 시험 103건 초록
- 남김: B06 구조물 목록(`Page_Structures_Panel` · sub8)의 관 쓰기는 `writePendingPipes`(= 가게 pipes) 경유 — 읽기만으로 바꾸는 것은 그 파일 주인 몫 · sectionDetail 은 세션 사본(화면 공유 객체는 Section_Store) · B05 [확정] 켜기(24-2b 남김)는 B05 에 횡단 본문(표준단면 · 전 측점 면적)이 없어 미결 — 24-3 한 페이지 때 B06 창구로
- [x] 24-2b 좌측 칸 등록부 · 아래 단추 — `design_panel` · `design_dock` · B05 좌측 칸(구조물 배치 · 페이지 설정 · 계획노선 · 경로 계산 설정 · 선택 포인트) · B06 좌측 칸(구조물 배치 · 횡단 조정 · 횡단 보기 설정 · 표준 횡단면 설정)을 등록부로 옮김 · `B05_Profile_UI_Panel.ts`(714) 나눔(sub5 · sonnet high · `B05_Profile_UI_Panel.ts` · `B06_Section_UI_Page.ts` 의 좌측 · 단추 부분 · `B06_Section_UI_Page_Common.ts`) — 검증완료(sub5 · 5180 · 사본 sub5_검증 · 진짜 마우스: 두 페이지 칸 DOM 전후 대조 = 칸 안 차이 0줄(B05 847→848줄 · B06 874→875줄은 아래 단추만) · 칸 차례 B05 5칸 · B06 3칸 그대로 · 단추 넷 B05 [초기화][저장][확정(꺼짐+툴팁)][횡단 보기] · B06 [초기화][저장][확정][종단 보기] · B05→B06→B05 구조물 폼 지문 동일(세월교 1 · 집계 항목 줄) · 월류 폭 3.5 고침이 페이지 오간 뒤에도 유지 · 계획고 60m 865.48→865.68 이 B06 에서도 865.68 · B05·B06 [저장] 토스트 · B06 [확정] → B07 · B06 [초기화] 취소=그대로 · 확인=B05 로 이동 + 계획고 865.48 복귀 · B05 [초기화] 동일 · 어두움 단추 글자 대비 5.8~8 · 폭 63~73px 한 줄) · B05 [확정]은 saveDesign 이음 뒤 켬(sub4) · B05 Panel 714→244줄
- [x] 24-2c 종단도 한 벌 — `design_profile` 이 B05 종단 패널을 바탕으로 · B06 위 종단(`Section_View*`)은 그것으로 바꿈 · 두 보기 같은 도구 · 막기 규칙(최소 흙덮기 · 기울기) B06 에도 · 확대 · 끌기 한 방식 · 크기 · 접기 저장 키 하나 · 유토곡선 · 표는 `overlay` 판 · `Profile_Panel.ts`(827) 나눔(sub6 · opus high · `B05_Profile_UI_Profile_*` · `B06_Section_UI_Section_View*`)
- 검증완료(sub6 · sub6_검증 · 두 보기 종단도 같은 자리 위 473px · 높이 616px · 같은 도구 11개 · B05 ▲ 20m 863.13→863.23 → B06 같은 값 · B06 ▲ 863.33 · 20m 카드 성토 7.38→8.35 · 되돌리기 · 다시 · 초기화 · B06 흙덮기 막기(배수관 Ø1000 860.25 그대로 · 막기 안내) · 유토곡선 160px · 표 140px 두 보기 열림 · 카드 → 종단 선택 따라감 · 종단 측점 → 카드 고름 · 알약 → 가까운 카드 + 좌측 폼 · 배수유역도 켬끔 두 보기 같은 값 · [저장] 뒤 새로고침 두 보기 863.23 · 원래 값 되돌림 · 밝음 · 어두움 대비 6.3 이상 · 오가기 6번 오류 0 · 계획고 초안 등록부 칸 alignment-draft · 시험 71건) · 검증 대기
- [x] 24-2d 선택 연동 한 줄 — 측점 · 구조물 고름 = `selection` 한 곳 → 3D · 종단 · 횡단 카드 · 목록 · 폼이 따라감 · 관 찾는 거리 한 값 · B06 횡단 카드에서 옹벽 · 세월교 · BOX 를 눌러도 폼이 그 구조물을 엶(집계 항목 줄 보임)(sub8 · sonnet high · `B05_Profile_UI_Page.ts` 의 selection 부분 · `B05_Profile_UI_Structures_Panel.ts` 의 selectPipeByChainage · `B06_Section_UI_Page_Structures_Panel.ts` · `B05_Profile_UI_Structure_Pick_Session.ts`)
- 검증완료(sub8 · 8010·5183 · 사본 sub8_검증 · 커밋 8a945657 · 병합 뒤 트리 d78ada9a): 시험 test_b05_b06_selection_single 21 초록(거리 한 값 · 카드 누름 → 폼 풀이 · 세션 알림 · 카드 찾기 · B05 되살리기) + 지키는 시험 64 초록 · 타입검사 통과 · B06 카드·벽 각각 눌러 폼 종류 · 측점 · 집계 항목 줄 = 옹벽(측점 범위 10+0~10+10) · 세월교(8+13 · 17+12) · BOX(15+0) · 배수관(4+5) · 독립 기슭막이(4+0~4+10) 전부 뜸 · B05 목록 · 알약 다섯 종류 같은 폼 · 알약 선택 표시 · 3D 표지(관 측점 띠 붉게) · B05→B06→B05 · B06→B05 다섯 종류 고른 것 그대로(카드 선택 · 폼 · 알약 · 부재키) · 밝음 · 어두움 · 원래 값 그대로(사본 BOX 는 시험 뒤 지움) · 남김: ① 3D 코리도 구조물 클릭은 못 봄 — B05_Profile_UI_Corridor_Structures.ts `ringsAt` 를 선언 전에 씀(ReferenceError · 코리도 안 만들어짐 · 내 변경 밖) ② 종단 알약 4+5 배수관을 눌러도 같은 자리 메쌓기 알약이 켜짐(sub6 몫) ③ 구조물(옹벽)을 고르면 옛 관 3D 붉은 표지가 남음(원래 동작) ④ 두 페이지가 아직 따로라 selection 구독(subscribeSelection)은 24-3a 정리(dispose) 뒤에 잇기 ⑤ B05_Profile_UI_Page.ts 770줄(24-3b 나눔 몫)
- [x] 24-2e 배수유역도 판 — `createDrainagePanel` 을 `side` 판으로 끼움(흙덮기 경고 · 되돌리기 · 메뉴 이음 다시) · 횡단 보기에서도 켜고 끔(sub7 · sonnet high · 24-2c 의 판 자리 약속 뒤 · `B05_Profile_UI_Drainage_*`)
- 1단계 끝(홀로 서기 · 나누기) · 검증완료(sub7 · ORCA 5182 · 랩탑_보조 읽기만): 판 = 종단 패널을 안 가져옴(시험) · 창구 `createDrainageSide(host)` · 켜고 끄기 · 끄는 단추 · Panel 700 → 660줄 · 관 보고 `_Report` 로 · B05 동작 그대로(관 11 · 유역 11 · [유역 다시 나누기] 뒤 같음 · 관 끌기 → 세션 초안 chainage 231.27 · 시설(세월교) 따라감 · 펼침 저장 키 · 초안은 지움) · B06 쪽 홀로 마운트: 관 보고 11건 도착 · 끄면 display none 폭 0 · 켜면 폭 320 · 밝음 · 어두움 · 시험 45 통과 · 타입검사 통과 · 남은 것: 종단도 side 자리에 끼우기(sub6 판 자리 약속 대기) · 관 자료 design_store(pipes) 잇기(sub4 뒤) · Profile_Panel 이 createDrainageSide 를 쓰게(sub6 몫) · [x] 는 끼운 뒤
- [x] 24-2f 같음 지킴 시험 — 두 보기의 좌측 패널 · 종단도를 같은 견본으로 그려 공용 칸이 같은지 · 페이지 파일이 좌측 칸 · 단추 · 저장을 직접 만들면 빨강(sub5 · 24-2b 끝에) — 검증완료(sub5 · test_design_view_parity.py 10건 초록 · 공용 칸 DOM 동일 · 단추 넷 차례 · 보기 전환 글자 · 페이지 파일이 좌측 칸 · 단추를 직접 만들면 빨강(B06 페이지에 createButton( 한 줄 넣어 빨강 확인 뒤 되돌림) · 지키는 시험 64건 초록)
### 24-3. 2단계 — 한 페이지(24-2 모두 합친 뒤 · 한 창)
- [x] 24-3a 주소 둘(`#/b05-profile` · `#/b06-section`)이 같은 페이지 · 보기만 다름 · 오갈 때 다시 안 만듦(라우터에 「같은 페이지면 보기만 바꿈」 길) · 떠날 때 3D · 종단 · 횡단 정리(dispose) · 숨긴 3D 는 그리기 멈춤(sub6 · opus high · `A00_Common/router.ts` · `main.ts` · 합친 페이지 파일 · `B05_Profile_UI_Viewer.ts`(771) 나눔)
- 검증완료(sub6 · 5181 · 사본 sub6_검증 · 뼈대 90a2cb9a): 약속 `design_page.ts` DesignPageView(mount 중간 단계 · mountCenter 끝 모습 + shared 자리) · B05↔B06 열 번 두 차례 = WebGL 문맥 1 · 그리기 루프 B05 켬 · B06 때 멈춤(숨김 중 그리기 0) · 좌측 패널 · 종단도 같은 노드 · 전환 B05 24~40ms · B06 71~136ms · 다른 페이지(B01 · A01)로 나가면 문맥 0 · 다시 오면 새로 만듦 · B05 ↑ → B06 계획선 좌표 2386개 차이 0 · 숨은 보기 방향키 안 먹음(B06 종단도 · 횡단 조정창 기슭막이 2.6m 그대로 · 보이면 2.5m) · 선택 이어받기 B05 찰쌓기 → B06 카드 4+0 · 폼 · 집계 항목 줄 · B06 배수관 → B05 알약 · 폼 · 종단도 위치 두 보기 위 473px · 높이 616px · 밝음 5.44 · 어두움 5.79 이상 · 오류 0 · 원래 값 되돌림 · 시험 113 · 뷰어 771→541줄 · 검증 대기
- [x] 24-3b 가운데 보기 전환 — 종단 보기 = 3D + 종단도 · 횡단 보기 = 종단도 + 횡단 카드(처음 누를 때 만듦) · 진행 단계 두 칸이 보기를 따라감 · B03 · B04 · 초기화 · 계획노선 편집에서 들어오는 길 그대로 · `B05_Profile_UI_Page.ts`(766) · `B06_Section_UI_Cross_View.ts`(756) 나눔(sub4 · opus high)
- 검증완료(24-3b · sub4 · 5179 · 사본 sub4_검증2 · 커밋 473d959d): 좌측 패널 · 종단도 · 아래 단추 · 구조물 배치 폼 = 두 보기 같은 노드 (패널 1 · 종단도 1) · 오가기 10번 WebGL 캔버스 1 · 오류 0 · 전환 2~10ms · 진행 단계 켜짐 · 제목 보기 따라감 · 단계 누름 = 보기만 바뀜 · 사용자 길: 종단 보기 세월교(8+13) 월류 폭 4 → 횡단 보기 같은 선택 · 폼 값 4 · 집계 항목 줄 · 카드 8+13 선택 → 횡단 보기 60m ▲0.2(865.48→865.68) · 80m ▼0.1(864.60) → [저장](횡단 보기) 요청 차례 관→계획고→암거 옵션→오르막→횡단 · 파일 월류 폭 4 · edits {60:0.246 · 80:−0.117} → 새로고침 두 보기 60=865.67 · 80=864.60 · 폭 4 → 종단 보기 [확정] 단계 2·3 COMPLETE · B07 이동 · 들어오는 길(B04 단계 · B07→횡단설계 · 대시보드→주소 직접 · [초기화] 다시 세움 · 계획노선 편집 창 열고 닫기) · 덧붙임 ① 조정창 열린 채 카드 초점 방향키 = 조정창만(d 2.1→1.1 · 계획고 그대로) · 종단도 누른 뒤 = 계획고만 ② 횡단 보기 계획고 편집 → 종단 보기 [3D 업데이트] 대기 켜짐 ③ 옛 B05 Page 786 삭제 → design_view_profile 654 · Cross_View 756→658 · 밝음 · 어두움 · 시험 169건 초록 · 타입검사 통과 · 검증 대기
- 남김: ORCA 창이 화면에 안 그려지면 requestAnimationFrame 이 안 돌아(카드 선택 넘김 등) 검증 때 setTimeout 으로 갈음해 잼 · 저장 전 새로고침에서 종단 보기 폼 세월교 월류 폭이 초안(3.5) 대신 10 으로 보임(초안 칸에는 3.5 · 까닭 미확인 · 저장 뒤에는 정상)
### 24-4. 3단계 — 관 · 옹벽 칸 한 곳(24-0 답 뒤)
- [x] 24-4a 횡단 카드 조정 창(옹벽 · 세월교 · BOX)과 좌측 폼이 같은 칸을 두 벌로 고치는 것 → 좌측 폼 하나 · 카드 창은 손잡이 · 미리 보기(sub3 · opus high · `B06_Section_UI_Cross_Structure_Panel.ts` · `_Box_Panel.ts` · `_Ford_Panel.ts` · `_Adjust_Dock.ts`)
- 대조(9-29 · sub3_검증 실측): 지금 칸은 세 자리 — 카드 조정 창(오버레이) · 좌측 [횡단 조정] 사본(같은 창 한 벌 더) · 좌측 폼. 사본의 −/+ 는 폼을 거치지 않고 조정 채널에만 써서 폼 값이 옛 값으로 남음(두 벌)
| 구조물 | 칸 | 조정 창 · [횡단 조정] 사본(지금) | 좌측 폼(지금) | 판정 |
| --- | --- | --- | --- | --- |
| 배관 벽(유입 · 유출) | 유입측 구조 · 형태 | 셀렉트 둘(숨김) | 「구조」 · 「형태」 | 없앰 |
| 〃 | 높이 · 길이 · 기준측점 전 · 후 | −/+ 넷(사본) | 같은 네 칸 | 없앰(폼 하나) |
| 〃 | 단 수 · 옵션(연동 · 경사) | 사본 줄이 폼 칸에 옮겨 붙음 | — | 남김(폼 칸) |
| 〃 | 좌우 · 상하 | 십자 ▲◀▶▼ · 읽기 | — | 조정 창 = 손잡이(십자 · 끌기) · 읽기 줄은 폼 칸에도 |
| 집수정(유입) | 길이 | −/+(사본) | 「길이」 | 없앰 |
| 〃 | 기준측점 전 · 후 | −/+(사본) | 없음(레지스트리 `inlet_basin_before_m` · `after_m`) | 옮김(폼 칸 · 옵션 보이기 따름) |
| 〃 | 내공 폭 · 높이(ㄴ · ㄷ형) | 9키 모서리 | 없음 | 옮김(유입구 칸) |
| 〃 | 좌우 · 상하 | 9키 십자 | — | 손잡이 |
| 추가 기슭막이(다단) | 형태 · 높이 · 길이 · 전 · 후 | 사본 줄이 「추가 기슭막이」 칸에 옮겨 붙음 | — | 남김(폼 칸) |
| 세월교 측벽 | 측벽 높이 | −/+ | 없음 | 옮김(날개벽(유입 · 유출) 칸) |
| 〃 | 관경 · 수량 | 셀렉트 · −/+ | 「관경」 · 「수량」 | 없앰 |
| 〃 | 날개벽 설치 · 짧은쪽 높이 · 길이 · 각도 | 토글 · −/+ 셋 | 날개벽 칸 | 없앰 |
| 〃 | 좌우 · 상하 | 십자 · 읽기 | — | 손잡이 · 읽기 줄 폼 칸에도 |
| BOX 끝(좌 · 우) | 구체 길이 · 표고 | 십자 · 읽기 | — | 손잡이 · 읽기 줄 폼(날개벽 칸)에도 |
| 공통 | [횡단 조정] 사본 상자 | 폼 아래 따로 | — | 없앰(줄은 모두 폼 칸으로) |
고치기 전 수치(조정 창 · 사본의 input+select): 배관 벽 2 · 2 · 집수정 2 · 2 · 세월교 1 · 1(사본 관경 셀렉트 보임) · 사본에 폼과 같은 값 −/+ 배관 벽 8 · 집수정 6 · 세월교 11
- 고침: 조정 창 = 읽기 · 십자 · 그림 끌기 손잡이(고른 도형을 끌면 십자 걸음 · 끄는 동안 「◀ 2.0m」 미리 보기) · [횡단 조정] 상자 없앰 — 폼에 없던 줄(읽기 · 단 수 · 옵션 · 집수정 내공 · 세월교 측벽 높이 · 다단 벽)만 폼 칸에 옮겨 붙음 · 집수정 전 · 후 = 폼 칸 · 폼 값 = 칸 전부(비운 칸 = 그림 자동 · 가게 pipes 에서도 지움 · 조정 예약 culvertopt 에 따로 안 담음) · sub8 24-7a 되얹기는 온 칸만 · 기슭막이 조작값 쓰기는 저장된 좌우 · 상하에서 출발(새 탭에서 폼 칸 하나 고치면 저장값이 지워지던 흠)
- 검증완료(sub3 · 7f04bf96 · 767adc4a · 트리 02b3b533 · sub8 45a22c5d 합침 · ORCA 5178 · 사본 sub3_검증 · 끝에 원래대로): 조정 창 input+select = 0(배관 벽 · 다단 · 집수정 · 세월교 · BOX · 시험) · 폼 → 그림: 유출 벽 형태 콘크리트 · 높이 3 → H 2.2→3.0m(91→124px) · 집수정 ㄴ형 내공 폭 1.1 → 71→75px · 전 1 / 후 2(길이 3) · 세월교 측벽 높이 1.5→1.7 · 관경 Ø1500 → 「흄관 Ø1500 2련」 · 날개 길이 3 → 바닥판 8.33→9.04m · BOX 본체 3.0×3.0 → 「BOX 3.0×3.0」 · 끌기 → 폼: 벽 ◀2.0 · ▼1.0(상하 3.1→4.1) · 집수정 ▶0.4 · 세월교 ▶0.7 · BOX ◀0.5(5.34→5.84) · ▲0.3 · 조정 창 안 닫힘 · [저장] → 새 탭 모두 유지 · 저장 안 한 초안 높이 3 → 같은 탭 새로고침 유지 · 예외: 빈 값(높이 비움 → 3.0→2.2 자동 · 파일에서 지워짐) · 같은 이름(세월교 173 · 352 오가도 각자 값) · 저장 안 하고 보기 전환(측벽 2.1 유지 · 종단 보기엔 옮긴 줄 0) · 권한 없음(로그인 없이 PUT 401 · 파일 그대로) · 밝음 대비 5.6 이상 · 어두움 6.6 이상 · 시험 116 초록(새 7) · 타입검사 0 · 검증 대기
- 남김: ↺(초기화)는 세션 값만 지워 **저장된** 조정값으로 돌아감(원래 동작 · 저장값을 자동으로 되돌리는 길 없음) · ORCA 방향키 전달은 이 창에서 안 됨(합성 키로는 십자 동작 확인) · `queueCulvertOptions`(Station_Controls)는 이제 부르는 곳 없음
### 24-5. 완료 기준(단계마다 · 코더 자기 검증)
- 지키는 시험 전부 초록(`test_b05_min_cover_guard` · `test_b05_stale_design_sync` · `test_masshaul_single_source` · `test_b05_map_interval_spans` · `test_b05_structures_form_summary` · `test_b06_save_recompute` · `test_b06_detail_options` · `test_session_keys_registered` · `test_b05_b06_save_roundtrip` 외 고친 대상) · 소스 문자열을 잡는 시험은 옮긴 자리로 함께 고침
- 사본 프로젝트에서 사용자 길: 종단 보기에서 구조물 고치기 → 횡단 보기(다시 안 만듦 · 같은 선택 · 같은 폼 · 집계 항목 줄) → 계획고 고치기 → [저장] → 새로고침 → 두 보기 값 그대로 · [확정] 단계 닫힘 · 3D 가 뒤에서 안 돎(메모리 · 그리기 횟수 수치)
- 1단계 끝나면 21장 집계 항목 개선 다시 시작
### 23-3. 노선 추천 다듬기(사용자 9-29 밤)
- [x] 23-3a 곡선 상세 창이 떠 있을 때 [노선 추천]을 열면 상세 창이 모달 뒤로(sub2)
- [x] 23-3b 모달 미리 보기 지도의 확대 · 축소 · 회전 = 편집 창과 같은 코드(가져다 씀 · 베끼지 않음)(sub2)
- [x] 23-3c 비중 슬라이더 세로 막대 · 제약 칸 4행 · 글자 크게(sub2)
- [x] 23-3d 도구 막대 구분선을 [노선 추천] 오른쪽으로(노선 추천 | 1m 등고선 …)(sub2)
- 검증완료(sub2 23-3a~d · ORCA 5177 랩탑_보조 읽기만 · 노선 안 씀): 모달 뒤 막 z-index 1002 > 곡선 라벨 패널 1001 · 라벨 한가운데 맨 위 요소 = 모달 안 단추 · 미리 보기 휠 확대 ×1.148 · 축소 ×0.871(편집 창 1.15 · 0.87) · 끌기 40·25px → 지도 이동 39.9·24.5px · 회전 15° 시계 → 반시계 원위치 · 슬라이더 셋 28×130px 나란히 · 50/25/25 → 토공 60 → 27/60/13 합 100 · 제약 4행(세로 37px 간격) · 글자 본문 14 · 라벨 14 · 값 16 · 알약 16px · 구분선 = 노선 추천 | 1m 등고선 … 거리 재기 | 되돌리기 · 밝음 · 어두움 · 폭 595px 한 열(가로 넘침 없음) · 타입검사 통과 · 시험 14 통과 · 남김: 옛 SVG 지도 함수 `mapPaths`(Initial_Model)는 쓰는 곳이 없으나 시험이 물고 있어 그대로
- [x] 23-3e 비중 예상 100 · 토공 0 · 기울기 0 = 예상노선 추적과 같은 노선 · 토공 100 = 토공 최소 · 기울기 100 = 기울기 순한과 같은 노선인지 검증 · 다르면 고침(sub3)
- 고치기 전: 100/0/0 = 후보 중 이격 최소(1153.26 m · 추적과 41.4 m) · 토공 · 기울기 끝값은 맞음 · 고침: 예상 100 = 추적 선 그대로 · 사이 비중은 제약 지킨 후보에서만 가중합(추적 선을 사이에 넣으면 평지에서 계류 제약 넘는 추적 선을 고름) · 비중의 기울기 몫 = 최대 먼저 · 평균은 같을 때만(기울기 순한과 같은 순서)
- 비중 이동(랩탑_보조 = 랩탑_메인 · 같은 값):
| 예상/토공/기울기 | 연장 m | 최대 % | 평균 % | 절성토 합 | 이격 m | 못 지킨 곳 | 같은 갈래(거리) |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 100/0/0 | 1078.01 | 32.4 | 13.72 | 7,535 | 1.07 | 12 | 추적(0.000 m · 노드 같음) |
| 90/5/5 · 75/12.5/12.5 · 50/25/25 | 1153.26 | 17.96 | 6.92 | 4,124 | 16.07 | 3 | — |
| 25/37.5/37.5 · 0/50/50 · 0/75/25 | 1156.68 | 20.09 | 6.68 | 3,893 | 18.06 | 4 | 토공 최소 |
| 0/100/0 | 1156.68 | 20.09 | 6.68 | 3,893 | 18.06 | 4 | 토공 최소(0.000 m · 노드 같음) |
| 0/25/75 · 0/0/100 | 1153.20 | 16.83 | 7.23 | 4,039 | 18.96 | 2 | 기울기 순한(0.000 m · 노드 같음) |
이어짐: 비중을 한쪽으로 옮기면 그 목표 값은 나빠지지 않음(예상 100→0: 이격 1.07 → 16.07 → 18.06 · 기울기 100→토공 100: 절성토 4,039 → 3,893 · 최대 16.83 → 20.09) · 후보가 셋뿐이라 값은 계단으로 건너뜀(100 → 90 에서 추적 → 제약 지킨 후보 · 끊김이 아니라 제약 넘는 추적 선이 끝값에만 있어서)
- 검증완료(sub3 17212254 · test_route_initial 24(끝값 셋 · 단조 · 합성 언덕 + 랩탑_보조) · API 8005 두 프로젝트 열 걸음 200 · 같은 결과 · ORCA 5178 노선 추천 비중 100/0/0 → 1,078.0m · 0/100/0 → 1,156.7m · 0/0/100 → 1,153.2m · 밝음 글자 rgb(97,94,110)/흰 바탕 · 어두움 rgb(179,174,198)/rgb(37,31,56) · 닫기 · 취소 · 노선 파일 안 씀 · 타입검사 0 · 검증 대기) · 좁은 폭은 화면 코드 안 바꿔 다시 안 잼
### 24-7. 사용자 지시(9-29 밤): 흠 · 3단계 반영
- [x] 24-7a 저장 전 새로고침 때 종단 보기 구조물 폼이 초안 값(월류 폭 3.5) 대신 저장값(10)을 보임 → 폼이 초안을 읽음(sub8)
- 원인: 새로고침 뒤 횡단 캐시 상세는 저장분(월류 폭 10 · 관경 1000)이고 폼은 스펙을 초안 옵션보다 앞세움(`withSpecDefaults`) · 횡단 보기가 먼저 서면 뒤에 서는 종단 보기가 빈 관 목록으로 시작해 구조물 로딩이 관을 지우며 초안 옵션이 사라짐
- 검증완료(sub8 · 8010·5183 · 사본 sub8_검증 · 커밋 45a22c5d · 트리 268d3e5c): 시험 test_b06_draft_pipe_replay 1건 + 지키는 시험 45건 초록 · 타입검사 통과 · 고치기 전(되얹기 끔) 횡단 새로고침 = 월류 폭 10 · 배수관 카드 Φ1000(폼 1200과 어긋남) · 세월교 카드 「기본값(미확정)」에 월류 폭 · 고친 뒤 세 가지(세월교 월류 폭 3.5 · 배수관 4+5 관경 1200 · 옹벽 높이 3 각각 초안) 새로고침 뒤 종단 · 횡단 두 보기 폼 값 초안 그대로 · 횡단 카드 Φ1200 · 옹벽 카드 H=3.0m · 세월교 카드 월류 폭이 기본값 목록에서 빠짐 · [저장] 뒤 서버 값 1200 · 3.5 · 3 · 초안 비움 · 새로고침 두 보기 같음 · [초기화] 뒤 1000 · 월류 폭 빈 칸(제안 10) · 카드 Φ1000 · 횡단에서 새로고침 → 종단으로 간 뒤 다른 관 관경을 고쳐도 세월교 초안 3.5 그대로(고치기 전엔 옵션 사라짐) · 빈 값 → 초안 옵션 빠짐 · 새로고침 뒤 빈 칸(제안 10) · 저장 안 하고 종단↔횡단 오가도 3.5 · 같은 종류 관(배수관 1 · 2) 하나만 고쳐도 다른 쪽 그대로 · 밝음 대비 11.8 · 어두움 13.1 · 사본은 시험 뒤 원래 값(옹벽 2 · 관경 1000 · 800 · 월류 폭 빈 칸)으로 되돌림(초기화가 지운 구조물은 백업으로 복원) · 남김: 종단도 · 배수유역도는 값이 아니라 이름 · 위치만 보여 값 판정은 폼 · 카드로 함 · 조정창(culvertopt 예약)만 고친 값은 새로고침 뒤 카드에 안 되얹힘(초안 관 목록에 안 실려 있어서 · 저장 때 예약이 나가므로 화면과 저장이 갈릴 수 있음)
- 24-4a 착수(sub3)
### 24-6. 1단계 끝(9-29 21:10) · 2단계 나눔
- 검증완료(24-2 전부 · 코더 자기 검증 · 메인 합침 트리 d78ada9a · 타입검사 0): 좌측 칸 등록부 · 단추 넷 · 저장 한 줄기 · 종단도 한 벌(두 보기 같은 자리) · 배수유역도 판 · 선택 연동 · 유토 뱃지 한 값 · 같음 지킴 시험
- 브레인 판정: 2단계는 sub6 이 한 페이지 뼈대(주소 둘 → 같은 페이지 · 보기 전환 길 · dispose)를 먼저 push → sub4 가 받아 가운데 보기 · 진행 단계 · 들어오는 길 · B05 [확정] · 파일 나눔
- [x] 24-6a 3D 코리도 구조물이 안 만들어짐 — `B05_Profile_UI_Corridor_Structures.ts` 가 ringsAt 를 선언 전에 씀(ReferenceError) · 고치고 3D 구조물 누름 → selection 확인(sub7)
- 검증완료(sub7 24-6a · ORCA 5182 · 사본 sub7_검증 8161cc22 · 랩탑_보조 읽기만): 원인 = `ringsAt` 가 `pushSwept` 보다 뒤에 선언 — 기슭막이 단 반복이 곧바로 `pushSwept` 를 불러 ReferenceError(TDZ) · 들어온 커밋 e371c275(2026-08-28 물넘이 3D 파임 + 독립 기슭막이) · 서버 사전 생성(Node 번들)도 같은 오류로 실패(끝 코드 1) → 브라우저 폴백도 같은 코드라 3D 코리도 없음 · 고침 = ringsAt 를 pushSwept 앞으로 · 고치기 전 사전 생성 FAIL(`Cannot access 'ringsAt' before initialization`) → 고친 뒤 OK 16.0MB · 구조물 솔리드 82(basin 40 · revet 31 · pipe 11 · 옛 저장본과 같음) · 3D 태그 메시 115 · 코리도 그룹 자식 228 · 콘솔 오류 0 · 3D 클릭(진짜 레이캐스트 경로): 옹벽 7+0~7+10 → selection {at 140 · key own · sid} · 좌측 폼 C 사면안정/돌쌓기(메) · 집계 항목 미지정 줄 · 목록 · 종단 알약 켜짐 / 배수관 4+5 → {at 85.05 · outlet} · A 횡단배수/배수관 / 세월교 8+13 → {at 173.09 · outlet:wall · floor · apron} · A 횡단배수/세월교 · 목록 8+13 · 유역도 2번 켜짐 · 밝음 · 어두움 · 시험 77 통과(새 2 · 24-5 지키는 시험 전부) · 타입검사 통과 · 다른 창: 코리도 저장본은 노선 id 별 파일이라 옛 프로젝트는 [3D 업데이트]나 다음 사전 생성 때 새 코드로 만들어짐 · 3D 에서 배수관 몸통은 흙 밑이라 눌리지 않고 날개벽 · 바닥 · 머리벽을 누르면 같은 측점으로 열림(선택은 측점 기준) · 사본 sub7_검증(8161cc22)은 지울 도구가 없어 남김
- [x] 24-6b 종단 알약이 겹친 자리(4+5 배수관 · 메쌓기)에서 누른 것과 다른 알약이 켜짐(sub6 · 24-3a 와 함께)
- 검증완료(sub6 · 사본 sub6_검증): 배수관을 메쌓기 자리 4+5 로 끌어 겹친 뒤 배수관 알약 누름 → 배수관 1 켜짐 · 벌룬 배수관 1(메쌓기 아님) · 관 91.89 로 되돌림 · 초안 없음
## 25. 구조물 집계 항목 — 선택 입력 · 프로젝트 복사본 완전체 · 모달 상세 편집 (검토 · 사용자 확정 전 착수 안 함 · 25-0 만 착수)
사용자 방향(9-29 밤) — M01 · M02 = 프로젝트에서 수량 · 원가를 내기 위한 프리셋 · 단가산출 로직의 선택 입력을 구조물 집계 항목에서 고름 · 형상(면적 · 부피) 입력 = 면적산출 알약(엑셀 칸 지정) · 자재 입력 = 재료산출 알약 + 자재조합 · 그 밖 선택 = 새 컨테이너 · 설계는 B05/B06 · 원가는 구조물에 이은 집계 항목 · 마스터 · 회사 · 개인은 「항목」을 두고 프로젝트는 가져온 시점의 목록과 값까지 가짐 · 고르기 모달 상세 = 카드(도면 · 면적 · 재료 · 추가 컨테이너) + 프로젝트 복사본 바로 고침 + 뒤로가기 = 선택지.
조사 결론(9-29 · 코드 읽기):
- 로직 1,354개 · 입력 3,238개(이름 869) — 형상 · 물량 620 · 자재 436 · 단가 지역 505 · 기계 · 인력 고르기 389 · 할증 260 · 조건 · 등급 1,028 · 일위대가 조합 37개(담은 로직 170 · 조합마다 입력 10~20개 안팎).
- 고른 값은 어디에도 저장 안 됨(로직 · 조합 · M02 · 스냅샷 모두) · 조합 `메모`에 글로만 새어 있음 · 「상목 기본값」 = 보기용 자동값(첫 선택지 · `master_auto.py:80`) · 엔진은 입력이 하나라도 없으면 계산 거부(`master_formula.py:489`).
- 자재는 로직에 키가 아니라 찾는 조건(검색어)으로 있음 · 고른 자재(고름)도 저장 안 됨.
- 단가(인력 · 자재 · 기계 · 유가 · 요율)는 시스템에 최신 한 벌뿐 · 「그 시점 값」 없음 · 스냅샷은 로직 줄만 얼림 — 단가 · 하위 로직(`로직(GC…)`) · 계수 · 소요량 표(`찾기(QC…)`) · 선택 입력이 빠짐 → 과거 시점 원가 재현 불가.
- 스냅샷은 읽기 · 쓰기 길이 없음 · 한 번 만들면 다시 안 씀 · 판을 비교 안 함 · 폴더 이름에 판 없음 · 항목 하나를 여러 구조물이 같이 씀.
- M01 길 전부 시스템 관리자 전용 → 일반 사용자는 알약 · 계산을 못 받음.
- 계산 엔진은 서버(파이썬)뿐 · 채움(`M02_Table_Fill`)은 수량만 · 시트의 알약 칸 값을 읽는 서버 코드 없음.
- 알약 줄은 지금 표 아래 · 합계 줄 **위**(`spreadsheet_links.ts:131`).
- 21-0 「모달 안 시트 편집 없음」은 이번 지시로 바뀜.
브레인 검토 — 방향은 됨 · 막히는 곳 여섯:
1. 입력 갈래(형상 · 자재 · 그 밖)를 이름으로 추측하면 5% 안팎 틀림 → 갈래를 자료로 적어야 함(입력마다 `갈래` 칸 또는 M02 쪽 갈래 표).
2. 「단가 지역」 · 「자재지역」(505개)은 항목마다 고를 값이 아님 → 프로젝트에서 한 번.
3. 형상 입력은 구조물마다 다름(높이 · 길이) → 항목엔 「어느 칸에서 받는지」만 · 값은 구조물(B05/B06)에서 · 그 밖 선택 · 자재는 항목 값(프로젝트 복사본에서 고치면 그 항목을 쓰는 구조물 모두에 적용).
4. 과거 시점 재현 = 복사본에 단가 · 하위 로직 · 표 · 고른 자재 · 선택 입력까지(닫힌 묶음) + 판 · 가져온 날 · 「마스터가 바뀜」 표시와 [새로 가져오기].
5. 일반 사용자용 읽기 · 계산 길(권한) 필요.
6. 원가 합계 화면(B08 · B09)은 이 장 밖 — 이 장은 항목 하나의 단가 · 수량이 서버에서 계산되는 데까지.
### 25-0. 바로 하는 것(사용자 지시 · 데이터 흐름과 무관)
- [x] 면적산출 · 재료산출 시트의 알약 줄을 합계 · 평균 · 숫자 개수 · 최소 · 최대 줄 **아래**로(sub2 · `A00_Common/spreadsheet/spreadsheet_links.ts` · css · 주석 · `npm run build:spreadsheet`)
- 검증완료(sub2 25-0 · ORCA 5177 · 저장 안 누름): 면적산출 합계 줄 y 980 < 알약 줄 y 1004(알약 10개 2줄 61px) · 재료산출 합계 줄 1008 < 알약 줄 1032 · 차례 = 표 → 합계 줄 → 알약 줄 · 페이지 스크롤 없음(문서 1080 = 창 1080) · 알약 눌러 F10 잇기 → 「찰쌓기㎡F10」 흐림 + 칸 세모 · 흐린 알약 누르면 D3 → F10 이동 · 카드 미리보기 시트 2개 알약 0 · 밝음 · 어두움 · 묶음 gzip 엔진 32267 + 화면 33825 + css 3179 = 69271(한도 131072) · 타입검사 · prettier · build:spreadsheet · 크기 시험 2 통과
### 25-0b. 사용자 방향 — 데이터 흐름(9-29 밤 · 모든 판단의 기준)
1. 품셈 원문 → 활동 하나의 원가를 인력 · 자재 · 경비로 나눈 단가산출 로직.
2. 일위대가 조합 = 구조물 원가를 위한 단가산출 로직들의 조합.
3. 구조물 집계표 항목 = 도면(치수) + 면적산출(부피 · 면적) + 재료산출(일위대가에 필요한 정보 + 더하는 자재 · 자재조합 포함).
4. 1~3 = 프로젝트에서 쓰려고 로직 · 조합 · 값을 미리 갖춰 둔 것(맨 위 = 구조물 집계표).
5. 프로젝트 안 = 미리 만든 구조물 집계표 항목을 B05/B06 구조물에 이음.
6. 원가에 필요한 수량 · 로직이 마스터 · 회사 · 개인 자료로 갖춰져 있어 원가 산출 가능.
- 브레인 위임(9-29 밤): 막히거나 고를 일이 나오면 데이터 흐름 · 사용자 조작성을 보고 코드를 먼저 분석해 브레인이 정하고 조율 · 아침에 반영 내용을 확인할 수 있게.
### 25-1. 사용자 확정(9-29 밤) · 브레인 판정
- M01 의 기본값 · 고른 값은 저장 안 함(확인용 · 지금 그대로) · M01 로직 파일 · 화면은 안 건드림.
- 구조물 집계 항목마다 필요한 입력 = 그 항목 일위대가 조합이 담은 단가산출 로직들의 입력 **전부** · 로직마다 갈라 보임 · 이름이 같아도 합치지 않음(로직마다 값이 다를 수 있음).
- 입력을 어디에 이을지(면적산출 알약 · 재료산출 알약 · 선택 컨테이너)는 **사용자가 고름** — 프로그램은 목록을 보이고 고르게만 함(갈래를 추측해 나누지 않음).
- 저장: 마스터 · 회사 · 개인 = **항목 연결만** 그 층 저장소에 · 프로젝트(구조물에 이은 것) = **항목 연결 + 값**을 프로젝트 영구저장소에.
- 브레인 판정(사용자가 안 정한 것 · 바꾸려면 말해 줌): 프로젝트 복사본은 과거 계산을 되살릴 수 있게 단가 · 하위 로직 · 표까지 담음 · 마스터가 바뀌면 표시만 하고 [새로 가져오기]는 사용자가 누름 · 복사본을 고치면 그 항목을 쓰는 구조물 모두에 적용 · 비어 있는 입력은 자동값(첫 선택지)을 흐리게 미리 보이고 「확인 안 함」 표시.
### 25-1b. 약속(모든 창 공통 · 바꾸려면 ask)
- 입력 목록(읽기 · 일반 사용자 가능) `GET /api/m02/layers/{layer}/items/{key}/inputs?owner=` → `{일위대가, 이름, 로직: [{로직, 이름, 결과단위, 입력: [{이름, 설명, 단위, 고르기?, 범위?, 자동값}]}], 빠진로직: []}`.
- 입력 하나의 키 = `{로직키}|{입력이름}` · 알약 키 = `입력|{로직키}|{입력이름}`.
- 항목 연결 파일(층 폴더 · 항목 열 id 마다) `inputs/<열id>.json` = `{판, 줄: [{로직, 입력, 자리: "면적"|"재료"|"선택"|null, 알약?: 키}]}` · 자리 면적 · 재료 = 그 시트의 알약으로 뜸(칸 잇기는 시트 `연결`이 맡음) · 자리 선택 = 「선택 입력」 카드.
- 프로젝트 복사본(`{프로젝트}/templates/items/{폴더}/`)에 더하는 파일 = `입력연결.json`(위와 같은 모양) · `입력값.json`{로직키: {입력이름: {값, 확인}}} · `고른자재.json`{로직키: {호표 차례: MT키}} · `단가.json`(그 항목 계산에 쓰이는 단가 줄 · 하위 로직 · 계수 · 소요량 표) · manifest 에 `가져온날` · `원본판`.
- 항목 연결 길 `GET|PUT /api/m02/layers/{layer}/items/{key}/input-links?owner=` — 본문 `{판, 줄}` · 없으면 `{판: null, 줄: []}` · 판 다르면 409 · 없는 키 422.
- 미리 가져오기 `POST /api/projects/{id}/items` 본문 `{layer, owner, key}` → `{폴더}` · 목록 줄 = `{폴더, 원본: {layer, owner, key, name}, 원본판, 가져온날, 마스터바뀜}` · 선택 입력 카드 = `M02_MasterTemplete_Inputs.ts` 하나(sub2 가 link 모드 · sub5 가 value 모드를 더함) · 카드 셋 그리기 옮김 = sub5 `M02_MasterTemplete_ItemCards.ts`.
- 복사본 길 `GET /api/projects/{id}/items` · `GET|PUT /api/projects/{id}/items/{폴더}/{도면|면적|재료|자재조합|입력연결|입력값|고른자재}` · `POST …/{폴더}/refresh`(새로 가져오기) · `POST …/{폴더}/calc`.
### 25-2. 단계(확정 뒤)
- [x] 25-2a 층 자료 틀 — 입력 목록 길(로직마다 갈라 · 합치지 않음) · 항목 연결 파일 읽기 · 쓰기(층 권한) · 열 지우기 · 복사 때 같이 · 일반 사용자 읽기 · 시험(sub4)
- 검증완료(25-2a · sub4 · 8006·5179 · 개인 층 1/3 에 sub4 열 잠깐 만들고 지움 · 커밋 057d3976 · 트리 da09696d): 입력 목록 = M01 과 같음(SS000006 UA000007 로직 3 · 입력 16 · SS000011 UA000036 3 · 12 · SS000014 UA000014 7 · 25 · 자동값 모두 같음 · 빠진 로직 0) · 같은 이름 입력은 로직마다 따로(UA000036 「지역」 ×3) · 일위대가 없는 항목 = 빈 목록 · 연결 저장 → 다시 읽기 같음(판 1→2 · 파일 inputs/pv_l.json 같은 내용) · 빈 줄 저장 · 판 옛것 409 · 없는 로직 · 없는 입력 · 모르는 자리 · 두 번 422 · 알약 면적 = 물량 3 + 입력 1 · 재료 = 입력 1 · 모르는 자리 422 · 일위대가 바꾸면 연결 3줄 사라짐 · 알약 0 · 열 지우기 → 연결 파일 지움 · 일반 사용자 읽기 200 · 쓰기 403 · 회사 층 일반 403 · 관리자 200(pytest) · M02 화면 밝음 · 어두움 오류 0 · 시험 test_m02_item_inputs 4 · M02 시험 전체 106 초록 · 검증 대기
- 다른 창이 알 것: 알약 길 GET /api/m02/layers/{layer}/items/{key}/pills?place=면적|재료 → {물량, 입력} 을 더함(M01 알약 길은 관리자 전용이라 sub2 pillsFor 가 이 길로) · 스냅샷(sub6)은 `M02_MasterTemplete_Inputs.read_file(열)`(store.at 층 안) · `copy_between` · 개인 층 1/3 은 sub2 가 같은 때 열을 넣고 지워 제 정리 뒤 rv 한 열
- [x] 25-2b 복사본 완전체(sub6) — 스냅샷에 단가 줄 · 하위 로직 · 계수 · 소요량 표 · 선택 입력 · 고른 자재 · 판 · 가져온 날 · 읽기 · 쓰기 길(`/api/projects/{id}/items/{폴더}/…`) · 마스터 바뀜 표시 · [새로 가져오기] · 옛 복사본 옮겨 받기 · 시험(마스터 단가 바꿔도 프로젝트 계산 그대로)
- 검증완료(sub6 · 8008·5181 · 사본 sub6_검증 · 커밋 0d8f9672 · b038e99d · sub4 25-2a 합침): 시험 56(새 11 — 조합 37개 로직 170개 × 고르기 끝값 = 복사본 단가 묶음만으로 마스터와 같은 값 · 임시 마스터 사본 인력 LB000002 두 배 → 프로젝트 계산 그대로 · 목록 마스터 바뀜 참 · 새로 가져오기 뒤 노무비 오름 · 입력값 살림 · 판 409 · 모양 400 · 고친 복사본 안 지움 · 옛 복사본 채움 · 미리 가져오기 · 남의 회사 403) · 실서버: B05 배수관 4+12 에 「관공 관매설」 지정 → [저장] → 폴더에 입력연결 · 입력값 · 고른자재 · 단가(518KB) · manifest 가져온날 · 원본판 · 입력값 없음 계산 = 빠진 입력 12 · 멈춤 3 · 자동값 PUT → 다시 읽기 같음 · 옛 판 PUT 409 · 모양 틀림 400 · 없는 폴더 404 · 계산 계 105,532.28(노무 16,405.75 · 재료 87,881.53 · 경비 1,244.99) = 마스터 조합 미리보기와 같음 · 면적 PUT 가짜 계산값 버림 · 새로 가져오기 뒤 입력값 12칸 살림 · 계산 그대로 · 미리 가져오기 SS000022 만듦 → 두 번째 그대로 · 없는 항목 404 · 저장 안 하고 떠나면 폴더 안 생김 · 관 지정 해제 [저장] → 파일 summary_item 0 · 미리 가져온 폴더 지움 · 고친 SS000011 은 구조물 [] 로 남음(사본) · 화면 변경 없음(밝음 · 어두움 해당 없음) · 미리 가져오기 몸 {layer, owner, key}(이름은 층 SS 줄) · 목록 원본판 · 모양 틀림 400 · 없는 항목 404 · 입력연결은 sub4 층 읽기 · 남의 회사 403 은 DB 에 다른 회사 프로젝트가 없어 시험으로만 · 검증 대기
- [x] 25-2c M02 화면 — 새 카드 「선택 입력」(로직마다 묶어 입력 목록 · 줄마다 자리 고르기: 면적산출 알약 · 재료산출 알약 · 선택 · 안 씀) · 자리가 면적 · 재료인 입력은 그 시트 알약 줄에 뜸 · 세 층 공용 · 값은 안 받음(sub2)
- 검증완료(sub2 25-2c · ORCA 5177 · 개인 층 사본 열 「sub2 검증」 · 끝나 지움 → 개인 층 항목 원래대로 SS000001 · SS000003 · 서버 입력 목록 · 연결 길은 아직 없어 약속 모양(GET|PUT `/layers/{층}/items/{키}/inputs` · `input-links` · 판 409)의 브라우저 가짜 응답으로 시험 → **실서버 오면 그대로 이어짐 · 코드 고칠 것 없음**): 카드 넷째(도면 · 면적 · 재료 · 선택 입력) 한 줄 4칸(폭 1449) · 좁은 폭 634px 2×2 가로 넘침 없음 · 마스터(system) · 개인 항목에서 「로직 2 · 입력 6」 = 목록 · 자리 고름 면적 2 · 재료 1 · 선택 1 → 집계표 [저장] 한 번으로 PUT 한 번(줄 4 · 알약 키 `입력|로직|이름`) → 다시 열기 · 열 다시 고름 유지 · 같은 이름 「높이」 두 로직 따로 · 면적산출 알약 줄에 「돌쌓기 찰쌓기 · 높이 m」 「콘크리트 타설 · 높이 m」 뜸(원래 알약 10개 뒤) → F12 칸 잇기 → 저장 → 다시 열기 잇기 유지 · 재료산출 알약에 「콘크리트 타설 · 배합」(우클릭 [목록에서 빼기] 없음) · 저장 안 하고 다른 열 갔다 오면 초안 유지 · 다시 열기는 버릴지 물음 → 확인 = 저장된 값 · 서버 오류 「저장 못 함 — 가짜 서버 오류」 · 판 다름 409 「그 사이 양식이 바뀜」 · 로직 0 = 「이 일위대가에 담긴 로직이 없음 · 빠진 로직 …」 · 일위대가 없는 열 = 「일위대가를 먼저 고름」 · 저장 전 새 열 = 「집계표를 저장하면 입력 목록이 나옴」 · 읽기만(isAdmin 거짓) 선택 상자 6개 모두 잠김 · 밝음 · 어두움 · 타입검사 · prettier · 시험 test_m02_inputs 7 + 관련 43(spreadsheet_d_input 15 · 크기 2 · m02 화면 · 패널) = 50 통과 · 다른 창이 알 것: 알약 항목에 `고정` 칸(spreadsheet_links · 자재 모드에서 [목록에서 빼기] 막음) · 집계표 열 카드 min 폭 300→260px(넷 나란히) · 저장 순서 = 집계표 → 선택 입력(PUT input-links)
- [x] 25-2d 고르기 모달 상세(sub5) — 글 목록 → 카드 넷(도면 · 면적산출 · 재료산출 · 선택 입력) · [수정] = 프로젝트 복사본 편집(M02 편집기를 자료 자리만 바꿔 다시 씀) · [뒤로] = 선택지 · 아직 안 가져온 항목은 읽기만
- 검증완료(sub5 25-2d · ORCA 5180 · 실서버 sub4 057d3976 + sub6 b038e99d · 사본 sub5_검증 · 랩탑_보조 안 씀): 세월교 구조물 [고르기] → 돌기슭막이 메쌓기 1.2m 기초유 → 카드 넷(도면 · 면적산출 · 재료산출 · 선택 입력) · 안 가져온 항목 「프로젝트에 아직 안 가져옴」 + [수정] 넷 「프로젝트로 가져와 고침」 → 면적산출 [수정] = 실서버 POST 가져오기(폴더 system_none_SS000001) → 시트 H10 = 12345 → [저장] → 실서버 GET 값 12345(PUT 판 · 서버 계산값) → [뒤로] → 선택지 · 선택 입력 [수정]: 강도 16(숫자 모양) · 지역 서울 · 소량감률 25 → 실서버 입력값 저장 {GF000222: 강도 16 · 지역 서울, GC000198: 소량감률 25} · 상태 줄 「복사본 계산 — 계 0원 · 빠진 입력 53개 → 50개 · 멈춘 로직 11개」 · 면적산출 [수정] 알약 「돌쌓기 찰쌓기(장비) · 뒷길이㎝」(입력연결 자리 면적) · 같은 이름 「지역」 로직마다 따로(서울 1줄만 확인함) · 범위 0~50 밖 60 → 「범위 0~50 밖」 · 확인 안 함 · 저장 막힘 토스트 · 값 지우면 확인 풀림 · 도면 [수정] CAD 한 줄 더하면 entities 138 → 139 저장 · 저장 안 한 고침 [뒤로] · 모달 [닫기]에서 버릴지 물음(취소 → 그대로 · 확인 → 돌아감/닫힘) · 마스터가 바뀜(목록 응답의 마스터바뀜 참) → 「마스터가 바뀜」 + [새로 가져오기] → 확인 → 실서버 refresh → H10 값 사라지고 넣은 값 그대로 · [적용] → 폼 「돌기슭막이 메쌓…」 → [해제] 미지정으로 되돌림 · 횡단 보기에서 같음 · 좁은 폭(390) 한 줄 쌓기 · 가로 스크롤 없음 · 모달 폭 1320 · 글자 대비 밝음 최소 6.3 · 어두움 최소 6.85 · 마스터 원본 해시 전후 같음(master_template fecfb76e…163개 · master_data add2794a…322개 · 회사 15a156a7 · 개인 8ce941f4) · 시험 새 12(test_item_picker_detail) + sub2 · sub4 · sub6 · M02 구조 · 한 페이지 시험 포함 64 통과 · 타입검사 · prettier · 다른 창: 가짜 응답은 지움(실서버만) · 카드 한 벌 = `M02_MasterTemplete_ItemCards.ts`(M02 화면도 이 카드) · 선택 입력 카드 = sub2 `_Inputs.ts` 에 모드 view · value(`createInputsValueCard`) 더함 · 권한 없음(403) · 판 다름(409) 까닭은 시험(가짜 서버)으로 · 사본 sub5_검증에 가져온 복사본 폴더 system_none_SS000001 이 남음(지울 도구 없음) · 원본이 없는 항목 · 모달 밖에서 고친 복사본은 모달을 다시 열어야 보임
- [ ] 25-2e 계산(25-2a · b 뒤 · sub6) — 구조물 + 항목 복사본 → 서버가 수량(시트 알약 칸) × 단가(복사본) 계산 · 항목 단가 · 세 비목 · 빠진 입력 목록
- 일부(sub6 · 25-2b 와 함께): 항목 단가 길 `POST /api/projects/{id}/items/{폴더}/calc` = 입력값 + 단가.json 만으로 세 비목 · 계 · 빠진 입력 · 멈춤(고른자재 반영) · 남음: 구조물 수량(시트 알약 칸) × 단가
### 25-3. 끝(9-30 새벽) · 남은 것
- 검증완료(24장 전부 · 25-0 · 25-2a~d · 25-2e 일부 · 코더 자기 검증 · 메인 합침 bf21676e 트리 821f047d · 타입검사 0 · 합친 뒤 시험 165 · 메인 5173 수치 확인: 오류 0 · 보기 전환 때 좌측 패널 같은 노드 · 진행 단계 따라감 · 횡단 보기 집계 항목 줄 · 고르기 모달 카드 넷(폭 1320) · M02 선택 입력 카드)
- [ ] 25-3a 구조물 수량 고리 — B05/B06 구조물 치수를 면적산출 시트 칸에 넣는 길(사용자 결정 뒤) → 수량 × 항목 단가
- [ ] 25-3b 고르기 모달 나무 이름에 분류3 이 빠져 같은 이름이 둘 보임
- [ ] 25-3c 구조물 관리(개인 · 회사) 새 종류 더하기 · 마지막 열 지우기
- [ ] 25-3d 검증 사본 프로젝트 · 개인 층 시험 열 정리(사용자 확인 뒤)
## 26. 집계 항목 — 폴더 구조 · 구조물마다 복사본 · 프로젝트에서 새 항목 (사용자 확정 9-30 아침)
사용자 확정:
- 구조물 수량은 B05/B06 값과 잇지 않음 — B05/B06 의 위치 · 크기는 상세설계(2D 도면)에만 · 수량은 면적산출 시트에 사용자가 수식을 쓰고 칸을 지정 · 마스터 자료는 사용자가 따로 다시 만듦 → 25-3a 닫음(수량 × 단가 계산은 요청 때).
- 종류 · 분류 개수 제약 없음 — **폴더 구조가 곧 이름** · 깊이 자유.
- 면적산출 · 재료산출 · 도면 · 선택 입력 복사본 = **구조물마다 하나**(같은 항목을 골라도 길이 · 소재 · 높이 · 옵션 · 측점마다 다름).
- 프로젝트 안에서도 새 항목을 만듦(신규 공사지의 신규 구조물) · 만들면 개인 층에도 저장.
- 마스터 · 회사 · 개인이 바뀌거나 지워져도 프로젝트는 영향 없음 · 고치려면 프로젝트 안에서 고치거나 [재적용] · 프로젝트에서 만든 · 고친 것을 개인에 저장할 수 있음.
- 관리 화면(마스터 · 회사 · 개인)에 고르기 모달과 같은 나무 · 오른쪽 클릭으로 더하기 · 지우기.
- 노선 추천 비중 슬라이더에 값 고정 단추.
- ORCA 탭은 전체 둘까지 · 작업 창은 브레인이 제어.
브레인 판정: 옛 「제목 4칸 · 번호 8자리 = 종류 · 분류 자리」 약속은 이 확정으로 바뀜 — 항목은 `경로`(폴더 이름 배열 · 깊이 자유) + 이름 · 도면 · 면적 · 재료 번호는 자리 뜻 없는 일련번호(있던 번호는 그대로) · 집계표 표는 머리 줄 수를 가장 깊은 경로에 맞춤 · 화면 검증은 한 번에 두 창(탭 둘) — 1차 = 서버 둘(시험만) + 화면 하나 · 2차 = 화면 둘.
### 26-1. 약속
- 항목 = `{키(SS), 경로: ["돌기슭막이", "메쌓기", "1.2m"], 이름(= 경로를 이은 글), 단위, 일위대가, 자재조합, 도번, 면적번, 재료번}` · 옛 `종류` · `분류1~3` 은 읽을 때 경로로 바꿔 받음(빈 분류는 건너뜀).
- 나무 고침 길(층 권한) `POST /api/m02/layers/{layer}/tree` 본문 `{op: "add-folder"|"add-item"|"rename"|"move"|"delete", 경로, 이름?, 새경로?, 키?, 판}` → 새 목록 · 쓰이는 항목 지우기 = 프로젝트엔 영향 없음(알림만).
- 구조물 복사본 자리 = `{프로젝트}/templates/structures/{structure_id 또는 pipe@측점}/`(파일은 25-1b 와 같음) · manifest 에 `원본`(층 · 주인 · 키 · 경로) · `가져온날` · `원본판` · `고침`.
- 복사본 길 = 25-1b 의 `/api/projects/{id}/items/{폴더}/…` 에서 폴더 = 구조물 id · `POST …/{폴더}/reapply`(재적용 = 원본을 다시 가져옴) · `POST …/{폴더}/save-as {to: "personal", 경로, 이름}`(개인에 저장) · `POST /api/projects/{id}/items/new {structure, 경로, 이름, 단위}`(프로젝트에서 새 항목 → 개인 층에도 만들고 그 구조물 복사본으로).
### 26-2. 1차(서버 둘 · 화면 하나)
- [x] 26-2a 폴더 구조 서버 — 항목 경로 모델 · 옛 자료 읽기 호환 · 번호 일련 · 나무 고침 길 · 집계표 저장 규칙(열 더하기 · 지우기 · 복사 · SS 맞춤 · 입력 연결 파일)이 경로를 따름 · 목록 길(`/api/m02/items`)에 경로 · 시험(sub4 · opus high · 화면 검증 없음)
- 검증완료(26-2a · sub4 · 8006 API · 탭 없음 · 쓰기는 pytest 임시 storage · 커밋 b5114ec1 · b3b43631 · 트리 99a672f8 · sub6 fbb214cd 합침): 옛 마스터 51 항목이 경로로 읽힘(개수 51 · 키 차례 · 이름 = 옛 종류 · 분류1~3 이음과 같음 · 나무 폴더 29) · 마스터 집계표 · 장부를 경로 모양으로 옮김(두 번 돌려도 같음 · 키 · 번호 그대로) · 빈 층 첫 폴더 · 항목 · 깊이 1 · 2 · 5 만들기(깊이 5 = 머리 줄 5 · 옛 칸 = 앞 넷) · 새 번호 일련(1 · 2 · 3 · 지운 뒤 4 · 안 되돌림) · 항목 · 폴더 이름 바꾸기(키 · 번호 그대로) · 옮기기(형제 곁) · 제 안으로 422 · 지우기(세 파일 · 입력 연결 같이 · 마지막 항목까지 · 열 0) · 다시 읽기 같음 · 판 409 · 모양 422 · 없는 키 · 폴더 404 · 회사 층 일반 · 남의 개인 · 시스템 일반 403 · 표에서 머리 고치면 경로 따라옴 · 표에서 열 지우면 나무 · 파일도 · 실서버 8006 목록 51 · 나무 판 · 409 · 422 · 404(마스터 안 바뀜) · 시험 test_m02_tree 6 · M02 · 복사본 · 모달 시험 174 초록 · 검증 대기
- 다른 창이 알 것: 나무 읽기 GET /api/m02/layers/{layer}/tree → {판, 폴더, items}(더함) · 나무 고침 본문에 단위? 더함 · 항목 줄에 경로 · 이름 · 번호 시험을 일련번호로 고침(test_m02_structure · test_spreadsheet_store) · SS 장부는 M02_MasterTemplete_Book(store.sync_combos · read_combos 이름 그대로) · 집계표 층이 5 이상이 될 수 있음(화면 표 머리 줄 · M02_Table_Fill 머리) · M02_Item_Personal 경로 이음 · 같은 경로면 이름 (2) · test_spreadsheet_size::test_M02_만_늦게_불러옴 빨강은 ui_template_item_picker_edit.ts(sub5)의 spreadsheet import 때문(제 변경 무관)
- [x] 26-2b 구조물마다 복사본 서버 — 스냅샷을 항목 폴더에서 구조물 폴더로 · 옛 폴더 옮겨 받기 · 같은 항목을 고른 구조물 둘이 따로 · 구조물 지우면 복사본 삭제(고친 것은 남김 규칙 유지) · 재적용 · 개인에 저장 · 프로젝트에서 새 항목 · 채움(`M02_Table_Fill`)은 구조물 복사본을 읽음 · 시험(sub6 · opus high · 화면 검증 없음)
- 검증완료(sub6 · 커밋 fbb214cd · 시험 64 = 기존 56 + 새 8 · 임시 저장소 · 임시 마스터 사본 · 탭 없음): 같은 항목 구조물 둘 = 폴더 둘(st · pipe@측점) · 한쪽 면적 고침 → 다른 쪽 그대로 · calc 각자 · 원본 SS 줄 지워도 calc 그대로 · 목록 원본없음 참 · 재적용 면적 덮임 알림 · 입력값 살림 · 개인에 저장 → 개인 층 새 SS(경로 = 제목행 · 일위대가 · 도면 · 입력연결 판 1 · 단가 안 가져감) · 새 항목 → 개인 층 + 구조물 복사본(원본 경로) · 옛 items 폴더 → 쓰는 구조물마다 복사(고친 값) · 지정 바꿈 · 삭제에 고친 것은 _지난 · 회사 없음 409 · 실서버 8008 사본 sub6_검증(curl): 옛 items 폴더 → structures/_지난 옮겨 받음 · 찰쌓기 · 메쌓기 두 구조물에 SS000022 미리 가져오기 → 폴더 둘 · 관 둘(91.89 · 163.82)에 SS000011 → 한쪽 입력값 PUT → 계 105,532.28 · 다른 쪽 빠진 입력 12 · 옛 판 PUT 409 · 없는 폴더 404 · structure 없는 미리 가져오기 400 · 끝에 맞추기로 지움(고친 한 벌은 _지난) · 개인 층 쓰기(save-as · new)는 실저장소에 안 씀(시험으로만) · 검증 대기
- 흠 고침(sub6): 재적용 뒤 manifest 고침 = false · 살린 입력값 · 고른 자재는 값있음 으로 따로(응답 · 목록 줄) · 시험 20 통과 · 검증 대기
- [x] 26-2c 노선 추천 비중 고정 — 슬라이더마다 고정 단추 · 고정한 값은 안 움직이고 나머지가 합 100 을 맞춤 · 둘을 고정하면 셋째는 저절로 정해져 잠김 · 값 직접 입력 칸(sub7 · sonnet high · 탭 1)
- 검증완료(sub7 26-2c · ORCA 5182 · 랩탑_보조 읽기만 · 노선 안 씀): 비중 슬라이더마다 자물쇠 · 값 칸 · 예상 70 고정 → 토공 20 끌기 → 기울기 10(합 100) · 토공도 고정 → 기울기 저절로 잠김(고정 단추 꺼짐 · 점선) · 셋째 고정 시도 막힘 · 값 칸: 토공 40(남는 몫 30 초과) · 1.5 · -3 · 빈 칸 = 빨간 테두리 · 비중 안 바뀜 · [다시 셈] · [적용] 꺼짐 · 비중 알약 눌러도 요청 0건 · 토공 25 → 서버 본문 {예상 70 · 토공 25 · 기울기 5} · 닫았다 열어도 고정 · 값 유지(창 안) · 밝음 · 어두움 · 폭 556px 세 막대 155px · 넘침 없음 · 시험 20 통과(순수 함수 합 100 규칙 · 표 스윕 · 값 칸 규칙) · 타입검사 통과 · 탭 하나 열고 닫음
### 26-3. 2차(1차 서버 뒤 · 화면 둘)
- [x] 26-3a 관리 화면 나무 — 좌측에 고르기 모달과 같은 나무(`ui_template_tree` · 같은 자료 모듈) · 누르면 표 · 카드가 그 항목 · 오른쪽 클릭: 폴더 더하기 · 항목 더하기 · 이름 바꾸기 · 옮기기 · 지우기 · 세 층 공용 · 읽기만 층은 메뉴 없음(sub2 · sonnet high · 탭 1)
- 검증완료(sub2 26-3a · sonnet high · ORCA 5177 탭 1 열고 닫음 · 개인 층 폴더 「sub2」 항목만 씀 · 서버 sub4 b3b43631): 좌측 「구조물 집계 양식」 아래 「항목 나무」 카드(세 층 공용 · 폴더 → … → 항목 · 검색 · 개수) · 항목 누름 → 표 그 열 고름 + 카드 넷 열림 · 표 칸 누름 → 나무가 그 항목까지 펼침 · 표시 · 만들기 깊이 1(맨 위 항목) · 3(폴더1/e2/항목) · 5(폴더1/d2/d3/d4/항목) → 표 머리 줄 종류~분류4 로 늘고 병합 머리 · 넘침 없음 · 이름 바꾸기(항목 F2 · 폴더 메뉴) · 옮기기(항목 · 폴더 · 자기 안 폴더는 목록에서 뺌) · 지우기(취소 · 확인 · 폴더는 안 항목 수 안내 · Delete 키) · 다시 열기 같음 · 고른 열 유지 · 키보드 위아래 · 왼쪽/오른쪽 접기 펴기 · F2 · Delete · 저장 안 한 표 고침 → 저장/버림/취소 창(취소 = 고침 그대로 · 버림 = 표 다시 읽음 · 저장 = 저장 뒤 진행 · 판 신선) · 판 409 → 다시 읽고 「그 사이 나무가 바뀜」 알림(서버 판을 딴 길로 바꾼 뒤 시도) · 빈 층(가짜 서버) 첫 폴더 · 첫 항목 · 마지막 항목 지움 · 읽기만(canEdit 끔) 메뉴 0 · F2/Delete 창 0 · 항목 고름은 됨 · 마스터 층 51 항목 열어 보기 + 이름 바꾸기 창 취소 + 잘못된 판 409(서버에 안 씀) · 밝음 · 어두움 · 폭 640 트리 넘침 0 · 개인 층 뒷정리(sub2 폴더 · 항목 지움 → 사용자 SS000001 만 남음) · 시험 새 8(test_m02_treepanel) + 관련 40 = 48 통과 · 타입검사 · prettier · 다른 창: ui_template_tree.ts · item_picker_data.ts 는 sub5 것을 그대로 씀(고치지 않음) · 개인 층 표는 sub5 와 같은 파일 — 동시에 쓰면 서로 지워질 수 있음 · UI_Main 에 openTable · settle 더함 · 검증 대기)
- [x] 26-3b 고르기 모달 — 구조물 복사본 기준(같은 항목을 고른 구조물마다 따로) · 나무 오른쪽 클릭으로 새 항목(개인 층에도) · [재적용] · [개인에 저장] · 이름 = 경로 이음(sub5 · sonnet high · 탭 2)
- 검증완료(sub5 26-3b · sonnet high · ORCA 5180 탭 1 · 사본 sub5_검증3 ddde31f7 · 랩탑_보조 안 씀 · 서버 sub6 fbb214cd): 배수관 1(4+5)·2(12+18)에 같은 항목(돌기슭막이 메쌓기 1.2m 기초유) 지정 → [저장] → 서버 복사본 폴더 pipe@85.05 · pipe@258.12 둘(관 지점 id 는 프런트가 pipe@측점 으로 만들어 서버와 같음) → 관 1 모달 상태 줄 「이 구조물 복사본」 → 면적산출 [수정] H10=12345 저장 → 서버 GET pipe@85.05 = 12345 · pipe@258.12 = 값 없음(따로) · 횡단 보기 관 2 모달도 「이 구조물 복사본」 · [재적용] → 확인 창(「고친 도면 · 면적산출 · 재료산출 · 선택 입력 자리가 덮임」) → 서버 reapply → H10 사라짐 · 상태 줄 「고침 있음」 표시 · [개인에 저장](경로 sub5 · 이름 sub5save) → 나무 「개인 › sub5」 에 뜨고 그 항목 선택 · 나무 개인 그룹 오른쪽 클릭 → 「새 항목」 하나(마스터 폴더는 메뉴 0) → 이름 sub5new · 단위 m → 개인 층 새 항목 + 폼 「sub5new」 지정 · [적용] 뒤 [저장] 안내 한 줄 · 메뉴 Esc = 메뉴만 닫힘(모달 그대로) · 이름 = 경로 이음(폴더 깊이 자유: 마스터 › 돌기슭막이 › 메쌓기 › 1.2m 폴더 · 잎 「돌기슭막이 메쌓기 1.2m 기초유」) · 마스터가 바뀜 · 고침 표시(목록 응답 가로채기) 배지 + 재적용 · 밝음 글자 대비 최소 6.3 · 어두움 6.85 · 좁은 폭 390 가로 스크롤 없음 · 마스터 원본 해시 전후 같음 · 뒷정리: 관 둘 해제 + [저장] → 복사본 0(고친 한 벌은 _지난) · 개인 층 sub5save · sub5new 열 지움 · 시험 새 18(test_item_picker_detail) + 자료 시험(node) · M02 구조 · 한 페이지 시험 포함 통과 · 타입검사 · prettier · 다른 창: 나무 오른쪽 클릭 메뉴 자리 = `ui_template_tree.ts` TreeNode.menu · openTreeMenu(sub2 26-3a 가 같이 씀) · 항목 경로 = `PickerRow.경로`(서버가 주면 그것 · 없으면 종류 · 분류1~3) · 서버 확인 필요: 재적용해도 manifest 「고침」 이 true 로 남음(재적용 뒤 「고침 있음」 표시) · 목록 GET 이 느려(항목당 0.5초) 모달 첫 표시가 몇 초 걸림
### 23-4. 비중이 뜻을 갖게 · 추천 갈래 둘 더함(사용자 9-30 아침)
브레인 실측(랩탑_보조 · 노선끼리 가장 먼 거리): 추적 1078.0m 최대 32.4% · 토공 최소 1156.7m · 기울기 순한 1153.2m — **토공 ↔ 기울기 6.1m**(눈으로 같은 노선) · 비중 100/0/0 = 추적 · 99/1/0 = 99/0/1 = 80/10/10 = 50/25/25 = 같은 노선(추적에서 36m · 계단) · 0/100/0 = 0/50/50 = 토공 최소 · 0/0/100 = 기울기 순한.
원인(브레인 분석): 추적 노선은 제약(종단기울기 상한)을 크게 넘음(32.4%) · 제약을 지키는(풀린 상한 안) 후보는 모두 같은 띠로 모임 · 비중은 후보 셋 가운데 고르기만 해서 값이 계단 · 목표끼리 차이가 작음.
- [x] 23-4a 비중 = 탐색 비용의 가중합으로(후보에서 고르기 아님) — 예상 몫 = 예상노선에서 벗어난 거리 벌점 · 토공 몫 = 절성토 · 기울기 몫 = 기울기 · 비중을 조금 움직이면 노선도 조금 움직임(예상 99 → 추적에서 몇 m 안) · 끝값 셋은 그 갈래와 같음 · 제약은 비중 계산에서는 「넘은 구간 알림」으로(막지 않음 — 추적 노선도 넘는 지형) · 토공 최소 · 기울기 순한 갈래는 지금처럼 제약 지킴 · 비중 0→100 을 10 단계로 잰 표(연장 · 최대 기울기 · 절성토 · 이격)를 PLAN 에(sub3)
- [x] 23-4b 토공 최소와 기울기 순한이 눈으로 구별되게 — 목표 차이를 키움(기울기 순한 = 최대 · 평균 기울기를 먼저 · 연장이 늘어도 됨 · 토공 최소 = 절성토 먼저) · 두 노선 가장 먼 거리 · 비교값 차이를 표로(sub3)
- [x] 23-4c 추천 갈래 둘 더함(브레인 제안 · 사용자 확인 대기): 「짧은 노선」(연장 최소) · 「흙 균형」(절토 ≈ 성토 · 남는 흙 최소) — 서버 logic `short` · `balance` · 화면 알약 여섯(sub3 서버 · sub7 화면 26-2c 뒤)
- 검증완료(sub7 23-4c 화면 · ORCA 5182 · 랩탑_보조 읽기만): 알약 여섯(예상노선 추적 · 토공 최소 · 기울기 순한 · 짧은 노선 · 흙 균형 · 비중 계산) 각각 미리 보기 — 짧은 노선 1,143.4m 남는 흙 +39㎥ · 흙 균형 1,156.7m +4㎥ · 토공 최소 +4㎥ · 기울기 순한 +122㎥ · 추적 −578㎥(모자람) · 비중 50/25/25 −1,250㎥ · 짧은 · 흙 균형은 비중 칸 숨김 · 같은 노선 알림 「이 지형은 제약 안에서 갈 길이 폭 13.5m 한 띠뿐 — 흙 균형 · 기울기 순한 · 짧은 노선과 거의 같은 노선(가장 먼 거리 6.1m)」 + 흐린 안내 · 추적 · 비중 계산은 줄 숨김 · 비중 계산 넘은 구간 「(비중 계산)」 사유 · 비중 고정(26-2c)도 같은 차례에 확인: 예상 70 고정 → 토공 20 끌기 = 70/20/10 · 토공 고정 → 기울기 10 자동 잠김 · 값 칸 40 = 빨간 테두리 · 안 보냄 · 닫았다 열어도 고정 유지 · 폭 556px 가로 넘침 0 · 밝음 · 어두움 · 시험 초기 20 + 왕복 7(short · balance 포함) 통과 · 타입검사 통과
- 고침(sub3): 비중 = 탐색 한 번(후보 고르기 아님) — 몫(이격 · 토공 가늠 · 기울기)을 끝 노선 셋(추적 · 토공 최소 · 기울기 순한) 사이 범위로 크기 맞춤(비중 1 = 끝 사이 차이의 1 %) · 제약은 (1 − 예상 몫)만큼 벌점(기울기 · 계류도 같은 크기 맞춤) · 탐색 상한은 갈래 상한 → 추적이 지나는 기울기 사이를 예상 몫만큼 넓힘(막지 않음) · 넘은 곳은 「비중 계산 —」 사유로 목록 · 끝값 100/0/0 · 0/100/0 · 0/0/100 = 추적 · 토공 최소 · 기울기 순한 그 선 · 갈래는 후보 묶음(제약 탐색 + 토공 ↔ 기울기 비중 쓸기 11 벌)에서 비교값으로 고름 → 끝값이 사이 비중보다 제 목표에서 좋음 · 새 갈래 short(연장 최소) · balance(|절토 − 성토| 최소) · 비교값 `surplus_m3`(흙 남음 = 절토 − 성토) · 응답 칸 더함 `similar`(10 m 안인 다른 갈래 · `max_gap_m`) · `band_width_m`(제약 안 후보끼리 가장 먼 거리 = 띠 폭 어림 · 추적은 묶음이 이미 있을 때만 · 없으면 null)
- 23-4b 원인(sub3 실측): 복도 · 격자 아님 — 복도 100 → 200 m 해도 칸 +20 %(지형 자료가 예상노선 ±120~170 m 뿐) · 풂 상한 29.08 % · 노선 그대로. 지형 옆경사 중앙값 67 % → 기울기 제약(풂 상한 + 벌점) 안의 길은 폭 10~20 m 한 띠뿐 · 절성토 비교값도 대부분 14 % 계획고를 맞추는 흙이라 토공 최소 ≈ 기울기 순한. 벌점 5 · 50 · 500 × 목표식(기울기 거듭제곱 2 · 4 · 8, 옆경사만) 어느 것도 두 갈래 거리 10 m 안 · 제약을 빼면(벌점 0) 160~200 m 갈리나 기울기 38 %. 브레인 판정: 제약 지킴 · 억지로 벌리지 않음 · 같은 노선은 `similar` 로 알림 · 토공 ↔ 기울기 축은 계단이어도 받아들임
- 갈래(랩탑_보조 = 랩탑_메인 · 같은 값 · 기준 14 % · R12 · 띠 폭 13.5 m):
| 갈래 | 연장 m | 최대 / 평균 % | 절성토 ㎥ | 흙 남음 ㎥ | 이격 m | 추적과 m | 못 지킨 곳 | similar(10 m 안) |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 예상노선 추적 | 1078.0 | 32.40 / 13.72 | 7,535 | −578 | 1.07 | 0 | 12 | — |
| 토공 최소 | 1156.7 | 20.09 / 6.68 | **3,893** | +4 | 18.06 | 41.4 | 4 | 흙 균형 0.0 · 기울기 6.1 · 짧은 6.1 |
| 기울기 순한 | 1153.2 | **16.83** / 7.23 | 4,039 | +122 | 18.96 | 47.4 | 2 | 토공 6.1 · 흙 균형 6.1 · 짧은 9.1 |
| 짧은 노선 | **1143.4** | 18.95 / 7.28 | 3,896 | +39 | 17.82 | 44.2 | 4 | 토공 6.1 · 흙 균형 6.1 · 기울기 9.1 |
| 흙 균형 | 1156.7 | 20.09 / 6.68 | 3,893 | **+4** | 18.06 | 41.4 | 4 | 토공 0.0(같은 선) · 기울기 6.1 · 짧은 6.1 |
| 비중 50/25/25 | 1091.1 | 27.25 / 7.00 | 4,856 | −1,250 | 4.77 | 20.1 | 6 | — |
토공 ↔ 기울기 가장 먼 거리 6.1 m(그대로) · 비교값 차이: 최대 기울기 20.09 → 16.83(−3.26 %p) · 절성토 3,893 → 4,039(+146 ㎥) · 연장 1156.7 → 1153.2
- 비중 예상 100 → 0(토공 : 기울기 1 : 1 · 10 단계 · 앞 단계와 = 이웃 단계 노선 가장 먼 거리):
| 예상/토공/기울기 | 연장 m | 최대 / 평균 % | 절성토 ㎥ | 흙 남음 ㎥ | 이격 m | 추적과 m | 앞 단계와 m | 넘은 곳 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 100/0/0 | 1078.0 | 32.40 / 13.72 | 7,535 | −578 | 1.07 | 0 | — | 12 |
| 99/0.5/0.5 | 1082.1 | 31.53 / 13.53 | 7,400 | −293 | 1.38 | 5.0 | — | 13 |
| 90/5/5 | 1082.0 | 27.69 / 10.87 | 6,068 | −516 | 2.04 | 9.3 | 9.3 | 11 |
| 80/10/10 | 1084.9 | 27.02 / 8.89 | 5,418 | −1,392 | 2.64 | 13.4 | 6.1 | 9 |
| 70/15/15 | 1090.8 | 27.57 / 7.60 | 4,932 | −1,031 | 3.22 | 13.4 | 4.3 | 7 |
| 60/20/20 | 1085.8 | 27.42 / 8.24 | 5,054 | −1,476 | 3.71 | 13.8 | 4.3 | 4 |
| 50/25/25 | 1091.1 | 27.25 / 7.00 | 4,856 | −1,250 | 4.77 | 20.1 | 9.6 | 6 |
| 40/30/30 | 1098.3 | 27.08 / 7.62 | 4,988 | −1,360 | 6.42 | 25.9 | 8.6 | 5 |
| 30/35/35 | 1093.0 | 27.08 / 7.03 | 4,865 | −1,243 | 7.49 | 25.9 | 9.1 | 4 |
| 20/40/40 | 1135.8 | 21.23 / 7.50 | 3,992 | +6 | 16.05 | 41.4 | 30.9 | 5 |
| 10/45/45 | 1142.8 | 21.82 / 7.30 | 4,041 | +2 | 16.58 | 41.4 | 6.1 | 5 |
| 0/50/50 | 1153.2 | 17.96 / 6.67 | 4,038 | +66 | 17.61 | 41.4 | 6.1 | 3 |
이격 1.07 → 17.61 늘기만(단조) · 이웃 단계 노선 차이 모두 0 초과(4.3~30.9 m) · 30 → 20 에서 한 번 크게(30.9 m) — 제약 몫이 이격 몫을 넘는 자리에서 띠로 건너감
- 비중 토공 100 → 기울기 100(예상 0 · 10 단계):
| 예상/토공/기울기 | 연장 m | 최대 / 평균 % | 절성토 ㎥ | 흙 남음 ㎥ | 이격 m | 추적과 m | 앞 단계와 m | 넘은 곳 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 0/100/0(= 토공 최소) | 1156.7 | 20.09 / 6.68 | **3,893** | +4 | 18.06 | 41.4 | — | 4 |
| 0/90/10 · 0/80/20 · 0/70/30 | 1144.4 | 20.76 / 7.12 | 3,989 | +205 | 17.42 | 44.2 | 6.1 · 0 · 0 | 4 |
| 0/60/40 · 0/50/50 · 0/40/60 | 1153.2 | 17.96 / 6.67 | 4,038 | +66 | 17.61 | 41.4 | 6.1 · 0 · 0 | 3 |
| 0/30/70 · 0/20/80 · 0/10/90 | 1152.2 | 22.39 / 6.76 | 3,952 | +6 | 17.97 | 41.4 | 4.3 · 0 · 0 | 4 |
| 0/0/100(= 기울기 순한) | 1153.2 | **16.83** / 7.23 | 4,039 | +122 | 18.96 | 47.4 | 6.1 | 2 |
한 띠 안 계단(노선 셋) · 값은 단조 아님(탐색 목표 = 4 m 링크 기울기 · 옆경사 ↔ 비교값 = 측점 20 m 기울기 · 절성토가 어긋남) · 끝값은 사이 어느 비중보다 제 목표에서 좋음(절성토 3,893 최소 · 최대 기울기 16.83 최소)
- 제약을 느슨하게 넣었을 때(사용자가 모달 칸을 바꿔 쓸 때 참고): 상한 20 % → 아직 풂(한 띠 9.6 m) · 토공–기울기 9.6 m · 토공 1167 m / 19.6 % / 3,737 ㎥ · 기울기 1166 m / 17.6 % / 3,750 ㎥ · 상한 30 % → 제약을 다 지키는 길이 생김(풂 아님) · 띠 51.6 m · 토공–기울기 51.6 m · 토공 1027 m / 29.8 % / 2,966 ㎥ · 기울기 1151 m / 22.9 % / 3,553 ㎥
- 검증완료(sub3 c14717d0 · 받기 뒤 트리 8f51352f · test_route_initial 27 + test_b05_routeedit_initial_roundtrip 7 = 34 · API 8005 두 프로젝트 여섯 갈래 + 비중 셋 200 · 같은 값 · 없는 갈래 422 · 요청 시간: 같은 입력 첫 요청(후보 묶음 짜기) 2.72 초 — 목표 2 초 넘음 · 까닭 = 제약 탐색 9 + 비중 쓸기 11 + 풂 상한 이분 탐색 + 비교값 잼(엔진 2.2 초 + 지형 읽기) · 이후 0.33~0.96 초 · 추적만 0.6~0.9 초(묶음 안 짬) · 화면 검증 없음 · 검증 대기)
- sub7 화면이 알 것: logic `short` · `balance` 알약 둘 · 비교값 `surplus_m3`(흙 남음 · + 남음 · − 모자람) 칸 · 응답 `similar`(배열 · 없으면 빈 배열 · 추적은 null 일 수 있음) · `band_width_m`(null 가능) — 「이 지형은 제약 안에서 갈 길이 폭 {band_width_m} m 한 띠뿐 · {similar[0].logic} 과 거의 같은 노선」 한 줄 · 비중 계산 violations 사유는 「비중 계산 —」으로 시작(막지 않음) · weights 는 short · balance 에서 0/0/0
- 브레인 판정(9-30 · sub3 실측): 이 지형은 옆경사 중앙값 67% 라 제약 안에서 갈 길이 폭 10~20m 한 띠뿐 — 복도 · 격자 · 목표식 탓 아님 · 제약을 풀면 160~200m 갈리나 기울기 38% → 제약은 지키고 갈래를 억지로 벌리지 않음 · 응답에 `similar`(갈래끼리 가장 먼 거리) · `band_width_m` 을 더해 화면이 「거의 같은 노선」을 알림 · 예상 축은 단조(99 → 5.0m · 90 → 9.3 · 50 → 20.1 · 0 → 45.1)
### 26-4. 끝(9-30 오전) · 남은 것
- 검증완료(23-4 · 26-2 · 26-3 전부 · 코더 자기 검증 · 메인 합침 d9ae3a1a 트리 58ee2400 · 타입검사 0 · 합친 뒤 시험 315 · 메인 5173 수치 확인: 오류 0 · 관리 화면 나무 · 단추 넷 · 노선 추천 모달 열림)
- [x] 26-4a 항목 키 체계(사용자 승인 9-30): 마스터 `SS` + 6자리 · 회사 `SC{회사번호}-` + 6자리 · 개인 `SP{사용자번호}-` + 6자리 · 한 번 주면 안 바뀜 · 다시 안 씀 · 폴더 뜻 없음 · 복사 · 올림은 새 키 + 본뜬 곳 + 분류 제한을 푼 뒤 품번(도번 SD · 면적번 SA · 재료번 SM · UA · UM) 자리수 · 겹침 점검(sub4)
- 검증완료(26-4a · sub4 · 탭 없음 · 쓰기는 pytest 임시 storage · 커밋 760e43c8 · 트리 f64ee645): 키 회사 SC7-000001 · 개인 SP42-000001 · 마스터 SS 그대로 · 이름 바꾸기 · 옮기기 뒤 키 그대로 · 지운 SC7-000002 다음은 SC7-000003 · 층 사이 복사 = SP42-000002 + 본뜬 {company · 7 · SC7-000001} · 옛 개인 층 SS000001 · SS000003(다음 5) → SP42-000001 · SP42-000003 + 옛키 · 옛 키로 입력 목록 200 · 나무 이름 바꾸기 · row_of 찾음 · 옮기기 전 파일도 읽힘 · 새 항목 SP42-000005 · 옛 숫자가 이미 있으면 다음 번호 · 참조 키 바른 5 · 틀린 6(다른 회사 · 다른 사람 · 층 머리 · 자리수 · 번호를 키로) · 번호 120 형제 깊이 6 = SD-000014~000133 한 모양 · 12장 6자리로 안 읽힘 · 옛 8자리 그대로 · 지운 번호 다음 · 층마다 SD-000001 따로(폴더 다름) · 키대장에 SS · SC · SP · SD · SA · SM · UM 없음 · 시험 test_m02_item_keys 7 + M02 · 복사본 · 모달 · B05 집계 항목 212 초록 · 실저장소 회사 · 개인 층 옛 SS 키는 안 건드림(처음 읽을 때 저절로 옮김) · 검증 대기
- 점검(키 · 품번을 읽는 코드):
| 어디 | 무엇을 가정 | 고침 |
| --- | --- | --- |
| `M02_MasterTemplete_Book.sync` | 키 = SS + 6 · `int(키[2:])` | 고침 — 층 머리(SS · SC{회사}- · SP{사용자}-) · 옛 SS 옮김 · `옛키` |
| `common_util_summary_item.py` `_KEY` | `^SS\d{6}$` | 고침 — SC · SP 는 그 층 · 머리 번호 = owner · 옛 SS 받음 |
| `common_util_summary_item.ts` `isSummaryItem` | 키 = 빈 글 아님만 | 그대로 |
| `snapshot_folder_name` · `M02_Table_Fill` 열 id `@폴더` | 키 글자 그대로 폴더 이름 | 그대로(`personal_7-42_SP42-000001` · 붙임표 가능) |
| `M02_Item_Source.row_of` · `_Inputs._item` · `_Items.copy_item` · 나무 고침 키 → 열 | 키 == | 고침 — 옛 키(`옛키`)로도 |
| `M02_MasterTemplete_Store._CODE` | 번호 = S[DAM] + 8자리 | 고침 — 새 `-` + 6자리도 |
| `Store._OLD_CODE` | 12장 옛 6자리(S[DCA] + 6 → 끝 00) | 그대로 — 제안 「글자 + 6자리」(SD000001)는 여기로 읽혀 01010100 처럼 바뀌어서 붙임표 `SD-000001` 로 |
| `Store._serial`(26-2a 8자리 max + 1) | 옛 자리 번호와 같은 모양 · 같은 범위(06030202 가 자리처럼 보임) | 고침 — 새 모양끼리 셈 · 지운 번호 포함 |
| `Store._codes` · `structure_numbers` · 지운번호 | 뒷자리 글 | 그대로(모양 무관) |
| 화면 `M02_UI_Main` · `_ItemCards` · `_UI_Side` · `_Structure` · `_Api_Fetch` · `ui_template_item_picker_data` | 번호 = 보이는 글(정규식 · 길이 · 정렬 없음 · 주석만 「8자리」) | 그대로 |
| M01 `_REF_KEY` · `KEY_RE` · `UI_Rows KEY` `[A-Z]{2}\d{6}` · Combo `U[AM]\d{6}` | M01 키 모양(SS 도 모양은 맞음) | 그대로 — M02 키 · 번호는 M01 줄에 안 들어감 · SC · SP 키와 SD- 번호는 이 모양 아님 |
| 자재조합 UM(`Matset` `다음`) | 층마다 따로 셈 · 같은 층 열만 가리킴 | 그대로 — 층 사이 복사는 새 UM |
결론: 옛 8자리 = 두 자리씩(99 넘는 형제 · 깊이 5 이상은 못 적음)이라 새 항목은 자리 뜻 없는 `-` + 6자리 · 옛 8자리는 그대로 유효 · 층마다 번호가 겹쳐도 파일은 층 폴더 · 열 id 로 가르고 번호는 보이는 이름뿐(프로젝트에서 같은 번호 둘이 보이면 키의 층 머리로 가름) · 키 머리 SS · SC · SP · 번호 SD · SA · SM · UM 은 M01 키대장(UA 포함 16 머리)과 안 겹침(시험으로 잠금)
- [ ] 26-4b 모달 처음 열 때 몇 초 · 추천 첫 요청 2.7초 — 속도는 사용자 요청 때
- [x] 26-4c 검증 사본 = 워크트리마다 하나(사용자 9-30) — 이름 「subN_검증」 · 나머지 사본 삭제 · 다음부터 그 하나를 다시 씀(sub8)
- 검증완료(sub8 · 8010 · 9-30): 삭제 9개(sub4_검증2 · sub4_검증 · sub5_검증3 · sub5_검증 · sub6_검증 · sub7_검증 중복 8bed1e2c · sub8_검증 · 대시보드 삭제 길 → DB 목록에서 빠짐 · storage 폴더도 같이 지워짐 · 옮길 폴더 없음) · 랩탑_보조에서 새로 복제 6개(sub1 · sub2 · sub4 · sub5 · sub6 · sub8 · 확정·지정·_지난 없음 · current_stage 3) · 남긴 것 sub3 · sub7(8161cc22) 그대로
- 표(워크트리 · 이름 · id): sub1 · sub1_검증 · 7c1c9041-5200-4442-bd0f-69361317ec1e / sub2 · sub2_검증 · d785fd98-100a-4a57-8f23-2eef5673bae8 / sub3 · sub3_검증 · 2fb68626-4608-4bdf-96f2-418e2923d6d7 / sub4 · sub4_검증 · 5f1d4e23-0705-4f73-8ecd-7de31b8874c7 / sub5 · sub5_검증 · f057db7a-fc52-4be4-9724-3b95b665c77c / sub6 · sub6_검증 · b6fe2304-7f2b-41ad-beb0-7b5755686766 / sub7 · sub7_검증 · 8161cc22-7e57-413f-b247-4f5538cd16c0 / sub8 · sub8_검증 · c81b21f8-e87d-468f-9a70-247930208a34
- 알림: 창마다 옛 id 를 쓰던 창(sub4 · 5 · 6 · 8)은 위 새 id 로 바꿀 것 · storage 에 DB 목록에 없는 폴더 deebac67-… 하나 있음(내 것 아님 · 안 건드림)
### 23-5. 추천 갈래 다시 정하기(안티그래비티 외부 조사 9-30 · 사용자 확정 대기)
- 조사 요지: 국내 절차 = 타당성평가 → 도상 선정 → 현장 영선(0선) 측량 → 중심선 · 종횡단 측량 · 영선법 = 허용 종단기울기에 맞춰 등고선 교점을 이어 가는 선(절성토 0 의 이상선) · 국외 = 등경사선 자동 추적(PEGGER) · 지형 위 최소 비용 경로(Dijkstra · A*) · 평면 · 종단 동시 최적화(Tabu · GA) · 흙 운반 최소 종단 최적화(Softree) · 노선망 배치(NETWORK 2000).
- 「가장 짧은 노선」 = 산지에서는 최대 경사선과 겹쳐 단독 목표로 못 씀 · 「흙 균형」 = 완경사에서만 뜻이 있고 급경사는 전폭 절토가 원칙 — 이 현장(옆경사 중앙값 67%)에는 안 맞음.
- 지식DB 확인: 영선 · 중심선 측량법은 `산림과임업기술(임도)/2. 임도/4. 노선측량.md` 에 있음 · 「35° 이상 전폭 절토」 · 기울기 수치는 지식DB 에서 아직 못 찾음(조사 글의 수치는 근거로 안 씀).
- 브레인 제안(⬜): 「짧은 노선」 · 「흙 균형」을 빼고 → ① 「영선 노선」(정한 종단기울기로 등고선을 따라 가는 등경사선 · 국내 교본 방식) ② 「안전 우선」(급경사 · 계류 가까운 곳을 피함) · 지금 있는 토공 최소 · 기울기 순한 · 비중 계산 · 예상노선 추적은 그대로.
- 사용자 위임(9-30 낮): 추가 갈래 3~5개 · 안티그래비티 조사(논문 2차 포함) 반영 · 결과 검증까지 · 판단은 브레인.
- 브레인 확정: 「짧은 노선」 · 「흙 균형」 뺌 → 더하는 갈래 넷 = 「영선 노선」(등경사선 · 목표 기울기 = 제약 칸의 종단기울기 상한 안에서 사용자가 넣는 값) · 「안전 우선」(급한 옆경사 · 계류 가까움 회피) · 「계류 횡단 최소」 · 「공사비 어림 최소」(토공 + 계류 횡단 구조물 + 연장의 상대 비용 — 단가는 임시 상대값 · 브레인 임의 판정 · 지식DB 근거가 붙으면 바꿈) · 갈래마다 자기 목표 지표가 모든 갈래 가운데 가장 좋은지 표로 검증 · 논문 2차 조사가 오면 목표 식 · 검증 지표를 대조해 고침.
- [x] 23-5a 서버 — logic `gradeline` · `safe` · `crossings` · `cost` 더함 · `short` · `balance` 뺌 · 비교값에 옆경사 평균/최대 · 계류 횡단 수 · 공사비 어림(상대값) · 갈래 × 지표 표(두 프로젝트) · 자기 지표 1등 검증 · 제약은 지킴(similar · band 알림 그대로)(sub3)
- 고침(sub3): 갈래 = 목표마다 제약 탐색(지금 규칙 · 풂이면 막은 기울기 안 벌점)한 후보를 한 묶음에 넣고 제 비교값으로 고름 — 영선 `gradeline`(링크 기울기와 목표 기울기 차의 제곱 · 비교값 `grade_dev_pct` = 측점 기울기와 목표 차 평균 · 목표 = 요청 `criteria.target_grade_pct` · 없으면 상한 · 상한 넘게 넣으면 상한) · 안전 `safe`(옆경사 35° 이상(지식DB 「35° 이상 전폭 절토」) 또는 계류 버퍼 안을 지나는 길이 · 비교값 `hazard_m`) · 계류 횡단 `crossings`(계류 선 위 링크 · 비교값 `stream_crossings` = 노선 × 계류 교점(10 m 안은 한 번) · 같으면 `stream_offset_avg_m` 큰 쪽) · 공사비 `cost`(비교값 `cost_index` = 절성토 ㎥ × 1 + 연장 m × 2 + 계류 횡단 × 400 — ⚠ 임시 상대값 · 브레인 임의 판정 · 까닭: 이 현장 절성토 1 m 당 3~4 ㎥ 라 연장 몫(벌개 · 노반 · 측구)을 흙 2 ㎥ 로 두면 두 몫이 같은 자릿수 · 횡단 배수 구조물(관 · 기슭막이) 한 곳 ≈ 흙 400 ㎥ · 지식DB 근거가 붙으면 바꿈) · `short` · `balance` 뺌(422) · 모든 갈래에 비교값 `side_slope_avg_pct` · `side_slope_max_pct` · `hazard_m` · `stream_crossings` · `stream_offset_avg_m` · `grade_dev_pct` · `cost_index` · 응답 `criteria.target_grade_pct` · similar · band_width_m 그대로
- 갈래 × 지표(랩탑_보조 = 랩탑_메인 · 같은 값 · 기준 14 % · R12 · 풂 · 띠 폭 13.5 m · 굵게 = 그 지표 1 등):
| 갈래 | 연장 m | 최대 / 평균 % | 절성토 ㎥ | 남는 흙 ㎥ | 옆경사 평균 / 최대 % | 위험 m | 계류 횡단 | 공사비 어림 | 기울기 편차 %p | 추적과 m | 못 지킨 곳 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 예상노선 추적 | 1078.0 | 32.40 / 13.72 | 7,535 | −578 | 65.8 / 104.1 | 458 | 0 | 9,691 | 8.53 | 0 | 12 |
| 영선 노선 | 1169.5 | 18.40 / 7.13 | 4,001 | −64 | 67.5 / 104.6 | 556 | 0 | 6,340 | **7.08** | 48.2 | 2 |
| 토공 최소 | 1156.7 | 20.09 / 6.68 | **3,893** | +4 | 67.8 / 104.3 | 564 | 0 | **6,206** | 7.84 | 41.4 | 4 |
| 기울기 순한 | 1153.2 | **16.83** / 7.23 | 4,039 | +122 | 67.6 / 104.3 | 584 | 0 | 6,346 | 7.13 | 47.4 | 2 |
| 안전 우선 | 1169.5 | 18.40 / 7.13 | 4,001 | −64 | 67.5 / 104.6 | 556(갈래 중 1 등) | 0 | 6,340 | 7.08 | 48.2 | 2 |
| 계류 횡단 최소 | 1169.5 | 18.40 / 7.13 | 4,001 | −64 | 67.5 / 104.6 | 556 | **0** | 6,340 | 7.08 | 48.2 | 2 |
| 공사비 어림 최소 | 1156.7 | 20.09 / 6.68 | 3,893 | +4 | 67.8 / 104.3 | 564 | 0 | **6,206** | 7.84 | 41.4 | 4 |
| 비중 50/25/25 | 1091.1 | 27.25 / 7.00 | 4,856 | −1,250 | 68.1 / 105.2 | 530 | 0 | 7,038 | 8.79 | 20.1 | 6 |
1 등 검사(제약 지키는 갈래 여섯 가운데): 영선 · 토공 · 기울기 · 계류 횡단 · 공사비 1 등 · 안전 우선은 갈래 여섯 가운데 1 등(556 m · 영선 · 계류 횡단과 같은 선)이나 **추적(458 m) · 비중(530 m)보다 김 — 까닭: 띠 제약**(추적 · 비중은 기울기 제약을 넘어 옆경사 덜 급한 산허리를 곧게 지남 · 제약 안 길은 폭 13.5 m 한 띠라 위험 길이가 다 비슷) · 같은 선끼리: 영선 = 안전 = 계류 횡단(0.0 m) · 공사비 = 토공(0.0 m · 짧고 흙 적은 길이 둘 다 이김) · 계류 횡단: 주요 수계(소하천 이상)가 노선에서 평균 1.2 km 떨어져 모든 갈래 0 — 이 현장에서는 가를 것이 없음(평지 합성 시험에서 한 번 건넘 확인) · 옆경사 평균 65~68 % 로 갈래 사이 차이 작음(지형이 한결같이 가파름)
- 제약 상한 30 % 로 넣었을 때(제약을 다 지키는 길이 생김 · 풂 아님 · 띠 폭 72.9 m):
| 갈래 | 연장 m | 최대 / 평균 % | 절성토 ㎥ | 남는 흙 ㎥ | 옆경사 평균 / 최대 % | 위험 m | 계류 횡단 | 공사비 어림 | 기울기 편차 %p | 추적과 m | 못 지킨 곳 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 예상노선 추적 | 1078.0 | 32.40 / 13.72 | 3,732 | −85 | 65.8 / 104.1 | 458 | 0 | 5,888 | 16.43 | 0 | 3 |
| 영선 노선(목표 30 %) | 1048.9 | 29.80 / 16.53 | 3,156 | +10 | 65.3 / 107.8 | 478 | 0 | 5,254 | **13.47** | 40.7 | 0 |
| 토공 최소 | 1027.2 | 29.79 / 14.19 | **2,966** | −26 | 65.2 / 104.6 | 480 | 0 | **5,020** | 15.81 | 40.7 | 0 |
| 기울기 순한 | 1151.3 | **22.90** / 6.90 | 3,553 | +43 | 68.0 / 104.5 | 574 | 0 | 5,856 | 23.10 | 45.0 | 0 |
| 안전 우선 | 1053.7 | 27.19 / 13.09 | 3,227 | −38 | 65.6 / 104.6 | **450** | 0 | 5,334 | 16.91 | 40.7 | 0 |
| 계류 횡단 최소 | 1144.3 | 25.42 / 7.09 | 3,517 | +5 | 68.1 / 104.3 | 576 | **0** | 5,805 | 22.91 | 48.9 | 0 |
| 공사비 어림 최소 | 1027.2 | 29.79 / 14.19 | 2,966 | −26 | 65.2 / 104.6 | 480 | 0 | **5,020** | 15.81 | 40.7 | 0 |
| 비중 50/25/25 | 1036.9 | 27.14 / 11.85 | 3,252 | −45 | 66.9 / 108.0 | 452 | 0 | 5,326 | 18.15 | 15.7 | 0 |
30 % 면 갈래가 벌어짐(similar: 토공 = 공사비 0.0 m · 기울기 ↔ 계류 횡단 8.6 m 뿐 · 나머지는 10 m 넘게 갈림) · 여섯 갈래 모두 제 지표 1 등(안전 우선 450 m 가 추적 · 비중보다도 짧음) · 공사비 = 토공은 30 % 에서도 같은 선(연장 · 흙이 함께 최소)
- 검증완료(sub3 a718c2d6 · 트리 0ad9444c · test_route_initial 31 + test_b05_routeedit_initial_roundtrip 7 + test_b05_routeedit_initial 20 = 58 · API 8005 두 프로젝트 갈래 여덟 + 목표 기울기 10 % · 상한 30 % 200 · 같은 값 · short · balance 422 · 요청 시간: 같은 입력 첫 요청(후보 묶음) 1.93 초 · 이후 0.26~0.64 초 · 목표 기울기 · 상한을 바꾸면 묶음을 다시 짬(1.6~1.9 초) · 화면 검증 없음 · 검증 대기)
- sub7 화면(23-5b)이 알 것: logic `gradeline` · `safe` · `crossings` · `cost` 알약 · `short` · `balance` 는 서버에서 422(화면 알약 · `test_b05_routeedit_initial` 의 여섯 알약 표시 시험은 23-5b 에서 고침) · 영선 목표 기울기 칸 = 요청 `criteria.target_grade_pct`(비우면 상한 · 응답 `criteria.target_grade_pct` 로 실제 쓴 값) · 새 비교값 칸 `side_slope_avg_pct` · `side_slope_max_pct` · `hazard_m`(위험 통과 길이) · `stream_crossings` · `cost_index`(상대값 · 단위 없음) · `grade_dev_pct` · 다시 열 때 새 갈래를 알아야 함(지금 화면은 모르는 갈래를 추적으로 읽음 — 왕복 시험 LOGICS 에 새 넷을 더할 것) · 비중 슬라이더 셋(예상 · 토공 · 기울기)은 그대로
- [x] 23-5b 화면 — 알약 여덟(예상노선 추적 · 영선 노선 · 토공 최소 · 기울기 순한 · 안전 우선 · 계류 횡단 최소 · 공사비 어림 최소 · 비중 계산) · 영선 노선은 목표 기울기 칸 · 비교값 새 지표 · 알약이 많아 두 줄 배치(sub7 · 23-5a 뒤)
- 검증완료(sub7 23-5b · ORCA 5182 · 랩탑_보조 읽기만 · [확인] 안 누름): 알약 여덟 각각 미리 보기 — 값이 sub3 표와 같음(영선 · 안전 · 계류 횡단 1,169.5m · 토공 = 공사비 1,156.7m · 기울기 순한 1,153.2m · 추적 1,078.0m · 비중 1,091.1m) · 비교값 두 묶음(노선 · 기울기: 연장 · 최대/평균 · 목표 기울기 편차 · 옆경사 평균/최대 · 기준 초과 · 예상노선과 이격 / 흙 · 안전 · 비용: 절토 · 성토 · 남는 흙 · 위험 구간 통과 · 계류 횡단 · 계류 이격 평균 · 공사비 어림(어림 · 상대값)) · 영선 목표 기울기 칸(영선일 때만 · 비우면 상한 14 자리표시 · 10 넣으면 「영선 목표 기울기 10.0%」 · 연장 1,156.7m · 편차 4.2%p · 다른 갈래로 옮기면 안 보냄) · 상한 14% 에서 같은 노선 알림이 영선 · 토공 · 기울기 · 안전 · 계류 · 공사비에 뜸(추적 · 비중은 안 뜸) · 상한 30 으로 바꾸니 갈래가 벌어짐(영선 1,048.9 · 토공 = 공사비 1,027.2 · 기울기 1,151.3 · 안전 1,053.7 · 계류 1,144.3m · 알림은 토공 = 공사비 0.0m · 기울기 ↔ 계류 8.6m 뿐 · 끝나고 상한 칸 비움) · 「제약 값을 바꾸면」 흐린 글 · [적용] 계류 횡단 최소 → 현재 추천 글 · 되돌리기 「예상노선 추적」 · 다시하기 「계류 횡단 최소」 · 취소 뒤 다시 열면 예상노선 추적 · 옛 저장값 short 를 캐시에 심어도 예상노선 추적으로 읽음 · 알약 넓은 폭 4×2 두 줄(넘침 0) · 700px 두 줄 · 560px 이하 두 칸 네 줄(글자 안 잘림) · 밝음 · 어두움 · 시험 초기 26 + 왕복 7(새 넷 포함 · 새 비교값 칸 다 있음) 통과 · 타입검사 통과
- 논문 2차 조사(안티그래비티 · 서지 브레인 미확인 · 방향만): 등경사선(Rogers 2005 · Stückelberger 2006) · 침식 회피(Aruga 2005) · 공사비 최소(Akay & Sessions 2005 — 토공 55~70% · 배수 구조물 15~20% · 노면 10~15%) · 계류 완충대(Anderson & Nelson 2004) · 급경사는 전폭 절토라 흙 균형 불가(Moretti 2014) · 다목적 정규화(Jha 2006) · 국내(송철호 2022 · 차두송 1992) · 검증 = 전문가 수작업 노선과 견줌(연장 · 기울기 · ㎥/m · 횡단 수 · 위험지 통과율) → 우리 대조군 = 예상노선 추적 · 지표 earth_per_m · steep_ratio_pct 더함 · cost 상수는 위 비에 맞춤.
- 사용자 확정(9-30 낮): 공사비 어림 = 임의 판정 그대로 · M01 단가와 안 이음 · 단순화 · 정밀 공사비 비교는 요청 때.
### 26-5. 마스터 구조물집계표 초기화(사용자 9-30 낮)
- 사용자: 지금 마스터 항목은 실무 문서를 본뜬 것 — 마스터를 하나씩 새로 만듦 → 구조물집계표 초기화.
- 브레인 판정: 지우는 것 = 마스터 층의 구조물 항목 51개(집계표 구조물 열 · SS 장부 줄 · structure/area/material/inputs 파일) · 남기는 것 = 집계표의 no · sta · 비고 열 · 일위대가 조합(M01) · 자재 조합 표 · 구조물 옵션 보이기 · 도면 양식 · 프로젝트 복사본 · 지우기 전 사본 `tmp/마스터_집계표_초기화전_0930/` · 키는 다시 안 쓰는 규칙대로 다음 번호 유지(SS000052 부터) · 실제 마스터를 읽는 시험은 시험 안 견본으로 바꿈.
- [x] 26-5a 초기화 + 시험 견본화(sub4 · 26-4a 뒤)
- 검증완료: 마스터 항목 51 → 0(나무 지우기 → 집계표 저장 한 줄기 · 파일 153 지움 · 장부 다음 52 · 지운번호 51) · 사본 156 파일 = 지우기 전 · 실제 마스터를 읽던 시험 일곱을 견본(`resources/tester/fixtures/m02_master_sample`)으로 · 새 test_m02_empty_master(빈 마스터 첫 화면 · 나무 · 새 항목 SS000052 · SD-000001 · 고르기 모달 마스터 0 · 복사본 calc 그대로 · 원본없음) · 관련 시험 336 초록 · 검증 대기
### 26-6. 브레인 실제 검증(9-30 · 메인 5173 · 사본 sub1_검증 · 진짜 마우스 · 사진 없음)
- 검증완료: 아홉 흐름 가운데 여덟 통과(구조물 관리 나무 · 새 항목 SP3-000010 · SD-000001 · 지우기 안내 · 고르기 모달 카드 넷 · 적용 → 횡단 보기 같은 색 → 저장 → 구조물 복사본 · 모달 편집 · 뒤로 · 폼 해제 → 저장 → 폴더 삭제 · 추천 알약 여덟) · 합친 뒤 시험 331 · 트리 681716de
- [ ] 26-6a 모달 [해제] 가 저장에 안 실림(sub5)
- [ ] 26-6b 항목 더하기 빈 이름 안내 없음(sub5)
- 한계: ORCA 사진 runtime_unavailable · orca type 안 먹음(입력은 입력 사건으로)
### 26-7. 관리 화면 「구조물 조합」 — 이름 · 나무 자리 · 비고 · 전구간 · 합계 빼기(사용자 9-30)
- 사용자: 이 표는 여러 표의 연결을 보여 주는 표 — 계산하는 표가 아님 · 표와 항목 나무는 같은 것의 두 보기.
- 대상 = 관리 화면(마스터 · 회사 · 개인) · 프로젝트 쪽 집계표(측점 줄 · 수량)는 건드리지 않음.
- [x] 26-7a 화면 이름 「구조물집계표」 · 「구조물 집계 양식」 → 「구조물 조합」(좌측 줄 · 상세 제목 · 안내글) · 파일 이름 · 양식 키 · API 길은 그대로
- [x] 26-7b 관리 화면 표에서 비고 열 · 전구간 줄 · 합계 줄을 안 보임
- [x] 26-7c(갈음 — 아래 26-7 고침 26-7c 로 구현) 좌측 패널 「항목 나무」 컨테이너 없앰 → 「구조물 조합」을 누르면 상세 화면 왼쪽에 나무 · 오른쪽에 표(프로젝트 구조물 관리와 같은 배치) · 나무 기능(오른쪽 클릭 더하기 · 이름 바꾸기 · 옮기기 · 지우기 · 찾기 · 표 열과 서로 고름)은 그대로
- 미결(사용자): 비고 · 전구간 · 합계를 프로젝트 집계표에서도 뺄지 — 정해질 때까지 양식 파일은 그대로 두고 관리 화면에서만 숨김
#### 26-7 고침(사용자 9-30 · 위 26-7c 를 갈음)
- 사용자: 나무를 관리의 주 기능으로 올림 · 「구조물 조합」 표는 나무를 따라오는 참조표 — 종류 · 분류가 나무에서 저절로 바뀜.
- 약속: 정본 = 나무(폴더 경로 + 항목) · 표 = 나무에서 만든 읽기 전용 보기 · 표 머리(종류 · 분류1…) = 항목의 폴더 경로 차례 · 깊이는 나무 깊이대로.
- [x] 26-7c 좌측 패널 「항목 나무」 컨테이너 없앰 → 「구조물 조합」을 누르면 상세 화면 왼쪽 나무(주) · 오른쪽 참조표
- [x] 26-7d 표를 참조표로 — 표 단추(열 더하기 · 분류N 더하기 · 열 지우기) 없앰 · 머리 손 고침 없앰 · 더하기 · 이름 · 옮기기 · 지우기는 나무에서만 · 표 열을 누르면 나무 항목이 골라짐(서로 고름 그대로)
- [x] 26-7e 나무를 고치면(폴더 이름 · 옮기기 · 항목 이름) 표 머리가 저절로 따라옴 — 서버가 경로에서 머리를 다시 만듦 · 세 층(마스터 · 회사 · 개인) 같음 · 프로젝트 복사본 · 프로젝트 집계표의 값은 건드리지 않음
- 정함(sub4): 표 [저장] = 있던 항목의 경로 · 층 이름 · 빈 폴더는 저장본 그대로(브라우저 머리 안 받음 · `store.write(screen=True)` · `tree.keep_paths`) · 단위 · 일위대가 · 도면 · 면적 · 재료 고름은 표에서 그대로 · 표 문서로 열 더하기 · 지우기 API 는 호환으로 남김(화면 단추 없음) · 비고 열(id memo) · 전구간 · 합계는 보일 때 빼고 [저장] 때 저장본 것을 다시 끼움 · 같은 이름 409 는 「이미 있는 항목」 까닭 그대로 보임(판 다름과 가름)
- 검증완료: ORCA 5179 세 층(마스터 · 회사 · 개인) 나무 오른쪽 클릭으로 빈 나무 · 폴더 넷 · 깊이 5 항목(표 층 4→5) · 깊이 2 · 깊이 1 · 폴더 이름 · 항목 이름 · 옮기기 · 같은 이름(바뀜 없음) · 폴더 지우기(층 5→4) · 항목 지우기마다 표 머리 = 나무 경로 일치 · 표 ↔ 나무 서로 고름 · 머리 · 층 이름 두 번 누르기 막힘 · 단위 고침 [저장] 뒤 memo · 전구간 · 합계 남음 · 층 폴더 되돌림 · 시험 127 초록 · typecheck 통과 · 검증 대기
- 사용자 확정(26-7 미결 풀림): 비고 · 전구간 · 합계는 「구조물 조합」 것이 아님 — B08 수량산출의 별도 프로젝트 표 「구조물 집계표」 것 · B08 은 사용자 지시 때 · 지금은 구조물 조합에서 빼기만 하고 프로젝트 값 채우기 코드는 그대로 둠
- [x] 26-3c 고르기 모달 [해제] 초안 누락 · 항목 더하기 창 빈 칸 안내(sub5 · 브레인 실제 검증 흠 둘)
- 검증완료(sub5 · ORCA 5180 탭 1 · 사본 sub5_검증 f057db7a): 원인 ① 횡단 보기에서 한 모달 [적용] · [해제] 는 그 보기의 세션 초안에만 있는데 [저장]이 종단 보기 몫 `ownStructures` 를 보냄 → 초안을 보냄(구조물) · ② 관은 시설 보관소가 서버 응답에 집계 항목 칸이 없으면 화면 값을 이어받아 [해제] 가 되살아남 → 응답이 정본 · ③ 항목 더하기 창(askText) 빈 이름 · 빈 단위 = 칸 빨간 테두리 + 「… 을(를) 적을 것」(토스트는 창 뒤에 가려 안 보임) · 확인: 횡단 보기 옹벽 지정 → 저장(structures.json retaining_wall SP3-000001 · 복사본 폴더 생김) → 모달 [해제] → 저장 → 지정 빠짐 · 복사본 폴더 삭제(고치기 전 = 지정도 저장에서 사라짐) · 종단 보기 옹벽 같음 · 관(배수관 1) 종단 · 횡단 각각 지정 → 저장(pipe_points.json 85.05 · 폴더 pipe@85.05) → 모달 [해제] → 저장 → 빠짐 · 폴더 삭제(횡단 관은 고치기 전 저장에 남던 것) · 개인 층 항목 더하기 창 빈 이름 · 단위 → 칸 둘 빨간 테두리 · 안내 글 · 시험 새 3(test_summary_clear_and_tree_dialog) + 관련 46 포함 49 통과 · 타입검사 · prettier · 뒷정리: 지정 모두 해제 · 복사본 0 · 탭 닫음 · 다른 창: 단위도 이제 필수(항목 더하기 · 새 항목)
## 27. 마스터 템플릿 재구성 — 라이브러리 셋 한 화면 · 대시보드 설정 컨테이너 · 일위대가 조합 이동 (사용자 확정 9-30 낮)
- 목적: 데이터를 정의대로 나눔(마스터 데이터 = 원문 원천 · 수정 불가 / 마스터 템플릿 = 사용자가 고치는 조합 · 양식) · 통합 로직으로 접근 · 권한 부여.
- 정함(브레인 기본값 — 바꾸려면 사용자 한 줄): 일위대가 회사 · 개인 키 `UC{회사}-######` · `UP{사용자}-######`(마스터 UA 그대로) · 회사 관리자는 회사 층 수정 + 자기 개인 수정 + 같은 회사 남의 개인 읽기 · 자재 조합 · 도면 · 면적 · 재료는 구조물 조합 하위 그대로 · 구조물 옵션 · 도면 양식은 시스템 관리자만(카드도 없음) · 나무 이름 「구조물 라이브러리」 · 「일위대가 라이브러리」 · 대시보드 카드 컨테이너는 통째로 접힘.
### 27-1. 라이브러리 한 화면 · 뿌리 셋 · 권한 (sub7 · 먼저)
- [x] 27-1a 「항목 나무」 → 「구조물 라이브러리」(locale 1 · 주석 13 · 시험 주석)
- [x] 27-1b `?layer=` 페이지 분리 폐기 → 한 화면에 뿌리 셋(마스터 · 회사 · 개인) · 뿌리마다 읽기/수정은 권한(`accessFor`)으로 · 읽기 뿌리는 오른쪽 클릭 메뉴 없음 · 표(구조물 조합)는 고른 뿌리 것을 보임
- [x] 27-1c 남의 층 목록 — 회사 관리자: 「개인」 뿌리 아래 같은 회사 사람 목록(읽기) · 시스템 관리자: 「회사」 뿌리 아래 회사 목록 → 사람 목록 · 펼칠 때 불러옴(목록 API + 나무 API 에 owner 인자) · 나무 · 항목 · 양식 API 권한 규칙 하나로 통일(Router_Items · Router_Layers)
- 규칙(`M02_Layer_Access` · 화면 짝 `accessFor`) ① 마스터 = 읽기 누구나 · 수정 시스템 관리자
- ② 회사 `{C}` = 자기 회사 읽기 누구나 · 수정 회사 관리자(ADMIN · 마스터 · 시스템 관리자) · 남의 회사 = 시스템 관리자 읽기만
- ③ 개인 `{C}/{U}` = 본인 읽기·수정 · 같은 회사 남 = 회사 관리자 읽기만 · 다른 회사 = 시스템 관리자 읽기만 · 남의 층은 자리 있을 때만(없으면 404) · 그 밖 403 · 프로젝트 가져오기(apply · sources)는 그대로
- [x] 27-1d 해시 인자 `?open=구조물조합|일위대가|옵션|도면` · `&root=master|company|personal` · `&owner=…` → 그 컨테이너 · 뿌리가 열린 채 진입 (item_picker 「관리 화면에서 고치기」도 이 인자로)
- [x] 27-1e 시험 · typecheck · ORCA 세 역할(시스템 · 회사 관리자 · 개인) 로그인으로 뿌리 · 메뉴 · 403 판정
- 검증완료(sub7 · 59cb28ce): 시험 103 초록(새 test_m02_layer_access 포함) · typecheck · ORCA 5182 시스템 관리자로 뿌리 셋 · 회사 목록 → 회사 공용 · 남의 개인(1/1) 읽기만(「읽기」 표기 · 메뉴 없음 · 저장 숨김 · 쓰기 403 · 없는 층 404 · 모양 400) · 해시 open=옵션 · 도면 · 회사 관리자 · 일반 화면은 세션 역할을 바꿔 뿌리 · 메뉴 · 저장 · 읽기 막대 판정(DB 에 두 역할 계정 없음 · 서버 403 은 시험) · 읽다 생긴 남의 층 뼈대 흠 고침 · storage 원래대로 · 검증 대기
- sub6 에게: 뿌리 부품 `createLibraryRoots({user, active, panel, go})`(TreePanel_Roots · 나무 종류 무관) + `createTreePanel({layer, owner, label, api:{fetch, edit}})` · 권한은 `M02_Layer_Access.require(session, layer, owner, write=)` + `folder(got)`(자기 층만 뼈대) · 남의 층 목록 `/layers/{company|personal}/owners`
### 27-2. 일위대가 조합 → 마스터 템플릿 · 층 · 라이브러리 (sub6 · 서버는 바로 · 화면은 27-1b 뒤)
- [x] 27-2a 서버 — 층별 저장(마스터 `resources/master_data/일위대가조합.json` 그대로 읽기 · 회사 `storage/{회사}/templates/일위대가조합.json` · 개인 `storage/{회사}/{사용자}/templates/`) · 키 UC/UP 장부 · `/api/m02/layers/{layer}/combos` new/edit/delete/tree · 권한 = 27-1c 규칙 · 마스터 조합 편집은 시스템 관리자만(옛 `/api/m01/combo/*` 는 M02 길로 옮기고 M01 에서 뺌)
- [x] 27-2b 화면 — M02 좌측에 「일위대가 조합」 컨테이너(구조물 조합 위) · 라이브러리 나무(폴더 · 조합) + 오른쪽 조합 편집(M01_MasterData_UI_Combo* 옮겨 씀) · M01 에서 일위대가 조합 컨테이너 제거
- [x] 27-2c 구조물 조합 · 면적산출에서 조합 고르기(use-combo · 갈라 내기)가 세 층 조합을 다 보게 · 갈라 내기 결과는 사용자 층에 저장
- [x] 27-2d 시험(M01 combo 시험 옮김 · 층 · 키 · 권한) · typecheck · ORCA
- 정함: 나무 폴더 = [구분, 상세구분] 깊이 2 · 빈 폴더는 파일 머리 「폴더」 · 회사 · 개인 파일도 마스터와 같은 열 한 벌 + 머리 「다음」(키 장부) · 갈라 낸 조합은 그 구조물 조합 층에(마스터 UA · 회사 UC · 개인 UP) · 조합 고르기 = 마스터 층 항목은 마스터만 · 회사 층은 마스터 + 회사 · 개인 층은 셋 · 남의 층 조합 403
- 검증완료(sub6 · opus high · 커밋 354e6cd0 · ae51bed2 · f8302149 · 머지 ca946ebb · c8686ee3 · 6d4b309e · ORCA 5181 탭 하나 열고 닫음): 마스터 뿌리 나무(산림품셈 1 · 실무 일위대가 36) · 조합 누름 → 상세(기슭막이 로직 11 · 이름 붙음) · 개인 뿌리 이동 · 오른쪽 클릭 폴더 더하기 · 2 단 폴더엔 폴더 더하기 없음 · 조합 더하기 → 구분 · 상세구분 채운 빈 조합 · 이름 없음 「이름을 적어야」 · 로직 없음 「빈 조합」(아직 없는 키 안 보임) · 로직 고르기(찾기 「찰쌓기」) → 저장 UP3-000001 · 나무에 뜨고 골라짐 · 나무로 이름 바꾸기 · 옮기기(편집 칸 구분 따라옴) · 폴더 이름 둘 · 서버 목록 같음 · 미리 보기 54,387원 · 나무 고침 뒤 저장 판 맞음 · 저장 안 한 고침 → 나무 고침 전에 버릴지 물음(버림 = 저장 안 됨) · 폴더 지우기(안 조합까지) · 세 층 고르기 목록(마스터 37 / 마스터 37 / 마스터 37 + 개인 1) · 알약 by-key · M01 좌측 여덟 컨테이너(일위대가 없음) · 좌측 「일위대가 조합」 이 구조물 조합 위 · 줄 누름 ↔ 구조물 조합 오갈 때 고름 표시 · 넘침 없음 · 마스터 파일 안 씀 · 개인 층 조합 파일 지워 원래대로 · 시험 test_m02_combo_layers 9 · test_m02_labor_tree 2 · test_m01_combo 21 · test_m01_combo_inputs 8 · 갈라 내기 · 입력 · 나무 · 화면 시험 초록 · typecheck 통과 · 검증 대기
- 다른 창이 알 것: 옛 `/api/m01/combo*` 없음(logic/combos 만) — 조합 길 `/api/m02/layers/{layer}/combos` · 키 하나 `/api/m02/combos/key/{키}`(+`/inputs`) · 세 층 `/api/m02/combos/all` · 담을 로직 읽기 `/api/m02/logic-lib/…`(로그인) · 화면 부품 `M02_MasterTemplete_Labor*`(옛 `M01_MasterData_UI_Combo*`) · 공용 고침: `TreePanel` 에 `maxDepth` · `item` 선택지 · `UI_Side` 에 `labor` 선택지 · `UI_Page` go 에 open 인자 · `Router_Items` 갈라 내기 시스템 관리자 한정 뺌 · `main.py` 두 줄 · `test_m02_structure_combo` 집계표 저장 시험 1 빨강은 26-7e(b4100acc)부터(이 일 무관)
### 27-3. 대시보드 설정 컨테이너 (sub8)
- [x] 27-3a 「구조물 관리」 컨테이너 삭제 · 「시스템 설정」을 모든 역할에 · 1행 1열 · 프로젝트 컨테이너 위 · 통째로 접힘
- [x] 27-3b 안은 작은 카드(제목 + 한 줄 설명) 공용 양식 하나 · 역할로 숨김: 시스템 관리자 = 마스터 데이터 · 일위대가 조합 · 구조물 조합 · 구조물 옵션 · 도면 양식 / 회사 관리자 · 개인 = 일위대가 조합 · 구조물 조합(카드 설명에 마스터 읽기 · 회사 수정/읽기 · 개인 수정 표기)
- [x] 27-3c 카드 누르면 27-1d 해시로 진입 · 마스터 데이터 카드는 M01
- [x] 27-3d 시험 · typecheck · ORCA 세 역할
- 검증완료(sub8 · 50abcb89 · ORCA 5183 탭 1): 시스템 설정 = 모든 역할 맨 위 한 줄(폭 1200/1200) · 제목 누름 접힘(169→90px) · 시스템 관리자 카드 다섯 · 회사 관리자(ADMIN · is_master) 「회사 수정」 root=company · 개인 「회사 읽기」 root=personal · 카드마다 해시 `?open=일위대가|구조물조합|옵션|도면&root=…` · 마스터 데이터 = #/m01-master-data · 「구조물 관리」 없음 · 역할은 /me 응답 바꿔 봄(읽기만 · 새로고침으로 되돌림) · 시험 9 통과 · typecheck 통과 · 검증 대기
## 28. M01 단가산출 — 입력 중심 검토 (사용자 의견 9-30)
- 사용자: M01 원가계산은 로직이 맞는지 · 어떤 입력이 들어와야 결과가 나오는지 확인하는 자리(임시 · 저장 안 함). 단가산출 로직 → 일위대가 → 구조물 조합으로 이어지고, 최종 원가는 사용자가 엑셀 · 자재목록으로 산출. **원가가 맞냐보다 「어떤 로직이 어떤 입력을 받아야 하는지」와 그 입력을 프로젝트 안에서 사용자에게 잘 알려 받게 하는 것이 핵심**(검증은 결국 산출 원가로).
- 대조 결과 = `docs/raw/M01_점검/종합/` (흠 799 · 먼저 고칠 것 10) · 고치기는 사용자 지시 뒤.
- [x] 28-1 로직마다 「받아야 할 입력」 목록을 뽑아 정의(입력 이름 · 단위 · 어디서 오는지 · 기본값) — 25장 선택 입력과 잇기
- [x] 28-2 흠 고치기 차례(28-2a~e 로 갈음): 로직 없음(임도 절) → 검색어 잘못 연결 → 주 · 단위 환산 → 값 · 칸 밀림
- 정함(27-2a · 브레인): 일위대가 라이브러리 폴더 = [구분, 상세구분] 깊이 2 · 마스터 열 한 벌 그대로 · 회사 · 개인 파일도 같은 열 · 나무 부품은 구조물 라이브러리 것 · 깊이 한도 2.
- 사용자(9-30 12:50): 검증보고서(종합_흠목록 799)를 반영해 고침 — 입력 중심 관점 유지 · 「확실」만 고침 · 「의심 · 사람 확인」은 목록으로 남겨 사용자 결정 · 임도 묶음(산림 · 토목 1~3 · 공통 5~7) 먼저.
- 정함(브레인): 갈래별로 창을 나눔(같은 장 파일을 두 창이 고칠 수 있으나 줄이 다름 · 작게 자주 커밋) · 새 키를 받는 「로직 없음」은 한 창(sub1)만 — `_키대장.json` 충돌 방지 · 고친 로직은 견본 입력으로 계산을 한 번 돌려 오류 없음 + 결과 자릿수 확인 · `_갱신절차.md` 그대로.
- [x] 28-1 로직마다 「받아야 할 입력」 목록(sub5) — 로직 키 · 입력 이름 · 단위 · 어디서 오는지(설계값 · 사용자 · 상수) · 기본값 · 빠진 입력 표시 → `tmp/M01_입력목록/` (브레인이 docs 로)
- [x] 28-2a 로직 없음 — 산림 84절 → 건설(공통 3 · 토목 3 · 유지관리 37) (sub1 · 새 키 유일 창)
- [x] 28-2b 재료 검색어 잘못 연결 159 (sub2) — 자재품목표에서 맞는 품목이 있는지 먼저 · 없으면 「품목 없음」 목록
- 검증완료(sub2 28-2b · 커밋 a9a46311 · 8ba38e47 · 07b01f96 · 5ada61bf · 7ffafabb): 확실 114줄(재료 줄 기준) 가운데 재료 검색어 143줄 고침(덧줄 MT 키 1 = GC000409 백열등 잡재료 포함) — 맞는 품목을 자재품목표에서 먼저 찾고 검색어가 그 품목을 첫째로 잡게 · 고친 뒤 줄마다 검색해 첫째 품목 확인 · 고친 로직 77개를 시험 입력으로 계산 77/77 오류 없음(계 자릿수 정상) · check_master 틀 0 · 로직 0 · 단위 경고 15→30(고친 품목의 단위 성격이 호표와 다른 줄 — 단위확인 목록) · 시험 test_masterdata_check · test_m01_api 98 통과 · 못 고친 것: 품목없음 34건(tmp/M01_고침/sub2/품목없음.md) · 입력빠짐 4 · 단위확인 23 · 사람확인 26 · 산림 GF000060 우드칩=포 · GC000431/432 규격 입력 BX/NX 를 검색어에 씀(GC000432 메탈리밍쉘 NX 는 품목 없어 NX 고르면 후보 없음 오류) · 코드 안 고침 · 검증 대기
- [x] 28-2c 주(할증 · 손료 %) 빠짐 65 · 단위 환산 빠짐 76 (sub3)
- 고침(sub3 28-2c · 커밋 c105d7ff · 417fcb2b · 21184fa1 · 22bf0ad7 · 8f1dfa06 · 29633732): 확실 81건 중 74건 고침 · push — 임도 8(도로포장 · 요율 덧줄 · 주⑤ 융착식·표시못은 「주재료비」 입력 더함) · 토목 5-2-3 · 6-7/6-8 5건 · 기계설비 13장 아세틸렌 병×ℓ입 → 아세틸렌 ℓ 품목 21줄 · 검사및교정 10% = 기술관리 뺀 직종 ×1.1 13건 · 표 단위 공란 · 주 보충 · 유지관리 2건
- 미커밋 7건: 공통 3-3-1~3-3-6 · 3-3-8 소모자재 덧줄(자료 고침 끝 · `tmp/M01_고침/sub3/토공사_미커밋.patch`) — `test_m01_api.py::test_단가_자동_요소_찾기_저장전_시험계산` 이 3-3-1 덧줄 비어 있음을 가정해 빨개짐 · 시험(py) 한 줄 고침 뒤 커밋
- 요율은 식 안 숫자로 넣음(계수표 새 키는 sub1 몫) · 새로 받아야 할 입력: `tmp/M01_고침/sub3/입력빠짐.md` · 검증 대기
- [x] 28-2d 값 · 칸 밀림 110 · 계산식 어긋남 90 (sub4)
- 검증완료(sub4 · 커밋 158d9784 ~ 9785556e): 두 갈래 「확실」 = 73줄(값 · 칸 49 · 계산식 24 — 110 · 90 은 의심 · 사람 확인 포함 수) · 고침 69 · 못 고침 4(8-1-3 이동속도 표 = 새 키 필요 · CC000120 b=150 경계 = 엔진 범위규칙이 섞인 경계를 못 담음 · 9-7~9-10 계수 합성 · 9-9-1 면적계수 = 원문 안 갈림 사람 확인) · 원문 설계예와 같아짐(GC000502 지하시설물 · GC000511 3차원 · GC000462/463 GNSS · GC000522 무인비행 · GC000991 등) · check_master 틀 0 · 본문 0 · 로직 0 · 계산전부 1354 통과 · 시험 test_masterdata_check · test_m01_api 98 통과 · 목록 tmp/M01_고침/sub4/목록.md · 입력빠짐 1(GC000511 구축데이터 고르기) · 코드 안 고침 · 검증 대기
- [x] 28-2e 로직 일부 구현 110 (데스크탑 메인)
- [x] 28-3 의심 347 · 사람 확인 18 → 사용자 결정 목록(브레인 · 고치지 않음)
- 검증완료: 1,354줄 · 입력 3,238 · 이름 빠짐 0 · check_logic 전부 통과 · docs\/raw\/M01_입력목록\/ · 검증 대기
### 27·28 브레인 실제 검증(9-30 15:20 · 메인 5173 · 임의 회사 「브레인검증회사_09301441」 · 회사관리자 A(14) · 일반 B(15) · B 프로젝트 928d8345 · 탭 하나 · 진짜 마우스 안 먹어 입력 사건)
- 검증완료: 대시보드 카드 세 역할(5 · 2 · 2 · 설명 글) · 카드 → 컨테이너 · 뿌리 열린 채 진입 · 회사 층 폴더 · 항목(SC3-000001 · 머리 = 나무) · 빈 이름 안내 · 회사 층 일위대가 조합(UC3-000001 · 로직 고르기 · 저장) · 개인 B 회사 읽기만(메뉴 없음 · 403) · 개인 항목 SP15-000001 · 조합 UP15-000001 · 회사관리자가 B 개인 층 읽기만 · 시스템 관리자 회사 → 사람 펼칠 때 불러옴 · 마스터 쓰기 403 · 프로젝트 고르기 목록 세 층 · 흠 1(일위대가 뿌리 바꾸면 구조물 조합으로 튐) → sub6 고침 → 재확인 통과 · 검증 계정 · 회사 · 프로젝트는 사용자 확인용으로 남김(정리는 지시 때)
- 한계: ORCA 진짜 마우스가 새 탭에 안 닿음(JS 클릭으로 대체) · 데스크탑 오르카 보고 통로 끊김(화면으로 읽음)
## 29. 시스템 설정 다듬기 — 회사 고르기 · 좌측 나무 · 결정 목록 보탬 · 산림 1~3장 (사용자 9-30 오후)
- 사용자: 여러 회사 · 여러 사람을 나무 하나에 다 넣으면 길고 복잡 — 시스템 관리자가 남의 회사를 보는 일은 AS · 기술지원 때만. 대신 「시스템 설정」 줄 오른쪽에 **회사 고르기** 라벨 → 고른 회사의 시스템 설정과 그 아래 컨테이너(프로젝트 · 임시 보관함 · 사용자 관리 · 가입 요청 · 회사 관리)를 그 회사 것으로 보고 고침. 시스템 관리자 회사 = 캐미팩토리(1).
- 정함(브레인): 고른 회사 = sessionStorage `aislo.adminCompany`(회사 id · 없으면 자기 회사) + M02 해시 `&company=<id>` · 회사 관리자에게는 회사 고르기 없음 · 회사 관리자의 남의 개인 층은 나무 대신 「사람 고르기」 라벨(같은 줄 · 같은 부품) · 나무의 뿌리 셋은 좌측 패널의 **층 단추 셋**(마스터 · 회사 · 개인)으로 바꾸고 나무는 고른 층 하나만 좌측에 · 찾기 칸은 상세 쪽(M01 표 컨테이너처럼).
- [x] 29-1 대시보드(sub8) — 시스템 관리자 화면에서 「시스템 설정」을 리소스 현황 **아래** · 「시스템 설정」 줄 오른쪽에 회사 고르기 라벨(시스템 관리자만 · 기본 자기 회사) · 고르면 프로젝트 · 임시 보관함 · 사용자 관리 · 가입 요청 · 회사 관리 컨테이너가 그 회사 것으로(읽기 + 고치기 · 서버 라우터에 `company_id` 인자 · 시스템 관리자만 허용) · 카드 해시에 `&company=` 실림 · 시험 · ORCA 세 역할
- 검증완료(sub8 · 59a4dd4e · 알약 e7d8ea80 · ORCA 5183 탭 1): 차례 리소스 현황 → 시스템 설정 → 프로젝트 · 회사 알약 = 시스템 설정 · 프로젝트 · 사용자 관리 · 가입 요청 · 회사 관리 제목 오른쪽 다섯(공용 ui-tag) · 누르면 회사 메뉴(공용 createMapContextMenu · 알약 4px 아래 · 밖 누르면 닫힘 · 한 번에 하나) · 가입 요청 알약에서 골라도 다섯 모두 바뀜 · 누름이 접힘으로 안 샘 · 기본 캐미팩토리(1) 프로젝트 14 · 사용자 4 · 회사 표 1줄 → 브레인검증회사(3) 고름 = 저장값 3 · 프로젝트 1 · 사용자 2(brain.admin · brain.user) · 가입 요청 0 · 회사 표 1줄 · 카드 해시 `&company=3` · 팀원 안내 메일 요청 `?company_id=3`(가로채 보내지 않음) · 서버 회사 관리자 = 자기 회사 200 · 남의 회사 403 · 일반 = 403 · 회사 관리자 · 일반 화면 고르기 없음 · 해시에 company 없음 · 임시 보관함은 사람 것이라 그대로(브레인 확정) · 라우터 700줄 넘어 Scope · Router_Assets 로 나눔 · 저장값 지워 되돌림 · 시험 13 통과 · typecheck 통과 · 검증 대기
- [x] 29-2 마스터 템플릿(sub7) — 좌측 패널: 「일위대가 라이브러리」 · 「구조물 조합」 아래 층 단추 셋(마스터 · 회사 · 개인 · 권한 없는 층은 「읽기」 표시) → 고른 층의 나무를 좌측 패널에(상세에서 뺌) · 상 · 하위가 잘 보이게 나무 모양 다듬기(밖의 흔한 방식을 먼저 살핌: 들여쓰기 안내선 · 접기 화살 · 폴더 · 항목 아이콘 · 부모 글 굵기 · 고른 줄 배경) · 찾기 칸은 상세 위쪽 · 회사 → 사람 펼침 제거 · 해시 `company=`(시스템 관리자) · 「사람 고르기」 라벨(회사 관리자 · 시스템 관리자) · 시험 · ORCA 세 역할
- 검증완료(sub7 · cd2ee566): 시험 m02 전체 · item_picker 177 초록 · typecheck · ORCA 5182 세 계정 로그인 — 시스템 관리자(자기 회사 · company=3 → 「회사 · 읽기」 · 사람 고르기 브레인사용자 → owner=3/15 읽기만 · 메뉴 없음 · 저장 숨김) · 회사 관리자(마스터 읽기 · 회사 수정 메뉴 · company=1 무시) · 일반(마스터 · 회사 읽기 · 사람 고르기 없음 · owners · 남의 나무 403) · 찾기 칸 = 상세 위 · 좌측 나무 거름 · 일위대가 나무 항목 → 상세 UP15-000001 열림(저장 안 함) · 나무 안내선 · 아이콘 · 폴더 굵게 수치 확인 · 검증으로 생긴 회사 관리자 빈 개인 층 뼈대 지움 · 검증 대기
- [x] 29-3 M01(sub6) — 자재표에 없는 34건은 검색어를 비움(억지 연결 없음) · 결정 목록(`docs/raw/M01_결정목록/결정목록.md`) 맨 아래 「자재표에 없는 품목」 절로 34줄 보탬(로직 키 · 재료 이름 · 단위 · 원문 절) · check_master · 계산전부 · 시험
- 검증완료(sub6 · opus high · 커밋 f7f4572f): 34건 중 33건 재료 줄 40개 검색어 비움(GF000181 둘 · GC000447~449 셋 · GC000216 ø740~1800 다섯 · GC000932 신주용접봉만) · GC000432 메탈리밍쉘 {규격} 은 그대로(BX 품목 있음 · NX 는 이미 후보 없음) · 빈 검색어는 전엔 구분 안 첫 품목으로 이어졌음(억지 연결) → 엔진이 빈 검색어 = 후보 없음 · 단가 없음 + 까닭 「자재표에 없는 품목」 · 고름은 그대로 · 검사 틀림 안 셈(master_pick · master_material · _틀.md 한 줄) · 로직 파일은 그 줄만 고침(다른 줄 모양 그대로) · check_master 틀 · 본문 · 로직 · 조합 0 · 단위 31(전과 같음 · 이 줄들 아님) · 계산전부 통과 1469 멈춤 0 · 결정 목록 맨 아래 34줄 · test_masterdata_check + test_m01_api 98 + 새 1 초록 · 검증 대기
- [x] 29-4 산림 1~3장 표 99개 대조(sub1 · 점검만 · 코덱스 방식 · tmp/M01_점검/sub1_3/ · 끝나면 브레인이 종합에 더함)
- 사용자 고침(9-30 17:25): 회사 관리자에게 「사람 고르기」도 없음 — 회사 관리자의 M02 는 지금 그대로(개인 뿌리 아래 사람 목록 유지) · 회사 고르기는 **알약** — 고른 회사 이름을 컨테이너 제목 오른쫀 알약으로 · 누르면 등록된 회사 가운데 고름 · 회사를 따라 바뀌는 컨테이너(프로젝트 · 사용자 관리 · 가입 요청 · 회사 관리)마다 제목 오른쪽에 같은 알약 · 임시 보관함은 그대로.
- [x] 29-5 대시보드 알약(sub8) — 고른 회사 알약을 컨테이너 제목 **왼쪽 맞춤**(제목 바로 옆) · 알약 누르면 드롭다운이 아니라 **조회 후 선택**(찾기 칸 → 이름 · 사업자번호로 거른 목록 → 고름 · 회사 100개 넘어도 됨 · 공용 고르기 모달 꼴)
- 검증완료(sub8 · 9ed36efe · ORCA 5183 탭 1): 알약 다섯(시스템 설정 · 프로젝트 · 사용자 관리 · 가입 요청 · 회사 관리) 모두 제목 오른쪽 끝에서 16px · 알약 누름 = 회사 고르기 창(찾기 칸 포커스 · 처음 2곳 최근 등록 순 · 지금 회사 줄 표시) · 「브레인 0930」 → 1곳 · 없는 이름 → 0 · 줄 누름 → 저장값 3 · 프로젝트 1 · 사용자 2 · 회사 표 1 · 알약 다섯 모두 바뀜 · 「437-41」 Enter → 캐미팩토리(프로젝트 14 · 사용자 4) · Esc · 바깥 누름 닫힘 · 알약 누름이 접힘으로 안 샘 · 50줄 넘으면 「N곳 중 50곳」 안내(시험) · 공용 item_picker 는 구조물 항목 전용이라 B01 모달 꼴 새 파일 · 저장값 지워 되돌림 · 시험 15 통과 · typecheck 통과 · 검증 대기
- [x] 29-6 M02 좌측 · 찾기(sub7) — 층 단추 위 「일위대가 라이브러리」 · 「구조물 조합」 단추 없앰(컨테이너 제목이 이미 있음) · 층 단추 아래 나무의 맨 위 뿌리 줄(단추와 같은 이름)도 없앰 — 폴더 · 항목부터 바로 · 두 라이브러리 상세 화면의 찾기를 하나로 단순화: 찾기 칸 하나 · 띄어쓰기로 나눈 단어를 모두 담은 줄만(AND) · 이름 · 키 · 경로 · 구분 다 봄 · 같은 부품을 둘이 씀
- 검증완료(sub7 · c1ad11e8): 시험 m02 + item_picker 초록(찾기 AND 새 시험) · typecheck · ORCA 5182 세 계정 — 같은 이름 줄 단추 · 뿌리 줄 없음(폴더부터) · 「+」 = 쓰기 층만(시스템 마스터 · 회사 관리자 회사 · 일반 개인) · 읽기 층 숨김 · 「+」 · 빈 자리 오른쪽 클릭 메뉴 = 폴더 · 항목(조합) 더하기 · 일반 개인에 「+」로 폴더 더함 → 맨 위에 보임 → 지움(원래대로 · SP15-000001 그대로) · 찾기 두 낱말(「콘크리트 ㎡」 나무 · 목록 1 · 「브레인 측구」 1 · 없는 낱말 0) · 제목 펼치면 일위대가 화면 · 검증 대기
- 사용자 고침(9-30 18:10): 「사람 고르기」 없앰 — 시스템 관리자는 대시보드에서 고른 회사의 **회사 관리자처럼** M02 를 봄(회사 층 = 그 회사 · 「개인」 단추 = 그 회사 사람들의 개인 층을 **나무**로 · 회사 관리자와 같은 모양) · 29-6 에 포함.
## 30. 모달 높이 · 용어 · 여러 개 고르기 · 층 사이 복사 · 「+」 자리 (사용자 9-30 저녁)
- 정함(브레인): 모달은 세로 가운데 대신 **위에서 고정 거리**(찾기 칸이 안 움직임 · 공용 `ui_template_modal.css` + 따로 backdrop 을 가진 모달 전부) · 용어는 「더하기」 → 「추가」(보이는 글 전부 · 다른 동사는 사용자 결정 뒤) · 여러 개 고르기 = Ctrl+클릭(하나씩) · Shift+클릭(범위) · 고른 줄 배경 · 층 단추 줄에 「N개 고름」 · 오른쪽 클릭 메뉴가 고른 것 전부에 적용 · 복사는 **읽을 수 있는 층 어디서나** → 붙여넣기는 **쓸 수 있는 층에만**(권한 규칙 = M02_Layer_Access 그대로) · 복사본은 대상 층의 새 키(SC/SP · UC/UP) · 본뜬키 = 원본 키 · 같은 이름이면 「이름 (2)」 · 폴더 복사는 안의 것까지 · 옮기기는 같은 층 안에서 여러 개 한 번에 · 단축키 Ctrl+C · Ctrl+V · Delete.
- [x] 30-1 (sub8) 모달 위 고정(전역) · 「더하기」 → 「추가」 33곳(스프레드시트 · M01 · M02 · 공용 표) · 시험 글 맞춤
- 검증완료(sub8 · 05418307 · ORCA 5183 탭 1): 공용 .ui-modal = 최대 높이 기준 가운데 자리에 윗변 고정(큰 창 --modal-max) · 따로 둔 B01 · M01 로직 고르기 · M01 조달 찾기도 같게 · 가운데 그대로 = 불러오는 중 · 공용 확인 창 · B03 확인 · B05 노선 편집(고정 높이) · 스프레드시트 메모 · 회사 고르기 창 목록 2→1→0→2 에 찾기 칸 y 192.9 그대로(창 윗변 107 = 10vh) · 구조물 고르기 모달 나무 63→1→63 에 찾기 칸 y 88.7 그대로(윗변 32) · M02 나무 오른쪽 클릭 메뉴 「폴더 추가 · 항목 추가」 · 「+」 제목 「맨 위에 폴더 · 항목 추가」 · 보이는 글 25곳 바꿈(안쪽 명령 이름 시트더하기 · 주석 · 「더함」 같은 다른 동사는 그대로) · 시험 10 통과 · typecheck 통과 · 검증 대기
- [x] 30-2 (sub7) 공용 나무(TreePanel) 여러 개 고르기 · 복사 · 붙여넣기 · 여러 개 옮기기 · 지우기 부품(콜백으로) + 구조물 조합 쪽 서버(여러 항목 · 폴더를 층 사이 복사 — 파일 structure · area · material · inputs 까지 · 여러 개 옮기기) · 층 단추 줄 「+」 오른쪽 맞춤
- 검증완료(sub7 · 0f510eb5): 시험 m02 + 새 test_m02_tree_paste · 고르기 규칙 Node 시험 초록 · typecheck · ORCA 5182 — 일반 B: 회사 층(읽기) Ctrl 클릭 2개 「2개 고름」 · 메뉴 = 복사만 · 빈 자리 메뉴 없음 · 회사 붙여넣기 서버 403 → 개인 빈 자리 「붙여넣기 (2개)」 → 폴더 + SP15-000002(본뜬 SC3-000001 · 세 파일) · 회사관리자 A: 동료 개인(읽기) Shift 범위 3개 복사 → 회사 「+」 붙여넣기 → 「브레인검증_배수 (2)」 · SC3-000002/3 → 여러 개 옮기기(제 안 폴더는 고를 곳에서 뺌) → Delete 여러 개 지우기 → 원래대로 · 「+」 오른쪽 끝 · 만든 것 모두 지움(검증 자료 그대로 · 키 번호만 올라감)
- sub6 에게: `createTreePanel({ api: { fetch, edit, many?, paste? }, clipKind: "일위대가" })` — `many(layer, {op: "move"|"delete", 대상: TreeRef[], 새경로?}, 판, owner)` · `paste(layer, owner, clip: TreeClip, dest)` · 없으면 그 메뉴 숨김 · 서버 모양은 `POST /layers/{층}/tree`(대상) · `POST /layers/{층}/items/paste` 참고
- 더함 검증완료(sub7 · d1675e62): 「〇〇로 복사」(일반 B 회사 읽기 층 메뉴 = 복사 · 개인으로 복사 → 개인 맨 위 SP15-000003) · 끌어다 옮기기(개인 항목 → 폴더 줄 · 놓을 자리 표시 · 읽기 층 끌기 없음) · 부품에 `copyTo` 옵션(sub6 도 같은 모양) · 만든 것 지움
- [x] 30-3 (sub6 · 30-2 부품 뒤) 일위대가 조합 쪽 서버(여러 조합 · 폴더를 층 사이 복사 · 여러 개 옮기기) + Labor 화면에 30-2 부품 연결
- 검증완료(sub6 · opus high · 서버 c0a76b84 · 화면 4fa49e30 · sub7 d1675e62 합침 · ORCA 5181 탭 하나): 일반 B(15) 마스터 조합 셋 Ctrl 고름 → 「3개 고름」 · 메뉴 복사 · 개인으로 복사(회사로 복사 없음) → 개인 층 빈 자리 붙여넣기(3개) → UP15-000002~004 · 본뜬키 UA000002~004 · 로직 수 같음 · 회사 층 = 붙여넣기 · 고치기 메뉴 없음 · 붙여넣기 API 403 · 회사관리자 A(14) 마스터 둘 → 「개인으로 복사」(층 그대로 · UP14-000001~002) → 개인에서 「회사로 복사」 → UC3-000002~003(본뜬키 UP14) → 회사에서 둘 고름 「옮기기 (2개)」 → 브레인검증 › 배수 · 「지우기 (2개)」 · 서버 시험 13(붙여넣기 새 키 · (2) · 403 · 404 · 409 · 폴더 · 깊이 422 · 여러 옮기기 · 지우기 한 번 · 하나 막히면 안 씀 · 마스터 붙이기 본뜬키 UA 만) · 연결 시험 · typecheck · 만든 것 지움 · 회사 3 · 개인 15 조합 파일 바이트 그대로 되돌림 · A 개인 층 폴더(검증 때 생김) 지움 · 마스터 일위대가 파일 안 건드림 · 검증 대기
- [x] 30-4 (sub7) 층 단추 다시 누름 — 이미 켜진 층 단추를 다시 눌러도 그 층의 목록(항목 · 조합 목록 화면)으로 돌아감(항목 하나를 열어 둔 상태에서도) · 일위대가 · 구조물 조합 둘 다 · 저장 안 한 고침이 있으면 기존 저장 물음 그대로
- 검증완료(sub7 · d1675e62): 일위대가 — 조합 UP15-000001 연 채 켜진 「개인」 단추 → 조합 목록 · 구조물 — 면적산출 상세(SA-000001) 연 채 켜진 단추 → 「구조물 조합」 표 · 저장 안 한 고침 물음 그대로(confirmLeave · BackAsk) · 시험 한 건
- 사용자 더함(9-30 19:00): 오른쪽 클릭 「복사」 · 「붙여넣기」 + 「〇〇로 복사」(〇〇 = 쓸 수 있는 층 이름 — 「개인으로 복사」 · 「회사로 복사」 · 시스템 관리자는 「마스터로 복사」 · 그 층 맨 위에 바로 붙음 · 층을 바꾸지 않아도 됨) · 단계(폴더) 옮기기는 끌어다 놓기 + 오른쪽 클릭 둘 다.
- [x] 30-5 (sub6 일위대가 · sub7 구조물) 상세 화면 「새 조합」 단추를 제목(「일위대가 라이브러리」 · 「구조물 조합」)과 같은 줄 오른쪽 끝으로 · 구조물 조합에도 같은 자리 「새 항목」(지금 층이 쓸 수 있을 때만 · 나무 「항목 추가」와 같은 동작) · 일위대가 조합 목록에 줄 사이 선(공용 표 모양과 같게)
- 검증완료(sub6 일위대가 몫 · 3ec501ab · ORCA 5181): 「새 조합」 제목 줄 오른쪽 끝 — 단추 가운데 y 96 = 제목 가운데 y 96 · 단추 오른쪽 x 1451 = 제목 줄 오른쪽 1451 · 읽기 층(일반 B 마스터) 단추 없음 · 개인 층 보임 · 누르면 빈 조합(저장 안 함) · 조합 목록 줄 border-bottom 1px · 머리 줄 고정(공용 ui-general-block__table) · 시험 · typecheck · 구조물 「새 항목」은 sub7 몫 · 검증 대기
- 구조물 쪽 검증완료(sub7 · dc725012): 「구조물 조합」 제목 줄 오른쪽 끝 「새 항목」(공용 `newItemButton` · `m02-main__new` — sub6 「새 조합」도 이것으로) · ORCA 5182 세 계정 — 제목과 같은 줄 · 오른쪽 끝(틈 0) · 읽기 층 없음(일반 마스터 · 회사 / 회사관리자 마스터) · 쓰기 층 있음(일반 개인 · 회사관리자 회사 · 시스템 마스터 · 회사) · 일위대가 화면에선 숨김 · 누르면 「항목 추가」 창 → 맨 위(SP15-000004) · 폴더 고른 채 → 그 안(SP15-000005) · 만든 것 지움 · 시험 한 건
- [x] 30-6 (sub7) 불러오는 중 표시 — 일위대가 조합 · 구조물 조합에서 나무 · 목록 · 표 · 상세를 불러오는 동안 그 **컨테이너 안**에 불러오는 중 표시(공용 작은 회전 표시 + 「불러오는 중」 · 화면 전체 잠금 아님 · 0.3초 넘을 때만 보임 · 실패하면 그 자리에 까닭 글 + 다시 불러오기) · 층 단추 바꿈 · 회사 · 사람 바꿈 · 처음 열기 모두
- 검증완료(sub7 · 25cf716a): 공용 `ui_template_loading`(showLoading · loadingError) · 시험 test_ui_loading(0.3초 가짜 시계 · 실패 글) + m02 초록 · typecheck · ORCA 5182 fetch 를 2.5초 늦춤 — 층 단추 바꿈 뒤 상세 칸 · 나무 칸 둘 안에 「불러오는 중...」(화면 잠금 없음) → 끝나면 사라짐 · 늦춤 없으면 안 보임 · 실패 흉내 → 그 자리 「불러오지 못함 — 까닭」 + [다시 불러오기] → 누르면 복구 · 조합 상세도 칸 안 표시 · ORCA 에서 setTimeout Illegal invocation 흠을 잡아 고침
- [x] 30-7 (sub4) 구조물 조합 표에서 No · 측점 열도 숨김(비고 · 전구간 · 합계와 같은 방식 — 관리 화면 보기만 · 양식 파일 · B08 쪽 그대로 · 틀고정 열 수 맞춤 · [저장] 때 저장본 것 되끼움)
- 검증완료(sub4 · 1b908d3c · ORCA 5179): 세 계정(시스템 관리자 마스터 · 회사관리자 회사 · 일반 개인) 표 머리에 NO · 측점 없음 · [저장] 뒤 파일 열 차례 그대로(마스터 no · sta · memo · 틀고정 2 · 전구간 · 합계 줄 남음) · 시험 항목 하나 넣어 첫 항목 열이 틀고정 안 됨(2 → 0) · 저장 뒤 no · sta · item1 · memo · 틀고정 2 · 만든 것 되돌림(층 폴더 백업과 같음) · 시험 test_m02_combo_screen · typecheck · 검증 대기
## 31. 구조물 조합 상세 — 표 이름 고침 · 항목 추가 입력 · 카드 2×2 · 미리보기에서 기본 수정 (사용자 9-30 20:00)
- 정함(브레인): 단위 행은 표에서 숨김(저장값은 B08 몫) · 항목 추가 창은 **구조물 종류**(맨 위 폴더 — 있는 것 고름 또는 새로) + **이름** + **일위대가**(세 층 조합에서 고름 · 권한대로 읽기 가능한 것) · 단위 안 받음 · 표 머리의 이름(종류 · 분류 칸)은 두 번 눌러 고치면 나무 이름도 같이 바뀜(한 정본 = 나무) · 키가 줄바꿈 안 되게 열 너비 자동 · 좌측에서 고른 항목은 표에서 **마지막 분류 칸**을 강조 · 표 위 옛 안내글 없앰 · 항목을 고르면 카드 넷(도면 정보 · 면적산출 · 재료산출 · 선택 입력)을 2행 2열 · 키를 조금 늘림 · 넘치면 스크롤 · 표는 접힘 · 카드는 미리보기지만 기본 수정: 도면 = 메뉴 없이 단축키로 그리기 · 고치기 / 엑셀(면적 · 재료) = 메뉴 없이 수식 입력 줄 보임 · 칸 고침 + 아래 연결 알약 줄(입력 연결) + 재료산출은 자재 조합 추가 · 카드 고침은 카드 안 [저장](정본 = 그 항목 파일 · 전체 편집기와 같은 저장 길).
- [x] 31-1 (sub4) 표 — 이름 칸 두 번 눌러 고침 → 나무 이름 바꿈 · 단위 행 숨김 · 열 너비 자동(키 줄바꿈 없음) · 좌측 고름 = 마지막 분류 칸 강조 · 옛 안내글 없앰(구조물 조합 표만)
- 검증완료(sub4 · f7c91f2f · ORCA 5179): 세 계정 — 회사관리자 회사 · 일반 개인에서 표 머리 이름 칸 두 번 누르기(항목 · 폴더) · F2 로 고침 → 나무 이름 바뀜(API 경로 확인) · 같은 이름은 「이미 있는 항목」 막음 안내 · 일반의 회사 층 · 읽기 층은 머리 고침 안 열림 · 세 층(시스템 관리자 마스터 포함) 단위 줄 0 · 안내글 없음 · 번호 줄 높이 26(줄바꿈 없음) · 나무에서 고르면 가장 깊은 이름 칸 강조 · 만든 것 되돌림(회사 층 = 백업 · 개인 이름 되돌림 — 다른 창 31-2 항목은 그대로) · 시험 test_m02_combo_table 3 · combo_screen · typecheck · 검증 대기
- [x] 31-2 (sub7) 항목 추가 창(나무 「항목 추가」 · 「새 항목」) = 종류 + 이름 + 일위대가 · 카드 넷 2×2 · 높이 늘림 · 스크롤 · 표 접힘
- 검증완료(sub7 · b9819117): 시험 m02(항목 추가 서버 · 창 · 격자 · 접기) + 옛 단위 필수 시험 31 정함으로 · typecheck · ORCA 5182 — 일반 개인 「새 항목」 창 = 종류 · 이름 칸 둘(단위 없음) · 빈 칸 안내 둘 · 종류 목록(있는 폴더) · 폴더 고른 채면 종류 칸 없이 「넣을 곳」 · 일위대가 고르기 「측구 조합」 두 낱말 → UC3-000001 → 항목 경로 [종류, 이름] · 일위대가 저장 · 단위 없음 · 회사관리자 회사 고르기 = 마스터 · 회사 조합 · 시스템 마스터 = 마스터만 · 카드 넷 2×2(각 360px) · 상세 칸 스크롤 · 제목 눌러 표 접힘/펴짐(카드 그대로) · 만든 것 지움 · 표 접기는 attachCollapsible 대신 제목 토글(표를 감싸면 전체 편집기 :has(> .m02-main__host) 규칙이 깨져서)
- [x] 31-3 (sub8) 엑셀 카드(면적 · 재료) 미리보기 수정 — 메뉴 없음 · 수식 입력 줄 · 칸 고침 · 연결 알약 줄 · 재료산출 자재 조합 추가 · 카드 [저장]
- 검증완료(sub8 · 13c6b581 · ORCA 5183 탭 1 · 시스템 관리자 개인 층 임시 항목 「sub8임시 카드」 만들어 확인 뒤 지움): 두 카드 ss--preview(도구 모음 · 메뉴 없음 · 수식 입력 줄 있음) · 칸 입력 → Enter · 방향키 · Ctrl+Z/Y · F2 편집 · 면적 A1=7 · B1 =A1*2 [저장] → 서버 문서 같음 · 면적번 유지 · 재료 「+ 자재 추가」 → 알약 · 아래 자재 조합 판 줄 + [적용] · [되돌리기] → 알약 눌러 A1 연결 → [저장] → 서버 연결 A1 · 재료번 유지 · 알약 오른쪽 클릭 [연결 풀기] · 자재 추가 창 카드 안에 맞음 · 저장 안 한 채 다른 항목 → 물음 → 취소면 머묾 · [재료산출 수정] → 기존 물음 → 전체 편집기 그대로(도구 모음 있음) · 고르기 모달 카드는 보기만 그대로 · 시험 57 통과 · typecheck 통과 · 검증 대기
- [x] 31-4 (sub6) 도면 카드 미리보기 수정 — 메뉴 없음 · 단축키로 그리기 · 고치기 · 되돌리기 · 카드 [저장]
- 검증완료(sub6 · opus high · 6ad43ed7 · 합침 f1b464e6 · ORCA 5181 탭 하나): 부품 = openwebcad iframe(cad_host) · CAD 앱 안 고침 — 고칠 수 있는 카드는 보기만 끄고 제목줄 · 리본 · 패널 · 상태줄 숨김(같은 출처 스타일) · 일반 B 개인 층 항목 「B 개인 배수관」: 머리 「? · 저장(꺼짐) · 도면 수정」 · 단축키 L Enter + 두 점 = 선 1(저장 켜짐) · Ctrl+Z 0 · Ctrl+Y 1 · 카드 [저장] → 파일 Line(도번 SD-000001 그대로 · 저장 꺼짐) · C Enter 원 + Ctrl+S → 파일 Line · Circle · ? = 단축키 13줄 칸 안 · 고친 채 「회사」 누름 → 「저장 안 한 고침…」 물음 · 취소 = 그대로 · 확인 = 넘어감 · 파일 안 바뀜 · 회사 층(B 읽기) = 보기만(도구 없음 · readOnly · viewOnly) · 회사관리자 A 회사 층 · 시스템 관리자 마스터 = 고치기 카드(저장 안 함) · 개인 15 구조물 파일 바이트 되돌림 · 회사 3 파일 그대로 · 카드 자동백업 칸 지움 · 마스터 파일 안 건드림 · 시험 53(새 test_m02_drawing_card 포함) · typecheck · 검증 대기 · 알림: 같은 브라우저 다른 창이 localhost 에 로그인하면 세션이 바뀜(쿠키는 포트를 안 가림)
- [x] 31-5 (sub7) 대시보드 카드로 M02 에 들어오면 좌측 「일위대가 조합」 · 「구조물 조합」 컨테이너 둘 다 펼친 상태 · 항목을 끌어 폴더로 옮긴 뒤 바깥(맨 위) 놓을 자리 강조가 안 사라지는 흠(dragend · drop · dragleave 에서 강조 지움)
- 검증완료(sub7 · fb56d7c2): 시험 한 건 + m02 초록 · typecheck · ORCA 5182 일반 계정 — 들어오면 「일위대가 조합」 · 「구조물 조합」 둘 다 펼침 · 항목을 폴더로 끌기: 빈 자리 위 = 칸 강조 → 폴더 위 = 폴더만 강조 → 놓은 뒤 강조 0(나무 칸 자신 포함) · 끌기 코드 TreePanel_Drag 로 나눔(700줄) · 만든 폴더 지우고 항목 제자리
- [x] 31-6 (sub7) 구조물 조합 카드 넷 높이 더 늘림(360px → 화면 높이에 맞춰 크게 · 예 min(640px, 70vh))
- 검증완료(sub7 · 2f7acff7): 시험 한 줄 + m02 초록 · typecheck · ORCA 5182(창 높이 1069) — 카드 넷 각 640px(min(640px, 70vh)) · 도면 CAD 칸 501 · 면적 격자 576(카드 채움) · 재료 격자 512 + 자재 조합 판 135 → 카드 안 스크롤 · 상세 칸 스크롤 유지 · 엑셀 격자 높이 0 이던 흠 함께 고침
- [x] 31-7 (sub7) 카드 넷 공용 틀(사용자 9-30 21:05) — 도면 정보 · 면적산출 · 재료산출 · 선택 입력(관리 화면 · 고르기 모달 값 카드까지)을 공용 카드 틀 하나로
- 정함(브레인): 머리 = 제목 줄(h3 · 오른쪽 단추 자리) + 한 줄 부제(번호 · 항목 이름 · 넘치면 말줄임) · 「〇〇 수정」 = 빈 단추(ghost sm) 한 모양 · [저장] = 고칠 수 있는 카드에서 늘 보임 · 고쳐야 켜짐(filled sm) · 카드 안에 초점이 있으면 Ctrl+S · 저장 알림 글 한 벌(「저장했음」 · 「저장 못 함 — 까닭」 · 「그 사이 바뀜 — 다시 읽음」) · ? = 단축키가 있는 카드(도면 · 엑셀)만 · 엑셀 ? 는 시트 단축키 · 불러오는 중 = 네 카드 모두(공용 showLoading) · 실패 = 카드 안 글 + [다시 불러오기](토스트 안 씀) · 비었음 글 한 모양 · 저장 안 한 표시 = 제목 옆 점(●) + 페이지에 같은 길(onDirty)로 알림 · 다른 항목 · 페이지 떠날 때 물음 한 번(어느 카드든 고침이 있으면) · 선택 입력은 [저장] 없이 위 [저장]과 함께(지금대로) · 겉으로 자리 · 동작은 위 정함 말고는 그대로
- 검증완료(sub7 · bcb1c725): 공용 틀 M02_MasterTemplete_CardShell · 시험 m02 + item_picker 초록(새 test_m02_card_shell · 옛 모양 시험 맞춤) · typecheck · ORCA 5182 일반 계정 — 네 카드 각 640px · 제목 줄 오른쪽 끝 단추(? · 저장 꺼짐 · 〇〇 수정) · 부제 번호 · 이름 · 도면 L 선 → 점 ● · [저장] 켜짐 → CAD Ctrl+S → 「저장했음」 · 점 지움(파일 원래대로 되돌림) · 면적 칸 고침 → 점 → 다른 항목 누름 → 물음 한 번 → 확인 뒤 두 번째 물음 없음 · 선택 입력 불러오는 중 → 실패 흉내 → 카드 안 까닭 + [다시 불러오기] → 복구 · 고르기 모달 = [저장] · ? 없음 · 값 카드 [선택 입력 수정] · 만든 항목 지움 · 줄 수 = 카드 셋 1171 → 1115 + 새 틀 158