인수인계 — GS 원주 단구 한샘 견적서 「복구하시겠습니까」 추적 (26.9.9 · ✅해결·종료)
✅ 결말 (26.9.9 후속 세션)
§1 의 결함 2개(app.xml ·
C{b})가 진짜 원인이었고, 그걸로 이미 고쳐져 있었다. NAS 에 올라가 있던 깨진 파일은 그 수정(build.py 10:09) 이전 산출물(10:05)이었다.🔴§3 의 이진탐색 표와 §4 의 「범인 =
fill_main/fill_sub」는 전부 무효다.bisect_stage.py가finalize()(=calcChain폐기)를 마지막 단계에서만 불러, 중간 산출물이 전부 낡은xl/calcChain.xml(1,547항목) 을 달고 나갔다. 행이 밀리고 수식이 지워진 뒤라 계산체인이 옛 좌표를 가리켰고 그게 Excel 복구 트리거였다._z_copyonlyOK /_z_copyfill깨짐도 calcChain 손상량 차이였을 뿐이다. ⛒모든 단계에 finalize 를 걸어 재측정 → pack→rename→clone→lay1~4→cover→hidden 9단계 전부 OK.재빌드한 정본: Excel 정상열림(mode 0) · 무수정(수식1553/병합466/도형1 이 정상화본과 동일) · verify 127/127 ·
_xlcheck0 ·xldiag0 · 신설sfcheck.py0. NAS 교체 완료(승인 후 삭제→재업로드, 왕복 sha256 일치). 8월 원본 무사.아래 원문은 기록용이다. §3·§4 는 따라가지 마라.
페페 보고: 엑셀이 「복구하시겠습니까」 + 「수식 참조 오류」를 띄운다. 작업 폴더 =
C:\dev\_work\gs-wonju-dangu\· 원본(무사) =…_26년 08월.xlsx
0. 🔴 지금 상태 — 먼저 알아야 할 것
- NAS 에 올라간
…_26년 09월.xlsx는 깨진 파일이다. 쓰면 안 된다. (8월 수작업 원본은 그대로 무사하다. 9월 파일만 교체하면 된다.) - PFS 한샘 견적
estimate_no=7과 운영배포 2건은 정상이다 — 서버 총액 29,109,099, 운영이 낸 엑셀은 Excel 로 정상 열림(별개 경로다). 이 사고는 로컬 수술본 xlsx 한 개의 문제다.
1. ✅ 확정해서 이미 고친 결함 2개
- 🔴🔴
docProps/app.xml개수/이름 불일치 = Excel 이 「파일 손상」으로 본다. 시트를 끼우고TitlesOfPartssize 만 +1 했는데 항목은 그대로였다(선언 12 / 실제 11). 게다가rename_sheet는 app.xml 을 안 건드려 옛 이름84A 내역서-주가 남아 있었다. ⛒build.sync_app_xml(parts)신설 — workbook.xml 시트 목록으로 다시 쓴다(마지막에 1회). ⚠_xlcheck·xldiag·openpyxl 은 이걸 전부 통과시킨다. 여긴 그들의 사각지대다. - 블록명 셀을
B{b}에 썼다 — 이 파일 규약은C{b}(C:N 병합). 그래서C39·C53에 복제 원본의 옛 이름 「상부장 부자재」가 남았다.C{b}로 고쳤고verify.py에 「B{b} 는 비어 있어야」 검사를 넣었다(현재 127/127 PASS).
2. 🔬 검증 인프라 — 이번에 만든 것 (이게 핵심 자산이다)
- 🔑
_xlcheck.py·xldiag.py(신설)·openpyxl 이 전부 통과해도 Excel 은 못 연다. 정본 판정기는 Excel 본인뿐이다.xldiag.py는 패키지 정합·수식 시트참조·sharedString 인덱스· 셀 타입·dxfId·definedName·codeName·공유수식까지 보는데도 결함 0 을 냈다. excel_probe.py+run_probe.py— Bash 는 Session 0 라 COM 이 거부된다 → 예약작업/IT+ 숨김.vbs+Excel.Visible=False로 사용자 세션에서 연다(화면에 안 뜬다).CorruptLoad0/1/2 세 모드를 다 시도하고, 열리면SaveAs로 Excel 정상화본까지 받는다.- 🔴단발 실행은 판정이 흔들린다 — 반드시 한 세션에 여러 파일을 몰아 넣고 「원본(대조군)」을 같이 잰다.
실측: 단발로는 대조군(재압축본)까지 「깨짐」이 나왔다. 배치로 바꾸니 대조군 OK 로 안정.
python run_probe.py a.xlsx b.xlsx …가 배치 모드다. 재현성 확인됨(같은 파일 2회 동일 판정). - 🔴파일명은 ASCII 로. VBS 가 한글 경로를 cp949 로 읽어 「파일 없음」이 된다 → 그 줄은 무효 판정이다.
3. 🎯 이진 탐색으로 좁힌 범위
배치 판정(대조군 OK 확인된 것만 유효):
| 산출물 | 내용 | 결과 |
|---|---|---|
_probe_base.xlsx |
원본 08월 | OK(대조군) |
_stage_pack |
읽고 재압축만 | OK |
_stage_rename |
+ rename_sheet |
OK |
_stage_clone |
+ clone_sheet(+sync_app_xml) |
OK |
_stage_lay1 |
+ 84A(기본) lay_blocks |
OK |
_y_dv / _y_rows / _y_merge |
DV 제거만 / 행 재배치만 / 병합 재작성만 | 전부 OK |
_z_copyonly |
lay_blocks 하되 fill_main·fill_sub 만 no-op |
OK |
_z_copyfill · _w_nocl · _probe_in |
lay_blocks 전체 |
깨짐 |
_x_rttonly |
갑지 _retarget_total 치환만 |
OK (무죄) |
⛒결론 = 범인은 build.fill_main / build.fill_sub 안이다.
블록 복제·행 재배치·병합·DV 제거·갑지 참조 치환은 전부 무죄로 실증됐다.
⚠무효 처리한 실험 = _q_str·_q_num·_q_frm·_r_blankonly·_r_noblank.
H.set_str 등 엔진 레벨을 no-op 으로 패치해서 lay_blocks 의 A4 평형명·총합 수식까지 꺼졌다
(XML diff 로 확인: OK본은 A4 가 inlineStr, 무효본은 t="s" 그대로). 결과를 믿지 마라.
4. 다음 한 걸음 (그대로 이어서 하면 된다)
fill_main 을 부분 수행하는 변형을 만들어 배치로 잰다. 반드시 B.fill_main 을 통째로 교체하는
방식으로 하고(엔진 H.set_* 는 건드리지 마라), 매 배치에 _probe_base.xlsx 를 넣는다.
- 블록명(
C{b}) + 합계 SUM 만 -
_blank_block(clear 60칸)
-
- 라벨/도어/길이/마감/10MM/등급
-
- 단가 LOOKUP 수식(
price_formula) ← 1순위 용의자. 내가 손으로 조립한 문자열이라 원본과 미세하게 다를 수 있다. 원본C9수식을 그대로 떠서 행만 옮기는 방식(H._repoint)으로 바꿔 보는 것이 가장 빠른 확인이다.
- 단가 LOOKUP 수식(
-
- 적용가 수식
깨지는 순간이 곧 범인이다. 잡으면 → build.py 수정 → verify.py(127항목) + _xlcheck + xldiag
+ run_probe 배치까지 4중으로 확인 → NAS 재업로드.
5. NAS 교체 절차
nasget.py put 은 대상이 있으면 거부한다. 깨진 9월 파일을 지워야 하는데 삭제는 위험작업이라
페페 승인 후 smbclient 로 지우고 다시 올린다. 8월 원본은 절대 안 건드린다.
6. 시드 포인터
- 상태 =
projects/pfs/handoff.md「✅ 26.9.9 GS 원주 단구 …」 절(엑셀 항목은 이 문서로 정정 필요) - 규칙 =
projects/pfs/rules.md🆕 맨 위 5줄(26.9.9) - pfs master
5a0c528· deploy-live7cb6ea1(둘 다 정상, 이 사고와 무관)