Problem
The DMG produced by build-macos-app.sh uses a shell script as CFBundleExecutable and bakes in the source checkout's virtual environment. When the checkout is under a protected macOS folder such as ~/Documents, TCC attributes access to sh instead of Odysseus. Python then fails before startup while reading venv/pyvenv.cfg with Operation not permitted, and the app cannot present a correctly attributed permission prompt.
The launcher also has no persistent menu-bar presence, so users cannot tell when its local Uvicorn process is running or stop it cleanly from the app UI.
Proposed fix
- Add protected-folder usage descriptions to the generated bundle.
- Compile a small native AppKit launcher so macOS associates access with
com.odysseus.launcher.
- Keep the existing shell launcher in bundle resources and supervise it with
NSTask.
- Add a menu-bar status item with an
Exit Odysseus action that terminates the shell launcher and server.
- Preflight
pyvenv.cfg access and show actionable recovery instructions.
- Add regression coverage for generated bundle metadata and launcher behavior.
Validation
Tested on Apple Silicon macOS by building and installing the DMG, resetting the Documents-folder TCC decision, launching the installed app, loading Odysseus at 127.0.0.1:7860, and verifying the native launcher, shell child, and Uvicorn listener remain active.
Problem
The DMG produced by
build-macos-app.shuses a shell script asCFBundleExecutableand bakes in the source checkout's virtual environment. When the checkout is under a protected macOS folder such as~/Documents, TCC attributes access toshinstead of Odysseus. Python then fails before startup while readingvenv/pyvenv.cfgwithOperation not permitted, and the app cannot present a correctly attributed permission prompt.The launcher also has no persistent menu-bar presence, so users cannot tell when its local Uvicorn process is running or stop it cleanly from the app UI.
Proposed fix
com.odysseus.launcher.NSTask.Exit Odysseusaction that terminates the shell launcher and server.pyvenv.cfgaccess and show actionable recovery instructions.Validation
Tested on Apple Silicon macOS by building and installing the DMG, resetting the Documents-folder TCC decision, launching the installed app, loading Odysseus at
127.0.0.1:7860, and verifying the native launcher, shell child, and Uvicorn listener remain active.