Conversation
- 파일트리 chevron: 커스텀 인라인 SVG → lucide ChevronRight - git 패널 그룹/트리 chevron: ChevronDown/Right 스왑 → ChevronRight + rotate-90 (파일트리와 동일한 회전 애니메이션 방식) - git 패널 헤더 펴기/접기 토글 아이콘: FoldVertical/UnfoldVertical → ChevronsUpDown/ChevronsDownUp (접기 아이콘을 파일트리와 일치, 기능 유지) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Appearance 설정에서 아이콘 테마를 선택할 수 있게 한다. Minimal(기존 lucide 단색, 기본·불변 베이스라인)과 Material(material-icon-theme 기반 언어별 컬러 로고, opt-in) 2종을 제공한다. - AppState.iconTheme(minimal|material) + theme.ts식 dual-write zustand 스토어 (set+localStorage+appState.set) + bootstrap hydrate 배선 - 통합 <FileIcon kind size tone/> 래퍼로 4개 소비 지점(file-tree/row, 에디터 탭, 검색 결과, git 폴더) 추상화. resolveLucide/resolveMaterial 순수함수 분리, Material 미커버 확장자는 per-icon lucide 폴백 - material-icon-theme(devDep) + vite-plugin-svgr 도입, 빌드타임 생성 스크립트 (gen:icons)로 매핑 JSON + SVG 1087개 번들. 정적 최빈셋 + lazy glob 하이브리드 - Appearance 패널 Icon Theme SegmentedControl + settings.json(en/ko) i18n - design.md §14 개정: Minimal 기본·불변 / Material opt-in 예외 명문화(§12/§13 교차 보정) - 순수 리졸버 단위테스트 50개 추가 검증: tsc(tsc -b) 통과, biome 클린(신규/수정 파일), bun test 3002개(+신규 50) 통과, electron-vite build exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
import.meta.glob 패턴에 `?react`를 직접 넣으면 Vite가 리터럴로 취급해 0개를
매칭한다. 그 결과 정적 import한 12개만 Material로 표시되고 나머지 모든
파일/폴더가 lucide로 폴백됐다. `?react`를 `{ query: "?react" }` 옵션으로 옮기고
glob 키 파싱 정규식을 쿼리 유무에 무관하게 보정.
검증: electron-vite build에서 변환 모듈 3030→4105, material 청크 1078개 방출
(folder-rust/folder-src/jenkins 등 비정적 아이콘 청크 확인). tsc·biome 클린.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
기존엔 아이콘마다 lazy()+Suspense(fallback=lucide)라 첫 등장 시 lucide→컬러 스왑 깜빡임이 보였다. VS Code(아이콘을 CSS background-image URL로 동기 참조, 컴포넌트 코드분할 없음) 방식을 차용: - 아이콘별 lazy 코드분할 폐기 → `?url` eager glob으로 iconName→에셋 URL을 동기 매핑하고 <img src>로 직접 렌더. Suspense 경계가 없어 스왑 깜빡임 없음. - assetsInlineLimit 함수로 material SVG는 base64 인라인 금지 → 파일로 방출. main 번들 5.79MB→4.95MB로 복귀(인라인 +850KB 제거), Minimal 기본 사용자가 미사용 에셋을 짊어지지 않음. SVG는 on-demand 디스크 로드 후 브라우저 캐시. 검증: build 1087개 SVG 파일 방출, tsc·biome 클린, bun test 3002개 0 fail. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
파일/폴더 아이콘 테마(Minimal lucide / Material 컬러 로고) 설정 추가. - AppState.iconTheme + dual-write 스토어, Appearance 컨트롤 + i18n - 통합 FileIcon 래퍼로 4지점(트리/탭/검색/git폴더) 추상화 - material-icon-theme 기반 1087 SVG 번들(동기 URL+<img>, 깜빡임 없음) - design.md §14 개정(Minimal 기본·불변/Material opt-in 예외)
에디터에서 git HEAD 대비 수정 라인을 거터에 표시하고, 마커 클릭 시 변경 전/후를 인라인 peek로 보여준다. git 패널 diff 뷰를 열지 않아도 일반 에디터에서 어디가 어떻게 바뀌었는지 확인할 수 있다. - diff 계산: monaco 번들 내부의 DefaultLinesDiffComputer 재사용 (VSCode quick-diff와 동일 엔진). 라이브 버퍼 기준이라 저장 전에도 갱신 - 거터: 추가/수정/삭제 색 막대 + overview ruler/minimap 틱 (--git-status-* 테마 변수 재사용) - peek: VSCode ZoneWidget 방식(뷰존+오버레이 위젯)으로 뷰포트 고정, ↑/↓ 네비게이션은 revealLineInCenterIfOutsideViewport로 스크롤, 헤더 아이콘은 lucide SVG - untracked/비저장소 파일은 baseline=null → 마커 없음(VSCode 동일) - tsconfig: bun 테스트 러너용 monaco esm 해석 별칭(vite/빌드 무영향) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
저장 성공 시 dirty-tracker만 갱신하고 엔트리의 lastLoadedValue는 편집 전 내용에 멈춰 있어서, 저장 직후 fs/git 이벤트의 reconcileExternalChange가 매번 diverged 분기로 빠져 diskDiverged를 거짓 설정했다. 현재는 이 플래그를 읽는 UI가 없어 무해하지만, 외부변경 충돌 경고를 얹으면 저장마다 거짓 경고가 뜨는 잠재 버그였다. - cache: syncLoadedValueAfterSave(input, content) 추가 - save/service: 쓰기 성공 직후 baseline을 방금 쓴 내용으로 동기화 (충돌 경로에서는 호출하지 않음) - test: 저장 성공 시 호출 / 충돌 시 미호출 회귀 테스트 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ErrorNotice 컴포넌트로 4개 뷰의 에러배너 중복 제거 (state-error 토큰/아이콘 픽셀 보존) - usePathAutocomplete 훅으로 디렉터리 피커 경로 콤보박스 추출 (상태 5·effect 4 이동) - hidden DOM-id 트리거(#picker-add-workspace-trigger)를 imperative ref handle로 교체 순효과 -180 LOC. UI/동작 불변. typecheck·biome(변경 라인)·기존 테스트 44 통과. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
키보드 close 경로(closeTabById)가 editor/terminal/diff/commit 4종만 처리해 untitled·browser 탭에서 Cmd+W가 무반응이었다. UI X 버튼 경로(handleCloseTab)와 동일하게 untitled(모델 release + closeTab)·browser(closeTab) 분기를 추가. Close Others/All도 같은 함수를 쓰므로 함께 수정됨. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
entry.ts의 타입정의를 model/types.ts로, registerKnownModelUri/notifiers/provider state를 lsp leaf로 추출해 entry↔attach-*·bridge↔cache 순환 제거. madge 0 순환 확인. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
handleCloseTab/closeTabById 중복 switch를 단일 디스패처 closeTabWithConfirm으로 통합. untitled 닫기 시 Save/Don't Save/Cancel 다이얼로그 추가(saveUntitledModel 3-way outcome, saved→이중 close 방지). 감사 ①의 발산 사례이자 Cmd+W 버그 근본 해소. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
validateArgs→getOrDetect→not-repo→op→refreshStatus→catch 스켈레톤을 withRepo로 통합, 41개 핸들러를 1줄화. 봉투·GitError 서브타입·invalid-args 매핑 보존. 리더/fetchAll/sync/stash-pop/cherry-pick/stream은 형태가 달라 수동 유지. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
internal/git의 run→exitcode→GitError 시퀀스와 branch/workflow/status 에러생성자를 run.go의 capture/gitError로 통합. diff/commitDetail은 ladder가 달라(raw stderr) 의도적 제외. status fallback 문구가 args 포함으로 통일(도달불가 경로). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FromContext가 도달불가(WithLogger가 넣은 값을 아무도 안 읽음)인 agentlog 패키지 전체와 host.go의 put-but-never-get 배선 제거. go build/vet 통과. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
z.string().uuid() 4중 중복과 contract.ts fs arg shape 16개를 WorkspaceIdSchema/workspaceScoped로 통합. 의미상 workspaceId인 인라인만 치환, tabId/sessionId/bookmark id는 보존. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
withFocusedTreePaths/withFocusedSinglePath/makeClipboardCommand로 wsId→tree→paths 전처리와 copy/cut 바이트동일 복붙을 통합. 동작 보존. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
main/renderer 110개 console.* 호출을 createLogger facade로 치환(conventions.md 강제사항). 함께: git store operations.ts 잉여 as 캐스트 12개 제거, 로깅 전환으로 깨진 테스트 4건을 logger-facade/계약 단언으로 갱신(log-test-spies 테스트 preload 추가). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
테스터10이 발견한 CRITICAL 2건: 1. closeUntitledWithConfirm이 untitled dirty 체크에 cacheUriFor(ws,"Untitled-N")를 써서 런타임 throw(absolutePath must be absolute) → untitled 탭 닫기가 전부 실패. untitledCacheUriFor(ws,index)로 교정(모델 캐시의 untitled:// 스킴과 일치). 2. use-group-actions.closeTabForId가 통합 안 된 제3의 타입 switch라 context-menu Close/Close Others/All이 untitled/git.commit/browser를 no-op → closeTabWithConfirm 위임으로 통일. not-dirty 경로 회귀 테스트 추가. 전체 3012 tests 0 fail. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
createUntitledEntry가 생성 직후 savedAlternativeVersionId=0/isDirty=true로 강제해, 아무것도 입력하지 않은 untitled도 닫을 때 save-confirm 모달이 떴다. 빈 모델의 현재 alt id를 저장 기준점으로 두어 시작은 clean, 실제 편집 시에만 dirty가 되도록 변경(undo로 빈 상태 복귀 시 다시 clean) — VSCode 동작과 일치. cmd+s는 untitled의 경우 saveUntitledModel로 직접 라우팅되어 dirty 가드를 타지 않으므로, clean 시작이어도 빈 untitled 저장-as는 그대로 동작한다. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
W0: tests/setup.ts에 electron canonical hermetic stub 추가(ipcMain/ipcRenderer/ webContents/app/BrowserWindow surface), 오염원 lsp-channel(-cancel) 불완전 mock 정리. process-global mock 순서의존으로 인한 단독통과·전체실패를 제거. 표준·역순·무작위 3시드 전부 3007 pass/0 fail/0 error. 프로덕션(src/**) 동작 변경 없음. W0 게이트: scripts/test-gate.sh(full/solo/compare/shuffle/coverage/baseline-freeze) + tests/.coverage-baseline.txt(66.52% lines). 단독==전체·커버리지 superset 자동검증. W1: .nexus/memory/pattern-test-design.md 신규(설계 의사결정 지침) + pattern-bun-mock- conventions.md Rule 5(electron canonical stub) + pattern-test-quality.md E절(회귀 가드). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
W2 결정성(핫스팟): status-coalescer·browse-session-registry에 nowFn DI seam (default Date.now, 호출부 불변 — Rule 3), file-delete 실지연 제거. 프로덕션 동작 불변. W3a 무손실 파라미터화: file-icon-resolvers/url-classifier/keybinding-parse를 test.each로 압축, expect 카운트 51/61/49 보존(단언 약화 케이스는 별도 유지). W3b 구현결합: claude-status since-값 단언 재작성(mutation spot-check 통과) + EMPTY_TABS 항등 테스트 삭제. 다수 '참조동일성' 테스트는 useSyncExternalStore return-state 가드 계약으로 정당 보존. W4: 렌더러 180파일 C104/B37/R33 분류 → tests/REFACTOR-BACKLOG.md. 전 구간 게이트 green: full 3011 pass/0 fail/0 error, shuffle 다수 시드, coverage 66.52%==baseline(무손실). next-cycle 잔여는 백로그에 정직 기록. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
게이트에 solo-all 모드 추가(전 314파일 단독 검사로 '전체통과·단독실패' 빈틈 마감). 단독실패 4개를 hermetic 수정(삭제 아님): terminal-services·load-external-entry는 ipc/client mock에 unwrapIpcResult 등 누락 surface 추가, bulk-close-cancel·pinned-tab은 mock 경로 불일치(barrel vs close-handler 직접 import) 교정. 과감 삭제 스윕 결과: 안전 삭제 대상 사실상 없음(후보 대부분 결과/상태 단언 기반 정당 테스트, AP-4 0건). 과도삭제 2건(open-editor·tabs/store: 회귀가드·제목파생 로직)은 되돌림. 검증: solo-all 314/314 PASS, full 0 fail/0 error, shuffle green, coverage 66.52%==baseline. src/** 동작 변경 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tests/.coverage-baseline.txt, tests/REFACTOR-BACKLOG.md 삭제. 둘 다 이번 테스트 오버홀의 일회성 스캐폴딩/메모 — 코드 참조 없음 (내용은 .nexus/history.json 회고에 보존). test-gate.sh의 coverage 모드는 baseline 부재 시 안내만 출력하고 graceful 동작, 필요시 baseline-freeze로 재생성. 나머지 게이트 모드(full/solo/solo-all/shuffle)·설계 지침 문서는 유지. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
마크다운 프리뷰가 GitHub처럼 inline HTML(<div align>, <img width>, <details> 등)을 렌더링하도록 rehype-raw를 추가하고, 곧바로 rehype-sanitize 기본 스키마(GitHub allowlist)로 정화한다. - 플러그인 순서 raw → sanitize → slug → highlight: sanitize는 raw 뒤·highlight 앞에 위치해야 함(allowlist가 <span> className을 막아 hljs-* 구문강조가 제거되는 것을 방지) - <script>(내용 포함)·<iframe>·on* 핸들러·잘못된 URL 스킴 제거 - 기존 워크스페이스 이미지 가드(nexus-workspace://)·링크 allowlist는 HTML 출신 태그에도 그대로 적용 - 보안 회귀 테스트 갱신 + GitHub-allowlisted HTML 렌더 테스트 추가 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
유사 에디터(Lapce/Void) 패턴에 맞춰 README를 매력→설치→세부 흐름으로 재구성한다. - 히어로(스크린샷·배지·태그라인) + "왜 NexusCode" + Features - 멀티 워크스페이스 전환 GIF, 멀티패널 히어로 이미지 추가 - 장황한 Gatekeeper 단계는 <details>로 접고, 풀 단축키 표는 docs/SHORTCUTS.md로 분리(README엔 핵심만) - 라이선스 TBD → MIT (LICENSE 파일 + package.json license 필드) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
배포 절차가 main 전제로만 쓰여 있어 develop→main 흐름이 누락돼 있던 것을 보완한다. - 0단계 신규: 브랜치 모델(develop=통합/main=릴리스, CI는 main PR/push 게이트)과 SemVer(pre-1.0) bump 정책 - 단계 재구성: 준비(develop) → main 승격(PR+CI) → Release 발행 → 검증. bump 커밋이 태그 대상이고 태그 target=main임을 명시 - 릴리스 노트 추출법(git log <tag>..develop) 추가, stale 예시 정리 - "미래 작업(Apple 서명)" 섹션 제거 (지식은 .nexus/memory에 잔존) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v0.4.0 이후 사용자 기능 추가(아이콘 테마·dirty-diff 거터·GitHub식 HTML 프리뷰·탭 동작 통합)로 SemVer minor bump. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
biome 2.4.14에서 noCommonJs가 nursery→style로 졸업하면서, 옛 카테고리를 가리키던 biome-ignore 주석이 suppressions/parse 에러를 내 CI lint를 막고 있었다. develop이 CI 게이트 밖이라 누적된 기존 문제로, 릴리스 작업과는 무관하다. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
moreih29
added a commit
that referenced
this pull request
Jun 2, 2026
Follow-up to the idle watchdog (e528ccd). Review surfaced six issues across correctness, scope, and recovery; this addresses all of them. #1 Monotonic clock: lastInbound was stored as wall-clock UnixNano and compared via time.Since on a time.Unix value, which silently falls back to wall-clock arithmetic. A laptop waking from sleep (local agent) or an NTP step (remote) made elapsed jump past the limit and reap a live session. Now anchored to a monotonic startMono via stampInbound/ idleElapsed. #2 Scope: the watchdog ran for local agents too, where parent death already arrives as stdin EOF (plus Pdeathsig on Linux) — pure downside. Now gated on a new --idle-watchdog flag the SSH launch sets and the local launch omits. #3 Threshold: 60s limit with 3-ping margin was tight enough that a stalled Electron main thread (ping is event-loop bound; ssh ServerAlive is not) could trip it. Widened to 90s limit / 15s ping (6 slots), with the check interval decoupled to limit/6 so the kill window stays tight. #4 Contract: client ping was gated on heartbeat advertisement, the agent watchdog on nothing — drift-prone. The agent now advertises idleWatchdogMs in the Ready frame; the client pings iff positive, at idleWatchdogMs/6. #5 Orphans: drainAndExit reaches os.Exit, which skips the `defer pty.Close()`. Linux survived via Pdeathsig; a darwin remote (supported, shipped) had only SIGHUP-on-fd-close, so SIGHUP-ignoring children orphaned. PTY cleanup is now a shutdown hook that SIGKILLs each process group on every OS. #6 Recovery: the watchdog exited 0, which the client's handleClose treats as a clean terminal exit (no reconnect). On a false positive (client alive but stalled) the session died permanently. Now exits 75 (EX_TEMPFAIL) so the client reconnects. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.4.0 이후 누적된 25개 커밋을 main으로 승격합니다. 머지 후
v0.5.0태그로 Release를 발행합니다.Added
<div align>·<img>·<details>등을 렌더 (rehype-raw + sanitize, GitHub allowlist)Changed
⌘W가 untitled·browser 탭도 닫도록, untitled dirty-confirm 경로 일원화docs/SHORTCUTS.md로 분리Fixed
lastLoadedValue동기화)내부 (사용자 영향 없음)
Protocol & Remote 영향
🤖 Generated with Claude Code