From a098ebd74d8a039e2bb780862a4004501aaf86a4 Mon Sep 17 00:00:00 2001 From: Leon Stadler Date: Tue, 29 Sep 2026 09:44:18 +0200 Subject: [PATCH 1/3] feat: automate release notes from pull requests (refs #8) --- .github/PULL_REQUEST_TEMPLATE.md | 20 ++ .github/release.yml | 25 ++ .github/workflows/release.yml | 21 +- AGENTS.md | 8 +- changelog.md | 313 +----------------------- docs/distribution.md | 6 +- scripts/generate_macos_release_notes.sh | 73 ++++++ 7 files changed, 144 insertions(+), 322 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/release.yml create mode 100755 scripts/generate_macos_release_notes.sh diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..8e3f418 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +## Summary + + + +## Validation + + + +## Release notes + +Before merging, apply exactly one category label to this PR: + +- `enhancement` — user-facing feature or improvement +- `bug` — behavior correction +- `breaking-change` — incompatible behavior or migration +- `documentation` — documentation-only change +- `maintenance` — internal tooling, dependencies, or maintenance +- `skip-release-notes` — no user-facing release note is needed + +The release workflow includes PR titles, grouped by these labels, and identifies contributors automatically. Keep the title concise and avoid putting issue references alone in the title. diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..ae2be51 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,25 @@ +changelog: + exclude: + labels: + - skip-release-notes + authors: + - dependabot[bot] + categories: + - title: "⚠️ Breaking changes" + labels: + - breaking-change + - title: "✨ Features and improvements" + labels: + - enhancement + - title: "🐛 Bug fixes" + labels: + - bug + - title: "📚 Documentation" + labels: + - documentation + - title: "🧰 Maintenance" + labels: + - maintenance + - title: "Other changes" + labels: + - "*" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 295bd7d..222466a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,7 @@ jobs: runs-on: macos-26 permissions: contents: write + pull-requests: read env: GH_TOKEN: ${{ github.token }} HOMEBREW_NO_AUTO_UPDATE: "1" @@ -36,6 +37,7 @@ jobs: uses: actions/checkout@v5 with: ref: main + fetch-depth: 0 submodules: recursive - name: Verify release source and version @@ -81,23 +83,20 @@ jobs: set -euo pipefail MAIN_SHA="$(git ls-remote origin refs/heads/main | awk '{print $1}')" [[ "$MAIN_SHA" == "$GITHUB_SHA" ]] || { echo "main moved during the build; rerun from the current main commit." >&2; exit 1; } + PREVIOUS_TAG="$(gh release list --limit 100 \ + --json tagName,isDraft,isPrerelease,publishedAt \ + | jq -er '[.[] | select(.isDraft == false and .isPrerelease == false)] | sort_by(.publishedAt) | last | .tagName')" NOTES_FILE="${RUNNER_TEMP}/release-notes.md" - cat >"${NOTES_FILE}" < " >&2 + exit 2 +fi + +RELEASE_VERSION="$1" +SOURCE_COMMIT="$2" +PREVIOUS_TAG="$3" +OUTPUT_FILE="$4" +GITHUB_REPOSITORY_VALUE="${GITHUB_REPOSITORY:-LeonStadler/Cortexa}" +RELEASE_TAG="v${RELEASE_VERSION}" + +[[ "${RELEASE_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { + echo "Release version must use MAJOR.MINOR.PATCH: ${RELEASE_VERSION}" >&2 + exit 2 +} +[[ "${SOURCE_COMMIT}" =~ ^[0-9a-f]{40}$ ]] || { + echo "Source commit must be a full lowercase Git SHA: ${SOURCE_COMMIT}" >&2 + exit 2 +} +[[ -n "${PREVIOUS_TAG}" ]] || { + echo "A previous published release tag is required to generate release notes." >&2 + exit 2 +} +git cat-file -e "${SOURCE_COMMIT}^{commit}" +git rev-parse --verify "refs/tags/${PREVIOUS_TAG}^{commit}" >/dev/null +git merge-base --is-ancestor "${PREVIOUS_TAG}" "${SOURCE_COMMIT}" || { + echo "Previous release ${PREVIOUS_TAG} is not an ancestor of ${SOURCE_COMMIT}." >&2 + exit 1 +} + +NOTES_RESPONSE="$(gh api --method POST \ + "repos/${GITHUB_REPOSITORY_VALUE}/releases/generate-notes" \ + -f "tag_name=${RELEASE_TAG}" \ + -f "target_commitish=${SOURCE_COMMIT}" \ + -f "previous_tag_name=${PREVIOUS_TAG}" \ + -f "configuration_file_path=.github/release.yml")" +GENERATED_NOTES="$(jq -r '.body' <<<"${NOTES_RESPONSE}")" + +DIRECT_COMMITS="$(git rev-list --no-merges "${PREVIOUS_TAG}..${SOURCE_COMMIT}")" +DIRECT_NOTES=() +while IFS= read -r COMMIT; do + [[ -n "${COMMIT}" ]] || continue + ASSOCIATED_PR_COUNT="$(gh api "repos/${GITHUB_REPOSITORY_VALUE}/commits/${COMMIT}/pulls" --jq 'length')" + [[ "${ASSOCIATED_PR_COUNT}" == "0" ]] || continue + + SUBJECT="$(git show -s --format=%s "${COMMIT}")" + AUTHOR="$(git show -s --format=%an "${COMMIT}")" + DIRECT_NOTES+=("- ${SUBJECT} — ${AUTHOR} (${COMMIT:0:7})") +done <<<"${DIRECT_COMMITS}" + +{ + printf '## Cortexa %s — macOS, Apple Silicon\n\n' "${RELEASE_VERSION}" + + if [[ "${#DIRECT_NOTES[@]}" -gt 0 ]]; then + printf '### Direct commits\n\n' + printf '%s\n' "${DIRECT_NOTES[@]}" + printf '\n' + fi + + printf '%s\n\n' "${GENERATED_NOTES}" + + cat <<'EOF' +### Download and install + +The DMG targets Apple Silicon (arm64). This open-source build is ad-hoc signed and is not notarized; macOS may ask you to approve the first launch. See the included install notes. Speech models are downloaded by the app when needed. +EOF + + printf '\nSource commit: %s\n' "${SOURCE_COMMIT}" +} >"${OUTPUT_FILE}" From b68029263cb12562d01ed07f569def751f3952b7 Mon Sep 17 00:00:00 2001 From: Leon Stadler Date: Tue, 29 Sep 2026 09:48:07 +0200 Subject: [PATCH 2/3] docs: preserve complete changelog in release notes PR --- changelog.md | 309 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 305 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index 1af5db8..f5f2e44 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,3 @@ -Warning: truncated output (original token count: 31563) -Total output lines: 765 - # Changelog ## Fixes @@ -163,7 +160,311 @@ Total output lines: 765 - 2026-09-23: DMG-Installationshintergrund passend zum Finder-Fenster skaliert und ausgerichtet. - Dateien: `apps/macos/AppShell/Resources/CortexaInstallerBackground.svg`, `scripts/create_macos_dmg.sh`, `Tests/DocsContractTests/DocsContractTests.swift`, `docs/distribution.md`, `VERSION` - - Funktionalität: Das Motiv nutzt eine 800 × 500-Leinwand passend zum Finder-Fenster. `sips` rendert die SVG direkt; `create-dmg` speichert Hintergrund, Fenstergröße, App- und Programme-Position gemeinsam in der Finder-Metadatei. Dadurch hängt die Darstellung nicht mehr von einem relativen AppleScript-Dateipfad oder einem bereits geöffneten gleichnamigen Volume ab. Die Version wu…15563 tokens truncated…rendert; danach bauen sowohl das macOS-App-Target (`WisprLocalMac`) als auch das iOS-Projekt mit Keyboard-Extension (`WisprLocaliOS`) erfolgreich per `xcodebuild`. + - Funktionalität: Das Motiv nutzt eine 800 × 500-Leinwand passend zum Finder-Fenster. `sips` rendert die SVG direkt; `create-dmg` speichert Hintergrund, Fenstergröße, App- und Programme-Position gemeinsam in der Finder-Metadatei. Dadurch hängt die Darstellung nicht mehr von einem relativen AppleScript-Dateipfad oder einem bereits geöffneten gleichnamigen Volume ab. Die Version wurde als Patch-Bugfix auf `0.30.2` angehoben. + +- 2026-09-16: Settings-Navigation und Hilfen an die nativen macOS-/Liquid-Glass-Empfehlungen angepasst. + - Dateien: `apps/macos/AppShell/SettingsViewShell.swift`, `apps/macos/AppShell/SettingsFormPageSupport.swift`, `apps/macos/AppShell/SettingsChromeComponents.swift`, `VERSION`, `Tests/DocsContractTests/DocsContractTests.swift` + - Funktionalität: Die Einstellungen verwenden ein ausgewogenes natives `NavigationSplitView`-Layout mit systemverwalteter Sidebar- und Hintergrunddarstellung. Die Sidebar wird nicht mit einer opaken eigenen Fläche übermalt und kann ihre macOS-27-Liquid-Glass-Darstellung adaptiv übernehmen. Die globale Suche liegt im systemeigenen Toolbar-Platz; die nativen Formularabschnitte besitzen nur noch einen Scrollcontainer, sodass alle Modelle erreichbar bleiben. Info-Hilfen behalten den systemeigenen Hover-Text und öffnen per Klick oder Tastatur ein zugängliches Popover. Die Version wurde auf `0.30.1` angehoben. + +- 2026-09-16: DMG-Installationshintergrund zuverlässig im Finder-Layout gespeichert. + - Dateien: `scripts/create_macos_dmg.sh`, `apps/macos/AppShell/Resources/CortexaInstallerBackground.svg` + - Funktionalität: Die DMG-Erstellung nutzt ein beschreibbares Zwischenimage, rendert das minimalistische Hintergrundmotiv als PNG und speichert die Finder-Hintergrundmetadaten vor der Komprimierung. Dadurch bleibt das Bild beim Öffnen des fertigen DMG sichtbar. + +- 2026-09-13: macOS-Berechtigungen bleiben bei korrekt signierten Cortexa-Updates an dieselbe App-Identität gebunden; der Bedienungshilfen-Flow verlangt kein routinemäßiges Entfernen und Neu-Hinzufügen mehr. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/PermissionCoordinator.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `apps/macos/AppShell/SettingsViewGeneralSections.swift`, `apps/macos/AppShell/BuildPermissionFingerprint.swift` (entfernt), `scripts/archive_macos_release.sh`, `scripts/smoke_test_macos_app.sh`, `scripts/preflight_macos_release.sh`, `Tests/AppShellSupportTests/AppShellCharacterizationTests.swift`, `Tests/AppShellSupportTests/PermissionCoordinatorTests.swift`, `Tests/AppShellSupportTests/BuildPermissionFingerprintTests.swift` (entfernt), `Tests/DocsContractTests/PermissionRecoveryContractTests.swift`, `Tests/DocsContractTests/DocsContractTests.swift`, `docs/permissions-macos.md`, `docs/macos-release-checklist.md`, `docs/distribution.md`, `README.md`, `VERSION` + - Funktionalität: Release-Archive ohne persistente Apple-Signatur werden abgelehnt; nach dem Archivieren prüft das Script Apple-Authority, TeamIdentifier und die Codesign-Integrität. Dadurch können keine ad-hoc-signierten Update-Artefakte mehr die TCC-Identität wechseln. Die App nutzt Apples `AXIsProcessTrustedWithOptions` nur nach einem expliziten Klick auf „Freigabe anfragen“, öffnet dabei direkt die Bedienungshilfen und fragt beim Start eines Diktats nicht wiederholt nach. Die frühere Build-Fingerprint-Heuristik und „Neu verknüpfen“-Banner wurden entfernt, weil sie einen normalen Denial fälschlich als kaputte Verknüpfung behandelten. Der Debug-Smoke-Test kennzeichnet ad-hoc-Signaturen ausdrücklich als ungeeignet für eine Berechtigungs-Persistenz-Aussage. Die Version wurde als Patch-Bugfix auf `0.29.6` angehoben. + +- 2026-09-13: Unterbrochene Speech-Modell-Downloads hinterlassen keine verwendbaren Teilmodelle mehr; kombinierte Diktat- und AI-Pfade sind als Testmatrix abgesichert. + - Dateien: `Sources/ASRCore/VoiceModelInstaller.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/DictationRuntimeServices.swift`, `Tests/ASRCoreTests/VoiceModelDownloadWorkspaceTests.swift`, `Tests/AIProcessingCoreTests/AIProcessingServiceTests.swift`, `Tests/AppShellSupportTests/DictationRuntimeServicesTests.swift`, `Tests/AppShellSupportTests/SessionConfigurationBuilderTests.swift`, `Tests/DocsContractTests/DocsContractTests.swift`, `docs/distribution.md`, `VERSION` + - Funktionalität: Modell-Downloads schreiben erst in einen privaten temporären Ordner und anschließend in eine versteckte Staging-Datei. Erst eine vollständige Datei wird atomar als installierte `.bin` veröffentlicht. Normale Fehler entfernen die Staging-Datei sofort; nach App-Abbruch zurückgebliebene Cortexa-Workspaces und `.partial`-Dateien werden beim nächsten Runtime-Sync gezielt entfernt, ohne fertige Modelle oder fremde temporäre Dateien anzutasten. Die neue Testmatrix prüft Live-/Final-AI an und aus, Streaming-/Finalize- und Clipboard-Zustellung, den Wechsel auf ein neu fokussiertes Textziel, den fehlenden-Ziel-Fallback sowie Promotion, Fehlererhalt und Recovery von Modelldateien. Die Version wurde als Patch-Bugfix auf `0.29.5` angehoben. + +- 2026-09-13: Live-Diktate werden beim Stoppen nicht mehr doppelt eingefügt, und neue Diktate verwenden kein veraltetes Textziel mehr. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/DictationRuntimeServices.swift`, `apps/macos/AppShell/SpeechModelController.swift`, `Tests/AppShellSupportTests/DictationRuntimeServicesTests.swift`, `Tests/AppShellSupportTests/SpeechModelControllerTests.swift`, `Tests/DocsContractTests/DocsContractTests.swift`, `VERSION` + - Funktionalität: Für eine aktive Live-Text-Sitzung ersetzt der Finalpfad den bereits eingefügten Live-Text unabhängig von der allgemeinen Option für simulierte Tastatureingaben. Damit wird das finale ASR- oder AI-Ergebnis nicht zusätzlich hinter den vorläufigen Text gesetzt. Fehlt beim Start oder während des Wartens ein aktuelles Textziel, wartet Cortexa nun auf ein neu fokussiertes Feld statt ein Textfeld einer älteren Sitzung wiederzuverwenden. Fortschritte beim Modell-Download werden nur noch in sinnvollen 5-Prozent-Schritten an den globalen UI-State weitergegeben; das reduziert unnötige Neuaufbauten des offenen Menüleistenmenüs. Die Version wurde als Patch-Bugfix auf `0.29.4` angehoben. + +- 2026-09-12: Runtime-Update erkennt gleich große Dateien mit identischem Zeitstempel nun inhaltsbasiert. + - Dateien: `Sources/ASRCore/BundledWhisperRuntime.swift`, `Tests/ASRCoreTests/BundledWhisperRuntimeTests.swift`, `Tests/DocsContractTests/DocsContractTests.swift`, `VERSION` + - Funktionalität: Die Synchronisierung vergleicht bei gleichen Dateimetadaten zusätzlich den Inhalt, bevor sie eine vorhandene `whisper-cli` beibehält. Dadurch kann eine veraltete, dynamisch gelinkte CLI nicht mehr als aktuell durchrutschen, wenn ihre Größe und ihr Zeitstempel zufällig mit der korrigierten CLI übereinstimmen. Die Version wurde als Patch-Bugfix auf `0.29.3` angehoben. + +- 2026-09-12: Nicht startbare Whisper-Runtime im installierten Cortexa-Bundle behoben und ASR-E2E-Prüfung ergänzt. + - Dateien: `Sources/ASRCore/BundledWhisperRuntime.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `scripts/build_whisper_xcframework.sh`, `scripts/prepare_runtime_bundle.sh`, `scripts/verify_whisper_cli_runtime.sh`, `scripts/smoke_test_macos_app.sh`, `Tests/ASRCoreTests/BundledWhisperRuntimeTests.swift`, `Tests/DocsContractTests/DocsContractTests.swift`, `apps/macos/README.md`, `docs/distribution.md`, `docs/macos-release-checklist.md`, `VERSION` + - Funktionalität: `whisper-cli` wird statisch gegen Whisper/GGML gebaut und enthält dadurch keine absoluten `@rpath`-Verweise auf den Entwicklungsrechner mehr. Build und Bundle-Vorbereitung lehnen nicht portable dynamische Abhängigkeiten ab und führen einen echten Start-Probe aus. Die App meldet „ASR CLI runtime ready“ erst nach einem erfolgreichen CLI-Start. Der macOS-Smoke-Test transkribiert zusätzlich synthetisierte Sprache mit der CLI und dem Standardmodell aus dem gebauten App-Bundle. Die Version wurde als Patch-Bugfix auf `0.29.2` angehoben. + +- 2026-09-11: macOS-Einstellungsfenster stabilisiert und Sidebar-/Glass-Darstellung korrigiert. + - Dateien: `apps/macos/AppShell/SettingsViewShell.swift`, `apps/macos/AppShell/MacNativeDesign.swift`, `VERSION` + - Funktionalität: Die Sidebar verwendet wieder ausschließlich die native `NavigationSplitView`-/Source-List-Darstellung. Der zusätzliche Hintergrund-Extension-Effekt und der globale Fenster-Hintergrund, die den Liquid-Glass-/Scroll-Edge-Effekt überlagerten, wurden entfernt. Die Sidebar-Breite ist kompakter und verhindert, dass die Detailspalte bei üblichen Fenstergrößen seitlich wegdrückt. Die Version wurde als Patch-Bugfix auf `0.29.1` angehoben. + +- 2026-09-02: Wiederholte macOS-Schlüsselbundabfragen beim Öffnen der Einstellungen behoben. + - Dateien: `apps/macos/AppShell/AIRemoteProviderSecretStore.swift`, `VERSION` + - Funktionalität: Geladene API-Schlüssel werden innerhalb einer App-Sitzung zwischengespeichert. Dadurch lösen erneute SwiftUI-Neuberechnungen und AI-Stack-Aktualisierungen keine wiederholten Abfragen desselben Schlüsselbund-Eintrags mehr aus. Beim Speichern und Löschen wird der Cache konsistent aktualisiert. Die Version wurde als Patch-Bugfix auf `0.28.1` angehoben. + +## Features + +- 2026-09-02: Cortexa-Menübar, Modellverwaltung, Dictionary und AppIcon nach UI-Review geschärft. + - Dateien: `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/SettingsViewShell.swift`, `apps/macos/AppShell/SettingsFormPages.swift`, `apps/macos/AppShell/SettingsTab.swift`, `apps/macos/AppShell/SettingsViewSpeechDictationSections.swift`, `apps/macos/AppShell/SettingsViewProductivitySections.swift`, `apps/macos/AppShell/SettingsViewGeneralSections.swift`, `apps/macos/AppShell/SettingsChromeComponents.swift`, `apps/macos/AppShell/MacAppStatePersistenceFacade.swift`, `apps/macos/AppShell/Resources/Assets.xcassets/AppIcon.appiconset`, `scripts/archive_macos_release.sh`, `docs/permissions-macos.md`, `Tests/AppShellSupportTests/AppShellCharacterizationTests.swift`, `Tests/AppShellSupportTests/SpeechModelControllerTests.swift`, `Tests/DocsContractTests/DocsContractTests.swift`, `VERSION` + - Funktionalität: Nicht installierte Speech-Modelle starten aus der Menüleiste direkt den bestehenden Download-/Auswahlpfad. Die Modellverwaltung enthält Suche sowie Filter für Installationsstatus und Sprachumfang. Sprachlisten sortieren `Auto` immer an erster Stelle. Gespeicherte Dictionary-Begriffe können nachträglich in Begriff, Kategorie und Sprachcode bearbeitet werden; JSON-Import/-Export liegt als Toolbar-Aktion im Dictionary-Tab. Speech- und Advanced-Erklärtexte wurden in den Info-Button verlagert. Berechtigungsstatus werden nutzerfreundlicher als `Freigegeben`/`Nicht freigegeben` angezeigt, inklusive Hinweis auf alte `WisprLocalMac`-TCC-Einträge. Das Statusleistensymbol nutzt explizit monochrome SF-Symbol-Darstellung, das Dock-AppIcon wurde aus den offiziellen Apple-Icon-Composer-Exports aktualisiert, und der lokale Release-Archive-Pfad kann ein validiertes vorhandenes `.xcodeproj` nutzen, wenn `xcodegen` nicht installiert ist. Das macOS-Produkt wird in Info.plist, Xcode-Produkt, App-Bundle, Archiv, DMG und Smoke-Test als `Cortexa` geführt; Target, Scheme, Projektpfad und Bundle-ID `com.wisprlocal.mac` bleiben für technische Kontinuität unverändert. Die Version wurde als Minor-Feature-Release auf `0.28.0` angehoben. + - Rename-Radius: `apps/macos/WisprLocalMac/project.yml`, `apps/macos/WisprLocalMac/WisprLocalMac-Info.plist`, `scripts/archive_macos_release.sh`, `scripts/export_macos_release.sh`, `scripts/create_macos_dmg.sh`, `scripts/smoke_test_macos_app.sh`, `scripts/generate_sparkle_appcast.sh`, `scripts/generate_macos_xcodeproj.sh`, `README.md`, `docs/distribution.md`, `docs/macos-release-checklist.md` führen die erzeugten Produktartefakte konsistent als `Cortexa.app`, `Cortexa.xcarchive` und `Cortexa.dmg`; technische Target-/Scheme-/Projektpfade und `com.wisprlocal.mac` bleiben unverändert. + - Sichtbares Branding: `OnboardingView.swift`, `SparkleUpdaterController.swift`, `DiagnosticsController.swift`, `SettingsViewAISections.swift`, `AIProviderController.swift`, `AIProcessingTypes.swift`, `SettingsViewGeneralSections.swift`, `scripts/preflight_macos_release.sh` und die Dokumentationsindizes verwenden `Cortexa`; `Cortexa.icon` ist als primäres Icon-Composer-Asset mit automatischer Appearance-/Fill-Anpassung, Translucency und expliziter heller Dark-Appearance-Glyph-Variante eingebunden, `AppIcon.appiconset` enthält vollständige macOS-Größen im Default-/Light-Modus plus Dark-Luminosity-Varianten, und das About-Fenster rendert das eingebundene `CortexaLogoHorizontal`-Asset adaptiv als Template. + - Icon-Quelle bereinigt: `apps/macos/AppShell/Resources/Assets.xcassets/AppIcon.appiconset` mit den alten PNG-Dock-Varianten wurde entfernt. Das macOS-Target verwendet ausschließlich `apps/macos/AppShell/Resources/Cortexa.icon`; die sechs gelieferten Appearance-Exporte liegen unverändert unter `cortexa_logos/Icon Exports` als Design-Referenz. + +- 2026-07-03: Cortexa-Release-Launch, Menüleisten-Capabilities und Speech-Settings konsolidiert. + - Dateien: `apps/macos/WisprLocalMac/WisprLocalMac-Info.plist`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/SettingsWindowPresenter.swift`, `apps/macos/AppShell/Onboarding/OnboardingWindowPresenter.swift`, `apps/macos/AppShell/SettingsTab.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/SettingsFormPages.swift`, `apps/macos/AppShell/SettingsViewShell.swift`, `apps/macos/AppShell/SettingsViewGeneralSections.swift`, `apps/macos/AppShell/SettingsViewSpeechDictationSections.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/SpeechModelController.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `Tests/AppShellSupportTests/SpeechModelControllerTests.swift`, `Tests/AppShellSupportTests/SettingsTabTests.swift`, `docs/distribution.md`, `VERSION` + - Funktionalität: Die App zeigt sichtbar `Cortexa`, behält die technische Bundle-ID bei und öffnet beim ersten sichtbaren Launch ein Settings-/Setup-Fenster, damit Release-/DMG-Starts nicht wie ein No-op wirken. Speech nutzt ein zentrales Modell-Dropdown mit installierbaren Modellen und Bestätigungsdialog; nach Download wird das Modell automatisch ausgewählt. Menüleiste und Settings lesen Sprache/Übersetzung aus denselben Modell-Capabilities, `Auto` bleibt bei English-only-Modellen erhalten, nicht unterstützte Übersetzung wird nicht mehr angeboten, der Menü-Footer wurde entfernt, das Settings-Fenster ist minimierbar und About steht vor Erweitert. Die Version wurde als Minor-Feature-Release auf `0.27.0` angehoben. + +- 2026-06-16: macOS First-Run-Onboarding und Release-Bundle ohne gebündeltes Standardmodell. + - Dateien: `Sources/ASRCore/VoiceModelCatalog.swift`, `Sources/ASRCore/VoiceModelDownloadClient.swift`, `Sources/ASRCore/VoiceModelDownloadProgressMath.swift`, `Sources/ASRCore/VoiceModelInstallProgress.swift`, `Sources/ASRCore/VoiceModelInstaller.swift`, `Sources/ASRCore/BundledWhisperRuntime.swift`, `apps/macos/AppShell/Onboarding/OnboardingStore.swift`, `apps/macos/AppShell/Onboarding/OnboardingCoordinator.swift`, `apps/macos/AppShell/Onboarding/OnboardingWindowPresenter.swift`, `apps/macos/AppShell/Onboarding/OnboardingView.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/SpeechModelController.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/SessionEntryController.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/SettingsChromeComponents.swift`, `apps/macos/AppShell/SettingsViewSpeechDictationSections.swift`, `scripts/prepare_runtime_bundle.sh`, `scripts/preflight_macos_release.sh`, `scripts/smoke_test_macos_app.sh`, `docs/distribution.md`, `docs/macos-release-checklist.md`, `Tests/ASRCoreTests/VoiceModelCatalogTests.swift`, `Tests/ASRCoreTests/VoiceModelDownloadProgressMathTests.swift`, `Tests/ASRCoreTests/BundledWhisperRuntimeTests.swift`, `Tests/AppShellSupportTests/OnboardingStoreTests.swift`, `Tests/AppShellSupportTests/OnboardingCoordinatorTests.swift`, `Tests/AppShellSupportTests/SpeechModelControllerTests.swift`, `VERSION` + - Funktionalität: Release-Bundles enthalten nur `whisper-cli` + Manifest (kein `.bin`); das Standardmodell wird im 5-Schritte-Onboarding heruntergeladen. Katalog-Größen und Download-Progress nutzen `expectedDownloadBytes` mit monotoner/indeterminater Anzeige. Bestehende Installationen mit `ggml-base.bin` überspringen Onboarding automatisch. Diktat bleibt gesperrt bis Onboarding und Standardmodell bereit sind. + +- 2026-05-19: Lokale Lizenzschlüssel-Aktivierung aus App-Shells und Release-Pfad entfernt. + - Dateien: `apps/macos/AppShell/MacAppConfiguration.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/DiagnosticsController.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/SettingsFormPages.swift`, `apps/macos/AppShell/SettingsViewAdvancedSections.swift`, `apps/macos/AppShell/SettingsViewSearchSections.swift`, `apps/macos/AppShell/AppShellStoragePaths.swift`, `apps/macos/WisprLocalMac/project.yml`, `apps/macos/WisprLocalMac/WisprLocalMac-Info.plist`, `apps/ios/App/IOSAppState.swift`, `apps/ios/App/WisprLocaliOSApp.swift`, `apps/ios/App/IOSSharedStorage.swift`, `apps/ios/WisprLocaliOS/project.yml`, `scripts/preflight_macos_release.sh`, `scripts/generate_macos_xcodeproj.sh`, `README.md`, `apps/macos/README.md`, `docs/licensing.md`, `docs/distribution.md`, `docs/features-and-implementation.md`, `docs/system-design.md`, `docs/README.md`, `docs/macos-release-checklist.md`, `docs/ios-keyboard-plan.md`, `Tests/DocsContractTests/DocsContractTests.swift`, `Tests/AppShellSupportTests/DiagnosticsControllerTests.swift`, `Tests/AppShellSupportTests/MacAppStateLifecycleAndContextFacadeTests.swift`, `VERSION` + - Funktionalität: macOS und iOS benötigen keine lokale Lizenzschlüssel-Aktivierung mehr. Die Lizenz-UI, AppState-Verkabelung, Diagnoseausgabe, Info.plist-Keys und Release-Preflight-Pflicht für `WISPR_LICENSE_PUBLIC_KEY_BASE64` wurden entfernt; Shipping benötigt nur noch die Sparkle-Update-Konfiguration (`SPARKLE_FEED_URL`, `SPARKLE_PUBLIC_ED_KEY`). + +- 2026-04-14: Funktionsreichen macOS-Settings-/Runtime-Stand für Speech, AI und Provider-Management wiederhergestellt. + - Dateien: `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/SettingsTab.swift`, `apps/macos/AppShell/SettingsFormPages.swift`, `apps/macos/AppShell/SettingsViewShell.swift`, `apps/macos/AppShell/AIProviderController.swift`, `apps/macos/AppShell/SpeechModelController.swift`, `apps/macos/AppShell/SessionEntryController.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/WisprLocalMac/project.yml` + - Funktionalität: Die umfangreichen Speech-/AI-Einstellungen sind wieder aktiv (Provider-, Modell- und Formatierungssteuerung inkl. Kontextbewusstsein und Dictionary-Workflows). Zusätzlich wurden die zugehörigen AppShell-Controller und Settings-Komponenten als konsistentes Paket zurückgeführt, damit alle früheren UI- und State-Pfade wieder verfügbar sind. + +## Fixes + +- 2026-06-18: macOS-App-Export und lokale Smoke-Validierung stabilisiert. + - Dateien: `apps/macos/AppShell/WisprLocalMacApp.swift`, `scripts/smoke_test_macos_app.sh`, `Tests/DocsContractTests/DocsContractTests.swift`, `VERSION` + - Funktionalität: Der Single-Instance-Guard nutzt unter macOS 14+ die nicht-deprecated Aktivierungs-API, wodurch die Release-Build-Warnung zu `activateIgnoringOtherApps` entfällt. Der macOS-Smoke-Test kann belegte DerivedData-Ordner robust beiseitelegen, statt an kurzzeitig offenen Xcode-Indexdateien abzubrechen. Die Repo-Version wurde als Patch-Bugfix auf `0.26.1` angehoben. + +## Chores + +- 2026-07-03: Cortexa-Logo als macOS-App-Branding integriert. + - Dateien: `apps/macos/AppShell/Resources/Assets.xcassets/AppIcon.appiconset`, `apps/macos/AppShell/Resources/Assets.xcassets/CortexaLogoHorizontal.imageset`, `apps/macos/AppShell/Resources/Assets.xcassets/CortexaLogoStacked.imageset`, `apps/macos/AppShell/MenuBarContentView.swift`, `Tests/DocsContractTests/DocsContractTests.swift`, `VERSION` + - Funktionalität: Das neue Cortexa-Favicon ersetzt die Dock-/AppIcon-PNGs in allen macOS-Größen. Die gelieferten Cortexa-Logo-SVGs liegen nun als Asset-Katalog-Imagesets vor; das Statusleistensymbol selbst nutzt weiterhin ein SF-Symbol. Die Repo-Version wurde als Patch-Chore auf `0.26.3` angehoben. + +- 2026-06-30: Eingebettetes `whisper.cpp` auf den benötigten lokalen Runtime-Build reduziert. + - Dateien: `third_party/whisper.cpp`, `scripts/build_whisper_xcframework.sh`, `Tests/DocsContractTests/DocsContractTests.swift`, `VERSION` + - Funktionalität: Nicht benötigte upstream-Demos und Beispiele wie `wchess`, Android-, WASM-, Server-, Stream- und Editor-Beispiele sowie upstream-CI-, Test-, Sample-, Binding- und generierte Build-Verzeichnisse wurden entfernt. Erhalten bleibt nur der minimale `whisper-cli`-Build mit den notwendigen Common-Hilfsdateien und CMake-Vorlagen. Der Standard-Build erzeugt jetzt nur noch die lokale macOS-CLI; die XCFramework-Erzeugung bleibt explizit über `ENABLE_XCFRAMEWORK_BUILD=ON` verfügbar. Die Repo-Version wurde als Patch-Chore auf `0.26.2` angehoben. + +- 2026-06-16: Fortschrittsanzeige für Speech-Modell-Downloads und klares Entfernen-Feedback in den Settings. + - Dateien: `Sources/ASRCore/VoiceModelInstallProgress.swift`, `Sources/ASRCore/VoiceModelDownloadClient.swift`, `Sources/ASRCore/VoiceModelInstaller.swift`, `apps/macos/AppShell/SpeechModelController.swift`, `apps/macos/AppShell/SettingsViewSpeechDictationSections.swift`, `apps/macos/AppShell/SettingsChromeComponents.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/MacAppStateFacadeActions.swift`, `Tests/ASRCoreTests/VoiceModelInstallProgressTests.swift`, `Tests/AppShellSupportTests/SpeechModelControllerTests.swift`, `VERSION` + - Funktionalität: Modell-Installationen zeigen einen linearen Fortschrittsbalken mit Prozent und übertragenen Bytes. Entfernen zeigt einen „Wird entfernt …“-Zustand, aktualisiert die installierte Modellliste optimistisch und rollt bei Fehlern zurück. + +- 2026-06-16: Optionale Speech-Modelle werden nicht mehr fälschlich als installiert angezeigt oder nach Entfernen aus dem App-Bundle zurückkopiert. + - Dateien: `Sources/ASRCore/BundledWhisperRuntime.swift`, `Sources/ASRCore/VoiceModelInstaller.swift`, `Sources/ASRCore/VoiceModelSuppressionStore.swift`, `scripts/prepare_runtime_bundle.sh`, `Tests/ASRCoreTests/BundledWhisperRuntimeTests.swift`, `Tests/ASRCoreTests/VoiceModelSuppressionStoreTests.swift`, `VERSION` + - Funktionalität: Das Runtime-Bundle enthält nur noch das Standardmodell (`ggml-base.bin`) plus Manifest. Beim Sync werden nur manifestierte Modelle kopiert; vom Nutzer entfernte optionale Modelle werden persistent unterdrückt und nicht erneut aus dem Bundle wiederhergestellt. Dadurch erscheint z. B. Pro nicht mehr automatisch als installiert, und Entfernen/Installieren verhält sich erwartbar. + +- 2026-06-16: macOS-Berechtigungsstatus nach Rebuild/TCC-Mismatch konsistent gemacht und Dev-Start stabilisiert. + - Dateien: `apps/macos/AppShell/BuildPermissionFingerprint.swift`, `apps/macos/AppShell/PermissionCoordinator.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/AppLifecycleCoordinator.swift`, `apps/macos/AppShell/SettingsWindowPresenter.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `apps/macos/AppShell/SettingsViewGeneralSections.swift`, `apps/macos/AppShell/SettingsChromeComponents.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `scripts/smoke_test_macos_app.sh`, `Tests/AppShellSupportTests/BuildPermissionFingerprintTests.swift`, `Tests/AppShellSupportTests/PermissionCoordinatorTests.swift`, `README.md`, `VERSION` + - Funktionalität: Die App erkennt veraltete TCC-Einträge nach Debug-Rebuilds (Build-Fingerprint), refresht Berechtigungen beim Start/Settings-/Menüleisten-Öffnen mehrfach stabilisiert, zeigt „Neu verknüpfen“-Hinweise in Settings und Menüleiste, startet im Smoke-Script per `open(1)` statt direktem Binary-Start und unterstützt `--skip-build` für schnellere lokale Iteration ohne Signatur-Reset. + +- 2026-04-20: Menüleisten-AI-Steuerung auf direkte Picker zurückgestellt und LLM-Label ohne statischen Selection-Suffix wiederhergestellt. + - Dateien: `apps/macos/AppShell/MenuBarContentView.swift`, `VERSION` + - Funktionalität: Das kompakte LLM-Menü zeigt wieder nur den Titel `LLM Modell` statt eines festen `LLM Modell: ...`-Labels. Die AI-Optionen für Stil, Anrede und Formatierung sind in der nicht-kompakten Menüleiste wieder direkt als Picker verfügbar (nicht als zusätzliche Untermenüs), sodass die Bedienung dem bisherigen Verhalten entspricht. + +- 2026-04-20: Startup-Crash durch rekursive Sprachmodell-Sanitization behoben und AI-Auswahlzustände in Menü/Settings klarer sichtbar gemacht. + - Dateien: `apps/macos/AppShell/SpeechModelController.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `apps/macos/AppShell/SettingsViewAISections.swift`, `VERSION` + - Funktionalität: Die Sprachmodell-Sanitization setzt Provider/Modell nur noch bei tatsächlicher Änderung, wodurch rekursive `didSet`-Ketten und der daraus resultierende Stack-Overflow-Crash beim App-Start verhindert werden. Zusätzlich zeigt die Menüleiste `Auto` wieder als Sprachoption an und macht aktive LLM-/AI-Auswahlen sichtbarer; in den Settings werden die aktuell gewählten Werte für Stil, Anrede und Formatierung explizit unter den Pickern angezeigt. + +- 2026-04-20: Menüleisten-Auswahl für Sprache/LLM/AI-Details wieder klar sichtbar gemacht und `Auto` als Sprachoption korrekt ergänzt. + - Dateien: `apps/macos/AppShell/MenuBarContentView.swift`, `VERSION` + - Funktionalität: Die Sprachauswahl in der Menüleiste enthält wieder explizit `Auto`, sodass bei aktivem Auto-Modus kein leerer Zustand mehr angezeigt wird. Zusätzlich zeigt das kompakte LLM-Menü jetzt direkt das aktuell ausgewählte Modell im Label, und die nicht-kompakten AI-Detailmenüs (Stil, Anrede, Format) zeigen den jeweils aktiven Wert sichtbar im Menülabel sowie per Auswahlmarkierung in der Liste. + +- 2026-04-20: Voice-Model-Auswahl auf installierte Modelle begrenzt und inkonsistente Modellzustände im Menü/Settings bereinigt. + - Dateien: `apps/macos/AppShell/SpeechModelController.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/MenuBarContentView.swift`, `apps/macos/AppShell/SettingsViewSpeechDictationSections.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `VERSION` + - Funktionalität: Nicht installierte Speech-Modelle können im Menüleisten- und Settings-Picker nicht mehr ausgewählt werden. Persistierte/ungültige Modellzustände werden bei der Sanitization wieder auf einen validen Default zurückgeführt, sodass UI-Auswahl und effektive Runtime-Konfiguration konsistenter bleiben. Zusätzlich reagiert der Smoke-Settings-Startup-Hook nur noch auf das explizite Launch-Argument statt auf ein Environment-Flag. + +- 2026-04-17: Streaming-/Final-Einfügepfad für schwierige Textfelder stabilisiert und unerwartete Vordergrund-Aktivierung beim Start entschärft. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/DictationRuntimeServices.swift`, `apps/macos/AppShell/SessionEntryController.swift`, `VERSION`, `Tests/DocsContractTests/DocsContractTests.swift` + - Funktionalität: Für Fallback-Textziele (z. B. IDE-/Electron-Felder ohne zuverlässiges AX-Value-Set) nutzt der Streaming-Pfad jetzt gezielt Paste-Replace über den selektierten AX-Bereich statt nur auf AX-Write zu warten; dadurch werden laufende Aktualisierungen robuster in solchen Controls zugestellt. Final-Insert-Fehler fallen zusätzlich auf einen klaren Clipboard-Backup-Pfad zurück, damit kein finales Transkript verloren geht. Außerdem aktiviert der Restore-Startpfad nicht mehr versehentlich die eigene App als Zielanwendung, was Fokus-/Menu-Bar-Störungen reduziert. + +- 2026-04-17: Texteingabe-Robustheit für IDE-/Electron-Ziele verbessert, AI-Live-Fehlerwellen gedrosselt und Stop-Recovery gegen Transkriptverlust ergänzt. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/DictationRuntimeServices.swift`, `VERSION`, `Tests/DocsContractTests/DocsContractTests.swift` + - Funktionalität: Bei nicht-AX-kompatiblen Textfeldern (z. B. manche IDE-/Electron-Controls) wird jetzt ein fokussiertes Fallback-Ziel für Cmd+V-basierte Einfügung erkannt, statt nur auf AX-Value-Set zu warten. Live-AI-Verarbeitung pausiert nach transienten Verbindungsfehlern kurzzeitig und begrenzt wiederholte Diagnosemeldungen, damit Diktatläufe nicht durch Fehler-Spam überlastet werden. Zusätzlich wird bei `stop`-Fehlern der letzte stabile Live-Text in History/Final-Event gesichert, damit gesprochener Inhalt nicht mehr vollständig verloren geht. + +- 2026-04-17: Offene Refactor-Findings für AppState-/Runtime-Entkopplung vollständig geschlossen und gegen Regressionen abgesichert. + - Dateien: `apps/macos/AppShell/SessionEntryController.swift`, `apps/macos/AppShell/DictationRuntimeEventBridge.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/MacAppStateFacadeActions.swift`, `apps/macos/AppShell/MacAppStatePersistenceFacade.swift`, `Tests/AppShellSupportTests/SessionEntryControllerTests.swift`, `VERSION`, `Tests/DocsContractTests/DocsContractTests.swift` + - Funktionalität: Der Startpfad nach App-Restore wurde gegen stale async Tasks abgesichert (inkl. explizitem Cancel), Fokus-Wartefehler brechen den Start jetzt deterministisch mit Diagnose/Audit ab, und die Runtime-Event-Bridge vermeidet doppelte Main-Thread-Scheduling-Ketten. Zusätzlich ist die Persistence-Fassade weiter entkoppelt (Datei-Dialog als Presenter, kein Cross-Facade-Normalizer), die Facade-Ownership in `MacAppState` wurde bereinigt und neue Regressionstests decken Abort-/Cancel-Verhalten gezielt ab. + +- 2026-04-14: Große Restore-Migration auf funktionsreichen Settings-/Runtime-Stand technisch konsolidiert und Build-Blocker auf aktuelle Core-APIs aufgelöst. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/DictationRuntimeServices.swift`, `apps/macos/AppShell/PermissionController.swift`, `Sources/TextTargetMac/TextTargetTypes.swift`, `Sources/ASRCore/ASRTypes.swift`, `Sources/ASRCore/WhisperCppEngine.swift`, `Sources/TextTargetMac/AXTextTargetServices.swift`, `apps/macos/AppShell/*` (Settings-/Controller-Restore), `Sources/AIProcessingCore/*`, `Sources/ASRCore/VoiceModelCatalog.swift`, `Sources/ASRCore/VoiceModelInstaller.swift`, `Sources/AudioCore/AudioPreprocessor.swift`, `Tests/AIProcessingCoreTests/*`, `Tests/AppShellSupportTests/*`, `Tests/AudioCoreTests/AudioPreprocessorTests.swift`, `apps/macos/WisprLocalMac/project.yml` + - Funktionalität: Nach der Rückführung auf den reicheren Stand (Basis: `5bc2504`) wurden API-Differenzen zur neueren Core-Schicht gezielt aufgelöst (u. a. `ASRConfig`-Signatur, Entfernung veralteter `onDebugEvent`-Hooks, AX-Permission/Focused-Target-Pfad auf aktuelle `AXTextTargetResolver`-Logik, Sichtbarkeit von `TextTargetSnapshot.element`). Dadurch sind die zuvor aufgetretenen Compilerfehler im AppShell-Pfad behoben und der lokale macOS-Build inkl. Smoke-Test wieder erfolgreich. + - Rückverfolgbarkeit: Diese Änderung bündelt den Restore des umfangreichen Settings-/Runtime-Pakets mit den notwendigen Kompatibilitätsfixes, damit spätere Qualitätsarbeit auf stabiler Build-Basis erfolgen kann. + +- 2026-04-14: AIProcessingCore und Test-Suite auf denselben API-Stand harmonisiert, um Build-/Test-Inkonsistenzen nach dem Restore zu beheben. + - Dateien: `Sources/AIProcessingCore/AIProcessingTypes.swift`, `Sources/AIProcessingCore/AIProcessingService.swift`, `Sources/AIProcessingCore/AppleFoundationTextProcessor.swift`, `Sources/AIProcessingCore/AIProcessingOutputValidator.swift`, `Sources/AIProcessingCore/OpenAICompatibleRemoteTextProcessor.swift`, `Sources/AIProcessingCore/AppleFoundationPromptBuilder.swift`, `Tests/AIProcessingCoreTests/AIProcessingServiceTests.swift`, `Tests/AIProcessingCoreTests/AppleFoundationPromptBuilderTests.swift`, `Tests/AIProcessingCoreTests/OpenAICompatibleRemoteTextProcessorTests.swift`, `Tests/AppShellSupportTests/*`, `apps/macos/AppShell/MacAppState.swift` + - Funktionalität: Der Restore wurde auf einen konsistenten Typen-/Provider-Vertrag gebracht, doppelte PromptBuilder-Definitionen wurden entfernt und der lokale AX-Fokus-Zugriff in `MacAppState` auf einen sicheren Cast umgestellt. Dadurch laufen die relevanten Pakettests wieder stabil. + +## Fixes + +- 2026-04-12: AI-Processing-Initialisierung bereinigt und Kontext-Gating pro Stage stabilisiert. + - Dateien: `Sources/AIProcessingCore/AIProcessingService.swift`, `Sources/AIProcessingCore/AIProcessingTypes.swift`, `Sources/AIProcessingCore/AppleFoundationTextProcessor.swift`, `Sources/AIProcessingCore/AppleFoundationPromptBuilder.swift`, `Tests/AIProcessingCoreTests/AIProcessingServiceTests.swift`, `Tests/AIProcessingCoreTests/AppleFoundationPromptBuilderTests.swift` + - Funktionalität: Der bisherige Initialisierungsfehler der AI-Processing-Defaults wurde behoben. Zusätzlich wird App-Kontext jetzt explizit nach `ContextAwarenessMode` (`off`, `finalOnly`, `liveOnly`, `liveAndFinal`) pro Live-/Final-Stage gefiltert, damit unerlaubter Kontext nicht versehentlich in Requests landet. + +- 2026-04-02: Sicherheitsrelevante Persistenzpfade gehärtet, Klartext-Lizenzcache entfernt und Clipboard-Tradeoff deutlicher gemacht. + - Dateien: `Sources/LicenseCore/LicenseStore.swift`, `apps/macos/AppShell/LicenseController.swift`, `apps/ios/App/IOSAppState.swift`, `apps/ios/App/IOSSharedStorage.swift`, `apps/ios/KeyboardExtension/KeyboardViewController.swift`, `Sources/SnippetCore/SecurePersistence.swift`, `Sources/SnippetCore/SnippetStore.swift`, `apps/macos/AppShell/TranscriptHistoryStore.swift`, `apps/macos/AppShell/AuditLogger.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/ios/App/WisprLocaliOSApp.swift`, `docs/licensing.md`, `docs/api-design.md`, `docs/system-design.md`, `README.md`, `Tests/DocsContractTests/DocsContractTests.swift`, `VERSION` + - Funktionalität: Roh-Lizenzschlüssel werden jetzt nur noch im Keychain gehalten; der bisherige Klartext-Cache-Fallback auf macOS/iOS wird nicht mehr verwendet und alte Cache-Dateien werden bei Nutzung älterer Builds aktiv entfernt, auch wenn zuerst nur die iOS-Keyboard-Extension geöffnet wird. Zusätzlich werden lokale Snippet-, Verlauf-, Audit- und App-Group-Dateien jetzt mit gehärteten Dateirechten bzw. iOS-Dateischutz geschrieben, rotierte/quarantänisierte Dateien nach dem Verschieben erneut gehärtet und der iOS-Transkriptverlauf aus dem Shared-App-Group-Container in host-app-lokalen Speicher verlagert. Der Zwischenablage-Fallback bleibt als absichtlicher Zustellpfad erhalten, wird in der Oberfläche aber explizit als weniger privater Tradeoff kommuniziert. +- 2026-04-01: Lizenz-Deaktivierung, Update-Flow, lokale Persistenz und Runtime-Härtung über macOS-, iOS- und Core-Module hinweg stabilisiert. + - Dateien: `apps/macos/AppShell/LicenseController.swift`, `Sources/LicenseCore/LicenseCache.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/SparkleUpdaterController.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/MacAppConfiguration.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/TranscriptHistoryStore.swift`, `apps/ios/App/IOSSharedStorage.swift`, `apps/ios/App/IOSAppState.swift`, `apps/ios/KeyboardExtension/KeyboardViewController.swift`, `Sources/SnippetCore/SnippetStore.swift`, `Sources/ASRCore/WhisperCLIExecutor.swift`, `Sources/ASRCore/BundledWhisperRuntime.swift`, `Sources/CapabilityCore/CapabilityProfiler.swift`, `Tests/LicenseCoreTests/LicenseCacheTests.swift`, `Tests/SnippetCoreTests/SnippetStoreTests.swift`, `Tests/ASRCoreTests/BundledWhisperRuntimeTests.swift`, `Tests/ASRCoreTests/WhisperCLIExecutorTests.swift`, `Tests/CapabilityCoreTests/CapabilityProfilerTests.swift` + - Funktionalität: Das Deaktivieren einer Lizenz entfernt auf macOS jetzt nicht nur den Keychain-Eintrag, sondern auch den lokalen Fallback-Cache, damit eine deaktivierte Lizenz nach einem Neustart nicht versehentlich wieder als aktiv erscheint. Der manuelle Update-Check ist in Menüleiste und Settings wieder dauerhaft sichtbar, Feed-URLs werden nur noch über `https` akzeptiert und der Updater nutzt einen typisierten Status statt stringbasierter Sichtbarkeitslogik. Korruptes History-/Snippet-/Shared-Storage-JSON wird in Quarantäne verschoben statt beim nächsten Speichern still überschrieben, iOS koordiniert Shared-Container-Zugriffe jetzt versioniert über `NSFileCoordinator`, und die Keyboard-Extension löscht ihren zuletzt bekannten Zustand bei temporären Lesefehlern nicht mehr. Zusätzlich protokolliert die Runtime keine Rohtranskripte mehr in Diagnostics, Release-Builds lösen `whisper-cli` restriktiver auf, das gebündelte Runtime-Manifest kann optionale SHA-256-Prüfsummen validieren, und das Capability-Profiling vermeidet wiederholte synchrone Benchmark-Kosten durch Caching. + +- 2026-04-01: Live-Diktat begrenzt rückwirkende Umschreibungen, verwirft `Blank Audio`-Platzhalter und macht Snippet-Replacements robuster. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `Sources/SessionCore/StreamingCommitStabilizer.swift`, `Sources/SnippetCore/DefaultSnippetMatcher.swift`, `Tests/SessionCoreTests/StreamingCommitStabilizerTests.swift` + - Funktionalität: Streaming-Updates ersetzen jetzt nur noch den wirklich veränderlichen Textbereich statt den kompletten sichtbaren Satz bei jeder Partial-Antwort neu zu schreiben. Dadurch bleiben ältere Wörter und Sätze stabiler, während der neue `Blank Audio`-Filter leere oder placeholderartige Finals zuverlässig verwirft. Zusätzlich ist der Snippet-Matcher thread-sicherer und behandelt tokenisierte Ersetzungen robuster, damit finale Textersetzungen nicht unnötig an der laufenden Streaming-Logik hängen. + +## Features + +- 2026-04-12: Dictionary-, Context-Awareness-, ASR-Prompt- und Media-Mute-Upgrade für den macOS-Diktierpfad umgesetzt. + - Dateien: `apps/macos/AppShell/PersonalDictionaryStore.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `Sources/ASRCore/ASRTypes.swift`, `Sources/ASRCore/WhisperCLIExecutor.swift`, `Sources/ASRCore/WhisperCppEngine.swift`, `Tests/ASRCoreTests/WhisperCLIExecutorTests.swift`, `VERSION` + - Funktionalität: Die App besitzt jetzt ein persönliches Dictionary mit Kategorien, Import/Export und Review-Queue für Auto-Add-Vorschläge. Dictionary-Terme werden sowohl in der AI-Nachbearbeitung (Begriffserhalt) als auch im ASR-Pfad über einen sicheren Initial-Prompt berücksichtigt. Zusätzlich gibt es einen konfigurierbaren Context-Awareness-Modus in den Settings sowie eine optionale `Mute music while dictating`-Funktion (best-effort Pause/Resume für Apple Music und Spotify). Die Qualitäts-/Formatierungs-Hinweise im Settings-UI wurden für den Live-vs-Final-Tradeoff geschärft. + +- 2026-04-02: macOS-Update-Flow für Sparkle + GitHub Releases konzeptionell geschärft und Status-Texte vereinheitlicht. + - Dateien: `apps/macos/AppShell/SparkleUpdaterController.swift`, `apps/macos/AppShell/MacAppConfiguration.swift`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Der Updater beschreibt jetzt klarer, ob Sparkle verfügbar ist, ob Updates bereits konfiguriert sind, ob gerade geprüft wird oder ob ein neues Release vorliegt. Der manuelle Check setzt den Status nicht mehr dauerhaft auf „Prüfe…“, sondern fällt nach kurzer Zeit wieder in den Bereitschaftszustand zurück, falls Sparkle selbst keine neue Zustandsmeldung liefert. Außerdem wird die Veröffentlichungsquelle in der Konfiguration lesbarer als `GitHub Releases Appcast` beschrieben, und die README erklärt den eingebetteten Sparkle-Flow ohne eigenes Backend. + +- 2026-04-02: macOS-Settings um überarbeiteten `About`-Reiter und vorbereitete interne Lizenz-/Support-Gates erweitert. + - Dateien: `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/MacAppConfiguration.swift`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Die Settings besitzen jetzt einen eigenen `About`-Bereich mit persönlicher Kurzvorstellung auf Basis von `leon-stadler.com/startseite/ueber-mich/`, einer offenen Projektbeschreibung und einem Link zur Website. Support-/Donation-Elemente sowie die Lizenzinfrastruktur bleiben intern vorbereitet, werden aber in öffentlichen Builds nicht angezeigt; Lizenz- und Support-UI erscheinen nur noch über den expliziten `WLMEnableInternalLicenseUI`-Schalter. Der Bereich `Erweitert` konzentriert sich damit öffentlich auf Sparkle-Updates und Diagnose. + - UI-Polish: Der `About`-Reiter nutzt jetzt eine klarere native Hierarchie mit persönlichem Intro, kurzen Faktenblöcken und einem zurückhaltenden Website-Einstieg statt eines reinen Fließtext-Layouts. + +- 2026-04-01: Neue Live-Anpassungs-Einstellung in den macOS-Diktatsettings eingeführt. + - Dateien: `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/README.md`, `docs/system-design.md`, `VERSION` + - Funktionalität: In den Einstellungen gibt es jetzt einen sichtbaren Live-Rewrite-Radius von `Nur aktueller Satz` bis `Ganzer aktueller Absatz`. Die Auswahl wird persistent in `UserDefaults` gespeichert und steuert, wie stark die laufende Eingabe bei neuen Partial-Ergebnissen noch umgeschrieben werden darf. + +## Docs + +- 2026-04-12: API-, System- und README-Dokumentation um Dictionary, Context Awareness, ASR-Initial-Prompt und Media-Mute erweitert. + - Dateien: `docs/api-design.md`, `docs/system-design.md`, `README.md`, `VERSION` + - Funktionalität: Die Dokumentation beschreibt nun die erweiterten Dictation-Startoptionen (AI-Konfiguration, Dictionary-Hinweise, optionaler App-Kontext, Media-Mute) sowie die neuen Qualitäts- und Kontextpfade im macOS-AppShell. + +- 2026-04-01: API-, System-, Licensing- und README-Verträge an die aktuellen AppShell-Optionen und den manuellen Update-Flow angepasst, und das Repo auf `0.21.0` angehoben. + - Dateien: `docs/api-design.md`, `docs/system-design.md`, `docs/licensing.md`, `README.md`, `Tests/DocsContractTests/DocsContractTests.swift`, `Package.swift` + - Funktionalität: Die Dokumentation beschreibt jetzt die aktuellen Dictation-Optionen inklusive `liveRewriteScope`, Delivery-Mode und Clipboard-Fallback, die Mutable-Tail-Semantik beim Streaming, den macOS-Lizenzcache als löschbaren Fallback und den permanent sichtbaren manuellen Update-Check. + +## Fixes + +- 2026-03-28: macOS-Settings auf natives Segment-Layout umgestellt und Diktier-Runtime gegen Start-/Audio-Fehlerzustände gehärtet. + - Dateien: `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Das Settings-Fenster nutzt jetzt eine ruhigere native Segmentsteuerung oberhalb der Form-Inhalte, konsistentere deutschsprachige Labels sowie verbesserte VoiceOver-Beschriftungen für Verlauf-/Snippet-Aktionen und gekürzte Vorschautexte. Gleichzeitig verhindert die Runtime Doppelstarts während der Startphase, kann einen Start sauber abbrechen und setzt bei Audio-Push-Fehlern den Session-Zustand vollständig zurück, statt in einem fehlerhaften „läuft bereits“-Zustand zu hängen. + +- 2026-03-27: macOS-Diktierpfad unterstützt jetzt den dokumentierten eingeschränkten Modus ohne Bedienungshilfen und zeigt gespeicherte Lizenzen nur noch maskiert an. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/DictationCapability.swift`, `apps/macos/AppShell/PermissionController.swift`, `apps/macos/AppShell/LicenseController.swift`, `apps/macos/AppShell/AuditLogger.swift`, `apps/macos/AppShell/TranscriptHistoryStore.swift`, `README.md`, `VERSION` + - Funktionalität: Mikrofonzugriff blockiert weiterhin den Aufnahmebeginn, fehlende Bedienungshilfen blockieren aber nicht mehr die Transkription insgesamt; direkte Einfügepfade werden stattdessen sauber auf Verlauf/Zwischenablage degradiert. Gleichzeitig wurden Audit-, History- und Lizenzlogik in eigene Services entkoppelt und gespeicherte Lizenzschlüssel werden nicht mehr ungefragt als Klartext ins UI zurückgeladen. + +- 2026-03-27: iOS-Host-App und Keyboard-Extension verwenden jetzt einen expliziten App-Group-Vertrag ohne stillen Local-Fallback, und die Tastatur fügt keine Platzhalter-/Stale-Texte mehr ein. + - Dateien: `apps/ios/App/IOSSharedStorage.swift`, `apps/ios/App/IOSAppState.swift`, `apps/ios/App/WisprLocaliOSApp.swift`, `apps/ios/KeyboardExtension/KeyboardViewController.swift`, `apps/ios/README.md`, `README.md`, `VERSION` + - Funktionalität: Die Shared-Container-/Defaults-Auflösung wirft jetzt klare Fehler statt unbemerkt auf lokale Speicherorte auszuweichen; die Extension liest nur noch Snippets plus einen dedizierten Latest-Transcript-Payload und entfernt die bisherige Pseudo-Diktier-/Placeholder-Insertion. Zusätzlich zeigt der Host gespeicherte Lizenzen nur noch maskiert an und entfernt Demo-Transkript-Aktionen aus der Produktionsoberfläche. + +## Features + +- 2026-03-27: Gebündelte Whisper-Runtime besitzt jetzt einen expliziten Default-Modell-Vertrag und bereinigt veraltete installierte Runtime-Assets automatisch. + - Dateien: `Sources/ASRCore/BundledWhisperRuntime.swift`, `Tests/ASRCoreTests/BundledWhisperRuntimeTests.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `VERSION` + - Funktionalität: Die Runtime liest optional ein `runtime-manifest.json`, liefert deterministisch `defaultModelFileName` und `availableModelFileNames`, funktioniert ohne harte `ggml-base.bin`-Annahme und entfernt beim Reinstall nicht mehr referenzierte Modell-Dateien aus dem Zielverzeichnis. Die neuen Tests decken Manifest-Defaults, Fallback-Modelle und Stale-Asset-Pruning ab. + +- 2026-03-27: CI- und Release-Tooling validieren jetzt generierte Xcode-Projekte, Release-Konfiguration und headless macOS-Smokes explizit. + - Dateien: `.github/workflows/ci.yml`, `scripts/generate_macos_xcodeproj.sh`, `scripts/preflight_macos_release.sh`, `scripts/smoke_test_macos_app.sh`, `README.md`, `VERSION` + - Funktionalität: Die Projektgenerierung unterstützt jetzt `--check`/`--require-clean` statt stiller Auto-Install-/Reuse-Wege, der Release-Preflight prüft zusätzlich Build-/Versions-Metadaten und Asset-Wiring, und der macOS-Smoke-Test kann in CI mit `--skip-launch` Build und Bundle validieren, ohne den App-Prozess offen zu halten. + +## Docs + +- 2026-03-27: README-Dokumentation auf eingeschränkten macOS-Modus, verpflichtende App Group auf iOS und headless Smoke-Checks aktualisiert. + - Dateien: `README.md`, `apps/ios/README.md`, `VERSION` + - Funktionalität: Die Dokumentation beschreibt jetzt den Direct-Insertion-Vorbehalt für Bedienungshilfen, den neuen `--skip-launch`-Pfad für den macOS-Smoke-Test sowie den dedizierten Latest-Transcript-Payload und die fehlende Local-Fallback-Strategie im iOS-App-Group-Flow. + +## Fixes + +- 2026-03-26: Bundled-Whisper-Runtime akzeptiert im macOS-App-Bundle jetzt sowohl verschachtelte als auch flache Resource-Layouts. + - Dateien: `Sources/ASRCore/BundledWhisperRuntime.swift`, `Tests/ASRCoreTests/BundledWhisperRuntimeTests.swift`, `apps/macos/WisprLocalMac/project.yml`, `scripts/smoke_test_macos_app.sh`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Die App findet `whisper-cli` und `models/` jetzt sowohl unter `Contents/Resources/Runtime` als auch direkt unter `Contents/Resources`, wodurch Diktierstarts nach XcodeGen-/Asset-Catalog-Anpassungen nicht mehr mit `Bundled runtime directory not found` abbrechen. Zusätzlich bevorzugt das macOS-Projekt wieder die konservative Folder-Resource-Einbindung für `Runtime`, und der Smoke-Test validiert beide Bundle-Varianten. + +- 2026-03-26: macOS-Settings und Menüleisten-UI stärker auf native Toolbar-/Form-/Asset-Catalog-Strukturen zurückgeführt. + - Dateien: `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/WisprLocalMac/project.yml`, `apps/macos/AppShell/Resources/Assets.xcassets/Contents.json`, `apps/macos/AppShell/Resources/Assets.xcassets/AccentColor.colorset/Contents.json`, `apps/macos/AppShell/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json`, `apps/macos/AppShell/Resources/Assets.xcassets/AppIcon.appiconset/*.png`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Das Settings-Fenster nutzt jetzt eine native Toolbar-Suche via `.searchable(...)` statt einer selbstgebauten Suchleiste, die Reiterinhalte sind stärker auf `Form`-/`GroupBox`-Verhalten zurückgeführt, und das Menüleisten-Menü gewichtet Primäraktion, Utility-Footer und Status-Pills klarer nach Apple-typischer Bedeutung. Zusätzlich besitzt das macOS-Target jetzt erstmals einen echten Asset Catalog mit `AccentColor` und vollständigem `AppIcon`-Set, der über XcodeGen nativ in das App-Target eingebunden wird. + +- 2026-03-26: macOS-Settings- und Menüleisten-Polish nähert die Oberfläche weiter an native Preferences- und Menu-Bar-Gewichtung an. + - Dateien: `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Das Settings-Fenster nutzt jetzt eine ruhigere Header-Hierarchie mit Kontextzeile, weichere Card-Radien, feinere Abstände und zurückhaltendere Labels; im Menüleisten-Menü wurden Breite, Kartenstärke, Status-Pills, Secondary-Text und Trenner reduziert, damit die Oberfläche weniger boxed und näher an nativer macOS-Preferences-/Menu-Bar-Anmutung wirkt. + +- 2026-03-26: macOS-Settings-Suche rendert Bereichstreffer jetzt ohne verschachtelte Reiter-Container und wirkt dadurch deutlich nativer. + - Dateien: `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Die globale Suche zeigt Treffer jetzt als echte Bereichssektionen statt komplette Pane-Container im Suchmodus; dadurch entfallen die zuvor sichtbare Reiter-/ScrollView-Verschachtelung, die History verhält sich im Suchmodus ohne innere Scrollfläche ruhiger, und das Suchfeld nutzt jetzt lokalisierte Accessibility-Hinweise und eine konsistentere native Interaktion. + +- 2026-03-26: macOS-Menü und Settings entfernen doppelten Verlauf, stabilisieren die History-Breite, vereinfachen Menüleisten-Optionen und zeigen Suchtreffer reiterübergreifend. + - Dateien: `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/GlobalHotkeyManager.swift`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Das Menü zeigt im Idle-Zustand keinen redundanten `Bereit`-Header und keine doppelte Verlaufsvorschau mehr; die Verlaufsvorschau im Menü wird zusätzlich gekürzt, damit lange Diktate das Layout nicht aufblähen. Die Settings halten jetzt eine feste Fensterbreite, zeigen im History-Reiter kompakte, aufklappbare Verlaufskarten statt ungebremster Volltexte, entfernen den zuvor fest reservierten Notfall-Kurzbefehl vollständig aus Hotkey-Registrierung, UI und Diagnosetexten, blenden den Update-Bereich nicht mehr in den Settings ein und verwenden bei aktiver Suche eine reiterübergreifende Ergebnisansicht mit getrennten Gruppen pro Bereich. + +- 2026-03-26: macOS-Settings und Menüleisten-Oberfläche in einem ersten Apple-like-Conformance-Pass visuell und semantisch überarbeitet. + - Dateien: `apps/macos/AppShell/SettingsView.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/README.md`, `VERSION` + - Funktionalität: Die Settings ersetzen große Standard-`Form`-Blöcke jetzt schrittweise durch ruhigere Preference-Cards mit klarerer Hierarchie, kleinerem Header und systemnäherer Fenstergröße; die Suche zeigt eine Trefferzusammenfassung, gruppiert Ergebnisse semantisch und ist für Screenreader klarer ausgezeichnet. Das Menüleisten-Menü nutzt subtilere Status-Pills, leichtere Kartenflächen, eine weniger dominante Kopfzeile und explizitere Accessibility-Auszeichnungen für Status und Sprachwahl. + +- 2026-03-25: macOS-Diktierlauf räumt Insert-/AX-Fehler jetzt sauber auf und bleibt bei fehlendem Textziel recoverable. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/MacAppState.swift`, `Sources/ASRCore/Protocols.swift`, `Sources/ASRCore/WhisperCppEngine.swift` + - Funktionalität: Der Runtime-Pfad hat jetzt einen zentralen Abort/Cleanup-Weg, der Audioengine, Streaming-Decoder, Pending-Insertion-Tasks und Session-Flags zuverlässig zurücksetzt; vorübergehend fehlende oder ungeeignete Textziele werden beim Streaming nicht mehr als fataler Fehler behandelt, sondern halten den bisherigen Text im Wartemodus vor, bis wieder ein editierbares Ziel verfügbar ist. + +- 2026-03-25: macOS-Finalisierung speichert Transkripte jetzt unabhängig von der Zustellung immer in der History. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/MacAppState.swift` + - Funktionalität: Finale Diktate werden jetzt als Ereignis mit Zustellungsstatus (`eingefügt`, `Zwischenablage`, `nur History`, `Zustellfehler`) verarbeitet; dadurch bleibt die History auch dann korrekt erhalten, wenn beim Einfügen oder beim Ziel-Timeout kein Textfeld verfügbar war. + +- 2026-03-25: Neuer ASR-Lifecycle-Test deckt den Reset-Pfad des Streaming-Engines ab. + - Dateien: `Tests/ASRCoreTests/WhisperCppEngineLifecycleTests.swift` + - Funktionalität: Der Test stellt sicher, dass `resetStreaming()` eine laufende Session wirklich zurücksetzt, `stopStreaming()` danach korrekt `engineNotRunning` liefert und ein erneuter Start im selben Engine-Objekt wieder möglich ist. + +- 2026-03-25: macOS-Xcode-Projektgenerierung findet Homebrew/XcodeGen jetzt auch außerhalb eines reduzierten PATHs und nutzt vorhandene Projektdateien weiter. + - Dateien: `scripts/generate_macos_xcodeproj.sh`, `scripts/smoke_test_macos_app.sh`, `VERSION` + - Funktionalität: Die Skripte suchen `xcodegen` und `brew` jetzt zusätzlich in typischen Homebrew-Pfaden wie `/opt/homebrew/bin`; fehlt `xcodegen` trotzdem, kann der Build auf ein bereits vorhandenes `WisprLocalMac.xcodeproj` zurückfallen, statt unnötig abzubrechen. + +- 2026-03-25: macOS-Build-Skripte brechen ohne Homebrew jetzt mit klarer XcodeGen-Anleitung ab. + - Dateien: `scripts/generate_macos_xcodeproj.sh`, `scripts/smoke_test_macos_app.sh`, `VERSION` + - Funktionalität: Die Skripte versuchen `brew` nicht mehr blind aufzurufen; wenn weder `xcodegen` noch `brew` verfügbar ist, geben sie eine konkrete Installationsanleitung für XcodeGen aus und stoppen früh mit einer verständlichen Fehlermeldung. + +- 2026-03-25: macOS-Settings lassen sich jetzt zuverlässig per globalem Shortcut öffnen. + - Dateien: `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/MacAppState.swift` + - Funktionalität: `Control + Option + Escape` stoppt weiterhin laufende Aufnahmen, öffnet im Idle-Zustand jetzt aber tatsächlich das Settings-Fenster; dafür nutzt die App ein eigenes `NSWindow`-basiertes Settings-Presenter statt einer nur visuell angedeuteten Menüleisten-Aktion. + +- 2026-03-25: Leerlauf-Halluzinationen wie `Musik` bei fehlendem Sprachsignal im macOS-Diktierpfad gefiltert. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift` + - Funktionalität: Der Runtime-Pfad misst jetzt einfache Sprachaktivität per RMS-Schwelle, ignoriert Partials vor gesichertem Spracheinsatz und verwirft sehr kurze bzw. typische Leerlauf-Transkripte ohne ausreichend Sprachenergie statt sie einzufügen oder in die History zu übernehmen. + +- 2026-03-25: macOS-Menüleisten-Menü auf Kernaktionen reduziert und visuell bereinigt. + - Dateien: `apps/macos/AppShell/WisprLocalMacApp.swift` + - Funktionalität: Das Menü zeigt jetzt keine langen Status-/Hinweisblöcke mehr; `Check for Updates` ist entfernt, `Open Settings` und `Start Dictation` zeigen ihre Shortcut-Hinweise direkt im Label, und `Letztes Diktat kopieren` ist als Schnellaktion ergänzt. + +- 2026-03-25: macOS-Settings auf Reiterstruktur und einklappbare Diagnose umgestellt. + - Dateien: `apps/macos/AppShell/SettingsView.swift` + - Funktionalität: Die Settings sind jetzt in Tabs für `General`, `Dictation`, `History`, `Snippets`, `Permissions`, `Diagnostics` und `License` organisiert; die Diagnose wird komprimiert angezeigt, kann aufgeklappt und direkt in die Zwischenablage kopiert werden, und der alte Live-Transkript-Block wurde entfernt. + +- 2026-03-25: Menüleisten-Popup gegen unkontrolliertes Anwachsen bei Diagnose-/Fehlertexten gehärtet. + - Dateien: `apps/macos/AppShell/WisprLocalMacApp.swift`, `apps/macos/AppShell/MacAppState.swift` + - Funktionalität: Das `MenuBarExtra` nutzt jetzt eine feste, scrollbare Kompaktansicht; im Fehlerfall wird dort nur noch die letzte relevante Diagnosezeile statt des gesamten Diagnoseverlaufs als Statushinweis angezeigt, wodurch das Popup nicht mehr durch lange Logs auf Bildschirmgröße anwächst. + +- 2026-03-25: Deaktivierte Menüleisten-Hinweise blenden den Shortcut-Text jetzt vollständig aus. + - Dateien: `apps/macos/AppShell/MacAppState.swift` + - Funktionalität: Wenn `Hinweise in der Menüleiste anzeigen` deaktiviert ist, zeigt die Menüleiste nur noch das Status-Icon und keinen zusätzlichen Start-/Stop- oder Shortcut-Text mehr. + +- 2026-03-24: macOS-Diktierstart nutzt zuletzt bekanntes AX-Textziel als Recovery-Pfad. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift` + - Funktionalität: Wenn beim Start kurzfristig kein fokussiertes Textfeld geliefert wird, versucht die App jetzt das zuletzt erfolgreich verwendete AX-Textziel im selben Frontmost-App-Kontext erneut zu lesen und dessen aktuellen Cursor-/Selection-Range zu übernehmen, statt den Start sofort scheitern zu lassen. + +- 2026-03-24: Menüleisten-Startpfad in der macOS-App von normalem UI-/Hotkey-Start entkoppelt. + - Dateien: `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift` + - Funktionalität: Der `Start Dictation`-Button im `MenuBarExtra` startet jetzt über einen eigenen verzögerten Ablauf, der erst das Menü schließen lässt, danach die zuletzt aktive App reaktiviert und erst dann die Aufnahme startet; dadurch schlägt der Start aus dem Menü nicht mehr am offenen Menü-Tracking fehl. + +- 2026-03-24: Start aus der macOS-Menüleiste gegen verlorenen Textfokus beim Diktierbeginn gehärtet. + - Dateien: `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/DictationRuntime.swift` + - Funktionalität: Beim Start über die Menüleiste aktiviert die App jetzt die zuletzt genutzte Fremd-App mit größerem Timing-Puffer erneut und wartet beim AX-Lock mehrere kurze Retry-Zyklen auf ein fokussiertes Textfeld, statt den Diktierstart sofort mit `Kein fokussiertes Textfeld gefunden.` abzubrechen. + +- 2026-03-24: macOS-Settings-Fenster in der Menüleisten-App zuverlässig erreichbar gemacht. + - Dateien: `apps/macos/AppShell/WisprLocalMacApp.swift` + - Funktionalität: Der Menüpunkt `Open Settings` öffnet jetzt ein explizites `Window(id: "settings")` statt sich auf `showSettingsWindow:` zu verlassen, was in der Agent-/Menüleisten-App zuvor unzuverlässig war. + +- 2026-03-24: macOS-Streaming-Insert gegen AppKit/HIToolbox-Absturz durch Queue-Verstoß gehärtet. + - Dateien: `apps/macos/AppShell/DictationRuntime.swift`, `Sources/TextTargetMac/AXTextTargetServices.swift` + - Funktionalität: Accessibility-Reads/Writes, Cursor-Updates und Clipboard-Fallbacks laufen jetzt konsistent auf dem Main Thread; dadurch bricht das Diktat beim partiellen oder finalen Einfügen in `NSTextView`-basierte Ziele nicht mehr mit `_dispatch_assert_queue_fail` auf der Queue `wispr.dictation.insert` ab. + +- 2026-03-22: macOS-AppShell gegen Main-Actor-/Lifecycle-Probleme und Hotkey-Verlust nach Wake gehärtet. + - Dateien: `apps/macos/AppShell/MacAppState.swift`, `apps/macos/AppShell/GlobalHotkeyManager.swift`, `apps/macos/AppShell/WisprLocalMacApp.swift`, `scripts/smoke_test_macos_app.sh` + - Funktionalität: Berechtigungen, Runtime-Initialisierung und Hotkey-Registrierung werden nach App-Aktivierung und System-Wake erneut synchronisiert; der globale Shortcut kann gezielt neu registriert werden, und der Smoke-Test prüft zusätzlich, dass die App als echte Menüleisten-App (`LSUIElement`) gebaut wurde. + +- 2026-03-20: iOS-Keyboard-Extension-Paketierung und `whisper.cpp`-XCFramework-Export auf echte Apple-Toolchain-Ausgaben korrigiert. + - Dateien: `apps/ios/WisprLocaliOS/project.yml`, `apps/ios/WisprLocaliOS/WisprLocaliOS-Info.plist`, `apps/ios/WisprLocaliOS/WisprLocalKeyboard-Info.plist`, `scripts/build_whisper_xcframework.sh`, `Sources/SnippetCore/SnippetStore.swift`, `Tests/SessionCoreTests/StreamingCommitStabilizerTests.swift` + - Funktionalität: Die Keyboard-Extension nutzt jetzt explizite `Info.plist`-Dateien mit gültigem `NSExtension`-Dictionary (`RequestsOpenAccess`, `PrimaryLanguage`, `IsASCIICapable`) statt flacher Build-Settings, der XCFramework-Wrapper übernimmt nun das tatsächlich von `whisper.cpp` erzeugte `build-apple/whisper.xcframework`, Snippet-Exports erzeugen fehlende Zielordner automatisch, und die Streaming-Stabilizer-Tests spiegeln die produktive Boundary-Commit-Logik korrekt wider. + +- 2026-03-20: iOS-Host-App-Target wieder erfolgreich kompilierbar gemacht und echte Xcode-Builds validiert. + - Dateien: `apps/ios/App/WisprLocaliOSApp.swift` + - Funktionalität: Optionaler `localeIdentifier` wird in der Snippet-Liste jetzt null-sicher gerendert; danach bauen sowohl das macOS-App-Target (`WisprLocalMac`) als auch das iOS-Projekt mit Keyboard-Extension (`WisprLocaliOS`) erfolgreich per `xcodebuild`. - 2026-03-17: ASR-/Session-Core und Text-Insertion auf Produktionsfehler und sichere Fallbacks gehärtet. - Dateien: `Sources/ASRCore/WhisperCLIExecutor.swift`, `Sources/ASRCore/ModelRegistry.swift`, `Sources/SessionCore/SessionStateMachine.swift`, `Sources/SessionCore/StreamingCommitStabilizer.swift`, `Sources/TextTargetMac/AXTextTargetServices.swift`, `apps/macos/AppShell/DictationRuntime.swift`, `apps/macos/AppShell/GlobalHotkeyManager.swift`, `apps/macos/AppShell/MacAppState.swift` From bd8fbb4714aa463f13a83a86dafdee47029b5a0c Mon Sep 17 00:00:00 2001 From: Leon Stadler Date: Tue, 29 Sep 2026 10:04:23 +0200 Subject: [PATCH 3/3] fix: make macOS whisper smoke input deterministic --- changelog.md | 4 ++++ scripts/verify_whisper_cli_runtime.sh | 33 +++++++++++++++------------ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/changelog.md b/changelog.md index f5f2e44..aeb1fc0 100644 --- a/changelog.md +++ b/changelog.md @@ -66,6 +66,10 @@ ## Chores +- 2026-09-29: Whisper-CLI-CI-Smoke-Test verwendet ein festes Sprachsample statt macOS-Texte-to-Speech. + - Dateien: `scripts/verify_whisper_cli_runtime.sh`, `changelog.md`. + - Funktionalität: Der macOS-Smoke-Test transkribiert jetzt das im gepinnten whisper.cpp-Submodul enthaltene JFK-WAV-Sample. Dadurch hängt die CI-Prüfung nicht mehr von der auf GitHub-Runnern erzeugten `say`-Audioausgabe ab. Wenn Whisper keinen Text erzeugt, zeigt der Fehler zusätzlich die CLI-Ausgaben. + - 2026-09-29: Release-Notizen automatisch aus gemergten PRs und direkten Commits erstellen. - Dateien: `.github/release.yml`, `.github/PULL_REQUEST_TEMPLATE.md`, `.github/workflows/release.yml`, `scripts/generate_macos_release_notes.sh`, `AGENTS.md`, `docs/distribution.md`, `changelog.md`. - Funktionalität: Der manuelle macOS-Release-Workflow erzeugt jetzt kategorisierte GitHub-Release-Notizen einschließlich Beitragenden und Commit-Nachrichten ohne PR. Eine PR-Vorlage beschreibt verständliche Titel und erforderliche Release-Labels; die Notiz enthält außerdem kurze Installationshinweise und den maschinenlesbaren getesteten Quell-Commit. Produktversion unverändert, da nur Release-Tooling und Dokumentation geändert wurden. diff --git a/scripts/verify_whisper_cli_runtime.sh b/scripts/verify_whisper_cli_runtime.sh index 1343dbf..eb697de 100755 --- a/scripts/verify_whisper_cli_runtime.sh +++ b/scripts/verify_whisper_cli_runtime.sh @@ -12,10 +12,11 @@ error() { usage() { cat < [path to ggml model] +Usage: $0 [path to ggml model [path to speech fixture]] Checks that whisper-cli has no non-system dynamic-library dependencies and can -start. When a model is supplied, also transcribes synthesized speech end to end. +start. When a model is supplied, also transcribes the pinned whisper.cpp speech +fixture end to end. The fixture path defaults to third_party/whisper.cpp/samples/jfk.wav. EOF exit 1 } @@ -26,6 +27,8 @@ fi CLI_PATH="$1" MODEL_PATH="${2:-}" +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +SPEECH_SAMPLE_PATH="${3:-${ROOT_DIR}/third_party/whisper.cpp/samples/jfk.wav}" [[ -x "${CLI_PATH}" ]] || error "whisper-cli is missing or not executable at ${CLI_PATH}" command -v otool >/dev/null 2>&1 || error "Required tool 'otool' is missing." @@ -66,8 +69,7 @@ if [[ -z "${MODEL_PATH}" ]]; then fi [[ -f "${MODEL_PATH}" ]] || error "Model is missing at ${MODEL_PATH}" -command -v say >/dev/null 2>&1 || error "Required tool 'say' is missing." -command -v afconvert >/dev/null 2>&1 || error "Required tool 'afconvert' is missing." +[[ -f "${SPEECH_SAMPLE_PATH}" ]] || error "Whisper speech fixture is missing at ${SPEECH_SAMPLE_PATH}" E2E_DIR="$(mktemp -d -t cortexa-whisper-e2e.XXXXXX)" cleanup_e2e() { @@ -75,26 +77,27 @@ cleanup_e2e() { } trap 'cleanup_e2e; cleanup_probe' EXIT -SPEECH_AIFF="${E2E_DIR}/speech.aiff" -SPEECH_WAV="${E2E_DIR}/speech.wav" OUTPUT_BASE="${E2E_DIR}/transcript" - -say -o "${SPEECH_AIFF}" "This is a speech recognition test for Cortexa." -afconvert -f WAVE -d LEI16@16000 "${SPEECH_AIFF}" "${SPEECH_WAV}" +CLI_STDOUT_LOG="${E2E_DIR}/stdout.log" +CLI_STDERR_LOG="${E2E_DIR}/stderr.log" if ! "${CLI_PATH}" \ -m "${MODEL_PATH}" \ - -f "${SPEECH_WAV}" \ + -f "${SPEECH_SAMPLE_PATH}" \ -l en \ -otxt \ -of "${OUTPUT_BASE}" \ -nt \ - >"${E2E_DIR}/stdout.log" \ - 2>"${E2E_DIR}/stderr.log"; then - E2E_ERROR="$(sed -n '1,20p' "${E2E_DIR}/stderr.log")" + >"${CLI_STDOUT_LOG}" \ + 2>"${CLI_STDERR_LOG}"; then + E2E_ERROR="$(sed -n '1,20p' "${CLI_STDERR_LOG}")" error "whisper-cli transcription failed: ${E2E_ERROR}" fi -[[ -s "${OUTPUT_BASE}.txt" ]] || error "whisper-cli produced no transcript for synthesized speech." +if [[ ! -s "${OUTPUT_BASE}.txt" ]]; then + CLI_STDOUT="$(sed -n '1,20p' "${CLI_STDOUT_LOG}")" + CLI_STDERR="$(sed -n '1,20p' "${CLI_STDERR_LOG}")" + error "whisper-cli produced no transcript for fixture ${SPEECH_SAMPLE_PATH}. stdout: ${CLI_STDOUT:-}; stderr: ${CLI_STDERR:-}" +fi TRANSCRIPT="$(tr '\n' ' ' <"${OUTPUT_BASE}.txt" | sed 's/[[:space:]]\{1,\}/ /g; s/^ //; s/ $//')" -log "Transcription E2E passed with non-empty output: ${TRANSCRIPT}" +log "Transcription E2E passed with non-empty output from ${SPEECH_SAMPLE_PATH}: ${TRANSCRIPT}"