From 74cbc8f6ae7b9055aef7ee917d162f89cd48092d Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Fri, 18 Sep 2026 21:07:00 +0900 Subject: [PATCH 1/9] docs(map): record the 1.3.6 release --- docs/map/00-index.md | 2 +- docs/map/02-infrastructure.md | 2 +- docs/map/11-gap-backlog.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/map/00-index.md b/docs/map/00-index.md index bda0005..6599721 100644 --- a/docs/map/00-index.md +++ b/docs/map/00-index.md @@ -2,7 +2,7 @@ > Status: ACTIVE > Last full audit: 2026-09-13 -> Scope: entire monorepo `D:/workspace/D3ROVoice` at product version `1.3.0` +> Scope: entire monorepo `D:/workspace/D3ROVoice` at product version `1.3.6` > Purpose: let any agent (or human) answer two questions in under a minute: > 1. **What infrastructure exists?** (build, CI, services, APIs, data, packages, deploy) > 2. **How far is each feature developed?** (per surface, with file anchors and status) diff --git a/docs/map/02-infrastructure.md b/docs/map/02-infrastructure.md index 6411555..d8233ab 100644 --- a/docs/map/02-infrastructure.md +++ b/docs/map/02-infrastructure.md @@ -191,7 +191,7 @@ Full detail: [`09-supabase-backend.md`](./09-supabase-backend.md). | File | Purpose | |---|---| -| `release/product-version.json` | version `1.3.0`, `androidVersionCode`/`iosBuildNumber` `1030001`, releaseDate, desktop license keyId | +| `release/product-version.json` | version `1.3.6`, `androidVersionCode`/`iosBuildNumber` `1031006`, releaseDate, desktop license keyId | | `release/android-release-identity.json` | package `com.d3ro.voice`, Play app ID, app-signing SHA-256, upload cert SHA-256, evidence keyId, AdMob unit IDs | | `release/desktop-license-public.pem` | Ed25519 public key for desktop offline licenses | | `release/mobile-release-evidence-public.pem` | Ed25519 public key for mobile release evidence | diff --git a/docs/map/11-gap-backlog.md b/docs/map/11-gap-backlog.md index 131d02b..47d0dc7 100644 --- a/docs/map/11-gap-backlog.md +++ b/docs/map/11-gap-backlog.md @@ -53,7 +53,7 @@ Legend: `[ ]` open · `[~]` in progress · `[!]` blocked externally · `[x]` res | GAP-REL-04 | Release | canonical feed는 Cloudflare 뒤에 있어 업로드 본문이 **100MiB**를 넘으면 HTTP 413으로 거부한다. | `scripts/ci/publish-updater-release.mjs`, `docs/deployment/unsigned-distribution.md` | `[~]` 2026-09-18: 설치본을 90.6MiB로 줄여 업데이트 피드 게시를 복구했다(GAP-STT-07). 휴대용/Scoop 채널은 여전히 95MiB 분할이 필요하다. | | GAP-STT-07 | Local STT | 진(사이드카)을 앱 번들에 넣으면 설치본이 100MiB를 넘고 매 업데이트마다 162MiB를 다시 받는다. | `apps/desktop/src/main/services/RuntimeProvisioner.ts`, `apps/desktop/electron-builder.yml` | `[x]` 2026-09-18: 설치본에서 엔진/ffmpeg를 제거하고 처음 필요할 때 `runtime-latest`에서 내려받는다(부품별 + 결합본 SHA-256 검증). 설치본 189MB → 90.6MiB, 런타임 1회 116MiB(엔진 94.4 + ffmpeg 21.7). 실제 feed로 통합 검증 완료. | | GAP-STT-06 | Local STT | Decode settings were untuned: previous-text conditioning let repeated hallucinations compound, and no VAD parameters meant slow, uneven segments. | `apps/desktop/sidecar/main.py` | `[x]` 2026-09-18: `condition_on_previous_text=false`, bounded low-temperature fallback, `no_speech`/`compression_ratio`/`log_prob` thresholds, 300 ms silence trimming. Same transcript, ~5x faster on the reference machine (7.7 s audio: 1609 ms → 303 ms). | -| GAP-STT-08 | Local STT | 1.3.5 설치본에서 엔진 설치가 "런타임 아카이브 해시 불일치 (sidecar)"로 항상 실패했다. 부품 검증은 **메모리 스트림**에서 센 값으로, 결합 검증은 **디스크 파일**에서 계산해 기준이 서로 달랐다. 디스크 쓰기가 잘려도 부품 검사를 통과하고 결합 단계에서만 터지므로 원인 파악도 불가능했다. 재시도가 없어 전송이 한 번 끊기면 곧바로 설치 실패였다. | `apps/desktop/src/main/services/RuntimeProvisioner.ts` | `[x]` 2026-09-18: 부품 크기·해시를 디스크 파일 기준으로 통일하고, 결합본은 크기를 먼저 검사한 뒤 해시를 본다(오류 메시지에 실제/기대값 포함). 부품 다운로드는 실패 시 해당 파일을 지우고 최대 3회 재시도한다. 서버 아티팩트는 무결함을 확인했고(부품 2개 해시 일치, 결합본 `e203aa53…` = 인덱스 기대값), 실제 feed로 설치를 재현해 18초 만에 성공. | +| GAP-STT-08 | Local STT | 1.3.5 설치본에서 엔진 설치가 "런타임 아카이브 해시 불일치 (sidecar)"로 항상 실패했다. 부품 검증은 **메모리 스트림**에서 센 값으로, 결합 검증은 **디스크 파일**에서 계산해 기준이 서로 달랐다. 디스크 쓰기가 잘려도 부품 검사를 통과하고 결합 단계에서만 터지므로 원인 파악도 불가능했다. 재시도가 없어 전송이 한 번 끊기면 곧바로 설치 실패였다. | `apps/desktop/src/main/services/RuntimeProvisioner.ts` | `[x]` 2026-09-18: 부품 크기·해시를 디스크 파일 기준으로 통일하고, 결합본은 크기를 먼저 검사한 뒤 해시를 본다(오류 메시지에 실제/기대값 포함). 부품 다운로드는 실패 시 해당 파일을 지우고 최대 3회 재시도한다. 서버 아티팩트는 무결함을 확인했고(부품 2개 해시 일치, 결합본 `e203aa53…` = 인덱스 기대값), 실제 feed로 설치를 재현해 18초 만에 성공. **1.3.6으로 게시 완료** — `latest.yml`이 1.3.6/90.6MiB를 서빙하고 설치본 sha512가 피드 메타데이터와 일치. 설치본 asar에 수정 코드가 포함되고 구버전 `archiveHash` 경로는 제거됨을 확인. | --- From ae7efb6acf0133c37c590df9aeffcd17d30f74a0 Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Sat, 19 Sep 2026 08:24:03 +0900 Subject: [PATCH 2/9] fix(desktop): render popup overlays in packaged builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Popup pages loaded their scripts as classic + + diff --git a/apps/desktop/src/renderer/popups/command-popup/index.html b/apps/desktop/src/renderer/popups/command-popup/index.html index 664087f..996a62f 100644 --- a/apps/desktop/src/renderer/popups/command-popup/index.html +++ b/apps/desktop/src/renderer/popups/command-popup/index.html @@ -19,6 +19,7 @@ - + + diff --git a/apps/desktop/src/renderer/popups/history-popup/index.html b/apps/desktop/src/renderer/popups/history-popup/index.html index 780a1fb..0a461e5 100644 --- a/apps/desktop/src/renderer/popups/history-popup/index.html +++ b/apps/desktop/src/renderer/popups/history-popup/index.html @@ -17,6 +17,7 @@ - + + diff --git a/apps/desktop/src/renderer/popups/recording-tip/index.html b/apps/desktop/src/renderer/popups/recording-tip/index.html index 58ea4ba..623064c 100644 --- a/apps/desktop/src/renderer/popups/recording-tip/index.html +++ b/apps/desktop/src/renderer/popups/recording-tip/index.html @@ -34,6 +34,7 @@ - + + diff --git a/apps/desktop/src/renderer/popups/result-popup/index.html b/apps/desktop/src/renderer/popups/result-popup/index.html index 552fe47..6457d33 100644 --- a/apps/desktop/src/renderer/popups/result-popup/index.html +++ b/apps/desktop/src/renderer/popups/result-popup/index.html @@ -23,6 +23,7 @@ - + + diff --git a/docs/map/00-index.md b/docs/map/00-index.md index 6599721..3cff6b7 100644 --- a/docs/map/00-index.md +++ b/docs/map/00-index.md @@ -2,6 +2,7 @@ > Status: ACTIVE > Last full audit: 2026-09-13 +> Last update: 2026-09-19 — GAP-INFRA-05 (desktop renderer popup bundle verification wired into CI) > Scope: entire monorepo `D:/workspace/D3ROVoice` at product version `1.3.6` > Purpose: let any agent (or human) answer two questions in under a minute: > 1. **What infrastructure exists?** (build, CI, services, APIs, data, packages, deploy) diff --git a/docs/map/02-infrastructure.md b/docs/map/02-infrastructure.md index d8233ab..fabfa53 100644 --- a/docs/map/02-infrastructure.md +++ b/docs/map/02-infrastructure.md @@ -78,6 +78,7 @@ npm run release:metadata[:test] npm run release:forgejo[:check] # canonical Forgejo publisher/feed npm run release:tag # annotated/signed immutable release tag npm run security:secrets[:test] # hardcoded-secret scanner +npm run check:desktop-renderer[:test] # built renderer pages reference only assets on disk npm run test:e2e:red # content-report red e2e npm run release:mobile:boundary[:test] npm run release:mobile:config[:test] @@ -136,7 +137,7 @@ See [`03-shared-packages.md`](./03-shared-packages.md). Summary: ### GitLab CI (`.gitlab-ci.yml`) -Stages `validate → test → build → e2e → package → publish → deploy`. Primary pipeline for desktop Windows/macOS releases (Forgejo Generic Registry is the canonical updater feed; GitLab project 1172 is a legacy mirror) and production mobile releases (`mobile-production-release`, manual/protected). Admin NAS deploy job is intentionally **disabled**. `package-windows`/`package-macos` build the faster-whisper sidecar (`sidecar:setup` → `sidecar:build`) and run `scripts/ci/verify-sidecar-bundle.mjs` before electron-builder, so a release can never ship without the local STT engine. +Stages `validate → test → build → e2e → package → publish → deploy`. Primary pipeline for desktop Windows/macOS releases (Forgejo Generic Registry is the canonical updater feed; GitLab project 1172 is a legacy mirror) and production mobile releases (`mobile-production-release`, manual/protected). Admin NAS deploy job is intentionally **disabled**. `package-windows`/`package-macos` build the faster-whisper sidecar (`sidecar:setup` → `sidecar:build`) and run `scripts/ci/verify-sidecar-bundle.mjs` before electron-builder, so a release can never ship without the local STT engine. Every pipeline that runs `npm run build --workspace=@d3ro/desktop` (`.forgejo` release/portable, `.github` CI/release) then runs `scripts/ci/verify-desktop-renderer-bundles.mjs`, which fails packaging when a renderer page references an asset the build did not emit (GAP-INFRA-05). ### Forgejo Actions (`.forgejo/workflows/`) `portable.yml` — 태그/수동 실행으로 **서명 없이** portable 채널(95MiB 7z 분할 볼륨 + Scoop 매니페스트 + 설치 스크립트)을 게시한다. `WIN_CSC_*` 불필요, updater feed는 건드리지 않는다. diff --git a/docs/map/04-desktop-app.md b/docs/map/04-desktop-app.md index dd6e5df..317ae42 100644 --- a/docs/map/04-desktop-app.md +++ b/docs/map/04-desktop-app.md @@ -146,6 +146,12 @@ Preload exposes **`window.electronAPI`** with 33 namespaces: `platform, audio, c `windows/WindowManager.ts` creates 6 windows: main (borderless, custom TitleBar; macOS `hiddenInset`), recording-tip, result-popup, history-popup, command-popup, caption-overlay. Injects popup theme CSS + i18n strings; 2-phase resize. `windows/TrayManager.ts` — tray icon + menu + double-click show. +**Popup invariants** (each shipped broken once — do not regress): + +- 팝업 HTML의 스크립트는 반드시 `') + const goodProblems = collectProblems(goodRoot, pages) + if (goodProblems.length !== 0) { + failures.push(`complete build reported problems: ${goodProblems.join('; ')}`) + } + + const brokenRoot = path.join(tmpRoot, 'broken') + bundlePage(brokenRoot, '') + const brokenProblems = collectProblems(brokenRoot, pages) + if (!brokenProblems.some((problem) => problem.includes('missing asset'))) { + failures.push('missing asset was not detected') + } + if (!brokenProblems.some((problem) => problem.includes('classic script'))) { + failures.push('classic script tag was not detected') + } + + const missingPageProblems = collectProblems(goodRoot, ['popups/absent/index.html']) + if (!missingPageProblems.some((problem) => problem.startsWith('missing built page'))) { + failures.push('missing page was not detected') + } + } finally { + rmSync(tmpRoot, { recursive: true, force: true }) + } + + if (failures.length > 0) { + console.error('verify-desktop-renderer-bundles self-test failed:') + for (const failure of failures) console.error(`- ${failure}`) + process.exit(1) + } + console.log('verify-desktop-renderer-bundles self-test: OK') +} + +if (process.argv.slice(2).includes('--self-test')) { + selfTest() +} else if (!existsSync(builtRendererDir)) { + console.error(`Renderer build not found: ${builtRendererDir}`) + console.error(' build: npm run build --workspace=@d3ro/desktop') + process.exit(1) +} else { + const pages = expectedPages() + const problems = collectProblems(builtRendererDir, pages) + + if (problems.length > 0) { + console.error('Desktop renderer bundle verification failed:') + for (const problem of problems) console.error(`- ${problem}`) + console.error(' rebuild: npm run build --workspace=@d3ro/desktop') + process.exit(1) + } + + console.log(`Desktop renderer bundle verification passed: ${pages.length} page(s) with all assets on disk`) +} \ No newline at end of file From 05f0aaa6603738b5c0c9445b12e411e04e0133bf Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Sat, 19 Sep 2026 08:24:13 +0900 Subject: [PATCH 3/9] chore(release): 1.3.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💘 Generated with Crush Assisted-by: Crush:deepseek-v4.1-flash --- CHANGELOG.md | 11 ++++++++++ apps/admin-swagger/openapi.json | 2 +- apps/admin/package.json | 2 +- apps/api-server/D3ROVoice.Api.csproj | 2 +- apps/desktop/package.json | 2 +- apps/mobile-rn/android/app/build.gradle | 4 ++-- .../ios/D3ROVoice.xcodeproj/project.pbxproj | 8 ++++---- .../android/en-US/changelogs/1031007.txt | 1 + .../android/ko-KR/changelogs/1031007.txt | 1 + apps/mobile-rn/package-lock.json | 14 ++++++------- apps/mobile-rn/package.json | 2 +- apps/web/package.json | 2 +- apps/web/src/components/layout/sidebar.tsx | 2 +- package-lock.json | 20 +++++++++---------- package.json | 4 +++- packages/api-client/package.json | 2 +- packages/core/package.json | 2 +- packages/i18n/package.json | 2 +- packages/ui-native/package.json | 2 +- packages/ui/package.json | 2 +- release/product-version.json | 8 ++++---- site/package-lock.json | 4 ++-- site/package.json | 2 +- 23 files changed, 58 insertions(+), 43 deletions(-) create mode 100644 apps/mobile-rn/metadata/android/en-US/changelogs/1031007.txt create mode 100644 apps/mobile-rn/metadata/android/ko-KR/changelogs/1031007.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index f6f813e..f3aaa8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Cloud-optional backup (encrypted, opt-in) - Plugin system for custom pipelines +## [1.3.7] - 2026-09-19 + +### Fixed +- **Recording and live caption overlays never worked in installed builds.** Popup + pages loaded their scripts as classic `