Three changes from the pre-merge Opus review:
**MUST-FIX** — XPC_SERVICE_NAME false-positive on macOS Terminal
macOS launchd sets `XPC_SERVICE_NAME` in EVERY Terminal-spawned shell, not
just real services. Typical noise values: `"0"` (truthy in Python!) and
`"application.com.apple.Terminal.<UUID>"`. A bare `os.environ.get(name)`
existence check would auto-promote interactive `./start.sh` runs to
foreground mode on every Mac dev machine — silently breaking the most
common installation path (no /health probe, no browser open, no log file,
hanging shell).
Fix: new `_is_real_supervisor_value()` helper that filters noise. For
`XPC_SERVICE_NAME` specifically, reject `"0"` and any `"application.*"`
prefix. Real launchd plists use reverse-DNS Label form (`com.<rdns>.<svc>`)
which still triggers correctly.
7 new tests in `TestXPCServiceNameNoiseFilter`:
- 4 noise values (`0`, Terminal.app, iTerm2, VSCode) → no detection
- 3 real Label forms → correct detection
- Mixed env with XPC noise + real INVOCATION_ID → falls through to systemd
**SHOULD-FIX 1** — Test env leakage
The original `clean_env` fixture stripped supervisor-detection env vars
but not the resolved bootstrap vars (HERMES_WEBUI_HOST/PORT/AGENT_DIR)
that `main()` mutates onto `os.environ`. After
`test_foreground_exports_resolved_env_vars` ran, later tests would import
bootstrap with polluted defaults (DEFAULT_HOST="0.0.0.0" instead of
"127.0.0.1"). Existing assertions still passed (tautological vs DEFAULT_*),
but it was a footgun for future tests.
Fix: extend `clean_env` to also `delenv` the three resolved vars before
each test.
**SHOULD-FIX 2** — Pre-execv executability guard
If `discover_launcher_python` returns a path that doesn't exist or isn't
executable, `os.execv` raises OSError → wrapper catches → SystemExit(1)
→ supervisor restarts → loop forever. That's exactly the failure mode
this PR is supposed to eliminate.
Fix: `os.access(python_exe, os.X_OK)` check before execv. Converts
infinite supervisor loop into a single visible RuntimeError.
1 new test in `TestForegroundExecutabilityGuard` pinning that the guard
fires before execv when the python path is non-executable.
**Docs** — supervisor.md updates
- New section explaining the XPC_SERVICE_NAME noise filter and what
values trigger / don't trigger detection
- New section listing supervisors that are NOT auto-detected (runit,
daemontools, PM2, Foreman/Honcho, custom shell-script supervisors)
with explicit recommendation to set HERMES_WEBUI_FOREGROUND=1
Verification
- 3820 tests pass (+9 from this commit's new tests vs the original PR
push of 3811)
- Filter manually verified end-to-end with the live os.environ:
XPC=0 → None, XPC=application.* → None, XPC=com.example.foo → triggers
- run-browser-tests.sh ALL CHECKS PASSED on the worktree
Items deferred from the Opus review
- #4 chdir target may not exist: REPO_ROOT comes from __file__.resolve()
so it's stable; not a real concern in practice
- #6 two startup messages in foreground mode: cosmetic, useful for
diagnostics
- #7 stricter explicit-only mode: leaves user the override of just not
passing --foreground (current behavior)
- #8 test stub return value: trivial, can fix later if regression surface
- #9 argparse positional-after-option ordering: test reads fine
These can be follow-up issues if anyone hits them.