v1.16.1: build/listener/widget/update cleanups + parser tests#83
Merged
Conversation
build.sh starts with `rm -rf build`, which wipes any previously-placed `.metadata_never_index` marker. After the next rebuild, Spotlight reindexes `build/StackNudge.app` and the user sees two StackNudge entries — the installed bundle in ~/Applications and the dev artifact — which is confusing right after an update. Re-create the marker every build so the dev artifact stays out of Spotlight regardless of how often we rebuild.
Auto-update relaunch race: new bundle's EventListener.start() unlinked any stale socket, bound, and created the file. The old bundle's applicationWillTerminate then ran listener.stop() and unlinked the socket file out from under the new bundle, breaking event delivery for the rest of the new bundle's lifetime. Symptom: after update, no events land in the panel (no banners, no sounds, no Events tab activity) until the panel is manually restarted. Record the bound inode after start() succeeds; stop() now only unlinks if the file on disk is still the one we bound to. A successor process that has already replaced the socket keeps its file intact.
… badge Two fixes in the user-facing update + pill loop: - Pill: the headline ladder pinned to a single session (busiest → recent event → mostRecentActive). Users with 2+ parallel agents only saw the most-recent-active session and lost sight of the others until opening the panel. Insert a new branch — when ≥2 sessions are active and nothing more urgent is on screen, rotate through them every 5s with a soft crossfade. Snap back to the busy/event display the moment one takes priority; SwiftUI tearing down the view auto-cancels the timer. Pause cycling during drag so it doesn't compete with AppKit's handler. - UpdateChecker: release-please creates the GitHub Release the moment its PR merges, but the release.yml build/sign/notarize/upload runs for 5–15 minutes after. During that window UpdateChecker advertised the new version but Updater couldn't find a matching .tar.gz and failed with noArtifactForArch. Now check the release's assets[] for -macos-<arch>.tar.gz before flipping nav.updateAvailable, so the badge only appears once the artifact is actually downloadable. The user just sees "up to date" until CI finishes.
…ner parser Two pure-logic surfaces with high blast radius had no test coverage: - UpdateChecker.isNewer / .stripV / artifact-matching: a regression here silently misroutes auto-update — users either never see the badge or click Update and hit noArtifactForArch. Cover the classic semver pitfall (1.10 > 1.9 numerically), the pre-CI-build window where the tag exists but the .tar.gz hasn't uploaded, and sha256-sidecar false-positives. - EventListener wire parser: malformed JSON, missing optional fields, multi-line batches without trailing newline, mid-batch recovery. This is the most-traffic I/O path in the app — every notify.sh event passes through it. Small enabling refactors: - UpdateChecker: extract `hasArtifact(in:arch:)` from `hasArtifactForThisHost` so tests can exercise both archs without spoofing uname. - EventListener: extract `parseEvents(_:) -> [NudgeEvent]` from `handleClient` so the parse pipeline is testable without spinning up a socket. Skipped SessionStore.merge for now — `private` + needs deep `Session` scaffolding; revisit in a follow-up.
parseEvents splits on \n before decoding, so a multi-line raw-string JSON payload shreds into malformed fragments and the test sees zero events. Reflow as one line.
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
Four
fix:commits + onetest:commit, all bug-only. release-please bumps to 1.16.1.Lifecycle / hygiene
build.sh: re-createbuild/.metadata_never_indexon every build so Spotlight doesn't reindex the dev artifact every rebuild, producing a confusing duplicate next to `~/Applications/StackNudge.app`.EventListener.stop(): inode-guard the unlink. The post-update relaunch race had the old bundle's terminate handler removing the new bundle's freshly-created socket file out from under it — symptom: no events arriving until manual restart.Widget
.tar.gzupload takes 5–15 minutes more. UpdateChecker no longer surfaces the badge until the matching artifact is present, so clicking Update can't fail with `noArtifactForArch`.Tests
Test plan
🤖 Generated with Claude Code