mirror of
https://github.com/alphaXiv/OpenResearch.git
synced 2026-10-02 01:34:34 +08:00
main
18
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
56c9b5fd0d |
Generate release notes with linked fixes and optional highlights (OR-357) (#472)
* Add generated release notes and issue links * Run release note check in CI * Grant release job read access to linked issues * Preserve release tags and keep issue lookup optional * Fix version check release notes link |
||
|
|
c95be22a35 |
OR-326 Add the Linux desktop app as a self-updating AppImage (#445)
* Open the macOS app's dashboard in its own window The OpenResearch.app now hosts the dashboard in a native window (tao + wry WKWebView) instead of handing it to the user's browser. It adds a standard menu bar, save panels for downloads, a native window.confirm panel, and a Cmd+Q that flushes workspace state and shuts the server down cleanly. Pop-ups open in the system browser (http/https/mailto only). The app now prefers port 4792 so the window's localStorage survives relaunches. The Dock-click tab-focus script, its Apple-events entitlement, and the SSE client counter it relied on are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Open the dashboard in its own window on Windows Adds the Windows desktop app. A small GUI-subsystem OpenResearch.exe (windows/launcher) starts the orx.exe beside it as `orx app` in a hidden console, so orx and the git, shell, and agent processes it runs share one invisible console instead of each flashing a window. `orx app` shares the macOS window code in src/commands/app.rs: WebView2 window, pop-ups to the system browser, save panel, page-load reveal, and port 4792. On Windows, closing the window quits, a second launch focuses the running window (named mutex + event), and the taskbar groups the window with the Start menu shortcut. An update restart relaunches as the app on the same port. Quit on both platforms now goes through up::request_shutdown instead of a self-sent SIGTERM. An Inno Setup script builds a per-user OpenResearch-Setup.exe with a Start menu entry and a WebView2 bootstrap. CI builds it as an artifact, and release-windows-app.yml attaches it to releases once WINDOWS_APP_ENABLED is set. The icon is embedded via embed-resource. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the Windows build and address review of the Windows app - The focus listener captured its bare HANDLE (edition 2021 disjoint capture) instead of the Send wrapper, which failed to compile on Windows. - An orx.exe away from the CLI installer's prefix, like the app's, is now Portable even when the installer's receipt exists, so it can update itself. - Single instance creates its event before the mutex; the launcher hands its foreground rights to orx.exe. - Focus requests and server readiness are ignored while quitting, and focus waits for the first load. The save dialog is owned by the window. - Telemetry counts an app start only after the instance claim. - The installer reports a failed WebView2 bootstrap and shows progress. - Icon embedding now fails the build if no resource compiler is found. - CI format-checks the launcher; the release job drops an unpinned action. - Docs: maintainer notes for the release gate, two known gaps, and wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tighten the Windows app after a second review - Keep the macOS save panel free-floating: only Windows gets the window as its owner, since a parent makes rfd show a sheet on macOS. - Treat the WebView2 bootstrap as failed unless the runtime is then present. - Move the UTF-16 helper out of the single-instance module, and bind the kernel object names before the mutex call that GetLastError follows. - Docs and a dead_code reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Linux desktop app as a self-updating AppImage A `desktop` cargo feature builds the windowed app on Linux (glibc, WebKitGTK), leaving the static musl CLI builds untouched. build.rs sets cfg(desktop_app) for macOS, Windows, and Linux with the feature, replacing the macOS-or-Windows gates. The AppImage's AppRun starts `orx app`, sharing the Windows entry point: the webview is built into the GTK window's box (X11 and Wayland), closing quits, a Unix socket in XDG_RUNTIME_DIR keeps one instance and focuses it, and the login shell's PATH is adopted as on macOS. scripts/build-linux-appimage.sh bundles WebKitGTK with pinned linuxdeploy, its GTK plugin, and appimagetool, copying WebKit's helper processes and rewriting libwebkit2gtk's /usr paths to ././ so they resolve inside the image. CI builds x86_64 and aarch64 AppImages on Ubuntu 22.04 and smoke-tests each under Xvfb; release-linux-app.yml attaches them with linux-app.json once LINUX_APP_ENABLED is set. The AppImage updates itself (InstallChannel::AppImage, updates/linux_app.rs): a sha256-checked download renamed over the file, production builds only, and Restart execs the new AppImage on the same port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the Linux app's downloads, bundled WebKit, and host environment From review of the Linux desktop app: - Downloads froze the app: rfd's GTK backend runs its dialog on a thread of its own, which waits forever on the main context tao holds. The save dialog is now a gtk::FileChooserDialog run on the main thread. - The bundled WebKit helpers found their libraries only beside themselves, so they loaded the host's WebKit or none. They now get an RPATH to the image's usr/lib, and linuxdeploy no longer makes stray copies of them. - The GTK hook's variables reached every host program orx opens. AppRun now saves the session's values and orx hands them back to xdg-open, the folder picker, error dialogs, and agents. - The smoke test now runs after WebKitGTK is removed from the runner and checks that each WebKit helper runs, and loads libwebkit2gtk, from the image; cleanup kills the app's whole process group. - Startup failures now reach stderr and a zenity or kdialog dialog. - The tools and the AppImage runtime are pinned by sha256, and only the release job that publishes can write to the release. - Smaller fixes: the shell probe runs after the single-instance claim and falls back to /bin/sh; APPDIR is canonicalized and must not be empty or root; relative project paths resolve against home inside the image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the session's GTK settings across Linux app restarts and terminals Restore the host GTK variables before an update relaunches the AppImage, so the new AppRun doesn't save the old image's values as the session's, and in the dashboard's terminals. Share one APPDIR containment check between the update channel, relative project paths, and the folder picker, which now keeps a terminal `orx up`'s working directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Relaunch the AppImage only from inside it, and tidy after review Pick the relaunch target with the same APPDIR check as the update channel, so an `orx app` started from the app's terminal restarts itself. Hand the shell probe the session's GTK settings, harden the smoke test's helper checks and cleanup, and bring the docs up to date. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Run the AppImage detection test only on Unix Its mount paths aren't absolute on Windows, which has no AppImage anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Import the AppImage test's helper inside the Unix-only test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show the app window even when the dashboard never finishes loading On a UTM VM the Linux app ran with no window: it stays hidden until the page finishes loading, and that never happened. Show it 15 seconds after the server is up regardless, say so on stderr, and have the smoke test fail if that fallback fires or no window appears. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give the Linux app its name and icon in the dock, and keep GIO off host modules GNOME shows an unmatched window as a gear named after its class, so name the program OpenResearch and have each launch install a desktop entry and icon pointing at the AppImage (TryExec hides it once the file is gone). Bundle GLib's TLS module and set GIO_MODULE_DIR to the image's, so the bundled GLib stops loading the host's modules, built against a newer one. A second launch now shows the window even before the page loads, so a stuck instance can't swallow it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tidy the Linux app after the fourth review Write the desktop entry only from the AppImage's own orx (shared with the update relaunch), keep a session's GIO_EXTRA_MODULES off the bundled GLib, mark a Dock-reopened macOS window as shown so the load fallback can't reopen it, close a race in the smoke test, and note the Fedora and openSUSE TLS gap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show a stalled app window, and close the app before the installer runs If the dashboard never finishes loading, show the window 15 seconds after the server is up and say so on stderr; a relaunch (or a Dock click on macOS) also shows it before the page loads. The installer and uninstaller now check the app's single-instance mutex and ask the user to close it, rather than replacing files under a running app and skipping its shutdown path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a replaced download's original until it lands, and don't offer a launch without WebView2 Move the file a download replaces aside and restore it if the download fails or is cancelled (WebView2's flyout can cancel), rather than deleting it up front. The installer no longer offers to start OpenResearch when the WebView2 Runtime is still missing, since the window could not open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2c63f548c2 |
OR-326 Open the dashboard in its own window on Windows (#439)
* Open the macOS app's dashboard in its own window The OpenResearch.app now hosts the dashboard in a native window (tao + wry WKWebView) instead of handing it to the user's browser. It adds a standard menu bar, save panels for downloads, a native window.confirm panel, and a Cmd+Q that flushes workspace state and shuts the server down cleanly. Pop-ups open in the system browser (http/https/mailto only). The app now prefers port 4792 so the window's localStorage survives relaunches. The Dock-click tab-focus script, its Apple-events entitlement, and the SSE client counter it relied on are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Open the dashboard in its own window on Windows Adds the Windows desktop app. A small GUI-subsystem OpenResearch.exe (windows/launcher) starts the orx.exe beside it as `orx app` in a hidden console, so orx and the git, shell, and agent processes it runs share one invisible console instead of each flashing a window. `orx app` shares the macOS window code in src/commands/app.rs: WebView2 window, pop-ups to the system browser, save panel, page-load reveal, and port 4792. On Windows, closing the window quits, a second launch focuses the running window (named mutex + event), and the taskbar groups the window with the Start menu shortcut. An update restart relaunches as the app on the same port. Quit on both platforms now goes through up::request_shutdown instead of a self-sent SIGTERM. An Inno Setup script builds a per-user OpenResearch-Setup.exe with a Start menu entry and a WebView2 bootstrap. CI builds it as an artifact, and release-windows-app.yml attaches it to releases once WINDOWS_APP_ENABLED is set. The icon is embedded via embed-resource. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the Windows build and address review of the Windows app - The focus listener captured its bare HANDLE (edition 2021 disjoint capture) instead of the Send wrapper, which failed to compile on Windows. - An orx.exe away from the CLI installer's prefix, like the app's, is now Portable even when the installer's receipt exists, so it can update itself. - Single instance creates its event before the mutex; the launcher hands its foreground rights to orx.exe. - Focus requests and server readiness are ignored while quitting, and focus waits for the first load. The save dialog is owned by the window. - Telemetry counts an app start only after the instance claim. - The installer reports a failed WebView2 bootstrap and shows progress. - Icon embedding now fails the build if no resource compiler is found. - CI format-checks the launcher; the release job drops an unpinned action. - Docs: maintainer notes for the release gate, two known gaps, and wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tighten the Windows app after a second review - Keep the macOS save panel free-floating: only Windows gets the window as its owner, since a parent makes rfd show a sheet on macOS. - Treat the WebView2 bootstrap as failed unless the runtime is then present. - Move the UTF-16 helper out of the single-instance module, and bind the kernel object names before the mutex call that GetLastError follows. - Docs and a dead_code reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show a stalled app window, and close the app before the installer runs If the dashboard never finishes loading, show the window 15 seconds after the server is up and say so on stderr; a relaunch (or a Dock click on macOS) also shows it before the page loads. The installer and uninstaller now check the app's single-instance mutex and ask the user to close it, rather than replacing files under a running app and skipping its shutdown path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a replaced download's original until it lands, and don't offer a launch without WebView2 Move the file a download replaces aside and restore it if the download fails or is cancelled (WebView2's flyout can cancel), rather than deleting it up front. The installer no longer offers to start OpenResearch when the WebView2 Runtime is still missing, since the window could not open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b05312eb8c |
Even out the DMG installer window's vertical padding (#454)
Finder's window bounds include the 28pt title bar, so the 640x320 frame left a 292pt content area: the background's bottom was cropped and the labels sat closer to the bottom edge than the icons to the top. Size the frame for a full 320pt content area, and park dot-folders off-window so Finder builds that show hidden files don't shift the icons down. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7159b1f134 |
Open the macOS app's dashboard in its own window (#438)
The OpenResearch.app now hosts the dashboard in a native window (tao + wry WKWebView) instead of handing it to the user's browser. It adds a standard menu bar, save panels for downloads, a native window.confirm panel, and a Cmd+Q that flushes workspace state and shuts the server down cleanly. Pop-ups open in the system browser (http/https/mailto only). The app now prefers port 4792 so the window's localStorage survives relaunches. The Dock-click tab-focus script, its Apple-events entitlement, and the SSE client counter it relied on are removed. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
609ad7e3ed |
Fix OpenCode 2.0.6+ health probe and WSL browser launch (#409)
OpenCode 2.0.6 removed /api/status in favor of /api/info, so orx probed two dead routes until the 30s timeout and reported "Could not read OpenCode configuration". The V2 check now negotiates /api/info -> /api/status -> /api/health and requires a JSON body carrying `version`, since the SPA fallback can answer unknown routes with HTML 200s. /api/health answering still marks the legacy (<=2.0.3) route layout for export/generate paths. On WSL, xdg-open often has nothing to launch, so the dashboard URL never reached the Windows browser. On WSL the URL now goes to the Windows host through rundll32.exe url.dll,FileProtocolHandler (by PATH, then by absolute System32 path for appendWindowsPath=false), then wslview, then xdg-open. rundll32 is tried first because some wslview builds re-parse the URL through cmd and truncate at '&', which breaks the login callback's state parameter. Native Windows switches from cmd /C start to the same argv-safe rundll32 call. The compat fixture learns the same health negotiation, treats the 2.0.6+ synthetic idle message correctly when waiting for a reply, and looks for export under /api/experimental first. Refs #341 |
||
|
|
94ef49b37e |
Run SSH experiments in existing Docker containers (#407)
* feat: run SSH experiments in existing Docker containers * Simplify SSH container settings and harden launch recovery |
||
|
|
5fa74d1c3b |
Support OpenCode V2 alongside V1 with safe history migration (#348)
* Support OpenCode V2 alongside V1 with safe history migration * Avoid guessing OpenCode V2 authentication method * Remove OpenCode migration backups after validated upgrade |
||
|
|
cf4baa720f |
Move managed repositories from cache to persistent storage (OR-230) (#315)
* fix(storage): migrate managed repositories out of cache (OR-230) * Repair native OpenCode directories during storage migration * Keep migration checks read-only and verify repaired references * Bump version to 0.2.1 |
||
|
|
e791d30695 |
OR-251: Add native SSH remote workspaces (#275)
* OR-251: Open remote dashboards over SSH * feat: add native SSH remote workspaces * feat: persist remote OpenResearch agent hosts * fix: harden persistent remote host lifecycle * fix: close persistent remote session races * Complete persistent remote workspace sessions |
||
|
|
76c671c3b2 |
OR-215 Use GitHub CLI for publishing (#254)
* OR-215 use GitHub CLI for publishing * Isolate dev slot caches * Color GitHub CLI connection states |
||
|
|
f27c858c78 |
Simplify the DMG installer window to a plain drag-to-install (#228)
Drop the brand mark from the DMG background so the window is just the app icon, an arrow, and the /Applications alias. With the mark gone the window shrinks 640x400 -> 640x320 and the icon row recenters (86px above the icons, 86px below the labels). The arrow now sits level with the icon centers (ICON_Y) and is centered on the icons' artwork gap rather than their 128px cells, since the two icons inset their art by different amounts. Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
45eb162e19 |
Focus the existing dashboard tab on a Dock click (#212)
The macOS app's Dock-icon handler called `open <url>` on every click. Once the dashboard SPA has navigated off `/` the browser has no exact-URL match, so the click opened a new tab instead of returning to the dashboard already open. The handler now tries, best first: the exact tab via a JXA script over the scriptable browsers; the browser window itself, when a tab still holds its `/api/events` stream (the only way to infer an open dashboard in Firefox, which exposes no tab API); and finally the plain open it did before. A repeat click within five seconds takes the plain open, so a raise that did not surface the dashboard is always recoverable — the app's port is ephemeral, and the user has no other route back to it. JXA rather than AppleScript because it resolves each browser's terminology at run time: an AppleScript `using terms from` block fails to compile on a Mac without Chrome installed. Signing now passes macos/entitlements.plist, since the hardened runtime denies the Apple event outright without it — a failure that appears only in signed builds, never in a local one. Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e9d322e547 |
Add lightweight project briefs and refresh onboarding (#200)
* feat: add lightweight project briefs and onboarding refresh * fix: refine onboarding and project workspace interactions * fix: harden demo onboarding state * fix: satisfy current clippy lint * chore: bump version to 0.1.105 |
||
|
|
46d359ff5e |
OR-173 Make the macOS app find harnesses, and stop it fighting a CLI install (#195)
* fix(app): detect harnesses in the macOS app by adopting the shell PATH Finder launches OpenResearch.app through launchd, so the bundle starts with PATH=/usr/bin:/bin:/usr/sbin:/sbin and no shell rc ever sourced. Harness detection resolves `claude`/`codex`/`opencode` off that PATH, so a DMG user with a Homebrew, nvm, or npm-global install saw every harness missing -- including an already-signed-in Claude Code session -- while a terminal `orx up` on the same machine detected them all. App mode now probes the user's shell once at startup and installs the result via `local::search_path`, which harness lookup and harness children consult instead of the process PATH. The probe is `$SHELL -ilc`: interactive, because zsh reads .zshrc only for interactive shells and that is where PATH edits live -- a login-only probe missed the ~/.local/bin holding `claude`. It runs an inner `sh -c` so fish reports a colon-separated PATH rather than its own list-valued $PATH, fences the value between per-probe nonce markers so rc-file chatter cannot forge one, and requires an absolute directory in the result. Best-effort throughout: a 5s cap, and every outcome logged. The five detection probes that spawned a harness binary with no env prep (`bin_version`, `claude_accepts_ultracode`, `claude_list_models`, `codex_model_list`, `run_models`) now go through `prepare_env` like `probe_auth` already did. Without that, a node-shebang install resolves via the hydrated PATH but its `--version` fails for want of `node`, and `gate_oauth_version` turns the missing version into `Unknown` -- telling a signed-in user to sign in. Verified end to end: a bundle run under launchd's PATH with an isolated ORX_DATA_DIR reports Claude Code agentReady, and finds a `codex` reachable only through the hydrated PATH -- codex has no fallback drop-location, so that resolution can only have come from the override. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(app): stop the bundle and a CLI install from conflicting Three ways the DMG app and a curl-installed `orx` stepped on each other. `orx delete` takes an exclusive lifecycle lock and refuses when another OpenResearch process holds it -- "Close `orx up`, `orx serve`, and any active runs before trying again." CLI `orx up` holds the matching read lock via `dispatch`, but app mode returns from `main` before `dispatch` runs, so it held nothing: `orx delete` from a CLI install would wipe the store out from under a live app. App mode now takes the same read lock for the life of the process. Agents shell out to `orx`, and `chat::prepare_env` prepends the running executable's directory so they get THIS build. In the bundle that directory held only `OpenResearch`, so `orx` fell through to whatever CLI the user had -- a different version, or nothing at all for a DMG-only user. The bundle now ships `Contents/MacOS/orx` as a symlink to the executable. Verified the symlink survives `codesign --options runtime` + `--verify --strict`. That alias would otherwise open a second dashboard, since a bare `orx` reaches app mode's no-arguments condition. `launched_as_app_bundle` now also requires that the process was invoked under the bundle executable's own name, which keeps the alias a plain CLI while leaving a direct run of the executable path -- the documented way to watch the app's logs -- in GUI mode. macOS `current_exe` reports the launch path symlink and all, so it is canonicalized before the comparison. Verified safe already, and left alone: the app binds an ephemeral port rather than 4791; the store is WAL with a 5s busy timeout; and run supervisors hold a per-run exclusive lock, so a second server recovering the same active run exits instead of double-driving it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(app): address review of the PATH and coexistence work Blocker: `launched_as_app_bundle` had grown real logic -- four distinct outcomes turning on a subtle platform fact -- with no coverage, and being macOS-gated it could not get any, since CI runs ubuntu only. The decision is now the pure `is_bundle_exe_launch(exe, argv0)`, compiled everywhere and table-tested for all four cases; only the process-state read stays gated. Same seam `extract_path` uses. The lifecycle lock moves ahead of the PATH probe. Taking it afterwards left the store unprotected for however long the probe ran -- up to 5s -- which is exactly when an `orx delete` racing app startup would land. A failed `read()` is now logged too; it was the one outcome in this module that could pass silently, and silently is how the app would then run unlocked. `orx delete` blocks on a running app now, so its message says so instead of naming three things the user isn't running. Probe diagnostics split the timeout from the spawn failure and name the shell, since "which shell, and did it hang or fail to start" is the whole question a report needs to answer. `bin_version` gets the `NO_COLOR` guard its siblings already carry: it feeds `parse_version`, an escape-laden version line parses as `None`, and `gate_oauth_version` turns that into `Unknown` -- reproducing the bug this branch exists to fix, via the synced env the probe now inherits. `find_opencode` skips empty PATH components, matching `find_on_path`. Packaging asserts the `orx` symlink survived staging. Every step preserves it today, but a dereferencing copy would fail silently -- the app builds, signs, notarizes and runs, and agents just quietly fall back to the user's own CLI. Docs: corrected the same overstatement in `search_path`'s module doc that DISTRIBUTION.md already fixed, and recorded the known gap that the probe imports only PATH, so `ORX_DATA_DIR`/`XDG_*` from a shell rc reach the CLI but not a Finder-launched app. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(app): import the shell's data and config dirs, not just PATH `ORX_DATA_DIR`, `XDG_DATA_HOME`, and `XDG_CONFIG_HOME` exported from a shell rc reached the CLI but never a Finder-launched app, so the two resolved different directories: the dashboard opened the default database while `orx` on the same machine used the user's, and the lifecycle lock added last commit guarded a file neither of them shared. Same root cause as the PATH bug, one layer down. `search_path` generalizes to `shell_env`: an allowlist (`IMPORTED`) the startup probe reads, NUL-separated so a directory can contain anything but NUL, behind `var()` -- process environment when no override is installed, so nothing changes for a terminal `orx`. `store::env_path` and `config::config_dir` are the only two places that resolve these, and both now go through it. The allowlist stays short on purpose: these are the variables whose divergence makes the app and the CLI act like separate installs, while credentials already reach harness children via `prepare_env`. This moves the lifecycle lock back after the probe, undoing last commit's reordering. The reason is now structural rather than incidental: the lock path is derived from `config_dir()`, so taking it before the probe would lock the default path while the CLI locks the user's -- protecting nothing. A correct lock a few hundred milliseconds late beats an immediate lock on the wrong file. Verified with the app's process environment stripped of both variables while the probe shell exported them: `orx.db` lands in the shell's data dir and `orx.lifecycle.lock` in the shell's config dir, and the HOME-derived defaults are never created. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(app): carry the imported environment into orx child processes Importing the shell's directories fixed the app's own resolution but not its children's, which made things worse rather than better for anyone exporting `ORX_DATA_DIR`. `spawn_detached_supervise` and the harness adapters spawn plain CLI processes; those never probe, so they re-resolved to the default store while the app read the user's. A run launched from the app would have been supervised against a different database than the dashboard was showing — before this branch both landed on the default and at least agreed. `shell_env::export_to` hands the imported variables to a child. `prepare_env` applies it, so an agent's `orx exp run` shares the dashboard's store, and `spawn_detached_supervise` applies it plus PATH, which also reaches the run payload it launches (`localbox` spawns `bash run.sh` with an inherited env, so it was losing the user's PATH entirely — no `python`, no `uv`, no `conda`). `opencode::spawn_agent` had hand-rolled a copy of `prepare_env`; it now calls it rather than growing a third copy of the same fix. Verified with the app's process environment stripped of both variables while the probe shell exported them: a harness child is handed ORX_DATA_DIR and XDG_CONFIG_HOME, and an `orx` run with that environment creates no default store. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): print a runnable command in the hints the bundle breaks A DMG user has no `orx` anywhere on PATH, so every hint telling them to run `orx exp wait …` names a command their shell cannot find. Agents are already covered -- `prepare_env` puts the bundle's `orx` first on their PATH -- but a human driving the bundle's CLI is not. `invocation::orx()` resolves the spelling once: plain `orx` when it is on PATH, which is every CLI install and every agent, otherwise this binary's own path, shell-quoted when it needs it. Nothing changes for anyone who installed the CLI. Applied to the three hints the report named, each of which had been copied per backend: the post-launch "Follow it with …" line (nine copies), the missing run-command error (eight), and the outdated-version warning. Both hint bodies move into `invocation`, so the eight backends now share one line each -- a net deletion, and one place to fix the next time the wording moves. `warning_for` takes the spelling as an argument rather than reading process state, keeping its tests deterministic. Not covered: the long tail of `orx login`-style hints in error strings, which still print a literal `orx`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(app): close the environment gaps review found A dashboard-synced `ORX_DATA_DIR`/`XDG_*` silently beat the shell-imported one for harness children: `prepare_env` exported the imported vars, then the synced loop overwrote any whose key was absent from the *process* env -- which in app mode is exactly these. The app read one store while claude and opencode wrote another. The guard now consults `shell_env::var`, so the imported value counts as present. codex escaped this only because it re-pins `ORX_DATA_DIR` after `prepare_env`; claude and opencode have no such pin. Local run payloads were never actually fixed. The previous commit claimed the supervisor passed its environment to `bash run.sh`, but the supervisor does not spawn it -- `localbox::run_job` does, in the launching process, from `LocalJobSpec::env`. A run started from the app still executed the user's script under launchd's PATH, with no python, uv, or conda. The env now carries the imported PATH and directories, and the supervisor comment drops the wrong claim. Three more readers of these same variables were still going to the process env, and two of them made harness detection itself diverge between app and terminal: `harness::xdg_config_home` (whose doc claims to mirror `config::config_dir`) and `opencode_auth_path`, which would report opencode signed out in the app while the CLI saw it signed in. `invocation::resolves_on_path` was the third -- it decides whether a hint can say plain `orx`, and the reader pastes that into the shell whose PATH we imported. Also: `orx login` -- the first hint a fresh DMG user meets -- now resolves like the rest; `export_to` iterates in `IMPORTED` order so the startup log is diffable; and the doc drift is repaired, including the octal-escape invariant that makes the nonce's leading underscore load-bearing, the reopened `orx delete` window, and the scope note listing what still inherits the process environment (`git`, `gh`, `kubectl`, `ssh`, `publish-branch`). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(app): allow dead_code for the launch check off macOS `is_bundle_exe_launch` is deliberately un-gated so its tests run on CI's Linux runner, but its only non-test caller is `#[cfg(target_os = "macos")]`, so the Linux bin target sees it as dead. `mod local` carries a blanket `#[allow(dead_code)]`, which is why `shell_env::parse_probe` -- same shape -- did not trip; `mod commands` does not. Verified by rebuilding with every `target_os = "macos"` in `src/` swapped to `"linux"`, which reproduces exactly what the runner cfgs out. Clean, and no other item on this branch is dead off macOS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
8c17722d88 |
feat(macos): styled drag-to-Applications DMG installer window (#188)
Opening OpenResearch.dmg now shows OpenResearch.app and an /Applications alias to drag it onto, over a branded background — instead of a bare app in the DMG root. - scripts/generate-dmg-background.mjs: pure-Node PNG background (no image deps, mirroring generate-icon.mjs) with the brand mark + a drag arrow, rendered at 1x and 2x and combined into a HiDPI background.tiff. - scripts/package-macos-app.sh: stage app + Applications symlink + background, lay out the Finder window (size, icon positions, background) via AppleScript on a read-write image, then flatten to the compressed DMG. Styling is best-effort: if the Finder step fails (e.g. headless), a functional but unstyled DMG still ships, and the temp/mount cleanup runs regardless. - release-macos-app.yml: bound the 10x-billed macOS job with a timeout. - DISTRIBUTION.md: document the installer window and its constants. Verified locally: styled DMG builds with the app + Applications alias + branded background, 640x400 window; happy-path cleanup leaves no leaked temp dirs or mounts. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
dccc37c4e8 |
feat: downloadable macOS app (OpenResearch.app) + signed release hosting (#180)
* feat: scaffold downloadable macOS app (OpenResearch.app) Adds a native macOS `.app` bundle whose executable IS the `orx` binary. Launched from the bundle (double-click, no args) it enters GUI "app mode": an AppKit NSApplication + delegate run loop on the main thread — Dock icon and "OpenResearch" name from the bundle's Info.plist + .icns, and a Dock-icon click that reopens the dashboard in the browser — while the `orx up` server runs on background tokio worker threads. App mode is entered only when the executable lives in `.app/Contents/MacOS` AND argv is empty, so the bundled binary is still usable as a CLI. - src/commands/app.rs: bundle detection + AppKit delegate + background server - macos/Info.plist: bundle metadata (name, icon, identifier, version) - scripts/generate-icon.mjs: transparent-PNG rasterizer (from favicon.svg) - scripts/build-macos-app.sh: builds release orx, generates .icns, assembles OpenResearch.app into dist/ - objc2/objc2-app-kit gated under cfg(target_os = "macos") so musl Linux is untouched The bundle is unsigned; code-signing + notarization is a follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: sign, notarize, and host OpenResearch.app via GitHub Releases Automates distribution of the macOS app as a signed, notarized DMG attached to each GitHub Release: - scripts/build-macos-app.sh: ORX_APP_UNIVERSAL=1 builds a universal (arm64 + x86_64) binary via lipo for distribution. - scripts/package-macos-app.sh: codesigns (hardened runtime, inside-out), notarizes + staples the .app (so it launches offline once dragged out of the DMG), packages a DMG, then notarizes + staples the DMG. Env-gated: runs unsigned locally, fully signed in CI. - .github/workflows/release-macos-app.yml: on the "Release" workflow completing (workflow_run — a GITHUB_TOKEN-created release: published event can't trigger workflows), a cheap ubuntu job gates on a real dispatched release + all signing secrets + the release existing, then a macOS job builds/signs/notarizes and uploads OpenResearch.dmg to that release. - macos/DISTRIBUTION.md: the one-time Apple setup + the six repo secrets. Inert until the signing secrets are configured, so it is safe to merge before the Apple Developer account exists. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: gate macOS signing behind CODEOWNERS + a required-reviewer environment Hardens the release-signing pipeline for a public repo: - .github/CODEOWNERS: marks the release workflows and macOS signing scripts as owned so they can't change unreviewed (with branch protection's "Require review from Code Owners"). - release-macos-app.yml: the cert-using job now runs in the `release-signing` environment, so adding required reviewers to it pauses signing for human approval — the Developer ID cert is never used by an unreviewed change. - DISTRIBUTION.md: documents creating the environment + branch protection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: add @sox8502 to CODEOWNERS Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * security: environment-scoped signing secrets + SHA-pinned actions Hardens the release-signing pipeline: - The 6 signing secrets move from repo secrets to the `release-signing` environment, so only the reviewed, environment-gated macos-app job can read them — the cert secrets never exist in the cheap ubuntu gate. - The gate now keys on a non-secret repo variable MACOS_SIGNING_ENABLED instead of reading the secrets to detect configuration. - actions/checkout and actions/setup-node are pinned to commit SHAs so a moved tag can't inject code into the job that holds the Developer ID cert. - DISTRIBUTION.md updated: create the environment (required reviewers + main-only deployment branches), add environment secrets, set the variable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: trim DISTRIBUTION.md to repo-specific config Drop the generic Apple-portal walkthrough (enrolment, cert creation, export click-by-click) — Apple documents that. Keep only what's specific to this repo: the environment/secrets/variable, the local build+sign commands, and the download URL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
417828221b | Add isolated dev slot helper (#166) |