@nolit/dsh-notify 0.0.0-stage → 0.0.1-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +388 -0
  2. package/LICENSE +21 -0
  3. package/PROVENANCE.md +96 -0
  4. package/README.md +298 -2
  5. package/cordis.patch.yml +19 -0
  6. package/docs/2026-10-20-dsh-notify-design.md +335 -0
  7. package/docs/2026-10-20-final-status.md +125 -0
  8. package/docs/2026-10-23-asset-policy.md +170 -0
  9. package/docs/2026-10-23-deployment-strategy-review.md +530 -0
  10. package/docs/2026-10-23-headless-nonintrusive-ui-architecture.md +579 -0
  11. package/docs/2026-10-23-hybrid-dual-mode-design.md +955 -0
  12. package/docs/2026-10-23-timezone-global-report.md +204 -0
  13. package/docs/2026-10-23-web-notify-plugin-spec.md +454 -0
  14. package/docs/2026-10-23-web-plugin-mount.md +111 -0
  15. package/docs/2026-10-23-windows-widget-poc-report.md +312 -0
  16. package/docs/2026-10-24-linux-desktop-verification.md +134 -0
  17. package/docs/BOOT-CARD.md +176 -0
  18. package/docs/RECOVERY-NOTES.md +111 -0
  19. package/docs/WORK-PROTOCOL.md +155 -0
  20. package/docs/deepseek-peak-spec.md +370 -0
  21. package/docs/dsh-harness-notify-spec.md +149 -0
  22. package/icon.svg +6 -0
  23. package/lib/client.js +2172 -0
  24. package/lib/client.src.js +1963 -0
  25. package/lib/index.js +13 -0
  26. package/lib/locale-table.js +215 -0
  27. package/locale/en.json +104 -0
  28. package/locale/ko.json +104 -0
  29. package/market/icons/dsh-notify.svg +6 -0
  30. package/market/index.json +77 -0
  31. package/package.json +80 -4
  32. package/scripts/build-client.mjs +41 -0
  33. package/scripts/gen-locale.mjs +36 -0
  34. package/test/client.test.mjs +601 -0
  35. package/test/locale.test.mjs +114 -0
  36. package/test/manifest.test.mjs +115 -0
  37. package/test/peak.test.mjs +333 -0
  38. package/test/typography.test.mjs +85 -0
@@ -0,0 +1,125 @@
1
+ # DSH Notify — 최종 상태와 알려진 문제
2
+
3
+ <!-- skeleton:
4
+ version: 1.0
5
+ kind: report
6
+ status: historical
7
+ updated: 2026-10-20
8
+ summary: Final state of the first DSH Notify round and the known problems left open at that point.
9
+ -->
10
+
11
+
12
+ > 상태: final · 최종 갱신: 2026-10-20 · git: main @ milestone-3 · 상위: [WORK-PROTOCOL.md](WORK-PROTOCOL.md)
13
+
14
+ 이 문서는 "지금 이 버전을 그대로 두고 멈춘다"는 결정에 따라, 현재 동작·구조·한계를 한곳에 정리한 마감 문서다.
15
+
16
+ ## 인덱스
17
+
18
+ | § | 섹션 | 한 줄 요약 |
19
+ |---|---|---|
20
+ | 1 | 현재 버전 | 마지막 커밋·태그·실행 방법 |
21
+ | 2 | 동작하는 기능 | 카드·트레이·DSH 팝업·동기화 |
22
+ | 3 | 구조 | 파일 맵과 이벤트 경로 |
23
+ | 4 | 설정 | config.json 키 |
24
+ | 5 | **알려진 문제** | 반드시 읽을 것 — 소리/토스트/SAC |
25
+ | 6 | 진단 로그 | core.log·bridge.log·popup 로그 |
26
+ | 7 | 테스트 | 실행 명령과 현재 결과 |
27
+ | 8 | 다음 후보 (미착수) | 클라이언트 오디오 등 |
28
+
29
+ ---
30
+
31
+ ## 1. 현재 버전
32
+
33
+ | 항목 | 값 |
34
+ |---|---|
35
+ | 브랜치 | `main` |
36
+ | 태그 | `milestone-3` (문서·팝업 마감) |
37
+ | 실행 | 시작 메뉴 `DSH Notify` 바로가기 또는 `pwsh -NoProfile -File start.ps1` |
38
+ | 종료 | 트레이 고래 아이콘 우클릭 → `종료` |
39
+ | 요구 | PowerShell 7, Windows 10/11, DSH 프로필에 브리지 플러그인 등록됨 |
40
+
41
+ ## 2. 동작하는 기능
42
+
43
+ - **피크/오프피크 카드**: 제목 `DeepSeek Peak (100%)` / `DeepSeek Off-Peak (50% discount)`. digital-7 타이머 `HH:MM:SS`, 초와 콜론은 배경색(`#2C2C2C`), 본문 색 피크 `#E5534B` / 오프피크 `#4ADE80`, 제목 CI 블루, 투명도 0.6
44
+ - **트레이 메뉴**: 지금 갱신 / 알림(체크) / OLED 보호(체크) / 항상 표시(체크) / 피크일 때만 / 위치 초기화 / 카드 보이기(체크) / 종료
45
+ - **OLED 보호**: 켜면 `oledIntervalSeconds`(기본 60초)마다 카드를 5px씩 네 방향 순환. 저장 기준 위치는 유지
46
+ - **시작 경량화**: 창은 즉시 `00:00:00` 으로 뜨고 5초 뒤 백그라운드 스레드에서 공휴일·지역 동기화
47
+ - **DSH 완료/승인 팝업**: 브리지가 `cache\popup-request.json` 을 남기면 코어가 팝업 표시 (소리 없음)
48
+ - **서브에이전트 완료 필터**: 완료 알림은 루트 세션만. 승인/질문은 서브에이전트 것도 알림
49
+ - **알림 전체 스위치**: 트레이 `알림` 체크 = `config.notifications`. 코어 전환 토스트와 DSH 팝업을 함께 끔
50
+
51
+ ## 3. 구조
52
+
53
+ ```
54
+ DSH host plugin bridge\index.js (@local/dsh-notify-bridge)
55
+ ├─ 턴 완료/승인/질문/오류 이벤트 구독 ({global:true})
56
+ └─ cache\popup-request.json 기록
57
+ ↓ (1초 tick 폴링)
58
+ core.ps1 (상주 WPF) ── 카드·트레이·팝업
59
+ ├─ providers\deepseek-peak.ps1 판정·공휴일 캐시
60
+ ├─ ui\presenter.ps1 표시 모델
61
+ ├─ ui\indicator.ps1 카드
62
+ ├─ ui\tray.ps1 트레이
63
+ └─ ui\popup.ps1 우하단 팝업
64
+ ```
65
+
66
+ - 포트·웹서버·데몬 없음. 파일 큐 + 프로세스 내부 타이머만 사용
67
+ - DSH 프로필 등록: `~\.dsh\profiles\desktop\node_modules\@local\dsh-notify-bridge` junction + `cordis.patch.yml` 의 insert 엔트리 (백업 `cordis.patch.yml.bak`)
68
+ - 브리지는 로더 핫 리로드로 재시작 없이 반영된다. 적용 증거: `cache\bridge.log` 의 `bridge x.y.z applied: ...`
69
+
70
+ ## 4. 설정
71
+
72
+ `config.json` (프로젝트 루트). 트레이 메뉴가 일부 값을 직접 바꾼다.
73
+
74
+ | 키 | 기본 | 의미 |
75
+ |---|---|---|
76
+ | `displayMode` | `always` | `peakOnly` 면 피크일 때만 카드 |
77
+ | `opacity` | 0.6 | 카드 불투명도 (0.2–1.0) |
78
+ | `position` | 저장값 | 카드 기준 위치 (OLED 오프셋 제외) |
79
+ | `notifyOnChange` | true | 구간 전환 시 토스트 1회 |
80
+ | `notifications` | true | 전체 알림 스위치 |
81
+ | `oledProtection` | false | OLED 번인 완화 이동 |
82
+ | `oledIntervalSeconds` | 60 | 이동 간격(최소 5초) |
83
+ | `pollSeconds` | 60 | provider 폴링 주기 |
84
+ | `providers.deepseek-peak` | enabled/treatMakeupAsPeak/refreshHours(240) | 공휴일·판정 옵션 |
85
+
86
+ ## 5. 알려진 문제
87
+
88
+ | 심각도 | 문제 | 원인/현상 | 현재 대응 |
89
+ |---|---|---|---|
90
+ | **높음** | **DSH 팝업 소리 없음** | 이 PC에서 WinMM(`SoundPlayer`/`PlaySound`)은 스피커 앰프까지 도달하지 않고 "뽁"만 났다(피크 0 실측). 5.1 WinRT MediaPlayer 자식도 무음, 미디어 플레이어 경유는 창이 떠서 UX 훼손 | **소리 제거 결정**. 팝업만 표시 |
91
+ | **높음** | 윈도 토스트 배너 미표시 | PushNotification 로그에는 `delivered` 로 찍히지만 배너가 억제됨(집중 지원/알림 설정). 앱은 표시 여부를 알 수 없음 | 토스트는 수동 확인용(`notify\send-toast.ps1`). 정식 알림은 자체 팝업 |
92
+ | **높음** | `DSH-Notify.exe` 실행 차단 | Smart App Control 이 서명 없는 exe 차단 (CodeIntegrity 3073/3077) | 시작 메뉴 바로가기/스크립트 사용. exe 는 서명·SAC 해제 환경용 |
93
+ | 중간 | 완료 팝업은 코어 상주가 전제 | 코어가 꺼져 있으면 요청 파일이 소비되지 않고 남음 | 트레이 앱 실행 상태 유지. 다음 실행 시 첫 tick 에서 소비됨 |
94
+ | 중간 | 로그 무한 증가 | `cache\core.log`, `cache\bridge.log` 로테이션 없음 | 수동 삭제. 필요 시 로테이션 추가 |
95
+ | 낮음 | OLED 이동폭 고정 | 5px 4방향만 지원 | `ui\popup`/`core.ps1` 상수 수정 |
96
+ | 낮음 | digital-7 폰트 라이선스 | 개인용 무료 | 배포 금지. 로컬 사용만 |
97
+ | 낮음 | WMP 11 설치해도 WPF MediaPlayer 실패 | 새 Store 앱은 레거시 WMP 구성 요소가 아님 | 사용 안 함 (소리 제거) |
98
+
99
+ ## 6. 진단 로그
100
+
101
+ | 파일 | 내용 |
102
+ |---|---|
103
+ | `cache\core.log` | 시작·동기화·UI 반영·팝업 소비·디스패처 예외 |
104
+ | `cache\bridge.log` | 플러그인 적용 버전, 수신 이벤트, 완료 판정 |
105
+ | `cache\popup-sound.log` | 과거 음향 실험 기록(현재 미사용) |
106
+ | `cache\region.json` / `cache\deepseek-peak\holidays.json` | 지역·공휴일 캐시 |
107
+ | `cache\audio-policy-backup.reg` | 실험 중 삭제한 PowerShell 앱 오디오 라우팅 백업 |
108
+
109
+ ## 7. 테스트
110
+
111
+ ```powershell
112
+ pwsh -NoProfile -File tests\run-all.ps1 # 19 files
113
+ pwsh -NoProfile -File tests\docs-contract.ps1 # 헤더/인덱스 검사
114
+ node .\bridge\test.mjs # 브리지 단위 테스트
115
+ ```
116
+
117
+ 마지막 결과: **19 files, 19 passed / 0 failed**, docs-contract 47 files PASS.
118
+
119
+ ## 8. 다음 후보 (미착수)
120
+
121
+ - **클라이언트(브라우저) 오디오**: DSH 웹 GUI에서 `<audio>` 로 재생. spawn 프로세스 오디오 문제를 우회하는 유일한 검증된 경로
122
+ - 토스트 AUMID 브랜딩(시작 메뉴 AUMID 등록) — 배너 억제 문제와는 별개
123
+ - 코드 서명으로 SAC 통과
124
+ - 로그 로테이션, OLED 이동폭/패턴 설정화
125
+ - 자동 시작 토글
@@ -0,0 +1,170 @@
1
+ # 에셋·상표 라이선스 정책 — BYO(Bring Your Own) 방식
2
+
3
+ <!-- skeleton:
4
+ version: 1.0
5
+ kind: policy
6
+ status: reference
7
+ updated: 2026-10-23
8
+ summary: Asset and trademark licence policy: bring-your-own assets, what may ship, and what must never be redistributed.
9
+ -->
10
+
11
+
12
+ > 상태: active · 최종 갱신: 2026-10-23 · git: main @ 8129b54 · 상위: [README.md](../README.md)
13
+
14
+ - 목적: 오픈소스 재배포 시 폰트·로고·사운드 라이선스 분쟁을 원천 차단한다.
15
+ - 원칙: **패키지는 에셋을 배포하지 않는다.** 사용자가 직접 주입한 에셋만 로컬에서 사용한다.
16
+ - 적용 대상: `@nolit/dsh-notify`(웹 플러그인), 윈도우 오프피크 위젯(포터블 패키지).
17
+ - 코드 라이선스: MIT ([LICENSE](../LICENSE)).
18
+
19
+ ## 인덱스
20
+
21
+ | § | 섹션 | 한 줄 요약 |
22
+ |---|---|---|
23
+ | 1 | 기본 원칙 | 기본은 시스템 폰트/중립 아이콘/합성음, 에셋 번들 없음 |
24
+ | 2 | 폰트 | 시스템 폰트 기본, `fonts/digital-7.ttf` 사용자 주입 시 우선 |
25
+ | 3 | 아이콘·상표 | DeepSeek 로고 제외, 중립 시계 아이콘, `icons/custom.ico` 지원 |
26
+ | 4 | 사운드 | `ding.wav` 제거, Web Audio 합성/시스템 소리 |
27
+ | 5 | 라이선스·면책 | MIT + 사용자 주입 에셋 책임은 사용자 |
28
+ | 6 | 패키징 검사 | 배포물에 금지 에셋이 없어야 함 |
29
+ | 7 | 사용자 안내 | 다운로드/배치/적용/제거 방법 |
30
+
31
+ ---
32
+
33
+ ## 1. 기본 원칙
34
+
35
+ 1. **기본값은 라이선스가 명확한 시스템 자산**을 쓴다.
36
+ 2. ** Digital-7, DeepSeek 로고, `ding.wav`는 저장소/배포물에서 제외**한다. 로컬 개발 편의를 위해 남아 있더라도 공개 아티팩트에는 포함하지 않는다.
37
+ 3. 사용자 주입 에셋은 앱이 **감지하면 우선 적용**하고, 없으면 기본값으로 조용히 폴백한다.
38
+ 4. 사용자 주입 에셋의 라이선스/재배포 권리는 **사용자 책임**이며, 프로젝트는 이를 배포하지 않는다.
39
+ 5. 기본 아이콘/코드 외에 제3자 에셋을 포함할 경우 `THIRD-PARTY-NOTICES.md`에 출처/라이선스를 기록한다.
40
+
41
+ ---
42
+
43
+ ## 2. 폰트
44
+
45
+ ### 2.1 기본값
46
+
47
+ - 타이머: `Consolas, "Cascadia Mono", "Segoe UI", monospace` 순서의 시스템 폰트.
48
+ - 일반 UI: `"Segoe UI", system-ui, sans-serif`.
49
+ - 별도 TTF/OTF를 패키지에 넣지 않는다. OS 기본 폰트로 렌더링한다.
50
+
51
+ ### 2.2 사용자 주입(BYO)
52
+
53
+ - 경로: `<widget-data>\fonts\digital-7.ttf` (권장) 또는 `fonts\*.ttf`.
54
+ - 앱은 시작 시 `fonts\digital-7.ttf` 존재 여부를 확인하고, 로드에 성공하면 타이머 폰트로 우선 사용한다.
55
+ - 파일이 없거나 로드에 실패하면 시스템 폰트로 폴백한다. 오류를 띄우지 않는다.
56
+ - README에는 폰트 배포 페이지 링크만 안내한다. 패키지에 폰트 파일을 포함하지 않는다.
57
+ - Digital-7 제작사: <https://www.styleseven.com/>
58
+ - 사용자는 다운로드한 폰트의 라이선스를 직접 확인해야 한다. Digital-7은 제작사 EULA상 가정용/프리웨어 조건이므로, 상업적 사용자는 별도 라이선스를 구매해야 한다.
59
+
60
+ ### 2.3 웹 플러그인
61
+
62
+ - 웹 플러그인은 폰트를 번들하지 않으며, DSH/브라우저의 시스템 폰트를 그대로 쓴다.
63
+ - 웹 알림에는 커스텀 폰트를 적용하지 않는다.
64
+
65
+ ---
66
+
67
+ ## 3. 아이콘·상표
68
+
69
+ ### 3.1 기본 아이콘
70
+
71
+ - 웹 플러그인: `plugin/icon.svg` — 자체 제작한 중립 알람시계 SVG(MIT).
72
+ - 윈도우 위젯: 동일 계열의 중립 시계/타이머 `.ico`. 기본 배포물에 DeepSeek 로고를 넣지 않는다.
73
+ - 트레이/창 아이콘은 중립 아이콘을 기본으로 하고, 사용자가 교체할 수 있다.
74
+
75
+ ### 3.2 DeepSeek 로고
76
+
77
+ - DeepSeek 공식 로고/워드마크/브랜드 자산은 **배포 패키지에서 완전히 제외**한다.
78
+ - 저장소에 남아 있는 로컬 개발용 로고 파일은 공개 아티팩트 빌드에서 제외한다.
79
+ - 사용자가 로컬에서 직접 넣는 경우에도 상표 사용 권한은 사용자 책임이다.
80
+
81
+ ### 3.3 사용자 커스텀 아이콘
82
+
83
+ - 경로: `<widget-data>\icons\custom.ico` (트레이/앱 아이콘), 선택적으로 `icons\custom.png`.
84
+ - 앱은 `custom.ico`가 있으면 우선 사용하고, 없으면 중립 기본 아이콘을 쓴다.
85
+ - 잘못된 ICO/크기 불일치는 무시하고 기본 아이콘으로 폴백한다.
86
+ - 웹 플러그인은 알림 아이콘을 지정하지 않는다(브라우저 기본 표시). 커스텀 아이콘 주입은 위젯 전용이다.
87
+
88
+ ---
89
+
90
+ ## 4. 사운드
91
+
92
+ ### 4.1 웹 플러그인
93
+
94
+ - `ding.wav`를 번들하지 않는다.
95
+ - Web Audio API로 짧은 2음 차임을 합성한다(예: 880Hz/1175Hz, 120ms).
96
+ - 사용자 제스처 전에는 `AudioContext`가 잠겨 있을 수 있으며, 패널의 “소리 켜기”로 활성화한다.
97
+
98
+ ### 4.2 윈도우 위젯
99
+
100
+ - `notify/ding.wav`를 배포물에서 제거한다.
101
+ - 시스템 기본 알림음(`[System.Media.SystemSounds]::Asterisk` 등) 또는 무음 정책을 사용한다.
102
+ - 별도 오디오 파일을 패키지에 넣지 않는다.
103
+
104
+ ---
105
+
106
+ ## 5. 라이선스·면책
107
+
108
+ - 코드는 MIT 라이선스다. [LICENSE](../LICENSE) 참조.
109
+ - **사용자 주입 에셋 면책:** 사용자가 `fonts/`, `icons/`, 사운드 등으로 주입한 제3자 자산의 저작권/상표권/라이선스 준수 책임은 전적으로 사용자에게 있다. 프로젝트 저자와 기여자는 이에 대해 책임지지 않는다.
110
+ - 프로젝트는 사용자 주입 에셋을 수집·배포·호스팅하지 않는다.
111
+ - 소프트웨어는 “있는 그대로(AS IS)” 제공되며, 상품성/특정 목적 적합성/비침해에 대한 보증을 하지 않는다.
112
+ - 기본 패키지에 포함된 자체 제작 아이콘/SVG는 MIT로 배포한다.
113
+ - 향후 OFL 폰트를 기본 포함할 경우, 해당 폰트의 OFL 고지와 저작권을 `THIRD-PARTY-NOTICES.md`에 포함한다.
114
+
115
+ ---
116
+
117
+ ## 6. 패키징 검사
118
+
119
+ 공개 아티팩트(`npm pack`, 위젯 zip)에 다음이 없어야 한다.
120
+
121
+ - [ ] `digital-7.ttf`, 기타 Digital-7 폰트 파일
122
+ - [ ] `deepseek-logo*.png`, `deepseek-*.ico` 등 DeepSeek 브랜드 자산
123
+ - [ ] `ding.wav`, 기타 출처 불명 오디오 파일
124
+ - [ ] `DSH-Notify.exe`, `start.vbs` (SAC/VBScript 문제)
125
+ - [ ] 사용자 `config.json`, 로그, 캐시, 개인 경로
126
+
127
+ 검사 예:
128
+
129
+ ```powershell
130
+ # 저장소에서 금지 에셋이 있는지 확인
131
+ Get-ChildItem -Recurse -File |
132
+ Where-Object { $_.Name -match 'digital-7|deepseek-logo|ding\.wav|DSH-Notify\.exe|start\.vbs' } |
133
+ Select-Object FullName
134
+
135
+ # npm 패키지 내용 확인
136
+ npm pack --dry-run --json
137
+ ```
138
+
139
+ > 로컬 개발용 `ui/assets`에 기존 에셋이 남아 있을 수 있다. 이는 공개 빌드 입력에서 제외하며, 위젯 패키징 단계에서 정리한다.
140
+
141
+ ---
142
+
143
+ ## 7. 사용자 안내(README용)
144
+
145
+ ### 폰트
146
+
147
+ 1. <https://www.styleseven.com/>에서 Digital-7 폰트를 내려받는다.
148
+ 2. 앱 데이터 폴더에 `fonts\digital-7.ttf`로 저장한다.
149
+ 3. 앱을 재시작하면 타이머에 적용된다. 파일이 없으면 Consolas/Segoe UI로 표시된다.
150
+ 4. 폰트 라이선스는 사용자가 직접 확인한다.
151
+
152
+ ### 아이콘
153
+
154
+ 1. 사용할 `.ico` 파일을 준비한다.
155
+ 2. 앱 데이터 폴더에 `icons\custom.ico`로 저장한다.
156
+ 3. 앱을 재시작하면 트레이/창 아이콘에 적용된다.
157
+ 4. 없으면 중립 기본 아이콘이 사용된다.
158
+
159
+ ### 사운드
160
+
161
+ - 웹 플러그인: 패널에서 “소리 켜기” 후 Web Audio 차임 사용.
162
+ - 윈도우 위젯: 시스템 기본 알림음 사용. 별도 파일 없음.
163
+
164
+ ---
165
+
166
+ ## 8. 관련 문서
167
+
168
+ - 웹 플러그인 사양: [2026-10-23-web-notify-plugin-spec.md](2026-10-23-web-notify-plugin-spec.md)
169
+ - 배포 전략 검증: [2026-10-23-deployment-strategy-review.md](2026-10-23-deployment-strategy-review.md)
170
+ - 코드 라이선스: [LICENSE](../LICENSE)