Skip to content

feat: a Mac offers to remove the 1.x it finds, and the resident holds the shortcut - #28

Merged
rgdevment merged 3 commits into
mainfrom
rgdevment/fin
Sep 26, 2026
Merged

rgdevment merged 3 commits into
mainfrom
rgdevment/fin

Conversation

@rgdevment

Copy link
Copy Markdown
Owner

1.x ships under com.rgdevment.linkunbound and 2.x under dev.rgdevment.linkunbound, so Launch Services treats them as unrelated applications: the old copy keeps its own login item, starts at sign-in and goes on answering for links however 2.x registers. Windows removes it from the installer; a Mac is dragged in, so the settings window is the only place that can ask.

Links now offers to retire a 1.x it finds: the copy goes to the trash, never deleted, and rules and browsers are untouched. A refusal — /Applications needs an administrator — hands the person to Finder. The command takes no path, so it cannot be asked to trash anything else.

The global shortcut moves to the resident. It was claimed by the settings binary, whose only effect was to open the very window that had to be open for the claim to exist, and sign-in starts the resident alone: the preference did nothing. The resident claims it through global-hotkey and writes down what it holds, which is what the window now reads.

Also:

  • The notice no longer takes the keyboard on a Mac. There is no window style for it there, so the application stops being the active one instead — unless a picker is up, which is the one moment it has to be.
  • Copy and private answer to Cmd on a Mac, where Ctrl+click is a right click.
  • The link channel refuses to open rather than fall back to a descriptor every account on the machine can read, with a test for both ways it can fail.
  • The uninstaller sweeps the OpenWithProgIds values it writes; without them "Open with" went on offering a program that is gone. A test fails if the list in the installer and the one in the code ever drift apart.
  • The diagnostics report is written in the language that was chosen, file name included, and lands on the Desktop of a Mac instead of its temporary folder.
  • One rule decides whether a version is worth offering. The strip compared semver alone, so it offered candidates the errand behind the button refused.
  • The resident's build script reads the target rather than the host, which is what made a cross build for a Mac embed a Windows manifest and die.
  • release: the tested gate waits forty minutes instead of twenty and the bundles wait for it; the tap token stays out of the clone's .git/config; the signing certificate leaves the runner store; the Store is asked what became of a submission that was tolerated, which is the case the question was written for.
  • scripts: the cache sweep sees past the hundredth cache.
  • save_prefs had no callers but its own tests; the stale version in app/package.json and the unread release-manifest.json at the root are gone.

… the shortcut

1.x ships under com.rgdevment.linkunbound and 2.x under dev.rgdevment.linkunbound,
so Launch Services treats them as unrelated applications: the old copy keeps its
own login item, starts at sign-in and goes on answering for links however 2.x
registers. Windows removes it from the installer; a Mac is dragged in, so the
settings window is the only place that can ask.

Links now offers to retire a 1.x it finds: the copy goes to the trash, never
deleted, and rules and browsers are untouched. A refusal — /Applications needs an
administrator — hands the person to Finder. The command takes no path, so it
cannot be asked to trash anything else.

The global shortcut moves to the resident. It was claimed by the settings binary,
whose only effect was to open the very window that had to be open for the claim to
exist, and sign-in starts the resident alone: the preference did nothing. The
resident claims it through global-hotkey and writes down what it holds, which is
what the window now reads.

Also:

- The notice no longer takes the keyboard on a Mac. There is no window style for
  it there, so the application stops being the active one instead — unless a
  picker is up, which is the one moment it has to be.
- Copy and private answer to Cmd on a Mac, where Ctrl+click is a right click.
- The link channel refuses to open rather than fall back to a descriptor every
  account on the machine can read, with a test for both ways it can fail.
- The uninstaller sweeps the OpenWithProgIds values it writes; without them
  "Open with" went on offering a program that is gone. A test fails if the list
  in the installer and the one in the code ever drift apart.
- The diagnostics report is written in the language that was chosen, file name
  included, and lands on the Desktop of a Mac instead of its temporary folder.
- One rule decides whether a version is worth offering. The strip compared
  semver alone, so it offered candidates the errand behind the button refused.
- The resident's build script reads the target rather than the host, which is
  what made a cross build for a Mac embed a Windows manifest and die.
- release: the tested gate waits forty minutes instead of twenty and the bundles
  wait for it; the tap token stays out of the clone's .git/config; the signing
  certificate leaves the runner store; the Store is asked what became of a
  submission that was tolerated, which is the case the question was written for.
- scripts: the cache sweep sees past the hundredth cache.
- save_prefs had no callers but its own tests; the stale version in
  app/package.json and the unread release-manifest.json at the root are gone.
Moving the claim to the resident left it reading preferences.json only when a
link arrived or the tray opened settings, so a combination changed in a window
that stays open went on being the old one until something unrelated happened.
The settings binary used to register synchronously and this was immediate.

The pump now looks at the file about once a second and obeys what it finds,
which is the same check catch_up() already made, split out so both can use it.
The screen asks again shortly after a combination changes, so what it says is
held is what the resident answered rather than what the file said before it had
a chance to reply.

tracking() defers to the core's on_the_candidate_track instead of repeating it:
the two had already drifted, since only one of them trimmed a leading `v`.
…er cannot run

The quality gate failed on coverage of new code (58.7% against 80), with
everything else green. What was missing was covered rather than waived:

- the shortcut the resident writes down and the window reads back, including a
  file of blanks, which must read as nobody holding anything
- the one rule that decides whether a version is worth offering, the candidate
  track it rests on, and the leading `v` the two copies of that rule used to
  disagree about
- the file-moved check behind the fix before this one, split from the call that
  reads the clock so it can be exercised without one
- what the Mac lookup answers when there is no 1.x installed, which is the
  machine every runner is

Two files are excluded from coverage instead, for the reason app/src-tauri/src
already is: a global shortcut cannot be registered on a headless runner, and
the resident's main.rs is the binary that talks to the system.
@rgdevment
rgdevment merged commit 3dc7b50 into main Sep 26, 2026
20 checks passed
@rgdevment
rgdevment deleted the rgdevment/fin branch September 26, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant