Skip to content

fix(mobile): tell organization members that only admins can reconnect GitLab on PR review - #9347

Open
iscekic wants to merge 7 commits into
mainfrom
drain/pr-review-org-reconnect-role
Open

iscekic wants to merge 7 commits into
mainfrom
drain/pr-review-org-reconnect-role

Conversation

@iscekic

@iscekic iscekic commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence

Evidence: demonstrated — seeded a local organization with a suspended GitLab integration and a fake member account, ran the app on the Android emulator against the local stack, compared the PR-review gate for a plain member and an owner, and measured the account switcher's placement and the dark tile's contrast in the captured pixels, at head 492c4a2.

What changed

apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx offered the integration-page action in the organization scope to every role. The web page that action opens is narrower than the gate assumed:

  • every organization Bitbucket connect requires ORGANIZATION_BILLING_ROLES (organizations.bitbucket.connect, and the Bitbucket OAuth connect route);
  • an organization GitLab re-authorization requires ORGANIZATION_BILLING_ROLES, because the connect route only keeps member-level access when no integration row exists;
  • a first-time organization GitLab connect keeps member-level access.

So a plain member pressing the action in the first two cases reached a page that refused them, with no action of its own, and the screen attributed the dead end to the provider connection.

The gate reads the caller's organization role through the same shared permission rule the code-reviewer screens use (useReviewerPermission → canManageOrganizationBilling), and a new pure selector decides the action:

  • lib/pr-review/pr-review-connect-gate-view.ts selectPrReviewConnectAction returns organization-admin-only only where the server refuses: an organization GitLab re-authorization, and every organization Bitbucket connect. Personal scope and a first-time GitLab connect keep the action.
  • In that state the gate renders no action and words the read-only state for the provider it is in: the expired GitLab connection keeps its title and says it expired, naming the roles that can reconnect it; the absent Bitbucket connection states the absence in its title and names only the roles that can connect it.
  • An unsettled role read keeps the action, matching the code-reviewer screens: the provider procedures stay authorized on the server, so a loading or failed membership read must not strand the reader.

The same selector also makes the gate wait for the restored account selection (useOrganization().isLoaded) before answering for a scope, which removes a personal-scope paint that the organization's repaint followed on the same route (found by the design gate's layout-shift check).

Not changed, deliberately:

  • the mid-session reconnect notice. Its action force-refetches the provider status through member-authorized procedures; it never opens the integration page, so every role can complete it.
  • no plan or billing messaging: the status read carries no plan input.

Design review round 1

Each finding is addressed on the screen it names:

  1. GitLab, read-only member state. The description no longer claims the provider was never connected, and no longer restates the title's expiry: under the unchanged "GitLab connection expired" title it reads "Ask an organization owner, admin, or billing manager to reconnect it." A follow-up review remark pointed out the restated sentence; it is dropped from the English copy and from every translation.
  2. Bitbucket, read-only member state. The title is now "Bitbucket not connected" instead of the "Connect Bitbucket" call to action the state no longer offers, and the line below it names only the roles that can connect, without restating the title.
  3. Arabic reconnect titles. The trailing period is gone from the Arabic reconnect titles, so the headline style matches the English copy, and the same edit covers the Arabic GitHub reconnect title in that family.

The three new English strings are translated in every one of the 86 other catalogs.

Design review round 2

  1. The account switcher under the title. It is now drawn as a bordered pill in the primary text color, with the caret in that same color, and it renders after the explanation instead of splitting the title from the text that explains it. The order and the style cover both provider screens and the GitHub arm of the gate, which shares the composition. The pill takes Button's outline surface and border pair, so the dark cell gets the visible edge the app's other outlined controls have. Measured in the base cell of the run below: the pill's pressable row, its label and the caret share one centre line (row centre 521.9pt, caret centre 522.1pt), and the explanation now sits above the pill.
  2. The illustration tile in dark mode. The tile now takes the secondary surface with an explicit border, and its glyph takes the secondary-ink token in dark mode; the light cell is untouched. Measured in the dark cell of the same run: the icon-to-tile contrast rose from 4.9:1 to 9.1:1 (the light cell measures 5.4:1), and the tile paints a border instead of the 7% hairline that vanished on the near-black background. lib/pr-review/pr-review-gate-illustration.ts holds the tile class and the scheme-based glyph token, and all three connect gates (GitLab, Bitbucket, GitHub) use them, so the family cannot disagree in dark mode.
  3. The organization-only arm keeps its switcher above its copy. That state's line reads "Switch the account above to an organization…", so the switcher stays the line the reader sees first; only the arms whose copy does not name a position moved the switcher below the explanation. Rewording instead would have meant an English copy change in every catalog.

Verification

Unit, at this head:

  • pnpm --filter kilo-app exec vitest run src/components/pr-review/ — 70 files, 691 tests pass, including the role matrix (member, billing role, unsettled), the first-time-connect exception, the unsettled-selection wait, and both read-only wordings.
  • pnpm --filter kilo-app exec vitest run src/i18n — 21 files, 1823 tests pass, including catalog parity.
  • pnpm --filter kilo-app lint, typecheck, check:unused, format — clean.

End to end on the Android emulator against the local dev stack at this head (fake account, seeded organization):

  1. Seeded an organization where the caller is a member, plus a GitLab integration row that is present but not serving (getGitLabStatus answers reconnectRequired: true).
  2. Opened the GitLab merge-request link under that organization. Observed the title "GitLab connection expired", then the line "Ask an organization owner, admin, or billing manager to reconnect it.", then the account switcher drawn as a bordered pill, and no Connect action. The screen hierarchy puts the explanation directly under the title, with the switcher last.
  3. Opened a Bitbucket pull-request link under the same organization as the same member. Observed the title "Bitbucket not connected", the line "Only organization owners, admins, and billing managers can connect it.", then the same switcher pill, and no action.
  4. Switched the device to dark mode and reopened the GitLab link: the illustration tile paints its own surface and border, and the glyph is no longer the muted gray on near-black.
  5. Raised the same caller to owner and reopened the GitLab link: the gate kept its action ("Connect GitLab") and the re-check instruction, with the switcher pill below them.
  6. Switched the app to the personal account and opened the Bitbucket link: the organization-only state reads title, then the switcher pill, then "Switch the account above…", so the copy still points at the control.
  7. Opened the GitHub connect gate in dark mode: the same tile surface and border with the secondary-ink glyph, matching the other two gates.
  8. The design gate's own run re-renders both organization screens in the base, dark, compact and Arabic-RTL cells and reported no layout shift from the new order. The personal organization-only state and the GitHub gate are outside that run's links; their evidence is the captures and pixel measurements above.

Screenshots of the member, dark-mode, and owner states are attached in a comment on this pull request.

Design gate

Design gate: 4 cells, 0 errors, 0 warnings.

The run covers /pr-review/gitlab/review-group/review-repo/7 and /pr-review/bitbucket/e2e-workspace/e2e-repo/5, opened as a plain organization member of a seeded organization whose GitLab row cannot serve a review — the state this change settles. The Arabic cell renders the current copy from the Arabic catalog, and the dark cell carries the illustration change.

It is uploaded for head 492c4a2 together with a second run of the same two links on the merge base cee0605bb, under base/ in the same folder. The base run also reported 4 cells, 0 errors, 0 warnings, so the two runs agree cell by cell and this change introduces no design-gate finding; the base run only differs in what it paints, since a plain member there still gets the integration-page action and the pre-fix composition.

In the same session at this head, the Android emulator re-showed each state the change settles: the member GitLab gate (expired title, admin-role line, switcher pill, no action), the member Bitbucket gate (absence title, admin-role line, switcher pill, no action), the owner gate (re-check line and the Connect GitLab action restored), and a member's first-time GitLab connect (the Connect GitLab action kept). Captures of those four states are in the comment below.

Production prerequisites

None.

Proxy answers

The owner's proxy gave these answers in the owner's place.

  1. Question: Hide scope: Server rules: a plain member CAN complete a first-time org GitLab connect (OAuth branch is member-level when no integration row exists; apps/web/src/lib/integrations/oauth/platforms/gitlab-connect.ts:215-224), but CANNOT reconnect an existing one (billing roles) and CANNOT connect Bitbucket at all (billing roles everywhere). Where should the Connect button be hidden for a plain member?
    Answer: Only where the server refuses: GitLab reconnect + Bitbucket connect
    Confidence: 0.75 · Precedent: Trust the code over documents: "those documents may be stale, only trust code" (session 269375d6e466). Hiding the first-time connect would remove a path a member can complete today.
  2. Question: Mid-session notice: The mid-session notice (pr-review-reconnect-notice.tsx) has a 'Check connection' CTA that only force-refetches the provider status through member-authorized procedures — it never opens the integration page, so a plain member can complete it. Apply the member split there too?
    Answer: Leave the notice unchanged
    Confidence: 0.70 · Precedent: Do the least work possible with no drop in quality (session 7f3470e0ba6f). The re-check works for every role, so there is no dead end to fix there.
  3. Question: Copy source: How should the admin-required line be sourced?
    Answer: Reuse the existing read-only keys
    Confidence: 0.70 · Precedent: Do the least work possible with no drop in quality: "do the least amount of work possible, with no drop in quality" (session 7f3470e0ba6f). The existing keys are accurate and already translated in every catalog.
  4. Question: Copy source: The design review (round 1) requires copy the reused read-only keys cannot express: an expired connection described as expired instead of never connected, and a Bitbucket read-only state whose title is not the connect call to action. Your earlier answer was to reuse those keys. Which should this change do?
    Answer: Add dedicated keys and translate them
    Confidence: 0.85 · Precedent: Localize every string in the mobile app and fix the whole class: "i18n is very important to me"; best-in-class UX standard ("design and UX MUST BE BEST-IN-CLASS")

…r on PR review

The PR-review connect gate offered its integration-page action to every
organization role. The server restricts every organization Bitbucket
connect and an organization GitLab re-authorization to the billing roles,
so a plain member pressed a button that led to a page refusing them with no
action of its own.

The gate now reads the caller's organization role through the same shared
permission rule the code-reviewer screens use, and in the states the server
refuses it keeps the provider title, states that an organization owner,
admin, or billing manager has to act, and renders no action. A first-time
organization GitLab connect keeps its action because the server allows
member-level access there, and a personal scope keeps it for every role. An
unsettled role read keeps the action too, so the provider procedures stay
authorized on the server without stranding the reader.

The gate also waits for the restored account selection before answering for
a scope. Before that, a reader whose organization is being restored is
briefly asked about the personal scope, so the screen painted the personal
connect view and then repainted the organization's.
@iscekic iscekic added drain Work item from the findings drain explorer:ios Finding surfaced by the iOS explorer labels Oct 31, 2026
@iscekic

iscekic commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Visual proof from the Android emulator against the local dev stack, with a seeded organization and a fake account. Each capture is the PR-review gate reached from a provider pull/merge-request link under that organization.

  • A plain member on a GitLab merge request whose organization integration cannot serve: the gate keeps the expired-connection title, states that an organization owner, admin, or billing manager has to act, and offers no action.
  • The same merge request as an owner: the re-check instruction and the Connect action are unchanged.
  • A plain member on a Bitbucket pull request: the same admin-required line and no action, because every organization Bitbucket connect is restricted the same way.
  • A plain member on a GitLab merge request with no organization integration yet: the first-time Connect action is kept, because the server allows member-level access there.
  • The Bitbucket pull request as an owner: the Connect action is kept.

Plain member, GitLab gate: admin-required line, no action

Owner, GitLab gate: Connect action kept

Plain member, Bitbucket gate: admin-required line, no action

Plain member, first-time GitLab connect: action kept

Owner, Bitbucket gate: Connect action kept

Design gate contact sheet

@kilo-code-bot

kilo-code-bot Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit extracts the connect gates' illustration tile and dark-mode glyph color into one shared module used by the GitHub, GitLab and Bitbucket arms, and moves the account switcher above the Bitbucket org-only explanation so its copy's "switch the account above" matches the control; no correctness, security, or memory-leak issue was found in the changed code.

Assumptions: [INFERENCE] the visual results were not rendered here; lint, typecheck, and vitest were not run because command execution is restricted in this session, so validity rests on diff and source inspection. The PR body's emulator and design-gate evidence is pinned to 8af5cc2, one commit behind this head, and that run predates the org-only reorder and the GitHub arm's shared tile class.

Files Reviewed (4 files, incremental 8af5cc2..492c4a2)
  • apps/mobile/src/lib/pr-review/pr-review-gate-illustration.ts - 0 issues (new shared tile class and usePrReviewGateIconColor; ink2 exists in both generated palettes, the light half of the class is byte-identical to EmptyState's default bubble, and the hook adds only the existing useColorScheme/useThemeColors reads, so no new subscription or leak)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx - 0 issues (both EmptyState arms now consume the shared class/hook; colors is still used for the spinner and button glyphs at lines 273, 350, 352; the org-only arm places PrReviewContextLine above OrgOnlyDescription, which matches the string bitbucketOrgOnlyDescription's "Switch the account above" and leaves the no-organization and memberships-error wordings correct)
  • apps/mobile/src/components/pr-review/pr-review-connect-gate.tsx - 0 issues (iconContainerClassName and iconColor are declared props forwarded by EmptyState to EmptyStateBody; the GitHub reconnect/connect arm keeps its action and both description nodes)
  • apps/mobile/src/components/pr-review/pr-review-context-line.tsx - 0 issues (documentation-only change; the pill styling itself is unchanged)
Previous Review Summaries (6 snapshots, latest commit 8af5cc2)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 8af5cc2)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit 8af5cc2 adds the opt-in iconColor/ICON_TILE_CLASS illustration contrast for dark mode and turns the switchable account line into an outlined pill, reordering the context line below the gate description; no correctness, security, or memory-leak issue was found in the changed code.

Assumptions: [INFERENCE] the visual results were not rendered here; lint, typecheck, and vitest were not run because command execution is restricted in this session, so validity rests on diff and source inspection. The PR body's emulator and design-gate evidence is pinned to a79f9f6, one commit behind this head.

Files Reviewed (6 files, incremental a79f9f6..8af5cc2)
  • apps/mobile/src/components/empty-state.tsx - 0 issues (new optional iconColor is spread through EmptyState to EmptyStateBody and falls back to colors.mutedForeground; compact mode still omits the icon)
  • apps/mobile/src/components/pr-review/pr-review-connect-gate.tsx - 0 issues (GitHub description order swap only; both nodes remain inside the EmptyState description)
  • apps/mobile/src/components/pr-review/pr-review-context-line.tsx - 0 issues (colors.foreground and the dark:border-neutral-700 dark:bg-secondary pair exist and match Button's outline variant; ROW_TARGET_CLASS and truncation retained)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx - 0 issues (useColorScheme resolves colors.ink2 in dark mode consistently with useThemeColors, which reads the same Appearance-backed scheme; no new subscription or leak)
  • apps/mobile/src/components/pr-review/pr-review-connect-gate-view.mounted.test.tsx - 0 issues (adds the useColorScheme stub the newly importing component tree needs)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.mounted.test.tsx - 0 issues (same stub; pinned to 'light' so the partial theme mock's missing ink2 is never read)

Previous review (commit a79f9f6)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit applies the previously requested fix: the GitLab read-only gate description now names only who can act, and the first sentence is dropped from all 87 catalogs, with the mounted test updated to pin the shorter copy.

Assumptions: [INFERENCE] all 87 locale files were changed consistently (one line each, same key, no leading space or empty value found by inspection); check:i18n, lint, and typecheck were not run because command execution is restricted in this session, so catalog parity and JSON validity rest on the diff and file inspection.

Files Reviewed (88 files, incremental 7193500..a79f9f6)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.mounted.test.tsx - 0 issues (expectation and comment now match the shorter description)
  • apps/mobile/src/i18n/locales/*.json (87 catalogs) - 0 issues (all changed to "Ask an organization owner, admin, or billing manager to reconnect it." and its translations; no restatement of the expiry title)

Previous review (commit 7193500)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The incremental commit rewords the read-only PR-review gate states per provider; the only finding is that the new GitLab read-only description repeats the expiry title it renders above.

Assumptions: [INFERENCE] the 86 non-English catalogs hold real translations for the three new keys; key presence and placeholder-free structure were verified by inspection, while check:i18n, lint, and typecheck were not run because command execution is blocked in this session.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/mobile/src/i18n/locales/en.json 754 gitlabReconnectAdminOnlyDescription opens with "The GitLab connection expired.", which restates the gitlabTitle rendered above it and contradicts the added comment claiming the description never restates the title; drop the first sentence and mirror the change in the other catalogs.
Files Reviewed (89 files, incremental 40e456b..7193500)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx - 0 issues (wording branch verified: GitLab admin-only keeps the reconnect title, Bitbucket swaps to the absence title, actions still gated by the selector)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.mounted.test.tsx - 0 issues
  • apps/mobile/src/i18n/locales/*.json (87 catalogs) - 1 issue (all catalogs contain the three new keys; only ar.json also normalizes punctuation on existing title values)

Fix these issues in Kilo Cloud

Previous review (commit 40e456b)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit resolves both prior findings: a failed selection restore now counts as settled (organization.error !== null), and a latched ref keeps the review subtree mounted across a re-restore, so no new defect was found in the changed gating code.

Assumptions: [INFERENCE] the failed-restore fallback (settling on error and answering for the last known/null selection) is intentional per the PR body and the earlier recommendation; the restore/re-restore ordering was read from organization-context.tsx, not replayed on a device. Setting the latch ref during render is an established pattern elsewhere in this app, and the boolean is monotonic, so it is not reported here.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 0
Files Reviewed (2 files, incremental 63b0f11..40e456b)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx - 0 issues (prior two findings verified fixed at lines 117-120 / 208)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.mounted.test.tsx - 0 issues

Previous review (commit 63b0f11)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The incremental commit only reformats the role fixtures, so no new defect was introduced; the two prior findings against the live isLoaded gating remain unresolved at current HEAD and still gate the whole PR-review route.

Assumptions: [INFERENCE] the mount/refresh ordering behind the isLoaded remount was reasoned from organization-context.tsx and auth-context.tsx, not replayed on a device. The failed-restore path was re-verified at current code: restore()'s catch sets only error: 'restore' without setting isLoaded: true.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/lib/pr-review/pr-review-connect-gate-view.ts 57 A failed organization restore keeps isLoaded false forever (organization-context.tsx:122 clears it, the catch at :158-162 sets only error), so every arm renders an endless spinner with no retry on the PR-review route.

SUGGESTION

File Line Issue
apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx 198 Passing the live isLoaded re-gates on every restore(); a foreground token refresh replaces the provider Stack (children) with the loading view and remounts it, dropping screen state. Latch the first loaded value.
Files Reviewed (6 files)
  • apps/mobile/src/components/pr-review/pr-review-connect-gate-view.mounted.test.tsx - 0 issues
  • apps/mobile/src/components/pr-review/pr-review-connect-gate.tsx - 0 issues
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.mounted.test.tsx - 0 issues (formatting only in incremental diff)
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx - 1 issue
  • apps/mobile/src/lib/pr-review/pr-review-connect-gate-view.test.ts - 0 issues
  • apps/mobile/src/lib/pr-review/pr-review-connect-gate-view.ts - 1 issue

Fix these issues in Kilo Cloud

Previous review (commit 63de1e2)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The role split matches the server rules (verified in gitlab-connect.ts, bitbucket-connect.ts, and ORGANIZATION_BILLING_ROLES), but gating the whole gate on the live isLoaded flag can strand the PR-review route on a permanent spinner after a failed selection restore, and unmounts the review stack on a token refresh.

Assumptions: [INFERENCE] the mount/refresh ordering behind the isLoaded remount was reasoned from organization-context.tsx and auth-context.tsx, not replayed on a device. No memory-leak risk found in the added hooks; the new useReviewerPermission and useOrganization read cached/shared state only.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/lib/pr-review/pr-review-connect-gate-view.ts 57 A failed organization restore keeps isLoaded false forever, so every arm (including Bitbucket org-only and the retryable status error) renders an endless spinner with no retry on the PR-review route.

SUGGESTION

File Line Issue
apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx 198 Passing the live isLoaded re-gates on every restore(); a foreground token refresh replaces the provider Stack (children) with the loading view and remounts it, dropping screen state. Latch the first loaded value.
Files Reviewed (6 files)
  • apps/mobile/src/components/pr-review/pr-review-connect-gate-view.mounted.test.tsx - 0 issues
  • apps/mobile/src/components/pr-review/pr-review-connect-gate.tsx - 0 issues
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.mounted.test.tsx - 0 issues
  • apps/mobile/src/components/pr-review/pr-review-provider-connect-gate.tsx - 1 issue
  • apps/mobile/src/lib/pr-review/pr-review-connect-gate-view.test.ts - 0 issues
  • apps/mobile/src/lib/pr-review/pr-review-connect-gate-view.ts - 1 issue

Fix these issues in Kilo Cloud


Reviewed by deepseek-flash-latest · Input: 54K · Output: 10K · Cached: 1M

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:human Substantive functional risk requires human review. labels Oct 31, 2026
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:human Substantive functional risk requires human review. and removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:human Substantive functional risk requires human review. labels Oct 31, 2026
The connect gate now waits for the stored account selection before it
answers for a scope. That wait read only the restore's success flag, but a
failed restore publishes its error without ever reporting the selection as
loaded, so the gate would wait for an answer that never arrives. A restore
also re-runs on a token change and briefly reports the selection as
unrestored again, which would replace a reader's open review with the
spinner. Treat the published error as a settled answer, and keep the first
settled answer for the life of the mount.
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:human Substantive functional risk requires human review. and removed merge:human Substantive functional risk requires human review. merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head labels Oct 31, 2026
@iscekic

iscekic commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Design gate for the current head: 4 cells (base, dark, compact, rtl), 0 errors, 0 warnings. Two provider screens per cell: an organization GitLab merge request with an unusable integration, and an organization Bitbucket pull request. Attached is the contact sheet; the full run is uploaded under the work session's design-gate path for this head.

Design gate contact sheet for the current head

@iscekic iscekic added the merge:blocked:design-review Design review has not cleared this change label Oct 31, 2026
…vider

The organization admin-only arm borrowed the code-reviewer read-only line.
On a merge request that arm told a reader whose connection had expired that
the provider was never connected, and on Bitbucket it left the state titled
with a connect call the state no longer offers.

Give each arm the copy its state needs: an expired connection says it
expired and asks for a reconnection, and an absent connection states the
absence in its title and names only the roles that can connect. The new
strings land in every catalog.

The Arabic reconnect titles no longer end with a period, so the headline
style matches the English copy on the same screens.
@iscekic iscekic removed the merge:human Substantive functional risk requires human review. label Oct 31, 2026
Comment thread apps/mobile/src/i18n/locales/en.json Resolved
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. labels Oct 31, 2026
…st state

The read-only state's line opened by repeating the expiry the title above it
already states. Name the roles that can reconnect, and nothing else, in the
English copy and in every translation.
@iscekic iscekic removed merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head labels Oct 31, 2026
@iscekic

iscekic commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Updated proof for the read-only merge-request state at a79f9f6. The line under the expiry title no longer repeats the expiry: on the emulator, as a plain member of a seeded organization whose GitLab integration cannot serve reviews, the gate shows the title "GitLab connection expired", the organization context line, and "Ask an organization owner, admin, or billing manager to reconnect it." with no action. The Arabic cell renders the same sentence from the Arabic catalog under a title without a trailing period.

The Bitbucket read-only state, the owner state, and the first-time connect state are unchanged by this follow-up; their captures are in the earlier comment. The design gate was re-run for this head and reports 4 cells, 0 errors, 0 warnings.

GitLab reconnect state for a plain organization member, line names only who can act

Design gate contact sheet for this head, four cells, no findings

@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:human Substantive functional risk requires human review. and removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change labels Oct 31, 2026
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. and removed merge:human Substantive functional risk requires human review. merge:blocked:insufficient-e2e Verification does not cover the change merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head labels Oct 31, 2026
@iscekic

iscekic commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Design-gate rerun for the two findings at this head, on the Android emulator against the local dev stack with a seeded fake organization.

  1. The account switcher under the title is now a bordered pill in the primary text color, with the caret in the same color, and it renders after the explanation instead of between the title and the text that explains it. Both provider screens and the GitHub arm of the gate share the composition, so all three changed together.
  2. The illustration tile now paints the secondary surface with an explicit border in dark mode, and its glyph takes the secondary-ink token, so the dark cell reads like the light one instead of a dim gray glyph on near-black.

The gate run covers 4 cells (base, dark, compact, Arabic RTL) with both provider screens in each: 0 errors, 0 warnings, no skipped rules, and no layout shift from the new order. Attached: the run's contact sheet, a dark-mode capture of the read-only merge-request state, and an owner-state capture where the switcher and the action appear together.

Design gate contact sheet: four cells, two provider screens each

Read-only merge-request state in dark mode with the bordered switcher pill

Owner state with the re-check line, the switcher pill and the connect action

@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:human Substantive functional risk requires human review. and removed merge:human Substantive functional risk requires human review. labels Oct 31, 2026
@iscekic

iscekic commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Follow-up at this head, after re-checking the reorder against the copy it sits next to.

  • The organization-only state keeps the account switcher above its explanation: that line says "Switch the account above to an organization…", so the control has to stay the line the reader reads first. Only the arms whose copy names no position moved the switcher below the explanation.
  • The illustration tile and its glyph token now live in one shared module, so all three connect gates (GitLab, Bitbucket, GitHub) draw the same dark-mode tile instead of the GitHub gate keeping the old dim bubble.
  • Three comments that the reorder had made inaccurate are corrected.

Re-verified on the Android emulator against the local dev stack: the organization-only state reads title, switcher pill, then the sentence naming the switcher above it; the GitHub connect gate in dark mode paints the same secondary tile with a visible border and the secondary-ink glyph. The design gate re-ran both organization screens at this head: 4 cells, 0 errors, 0 warnings, no skipped rules. Attached are the new contact sheet, the organization-only state, and the GitHub gate in dark mode.

Design gate contact sheet at this head: four cells, two organization screens each

Organization-only state with the switcher pill above the sentence that names it

GitHub connect gate in dark mode with the shared tile and visible border

@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:blocked:human-design The owner reviews the design and removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change merge:blocked:human-design The owner reviews the design labels Oct 31, 2026
@iscekic

iscekic commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Re-ran the design gate for head 492c4a2 on the Android emulator against the local dev stack. Head run and merge-base run on the same two links: 4 cells each, 0 errors, 0 warnings, and the merge-base run is uploaded under base/ beside the head run.

The four captures below come from the same session at this head, with a seeded organization and a fake account: the organization member's read-only gate for a connection that has to be re-authorized, the member's read-only gate for a provider that is not connected, the same caller raised to owner, and a member's first-time connect.

Design gate contact sheet: organization provider gates at the head

Organization member gate for a connection that has to be re-authorized

Organization member gate for a provider that is not connected

Organization owner gate with the connect action

Organization member gate for a first-time connect

@iscekic iscekic added the merge:blocked:human-design The owner reviews the design label Oct 31, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drain Work item from the findings drain explorer:ios Finding surfaced by the iOS explorer merge:blocked:design-review Design review has not cleared this change merge:blocked:human-design The owner reviews the design merge:human Substantive functional risk requires human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants