Skip to content

Code: a repository's GitHub Commands, Production Review and Runner go under More settings, and links land on them - #5218

Merged
simlarsen merged 11 commits into
masterfrom
claude/code-repo-settings-more
Oct 23, 2026
Merged

simlarsen merged 11 commits into
masterfrom
claude/code-repo-settings-more

Conversation

@simlarsen

@simlarsen simlarsen commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

The ask

From the maintainer's task doc (block 69), with a screenshot of a repository's Settings page in Code:

GitHub commands and runner should be inside of more settings as well.

The page showed Repository Details, then a GitHub Commands card (the "Respond to GitHub Commands" switch), then a Runner card with Edit, then a folded More settings whose chips read "Pull Requests" and "GitHub Trigger Label". Since then #5172 added a Production Review switch card on top as well.

What changed

Code > a repository > Settings now shows the repository itself on top - Repository Details alone - and folds every other setting under More settings, in the order the page had them:

  1. GitHub Commands (the switch, still saved the moment it is flipped)
  2. Production Review (the switch, same)
  3. Runner (still Edit, the same one-field dialog)
  4. Pull Requests, GitHub Trigger Label, Production Review Comment - as before
  5. Build and Test Commands - only where an operator set them, as before

Folded, More settings names the first four - GitHub Commands · Production Review · Runner · Pull Requests · 2 more - and says what is set to something other than its default, as every More settings does: GitHub Commands: Off, Production Review: Off, Runner: prod-eu-west-1 (with "· Disconnected" when that Runner is not connected, "A Runner you do not have access to" for one the reader is not shown, and Runner: None where there is no global Runner to fall back on). Open, it says what it holds: "GitHub commands, production reviews, where AI works, and where its pull requests open." (translated in all 16 languages; the old description, now unused, is removed from all 17 locale files).

Links land on the setting, with More settings open. Folding the Runner would have sent "Pick a Runner" to a folded card, so a link can now name a setting after the page's # and the fold opens by itself there, with that card brought into view right under the sticky header, tinted for a moment and holding the keyboard's focus (see UI review):

  • "Pick a Runner" (the blockers NoAgent, RunnerNotOnline, GlobalRunnersOff) and the slow-queue line in a task's conversation open …/settings#runner;
  • a Runner's page links each repository that picks it to …/settings#runner;
  • Production Reviews' "Turn on in Settings" / "Change in Settings" opens …/settings#production-review;
  • the GitHub App's reply when commands are switched off now says "Code → this repository → Settings → More settings".

Decisions

  • Production Review goes under More settings too. The brief asked to decide "with the same rule": a switch whose default works for most repositories (GitHub Commands' is on; Production Review's is on for every repository connected since Code: a production review of every pull request - what production says about the code it changes, one switch, safe for public repositories and outside contributors #5172) is folded. Keeping it alone on top would have left the page Details + one switch + the fold. People still find it: the Production Reviews page (its own side-menu entry) says whether reviews are on and links straight to the switch, and the folded header says "Production Review: Off" on a repository where it is off (every repository connected before Code: a production review of every pull request - what production says about the code it changes, one switch, safe for public repositories and outside contributors #5172).
  • Order in the fold: what was on top comes first, in the order it had (GitHub Commands, Production Review, Runner), then what was already folded, in its order. This keeps the three moved settings among the four names the folded header shows (it names four and counts the rest), and people who knew the page find them in the same order. Grouping the trigger label next to GitHub Commands would have pushed the Runner into "2 more".
  • Shared, not Code-only: a page's More settings opens by itself at a card its address names. AdvancedPageSection reads the # of the address (Common/UI/Utils/PageAnchor): when it names one of its items' keys it is open from the first paint (never drawn folded first) and brings the card whose id is that key into view - or the section itself for a card with no id. Folded by hand, it stays folded. Card takes an id (with a scroll margin under the sticky header, --app-header-height), ModelSwitchCard a cardId. The place is kept in view while the page settles (cards above it load and grow) for up to 3 seconds, and the person scrolling, clicking, touching or typing ends that at once. Only plain names ([A-Za-z][A-Za-z0-9_-]*) are read from the address, so nothing from it reaches a selector unescaped. Every other page's More settings is unchanged until it gives its cards ids.
  • One read of the Runner choices. The page reads them once for the Runner card's value and for the folded chip (CodeRepositoryRunnerValueView); CodeRepositoryRunnerValue still reads its own where used alone.

What changes for existing customers

  • The GitHub Commands, Production Review and Runner settings of every repository move from the top of its Settings page into More settings. Nothing about what they do, their values or who may change them changes, and no data changes (no migration).
  • Links into a repository's settings from Code (Pick a Runner, the slow-queue line), a Runner's page and Production Reviews now open the page at the setting, with More settings open.
  • The GitHub App's comment for switched-off commands names More settings.

Docs (17 languages)

  • ai/ai-agent: turning on Review Pull Requests Against Production is "under More settings"; picking the repository's Runner (both places) is "open More settings, click Edit on the Runner card".
  • ai/github-app: Respond to GitHub Commands is "under More settings on the repository's Settings page".
  • Each translation names More settings as its Dashboard draws it. AiDocsFacts now also holds the pages to the product: the Runner card, both switches and the trigger label's card are inside AdvancedPageSection in Settings.tsx.

Tests

  • Common/Tests/UI/Utils/PageAnchor.test.ts (new): plain names only; #%72unner reads as runner, anything else names no place; a link puts #place after the query and never adds a second #; the place is scrolled to on the next frame (block: start), again when the page changes size (once a frame), never after the settle time, any of wheel/touchstart/mousedown/keydown, stop() (listeners, observer and timer all gone), or once the element is gone; falls back to a timeout without requestAnimationFrame and to a single scroll without ResizeObserver.
  • AdvancedPageSection.test.tsx: opened at an item's key it is open from the first paint and scrolls to that card (with its scroll margin); a card with no id scrolls the section; an id elsewhere on the page is not used; an address naming nothing, or a title-keyed item, stays folded with no style; an item that arrives later opens it then; a same-page hash change opens it on the next draw; folded by hand stays folded; unmounting before the frame scrolls nothing; getAnchoredItemKey matches keys exactly.
  • Card.test.tsx / ModelSwitchCard.test.tsx: an id lands on the card (page and section surfaces) with the header scroll margin; no id draws exactly as before.
  • CodeRepositorySettingsPage.test.tsx (rewritten around the new layout): Repository Details is the only card above the fold; the six cards are inside it in order, with ids equal to the fold's item keys and CodeRepositorySetting; folded names and "2 more"; the switches flip and save from inside the fold; chips for GitHub Commands/Production Review off; the Runner chip for a global Runner, a connected/disconnected/hidden project Runner and "None" (global Runners off, no global Runner); opening at #runner, #production-review, #github-commands and #commands (which appears after the read); an address naming nothing leaves it folded; folded by hand stays folded; a read-only member sees locked switches and the fold opens for them at #runner; the copy's order, set rules and description length.
  • CodeRepositoryRunnerPicker.test.tsx: the value drawn from the page's choices reads nothing itself and says exactly what the self-reading value says.
  • Links: CodeConversationParts, RunnerNavigation (Pick a Runner → #runner), CodePages (slow queue → #runner), CodeRepositorySettingsRunner (a Runner's repositories → #runner), CodeProductionReview (→ #production-review), CodeProduct (getRepositorySettingsRoute with every setting; the side menu still marks Settings at …/settings#runner), CodeTaskCopy (only repository-settings fixes name a setting).
  • App/Tests/Dashboard/CodeProductWiring: the GitHub reply names More settings. AiDocsFacts: the new sentences and the "under More settings" facts.
  • Offline browser suite packages/E2E/Code/Code.spec.ts (desktop 1280 and phone 390): the structure (details on top, folded names, nothing folded in sight, the six section titles in order once open), a flip from inside the fold and the "GitHub Commands: Off" chip, landing at #github-commands (in viewport) and #runner (Pick a Runner: URL, fold open, Runner card and its Edit in viewport), Production Reviews' link landing on the switch, the Runner chip for global/prod/hidden/None, a read-only member (locked switches, four locked Edits, nothing saved), dark mode folded and open, German. The Runner tests now open at #runner as Pick a Runner does.

A mutation check: making AdvancedPageSection ignore the address fails 12 tests across the two jsdom suites.

Ran locally

After the last merge of master (b717bc0):

  • Type-checks: tsc --noEmit in Common, the Dashboard, App (with its tests) and E2E, and Common's npm run compile-tests - all exit 0; --listFiles shows no file from the repo-root Scripts/ or another package in any of them.
  • Common jest: the 14 new/changed suites, every suite that reads a changed file (switch cards, Code pages, GitHub command and webhook handling, CodeTaskAPI, PageSearchIndexCovers*, the Locale suites) - 76 suites, 2,865 tests; every Guard suite plus UpdateChecksReadHeldRows, DeleteChecksReadHeldRows, HookWritesCallersMayMake, ListOrderColumnModels, PermissionCatalogueCoverage and SchemaMigrationsOnlineDdl - 168 suites, 5,452 tests. All pass.
  • App jest: its root-level tests, every Guard and Locale suite, the Dashboard wiring suites that read the changed files (CardDescriptionsSayWhatFor, CodeDarkMode, CodeProductWiring, the switch-card and More settings suites), AdminDashboard, NormalizeListOrder, the general docs suites (Tests/FeatureSet/Docs/Docs*) and every docs suite that names ai/ai-agent or ai/github-app - 172 suites, 9,377 tests. All pass. (Before the merge also the remaining docs suites that name the two pages: 49 + 14 suites.)
  • With ee/ hidden: the new and changed Common and App suites (17 suites) pass.
  • npm run i18n:check (no translation lost), npm run i18n:validate, npm run docs:check-anchors, docs:localize-anchors for both pages (0 to localize).
  • Offline Code suite (npm run test-code-ui, Chromium at 1280 and 390): all 169 pass (25 skipped as before) in 8.8 minutes on this loaded machine; the settings, Runner and review tests again after the merge (60 passed). CI time: the five new tests add about 19 seconds locally (three run at the laptop's width only), so group 9 goes from about 21.5 to about 21.9 minutes.
  • Prettier and ESLint clean on every changed file; the branch ReDoS checker finds one new pattern (the plain anchor name), linear.
  • Visual check through the offline fixture at 1280 and 390, light and dark, German, a read-only member, and landing at #runner / #production-review (scratch screenshots, not attached).

Not run: the full Common and App jest suites (CI runs them on master), a live stack (no backend change beyond one reply string).

No failure seen on master.

Not done / left alone

  • ai/ai-sre still calls the cap "Max Open Fix Pull Requests (on the repository's Settings page)": it was already folded before this change (and is now "AI Fix Pull Requests" with a choice), a separate wording fix for that page.
  • Other pages' More settings cards have no ids yet, so links cannot land on them; adding an id to a card (and its item key) is all a page needs.

UI review

What I looked at. The real pages through the offline Code fixture in Chromium with Inter, with a 64px sticky header added the way MasterPage draws one (the fixture draws none): a repository's Settings folded and open at 1280 and 390, light and dark, in English, German and Japanese; the folded chips for GitHub Commands and Production Review off and for each Runner case (a Runner of the project's own, one the reader is not shown, None); a read-only member; a repository with build and test commands; landing at #runner, #production-review and #github-commands, after a mouse click and after Enter on the link, on a 900px and a 1500px-tall window; Pick a Runner from the blocker notice; Production Reviews' Turn on in Settings; the slow-queue line; the two docs pages; and the GitHub App's switched-off reply as it reads on GitHub.

What I changed, and why.

  1. A setting inside More settings now lands flush under the sticky header. It landed 1.5rem below the header, as a card of its own does - but a setting in More settings is a section of one card, so that gap showed a cut-off strip of the setting above it (half a line of the switch's description) between the header and the divider. A card drawn as a section now lands with its divider right under the header and its own padding as the room above its title (PAGE_ANCHOR_SECTION_SCROLL_MARGIN_TOP); a card of its own keeps the page's gap.
  2. The setting a link lands on is marked, and takes the keyboard's focus (markPageAnchorLanded in Common/UI/Utils/PageAnchor, called by AdvancedPageSection for the card it lands on). On a tall screen the page cannot scroll a setting near its end to the top (at 1280x1500 the Runner lands mid-window among five others), so the one the link was for is tinted in the product's indigo for 2.4 s and the tint fades (light and dark; held still, without the fade, for a reader who asks for less motion). And the page used to leave the focus at its top: after Enter on Pick a Runner, Tab walked the side menu, Edit Details, the fold's header and two switches before reaching the Runner's Edit. Now the landed card holds the focus (tabindex -1 only while it does), so Tab goes straight to its Edit or switch and a screen reader reads where it landed; focus a field already holds is never taken. After a keyboard landing the card shows an inset indigo ring (as a row's focus ring is drawn, inside the edge so the card's rounded clip does not cut it); after a mouse click the browser draws none. No focus ring is silenced anywhere (ChartFocusRing's guard holds that).
  3. More settings' description, open, says what it holds plainly. "GitHub commands and production reviews, the Runner AI works on, and where AI's pull requests open." read "Runner AI" as one name. It is now "GitHub commands, production reviews, where AI works, and where its pull requests open." - in the words its cards use ("Where AI works in this repository.", "Where AI's pull requests open") - in all 17 languages (the key renamed in place, so no translation is lost: i18n:check, i18n:validate).

Left as is, on purpose.

  • The chip for a Runner the reader is not shown reads "Runner: A Runner you do not have access to" - the Runner picker's own words for it, kept the same everywhere.
  • Card descriptions are hidden below md on every card in the product (Card's default header); the cards in More settings follow that.
  • The GitHub App's switched-off reply names "Code → this repository → Settings → More settings". It could link straight to the switch now that links can land on it (.../settings#github-commands); left as a follow-up, since it means building a Dashboard address on the server and pinning it to the Dashboard's route.

Tests added or changed in the review.

  • Common/Tests/UI/Utils/PageAnchor.test.ts: a section lands with the header's height alone; marked at once and for 2.4 s exactly (or as told), unmarked at once by whoever asked with no timer left; focus taken without scrolling only when nothing holds it, given back with the tabindex when it moves on, a place's own tabindex kept, a place that cannot take focus keeps nothing it was given.
  • Common/Tests/UI/Components/AdvancedPageSection.test.tsx: the landed card is the one marked, holds the focus, and Tab reaches its own button; a focused field keeps the focus; a card with no id marks nothing; a link landing elsewhere moves the mark, and unmounting removes it; a section card's margin is the header's height.
  • Common/Tests/UI/Components/Card.test.tsx: a card lands with the page's gap, a section with its divider under the header.
  • Common/Tests/UI/Styles/PageAnchorLandedTheme.test.ts (new): the tint in each theme, the fade over exactly the mark's time, motion only for no-preference, a still tint for reduce, the keyboard ring (inset, each theme's indigo), no ring silenced, and the rules ahead of the spinner arcs that stay last.
  • Common/Tests/App/Dashboard/CodeRepositorySettingsPage.test.tsx: at #github-commands the switch card is marked and focused and Tab reaches the switch; at #runner the Runner card; the new description (and never "Runner AI").
  • packages/E2E/Code/Code.spec.ts: Pick a Runner lands with the Runner card as high as the page lets it go, the only card marked, holding the focus, and Tab reaches its Edit - at 1280 and 390; the description in English and German.
  • A mutation check: dropping the mark, the section margin, the focus, the focus guard, the tabindex clean-up, the unmark or the reduced-motion rule each fails 2 to 6 tests.

Ran in the review, after merging master (f642aa3): Common tsc --noEmit and npm run compile-tests, the Dashboard, App and E2E tsc --noEmit - all exit 0, and none pulls in a file from Scripts/ or another package; Common jest - every Guard suite plus UpdateChecksReadHeldRows, DeleteChecksReadHeldRows, HookWritesCallersMayMake, ListOrderColumnModels, PermissionCatalogueCoverage and SchemaMigrationsOnlineDdl, and every suite that reads a changed file (Theme.css's readers with the DarkMode suites, Card, folds, switch cards, the Locale and Code suites): 307 suites, 11,066 tests; App jest - its root-level tests, every Guard, Locale and DarkMode suite, CodeProductWiring, AiDocsFacts, CardDescriptionBoilerplateGuard, ShortDescriptionsGuard and the AdminDashboard suites: 169 suites, 5,053 tests; the changed suites again with ee/ hidden; i18n:check, i18n:validate; the offline Code suite's settings, Runner and production review tests at 1280 and 390 (56 passed), after the whole suite passed before the merge (166 passed, 28 skipped as before, 8.3 min - the review adds about a second to group 9); Prettier and ESLint on every file the branch changes; the branch ReDoS checker (nothing new that is not linear). All pass. Not run: the full Common and App suites, a live stack. No failure seen on master.

🤖 Generated with Claude Code

valeriamustafaeva and others added 7 commits October 23, 2026 18:44
…ner go under More settings

The maintainer: GitHub commands and runner should be inside of more
settings as well. A repository's Settings page now shows Repository
Details on top and folds every other setting under More settings, in the
order the page had them: GitHub Commands, Production Review, Runner,
Pull Requests, GitHub Trigger Label, Production Review Comment (and
Build and Test Commands where an operator set them). The folded header
names them and says what is set: GitHub Commands: Off, Production
Review: Off, Runner: <name>.

A link that names a setting after the page's # lands on it with More
settings open (Common/UI/Utils/PageAnchor, AdvancedPageSection opens at
an item its address names, Card gets an id): Pick a Runner and the slow
queue line open #runner, a Runner's repositories link #runner, Production
Reviews' Settings link #production-review. The GitHub App's reply for
switched-off commands names More settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… setting, and the shared anchor

- CodeRepositorySettingsPage: Repository Details alone on top, the six
  cards in the fold in order with their ids, the folded names and chips
  (GitHub Commands: Off, Production Review: Off, Runner by name, status,
  hidden or None), opening at #runner, #production-review, #github-commands
  and #commands, staying folded when folded by hand, a read-only member.
- PageAnchor: plain names, links with a #, bringing a place into view on
  the next frame and while the page settles, stopping on the person's
  input, on stop() and after the settle time.
- AdvancedPageSection, Card and ModelSwitchCard: opening at an item the
  address names, a card's id and scroll margin, a switch card's id.
- Links: Pick a Runner, the slow queue line and a Runner's repositories
  land on #runner; Production Reviews on #production-review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ore settings, in 17 languages; offline suite follows

- ai/ai-agent: turning on Review Pull Requests Against Production and
  picking the repository's Runner (both places) go through More settings;
  ai/github-app: Respond to GitHub Commands is under More settings. Every
  translation names More settings as its Dashboard draws it.
- AiDocsFacts pins the new sentences and holds them to Settings.tsx: the
  Runner card, both switches and the trigger label's card are inside
  AdvancedPageSection; the GitHub App's reply names More settings.
- Offline Code suite: the page's structure (details on top, folded names,
  sections in order), flips from inside the fold, landing at
  #github-commands, #runner and #production-review, the Runner chip, a
  read-only member, dark mode and German; the Runner tests open at #runner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idth only

The read-only member, dark mode and folded Runner checks do not depend on
the screen's width; the Runner chip check keeps the two cases the jsdom
suite cannot show in a browser. About 19 seconds added to the offline
Code suite in all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	packages/App/FeatureSet/Dashboard/src/Locales/da.json
#	packages/App/FeatureSet/Dashboard/src/Locales/de.json
#	packages/App/FeatureSet/Dashboard/src/Locales/en.json
#	packages/App/FeatureSet/Dashboard/src/Locales/es.json
#	packages/App/FeatureSet/Dashboard/src/Locales/fa.json
#	packages/App/FeatureSet/Dashboard/src/Locales/fr.json
#	packages/App/FeatureSet/Dashboard/src/Locales/hi.json
#	packages/App/FeatureSet/Dashboard/src/Locales/it.json
#	packages/App/FeatureSet/Dashboard/src/Locales/ja.json
#	packages/App/FeatureSet/Dashboard/src/Locales/ko.json
#	packages/App/FeatureSet/Dashboard/src/Locales/nl.json
#	packages/App/FeatureSet/Dashboard/src/Locales/no.json
#	packages/App/FeatureSet/Dashboard/src/Locales/pt.json
#	packages/App/FeatureSet/Dashboard/src/Locales/ru.json
#	packages/App/FeatureSet/Dashboard/src/Locales/sv.json
#	packages/App/FeatureSet/Dashboard/src/Locales/zh-CN.json
#	packages/App/FeatureSet/Dashboard/src/Locales/zh-TW.json
…ESLint write them

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@simlarsen

simlarsen commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

valeriamustafaeva and others added 4 commits October 23, 2026 20:31
… and focused; More settings says what it holds plainly

UI review of the repository settings page and the links that land on it:

- A setting inside More settings landed 1.5rem below the sticky header, so
  a cut-off strip of the setting above it showed between the header and
  its divider. A card drawn as a section of a card now lands with its
  divider right under the header (PAGE_ANCHOR_SECTION_SCROLL_MARGIN_TOP);
  a card of its own keeps the page's gap.
- The setting a link lands on is tinted for a moment, the tint fading
  (Theme.css, held still for reduced motion), and takes the keyboard's
  focus when nothing holds it (markPageAnchorLanded), so on a tall screen
  the eye still finds it and Tab goes on to its Edit or switch, not to the
  top of the page. Focus a field already holds is never taken.
- More settings' description read "the Runner AI works on" as one name;
  it is now "GitHub commands, production reviews, where AI works, and
  where its pull requests open." in the words its cards use, in all 17
  languages.

Tests: PageAnchor, AdvancedPageSection, Card, the settings page and a new
PageAnchorLandedTheme suite; the offline Pick a Runner test checks the
landing height, the mark, the focus and Tab reaching Edit at 1280 and 390.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s, never silenced

The first round hid the focus ring of the card a link lands on, and
ChartFocusRing's guard rightly refused it: only charts may silence their
ring. The landed card now draws no ring after a mouse click (the browser
draws none for programmatic focus then) and, after a link followed with
the keyboard, an inset indigo ring - inside its edge, as a row's focus
ring is, so the More settings card's rounded clip does not cut it - in
each theme's indigo.

PageAnchorLandedTheme pins the ring and that no ring is silenced; the
AdvancedPageSection test's card button carries its icon, as
CardButtonSchema asks; the offline suite's README says how Pick a Runner
lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Theme.css writes every colour with an alpha as rgb(r g b / a%); the two
tints of a setting a link lands on now do too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@simlarsen
simlarsen merged commit f223983 into master Oct 23, 2026
3 of 43 checks passed
@simlarsen
simlarsen deleted the claude/code-repo-settings-more branch October 23, 2026 21:16
@simlarsen simlarsen mentioned this pull request Oct 23, 2026
simlarsen pushed a commit that referenced this pull request Oct 24, 2026
…unner setting

#5218 put everything but Repository Details under More settings on a
Code repository's Settings page, and made the links that lead to a
setting land on it: a Runner's Code Repositories row now links to
settings#runner, which opens the fold on the Runner card. The Code
suite's checks were updated with it; the GlobalRunners browser suite,
which reads the same row from the Runner's side, still expected the bare
/settings address, and failed Dashboard Offline UI (6) on the 14.0.88
release gate. It now expects the #runner address. Test only.

The GlobalRunners suite passes in Chromium (48).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant