# HMDesign OrgChart P9.2 — Full Composition 중앙 정렬 · 회사 선택 통합 RESULT: **PASS — 요청한 P9.2 변경 범위.** 기존 Guard FAIL/NOT VERIFIED 및 사용자 디자인 승인 상태는 별도로 유지한다. ## 작업 기준·시간 - 범위: `STORYBOOK_ONLY`, 기존 실제 React Storybook 수정. - 작업 폴더: `D:\디자인시스템\HMDesign-OrgChart` - 브랜치: `feature/orgchart-package` - 시작/완료 HEAD: `7614507583927a25a270963a74ff044be0557b9f` - origin: `https://gitea.hmac.kr/b25027/HMDesign.git`. 원격 조회·Fetch·Pull 없음. - Started At: 2026-10-13 10:53:44 KST - Completed At: 2026-10-13 11:06:16 KST - Actual Duration: 12분 32초 - Estimated Duration: 최초 35~50분 — 구조 확인 8분 / 수정 15~20분 / 검증·캡처·보고 12~22분. - Variance: 예상보다 22분 28초~37분 28초 짧음. ## Full Composition 원인·수정 P9.1은 6개 조직 카드의 시각적 합집합 중심을 전체 Stage 중심으로 취급했다. 가용 폭도 부모의 border-box 폭으로 구해 Border/Padding이 있을 때 실제 콘텐츠 영역과 달라졌다. 따라서 1920·1440px에서 Stage가 약 16.12px 오른쪽으로 이동했고, 비대칭 여백에서 약 51.44px 오차와 실제 콘텐츠 밖 배치가 발생했다. 실제 사용자에게 보이는 회색 배경 `section.hm-orgchart-story-full[aria-label="Full Composition"]`을 Content Wrapper로 사용한다. 경로는 StoryPage → StorySection의 `.sb-page-section-body` → 이 section → React OrgChart host/Shadow DOM → Core Scale Wrapper `.hm-orgchart-composition` → `.hm-orgchart-stage[data-workdesk-artwork]`다. Wrapper의 BoundingRect에서 왼쪽 Border·Padding을 더하고 오른쪽 Border·Padding을 빼 콘텐츠 가용 영역을 계산한다. 그 중심과 변환된 전체 Stage BoundingRect 중심의 차이를 실측해 전체 Stage 하나에 CSS translate를 적용한다. 임의 고정 이동값·조직별 좌표 수정이 없으며 Core transform/width-height fit과 원본 1920×914.5px을 유지한다. P9.1의 카드 중심에 맞춘 추가 scale 보정은 제거했다. | 화면 폭 | Wrapper Left | Wrapper Right | Wrapper Center X | Stage Left | Stage Right | Stage Center X | 수정 전 오차 | 수정 후 오차 | |---|---:|---:|---:|---:|---:|---:|---:|---:| | 1920px | 360.000 | 1560.000 | 960.000 | 360.000000 | 1560.000000 | 960.000000 | +16.117645 | 0.000000 | | 1440px | 120.000 | 1320.000 | 720.000 | 121.967201 | 1318.032753 | 719.999977 | +16.117462 | -0.000023 | | 390px | 16.000 | 374.000 | 195.000 | 16.000000 | 374.000000 | 195.000000 | +4.808695 | 0.000000 | canonical 화면에서 Wrapper 중심이 Viewport 중심과 우연히 일치한다. 기준이 Viewport가 아님은 비대칭 조건에서 확인했다: 1440px Viewport 중심720, 실제 콘텐츠 중심680, Stage 중심680. Padding만 재분배하면 콘텐츠/Stage 중심714로 같이 이동한다. 1010/390px 동일 mount resize에서도 오차 최대0.000016px이다. - Full Composition 브라우저 **43/43 PASS**, canonical3개+비대칭 Border/Padding+동일 폭 Padding 재분배+1010/390 resize7조건. - 152개 내부 요소의 DOM·정규화 상대 좌표·computed style 및 이미지139개의 SHA-256을 수정 전과 비교해 일치. - 카드43개·조직6개·연결경로5개·대표자·허브·협업 화살표·우측통계·좌측파견/휴직·하단관계사·배경/장식 유지. - 실제 rendered Stage와 모든 측정 콘텐츠가 부모 콘텐츠 영역에 포함됨. 잘림·카드/통계의 부적절한 충돌0건, 문서/사용 가능한 내부 스크롤바0건. - 기존 Core `overflow:hidden`은 변경하지 않았다. transform 전 자연1920×915 layout 때문에 Scale Wrapper raw scrollWidth/scrollHeight가 client 크기보다 큰 기존 값은 보존된다. 이를 raw overflow0으로 보고하지 않으며, 실제 변환 후 Stage/콘텐츠 포함 검사로 잘림이 없음을 별도로 증명했다. - 정렬 후12프레임 Stage style mutation0, observer 반복 루프 없음. - [수정 전 측정](../../test-results/org-chart-p9-2/before-composition.json), [수정 후 원본](../../test-results/org-chart-p9-2/browser-composition.json). ## Expanded 회사 선택 외부에 펼쳐진 회사 체크박스7개와 전체 회사/선택 해제 버튼을 제거하고, 기존 FilterBar 데이터 범위·직원 수 사이에 회사 선택 드롭다운1개를 배치했다. 공개 MultiSelect export가 없고 Select는 단일값 API이므로 실제 HM `Popover + Checkbox + Label + Button + Separator`를 렌더링한다. 기존 library 의존성을 사용하며 추가 설치 없음. 실제 P5-0 preset ID/이름 `hanmac/한맥기술, saman/삼안, jangheon-industry/장헌산업, jangheon/장헌, ptc/피티씨, halla/한라산업개발, baron/바론컨설턴트`를 그대로 사용한다. | 선택 상태 | 닫힘 요약 | 전체 선택 상태 | 실제 결과 | |---|---|---|---| | 7개 | 전체 회사 (7개) | checked | 전체 회사 Root/기존 합산20명 | | 1개 | 한맥기술 또는 실제 선택회사명 | mixed | 해당 회사만 표시 | | 2개 | 2개 회사 선택 | mixed | 한맥기술+삼안 반영 | | 0개 | 회사를 선택하세요 | unchecked | 빈 forest·0명·오류 없음 | - 전체 선택·해제·단일·복수·개별 제외·부분 선택에서 전체 선택을 확인했다. 닫고 다시 열어도 상태 유지. - 회사 선택은 draft/applied의 companyIds에 즉시 반영한다. 데이터 범위·직원 수의 기존 draft→데이터 적용 정책은 보존한다. 미적용 범위/인원수를 바꾼 뒤 회사만 체크해도 적용된 범위/인원수는 그대로다. - 회사별100명: 한맥기술100명 → 삼안 추가 즉시200명. 회사별20/300명도 단일회사 실제 확인. - 전체 합산20/100/300명: 기존 P7 weighted partition 후 선택회사만 필터하는 계약 유지, 선택회사에 재분배하지 않음. 데이터 helper/직원JSON/Core 계약 source hash 동일. - TB/LR/Hybrid 대표모드에서 선택된6개 회사/직원 및 제외된회사 반영 확인. 흰 제목·연결 방향별 Border, 그룹 접기/Space 펼치기, HM 직원 Dialog identity/ESC/카드focus복귀, 실제 Zoom·pointer Pan·Fit PASS. - Enter로 열기, Tab으로 전체/회사checkbox 접근, Space 조작, ESC/trigger 클릭/외부 클릭 닫기, ESC trigger focus복귀 PASS. 접근성 이름 및 aria-checked true/mixed/false 제공, 기존 HM focus 스타일 사용. - 실제 public Popover Portal 사용. 1920/1440/768/390px에서 표시 및 요청한 닫힘/열림/전체/부분선택 캡처. 1920/768/390px 모든8개checkbox의 panel 포함·viewport 포함·가로overflow없음 확인. - Expanded 최초 원본44PASS/1FAIL 중 FAIL은 검증 코드가 존재하지 않는 `.hm-orgchart-empty` 안내요소를 찾은 문제였다. 기존 Core empty 계약은 자식이 없는 forest이므로 probe만 수정하고 실패한 항목만 재실행2/2PASS. 앱 코드는 변경하지 않았으며 성공한 테스트를 재실행하지 않았다. **최종45개 항목PASS**. 원본 실패기록은 보존하고 [종합/provenance](../../test-results/org-chart-p9-2/verification-summary.json)에 해소 근거를 연결했다. - [최초 원본](../../test-results/org-chart-p9-2/browser-expanded.json), [empty항목 보정](../../test-results/org-chart-p9-2/browser-expanded-empty.json). ## 기술 검증·보존 | 항목 | 결과 | |---|---| | 변경 Story/helper Typecheck | PASS — `node node_modules/typescript/bin/tsc -p test-results/org-chart-p9-2/story-tsconfig.json` | | Storybook production build | PASS — `npm.cmd exec -- storybook build -o storybook-static --disable-telemetry`. 기존500kB chunk 경고/plugin timing 진단 유지, 오류없음 | | 신규 console/pageerror | 두 변경 및 보정/변수근거 실행 모두0건 | | 기존 공개메뉴·StoryID | Overview / Department Colors / Full Composition / Expanded OrgChart4개 동일. OrgChart root/Patterns 다음 메뉴설정 hash 동일, 기존P8 manager증거 재사용 | | Fixed/Auto CSS 격리 | Core/React 패키지와 공통CSS hash 동일. 신규StoryCSS는 설정컨트롤/Portal만 대상으로 하며 Shadow 내부 Fixed/Auto 카드·레이아웃을 변경하지 않음 | | Overview·Department Colors | JSX/스타일/helper/CSF hash 동일. P9.1 간소화 결과 보존 | | 코드리뷰·변경범위 | 독립 read-only 리뷰 finding0. 소스3개만 수정, baseline 나머지 파일 SHA-256 동일 | | diff/공백 | `git diff --check` PASS 및 신규 authored파일 whitespace 확인 | Core/React 데이터 생성·레이아웃 알고리즘·Theme·카드SVG·회사색은 수정하지 않았다. 기존 P7~P9.1 PASS를 동일 소스 근거로 재사용하며 전체2100명 성능·과거전체suite·전체Guard는 반복하지 않았다. ## Guard·미검증 이번 PARTIAL/STORYBOOK Guard 원본은 **status/staticStatus/runtimeStatus NOT VERIFIED**, 신규FAIL0. 원본 issue2개: - `TOKEN-001 NOT VERIFIED`: StoryCSS의 `--radix-popover-content-available-height`. HM 공개 Popover/Radix가 런타임에 선언하는 위치변수이므로 연결consumerTheme 정적 선언만으로 확인되지 않는다. 실제 변수값과 maxHeight 일치를 [추가 런타임 근거](../../test-results/org-chart-p9-2/browser-expanded-token.json)로 확인했다. 원본 미검증을 덮어쓰지 않았다. - `TOKEN-002 NOT VERIFIED`: 기존 StoryPage 동적class site. 소스불변. styleEvidence는 **STATIC PASS / RUNTIME NOT VERIFIED / DESIGN_INTENT NOT VERIFIED / FINAL NOT VERIFIED**, 결합styleVerification은 생성하지 않았으며 NOT VERIFIED다. 실제 computed/상호작용PASS는 사용자 디자인의도 승인으로 확대하지 않는다. 기존 P9 Guard의 status/staticStatus **FAIL**, runtime **NOT VERIFIED**, TOKEN-00110FAIL/TOKEN-00210NOT VERIFIED 및 패키지CSS SCOPE-0012NOT VERIFIED 원본/보고서/hash를 그대로 보존한다. 이번 PARTIAL 검사가 이전 전체범위 결과를 대체하지 않는다. 삼안·장헌산업 흰 제목 대비 잔여진단, Compact NOT SUPPORTED도 유지한다. 사용자 최종 디자인 승인·다른브라우저/실기기/스크린리더·모든옵션조합·SSR/배포는 NOT VERIFIED. 요청범위 완료 후 사용자 검토 대기하며 P10은 시작하지 않았다. ## 변경파일 | 파일 | P9.2 변경 | |---|---| | src/org-chart/center-composition-preview.ts | 실제부모 content-box 기준 전체Stage 중앙정렬 | | src/org-chart/org-chart-expanded.stories.tsx | HM 회사선택Popover·전체/부분/미선택·즉시회사반영 | | src/org-chart/org-chart-expanded-story.css | trigger/요약/Portal 콘텐츠레이아웃 | | examples/org-chart/verify-p9-2-composition.mjs | 중앙정렬 수정전후·포함·내부보존·scroll/resize검증 | | examples/org-chart/verify-p9-2.mjs | 회사선택·데이터·키보드·레이아웃·Portal 검증 | | docs/org-chart/implementation-report-p9-2.md | 이 보고서 | test-results/org-chart-p9-2 및 storybook-static은 생성검증산출물이다. [시작baseline](../../test-results/org-chart-p9-2/baseline.json), [최종audit](../../test-results/org-chart-p9-2/final-state.json), [typecheck log](../../test-results/org-chart-p9-2/typecheck.log), [build log](../../test-results/org-chart-p9-2/build.log), [Guard원본](../../test-results/org-chart-p9-2/guard.json). **Stage·Commit·Push·Merge·main checkout·PR·Pull·Reset·Rebase·Force Push 모두 미진행.** 시작과완료branch/HEAD 동일, staged파일0. 기존미커밋P7~P9.1변경 보존. ## 실제 Storybook·캡처 - [Full Composition](http://127.0.0.1:6062/?path=/story/orgchart--full-composition): [1920px](../../test-results/org-chart-p9-2/after-full-composition-1920.png), [1440px](../../test-results/org-chart-p9-2/after-full-composition-1440.png), [390px](../../test-results/org-chart-p9-2/after-full-composition-390.png). - [Expanded OrgChart](http://127.0.0.1:6062/?path=/story/orgchart--expanded-org-chart): [닫힘](../../test-results/org-chart-p9-2/expanded-closed.png), [열림](../../test-results/org-chart-p9-2/expanded-open-all.png), [전체선택](../../test-results/org-chart-p9-2/expanded-all-selected.png), [부분선택](../../test-results/org-chart-p9-2/expanded-open-partial.png), [2회사100명씩](../../test-results/org-chart-p9-2/expanded-closed-partial.png), [390px열림](../../test-results/org-chart-p9-2/expanded-open-390.png). - [수정전회사UI](../../test-results/org-chart-p9-2/before-expanded-1440.png). 수정전FullComposition은 같은폴더before-full-composition-1920/1440/390.png에 보존.