From bc7b9e3a48f024ce333b213b90099b3a796560b2 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 3 Sep 2026 20:49:25 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06):=20=EC=9C=A0=ED=86=A0=EA=B3=A1?= =?UTF-8?q?=EC=84=A0=20=EC=98=81=EC=97=AD=20=EB=88=84=EB=9D=BD=20=E2=80=94?= =?UTF-8?q?=20=EC=9E=AC=EA=B3=84=EC=82=B0=20=EA=B2=B0=EA=B3=BC=EC=99=80=20?= =?UTF-8?q?=EA=B3=84=ED=9A=8D=EC=84=A0=20=EC=A0=95=EB=B3=B8=EC=9D=B4=20?= =?UTF-8?q?=EC=96=B4=EA=B8=8B=EB=82=98=EB=8D=98=20=EA=B2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 두 곳이 같은 뿌리였음. 브라우저 재계산은 **편집이 반영된 계획고**로 횡단 설계를 만드는데 `design_profiles` 는 저장분 그대로라 두 값의 기준이 갈렸음. 1. 재계산 창구가 방금 푼 계획선을 **공유 캐시에도 얹도록** 함 (`detail.longitudinal.design_profiles`). 이게 없으면 낡음 판정이 영원히 참이 되어 B06 유토곡선이 통째로 빈 채로 남았음(사용자 보고). `profile_alignment`(base_pvi)는 건드리지 않음 — 편집 델타의 기준선이라 편집분을 구워 넣으면 이중 적용됨. 2. B06 진입 정합이 **미저장 세션 편집을 못 보고 건너뛰던** 것. 서버에서 갓 받은 저장분 끼리는 늘 일치해 「낡지 않음」이 되는데, B05가 세션에 남긴 편집은 그 안에 없음. 세션 초안이 있으면 판정을 건너뛰고 무조건 맞추도록 함 — 재계산은 브라우저 안에서 끝나 값이 쌈. 화면 검증(5174, 같은 시점 비교): 수정 전 — B05 절토 4,774.1㎥ / 성토 16,715.5㎥, B06 절토 4,515.0㎥ / 성토 14,857.5㎥ 수정 후 — 양쪽 모두 절토 4,774.1㎥ / 성토 16,690.7㎥ (일치) B06 유토곡선 영역도 곡선이 다시 그려짐(문구 없음). 전체 테스트 183건 통과, `tsc --noEmit` 통과. Co-Authored-By: Claude Opus 5 (1M context) --- B06_Section/B06_Section_Cross_Refresh.ts | 11 ++++++++++- B06_Section/B06_Section_UI_Page.ts | 10 ++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/B06_Section/B06_Section_Cross_Refresh.ts b/B06_Section/B06_Section_Cross_Refresh.ts index f6ebbf33..28dee239 100644 --- a/B06_Section/B06_Section_Cross_Refresh.ts +++ b/B06_Section/B06_Section_Cross_Refresh.ts @@ -39,7 +39,7 @@ import { planElevationAt, toAlignmentBase, } from "../B05_Profile/B05_Profile_UI_Profile_Alignment"; -import { readAlignment } from "../B05_Profile/B05_Profile_UI_Profile_Data"; +import { readAlignment, toDesignProfile } from "../B05_Profile/B05_Profile_UI_Profile_Data"; /** 계획선 편집 델타 — B05 `AlignmentEdits`와 저장분 `profile_alignment.edits`가 같은 모양이다. */ export interface CrossRefreshEdits { @@ -118,6 +118,15 @@ function refreshLocally(input: CrossRefreshInput): number[] | null { station_offsets: edits.station_offsets ?? {}, curve_radii: edits.curve_radii ?? {}, }); + // 방금 푼 계획선을 **공유 캐시에도 얹는다**. 여기서 만드는 횡단 설계는 편집이 반영된 + // 계획고 기준인데 `design_profiles` 만 저장분으로 남으면 두 값의 기준이 어긋나, 낡음 + // 판정이 영원히 참이 되어 유토곡선이 빈 채로 남는다(2026-09-03 사용자 보고: B05 편집 중 + // 문구만 뜸 → B06 유토곡선 영역 누락). `profile_alignment`(base_pvi)는 **건드리지 않는다** + // — 편집 델타의 기준선이라 편집분을 구워 넣으면 다음 편집에서 이중 적용된다. + detail.longitudinal.design_profiles = [ + toDesignProfile(alignment, detail.longitudinal.design_profiles?.[0]), + ]; + const rockOffsets = readRockBoundarySession(projectId, input.routeId) ?? {}; const rockDefault = readRockBoundaryDefault(projectId); diff --git a/B06_Section/B06_Section_UI_Page.ts b/B06_Section/B06_Section_UI_Page.ts index 72cf6adf..7cd9fa6a 100644 --- a/B06_Section/B06_Section_UI_Page.ts +++ b/B06_Section/B06_Section_UI_Page.ts @@ -289,9 +289,15 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { */ async function reconcileStaleDesigns(): Promise { if (!sectionDetail || !projectId || currentRouteId === null) return; + const draft = readAlignmentDraft(currentRouteId); // 낡음 판정은 B05와 **같은 규칙** 하나뿐이다(공용 판정 — 계획고 어긋남 + // 옛 암 2단계 필드 누락). 조건이 갈리면 같은 데이터가 두 화면에서 다른 값이 된다. - if (!hasStaleDesigns(sectionDetail)) return; + // + // 다만 **미저장 세션 편집이 있으면 판정을 건너뛰고 무조건 맞춘다**. 서버에서 갓 받은 + // 저장분끼리는 늘 일치해 「낡지 않음」으로 나오는데, B05가 세션에 남긴 편집은 그 안에 + // 없어 B06이 재계산을 통째로 건너뛰었다 — 같은 시점에 B05 절토 4,774.1㎥ ↔ B06 + // 4,515.0㎥ 로 갈렸다(2026-09-03 실측). 재계산은 브라우저 안에서 끝나 값싸다. + if (!draft && !hasStaleDesigns(sectionDetail)) return; // 진입 정합은 화면을 잠그지 않는다 — 카드가 도착하는 대로 조용히 갱신된다 // (CLAUDE.md 5장). try { @@ -303,7 +309,7 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { }; } | undefined; - const edits = readAlignmentDraft(currentRouteId) ?? { + const edits = draft ?? { station_offsets: alignment?.edits?.station_offsets ?? {}, curve_radii: alignment?.edits?.curve_radii ?? {}, };