Repository navigation
Switch auto-updating to Sparkle, with a staging rehearsal and hand-written release notes - #214
Merged
Merged
Conversation
Replace the download-only GitHub-API update check with Sparkle 2.10.0 (app target only; the engine stays dependency-free). - App: UpdaterModel wraps SPUStandardUpdaterController; the app menu, menu-bar item and a new Settings → Advanced → Updates section (check button, auto-check and auto-install toggles) all drive it. Only the shipping bundle id starts the updater, so Blurt Dev never replaces itself with the release. - project.yml: Sparkle package pinned exactly, SUFeedURL pointing at releases/latest/download/appcast.xml, SUPublicEDKey from the new SPARKLE_PUBLIC_ED_KEY setting (placeholder until the key pair exists). - Engine: remove UpdateChecker, GitHubRelease, UpdateAlertContent, AutomaticUpdateCheck, LastUpdateCheckStore, SemanticVersion, HostIdentity.releaseURL and the lastUpdateCheck defaults key. - Release: sign Sparkle's nested helpers, EdDSA-sign the DMG with sign_update, verify the signature against the built app's key, write appcast.xml, and attach + verify it on publish. New SPARKLE_ED_PRIVATE_KEY secret on release-build. - Guards/docs: check.sh allowlists the Sparkle URL as the one remote app package; retire the "download-only updates" invariant rule and rewrite the settled-decision row, guardrails skill, AGENTS.md, RELEASE.md, SECURITY.md and READMEs. project.pbxproj still needs `xcodegen generate` on a Mac. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FQUiqVMpAMeReVN9Ej2yBu
Match the button title to the menu item ("Check for Updates…"), use
less update-ambiguous symbols, name updates in the auto-install toggle,
and word the debug footer for the build in hand.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FQUiqVMpAMeReVN9Ej2yBu
Sparkle's update alert can switch automatic installs on; observe both preferences so an open Settings pane reflects it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FQUiqVMpAMeReVN9Ej2yBu
Replaces the SPARKLE_PUBLIC_ED_KEY placeholder with the real EdDSA public key so release-build.sh no longer refuses to run, and commits the xcodegen output for the Sparkle switch (package reference + SU* Info.plist keys). The private half is the SPARKLE_ED_PRIVATE_KEY secret on release-build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SUFeedURL is now the BLURT_SPARKLE_FEED_URL build setting, so `release-build.sh --staging` can build an app that polls the sparkle-staging prerelease (never marked latest) instead of /latest. The build reads SUFeedURL back out of the built app, release-stage.sh (and the workflow's `stage` job) uploads there, and release-publish.sh refuses a staging build. - The appcast carries a Markdown <description> for the update window. A release requires docs/release-notes/X.Y.Z.md: release-bump.sh scaffolds it with the commits as a comment plus a TODO, and check-release-notes.sh (in check.sh and the build) fails on the TODO, filler phrases, emoji, PR numbers, identifiers, and over-long lists. Only a staging build falls back to filtered commit subjects. - RELEASE.md documents the notes rules and the update rehearsal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Stop banning "enhanced": it is part of the "Enhanced transcripts" setting name, so accurate notes failed lint and blocked the build. - Report lint line numbers against the file: comments are blanked but their newlines kept, so the bump scaffold's long comment no longer shifts every reported line. - Add `check-release-notes.sh --new X.Y.Z` to scaffold notes for a version that didn't come through release-bump.sh (a re-run or republish), and point the build's missing-notes error at it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/ is local-only working notes (.gitignore), so neither the bump nor a maintainer could commit docs/release-notes/X.Y.Z.md. Move them to a top-level release-notes/ and pin that it stays committable in release.test.sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
alexkroman
enabled auto-merge
September 30, 2026 02:21
alexkroman
disabled auto-merge
September 30, 2026 02:22
The bump now scaffolds release-notes/X.Y.Z.md with a TODO that check fails on, so following the old steps stalled at the PR. Add the notes-drafting step (draft, show the user, commit on their go-ahead), the SPARKLE_ED_PRIVATE_KEY precondition, what the build and publish now do for the appcast, the staging rehearsal for updater changes, and the one-time manual update for v0.1.58. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RELEASE.md → Release notes → Writing them covers what the lint can't: the reader, translating commits into what a user notices (with commit-to-note examples), what to leave out, ordering, wording, and v0.1.57's rehearsal notes as the model. The release skill now drafts from that guide, checks the PRs behind vague subjects, and shows the user what it left out and why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cleanup (/simplify): - One helper each for the notes scaffold (release-bump.sh and check-release-notes.sh --new), commit subjects since a release, and verifying downloads against SHA256SUMS (publish and stage). - sparkle_release_tag is the one channel -> tag mapping; the enclosure and "Version History" URLs derive from it, so the release page URL is no longer an untested inline if in the build. - Publish and stage compare the build channel exactly, so a build-info without one is refused instead of read as a release. - lint_release_notes: nocasematch instead of a tr per line, one perl pass for emoji instead of one per line. - RELEASE.md points at RELEASE_NOTES_BANNED instead of a copy that had drifted (it still banned "enhanced"), and no longer calls updates a manual DMG download in the cert-rotation section. Fixes (/code-review): - "Reset Blurt" clears the app's whole defaults domain after the engine keys, so Sparkle's SU* settings (auto-install) don't survive it. - release-bump.sh checks for an earlier release tag before editing project.yml, so that failure can't leave a dirty tree. - The scaffold neutralizes every run of dashes, not just pairs, so a "--->" in a commit subject can't close the context comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#186 renamed STT/ConversationContext.swift to STTPrompt.swift, but mutate.sh's default targets still named the old file, so the script refused to start. Nothing noticed because the full run is deliberately kept out of check.sh. - Swap the dead target for STTPrompt.swift (still pure logic, no imports). - check.sh now runs `mutate.sh --list`, which validates every target and enumerates mutants without building or testing, so it runs in --portable. - --list no longer backs up and restores targets: the restore's cp bumped every target's mtime, which would force a recompile in check.sh's Swift build. restore_all uses an `if` so a missing backup doesn't fail the EXIT trap under errexit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
alexkroman
enabled auto-merge
September 30, 2026 02:35
alexkroman
added this pull request to the merge queue
Sep 30, 2026
This was referenced Sep 30, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Moves Blurt's auto-updating to Sparkle and adds what's needed to ship it safely.
0266f8a,ebc873b,bf453fa):UpdaterModeloverSPUStandardUpdaterController. Only the shipping bundle ID starts the updater. The Settings → Updates section follows the HIG review.0358a67):SPARKLE_PUBLIC_ED_KEYis set, and the Xcode project is regenerated. The private key is theSPARKLE_ED_PRIVATE_KEYsecret onrelease-build, with a backup outside the keychain.021d449):SUFeedURLis now theBLURT_SPARKLE_FEED_URLbuild setting.release-build.sh --stagingbuilds an app that checks thesparkle-stagingpre-release, which is never marked latest.SUFeedURLback out of the built app and fails on a mismatch.stagejob (andrelease-stage.sh) uploads there.release-publish.shrefuses to publish a staging build.021d449,b7c4df9,507fc76): the appcast carries a Markdown<description>. A release needs a hand-writtenrelease-notes/X.Y.Z.md:TODOthatcheckfails on.check-release-notes.shlints it: at most 6 bullets of 100 characters, no filler words, emoji, PR numbers, or code names.--new X.Y.Zcreates the file for a version that didn't come through a bump.Documented in
RELEASE.md→ Release notes and Rehearsing an update.Rehearsal (done)
This ran end to end on CI from
release-dry-run-sparkle:EdDSA signature is correct for update.spctlreportsaccepted/Notarized Developer ID, and it has no quarantine flag./releases/lateststayed onv0.1.57throughout.The rehearsal caught one bug, fixed in
507fc76: notes under the gitignoreddocs/couldn't be committed.Test plan
scripts/check.shpasses locally (full run before507fc76;--portableafter)scripts/release.test.shpasses under bash 5 and macOS bash 3.2release-notes/0.1.58.md; write the notes in that PRNotes
release-buildenvironment currently has no branch restriction.RELEASE.mdrecommendsmainonly, and the rehearsal steps explain the temporaryrelease-dry-run*exception.🤖 Generated with Claude Code