- `docs/` 를 .gitignore 에서 빼 git 추적 대상으로 전환 (위키·완료 이력·검증 기록) - `docs/raw/PLAN.md` · `docs/raw/OWNERS.md` 를 저장소 최상위로 이동 후 .gitignore 에 등록 — 창끼리 공유하되 저장소에는 안 올리는 장부 - 살아 있는 경로 참조 7개 파일 정정 (아카이브 107건은 그때 사실이라 그대로 둠) - graphify 날짜별 산출물(`docs/wiki/graphify-out/20*/`) 제외 — `graphify update` 가 다시 만듦 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.0 KiB
B03/B05 초기값 스냅샷 기반 초기화 완료 아카이브
- 완료일: 2026-08-29
- 상태: 사용자 검증 완료
- 검증:
docs/raw/verification/2026-08-29_verify_initial_snapshot_reset.md - 검증 방식: 사용자 실무 검증 채택, Codex 2차 교차검증 생략
완료 범위
초기값 스냅샷 기반 [초기화] (2026-08-29 구현 완료 — 검증 대기)
배경 — 현행 [초기화]는 복원이 아니라 재생산이다. DELETE FROM routes 뒤
run_auto_design_chain()을 처음부터 다시 돌린다(B05_Profile_Router.py:608).
초기값을 콕 집어 부를 수 없는 이유는 두 가지다.
routes에 초기값/변경값 구분이 없다(001_create_schema.sql:284—status는 DRAFT/CONFIRMED/ARCHIVED뿐).- [저장]·[확정]이 새 행을 만들지 않고 최신 행을 제자리 갱신한다
(
confirm_latest_route→confirm_route(connection, latest["id"])). 종단·횡단 정본 파일도 덮어쓴다. 초기 상태가 물리적으로 남지 않는다. - 게다가 현행 초기화는 DB만 지우므로
structures.json·edits/pipe_points.json은 살아남아, 재계산 결과가 초기값과도 다르다(구조물 측점이 편집분에서 파생).
사용자 확정(2026-08-29) — 초기연산 결과를 초기값으로 영구 보존하고, [초기화]는 그 초기값을 되돌려 놓는다. 재계산하지 않는다.
설계
- 스냅샷 시점:
run_auto_design_chain()성공 직후 1회 (B03_FileInput_Service_Chain.py5)단계 뒤,return직전). 재계산 체인 (run_redesign_chain)에서는 만들지 않는다 — 초기값은 최초 1회뿐. - 저장 위치: 프로젝트 저장소 아래
initial_snapshot/(stage 폴더와 형제,PROJECT_STORAGE_LAYOUT_V2에는 넣지 않는다 — 워크플로 단계가 아니다). - 파일 스냅샷(그대로 복사):
B05_Profile/route/·B06_Section/longitudinal/·B06_Section/cross_sections/·{배수유역}/edits/(common_util_drainage_pipes.edits_dir). - DB 스냅샷:
routes1행 + FK 자식 4개(route_points·route_statistics·longitudinal_sections·cross_sections)를 JSON 덤프로 같은 폴더에 남긴다. 스키마상 route_id를 참조하는 표는 이 4개가 전부다(001_create_schema.sql:539~556). - 복원(=[초기화]):
DELETE FROM routes→ 덤프에서routes1행 INSERT(새 id) → 자식 4표를 새 route_id로 INSERT → 파일 스냅샷을 위 4개 경로에 덮어쓰기 →prune_corridor_files()로 주인 없는 코리도 정리. 자동 설계 체인 호출 없음. - 폴백: 스냅샷이 없으면(옛 프로젝트) 지금의 재계산 경로를 그대로 탄다.
체크리스트
common_util/common_util_initial_snapshot.py신설 —save_initial_snapshot()·load_initial_snapshot()·has_initial_snapshot(). 파일 복사와 JSON 덤프 한 벌만 담는다(700줄 제한 여유).B03_FileInput_Service_Chain.run_auto_design_chain()— 성공 반환 직전save_initial_snapshot()호출. 실패는 비치명적(로그만) — 체인 규약과 동일.B05_Profile_Router.reset_route_design()— 스냅샷이 있으면 복원 경로, 없으면 기존 재계산 경로. 응답 스키마(RouteResetResponse)는 유지하고restored: bool만 더한다.- 프론트
B05_Profile_Api_Fetch.RouteResetResponse에restored추가. 복원이면 분석용 긴 타임아웃이 필요 없으나, 폴백을 위해 타임아웃은 그대로 둔다. - 세션 캐시 정리는 현행
resetDesign()그대로 둔다(이미 B05·B06 양쪽을 비운다). - 정본 파일 덮어쓰기 확인 — 복원이
structures.json·edits/pipe_points.json을 스냅샷본으로 되돌리는지 테스트로 못박는다. 현행 초기화가 이 둘을 남겨 두는 것이 초기값 오염의 실체다(2026-08-29 사용자 확인). - 테스트
tmp/tests/test_initial_snapshot.py— ① 저장 후 파일·덤프 존재 ② 편집·저장 뒤 초기화하면 route 행 수 1, 종단 정본 파일이 스냅샷과 동일 ③ 스냅샷 없는 프로젝트는 재계산 폴백. - 화면 실측(2026-08-29) — 아래 「화면 실측」 절 참조.
확정 (2026-08-29 사용자)
- 자동저장은 폐지한다. 사용자 조작분은 세션 캐시에 담고 [저장]·[확정]에서만 영구저장소에 쓴다 — 별도 항목 「자동저장 폐지…」 참조.
- 스냅샷은 사용자 첫 접근 이전에 찍히고 그 뒤 읽기 전용이므로, 자동저장이 남아 있든 없든 초기값 자체는 오염되지 않는다.
- 현재 조작 속도는 불편하지 않다. 성능이 아니라 초기값 보전이 이 작업의 목적이다.
구현 메모 — 복원은 DELETE FROM routes와 같은 트랜잭션 안에서 끝낸다(지우기만 하고
실패하면 경로가 없는 프로젝트가 된다). 파일 복원은 트랜잭션 밖 asyncio.to_thread.
스냅샷 파일 트리는 폴더명을 B05_Profile__route처럼 평탄화해 담는다.
- 자체검증(2026-08-29) —
tmp/tests/test_initial_snapshot.py5 passed: ① 파일 4트리 + DB 덤프 촬영 ② 촬영 뒤 정본을 고쳐도 스냅샷 불변(읽기 전용 층) ③ 복원이 편집된pipe_points.json을 초기값으로 되돌리고 스냅샷에 없던 파일은 남기지 않음 ④ 자식 4표가 새 route_id로 다시 들어가고id열은 비워짐 ⑤ 스냅샷 없으면 None(재계산 폴백). ruff format·check 통과. 실제 DB·화면 왕복은 미검증 — 공용 브라우저 확인 필요.
화면 실측 — 진짜 초기값 재생산 겸 검증 (2026-08-29, 사용자 승인 후 실행)
배경: 검증 대상 프로젝트(c1bb453f…)는 기능 추가 전에 만들어져 initial_snapshot/이
없었고, [저장]이 정본을 덮어써 진짜 초기값이 남아 있지 않았다. 자동설계 체인은 계획노선
CSV + config 기본값으로 도는 결정적 절차이므로 편집 정본만 걷어내고 다시 돌리면 원래
나왔어야 할 값이 나온다 — 종전 [초기화]가 그걸 못 하던 이유가 정확히 structures.json·
edits/pipe_points.json을 안 지운 것이었다.
절차
- 백업 —
tmp/backup_before_initial/에 storage 152파일 +routes·자식 4표 덤프 (스크립트tmp/reconstruct_initial.py,backup/show단계). - 편집 정본 2개 삭제 — 자동 권한 검사가 파일 삭제·이동을 막아 사용자가 직접 지웠다.
- 공용 브라우저에서 B05 [초기화] 클릭(확인 모달 → 스냅샷이 없으므로 재계산 폴백).
결과
| 항목 | 초기값(route 102) | 직전 작업본(route 101) |
|---|---|---|
| 연장 | 350.11m | 350.11m (계획노선 CSV가 같으니 동일) |
| 횡단 측점 | 23 | 25 |
| 관 지점 | 4 | 6 |
| 구조물 | 0 (structures.json 없음) |
0 |
줄어든 측점 2 · 관 2가 곧 사용자가 손댔던 몫이다. 초기 관 배치는 전부 자동 산출이다 — 4+4.3 배수관(spacing) · 7+9.7 세월교(stream) · 10+0.9 BOX암거(spacing) · 13+15.7 배수관(spacing).
체인이 스냅샷을 스스로 떴다 — 따로 부르지 않았다. initial_snapshot/db.json에
routes 1 · route_points 135 · route_statistics 1 · longitudinal_sections 1 ·
cross_sections 23(route 102 · CONFIRMED · 350.11m), 파일 4트리(cross_*.json 23개 포함).
DB 값과 일치한다. 토스트 "초기 계산 상태로 되돌렸습니다." 확인, 10초 안에 완료.
남은 것
- 복원 경로(
restored=true)는 아직 미실측이다. 이번 클릭은 스냅샷이 없던 마지막 폴백 실행이었고, 그 실행이 초기값을 만들면서 동시에 촬영했다. 이제 스냅샷이 있으므로 다음 [초기화]가 복원 경로를 탄다 — 그때 route 행 재삽입·정본 파일 되돌리기·응답restored를 실측한다. - 현재 작업본 = 초기값(route 102). 직전 설계(route 101)는
tmp/backup_before_initial/에만 있다. 되살릴지 초기값 상태로 둘지는 사용자 판단.