Skip to content

Report installed plug-in copies from bridge-health-check (#200) - #201

Merged
deverman merged 1 commit into
masterfrom
plugin-path-diagnostic
Aug 1, 2026
Merged

Report installed plug-in copies from bridge-health-check (#200)#201
deverman merged 1 commit into
masterfrom
plugin-path-diagnostic

Conversation

@deverman

@deverman deverman commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Addresses the durable half of #200. The documentation fix shipped in #199; this is the part that makes the failure self-diagnosing.

Problem

OmniFocus can load a plug-in bundle from a directory the user never updated, and keep doing so across reinstalls and full restarts. The version the bridge reports cannot distinguish "the plug-in I just installed" from "a stale plug-in in a folder I forgot about" — both look like a plain version string. Diagnosing it means manually enumerating up to four locations and reading a JS constant out of each.

That is not hypothetical: it happened on a development machine today and took roughly an hour to track down, after a version check had already reported everything as fine.

Change

bridge-health-check now reports every installed bundle it can find, and warns when they disagree:

{
  "ok": true,
  "plugin": "FocusRelay Bridge",
  "version": "0.12.0-beta",
  "installedPlugins": [
    { "location": "icloud",  "version": "0.12.0-beta", "path": ".../iCloud~com~omnigroup~OmniFocus/Documents/Plug-Ins/FocusRelayBridge.omnijs" },
    { "location": "sandbox", "version": "0.0.0-dev",   "path": ".../com.omnigroup.OmniFocus4/Data/.../Plug-Ins/FocusRelayBridge.omnijs" }
  ],
  "pluginWarning": "OmniFocus is running plug-in 0.12.0-beta, but these installed copies differ: sandbox (0.0.0-dev). OmniFocus prefers the iCloud copy when plug-in sync is enabled, so updating only the sandbox copy has no effect. ..."
}

The warning names iCloud precedence explicitly, because "I updated the plug-in and nothing changed" is the symptom users actually report.

Two implementation notes:

  • Versions come from the FOCUSRELAY_VERSION constant, not manifest.json. The manifest carries only the numeric core (0.12.0) while the bridge reports the full tag (0.12.0-beta), so comparing manifests would produce spurious mismatches on every prerelease.
  • BridgeHealthResult gains two optional fields. It has no MCP surfacebridge-health-check is CLI-only, confirmed by grep — so the tool wire contract is unchanged and the additions are decode-compatible.

Validation

Impact: query, per focusrelay-dev classify (conservative: the change lives in OmniFocusAutomation). Ran that tier rather than arguing for a narrower one.

  • All semantic gates pass — bridge health plus every task/project count contract matching its list total.
  • 246 tests pass, including 11 new ones covering version extraction, the warning matrix (agreement, stale copy, binary mismatch, missing bundles, unreadable bundle, no-version), search order, and on-disk discovery against a temporary home.
  • Verified live by reproducing Installed plug-in is ignored when OmniFocus plug-in sync is enabled: README installs to the wrong directory #200: with only the sandbox copy updated — exactly what the old README instructed — the health check named the stale copy and explained why the update had no effect. Machine restored afterwards.

Not included

The installer-side half of #200: install-plugin.sh silently skips a plug-in directory that is not materialised at that instant (create_if_missing=False), so an evicted iCloud folder produces a partial install that reports success and exits 0. That is tracked in the issue and left for a follow-up, since it is installer behavior rather than diagnostics.

🤖 Generated with Claude Code

OmniFocus can load a plug-in bundle from a directory the user never
updated, and the reported version alone cannot distinguish "correct
plug-in" from "stale plug-in somewhere else". Diagnosing that today means
manually enumerating four possible locations.

bridge-health-check now lists every installed bundle with its location and
runtime version, and emits a warning when the loaded plug-in disagrees
with an installed copy or with the binary. The warning names the iCloud
precedence explicitly, because updating only the sandbox copy is the
failure users actually hit.

Versions are read from the FOCUSRELAY_VERSION constant rather than
manifest.json: the manifest carries only the numeric core (0.12.0) while
the bridge reports the full tag (0.12.0-beta), so comparing manifests
would produce spurious mismatches.

BridgeHealthResult gains two optional fields. It has no MCP surface --
bridge-health-check is CLI-only -- so this does not change the tool wire
contract.

Validation impact: query, per focusrelay-dev classify. All semantic gates
pass; 246 tests pass including 11 new ones. Verified live by reproducing
the issue #200 scenario: with only the sandbox copy updated, the health
check named the stale copy and explained why the update had no effect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@deverman
deverman merged commit d85a9c2 into master Aug 1, 2026
4 checks passed
@deverman
deverman deleted the plugin-path-diagnostic branch August 1, 2026 12:40
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