* feat(dashboard): restructure Open SWE Review tab + wire create_prs
Restructures the dashboard around two related changes the reviewer settings
have been asking for:
- Wire profile.create_prs. Defaults to true (opt-out); when off the system
prompt gets a `Pull Request Policy Override` section telling the agent
to push the branch and notify with the branch URL instead of opening a
PR. Removes the noop Slack Notifications / Allow Artifacts / First Name
/ Last Name controls and their schema fields.
- Repositories opt-in for Open SWE Review. New per-team enabled list
stored in the LangGraph Store (`["enabled_review_repos"]`). Every
reviewer webhook chokepoint now goes through `_is_repo_enabled_for_review`
which AND-combines the existing env allowlist with the dashboard list.
Default is empty (opt-in) — admins enable repos per-installation from
the new Repositories page nested under Open SWE Review.
- Open SWE Review tab now mirrors the Cursor "rules" pattern: main page
shows installation rows + a Rules entry; both drill into nested pages
(/review/repositories/$owner and /review/styles) with a back link.
- Adds the new logo/favicon assets shipped from sidebar + html head.
Tests pass with a new autouse fixture (`tests/conftest.py`) that defaults
`is_review_repo_enabled` to True for existing allowlist tests.
* fix(dashboard): make main content scroll independently of the sidebar
Outer flex container was min-h-svh, so it grew with main's content and the
whole page scrolled — sidebar moved with it. Pin to h-svh + overflow-hidden
so the sidebar stays put and only <main> scrolls.
* fix(dashboard): make disabled repo toggles obviously disabled
Switch's disabled state used opacity-50 against a muted background, so
the not-admin state looked nearly identical to the off state. Bump to
opacity-40 + grayscale, and wrap each repo toggle in a span carrying a
native hover tooltip explaining why it's disabled.
* fix(switch): handle base-ui's data-disabled state
base-ui's Switch.Root sets data-disabled (not the HTML disabled attribute)
when disabled, so Tailwind's disabled: variant never matches and the
button keeps its cursor-pointer + clickable look. Mirror the styling
under the data-[disabled] variant and add pointer-events-none so the
disabled state is both visible and actually unclickable.
* feat(dashboard): paginate per-installation repository list
20 repos per page with Prev / page X of Y / Next controls at the bottom.
Pager only renders when there are more than 20 repos. Page resets to 0
when navigating between installations.
* feat(dashboard): global default model selectors for Agent + Reviewer
Adds team-wide default model + reasoning effort for both agents in the
Admin tab so operators can switch models without redeploying.
Resolution chain:
Agent: hardcoded -> LLM_MODEL_ID env -> team default -> user profile
Reviewer: hardcoded -> LLM_MODEL_ID env -> team default -> per-call configurable
Team defaults live in team_settings and are validated against the
SUPPORTED_MODELS allowlist + the model's supported reasoning efforts.
'Inherit from env' clears the override and falls back to LLM_MODEL_ID.
* refactor(models): drop LLM_MODEL_ID env in favour of the team default
The team default is now the single source of truth for the runtime model
choice; per-user (agent) and per-call configurable (reviewer) selections
still win on top. When no admin has touched the team default, it surfaces
the hardcoded fallback (DEFAULT_MODEL_ID + its default effort), so the
admin UI's dropdown is always pre-populated with a sensible value.
The Admin UI loses the 'Inherit from env' option since there is no longer
an env layer to inherit from.
* chore(models): set hardcoded fallback to gpt-5.5 medium
Decouple the team-default boot value (gpt-5.5 / medium) from each model's
ProfileForm-suggested default_effort so we can change one without nudging
the other. The Opus xhigh default for new user profiles is unchanged.
* feat(dashboard): trigger-mode copy, Coming Soon badges, logout in My Settings
- Rename trigger mode 'ready_for_review' -> 'once_per_pr' with new
description copy that matches the screenshot. Legacy stored values
fall back to 'every_push' on read so the UI never shows an unknown
selection.
- Add a 'Coming soon' badge + greyed-out + disabled state on the
controls that don't have runtime consumers yet: Trigger Mode,
Autofix Mode, Autofix Severity Threshold, and Automatically fix CI
failures. SettingsRow grew a comingSoon prop to keep this consistent.
- My Settings drops the noop PR Preferences section and adds a Sign
Out button. preferred_pr_destination is removed from the profile
schema; old records get the field popped on next write.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>