bug(browser): forward preferredContextId through health and readiness routing
- Dominant language
- JavaScript
- Stars
- 29.3k
- Forks
- 2.9k
- Avg merge
- 15h 36m
- Merged PRs (30d)
- 70
Description
### Summary
#2073 introduced `preferredContextId` so a persisted default is a soft preference rather than a strict requirement. Command dispatch forwards it, but the health/status/readiness paths still drop it. This makes the configured default ineffective before command dispatch and can make `opencli doctor` or browser startup return `profile_required` whenever two Browser Bridge profiles are connected.
### Reproduction
1. Connect two Browser Bridge profiles.
2. Run `opencli profile use ` so `~/.opencli/browser-profiles.json` has that `defaultContextId`.
3. Run `opencli doctor` (or a browser command that reaches `ensureBrowserBridgeReady()`) without `--profile`.
### Actual
The status/health request contains neither `preferredContextId` nor the persisted default. `/status` resolves with no selection and returns `profile_required`; `doctor` reports that no default is selected even though one is configured.
### Expected
The persisted default should remain a soft `preferredContextId` through health, readiness polling, `/status`, and doctor. With the preferred profile connected it should be selected; if stale, retain #2073 behavior: fall back only when one live profile exists, otherwise require an explicit choice.
### Evidence
- [`profileRouteParams`](https://github.com/jackwener/OpenCLI/blob/5256711a25458e537c5a63d2a6f9c7fd36d0d1eb/src/browser/profile.ts#L70-L90) correctly distinguishes explicit `contextId` from soft `preferredContextId`.
- [`BrowserBridge.connect()`](https://github.com/jackwener/OpenCLI/blob/5256711a25458e537c5a63d2a6f9c7fd36d0d1eb/src/browser/bridge.ts#L28-L46) drops `routing.preferredContextId` when calling `_ensureDaemon`.
- [`fetchDaemonStatus` / `getDaemonHealth`](https://github.com/jackwener/OpenCLI/blob/5256711a25458e537c5a63d2a6f9c7fd36d0d1eb/src/browser/daemon-transport.ts#L69-L87) accept only `contextId`.
- [`waitForBridgeReady`](https://github.com/jackwener/OpenCLI/blob/5256711a25458e537c5a63d2a6f9c7fd36d0d1eb/src/browser/bridge-readiness.ts#L5-L23) and [`ensureBrowserBridgeReady`](https://github.com/jackwener/OpenCLI/blob/5256711a25458e537c5a63d2a6f9c7fd36d0d1eb/src/browser/daemon-lifecycle.ts#L96-L104) forward only `contextId`.
- [`/status`](https://github.com/jackwener/OpenCLI/blob/5256711a25458e537c5a63d2a6f9c7fd36d0d1eb/src/daemon.ts#L262-L286) parses only `contextId`, while `/command` already carries both route fields.
- [`runBrowserDoctor()`](https://github.com/jackwener/OpenCLI/blob/5256711a25458e537c5a63d2a6f9c7fd36d0d1eb/src/doctor.ts#L109-L115) calls bare `getDaemonHealth()`.
### Relation to existing work
This is not #1575 (formatter wording) and not the stale-default arbitration addressed by #2073 / #2081. It is the remaining pre-dispatch health/status propagation gap.
I reproduced this with two connected profiles and a persisted default; forwarding the soft preference end-to-end fixes the health probe while preserving the strict-vs-preferred semantics added in #2073.
Contributor guide
Research direction
Start with profileRouteParams in src/browser/profile.ts, then trace routing through src/browser/bridge.ts, daemon-transport.ts, bridge-readiness.ts, daemon-lifecycle.ts, src/daemon.ts, and src/doctor.ts. Verify that preferredContextId reaches health, readiness, /status, and doctor while preserving the strict contextId versus soft-preference behavior described in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100