feat: add optional read-only Companion discovery - #28
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 34207a17b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
|
|
||
| def _bounded_file(path): | ||
| fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK) |
There was a problem hiding this comment.
Provide a Windows-safe metadata open path
On Windows, which README.md lists as a supported Hermes platform, Python does not expose the POSIX-only os.O_NOFOLLOW and os.O_NONBLOCK constants. Every inspection reaches this expression—even when the profile and metadata are absent—and raises an uncaught AttributeError before os.open, making Companion discovery unusable on that platform. Use a Windows-safe no-follow regular-file implementation or explicitly handle unsupported platforms before evaluating these flags.
Useful? React with 👍 / 👎.
| result["installation"] = "unrecognized" | ||
| if isinstance(entry, dict) and evidence["pluginIdentity"] is not None: | ||
| revision, source = entry.get("revision"), entry.get("source") | ||
| if isinstance(revision, str) and REVISION.fullmatch(revision) and source in (SOURCE, SOURCE + ".git"): |
There was a problem hiding this comment.
Recognize sources already accepted by the updater
When metadata comes from a supported coordinated-app installation such as https://github.com/promptclickrun/loopdy-ios#plugins/loopdy or a file://...#plugins/loopdy checkout, this exact comparison reports unrecognized. The existing updater explicitly recognizes those installations in loopdy_plugin/plugin_update_worker.py:285-294 (and also normalizes valid SSH/trailing-slash forms at lines 298-306), so Companion can incorrectly direct an updateable installation into the repair flow. Apply the updater's established source normalization and accepted-source rules here.
Useful? React with 👍 / 👎.
A Companion setup flow needs to inspect an explicitly selected Hermes profile without importing a gateway or confusing installed metadata with live activation.
Adds a standalone read-only probe and attended initial-install argument planner. It reads bounded installation metadata, refuses malformed/symlinked or existing installations, rechecks the profile fingerprint, and emits immutable revision arguments with --no-enable for the supported Hermes installer. It reads no provider configuration or pairing keys and creates no files. Active revision stays null; live activation must come from the authenticated gateway.
Existing installations remain with Hermes update/repair. This does not execute an installer, choose an executable, provide installation locking, verify release signatures, enable a plugin or restart a gateway. Existing plugin imports, registration and updater are unchanged. See scripts/COMPANION_DISCOVERY.md.
Validation: 6 focused unittest tests passed, including null registrations, deep/malformed JSON, stale snapshots, symlinks and read-only preservation. Independent scoped review passed after malformed-registration fixes. New CI runs the focused suite. Real installed Hermes/Companion integration remains pending.