Skip to content

fix(mobile): give the organization boundary a usable next step - #8063

Merged
iscekic merged 3 commits into
mainfrom
drain/org-boundary-next-step
Oct 21, 2026
Merged

iscekic merged 3 commits into
mainfrom
drain/org-boundary-next-step

Conversation

@iscekic

@iscekic iscekic commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Change

The shared organization boundary (OrganizationBoundary in
apps/mobile/src/components/organization/organization-boundary.tsx) told an
account with no organization to pick one from its profile, but the profile has
no organization control, so the recovery path dead-ended. The settled boundary
states now branch on the membership list:

  • No memberships — a "No organization" state whose primary action opens the
    web organizations page (WEB_BASE_URL/organizations, where create and join
    live), with "Back to profile" as the plain exit. This also covers a stale
    persisted selection with no memberships left.
  • Memberships, nothing usable selected — the action opens the existing
    context picker sheet (ContextPickerSheet, the same account switcher the
    composer uses), so the reader can actually make the selection the heading
    asks for. This covers nothing-selected and a stale selection while other
    memberships remain.
  • Deep-link override absent from a non-empty member list — access denied,
    unchanged precedence.

The pull-request review screen reuses the shared boundary body instead of
duplicating the old copy, so its no-organization state gets the same recovery
actions. The stale-selection copy no longer points at the profile.

Library note: no new UI library was introduced; the boundary reuses the
existing EmptyState, Button, and ContextPickerSheet components, and the
web action goes through the existing openExternalUrl helper.

Copy

en.json only: five new keys under organization.boundary
(chooseAccount, noOrganization, noOrganizationDescription,
openWebOrganizations, selectDescriptionWithOrganizations) plus
unavailableSessionsDescription for the sessions surface, the old
selectDescription key removed, and unavailableDescription repointed to the
account picker. All 87 catalogs were filled in the same commits
(check-catalogs reports every catalog matching en.json).

Verification

  • apps/mobile: pnpm test (1190 files, 17874 passed), tsgo --noEmit clean,
    oxlint clean, check:unused clean, check:i18n and check:plurals pass.
  • Android emulator, local stack, signed-in fake account:
    • kiloapp:///organization/invite-member and
      kiloapp:///organization/low-balance-alert with no memberships render
      "No organization" with the web action and "Back to profile".
    • With a seeded membership and nothing selected, the boundary shows
      "Choose an account"; tapping it opens the context picker sheet with
      Personal and the organization, and selecting the organization drops the
      reader straight into the invite form / low-balance form.
    • Deleting the membership while the selection persists, then reopening the
      route, falls back to the "No organization" web state (verified after the
      fix; the pre-fix build showed "Organization unavailable" with no next
      step).

Proxy answers

  1. Question: No-org next step: For an account with no organizations, what should the boundary's primary next step be?
    Answer: Open web organizations page (Recommended)
    Confidence: 0.75 · Precedent: Speed and least work: 'do the least amount of work possible, with no drop in quality' (session 7f3470e0ba6f); reuses the existing openExternalUrl pattern, adds no backend, and puts no support address in public copy
  2. Question: Picker action: For an account WITH organizations but nothing selected, what should the boundary do?
    Answer: Open the context picker sheet (Recommended)
    Confidence: 0.85 · Precedent: Work item brief: the action opens the existing context picker; consistent with 'Keep similar elements consistent across surfaces' (session a247f3c19b1e)
  3. Question: PR-review screen: The PR-review screen duplicates this copy in its own EmptyState. Include it in the fix?
    Answer: Reuse the shared boundary body (Recommended)
    Confidence: 0.85 · Precedent: Fix the class on every affected surface: 'fix this for all shared services model pickers on all surfaces' (session 75f8833fe8c1); 'if you saw a gap, fix it' (session 89824a222897)
  4. Question: Old copy: The old 'Choose an organization from your profile' keys keep existing consumers (stale-selection 'unavailable' state also says 'choose one from your profile'). Repoint or keep?
    Answer: Remove/repoint dead-end copy (Recommended)
    Confidence: 0.85 · Precedent: Replace old paths instead of keeping them alongside: 'alongside? why not instead?' (session ad6a3f589364); fix the class, not the symptom (session 00eb2a1d3e4b)

The organization boundary told accounts without an organization to pick
one from their profile, but the profile has no such control, so the
recovery path dead-ended. The settled boundary states now branch on the
membership list: an account with no memberships gets a no-organization
state whose primary action opens the web organizations page (create and
join live there) with Back to profile as the plain exit, and an account
with memberships gets an action that opens the existing context picker
sheet. The access-denied state keeps precedence for deep-link overrides
absent from a non-empty member list, and the stale-selection copy no
longer points at the profile.

The pull-request review screen reuses the shared boundary body instead
of duplicating the old copy, so its no-organization state gets the same
recovery actions.

Copy changes are en.json only; the translation slice lands the other
catalogs. Verified on the Android emulator: a fresh account sees the
web action on the invite-member and low-balance-alert routes, selecting
an account from the picker sheet drops the reader straight into the
invite form, and a stale selection with no memberships left falls back
to the no-organization state.
@iscekic iscekic added drain Work item from the findings drain explorer:android Finding surfaced by the Android explorer labels Oct 19, 2026
Comment thread apps/mobile/src/i18n/locales/en.json Resolved
@kilo-code-bot

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

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The follow-up commit resolves both previous findings: the sessions surface now uses a dedicated copy key, and the no-organization state renders the caller's icon, with the new key present in all 87 catalogs.

Files Reviewed (89 files)
  • apps/mobile/src/components/home/agent-sessions-section.tsx
  • apps/mobile/src/components/organization/organization-boundary.tsx
  • apps/mobile/src/i18n/locales/en.json
  • 86 other apps/mobile/src/i18n/locales/*.json catalogs
Previous Review Summary (commit 81f40d3)

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

Previous review (commit 81f40d3)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

Changing the shared organization.boundary.unavailableDescription copy leaves the home sessions failure state pointing at an account picker it does not render.

Overview

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

WARNING

File Line Issue
apps/mobile/src/i18n/locales/en.json 2999 unavailableDescription now says to use the account picker, but agent-sessions-section.tsx renders it with only a "Back to profile" action (and non-English catalogs still carry the old profile copy).

SUGGESTION

File Line Issue
apps/mobile/src/components/organization/organization-boundary.tsx 112 The no-organization state hardcodes Building2 and ignores the new icon prop, so the PR-review screen loses its GitPullRequest glyph in that state.
Files Reviewed (91 files)
  • apps/mobile/src/components/organization/organization-boundary.tsx - 1 issue
  • apps/mobile/src/components/organization/organization-boundary.mounted.test.tsx - 0 issues
  • apps/mobile/src/components/pr-review/pr-review-screen.tsx - 0 issues
  • apps/mobile/src/components/pr-review/pr-review-screen.test.tsx - 0 issues
  • apps/mobile/src/i18n/locales/en.json - 1 issue
  • 86 other apps/mobile/src/i18n/locales/*.json catalogs - 0 issues (key sets verified complete)

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash-1017 · Input: 56.8K · Output: 11.4K · Cached: 950.3K

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added the merge:human Substantive functional risk requires human review. label Oct 19, 2026
@iscekic

iscekic commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Verified the fixed organization boundary end to end on the Android emulator (local dev stack, fake-account test data).

  • An account with no memberships sees the "No organization" state on both organization deep-link routes; the primary action targets the web organizations page and "Back to profile" stays as the plain exit.
  • With a membership but nothing selected, the boundary's action opens the account picker sheet; selecting the organization drops the reader straight into the real screen instead of a dead end.
  • A stale persisted selection with no memberships left (seeded, selected, then the membership deleted) falls back to the same no-organization state instead of the old dead end.

Invite-member route for an account with no organizations: No organization state with the web action and back action

Low-balance-alert route for an account with no organizations: same recovery state

With a membership and nothing selected, the boundary action opens the account picker sheet

Selecting the organization from the sheet drops the reader into the invite form

Same flow on the low-balance-alert route: the settings form loads after selection

Stale persisted selection with no memberships left falls back to the no-organization web state

Review follow-ups: the no-organization state now honors the caller's
icon like every other settled state, and the sessions surface gets its
own unavailable description because it has no account picker to point
at. Catalogs updated in the same commit.
@iscekic

iscekic commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Review replies:

  1. unavailableDescription shared with a surface that has no account picker (apps/mobile/src/i18n/locales/en.json:2999) — fixed in 268fc92. The sessions surface (agent-sessions-section.tsx) now uses a dedicated organization.boundary.unavailableSessionsDescription ("This organization is no longer available. Sessions for it cannot be loaded."), since its only action is Back to profile and it never renders the account picker. The picker-pointer copy stays on the boundary itself, where the picker actually renders. All 87 catalogs were filled in the same commit; check-catalogs passes.

  2. The new icon prop is ignored in the no-organization state (organization-boundary.tsx:112) — fixed in 268fc92. The no-organization EmptyState now renders the caller's icon like every other settled state.

@iscekic iscekic added merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. and removed merge:human Substantive functional risk requires human review. labels Oct 20, 2026
…xt-step

# Conflicts:
#	apps/mobile/src/i18n/locales/sv.json
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:android Finding surfaced by the Android explorer merge:bot Bot-owned review; merge when ready once readiness passes and a review approves.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants