크라우니 오피스 브릿지 1차 실증 (punch #1 서식 + #2 상태바)
개요
spec/오피스-개발계획.md "두뇌 연결 = 한선씨 엔진 브릿지"의 [즉시층] 첫 구현. spec/문서기능-판정표.md에서 실측된 punch #1(B/I/U/S가 버튼 자기 하이라이트만 토글, 선택 텍스트에 미적용)과 punch #2(상태바 단어/글자수가 하드코딩 리터럴)를 앱 번들(bundle/office/app/index.html) 무수정으로 해결. 셸이 WKUserScript로 순수 JS(crownyBridge.js)를 주입해, 앱의 죽은 껍데기(div onClick 자기 하이라이트, 하드코딩 statusMap) 위에 실제 로직을 얹는 방식.
무엇을 했는지
D1 — crownyBridge.js (신규)
- 위치:
bundle/office/bridge/crownyBridge.js - 가드:
location.pathname이office/app/index.html을 포함하지 않으면 즉시 종료(공유 WKUserContentController가 전 탭에 스크립트를 주입하므로 자체 가드 필수). - 서식:
mousedowncapture에서 B/I/U/S 버튼(span.sc-interp 텍스트 + 부모 div의 인라인 style 힌트로 식별,font-weight/font-style/text-decoration) 클릭 시preventDefault로 선택영역 보존 →clickcapture에서document.execCommand('bold'/'italic'/'underline'/'strikeThrough')로 실제 적용. 앱 자체의 onClick(자기 하이라이트)은 막지 않고 그대로 유지, 이후queryCommandState로 버튼 활성상태를 실제 커서 위치 서식과 재동기화(syncFormatButtons). - 상태바:
input/selectionchange/MutationObserver(재렌더 방어) 트리거로computeStats()— 단어수(공백류[ \t\n\r]+분리 토큰, 한글은 어절 단위)·글자수(공백류 제외) 재계산 → "N단어"/"N자" 숫자 패턴을 정규식으로 찾아 상태바 텍스트 노드에 그대로 치환(원문의 "1페이지"/"한국어" 등 나머지는 보존).
D2 — 문서통계.한선 (신규, 정본 동반)
- 위치:
bundle/office/bridge/문서통계.한선 - JS
computeStats()의 한선씨 정본 미러.crowny-word/도구/문서통계확장.한선의공백문자인가/단어분리로직을 이 파일 안에 이식(원본 미수정, 기존 학습패턴fn_문서통계확장_공백문자인가/fn_문서통계확장_단어분리재사용). - 공개 함수:
단어수(텍스트),글자수공백제외(텍스트). - 자체시험 10건(5개 케이스 × 2함수) — JS
computeStats()와 동일 입력으로 수기 교차계산 후 값 일치 확인.
D3 — 셸 배선
native/crowny-ai-content.m:caOfficeBridgeScriptSource()헬퍼 추가(번들 리소스office/bridge/crownyBridge.js→CROWNY_BROWSER_ROOT/bundle/office/bridge/crownyBridge.js2단 폴백, 기존caiAssetPath규약과 동일 패턴).CrownyContentViewinit에서_ucc(공유 WKUserContentController) 생성 직후WKUserScript(injectionTime:AtDocumentEnd,forMainFrameOnly:YES)로 addUserScript.native/배포패키징.sh:Contents/Resources/office/bridge/복사 라인 추가(office/app과 동일 패턴).crowny-browser.m,crowny-shell.m,Makefile기존 타깃, 앱 번들(bundle/office/app/)은 무수정.
게이트 결과
- hanseonc_high 컴파일 + crownyc run:
./hanseonc_high 문서통계.한선 > x.toau && ./crownyc run x.toau→ PASS 10/10. - make ai:
cc -O2 -Wall ...경고 0·에러 0,strip -x완료(409K)../CrownyAI백그라운드 실행 후 3.5초 뒤 프로세스 생존 확인, 크래시 로그 없음.cc -fsyntax-only -fobjc-arc -DCROWNY_HYBRID crowny-ai-content.m클린. - 실측(CDP, Chrome :9333, 셸 없이 로직 검증) —
file:///Users/ef/crownybrowser/bundle/office/app/index.html에 이미 로드된 세션에crownyBridge.js를Runtime.evaluate로 그대로 주입(node 워크어라운드로 파일 내용을 직접 전송, 셸따옴표 문제 회피) 후:
ce.innerHTML.length 3825→3832, <b>/<strong> 개수 1→2, 신규 <b>몇 달간의 베타 테스트</b> 확인(wrapped:true). 지연 후 B 버튼에 data-crowny-active="1" + 하이라이트 인라인 style 확인(커서 위치 실제 서식과 버튼 상태 동기화 확증).
- 상태바 before/after: 편집영역 끝에 " TESTWORD12345"(공백포함 14자, 공백제외 13자) execCommand('insertText') 삽입 → ce.innerText.length 428→442(+14, 정확히 일치) → 상태바 텍스트 "1페이지 · 99단어 · 325자 · 한국어" → "1페이지 · 100단어 · 338자 · 한국어"(단어 +1, 글자 +13, 삽입 문자열과 정확히 일치). 하드코딩 리터럴("1,243단어 · 6,812자")이 실제 편집 이전에 이미 실측값(99단어·325자)으로 살아있었음도 확인(초기 boot 폴링 → MutationObserver가 정상 작동 중이라는 방증).
- 셸 주입판(WKUserScript 경유 실배선): 이번 세션에서는 미실행(스펙상 "선택").
native/crowny-ai-content.m문법검사 통과 + 동일_ucc가 오피스 탭 webview 생성(makeWebView)과caOpenOfficeInActiveTab의loadFileURL대상 모두에 공유되는 구조를 코드로 확인. 실기 WKWebView는 CDP 원격디버깅 대상이 아니라(Web Inspector 별도 트랙 필요) 이번 실증 범위에서 제외 — 후속 트랙에서 Safari 원격 웹 인스펙터로 재검증 권장.
관련 파일
/Users/ef/crownybrowser/bundle/office/bridge/crownyBridge.js(신규)/Users/ef/crownybrowser/bundle/office/bridge/문서통계.한선(신규, 정본)/Users/ef/crownybrowser/native/crowny-ai-content.m(수정:caOfficeBridgeScriptSource()+_uccWKUserScript 등록)/Users/ef/crownybrowser/native/배포패키징.sh(수정: bridge/ 복사)- 참조:
/Users/ef/crownybrowser/spec/오피스-개발계획.md,/Users/ef/crownybrowser/spec/문서기능-판정표.md,/Users/ef/crowny-word/도구/문서통계확장.한선
크라우니코드
- lookup HIT 1건(
문서통계계열 다수 —fn_문서통계확장_공백문자인가/단어분리재사용) / MISS 1건(단어수 글자수) - learn 1건 등록(
문서통계_글자수공백제외), 1건은 코드 길이 미달로 학습기가 무시(문서통계_단어수, 정상 동작에는 무관)
잔여 이슈
- 실기 WKWebView 경유 실배선 검증(게이트 4)은 미실행 — Safari 원격 웹 인스펙터 또는
WKWebView.isInspectable+ CDP 유사 브리지로 후속 검증 권장. - 판정표 punch #3~#10(실행취소/재실행, 찾기 실동작, 삽입 3종, 개요 동기화, 댓글 CRUD, 히스토리 스냅샷, 단축키, 드롭다운 3종)은 이번 스코프 밖 — Phase 1-A 후속 착수 순서대로 진행.
- 상태바 "저장상태"/"페이지 수"/"언어감지"는 이번 스코프(단어/글자수만) 밖, statusMap 문자열의 나머지 구간은 그대로 하드코딩 유지.
- 서식 동기화(
syncFormatButtons)는 클릭 직후setTimeout(0)에 의존 — 매우 빠른 연속 클릭/재렌더 경쟁 상황에서 드물게 한 프레임 지연 가능(치명적이지 않음, 후속 다듬기 대상). - CDP 테스트 하네스 스크립트(
cdp_inject_file.js,test_bold.js,test_bold2.js,test_statusbar.js)는 scratchpad 1회성 검증용 — DOM/WebSocket 프로토콜 조작뿐이라 계산 로직이 없어 한선씨 동반을 생략함(기존win/cdp평가.js도 동일 취급).